我正在尝试围绕另一个已经在轴上旋转的 (THREE.mesh) 3d 对象旋转。任何指针?

I'm trying to rotate a (THREE.mesh) 3d object around another that is already rotating on an axis. Any pointers?

我正在寻找一种方法,让卫星绕着我的行星运行,而我的行星又绕着我的太阳运行。

(所有这些都是three.js中的3d对象)

我已经定义了我所有的物体,目前地球绕着我的太阳旋转,但我很难让月球绕着已经旋转的地球旋转。

sun = models['sun'];
earth = models['earth'];
moon = models['moon'];

let suns = new THREE.Group();
suns.add(sun);

let planets = new THREE.Group();
planets.add(earth);

let moons = new THREE.Group();
moons.add(moon);

scene.add(sun);
scene.add(earth);
scene.add(moon);

var orbit = 3;
var date = Date.now() * 0.0005;

earth.position.set(Math.cos(date) * orbit, 0, Math.sin(date) * orbit);

earth.rotation.y += 0.01*animation_speed;
moon.rotation.y += 0.01*animation_speed;

预期:地球围绕太阳旋转(静态),而月球在围绕太阳旋转时也围绕地球旋转。

当前:地球围绕太阳旋转。不确定如何处理月亮...

如果你为你的对象创建一个层次结构,那么它们会围绕它们的父对象旋转。

首先请注意,您的群组毫无意义。如果您调用 suns.add(sun) 然后调用 scene.add(sun),第二次调用会从 suns 中删除 sun 并将其添加到 scene,因此您的组为空。所以在下面的例子中,我不会使用分组。

F.e.

const sun = models['sun'];
const earth = models['earth'];
const moon = models['moon'];

const sunContainer = new THREE.Object3D
sunContainer.add(sun)
const earthContainer = new THREE.Object3D
earthContainer.add(earth)
const moonContainer = new THREE.Object3D
moonContainer.add(moon)

scene.add(sunContainer); // sunContainer is child of scene
sunContainer.add(earthContainer); // earthContainer is child of sunContainer
earthContainer.add(moonContainer); // moonContainer is child of earthContainer

var earthOrbitRadius = 3;
var moonOrbitRadius = 0.2;

// position them at their orbit radius (relative to their parents)
earthContainer.position.set(earthOrbitRadius, 0, 0);
moonContainer.position.set(moonOrbitRadius, 0, 0);

// each planet rotates around its poles
sun.rotation.y += 1*animation_speed;
earth.rotation.y += 1*animation_speed;
moon.rotation.y += 1*animation_speed;

// and each planet orbits around its parent
sunContainer.rotation.y += 0.1*animation_speed;
earthContainer.rotation.y += 0.1*animation_speed;

现在将这些位恢复到您的代码中,根据需要调整数字,它应该会像想要的那样工作。

还有其他方法,这只是一种方法。要使行星旋转独立于轨道旋转,您可以使用负轨道旋转调整行星旋转。或者,您可以让容器绕轨道运行,然后将太阳、地球和月亮直接添加到场景而不是容器,然后将容器位置复制到它们,同时它们独立旋转。或者您可以使用物理引擎(Bullet Physics 内置于 Three.js 中)。或者你使用 pivot points.

顺便说一下,如果您 post 工作代码,那将会有所帮助。 :)

我开发了一个简单的示例来说明 THREE.Object3D 的层次结构以及子项与其 "parents" 及其位置和旋转的关系。

var scene = new THREE.Scene();
var aspect = window.innerWidth / window.innerHeight;
var camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
solarsystem.forEach(d => create(d, scene))
scene.add(sphere({radius:5, orbit:0}))

function create(d, target) {
   var o = new THREE.Object3D(d.name);
   o.add(orbit(d));
   let p = sphere(d)
   o.add(p);
   d.satellites && d.satellites.forEach(d1 => create(d1, p))
   target.add(o);
   d.o=o; 
}

function orbit(d) {
    var o = new THREE.Object3D('orbit '+d.name);
    o.rotateX(Math.PI/2);
    o.add( new THREE.Line( 
        new THREE.CircleGeometry( d.orbit, 64 ), 
        new THREE.LineBasicMaterial( { color: 0xffffff } ) ));
    return o;
}

function sphere(d){
    var o = new THREE.Object3D('sphere '+d.name);
    o.add(new THREE.Mesh( 
        new THREE.SphereGeometry(d.radius, 16, 16), 
        new THREE.MeshBasicMaterial({ 
            color: 0x2980b9, wireframe: true 
        })));
    o.translateX(d.orbit)
    return o;
}

var grid = new THREE.GridHelper(500, 100, 0x666666, 0x444444)
grid.rotateY(Math.PI/2);
scene.add(grid);
camera.position.set(5,5,0);

new THREE.OrbitControls( camera, renderer.domElement );

let t = 0;

function render(dt) {
    let t2= dt-t;
    requestAnimationFrame( render );
    renderer.render( scene, camera );
    solarsystem.forEach(upd)
    t = dt;
    
    function upd(d) {
        d.o.rotateY(t2/10000*d.speed);
        d.satellites && d.satellites.forEach(upd)
    }
}

requestAnimationFrame( render );
body, canvas { 
  margin: 0;  
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/103/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
    let solarsystem = [{
        name: 'earth', radius: 2, orbit: 30, speed: 2,
        satellites: [{
            name: 'moon', radius: 1, orbit: 6, speed: 1,
        }]
    }, {
        name: 'mars', radius: 2, orbit: 50, speed: 1,
        satellites: [{
            name: 'phobos', radius: 0.5, orbit: 3, speed: 1,
        }, {
            name: 'deimos', radius: 0.5, orbit: 4, speed: 3,
        }]
    }];
</script>