如何使用 THREE.js 围绕行星旋转一些卫星?

Posted

技术标签:

【中文标题】如何使用 THREE.js 围绕行星旋转一些卫星?【英文标题】:How do I rotate some moons around a planet with THREE.js? 【发布时间】:2013-02-19 07:26:16 【问题描述】:

我认为这张照片最能说明我的问题:

首先我沿着红线平移方框。接下来,我希望旋转的效果是a 中的蓝线,但实际发生的更像b 中的蓝线。感觉就像改变旋转总是相对于原始对象空间,但平移(尽管首先发生)总是相对于父对象,并且不会真正影响与对象空间相关的几何点。如果这令人困惑,我深表歉意;显然我是新手。

产生这种效果的代码的重要部分如下。请记住,图像的方向与此代码生成的方向不同;图片只是一个例子,可以清楚地展示效果。

var objectContainer = new THREE.Object3D();

var tubeRadius = 100;
var tubeGeometry = new THREE.CylinderGeometry(tubeRadius, tubeRadius, tubeRadius * 3, 36, 1, false);
var tube = new THREE.Mesh(tubeGeomtry, material);
scene.add( tube );

var boxes = new THREE.Object3D();
var boxEdge = 50;
var boxGeometry = new THREE.CubeGeometry(boxEdge, boxEdge, boxEdge);
var box1 = new THREE.Mesh( boxGeometry, material );
box1.translateX(tubeRadius + boxEdge / 2 + 5);
box1.translateY(boxEdge / 2);
box1.rotation = new THREE.Vector3(0, 2*Math.PI/3*0, 0);
boxes.add(box1);
var box2 = box1.clone();
box2.rotation = new THREE.Vector3(0, 2*Math.PI/3*1, 0);
boxes.add(box2);
var box3 = box1.clone();
box3.rotation = new THREE.Vector3(0, 2*Math.PI/3*2, 0);
boxes.add(box3);
scene.add( boxes );

我能想到的唯一解决方案是将每个盒子包装在另一个对象空间中并围绕它进行旋转,但这似乎是多余的工作。实现我想要的结果的首选方法是什么?

【问题讨论】:

我不知道 Three.js,但是通过 Math.cos(rotation) * boxEdge / 2, Math.sin(rotation) * boxEdge / 2 以及本地旋转翻译它怎么样? 感觉就像双重工作,旋转和翻译每个盒子。我真正想要做的是围绕同一点旋转每个克隆,这是平移之前的原点。 【参考方案1】:

有几种方法可以做你想做的事,但我认为最简单的是这样:

// parent
parent = new THREE.Object3D();
scene.add( parent );

// pivots
var pivot1 = new THREE.Object3D();
var pivot2 = new THREE.Object3D();
var pivot3 = new THREE.Object3D();

pivot1.rotation.z = 0;
pivot2.rotation.z = 2 * Math.PI / 3;
pivot3.rotation.z = 4 * Math.PI / 3;

parent.add( pivot1 );
parent.add( pivot2 );
parent.add( pivot3 );

// mesh
var mesh1 = new THREE.Mesh( geometry, material );
var mesh2 = new THREE.Mesh( geometry, material );
var mesh3 = new THREE.Mesh( geometry, material );

mesh1.position.y = 5;
mesh2.position.y = 5;
mesh3.position.y = 5;

pivot1.add( mesh1 );
pivot2.add( mesh2 );
pivot3.add( mesh3 );

然后在你的渲染循环中:

parent.rotation.z += 0.01;

编辑:更新小提琴:https://jsfiddle.net/edqf7ugc/

three.js r.116

【讨论】:

感谢您的示例。正如我在问题中提到的,这就是我的想法。这是问题的典型解决方案吗?我打算开发一段时间,我只是想确保我不会在脚下开枪。 是的。这是典型的。另一种解决方案是让每个框都成为场景的子对象,并使用数学计算每一帧的新 positionrotation 向量。【参考方案2】:

创建一个复合对象,其中心将是内部对象旋转的点是一个明显的答案,并且编写起来非常快。只需创建一个 Object3D 并将您的框添加到其中。

this question 涵盖了类似的方法。它移动了一个对象的顶点,因此它实际上有一个新的中心。

或者,您可以手动处理矩阵。试试这个:

var boxGeometry = new THREE.CubeGeometry(boxEdge, boxEdge, boxEdge);
var mr = new THREE.Matrix4();
var mt = new THREE.Matrix4();
mt.setPosition(new THREE.Vector3(0,tubeRadius,0));
var box1 = new THREE.Mesh( boxGeometry, material );
box1.applyMatrix(mt);
var box2 = box1.clone();
mr.makeRotationZ(2 * Math.PI /3);
box2.applyMatrix(mr);
boxes.add(box2);
var box3 = box1.clone();
mr.makeRotationZ(4 * Math.PI /3);
box3.applyMatrix(mr);
boxes.add(box3);
boxes.add(box1);
scene.add( boxes );

【讨论】:

以上是关于如何使用 THREE.js 围绕行星旋转一些卫星?的主要内容,如果未能解决你的问题,请参考以下文章

如何围绕组内的一个点旋转 Three.js 组?

three.js围绕边缘旋转三角形

使用鼠标围绕中心旋转 Three.js 相机

Three.js - 围绕某个轴旋转球体

three.js 围绕 Y 轴的相机旋转似乎关闭

three.js:结合 tween.js 围绕世界轴旋转对象