使用轴和角度进行3D旋转

14
我知道3D旋转在SO和其他许多网站上都有详细的文档,但是尽管我阅读了无数的解释,我仍然没有弄清楚我的问题出在哪里。我的背景是艺术和设计,而不是数学和编程,我从来不确定我的攻击角度(没有双关语的意思)是否正确。与其粘贴我悲惨代码的拼贴物,我包含了一个描述我的问题的图片。我真正想要的是一个逐步的文字分解如何解决这个问题。伪代码很有用,但如果有人可以直接指引我或指出常见的陷阱,我会学到更多。

alt text

红色=X轴,绿色=Y轴,蓝色=Z轴

品红色向量=原点-->一些X,Y,Z点

品红色立方体=两个品红向量的端点的平均值(有更好的名称吗?)

白色向量=两个品红向量的叉积(为了显示而扩展,实际向量已被规格化)

青色立方体对象=旋转失败


我以前使用Away3D和Papervision;在这些库中,将欧拉角应用于对象的rotationX、rotationY或rotationZ属性会在本地旋转对象,就像它位于原点一样,而不考虑其实际位置。在Three.js中,情况并非如此。修改对象的rotation.x和rotation.y属性会产生一种奇怪的效果,似乎对象在Z轴上有点倾斜。更令人困惑的是,在对象停留在原点时发生这种情况。我认为可能使用四元数-->矩阵或轴/角度-->矩阵函数可以解决我的问题,但没有结果。看来有一个核心概念我没有领会。

无论如何,我想做的是将立方体定向到叉积向量(白色),以使立方体的顶部面向该向量的方向。然后我想沿着同一轴旋转立方体。我附加的图像显示了尝试实现这个结果比我想象的要多得多的小时。我的代码大致如下:

axis = Vector3.cross(a, b)
axis.normalize()
angle = 45 * TO_RADIANS;
quat = AxisAngle2Quaternion(axis, angle)
rot = Quaternion2Matrix(quat)
cube.matrix = rot

提前感谢您的帮助。


编辑:开始悬赏

也许我误解了它该如何工作。这是另一张图片:

alt text

我是否错误地认为这个品红色向量是轴,而橙色箭头表示根据角度围绕此轴旋转?无论如何,我想基于某个方向向量定位青色立方体并旋转它。我做错了什么!?


1
没人回应,但实际上我认为你的问题是我在这里看到的最好阐述的之一。也许只是没有人知道?我也很想在这里看到答案。 - erikbstack
也许他们在回避Three.js方面...我原以为这是一个相当基本的问题。 - Casey
我在Flash中使用了“Utils3D.pointTowards()”方法,使得我更接近目标:http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/geom/Utils3D.html 但是我不知道如何应用绕轴旋转,并且我找不到任何类似的开放源代码函数。 - Casey
我之前发布过一个类似的问题,可能表述不够清晰。是的,你说得对,品红色单位向量是旋转轴,这确实很困难。我对Three.js一无所知,但我很好奇。相反,我尝试自己编写了一个项目。我发现研究所谓的四元数非常有用,但也很痛苦。此外,尝试在Google上搜索“绕任意轴旋转”可以找到许多答案,它们对我很有帮助。 - WebWanderer
甚至,看看这个链接,它对我帮助最大。 - WebWanderer
3个回答

4
你的方法听起来是正确的,但你没有展示出a、b向量以及常数角度是多少,我猜想这只是为了测试。我之前也做过类似的事情,所以我找到了我的代码,并且这就是我找到的数学公式...
给定:
originalVec = 指向Y轴上方(立方体顶部/法线方向)的单位向量
targetVec = 白色向量
现在你需要找到旋转originalVec与targetVec对齐所需的轴和角度。最直接的旋转轴是两个输入向量的垂直向量,所以取它们的叉积。该轴不是一个单位向量,因此还需要将其归一化。旋转角度(弧度制)是点积的反余弦值。
axis = Vector3.cross(originalVec, targetVec)
axis.normalise
angle = inversecos(Vector3.dot(originalVec, targetVec))

quat = AxisAngle2Quaternion(axis, angle)
rot = Quaternion2Matrix(quat)
cube.matrix = rot

我认为你想要将新的变换与立方体的矩阵组合,而不是替换它...

cube.matrix.multiplyBy(rot)

...但我不确定百分之百。此外,我看到过实现中AxisAngle2Quaternion采用角度的情况。当输入向量平行或相反时,轴为<0,0,0>,因此应进行测试。如果立方体旋转错误,则叉积向量参数的顺序不正确,我永远不记得哪个是哪个,只是尝试两种方法。希望有所帮助。

编辑
我有机会玩了一下Three.js并对其中一个示例进行了修改以定位立方体。注释显示了我添加东西的位置,所有定向数学都在alignCube()中发生。
对齐和旋转示例
上下移动目标线。左右移动在该线上旋转。

Three.js中的场景对象似乎都继承自Object3D,默认情况下具有autoUpdateMatrix属性设置为true。这需要将其设置为false,否则将调用updateMatrix函数,该函数从对象的位置、缩放和旋转属性重新计算矩阵。或者,您可以分配不同的updateMatrix函数。

如果Three.js有一些文档就好了:)


谢谢,很高兴听到我走在正确的道路上。不幸的是,我还没有让它工作。我正在替换立方体的矩阵,因为我现在正在尝试简化事情并使其在原点工作。这样做可以吗?还是会引入问题? - Casey
这个例子太棒了!我现在没有时间仔细看,但我猜你会得到奖励的 :) 谢谢! - Casey
没问题,太好了。我误解了轴/角矩阵的工作方式。我试图用单个矩阵来完成所有操作。我在下面发布了对齐函数,供有兴趣的人参考。 - Casey

3

从Trochoid的例子中,这是我用来实现第二幅图像对齐和旋转的函数:

//object, normalized direction vector, rotation in radians
function align(target, dir, rot) {
    //Three.js uses a Y up coordinate system, so the cube inits with this vector
    var up = new THREE.Vector3(0, 1, 0);

    //euler angle between direction vector and up vector
    var angle = Math.acos(up.dot(dir));

    //cross product of the up vector and direction vector
    var axis = new THREE.Vector3();
    axis.cross(up, dir);
    axis.normalize();

    //rotation to aligns the target with the direction vector
    var rotate = THREE.Matrix4.rotationAxisAngleMatrix(axis, angle);

    //rotation around direction vector
    var revolve = THREE.Matrix4.rotationAxisAngleMatrix(dir, rot);

    //compose the rotations (order matters, can be done other ways)
    revolve.multiplySelf(rotate);

    //assign matrix (autoUpdateMatrix = false)
    target.matrix = revolve;
}

0

因为没有人有一个真正好的解决方案,我至少可以建议你如何更接近。

有三个可能的问题,你其中之一:

  1. 数学不正确,或者你不理解它。(在这里不应该是太大的问题)
  2. 浮点运算对计算机总是一个问题(也不应该是一个问题,因为这是一个相当基本的问题。如果你的框架不能提供一个解决方案,那么这个框架对于3D编程来说根本没有价值)
  3. 你没有正确使用框架

因为很可能第三种情况是问题所在,尝试找到一个邮件列表、支持论坛或任何其他框架,并与那里的人交谈。他们应该能够向你解释,你在他们的框架中做错了什么。然后回来在这里发布解决方案!


感谢您的建议-我已经联系了框架的作者,并要看看是否类似的代码会在Away3D中产生类似的结果。 - Casey
我显然做错了什么——在 Flash 中也无法使其工作。 - Casey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接