Tips for making objects rotate vertically on their axis and orbit around another object in three.js

Thank you in advance for all the support as I've been asking a lot of questions about my project.

My project involves creating a simulation where a planet earth and moon rotate around a sun. (They're not exactly rotating around the sun, but more around the central axis where the sun is positioned).

I started by creating the geometries and adding them to the scene and then to the orbit group as shown below

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

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

Then, I set up the rotation within the render function like this

                   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);
            }

Currently, the moon and earth are orbiting around the sun instead of the moon revolving around the earth while it orbits the sun. Is there a way to specify the exact point or object that should be orbited and also customize the orbit axis rather than just 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;
                }

Answer №1

To achieve this, you can easily nest THREE.Object3D objects inside each other, adjusting their positions by rotations, radii, and centers.

Take a look at this straightforward example, where orbit controls are utilized - use the mousewheel to zoom out and drag to rotate:

https://i.sstatic.net/AJ6YY.gif

<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: Apologies for any language errors

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How should we structure our JavaScript code: MVC or self-rendering components?

I'm in the process of developing a highly JS-centric web application. The bulk of the work is being carried out on the client side, with occasional syncing to the server using AJAX and XMPP. This is my first venture into creating something of this ma ...

Tips for navigating a dynamic viewport using scroll movement

Attempting to create a responsive page with two distinct sections at this example link including: Map View Table View Both of these views (table and map divs) need to be responsive without a hard-coded height, so the size of the map div adjusts automatic ...

"When using FireFox, you can easily create a hyperlink that scrolls to a specific section of a webpage,

I have created a style for image button: .sticky { position: fixed; top: 50px; width: 120%; z-index: 1; } @media screen and (min-device-width : 100px) and (max-width: 600px) { .sticky{ display:none; } } and also implemented a script for it: ...

What is the method for determining the overall page load time of a website, taking into account the total loading time instead of just the document.ready()

I recently attempted to create a function using either JavaScript or Python with Selenium to measure the page load time of a website. While document.ready() gives me the DOM load time, it may not capture AJAX calls that occur afterwards. I noticed there i ...

Modify content on a link using AngularJS

Currently, my setup looks like this: HTML Code <div ng-app="home" ng-controller="customersCtrl"> <div ng-bind-html="home" id="content">{{content}}</div> </div> JS Code angular.module('home', []).controller('c ...

Transition the object in smoothly after the slide has changed

How can I make the h4 tags fade in after the divs slide into view, while also adding the class "current" to each visible slide? Check out the example on JSFiddle here. <div class="slider"> <div class="slides"> <div class="slide ...

Ensure that the user remains within the current div when they click the submit button, even if the textbox is

For the past 48 hours, I've been grappling with an issue on my HTML page that features four divs. Each div contains three input fields and a button. The problem arises when a user leaves a text box empty upon submitting - instead of staying in the sam ...

Route parameter in JavaScript: only accept numerical values

Is it possible to restrict parameter types to only accept digits? If a letter or other character is inputted, I want to fallback to a default scenario. Below are the two attempts I've made. app.get('/multi/:num?', function (request, respons ...

JavaScript Evaluation Error

try { eval(somejavascript); } catch(e) { console.log(e); } When I encounter runtime errors like: TypeError: Cannot call method 'leftPad' of undefined I wonder if there is any way to debug this error. Specifically, I'm looking for ...

Initiating a server call to fetch data using jQuery's AJAX function

I need to create a simple AJAX request to check if a username already exists in the database. The challenge lies in the JavaScript function that sends the request: function usernameCheck(){ $.post("http://example.com/signup", {username: $("#username"). ...

Sign up with React: A seamless registration form for

Currently, I am working on integrating a signup feature into my React application Here is a snippet of the code from my signup.JSX file: const Senddata = () => { // if(isvalid.username && // isvalid.password && ...

Move to the top of the page when the next action is activated

I am working with an Angular 8 application. Within the application, I have implemented navigation buttons for next and previous actions. My goal is to ensure that when a user clicks on the "next" button, the subsequent page starts at the top of the page ...

What is the method for identifying the points where two faces of two bufferGeometryBox objects intersect?

I am currently working on a 3D configurator project. In this project, a cube is initially displayed on the scene. When a side of the cube is clicked, a rectangle is supposed to appear. However, the issue I am facing is that upon clicking the same side of t ...

Do we need to use parseInt for the '*' operator in JavaScript?

I have an array where I am mapping it at some point to calculate the sum and percentages. However, when I tried implementing the logic, I noticed that using '*' directly works fine but using '+' adds the two strings together. For exampl ...

Contrast between using "export { something }" and "export something" in JavaScript modules

Can you explain the difference between the following code snippets: import something from "../something"; export { something }; vs import something from "../something"; export something; I noticed in the react-is package from react, there is an export ...

What is the best way to eliminate base tags from jQuery mobile scripts?

In jQuery Mobile, how can I remove the base href tags from the page and disable base href? Code Snippet: // Function to test for dynamic-updating base tag support function baseTagTest() { var fauxBase = location.protocol + "//" + location.host + l ...

Masking input text to allow numbers only using either javascript or jquery

I have experience with javascript and jquery. My goal is to create a masking template for <input type="text"> This template should only accept numbers and automatically format the input with dashes after every two numbers typed. The desi ...

JavaScript - Unexpected fluctuations in variable values

After studying Japanese language, I decided to try my hand at experimenting with JavaScript by creating a simple FlashCard game for a project. The game generates an array of random numbers, fills the divs with 6 possible choices using jQuery, randomly sele ...

Downsides of utilizing variables as global entities in React components

I am currently working on integrating API data into my React component: const request = new XMLHttpRequest() let outputArray = [] request.open('GET', 'http://localhost:3005/products/157963', true) request.onload = function() { let d ...

How to make multiple requests to populate a single object in MongoDB

I am in the process of developing a forum and I need to find out the number of messages in each topic. In my GetListTopic method, I retrieve the list of topics and then I query the forum_message table to count the messages for each topic in my list: db. ...