我有点失落,
我终于有时间在GPU上使用MD5进行蒙皮网格研究 - 通过矩阵,我绝对无法得到正确的结果(这太糟糕了)!
所以这就是我所做的:
加载MD5MESH文件
构建绑定姿势网格(这一步已正确完成 - 几何图形正确)
像这样创建bindpose和inverse bindpose(注意关节是用来加载的,不是父项转换的,它们需要是吗?):
for(unsigned int i = 0; i < this->mMatricesCount; i++)
{
mat4 mBoneTranslation = mat4(
1, 0, 0, mModel->mJoints[i].mPosition.x,
0, 1, 0, mModel->mJoints[i].mPosition.y,
0, 0, 1, mModel->mJoints[i].mPosition.z,
0, 0, 0, 1);
mat4 mBoneRotation = mat4(mModel->mJoints[i].mOrientation);
mat4 mBoneMatrix = mBoneTranslation * mBoneRotation;
this->mMatrices[i] = mBoneMatrix;
this->mInverseMatrices[i] = inverse(mBoneMatrix);
}
加载MD5ANIM文件(计算每个帧关节的位置):
if(mAnimation->mJoints[i].mParent < 0)
{
mAnimation->mFrames[mFrameID][i].mPosition = _position;
mAnimation->mFrames[mFrameID][i].mOrientation = _orientation;
}
else
{
MD5FrameJoint *mParent = &mAnimation->mFrames[mFrameID][mAnimation->mJoints[i].mParent];
float4 rpos = rotate(mParent->mOrientation, _position);
mAnimation->mFrames[mFrameID][i].mPosition = rpos + mParent->mPosition;
mAnimation->mFrames[mFrameID][i].mOrientation = mParent->mOrientation * _orientation;
}
每一帧,构建骨骼矩阵(现在最多4个权重不会造成麻烦,因为目前我在简单镶嵌四边形的场景中只有3个骨骼 - 错误地旋转):
for(unsigned int i = 0; i < this->mJoints; i++)
{
const mat4 mTranslate = mat4(
1, 0, 0, this->mFramePositions[mFrame][i].x,
0, 1, 0, this->mFramePositions[mFrame][i].y,
0, 0, 1, this->mFramePositions[mFrame][i].z,
0, 0, 0, 1);
const mat4 mRotate = mat4(this->mFrameOrientations[mFrame][i]);
this->mOutput[i] = mTranslate * mRotate;
}
并计算顶点(现在在CPU上执行,想将其移动到GPU):
for(unsigned int j = 0; j < mSkinnedModel->mVertexCount[i]; j++)
{
float4 mResult = float4(0, 0, 0, 0);
float4 mPosition = float4(mSkinnedModel->mVertices[i][j].mPosition[0],
mSkinnedModel->mVertices[i][j].mPosition[1],
mSkinnedModel->mVertices[i][j].mPosition[2],
1.0f);
for(unsigned int k = 0; k < 4; k++)
{
mResult += (mAnimatedBones[mSkinnedModel->mVertices[i][j].mBoneIndices[k]] * mPosition) * mSkinnedModel->mVertices[i][j].mBoneWeights[k];
}
mBuffer[j].mPosition[0] = mResult.x;
mBuffer[j].mPosition[1] = mResult.y;
mBuffer[j].mPosition[2] = mResult.z;
mBuffer[j].mPosition[3] = 1.0f;
}
网格+动画文件是正确的(导出它们并导入到3D建模软件中,有效!)
现在我正在测试我的数学库是否正常,到目前为止看起来还不错(矩阵求逆很好,四元数乘法也是如此,四元数测试矩阵,......)
请不要指向任何文章,我有一些(包括那些在GPU上使用矩阵+源代码进行MD5蒙皮的人)打开并弄清楚什么是错的,到目前为止代码看起来几乎完全一样喜欢我的。这将是一些小小的蹩脚细节。
任何人都可以看到大师的位置?
答案 0 :(得分:3)
(真是太糟糕了!)
一张图片胜过千言万语。你没有发布图片。那么,你期待什么?
mat4 mBoneTranslation = mat4(
1, 0, 0, mModel->mJoints[i].mPosition.x,
0, 1, 0, mModel->mJoints[i].mPosition.y,
0, 0, 1, mModel->mJoints[i].mPosition.z,
0, 0, 0, 1);
这应该是OpenGL矩阵吗? OpenGL矩阵具有不同的方向,它们的布局与DirectX中使用的D3DXMATRIX / D3DMATRIX完全相同 - 除非您想要存储所有转置的矩阵。
非转置翻译矩阵:
mat4 translation = mat4(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1);
当然,非转置矩阵使用反向乘法顺序:
mat4 combined = rotation * translation;
此外,您可以简单地复制最后一行(非转置),而不是相乘:
mat4 combined = rotation;
combined.rows[3] = translation.rows[3];
或列(转置)。
此外,在这部分:
this->mOutput[i] = mTranslate * mRotate;
您忘记将逆骨骼变换包含在计算中。 Withotu逆骨变换皮肤网将“爆炸”。
它应该是(转置矩阵)
this->mOutput[i] = mTranslate * mRotate * mInverseMatrices[i];
或(对于非转置)。
this->mOutput[i] = mInverseMatrices[i] * mRotate * mTranslate;
- 编辑 -
您可能无法正确计算联合层次结构转换。
{
MD5FrameJoint *mParent = &mAnimation->mFrames[mFrameID][mAnimation->mJoints[i].mParent];
float4 rpos = rotate(mParent->mOrientation, _position);
mAnimation->mFrames[mFrameID][i].mPosition = rpos + mParent->mPosition;
mAnimation->mFrames[mFrameID][i].mOrientation = mParent->mOrientation * _orientation;
}
这不是通常的做法。
计算每个关节的局部变换。
this->localTransform = positionMatrix * rotationMatrix
通过将父变换和子变换相乘来计算每个关节的世界变换
this->worldTransform = parent->worldTransform * this->localTransform;
对于根节点,世界变换是对象矩阵的乘法(用于平移网格)和局部变换。
root->worldTransform = worldMatrix * root->localTransform;
如果层次结构中的矩阵(ANY矩阵)具有缩放组件,则方案将无法正常工作。
如果这没有帮助,那么你需要让某人调试你的代码。我不做免费调试,但不允许(AFAIK)在SO上提供“自由职业”服务。所以你必须找到其他人。
另一件事是,你必须使用可以显示动画md5格式的应用程序而不是使用“白点来表示”应该是“”的应用程序,并保证正确地执行它。不保证您的白点位于正确的位置。