java – 从.smd模型导入3D骨架动画
我正在写一个.smd导入器,我被困在骨骼动画部分.问题是我不确切知道它是如何工作的.我正在使用这个
this编写导出器,但它没有显示如何使用存储在文件中的信息.
我想所有具有相同骨骼id的顶点都应该被分组,平移和旋转,因为你无法旋转每个顶点.但我不知道我是否正确,即使我是,我仍然不知道如何通过脚本来做到这一点…… 所以问题是:我如何使用存储在文件中的骨架动画信息? 解决方法
我并不特别熟悉SMD格式,但是这里……
注意:此答案假定您知道如何为对象/节点构造复合变换.这是结合其平移,旋转和缩放的矩阵(虽然看起来在SMD中没有使用比例).此外,使用矩阵乘法,矩阵求逆和矩阵*向量乘法. 骨头和动画 模型的骨节点形成树;除了根骨(节点部分)之外,每个骨骼都有一个父骨骼.每个节点都有自己的局部变换(位置和旋转). 局部节点变换:节点的局部变换是从其位置和旋转构造的4×4矩阵,它将点从其局部空间转换到其父节点的空间:如果表示节点空间中位置的向量,则将其与矩阵相乘得到父母的空间中的那个向量.有关如何执行此操作的详细信息,请参阅this link. Google a bit更多. 在SMD中,骨骼变换仅在动画中的关键帧(骨架部分)中定义. “参考”SMD文件具有单帧动画;模型参考位置中每个骨骼节点的位置和旋转. 动画SMD文件具有包含多个帧的动画序列,每个帧指定(某些)骨骼的不同变换.在播放动画时,您可以根据帧的时间和当前场景/游戏时间在帧之间进行插值,并为每个骨骼进行变换(位置旋转). 获得静止骨骼变换 在预处理中(当加载网格时),您需要计算所谓的“静止”骨骼变换.这些是每个骨骼在参考位置时的模型到骨骼空间变换.原因如下: 所有顶点位置都在模型空间中定义,但最终,顶点变换必须从骨骼空间开始,因为您希望顶点与单个骨骼一起移动.因此,必须首先将顶点位置转换为骨骼空间.这是静止骨转换的来源. 因此,我们正在寻找的静止变换将顶点从模型空间转换为骨骼空间.将所有骨骼放在参考位置.从根节点开始遍历树,并连接变换矩阵.因此,例如,对于上臂节点,您将获得变换: transform = root * spine * shoulderR * upperArmR 然而,这是从上臂空间到模型空间的转换.因此,只需反转矩阵即可获得静止骨骼变换.为每个骨骼执行此操作并存储这些矩阵. 请注意,静止变换不会随时间变化;它们是根据模型的参考位置修复的. 顶点/骨骼关联 每个顶点与一个或多个骨节点相关联.对于每个这样的关联,顶点具有相应的权重.通常,所有权重总和为1.在SMD中,这些关联在三角形段中定义.根据您链接的页面,格式为: triangles my_material bone_id x y z nx ny nz u v bone_links 这在(x,y,z)处定义了一个顶点,并且最终将它与骨骼bone_id相关联(假设权重为1). bone_links部分可以(排序)覆盖它并指定多个关联,如下所示: bone_links = num_links bone_id[0] weight[0] bone_id[1] weight[1] ... etc. 如果权重不等于1,则剩余权重将转换为与原始bone_id的关联. 因此,与骨骼0,1和2相关联的示例顶点将是: 0 x y z nx ny nz u v 3 0 0.15 1 0.35 2 0.5 顶点变换 这是我们最终根据当前骨骼变换确定顶点位置的位置.如前所述;根据当前时间和动画,您可以确定(插入)当前骨骼变换.对于每个骨骼,计算骨骼到世界的变换.示例(我们之前看到过): boneToWorld = root * spine * shoulderR * upperArmR 现在,对于与单个骨骼相关联的顶点,下面给出了它的动画/蒙皮位置: vertexPosAnimated = boneToWorld * boneAtRest * vertexPosModel 这首先将顶点位置从模型空间(vertexPosModel)转换为与其关联的骨骼空间(此变换不会随时间变化).然后,使用骨骼的当前位置,顶点再次从骨骼转换为模型空间.这允许它随着变换的变化随着骨骼移动. 观察到,当骨骼当前处于静止位置时,boneAtRest是boneToWorld的反转,因此boneToWorld * boneAtRest是单位矩阵,因此顶点位置保持不变,这是正确的! 最后,由于顶点可以与多个骨骼相关联,而不是上面的,我们计算每个相关骨骼的上述加权和.例如,对于与3个骨骼关联的顶点: vertexPosAnimated = boneToWorld[0] * boneAtRest[0] * vertexPosModel * weight[0] + boneToWorld[1] * boneAtRest[1] * vertexPosModel * weight[1] + boneToWorld[2] * boneAtRest[2] * vertexPosModel * weight[2]; 最后的想法 这些是一些广泛的笔触,我甚至没有讨论着色器实现(如果那是你要做的),但我认为我已经涵盖了所有原则,而且它已经是一个很长的答案. 我过去发现有助于3D引擎开发的一件事是M3G文档(旧的Java Mobile 3D API). SkinnedMesh上的条目基本上描述了我在这里发布的内容. 此外,尝试理解使用静止骨骼变换将顶点从模型转换为骨骼空间的概念,并使用其当前变换再次返回.这是整个事情的关键. 祝好运! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |