gpt4 book ai didi

OpenGL骨架动画

转载 作者:行者123 更新时间:2023-12-04 12:14:05 24 4
gpt4 key购买 nike

我正在尝试向我的程序添加动画。

我在 Blender 中创建了带有骨骼动画的人体模型,我可以跳过关键帧来查看模型的行走情况。

现在我已将模型导出为 XML (Ogre3D) 格式,在此 XML 文件中,我可以看到在特定时间(t=0.00000、t=0.00040 等)分配给每个骨骼的旋转、平移和缩放.)

我所做的是找到为每个骨骼分配了哪些顶点。现在我假设我需要做的就是将为骨骼定义的变换应用到这些顶点中的每一个。这是正确的方法吗?

在我的 OpenGL draw() 函数中(粗略的伪代码):

for (Bone b : bones){
gl.glLoadIdentity();

List<Vertex> v= b.getVertices();
rotation = b.getRotation();
translation = b.getTranslation();
scale = b.getScale();

gl.glTranslatef(translation);
gl.glRotatef(rotation);
gl.glScalef(scale);

gl.glDrawElements(v);
}

最佳答案

顶点通常受多个骨骼的影响 - 听起来您正在使用线性混合蒙皮。不幸的是,我的代码是用 C++ 编写的,但希望它能给你这个想法:

void Submesh::skin(const Skeleton_CPtr& skeleton)
{
/*
Linear Blend Skinning Algorithm:

P = (\sum_i w_i * M_i * M_{0,i}^{-1}) * P_0 / (sum i w_i)

Each M_{0,i}^{-1} matrix gets P_0 (the rest vertex) into its corresponding bone's coordinate frame.
We construct matrices M_n * M_{0,n}^-1 for each n in advance to avoid repeating calculations.
I refer to these in the code as the 'skinning matrices'.
*/

BoneHierarchy_CPtr boneHierarchy = skeleton->bone_hierarchy();
ConfiguredPose_CPtr pose = skeleton->get_pose();
int boneCount = boneHierarchy->bone_count();

// Construct the skinning matrices.
std::vector<RBTMatrix_CPtr> skinningMatrices(boneCount);
for(int i=0; i<boneCount; ++i)
{
skinningMatrices[i] = pose->bones(i)->absolute_matrix() * skeleton->to_bone_matrix(i);
}

// Build the vertex array.
RBTMatrix_Ptr m = RBTMatrix::zeros(); // used as an accumulator for \sum_i w_i * M_i * M_{0,i}^{-1}

int vertCount = static_cast<int>(m_vertices.size());
for(int i=0, offset=0; i<vertCount; ++i, offset+=3)
{
const Vector3d& p0 = m_vertices[i].position();
const std::vector<BoneWeight>& boneWeights = m_vertices[i].bone_weights();
int boneWeightCount = static_cast<int>(boneWeights.size());

Vector3d p;
if(boneWeightCount != 0)
{
double boneWeightSum = 0;

for(int j=0; j<boneWeightCount; ++j)
{
int boneIndex = boneWeights[j].bone_index();
double boneWeight = boneWeights[j].weight();
boneWeightSum += boneWeight;
m->add_scaled(skinningMatrices[boneIndex], boneWeight);
}

// Note: This is effectively p = m*p0 (if we think of p0 as (p0.x, p0.y, p0.z, 1)).
p = m->apply_to_point(p0);
p /= boneWeightSum;

// Reset the accumulator matrix ready for the next vertex.
m->reset_to_zeros();
}
else
{
// If this vertex is unaffected by the armature (i.e. no bone weights have been assigned to it),
// use its rest position as its real position (it's the best we can do).
p = p0;
}

m_vertArray[offset] = p.x;
m_vertArray[offset+1] = p.y;
m_vertArray[offset+2] = p.z;
}
}

void Submesh::render() const
{
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_DOUBLE, 0, &m_vertArray[0]);

if(m_material->uses_texcoords())
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_DOUBLE, 0, &m_texCoordArray[0]);
}

m_material->apply();

glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_vertIndices.size()), GL_UNSIGNED_INT, &m_vertIndices[0]);

glPopAttrib();
glPopClientAttrib();
}

请注意,据我所知,真实世界的实现通常会在 GPU 上执行此类操作。

关于OpenGL骨架动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4261812/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com