8

我从 Molehill 开始,在掌握 Matrix3D 时遇到了很多问题。我的第一个问题是如何管理描述单个模型方向的 Matrix3D。

我使用 Matrix3D.appendRotation() 来做到这一点。但是根据我添加的顺序,我会得到不同的结果(显然,因为我在全局空间中一次旋转一个)。我知道这是一个常见问题,我在使用 3d 软件建模时遇到过。但这一次,我必须以编程方式修复它。这是我需要帮助的地方。

首先,如果有任何混淆,这里是图片中的问题:

第 1 步:我渲染一个模型。

起始位置

步骤 2a:我在 X 轴上旋转它。看起来正确!

X轴旋转

步骤 2b:我在 Z 轴上旋转它。看起来正确!

Z轴旋转

所以......如果我在模型的 X 和 Z 轴上旋转我想要这个:

所需的 XZ 旋转

但是,悲伤的脸,我明白了:

在此处输入图像描述

我可以看到问题。我在全局空间中一次添加一个旋转。我需要在对象的本地空间中旋转。我不知道如何做到这一点,或者我什至应该搜索什么(术语等)。代码很简单(而且错误):

modelLocalMatrix.identity();
modelLocalMatrix.appendRotation(modelZRot, Vector3D.Z_AXIS);
modelLocalMatrix.appendRotation(modelXRot, Vector3D.X_AXIS);
//eventually y-axis rotation as well...
renderMatrix.append(modelLocalMatrix);

我猜我不想使用 Vector3D 轴常数,而是想使用一些归一化向量和一些……呃,东西……代替 modelZRot、modelXRot,最后是 modelYRot。谁能告诉我应用上述所需旋转类型的最佳实践解决方案是什么?

更新:花了一天时间阅读“书籍”(又名 YouTube 上的 KhanAcademy)并在此处开始此演示:3d 旋转矩阵的数学我偶然发现了一种非常接近我想要的“查看”方法解决方案。不幸的是,我只有 50% 的理解。我仍然希望有人能对这个话题有所了解!

var angleOfRotation:Number = Math.PI / 2; //90 degrees...
var axisOfRotation:Vector3D = new Vector3D(0, 1, 0); //some point to look at... 
//normalize the vector!
axisOfRotation.normalize();
var x:Number = axisOfRotation.x;
var y:Number = axisOfRotation.y;
var z:Number = axisOfRotation.z;
var c:Number = Math.cos(angleOfRotation);
var s:Number = Math.sin(angleOfRotation);
var t:Number = 1 - c;

//Graphics Gems (Glassner, Academic Press, 1990). 
modelLocalMatrix = new Matrix3D(new <Number>[
  t * (x * x) + c,   t * x * y - s * z,   t * x * z + s * y,   0, 
  t * x * y + s * z,   t * (y * y) + c,   t * y * z - s * x,   0, 
  t * x * z - s * y,   t * y * z + s * x,   t * (z * z) + c,   0, 
  0,           0,           0,           1
]);

问题是,这似乎相当笨重。特别是因为 Vector3D 的旋转角度应该是第四个 (w) 值。更重要的是,Matrix3D 似乎已经有了一个lookAt() 方法。我还没明白……请有人把我从数小时的反复试验中拯救出来!

4

1 回答 1

2

好的,我基本上想出了如何做到这一点。它比我做的简单得多。它还有助于审查 Matrix3D API(它有一些很棒的功能!)。

首先,我用来在局部轴上旋转模型的源代码:

var raw:Vector.<Number> = modelLocalMatrix.rawData;
var right:Vector3D = new Vector3D(raw[0], raw[1], raw[2]);
var up:Vector3D = new Vector3D(raw[4], raw[5], raw[6]);
var out:Vector3D = new Vector3D(raw[8], raw[9], raw[10]);

modelLocalMatrix.appendRotation(modelXRot, right);
modelLocalMatrix.appendRotation(modelYRot, up);
modelLocalMatrix.appendRotation(modelZRot, out);

“上”、“右”和“出”归一化向量在我原始帖子的链接中进行了讨论。它们基本上是模型的俯仰、偏航和滚动轴。可以说,当您初始化对象时,这些向量与 Vector3D.X_AXIS、Y_AXIS 和 Z_AXIS 相同。我已经使用 Matrix3D.rawData 属性提取了它们,尽管可能有更好的方法。

现在,您可以根据自己的选择沿这些轴中的任何一个旋转,但在您这样做的瞬间,其他两个轴的方向会立即改变。这是有道理的。您的模型已经旋转,它的“右”、“上”和“前”现在不同了!因此,如果您首先在模型的“右”轴上旋转(请记住,这与全局 X_AXIS 相同)然后您想在其“外”轴上滚动模型,您需要从模型的本地获取它矩阵。显然,它不再与全局 Z_AXIS 相同。请注意,我不调用 Matrix3D.identity()。如果我这样做了,那么我的模型的轴将被重置!这对我的渲染循环来说没问题,尽管我不得不稍微更改我的代码(和思维方式),因为我在应用转换和旋转之前已经重置了所有矩阵。请注意,modelXRot、modelYRot 和 modelZRot 以度为单位存储旋转值。

我当然希望这对某人有所帮助。我无法相信如此简单的解决方案却找不到如此普遍的问题。无论如何,它似乎确实在做我想做的事。

于 2011-11-23T13:04:59.013 回答