在 Three.js 中复制旋转父对象内的对象旋转

Replicate object rotation inside rotated parent in Three.js

我构建了我的 3D 地球仪并将其放入父边界框/枢轴,如下所示:

var globe = new THREE.Group();
if (earthmesh) {globe.add(earthmesh);};
if (linesmesh) {globe.add(linesmesh);};
if (cloudmesh) {globe.add(cloudmesh);};
if (atmosmesh) {globe.add(atmosmesh);};
pivot = new THREE.Group();
if (globe) {pivot.add(globe);};
if (pivot) {scene.add(pivot);};

因此,例如,在父对象上绕 Z(远到近)轴旋转 23 度时:

pivot.rotation.set(THREE.Math.degToRad(0), THREE.Math.degToRad(0), THREE.Math.degToRad(23));

在动画函数中,地球将相对于其父项围绕 Y(从下到上)轴旋转(如果您想知道,v 只是一个保存 [=16 值的对象=]即360度,.rate即旋转速度,还有.roll.spin.tilt变量分别对应球体的X、Y、Z旋转,以度为单位):

function animate()
{
  delta = clock.getDelta();
  resize();
  v.spin = (v.loop + v.spin + v.rate * delta) % v.loop;
  globe.rotation.set(THREE.Math.degToRad(v.roll), THREE.Math.degToRad(v.spin), THREE.Math.degToRad(v.tilt));
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

就像下面的绿色箭头指示的那样,而不是红色箭头指示地球是否没有旋转父对象的方式:

这很简单,而且效果很好,如果我这样做:

pivot.rotation.set(THREE.Math.degToRad(v.roll), THREE.Math.degToRad(0), THREE.Math.degToRad(v.tilt));
globe.rotation.set(THREE.Math.degToRad(0), THREE.Math.degToRad(v.spin), THREE.Math.degToRad(0));

在上面的动画功能和我的按需/手动旋转系统中,没有改变相机位置/方向,因为这是由 Three.js 的 ArcballControls 库按需要处理的,也在上面可见。

但是,我想通过使用 Three.js 中可用的其他工具(如矩阵、向量、四元数或其他内置函数)在其父对象内部实现此对象旋转,为地球设置父级并在父级和子级之间分配旋转。这个想法是像上面的原始动画功能一样正常地进行地球旋转,并应用一些其他工具(甚至公式)来改变旋转并产生所需的效果。我该怎么做?

为了清楚起见,这种方法相对于为地球创建父级的好处是:

此外,如果其他方法太复杂,以防万一我最终选择上面的父子方法,我将如何将旋转系统“重置”为“原始”(即红色箭头)方式在那种情况下,不改变对象的视觉方向?我的意思是,将 pivot 旋转重置为 (0, 0, 0) 很清楚,但是应用于地球子项的旋转是什么,以便即使其父项现在未旋转,它也保持不变?

注意:为简单起见,假定父组/子组/对象都位于 (0, 0, 0) 位置,并且父旋转在单个图上说明轴,但理想情况下,替代方案应该允许对枢轴和对象进行不同的假设定位,而地球仪改变旋转应该可以在所有 3 个轴上进行。

P.S. 随时提出改进问题的建议,以使其更清晰或更紧凑(抱歉,我不是专家在技​​术术语中,如世界或局部旋转等),但在你完全确定之前不要急于将其标记为重复或关闭它

你的问题很长,但我认为你要找的是“轮换顺序”。旋转通常应用于 x,然后是 y,最后是 z 轴。

您可能希望将地球的倾斜度 (z) 放在第一位,然后将日自转 (y) 放在最后,因此您可以更改为:globe.rotation.order = "ZXY"

See here for official documentation on rotation order