我一直在使用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));
答案 0 :(得分:1)
这不可行。 std::vector
实例是一个内部包含指向动态分配数据的指针的对象。
所以这个定义:
struct VertexBoneData
{
std::vector<glm::uint> IDs;
std::vector<float> weights;
IDs
和weights
的值不会直接存储在结构中。它们位于动态分配的堆内存中。该结构仅包含vector
个对象,其中包含指针和一些簿记属性。
您无法将这些结构直接存储在OpenGL缓冲区中,并让GPU访问数据。 OpenGL不知道对vector
对象做了什么。