我正在尝试在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);
}
}
结果
旋转不是根据其关节位置进行的
答案 0 :(得分: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]);
}