Animation 骨骼顶点蒙皮变换

Animation 骨骼顶点蒙皮变换,animation,skinning,Animation,Skinning,我正在尝试在OpenGL中实现骨骼动画。在这个阶段,我试图让我的骨骼系统使网格变形。我相信问题在于如何创建矩阵Bone::getMatrix() 背景: glm::mat4 Bone::getMatrix(){ Bone* parent = getParent(); glm::mat4 rot = glm::mat4(1.0f); glm::mat4 trans= glm::mat4(1.0f); glm::vec3 orient = getOrie

我正在尝试在OpenGL中实现骨骼动画。在这个阶段,我试图让我的骨骼系统使网格变形。我相信问题在于如何创建矩阵
Bone::getMatrix()

背景:

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 ;
}
每个骨骼都有到其父骨骼的偏移量,如果骨骼没有父骨骼,则偏移量将改为整个骨骼的世界位置。骨骼的集合构成骨骼。目前,出于测试目的,我在一个骨骼中有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);

    }
}
void电枢::draw(常量浮点和dt){
如果(网格==nullptr){
postMsg(“网格参考副本为nullptr”,“绘制”,34);
返回;
}
ArrayVertex3*mesh_Vertex=mesh->getVertex3();
ArrayVertex3渲染顶点;
if(网格顶点==nullptr){
postMsg(“绘制期间网格顶点结构为空”,“绘制”,30);
}否则{
render_vertex.reserve(网格_vertex->size());
}
int i=0,j=0,k=0;
glPushMatrix();
glTranslatef(10,0,0);
glBegin(总分);
对于(i=0;igetBoneCount();i++){
glVertex3fv(glm::value_ptr(glm::vec3(glm::vec4()*getBone(i)->getMatrix()));
}
格伦德();
glBegin(GL_行);
对于(i=1;igetBoneCount();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());
}
格伦德();
glPopMatrix();
//循环所有顶点
对于(i=0;igetnumbertexes());i++){
渲染顶点[i].vtx=glm::vec3(0.0f,0.0f,0.0f);
int inf_count=(*网格顶点)[i].numInfluences;
//循环所有这些顶点的影响
对于(j=0;jgetTranslationMatrix();
渲染顶点[i]。vtx+=glm::vec3(骨骼->getMatrix()*原始顶点)*(权重);
//变换法线
render_vertex[i].norm=glm::vec3(bone->getRotationMatrix()*原始_norm);
}
(*网格顶点[i].vtx=渲染顶点[i].vtx;
(*网格顶点[i].norm=glm::规格化(渲染顶点[i].norm);
}
}
结果


旋转不是根据关节位置进行的,因为你的骨基质功能有点混乱。根据我的理解,所有的顶点都需要通过全局变换矩阵进行变换。全局变换矩阵是所有局部变换矩阵的串联。以下代码用于计算全局转换。这篇文章很有用。

我以前使用GLSL+assimp+glm的一些工作

glm::mat4t=glm::translate(骨骼->偏移);
glm::mat4 R=glm::toMat4(骨骼->旋转);
glm::mat4 S=glm::比例(骨骼->比例);
glm::mat4 localTransform=T*R*S;
如果(骨骼->获取ID()!=0)
{
bone->globalTransform=bone->getParent()->globalTransform*localTransform;
}
其他的
{
骨骼->全局变换=局部变换;
}
对于(uint i=0;igetChildren().size();i++){
updateTransform(bone->getChildren()[i]);
}

什么是反向绑定矩阵?什么是反向绑定矩阵?再解释一下?我想问题出在glm::inverse(parent->getMatrix())上。如果使用getMatrix()提供的矩阵直接操作顶点,则该矩阵需要是全局矩阵。我认为你不需要对父矩阵求逆,只需要将局部矩阵乘以父全局矩阵。或者,如果以后要连接局部矩阵(例如在draw函数中),则使用get matrix函数来获取局部矩阵。父级全局矩阵的逆矩阵可以将顶点转移到局部空间,但这将与提供局部矩阵的getMatrix()函数冲突。