2013-07-21 36 views
1

我想在OpenGL中實現骨架動畫。在這個階段,我試圖讓我的骨骼系統變形成網狀。我相信問題在於如何創建矩陣Bone::getMatrix()骨骼頂點蒙皮轉換

背景:

每個骨骼已經偏移到它的父,如果骨頭沒有父偏移反而是整個骨架的世界上的地位。骨骼的集合包括骨架。目前,爲了測試目的,我在骨骼中有3塊骨骼,使變形的網格變形。

此外,問題是,當變形網格時,視覺效果不會產生所需的效果。

代碼:

glm::mat4 Bone::getMatrix(){ 

    Bone* parent = getParent(); 
    glm::mat4 rot = glm::mat4(1.0f); 
    glm::mat4 trans= glm::mat4(1.0f); 

    glm::vec3 orient = getOrientation(); 


    //Create Rotation Matrix; 
    rot *= glm::rotate(orient.x,1.0f,0.0f,0.0f); 
    rot *= glm::rotate(orient.y,0.0f,1.0f,0.0f); 
    rot *= glm::rotate(orient.z,0.0f,0.0f,1.0f); 

    //Create Translation Matrix 
    if(parent != nullptr){ 
     glm::vec3 OFF = offset; 
     trans = glm::translate(OFF.x,OFF.y,OFF.z); 
    }else{ 
     glm::vec3 pos = getPosition(); 
     //trans = glm::translate(pos.x,pos.y,pos.z); 
    } 


    glm::mat4 PM = glm::mat4(1.0f); 
    if(parent != nullptr){ 
     PM *= glm::inverse(parent->getMatrix()); 
    }else{ 
    } 
    return PM * trans * rot ; 
} 

形變網格:

void Armature::draw(const float& dt){ 
    if(mesh == nullptr){ 
     postMsg("reference copy to mesh is nullptr","draw",34); 
     return; 
    } 

    ArrayVertex3* mesh_Vertex = mesh->getVertex3(); 
    ArrayVertex3 render_vertex; 

    if(mesh_Vertex == nullptr){ 
     postMsg("mesh vertex structure is null during draw","draw",30); 
    }else{ 
     render_vertex.reserve(mesh_Vertex->size()); 
    } 

    int i=0,j=0,k=0; 

    glPushMatrix(); 
     glTranslatef(10,0,0); 

     glBegin(GL_POINTS); 

     for(i =0; i<this->getBoneCount(); i++){ 
      glVertex3fv(glm::value_ptr( glm::vec3( glm::vec4() * getBone(i)->getMatrix() ) )); 
     } 
     glEnd(); 

     glBegin(GL_LINES); 

     for(i =1; i<this->getBoneCount(); i++){ 

     // glVertex3fv(glm::value_ptr(getBone(i)->getTranslationMatrix() * glm::mat3(getBone(i)->getRotationMatrix()))); 
     // glVertex3fv(glm::value_ptr(getBone(i-1)->getTranslationMatrix() * glm::mat3(getBone(i-1)->getRotationMatrix()))); 
     } 
     glEnd(); 

    glPopMatrix(); 

    //Loop all vertices 
    for(i = 0 ; i < int(mesh->getNumberVertexes()); i ++){ 
     render_vertex[i].vtx = glm::vec3(0.0f, 0.0f, 0.0f); 


     int inf_count = (*mesh_Vertex)[i].numInfluences; 

     //Loop all this vertices influences 
     for(j=0; j < inf_count; j ++){ 
      Bone *bone = getBone( (*mesh_Vertex)[i].boneIDs[j] ); 
      float weight = (*mesh_Vertex)[i].boneWeights[j]; 

      glm::vec4 original_vert = glm::vec4((*mesh_Vertex)[i].vtx,1.0f); 
      glm::vec4 original_norm = glm::vec4((*mesh_Vertex)[i].norm,0.0f); 


      glm::vec3 T = bone->getTranslationMatrix(); 

      render_vertex[i].vtx += glm::vec3( bone->getMatrix() * original_vert) * (weight) ; 


      //Transform normal 
      render_vertex[i].norm = glm::vec3( bone->getRotationMatrix() * original_norm) ; 


     } 


     (*mesh_Vertex)[i].vtx = render_vertex[i].vtx; 
     (*mesh_Vertex)[i].norm = glm::normalize(render_vertex[i].norm); 

    } 
} 

結果 enter image description here

的旋轉不根據其關節位置完成

回答

2

我從你的骨骼矩陣函數有點混亂。根據我的理解,所有的頂點需要通過全局變換矩陣進行變換。全局變換矩陣是所有局部變換矩陣的串聯。以下代碼用於計算全局轉換。這篇文章很有用。 http://graphics.ucsd.edu/courses/cse169_w05/2-Skeleton.htm

一些我以前使用GLSL + assimp + GLM http://www.youtube.com/watch?v=bXBfVl-msYw&list=HL1385555185&feature=mh_lolz

glm::mat4 T = glm::translate(bone->offset); 
glm::mat4 R = glm::toMat4(bone->rotate); 
glm::mat4 S = glm::scale(bone->scale); 
glm::mat4 localTransform = T * R * S; 

if(bone->getID()!=0) 
{ 
    bone->globalTransform = bone->getParent()->globalTransform * localTransform; 
} 
else 
{ 
    bone->globalTransform = localTransform; 
} 

for (uint i = 0 ; i < bone->getChildren().size() ; i++) { 
    updateTransform(bone->getChildren()[i]); 
} 
+0

怎麼樣逆矩陣結合的工作? – ukaku

+0

什麼是反向綁定矩陣?多一點解釋? –

+0

我認爲問題出在glm :: inverse(parent-> getMatrix())上。如果getMatrix()提供的矩陣用於直接操作頂點,則矩陣需要是全局矩陣。我認爲你不需要對父矩陣進行求逆,只需將父矩陣的局部矩陣乘以多個矩陣即可。或者,如果您想稍後連接局部矩陣(例如在繪圖函數中),則使用get矩陣函數來獲得局部矩陣。父母的全局矩陣的逆可以將您的頂點轉移到本地空間,但這會與您的getMatrix()函數衝突,該函數爲您提供了一個局部矩陣。 –