【问题标题】:How to rotate a object on axis world three.js?如何在轴世界 three.js 上旋转对象?
【发布时间】:2012-06-22 14:25:48
【问题描述】:

是否可以以世界而不是对象的轴为轴进行旋转?

我需要对一个对象进行一些旋转,但是在第一次旋转之后,我无法像我想要的那样进行其他旋转。

如果无法在世界轴上进行旋转,我的第二个选择是在第一次旋转后重置轴。有这个功能吗?

我不能使用object.eulerOrder,因为当我在一些旋转后设置object.eulerOrder="YZX" 时,它会改变我的对象的方向。

【问题讨论】:

标签: javascript three.js


【解决方案1】:

更新:3 - 0.125.2

演示:codesandbox.io

const THREE = require("three");

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.z = 5;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const geometry = new THREE.BoxGeometry(1, 1, 1, 4, 4, 4);
const material = new THREE.MeshBasicMaterial({
  color: 0x628297,
  wireframe: true
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// select the Z world axis
const myAxis = new THREE.Vector3(0, 0, 1);
// rotate the mesh 45 on this axis
cube.rotateOnWorldAxis(myAxis, THREE.Math.degToRad(45));

function animate() {
  // rotate our object on its Y axis,
  // but notice the cube has been transformed on world axis, so it will be tilted 45deg.
  cube.rotation.y += 0.008;
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

animate();

【讨论】:

  • getRotationFromMatrix 不被识别为函数,multiplySelf 也是。我需要使用特定的 three.js 版本吗?
  • getRotationFromMatrix(object.matrix, object.scale) -> setFromRotationMatrix(object.matrix)multiplySelf -> multiply。 r71
  • 注意:使用THREE.Math.degToRad(30) 将度数转换为弧度。比30 * Math.PI/180更具可读性。
  • fiddle 不再起作用 - cmets 的提示也不起作用
  • @WolfgangFahl - 更新到 r107,这些天看起来更容易做,希望这对你有帮助!
【解决方案2】:

@Neil 的更新答案(在 r98 上测试)

function rotateAroundWorldAxis(obj, axis, radians) {
   let rotWorldMatrix = new THREE.Matrix4();
   rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);
   rotWorldMatrix.multiply(obj.matrix);
   obj.matrix = rotWorldMatrix;
   obj.setRotationFromMatrix(obj.matrix);
}

【讨论】:

    【解决方案3】:

    @acarlon 您的回答可能刚刚结束了一周的沮丧。我已经稍微完善了你的功能。这是我的变化。我希望这可以节省我花费 20 多个小时试图解决这个问题的时间。

    function calcRotationAroundAxis( obj3D, axis, angle ){
    
        var euler;
    
        if ( axis === "x" ){
            euler = new THREE.Euler( angle, 0, 0, 'XYZ' );      
        }
    
        if ( axis === "y" ){
            euler = new THREE.Euler( 0, angle, 0, 'XYZ' );              
        }
    
        if ( axis === "z" ){
            euler = new THREE.Euler( 0, 0, angle, 'XYZ' );      
        }
        obj3D.position.applyEuler( euler );
    }
    
    function calcRotationIn3D( obj3D, angles, order = 'XYZ' ){
    
       var euler;
    
       euler = new THREE.Euler( angles.x, angles.y, angles.z, order );
    
       obj3D.position.applyEuler( euler );
    
    }
    

    这在 r91 中运行良好。 希望对您有所帮助。

    【讨论】:

      【解决方案4】:

      在 r59 附近的某个地方,这变得容易多了(围绕 x 旋转):

      bb.GraphicsEngine.prototype.calcRotation = function ( obj, rotationX)
      {
          var euler = new THREE.Euler( rotationX, 0, 0, 'XYZ' );
          obj.position.applyEuler(euler);
      }
      

      【讨论】:

        【解决方案5】:

        这里有一个小的变化。用 r56 测试。

        THREE.Object3D._matrixAux = new THREE.Matrix4(); // global auxiliar variable
        // Warnings: 1) axis is assumed to be normalized. 
        //  2) matrix must be updated. If not, call object.updateMatrix() first  
        //  3) this assumes we are not using quaternions
        THREE.Object3D.prototype.rotateAroundWorldAxis = function(axis, radians) { 
            THREE.Object3D._matrixAux.makeRotationAxis(axis, radians);
            this.matrix.multiplyMatrices(THREE.Object3D._matrixAux,this.matrix); // r56
            THREE.Object3D._matrixAux.extractRotation(this.matrix);
            this.rotation.setEulerFromRotationMatrix(THREE.Object3D._matrixAux, this.eulerOrder ); 
            this.position.getPositionFromMatrix( this.matrix );
        }
        THREE.Object3D.prototype.rotateAroundWorldAxisX = function(radians) { 
            this._vector.set(1,0,0);
            this.rotateAroundWorldAxis(this._vector,radians);
        }
        THREE.Object3D.prototype.rotateAroundWorldAxisY = function(radians) { 
            this._vector.set(0,1,0);
            this.rotateAroundWorldAxis(this._vector,radians);
        }
        THREE.Object3D.prototype. rotateAroundWorldAxisZ = function(degrees){ 
            this._vector.set(0,0,1);
            this.rotateAroundWorldAxis(this._vector,degrees);
        }
        

        最后三行只是从矩阵中重新同步参数(position,rotation)...我想知道是否有更有效的方法来做到这一点...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-02-29
          • 2015-07-23
          • 1970-01-01
          • 2013-02-06
          • 1970-01-01
          • 2012-06-19
          • 2017-10-26
          相关资源
          最近更新 更多