c# - 通过局部旋转和位置平移和旋转子网格(如在 Unity 中)
问题描述
我正在导出使用旧动画方法的模型。骨架网格物体中的每个骨骼都有一个局部的平移和旋转值。在 Unity 中,我可以设置每个子网格的本地位置,并且模型在每一帧看起来都是正确的。
我现在正在尝试使用 glmsharp 从我的 C# 程序中导出这些网格,并且得到了奇怪的视觉导出。我在其他地方使用模型导出代码,它可以工作,所以我们假设问题出在子网格顶点的平移和旋转中。
这是我的方法:
public void ShiftSkeletonValues(List<SkeletonNode> skeleton, List<BoneTrack> boneTracks,
mat4 parentMatrix, int index, int frame, ILogger logger)
{
mat4 translationMatrix = mat4.Translate(boneTracks[index]._frames[frame].Translation);
mat4 rotationMatrix = glm.ToMat4(boneTracks[index]._frames[frame].Rotation);
mat4 modelMatrix = translationMatrix * rotationMatrix;
mat4 combinedMatrix = modelMatrix * parentMatrix;
ShiftAndRotateVertices(combinedMatrix, index, logger);
foreach (var pieces in skeleton[index].Children)
{
ShiftSkeletonValues(skeleton, boneTracks, combinedMatrix, pieces, frame, logger);
}
}
这个函数递归地迭代骨架。调用此方法时,我传入了一个标识 mat4。该函数计算出平移矩阵,然后计算出旋转矩阵(Rotation 是一个四元数)。然后我将它们组合到模型矩阵中,再次将其与父矩阵组合,然后在每个子网格中移动和旋转顶点。然后对于任何连接的部分(孩子),我用组合矩阵递归地调用这个函数。
我用来实际修改顶点值的代码非常简单:
private void ShiftAndRotateVertices(mat4 combineModelMatrix, int index, ILogger logger)
{
MobVertexPiece mobPiece = MobPieces[index];
for (int i = 0; i < mobPiece.Count; ++i)
{
var position = Vertices[mobPiece.Start + i];
vec4 newPosition = new vec4(position, 1.0f);
vec4 shiftedPosition = combineModelMatrix * newPosition;
Vertices[mobPiece.Start + i] = shiftedPosition.xyz;
}
}
我将顶点转换为 vec4,并将其乘以组合模型矩阵。同样,这个逻辑应该模仿 Unity 处理局部旋转的方式。不知道我哪里出错了。我认为这与旋转矩阵有关。
解决方案
多玩了一会儿,意识到除了最后的操作,我什么都做对了。parentMatrix * modelMatrix
结合它们时应该是这样。安德里亚也在评论中提出了这一点。谢谢!
推荐阅读
- java - 未选中时如何在 MacOS 中更改 Java JComboBox 的背景颜色
- javascript - 如何处理默认页面中的相对href
- angular - 仅加载一次 Angular 组件
- c# - 重构所有代码文件以删除类型限定符
- node.js - 公共模块在路由内的代码之前执行?
- python - 如何使用 python 在日期之间访问 azure Dev Ops 数据,例如 Changeset?
- ruby-on-rails - 在 Rails 6 中 Webpacker 在 image_pack_tag 的帮助下使用(添加)图像到 html
- rust - 一个 Rust 函数,用于在压缩文件的行上返回一个迭代器
- android - android:textSize 在 MotionLayout 中的变化
- php - 如何在 php 中的 Google adwords api Traffic Estimator Service 中设置估计的最大每日费用