Я следую открытому учебнику GL, но меняю порядок умножения матриц, так как использую прямой x. Я нахожусь в C ++.
Это код, который я следую: http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html
И это код, который у меня есть:
void jointTransform(float timeInSeconds,
std::vector<DirectX::XMMATRIX>& transformM, aiAnimation* ani, UINT nrOfJoints,
std::vector<joints>& jointInfo, const aiScene* scenePtr)
{
DirectX::XMMATRIX iD = DirectX::XMMatrixIdentity();
float ticksPerSecond = (float)ani->mTicksPerSecond;
if (ticksPerSecond == 0)
{
ticksPerSecond = 30;
}
float timeInTicks = timeInSeconds * ticksPerSecond;
float animationTime = fmod(timeInTicks, (float)ani->mDuration);
readNodeHeiarchy(animationTime, scenePtr->mRootNode, iD, jointInfo, ani, scenePtr);
transformM.resize(nrOfJoints);
for (UINT i = 0; i < transformM.size(); i++)
{
transformM[i] = jointInfo[i].transformFinal;
}
}
void readNodeHeiarchy(float time, const aiNode* node, DirectX::XMMATRIX parentMat,
std::vector<joints>& jointInfo, aiAnimation* ani, const aiScene* scenePtr)
{
std::string nodeNameString = node->mName.data;
//
//aiString nName = node->mName;
aiMatrix4x4 nodeTransform = node->mTransformation;
DirectX::XMMATRIX combined;
combined = DirectX::XMMatrixSet(nodeTransform.a1, nodeTransform.a2, nodeTransform.a3,
nodeTransform.a4,
nodeTransform.b1, nodeTransform.b2, nodeTransform.b3, nodeTransform.b4,
nodeTransform.c1, nodeTransform.c2, nodeTransform.c3, nodeTransform.c4,
nodeTransform.d1, nodeTransform.d2, nodeTransform.d3, nodeTransform.d4);
const aiNodeAnim* joint = nullptr;
for (UINT i = 0; i < ani->mNumChannels; i++)
{
if (nodeNameString == ani->mChannels[i]->mNodeName.data)
{
joint = ani->mChannels[i];
}
}
if (joint)
{
DirectX::XMMATRIX S;
DirectX::XMMATRIX R;
DirectX::XMMATRIX T;
//scale
aiVector3D scaleV;
calcLerpScale(scaleV, time, joint);
S = DirectX::XMMatrixScaling(scaleV.x, scaleV.y, scaleV.z);
//rotate
aiQuaternion rotationQ;
calcLerpRot(rotationQ, time, joint);
DirectX::XMVECTOR q;
q = DirectX::XMVectorSet(rotationQ.x, rotationQ.y, rotationQ.z, rotationQ.w);
R = DirectX::XMMatrixRotationQuaternion(q);
//translate
aiVector3D transV;
calcLerpTrans(transV, time, joint);
T = DirectX::XMMatrixTranslation(transV.x, transV.y, transV.z);
combined = S * R * T;
}
DirectX::XMMATRIX globalTransform = combined * parentMat;
if (jointInfo[jointInfo.size() - 1].name.C_Str() != nodeNameString)
{
for (UINT i = 0; i < jointInfo.size(); i++)
{
if (jointInfo[i].name.C_Str() == nodeNameString)
{
aiMatrix4x4 off = jointInfo[i].offsetM;
DirectX::XMMATRIX offset;
offset = DirectX::XMMatrixSet(off.a1, off.a2, off.a3, off.a4,
off.b1, off.b2, off.b3, off.b4,
off.c1, off.c2, off.c3, off.c4,
off.d1, off.d2, off.d3, off.d4);
DirectX::XMMATRIX rootMInv;
aiMatrix4x4 rootInv = scenePtr->mRootNode->mTransformation.Inverse();
rootMInv = DirectX::XMMatrixSet(rootInv.a1, rootInv.a2, rootInv.a3, rootInv.a4,
rootInv.b1, rootInv.b2, rootInv.b3, rootInv.b4,
rootInv.c1, rootInv.c2, rootInv.c3, rootInv.c4,
rootInv.d1, rootInv.d2, rootInv.d3, rootInv.d4);
jointInfo[i].transformFinal = offset * globalTransform * rootMInv;
}
}
}
for (UINT i = 0; i < node->mNumChildren; i++)
{
readNodeHeiarchy(time, node->mChildren[i], globalTransform, jointInfo, ani, scenePtr);
}
}
void calcLerpScale(aiVector3D& scale, float aniTime, const aiNodeAnim* joint)
{
if (joint->mNumScalingKeys == 1)
{
scale = joint->mScalingKeys[0].mValue;
return;
}
UINT scaleInd = findIndexS(aniTime, joint);
UINT nextScale = scaleInd + 1;
assert(nextScale < joint->mNumScalingKeys);
float deltaTime = (float)joint->mScalingKeys[nextScale].mTime - (float)joint-
>mScalingKeys[scaleInd].mTime;
float factor = (aniTime - (float)joint->mScalingKeys[scaleInd].mTime) / deltaTime;
assert(factor >= 0.0f && factor <= 1.0f);
const aiVector3D& startScaleV = joint->mScalingKeys[scaleInd].mValue;
const aiVector3D& endScaleV = joint->mScalingKeys[nextScale].mValue;
//interpolate
aiVector3D Delta = endScaleV - startScaleV; //
scale = startScaleV + (factor * Delta);
scale.Normalize();
}
void calcLerpRot(aiQuaternion& rotation, float aniTime, const aiNodeAnim* joint)
{
if (joint->mNumRotationKeys == 1)
{
rotation = joint->mRotationKeys[0].mValue;
return;
}
UINT rotIndex = findIndexRot(aniTime, joint);
UINT nextRot = (rotIndex + 1);
assert(nextRot < joint->mNumRotationKeys);
float deltaTime = (float)joint->mRotationKeys[nextRot].mTime - (float)joint-
>mRotationKeys[rotIndex].mTime;
float factor = (aniTime - (float)joint->mRotationKeys[rotIndex].mTime) / deltaTime;
assert(factor >= 0.0f && factor <= 1.0f);
const aiQuaternion& StartRotationQ = joint->mRotationKeys[rotIndex].mValue;
const aiQuaternion& EndRotationQ = joint->mRotationKeys[nextRot].mValue;
aiQuaternion::Interpolate(rotation, StartRotationQ, EndRotationQ, factor);
rotation.Normalize();
}
void calcLerpTrans(aiVector3D& translation, float aniTime, const aiNodeAnim* joint)
{
if (joint->mNumPositionKeys == 1)
{
translation = joint->mPositionKeys[0].mValue;
return;
}
UINT transIndex = findIndexT(aniTime, joint);
UINT nextTrans = (transIndex + 1);
assert(nextTrans < joint->mNumPositionKeys);
float deltaTime = (float)joint->mPositionKeys[nextTrans].mTime - (float)joint-
>mPositionKeys[transIndex].mTime;
float factor = (aniTime - (float)joint->mPositionKeys[transIndex].mTime) / deltaTime;
assert(factor >= 0.0f && factor <= 1.0f);
const aiVector3D& startTransV = joint->mPositionKeys[transIndex].mValue;
const aiVector3D& endTransV = joint->mPositionKeys[nextTrans].mValue;
//interpolate
aiVector3D Delta = endTransV - startTransV;
translation = startTransV + (factor * Delta);
translation.Normalize();
}
UINT findIndexRot(float aniTime, const aiNodeAnim* joint)
{
assert(joint->mNumRotationKeys > 0);
for (UINT i = 0; i < joint->mNumRotationKeys - 1; i++)
{
if (aniTime < (float)joint->mRotationKeys[i + 1].mTime)
{
return i;
}
}
assert(0);
}
UINT findIndexS(float aniTime,const aiNodeAnim* joint)
{
assert(joint->mNumScalingKeys > 0);
for (UINT i = 0; i < joint->mNumScalingKeys - 1; i++)
{
if (aniTime < (float)joint->mScalingKeys[i + 1].mTime)
{
return i;
}
}
assert(0);
}
UINT findIndexT(float aniTime,const aiNodeAnim* joint)
{
assert(joint->mNumPositionKeys > 0);
for (UINT i = 0; i < joint->mNumPositionKeys - 1; i++)
{
/*
OutputDebugStringA("\n");
OutputDebugStringA(std::to_string(aniTime).c_str());
OutputDebugStringA("\n");
OutputDebugStringA("\n");
OutputDebugStringA(std::to_string((float)joint->mPositionKeys[i + 1].mTime).c_str());
OutputDebugStringA("\n");
*/
if (aniTime < (float)joint->mPositionKeys[i + 1].mTime)
{
return i;
}
}
assert(0);
}
Код здесь немного запутан, я также умножаю, как 52 матрицы, которые устанавливаются при обновлении. И я собираю объединенную информацию, сохраняя ее в правильных вершинах.
Я не следовал точно коду, вы видите какие-либо очевидные ошибки?
Вот остальные:
for (UINT k = 0; k < vertexVector.size(); k++)
{
vertexVector[k].joints.x = 0;
vertexVector[k].joints.y = 0;
vertexVector[k].joints.z = 0;
vertexVector[k].joints.w = 0;
}
std::vector<joints> jointInfo;
nrOfJs = currentMesh->mNumBones;
for (UINT k = 0; k < currentMesh->mNumBones; k++)
{
aiBone* bone = currentMesh->mBones[k];
joints joint;
joint.name = bone->mName;
joint.offsetM = bone->mOffsetMatrix;
jointInfo.push_back(joint);
for (UINT m = 0; m < bone->mNumWeights; m++)
{
aiVertexWeight weight = bone->mWeights[m];
for (UINT n = 0; n < currentMesh->mNumVertices; n++)
{
if (n == weight.mVertexId)
{
if (vertexVector[n].joints.x == 0)
{
vertexVector[n].joints.x = weight.mVertexId;
vertexVector[n].weights.x = weight.mWeight;
}
else if (vertexVector[n].joints.y == 0)
{
vertexVector[n].joints.y = weight.mVertexId;
vertexVector[n].weights.y = weight.mWeight;
}
else if (vertexVector[n].joints.z == 0)
{
vertexVector[n].joints.z = weight.mVertexId;
vertexVector[n].weights.z = weight.mWeight;
}
else if (vertexVector[n].joints.w == 0)
{
vertexVector[n].joints.w = weight.mVertexId;
vertexVector[n].weights.w = weight.mWeight;
}
else
{
continue;
}
}
}
std::vector<joints> copyJ = sp.getJ(0);
jointTransform(runningTime, nrOfTransforms,sp.getAni(0) , nrOfJs, copyJ, sp.get(1));
for (UINT i = 0; i < nrOfTransforms.size(); i++)
{
constants.skinMatrix[i] = nrOfTransforms[i];
}
Результатом сейчас является то, что у меня мерцает меня sh, который похож на грязную липучку, как будто все значения tra sh.
против:
float4x4 jointTrans = float4x4(ID);
if (input.joints[0] != 0)
{
jointTrans = float4x4(skinMatrix[input.joints.x]) * input.weights.x;
}
if (input.joints[1] != 0)
{
jointTrans += float4x4(skinMatrix[input.joints.y]) * input.weights.y;
}
if (input.joints[2] != 0)
{
jointTrans += float4x4(skinMatrix[input.joints.z]) * input.weights.z;
}
if (input.joints[3] != 0)
{
jointTrans += float4x4(skinMatrix[input.joints.w]) * input.weights.w;
}