2

you probably noticed me asking quite a few questions related to my project so thank you in advance for all the support.

My project consists of a planet earth and moon that rotate around the sun. (They aren't specifically rotating around the sun, it's more just around the 0,0 axis where the sun happens to be).

I initially created my geometries and then added them into the scene and then into the orbit group as follows

var orbitGroup = new THREE.Object3D();
                scene.add(orbitGroup); 

            scene.add(planetEarth);
            orbitGroup.add(planetEarth);
            scene.add(planetMoon);
            orbitGroup.add(planetMoon);

I then declared the rotation within the render function as follows

                   planetEarth.add( planetMoon );
                planetEarth.add(rocketGroup);

            // call the render function
            var angle = 0;
            render();

            function render() {
                stats.update();

                 // rotate the orbit group
                angle += 0.002;                    
                angle += 0.002 * controls.EarthRotationSpeed;
                planetEarth.rotation.y += controls.EarthRotationSpeed;                    
                planetMoon.rotation.y += controls.MoonRotationSpeed;                    
                angle+= 0.01 * controls.SunRotationSpeed;
                planetSun.rotation.y += controls.SunRotationSpeed;        

                 // rotate the orbit group
                angle += 0.02;
                orbitGroup.rotation.y = -angle / 10;


                littleOrbitGroup.rotation.x = -angle;


                // render using requestAnimationFrame
                requestAnimationFrame(render);
                renderer.render(scene, camera);
            }

As you can tell, the moon and the earth are both orbiting around the sun instead of the moon rotating the earth while it rotates the sun. Is there a way I can declare the specific point or object that it should orbit and also make it orbit it at whatever axis I want rather than specifically on the y axis?

----------------EDIT-----------------

function createMesh(geom) {
                    var loader = new THREE.TextureLoader();
                    var planetTexture = loader.load("../assets/textures/planets/Earth.png");
                    var normalTexture = loader.load("../assets/textures/planets/EarthNormal.png");
                    var planetMaterial = new THREE.MeshPhongMaterial({map: planetTexture, bumpMap: normalTexture});
                    // create a multimaterial
                    var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [planetMaterial]);
                    return mesh;
                }
zadders
  • 428
  • 1
  • 8
  • 30

1 Answers1

5

You can easily do that using nesting of THREE.Object3D one inside another, shifting them by rotarions radiuses and rotating it's around centers.

Look at this simple example, here used orbit controls - use mousewheel to zoom out and drag to rotate:

enter image description here

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

<script>
    THREE.TOUCH = {}
    let base64prefix = 'data:image/png;base64,'
    let blue = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkuPn/PwAFkgLZdUNuXwAAAABJRU5ErkJggg=='
    let blue2= 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkqPz/HwAEcgJ5UUczUQAAAABJRU5ErkJggg=='
    let orange = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8H8PwHwAGGQJcoBRfLQAAAABJRU5ErkJggg=='
    
let solarsystem = [{
        texture: blue,
        name: 'earth', radius: 2, orbit: 30, speed: 2,
        satellites: [{
            texture: blue2, rotation: [1, 1, 1],
            name: 'rock', radius: 0.5, orbit: 4, speed: 5,
        },{
            texture: blue2,
            name: 'moon', radius: 1, orbit: 6, speed: 1,
        }]
    }, {
        texture: orange,
        name: 'mars', radius: 2, orbit: 50, speed: 1,
        satellites: [{
            texture: blue2,
            name: 'phobos', radius: 0.5, orbit: 3, speed: 1,
        }, {
            texture: blue2,
            name: 'deimos', radius: 0.5, orbit: 4, speed: 3,
        }]
    }];
   
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 );


// planets
solarsystem.forEach(d => create(d, scene));

// sun
let sun = sphere({radius:3, orbit:0, texture: orange});
scene.add(sun)

function create(d, target) {
   var o = new THREE.Object3D(d.name);
   d.rotation && o.rotateX(d.rotation[0]);
   d.rotation && o.rotateY(d.rotation[1]);
   d.rotation && o.rotateZ(d.rotation[2]);
   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.translateX(d.orbit);
    var loader = new THREE.TextureLoader();
    loader.load( base64prefix + d.texture, function ( texture ) {
        var geometry = new THREE.SphereGeometry( d.radius, 20, 20 );
        var material = new THREE.MeshBasicMaterial( { 
            map: texture, overdraw: 0.5 
        } );
        o.add( new THREE.Mesh( geometry, material ) );
    } );    
    return o;
}

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

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);
    sun.rotateY(t2/1000);
    t = dt;
    
    function upd(d) {
        d.o.rotateY(t2/10000*d.speed);
        d.satellites && d.satellites.forEach(upd)
    }
}

requestAnimationFrame( render );

</script>

<style>

  body, canvas { 
    margin: 0;  
    width: 100%;
    height: 100%;
    overflow: hidden;
    background-color: black;
  }
  
</style>

PS: Sorry for my english

Stranger in the Q
  • 3,668
  • 2
  • 21
  • 26
  • I edited the question to add the code of how I made my planet models, would I be able to apply it to your method? – zadders Apr 13 '19 at 13:03
  • @zadders if your question about adding texured spheres instead of blue wireframe - so yes – Stranger in the Q Apr 13 '19 at 13:29
  • Mine currently function like so: https://imgur.com/a/LEgcIIi how exactly would I apply that to mine? Also your English is perfect don't worry – zadders Apr 13 '19 at 15:57
  • @zadders i've added earth texture to snippet – Stranger in the Q Apr 13 '19 at 18:40
  • For my planets I have 2 images, one for the texture and one for the bump texture, would it be applied the same way? – zadders Apr 13 '19 at 22:22
  • @ stranger in the Q I've edited my code at the top for the render section, my rocket basically orbits around the earth now but that's only because it's part of the earth group similar to the moon. But it's not actually orbiting the earth the same way the earth is orbiting the sun. When I try recreate the same code it still won't work for some reason... This is how it looks now (https://imgur.com/a/mSsR8OI) is there any way you can think of me to get the rocket to orbit properly without having to change almost all my code? – zadders Apr 14 '19 at 00:59
  • @zadders look at mars in my example, there are 2 sattelites phobos and deimos in different orbits in different groups. if you add some angle to them... – Stranger in the Q Apr 14 '19 at 06:39
  • I'm finding it quite hard to understand how to translate your code into a form that I'd understand or be able to relate it to mine. Is there somewhere we can chat quickly just so I don't spam this post? – zadders Apr 14 '19 at 08:51
  • @zadders did you solve your problem? i’ve missed last your message.. – Stranger in the Q Feb 14 '20 at 15:59
  • I ended up getting it done, but not in the way I wanted. The assignment has been long due anyway ahaha – zadders Feb 14 '20 at 19:18
  • 1
    @StrangerintheQ This code sample is awesome and really helping me better understand three.js and how nested rotations work. Note, `new THREE.Object3d( xyz.name)` is a fail. Object3d constructor takes no arguments. You have to add `o.name = d.name` instead, numerous times in the code. That naming makes things easier to understand. – zipzit Oct 07 '20 at 00:19
  • @zipzit hm, looks like syntax is changed across versions.. – Stranger in the Q Oct 07 '20 at 06:54
  • 1
    No worries. Going through that code in great detail has really helped me wrap my head around threejs. I will say I don't fully understand what happens to children satellites when they hit the `upd()` recursive call with `d.o.rotateY()` thing. I'm trying hard to understand what is generating the Euler and quaternion matrices in this example. Again, many thx. – zipzit Oct 07 '20 at 08:08