向量中的骨骼重量到GPU

时间:2014-12-07 16:10:53

标签: c++ opengl animation vector gpu

我一直在使用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
}

循环加载Skeleton并从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));

1 个答案:

答案 0 :(得分:1)

这不可行。 std::vector实例是一个内部包含指向动态分配数据的指针的对象。

所以这个定义:

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

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

您无法将这些结构直接存储在OpenGL缓冲区中,并让GPU访问数据。 OpenGL不知道对vector对象做了什么。