2016-09-22 6 views
6

हाल ही में मैं हड्डी एनीमेशन आयात पर काम कर रहा हूं, इसलिए मैंने एसिंप एनीमेशन आयात का परीक्षण करने के लिए कुछ आईके तकनीक के साथ 3 डी Minecraft-like मॉडल बनाया। औपुत प्रारूप COLLADA (*। डीएई) है, और मैंने जो टूल इस्तेमाल किया वह ब्लेंडर है। प्रोग्रामिंग पक्ष पर, मेरा पर्यावरण opengl/glm/assimp है। मुझे लगता है कि मेरी समस्या के लिए ये जानकारी पर्याप्त है। एक बात, मॉडल की एनीमेशन, मैं सिर्फ assimp एनीमेशन परीक्षण के लिए 7 unmove keyframe रिकॉर्ड।असंप एनीमेशन हड्डी परिवर्तन

सबसे पहले, मुझे लगता है कि स्थानीय परिवर्तन भाग को छोड़कर मेरा परिवर्तन सही है, इसलिए फ़ंक्शन केवल glm::mat4(1.0f) लौटाएं, और परिणाम बाइंड पॉज़ (सुनिश्चित नहीं) मॉडल दिखाएं। (नीचे छवि देखें)

दूसरा, मूल्य glm::mat4(1.0f) से bone->localTransform = transform * scaling * glm::mat4(1.0f); पर वापस करें, फिर मॉडल विकृति। ब्लेंडर में टेस्ट छवि और मॉडल (छवि नीचे देखें)

