动画行星围绕父母的旋转状态进行轨道运动

时间:2015-04-20 09:39:00

标签: javascript matrix three.js matrix-transform

我正在努力学习Three.js,对这些技术不熟悉。我实现了一个绕行星绕行的太阳,月亮环绕着行星。我关心的是,到目前为止,我必须做很多对象,并在渲染循环中执行大量计算。

1。源代码:

WestLangley为我们提供了以更易于理解的方式呈现问题的小提琴:

  • this fiddle呈现的更像它现在正在寻找 - 行星的父母在太阳内,旋转那个父母将使行星轨道。但是在每个行星/月球上还有一个额外的物体,在updateMatrixWorld Object3D方法期间,父旋转也会将行星旋转到位。因此,通过查看mesh2.rotateOnAxis( AXIS, 0.01 );位,它会比您假设的速度快一点。
  • this fiddle显示了一个无父母方法。案例是,我正试图找到方法,我可以在系统启动时配置行星位置/旋转速度/轨道速度,而不仅仅是服务器时间,因此它会让玩家在同一位置感觉同步

3。问题本身

据我浏览手册,我发现可能使用Three.js矩阵逻辑执行此类动画。我愿意尽可能地减少对象内::animate()的使用(可能通过覆盖updateMatrixupdateMatrixWorld方法)。不幸的是,我的英语和数学都不够理解,有什么方法可以解决这些矩阵问题。如果有人可以帮助我,我会非常感激。

4。当前的工作进度

工作小提琴是here。我能够创造一个星球并且几乎拥有我想要的一切。剩下的一个问题是,想要以更随机的程度绕行星运行。

1 个答案:

答案 0 :(得分:2)

分叉这一点。我愿意减少太阳系中的物体数量,隐藏动画循环中的计算,并使其尽可能配置。

为此,我实施了名为Mesh的自定义Planet

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

并覆盖标准Object3D矩阵计算函数:

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

由于这个原因,我可以重新计算在标准方法内部在该基础上创建的行星/卫星的位置和旋转,每次渲染调用都在运行。

为了好的开始,我在Planet构造函数中构建了一些我需要的基本参数:

    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

那些应该可以在创建时配置,但是现在硬编码还可以。

进入新的updateMatrix(),计算与其父母有关的当前行星位置:

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

最后,但并非最不重要 - 通过Object3D.worldMatrix实施将这些更改提供给updateMatrixWorld

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.

工作代码位于this fiddle。这样我在渲染循环期间减少了数学时间,减少了嵌套代码,最后:减少了最多50%的对象数量。但我对这个答案并不是100%有信心,所以任何进一步的优化都会受到赞赏。