矢量中骨骼重量到 GPU 的重量

Bone weights to GPU in vectors

本文关键字:GPU      更新时间:2023-10-16

我一直在使用 OPenGL 制作骨骼动画,并在包含一对数组的结构中向 GPU 发送骨量影响,但是将这些数组更改为矢量似乎不起作用(就像模型中停止渲染一样,好像骨骼信息以某种方式丢失或错误(。

除了结构中向量的声明之外,代码路径是相同的。我已经调试并确保元素的大小/值正常。我唯一能想到的是,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
}

循环加载框架并从 Mesh 类插入到 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);
}

最后,将信息从 Mesh 类添加到 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));

不可能奏效。std::vector实例是一个对象,它内部包含指向动态分配数据的指针。

所以有了这个定义:

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

IDsweights的值不会直接存储在结构中。位于动态分配的堆内存中。该结构仅包含vector对象,这些对象包含指针和一些簿记属性。

您不能将这些结构直接存储在 OpenGL 缓冲区中,并让 GPU 访问数据。OpenGL不知道如何处理vector对象。

相关文章:
  • 没有找到相关文章