: test and origin (bone->localTransform = glm::mat4(1.0f) * scaling * rotate;: इस छवि को जमीन :(किया जा रहा है):

void MeshModel::UpdateAnimations(float time, std::vector<Bone*>& bones) 
{ 
    for each (Bone* bone in bones) 
    { 
     glm::mat4 rotate = GetInterpolateRotation(time, bone->rotationKeys); 
     glm::mat4 transform = GetInterpolateTransform(time, bone->transformKeys); 
     glm::mat4 scaling = GetInterpolateScaling(time, bone->scalingKeys); 
     //bone->localTransform = transform * scaling * glm::mat4(1.0f); 
     //bone->localTransform = glm::mat4(1.0f) * scaling * rotate; 
     //bone->localTransform = glm::translate(glm::mat4(1.0f), glm::vec3(0.5f)); 
     bone->localTransform = glm::mat4(1.0f); 
    } 
} 

void MeshModel::UpdateBone(Bone * bone) 
{ 
    glm::mat4 parentTransform = bone->getParentTransform(); 
    bone->nodeTransform = parentTransform 
     * bone->transform // assimp_node->mTransformation 
     * bone->localTransform; // T S R matrix 

    bone->finalTransform = globalInverse 
     * bone->nodeTransform 
     * bone->inverseBindPoseMatrix; // ai_mesh->mBones[i]->mOffsetMatrix 

    for (int i = 0; i < (int)bone->children.size(); i++) { 
     UpdateBone(bone->children[i]); 
    } 
} 

glm::mat4 Bone::getParentTransform() 
{ 
    if (this->parent != nullptr) 
     return parent->nodeTransform; 
    else 
     return glm::mat4(1.0f); 
} 

glm::mat4 MeshModel::GetInterpolateRotation(float time, std::vector<BoneKey>& keys) 
{ 
    // we need at least two values to interpolate... 
    if ((int)keys.size() == 0) { 
     return glm::mat4(1.0f); 
    } 
    if ((int)keys.size() == 1) { 
     return glm::mat4_cast(keys[0].rotation); 
    } 

    int rotationIndex = FindBestTimeIndex(time, keys); 
    int nextRotationIndex = (rotationIndex + 1); 
    assert(nextRotationIndex < (int)keys.size()); 
    float DeltaTime = (float)(keys[nextRotationIndex].time - keys[rotationIndex].time); 
    float Factor = (time - (float)keys[rotationIndex].time)/DeltaTime; 
    if (Factor < 0.0f) 
     Factor = 0.0f; 
    if (Factor > 1.0f) 
     Factor = 1.0f; 
    assert(Factor >= 0.0f && Factor <= 1.0f); 
    const glm::quat& startRotationQ = keys[rotationIndex].rotation; 
    const glm::quat& endRotationQ = keys[nextRotationIndex].rotation; 
    glm::quat interpolateQ = glm::lerp(endRotationQ, startRotationQ, Factor); 
    interpolateQ = glm::normalize(interpolateQ); 
    return glm::mat4_cast(interpolateQ); 
} 

glm::mat4 MeshModel::GetInterpolateTransform(float time, std::vector<BoneKey>& keys) 
{ 
    // we need at least two values to interpolate... 
    if ((int)keys.size() == 0) { 
     return glm::mat4(1.0f); 
    } 
    if ((int)keys.size() == 1) { 
     return glm::translate(glm::mat4(1.0f), keys[0].vector); 
    } 

    int translateIndex = FindBestTimeIndex(time, keys); 
    int nextTranslateIndex = (translateIndex + 1); 
    assert(nextTranslateIndex < (int)keys.size()); 
    float DeltaTime = (float)(keys[nextTranslateIndex].time - keys[translateIndex].time); 
    float Factor = (time - (float)keys[translateIndex].time)/DeltaTime; 
    if (Factor < 0.0f) 
     Factor = 0.0f; 
    if (Factor > 1.0f) 
     Factor = 1.0f; 
    assert(Factor >= 0.0f && Factor <= 1.0f); 
    const glm::vec3& startTranslate = keys[translateIndex].vector; 
    const glm::vec3& endTrabslate = keys[nextTranslateIndex].vector; 
    glm::vec3 delta = endTrabslate - startTranslate; 
    glm::vec3 resultVec = startTranslate + delta * Factor; 
    return glm::translate(glm::mat4(1.0f), resultVec); 
} 

कोड विचार संदर्भित है

यहाँ कोड Matrix calculations for gpu skinning और Skeletal Animation With Assimp से

कुल मिलाकर, मैं assimp से मेशमोडेल तक सभी जानकारी fectch और इसे हड्डी संरचना में बचाने के लिए, तो मुझे लगता है कि जानकारी ठीक है?

आखिरी बात, मेरी शीर्ष शेडर कोड:

#version 330 core 
#define MAX_BONES_PER_VERTEX 4 

in vec3 position; 
in vec2 texCoord; 
in vec3 normal; 
in ivec4 boneID; 
in vec4 boneWeight; 

const int MAX_BONES = 100; 

uniform mat4 model; 
uniform mat4 view; 
uniform mat4 projection; 
uniform mat4 boneTransform[MAX_BONES]; 

out vec3 FragPos; 
out vec3 Normal; 
out vec2 TexCoords; 
out float Visibility; 

const float density = 0.007f; 
const float gradient = 1.5f; 

void main() 
{ 
    mat4 boneTransformation = boneTransform[boneID[0]] * boneWeight[0]; 
    boneTransformation += boneTransform[boneID[1]] * boneWeight[1]; 
    boneTransformation += boneTransform[boneID[2]] * boneWeight[2]; 
    boneTransformation += boneTransform[boneID[3]] * boneWeight[3]; 


    vec3 usingPosition = (boneTransformation * vec4(position, 1.0)).xyz; 
    vec3 usingNormal = (boneTransformation * vec4(normal, 1.0)).xyz; 

    vec4 viewPos = view * model * vec4(usingPosition, 1.0); 
    gl_Position = projection * viewPos; 
    FragPos = vec3(model * vec4(usingPosition, 1.0f)); 
    Normal = mat3(transpose(inverse(model))) * usingNormal; 
    TexCoords = texCoord; 
    float distance = length(viewPos.xyz); 
    Visibility = exp(-pow(distance * density, gradient)); 
    Visibility = clamp(Visibility, 0.0f, 1.0f); 
} 

मेरे सवाल इसके बाद के संस्करण, कोड की कमी या अस्पष्ट वर्णन है, तो कृपया मुझे बताएं, तो धन्यवाद!

संपादित करें: (1)

अतिरिक्त में, इस तरह मेरे हड्डी जानकारी (कोड प्राप्त करने में कठिनाई भाग):

for (int i = 0; i < (int)nodeAnim->mNumPositionKeys; i++) 
{ 
    BoneKey key; 
    key.time = nodeAnim->mPositionKeys[i].mTime; 
    aiVector3D vec = nodeAnim->mPositionKeys[i].mValue; 
    key.vector = glm::vec3(vec.x, vec.y, vec.z); 
    currentBone->transformKeys.push_back(key); 
} 

कुछ परिवर्तन वेक्टर था, तो मेरे कोड glm::mat4 transform = GetInterpolateTransform(time, bone->transformKeys); ऊपर, Absloutely, मिल उसी मूल्य से। मुझे यकीन नहीं है कि मैंने नामांकित कीफ्रेम एनीमेशन बनाया है जो ट्रांसफॉर्म मान प्रदान करता है या नहीं (बेशक इसमें 7 कीफ्रेम है)।

इस (सिर की हड्डी पर डिबग) की तरह एक-फ़्रेम सामग्री: keyframe from head 7 विभिन्न कीफ़्रेम, एक ही वेक्टर मूल्य।

संपादित करें: (2)

तुम मेरे डे फ़ाइल का परीक्षण करना चाहते हैं, मैं यह jsfiddle में डाल दिया, आते हैं और इसे ले :)। एक और बात, एकता में मेरी फ़ाइल सही तरीके से काम करती है, इसलिए मुझे लगता है कि शायद मेरा स्थानीय परिवर्तन समस्या नहीं होती है, ऐसा लगता है कि समस्या कुछ अन्य माता-पिता ट्रान्सफॉर्म या हड्डी-> ट्रांसफॉर्म ... आदि जैसी हो सकती है? मैं भी सभी हड्डी के साथ स्थानीय ट्रांसफॉर्म मैट्रिक्स जोड़ता हूं, लेकिन यह पता नहीं लगा सकता कि क्यों COLLADA में मेरे अनमोल एनीमेशन के लिए इन मान हैं ...

