Я пытаюсь повернуть (THREE.mesh) 3d-объект вокруг другого, который уже вращается на оси.Есть указатели? - PullRequest
2 голосов
/ 06 апреля 2019

Я ищу способ облететь луну вокруг моей планеты, которая вращается вокруг моего солнца.

(Все это трехмерные объекты в three.js)

Я определил все свои объекты, и в настоящее время Земля вращается вокруг моего Солнца, но мне трудно заставить Луну вращаться вокруг уже вращающейся Земли.

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;

Ожидаемое: Земля вращается вокруг Солнца (статично), а Луна вращается вокруг Земли, вращаясь вокруг Солнца.

Ток: Земля вращается вокруг Солнца. Не уверен, что делать с Луной ...

Ответы [ 2 ]

1 голос
/ 06 апреля 2019

было бы легко, если бы вы создали иерархию своих объектов, чтобы они вращались вокруг своих родителей.

Первое, заметьте, что ваши группы бессмысленны.Если вы набираете suns.add(sun), а затем набираете scene.add(sun), второй вызов удаляет sun из suns и добавляет его к scene, поэтому ваши группы пусты.Поэтому в следующем примере я не буду использовать группы.

Fe

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).Или вы используете точки разворота .

Кстати, это поможет, если вы разместите рабочий код.:)

0 голосов
/ 08 апреля 2019

Я разработал простой пример, иллюстрирующий иерархию THREE.Object3D и то, как дети соотносятся с ее «родителями», ее позициями и вращениями.

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>
...