我正在尝试学习Three.js,对这些技术是陌生的。我实现了太阳绕行星公转,月亮绕行星公转的任务。我所关心的是,做我到目前为止所要做的事情,我必须在渲染循环中制作很多对象并执行很多计算。

1.源代码:

WestLangley通过更容易理解的方式为我们提供了提琴提琴来呈现问题,因此:


this fiddle呈现的像现在一样-行星的母行星位于太阳内部,旋转该母行星将使行星绕轨道运行。但是,与每个行星/月亮一个额外的对象一起,存在一个问题,即在updateMatrixWorld Object3D方法期间,父级旋转也会使行星旋转到位。因此,它旋转的速度会比您查看mesh2.rotateOnAxis( AXIS, 0.01 );位所假定的速度快一点。
this fiddle显示了一种无父方法。情况是,我正在尝试寻找方法,可以在系统启动时配置行星位置/自旋速度/轨道速度,而不仅仅是提供服务器时间,因此它将使处于相同位置的玩家之间感觉到同步。


3.质疑本身

就我阅读手册而言,我发现有可能使用Three.js矩阵逻辑来执行此类动画。我愿意尽可能减少对象内部::animate()的使用(也许是通过覆盖updateMatrixupdateMatrixWorld方法)。不幸的是,我的英语和数学知识都不够好理解,这些矩阵又是怎么回事。如果有人可以帮助我,我将非常感激。

4.当前工作进展

工作提琴是here。我能够创建一个Planet,并拥有几乎所有我想要的东西。剩下的一个问题是,一个行星希望以更随机的角度绕轨道运行。

最佳答案

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

为此,我实现了称为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%充满信心,因此我们欢迎进一步的优化。

09-25 17:32