उत्तर

4

परीक्षण की मात्रा के लिए, और आखिरकार समस्या मिली UpdateBone() भाग है।

इससे पहले कि मैं अपनी समस्या को इंगित करता हूं, मुझे कहना है कि मैट्रिक्स गुणा की श्रृंखला मुझे भ्रमित करने देती है, लेकिन जब मुझे समाधान मिल गया, तो यह मुझे पूरी तरह से (शायद 9 0%) सभी मैट्रिक्स को महसूस करने के लिए तैयार करता है।

समस्या आलेख, Matrix calculations for gpu skinning से आती है। मैंने माना कि उत्तर कोड बिल्कुल सही है और मैट्रिक्स के बारे में और कुछ नहीं सोचना चाहिए। इस प्रकार, मैट्रिक्स का दुरुपयोग स्थानीय रूप से स्थानीय रूपांतरित परिवर्तन मैट्रिक्स में मेरा स्थानांतरण स्थानांतरित करता है। परिणाम पर वापस मेरे प्रश्न खंड में छवि बाध्य है जब मैं स्थानीय ट्रांसफॉर्म मैट्रिक्स को glm::mat4(1.0f) लौटने के लिए बदलता हूं।

तो प्रश्न यह है कि बदले में बाँधने का कारण क्यों बन गया? मुझे लगता है कि समस्या हड्डी की जगह में स्थानीय परिवर्तन होना चाहिए, लेकिन मैं गलत हूँ। इससे पहले कि मैं जवाब दे, नीचे दिए गए कोड को देखो:

void MeshModel::UpdateBone(Bone * bone) 
{ 
    glm::mat4 parentTransform = bone->getParentTransform(); 
    bone->nodeTransform = parentTransform 
     * bone->transform // assimp_node->mTransformation 
     * bone->localTransform; // T S R matrix 

    bone->finalTransform = globalInverse 
     * bone->nodeTransform 
     * bone->inverseBindPoseMatrix; // ai_mesh->mBones[i]->mOffsetMatrix 

    for (int i = 0; i < (int)bone->children.size(); i++) { 
     UpdateBone(bone->children[i]); 
    } 
} 

और मैं नीचे के रूप में परिवर्तन करने के:

void MeshModel::UpdateBone(Bone * bone) 
{ 
    glm::mat4 parentTransform = bone->getParentTransform(); 
    if (boneName == "Scene" || boneName == "Armature") 
    { 
     bone->nodeTransform = parentTransform 
      * bone->transform // when isn't bone node, using assimp_node->mTransformation 
      * bone->localTransform; //this is your T * R matrix 
    } 
    else 
    { 
     bone->nodeTransform = parentTransform // This retrieve the transformation one level above in the tree 
      * bone->localTransform; //this is your T * R matrix 
    } 

    bone->finalTransform = globalInverse // scene->mRootNode->mTransformation 
     * bone->nodeTransform //defined above 
     * bone->inverseBindPoseMatrix; // ai_mesh->mBones[i]->mOffsetMatrix 

    for (int i = 0; i < (int)bone->children.size(); i++) { 
     UpdateBone(bone->children[i]); 
    } 
} 

मैं नहीं जानता कि क्या assimp_node->mTransformation मेरे सामने देते हैं, केवल विवरण " नोड के माता-पिता के सापेक्ष परिवर्तन "गधे के दस्तावेज में। कुछ परीक्षणों के लिए, मैंने पाया कि mTransformation बाइंड पॉज़ मैट्रिक्स है जो मौजूदा नोड माता-पिता से संबंधित है यदि मैं इन्हें हड्डी नोड पर उपयोग करता हूं। मुझे एक तस्वीर दें जो सिर की हड्डी पर मैट्रिक्स पर कब्जा कर लेती है।

Prove

बाएं हिस्से transform जो assimp_node->mTransformation व्याप्ति सही भाग से प्राप्त किए गए है है मेरी unmove एनीमेशन के localTransform जो nodeAnim->mPositionKeys, nodeAnim->mRotationKeys और nodeAnim->mScalingKeys से चाबी की जाती है।

वापस देखो मैं क्या किया, मैं एक बाँध बना मुद्रा tranformation दो बार, तो मेरे सवाल अनुभाग में छवि सिर्फ अलग नहीं बल्कि स्पेगेटी :)

पिछले पर, मुझे दिखाओ कि मैं क्या पहले किया था चलो देखो अनमोल एनीमेशन परीक्षण और सही एनीमेशन परिणाम।

Result

(हर किसी के लिए, तो मेरी अवधारणा गलत है, कृपया मुझे कहना! Thx।)

संबंधित मुद्दे