numWeights, соответствующий mnumVertices? - PullRequest
0 голосов
/ 27 января 2020

У меня осталась одна проблема с ASSIMP DIRECT X C ++ ANIMATION WITH SKELETON.

        for (UINT m = 0; m < currentMesh->mBones[k]->mNumWeights; m++) //verticer som påverkas
        {


            vertexVector[k].joints.x = currentMesh->mBones[k]->mWeights[m].mVertexId;

Этот код показывает все вершины, затронутые костью - k, внутри итерации.

Все эти вершины должны иметь один и тот же идентификатор вершины, поскольку все они подвержены влиянию одной и той же кости / сустава.

Проблема в том, что мне нужно составить список каждой вершины и список всех индексов лица, где Я сохраняю положение, UV, Normal и c.

Список, который отображает все вершины, не в том же порядке, что и списки, которые отображают все вершины, затронутые каждой костью.

Так как я могу объединить эти списки?

"vertexVector" ... et c - это пример списка с jointInfo, который соответствует vertexID. В нем есть место для большего количества мест и другая переменная для веса.

Но этот список явно не работает.

Что я делаю не так с Assimp? Надеюсь, это был ясный пост.

ОБНОВЛЕНИЕ Это то, как я строю матрицы: я не знаю, что не так.

                                      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;



//Skapa en parentTransform från noden. Som sedan skickas in som parent 
  matris, första gången är det identitetsmatrisen.


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;
//Kolla om noden är ett ben.

for (UINT i = 0; i < ani->mNumChannels; i++)
{


    if (nodeNameString == ani->mChannels[i]->mNodeName.data)
    {
        joint = ani->mChannels[i];

    }


}
DirectX::XMMATRIX globalTransform = DirectX::XMMatrixIdentity();
//om den är ett ben så är joint inte längre nullptr, den blir det benet.
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;

    globalTransform = combined * parentMat;

 }

 //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)
        {
            OutputDebugStringA("\n");
            OutputDebugStringA(jointInfo[i].name.C_Str());
            OutputDebugStringA("\n");

            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;


            break;
        }


    }


//}


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; // längden

scale = startScaleV + (factor * Delta); //gå ett antal steg beroende på 
 faktorn mellan start och slut.

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







        }

1 Ответ

0 голосов
/ 03 февраля 2020

Не уверен, что вы подразумеваете под "Все эти вершины должны иметь одинаковый идентификатор вершины" - идентификаторы вершин k : th-кость, согласно mBones[k]->mWeights[..].mVertexId, являются индексами для вершин, на которые влияет эта кость, и они будут разными (в противном случае возникла бы избыточность конфликта).

Возможно, вы хотите, чтобы индексы костей и вес костей были частью определения вершины для удобства обработки в шейдере. Что-то вроде

struct vertex ( 
  vec3 pos;
  vec3 normal;
  float bone_weights[N]; // weights of bones influencing this vertex
  unsigned bone_indices[N]; // indices of bones influencing this vertex
}
std::vector<vertex> mesh_vertices;

Где N - максимальное количество костей влияния на вершину. Общее значение равно четырем, но это зависит от того, что вы импортируете. Исходя из вашего примера, черновик может выглядеть примерно так:

// k:th bone of bones in currentMesh
  for (UINT m = 0; m < currentMesh->mBones[k]->mNumWeights; m++)
  {
    float bone_weight = currentMesh->mBones[k]->mWeights[m].mWeight;
    unsigned vertex_index = currentMesh->mBones[k]->mWeights[m].mVertexId;
    mesh_vertices[vertex_index].bone_weights[m] = bone_weight;
    mesh_vertices[vertex_index].bone_indices[m] = k;
  }

Здесь мы предположили, что mNumWeights = N, но это нужно проверить, как уже упоминалось.

...