2014-12-07 26 views
0

我一直在使用OPenGL處理​​骨骼動畫,並在包含一對數組的結構中向GPU發送骨骼重量影響,但是將這些數組更改爲向量似乎不起作用(如在模型中不再呈現,就好像骨信息以某種方式丟失或錯誤)。骨骼向量中的GPU權重

除了聲明struct中的向量,代碼路徑是相同的。我已經過調試並確保了元素的大小/值是可以的。我能想到的唯一的事情就是C++在矢量上傳到GPU之前就釋放了矢量的內容,但我沒有看到證據支持這一說法。

值得注意的是,所使用的大小調整將使結構與現有數組功能兼容,並且在解決此問題後將被移除以允許動態縮放。

這裏的結構,因爲它的立場,用向量:

struct VertexBoneData 
{ 
    std::vector<glm::uint> IDs; 
    std::vector<float> weights; 
    VertexBoneData() 
    { 
     Reset(); 
     IDs.resize(NUM_BONES_PER_VEREX); 
     weights.resize(NUM_BONES_PER_VEREX); 
    }; 

    void Reset() 
    { 
     IDs.clear(); 
     weights.clear(); 
    } 

    void AddBoneData(glm::uint p_boneID, float p_weight); 
}; 

編輯:附加信息。

這裏的循環,以獲得骨信息的結構:

void Skeleton::LoadBones(glm::uint baseVertex, const aiMesh* mesh, std::vector<VertexBoneData>& bones) 
{ 
    for (glm::uint i = 0; i < p_mesh->mNumBones; i++) { 
     glm::uint boneIndex = 0; 
     std::string boneName(mesh->mBones[i]->mName.data); 

     if (_boneMap.find(boneName) == _boneMap.end()) { 
      //Allocate an index for a new bone 
      boneIndex = _numBones; 
      _numBones++; 
      BoneInfo bi; 
      _boneInfo.push_back(bi); 
      SetMat4x4(_boneInfo[boneIndex].boneOffset, mesh->mBones[i]->mOffsetMatrix); 
      _boneMap[boneName] = boneIndex; 
     } 
     else { 
      boneIndex = _boneMap[boneName]; 
     } 

     for (glm::uint j = 0; j < mesh->mBones[i]->mNumWeights; j++) { 
      glm::uint vertId = baseVertex + mesh->mBones[i]->mWeights[j].mVertexId; 
      float weight = mesh->mBones[i]->mWeights[j].mWeight; 
      bones[vertId].AddBoneData(boneIndex, weight); 
     } 
    } 
} 

代碼的ID /重量添加到頂點:

void VertexBoneData::AddBoneData(glm::uint p_boneID, float p_weight) 
{ 
    for (glm::uint i = 0; i < ARRAY_SIZE_IN_ELEMENTS(IDs); i++) { 
     if (weights[i] == 0.0) { 
      IDs[i] = p_boneID; 
      weights[i] = p_weight; 
      return; 
     } 
    } 
    assert(0); //Should never get here - more bones than we have space for 
} 

循環加載骨架和插入從網格類到VBO對象:

if (_animator.HasAnimations()) 
{ 
    bones.resize(totalIndices); 
    for (unsigned int i = 0; i < _scene->mNumMeshes; ++i){ 
    _animator.LoadSkeleton(_subMeshes[i].baseVertex, _scene->mMeshes[i], bones); 
    } 
    _vertexBuffer[2].AddData(&bones); 
} 

插入到VBO對象:

void VertexBufferObject::AddData(void* ptr_data) 
{ 
    data = *static_cast<std::vector<BYTE>*>(ptr_data); 
} 

最後的代碼在網格類的信息添加到GPU:

_vertexBuffer[2].BindVBO(); 
_vertexBuffer[2].UploadDataToGPU(GL_STATIC_DRAW); 
glEnableVertexAttribArray(BONE_ID_LOCATION); 
glVertexAttribIPointer(BONE_ID_LOCATION, 4, GL_INT, sizeof(VertexBoneData), (const GLvoid*)0); 
glEnableVertexAttribArray(BONE_WEIGHT_LOCATION); 
glVertexAttribPointer(BONE_WEIGHT_LOCATION, 4, GL_FLOAT, GL_FALSE, sizeof(VertexBoneData), (const GLvoid*)(sizeof(VertexBoneData)/2)); 
+1

您的代碼實際上並不包含任何有助於解決問題的方法。除了構造函數很愚蠢之外,這很好。我不知道爲什麼你認爲問題會出現在C++/gpu的屏障上(你甚至懶得告訴我們是否使用d3d或OpenGL) – Cubic 2014-12-07 16:20:41

+0

公平點,我試圖減少我發佈的代碼量。我剛剛添加了很多! – Mark 2014-12-07 17:05:25

回答

1

這不可能工作。 A std::vector實例是一個內部包含指向動態分配數據的指針的對象。

所以用這個定義:

struct VertexBoneData 
{ 
    std::vector<glm::uint> IDs; 
    std::vector<float> weights; 

IDsweights的值不會直接存儲在結構。這些在動態分配的堆內存中。該結構只包含vector對象,其中包含指針和一些簿記屬性。

你不能在OpenGL緩衝區直接存儲這些結構,並具備GPU訪問的數據。 OpenGL將不知道如何使用vector對象。

+0

啊哈,是的。這符合我所看到的行爲。話雖如此,我仍然需要動態調整結構,並讓GPU可用。我想不出一種優雅的方式來解決這個問題,但感謝解決我最初的困惑! – Mark 2014-12-07 17:38:26

+0

@Mark在結構中添加一個方法,將其內容轉儲到緩衝區中,而不是將骨骼數組/矢量用作緩衝區,然後將該緩衝區傳遞給着色器。 – Cubic 2014-12-07 17:54:02

+0

這是一個非常整潔的解決方案,但我看到的問題是權重不是按順序添加的;即骨骼的重量和ID將被添加,接下來將是骨骼j的重量和ID,然後骨頭q然後再骨頭i。 – Mark 2014-12-07 22:33:18