1

我正在尝试学习 Three.js,对这些技术很陌生。我实现了一个行星绕着太阳运行,而月亮绕着行星运行。我所关心的是,要做我目前所做的事情,我必须制作相当多的对象并在渲染循环期间执行相当多的计算。

1. 源代码:

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

  • 这个小提琴现在看起来更像是它现在的样子——行星在太阳内部有它的父级,旋转那个父级将使行星轨道运行。updateMatrixWorld但是,除了每个行星/月球一个额外的物体外,在Object3D 方法期间,父旋转也会将行星旋转到位。所以它会比你想象的要快mesh2.rotateOnAxis( AXIS, 0.01 );一点。
  • 这个小提琴展示了一种没有父母的方法。案例是,我正在尝试找到方法,我可以在系统启动时配置行星位置/旋转速度/轨道速度,而不仅仅是提供服务器时间,所以它会让处于同一位置的玩家之间感觉同步.

3. 质疑本身

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

四、目前工作进展

工作小提琴就在这里。我能够创造一个星球并拥有几乎所有我想要的东西。剩下的一个问题是,想要以更随机的角度运行行星轨道。

4

1 回答 1

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

这些应该可以在创建时进行配置,但现在硬编码是可以的。

比进入 new 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.

工作代码在这个小提琴中。通过这种方式,我减少了渲染循环期间的数学时间,减少了嵌套代码,最后:减少了高达 50% 的对象计数。但我对这个答案不是 100% 有信心,所以任何进一步的优化都值得赞赏。

于 2015-04-22T09:22:39.483 回答