1

I'm trying to learn Three.js, beeing new to those technologies. I achieved a sun with planet orbitting around, with moon orbitting around planet. What am I concerned of, is to do what i have so far i have to make quite a lot of objects and perform quite a lot of calculations during rendering loops.

1. Sourcecodes:

WestLangley provided us with fiddles presenting problem in more easy-to-understand way so:

  • this fiddle presents more like it is looking right now - planet has its parent inside sun, and rotating that parent will make planet orbit. But along with one extra object per planet/moon, theres an issue that parent rotation spins planet in place too, during to updateMatrixWorld Object3D method. So it will spin a bit faster than you may assume by looking at mesh2.rotateOnAxis( AXIS, 0.01 ); bit.
  • this fiddle shows one parent-less approach. Case is, I'm trying to find way, where I can configure planet positions/spins-speed/orbit-speed at system start and than just feed it with server time, so it will make it feel synchronised between players being at same location.

3. Question itself

As far as I travelled through manuals, I found there may be a possibility of performing such animation using Three.js matrix logic. I'm willing to reduce usage of ::animate() inside objects as far as possible (maybe by overriding updateMatrix and updateMatrixWorld methods). Unfortunately my english nor math are not good enough to understand, whats going around with those matrixes. If somebody can help me, I would really appreciate this.

4. Current work progress

Working fiddle is here. I was able to create a Planet and have almost all I want. One left issue is that, a would like to planet orbit at more random-looking degrees.

Community
  • 1
  • 1
yergo
  • 4,761
  • 2
  • 19
  • 41
  • [This fiddle](http://jsfiddle.net/t83pzoj2/) shows how three.js is intended to be used. See [this post](http://stackoverflow.com/questions/11966779/learning-webgl-and-three-js/11970687#11970687) for some math resources. – WestLangley Apr 20 '15 at 16:19
  • @WestLangley this looks exactly like what I have right now. Problem is, that rotation of pivot along changing mesh2 position, changes its local rotation in result of `updateWorldMatrix` I am willing in controlling its rotation speed separately and avoid using empty Object3D elements as parents. Is it at least possible? – yergo Apr 21 '15 at 08:44
  • Is this what you mean -- with no pivots? http://jsfiddle.net/t83pzoj2/4/ – WestLangley Apr 21 '15 at 15:19
  • @WestLangley looks like it work the way I'm willing to achieve, but i wonder about spinning moon around planet at certain position with this approach. If you are able to manage it simply I may accept that as answer :) – yergo Apr 21 '15 at 15:33
  • It has only been 15 minutes. I expect you can figure it out yourself and answer your own question. : - ) – WestLangley Apr 21 '15 at 15:41

1 Answers1

2

Forked this bit around. I was willing to reduce object count in my solar system, hide calculations from animation loop nad make it as configurable as possible.

To make this I implemented custom Mesh called Planet:

var Planet =  function ( geometry, material ) {
    THREE.Mesh.call( this, geometry, material );
    this.type = 'Planet';
};
Planet.prototype = Object.create( THREE.Mesh.prototype );

and overriden standard Object3D matrix-calculation functions:

Planet.prototype._matrixUpdate = THREE.Object3D.prototype.updateMatrix;
Planet.prototype._updateMatrixWorld = THREE.Object3D.prototype.updateMatrixWorld;
Planet.prototype.updateMatrix = function() {};
Planet.prototype.updateMatrixWorld = function() {};

Thanks to that I can recalculate positions and rotations of planets/moons created on that base inside standard methods been running every render call.

For good start I've prototyped in Planet constructor some basic arguments I will need:

    this.rotationAxis = new THREE.Vector3( 0, 1, 0 ).normalize(); // always rotate on Y
    this.rotationSpeed = Math.PI/2; // length of planet day

    this.orbitAxis = new THREE.Vector3( 0, 0.1, 1 ).normalize(); // y,z for orbit AXIS
    this.orbitSpeed = Math.PI / 8; // length of planet year

those should be configurable on creation time, but for now hardcode is ok.

Than going into new updateMatrix(), to calculate current planet position in relation of it's parent:

Planet.prototype.updateMatrix = function() {

    var dta = delta || 0; // THREE.Clock::getDelta

    // just for now, sun is not orbiting around
    // anything, so checking instance
    if ( this.parent instanceof Planet ) {
        // rotate position in relation to parent, to make planet orbit
        this.position.applyAxisAngle(this.orbitAxis, this.orbitSpeed * dta);
    }

    // rotate planet in place, to make it spin
    this.rotateOnAxis(this.rotationAxis, this.rotationSpeed * dta);

    this._matrixUpdate(); // fabricating Object3D.matrix
};

And last, but not least - providing those changes to Object3D.worldMatrix via updateMatrixWorld implementation:

Planet.prototype.updateMatrixWorld = function() {
    if ( this.matrixAutoUpdate === true ) this.updateMatrix();

    if ( this.matrixWorldNeedsUpdate === true || force === true ) {

        if ( this.parent === undefined ) {
            this.matrixWorld.copy( this.matrix );
        } else {
            // THIS else block is all whats different
            // between Planet and standard Object3Dmethod
            v = new THREE.Vector3(); // empty vector
            v.applyMatrix4(this.parent.matrixWorld); // setup with parent position
            v.add(this.position); // add local position

            // compose instead of multiplication
            this.matrixWorld.compose(v, this.quaternion, this.scale); 

        }
   // ... rest like in THREE's (71) git.

Working code is in this fiddle. This way I have reduced math-time during render loop, reduced nested code and finally: reduced objects count by up to 50%. But I'm am not 100% confident about that answer, so any further optimisations are appreciated.

yergo
  • 4,761
  • 2
  • 19
  • 41