Animating planet orbiting it's parent idependent on parent's rotation state

耗尽温柔 提交于 2019-12-06 20:39:25

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!