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);

    }
}

结果 在此处输入图像描述

旋转不是根据其关节位置进行的

4

1 回答 1

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]);
}
于 2013-11-27T12:24:41.290 回答