Javascript 如何在轴世界three.js上旋转对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11119753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:33:30  来源:igfitidea点击:

How to rotate a object on axis world three.js?

javascriptthree.js

提问by EnZo

Is it possible to do rotations taking axis of the world and not of the object?

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

I need to do some rotations of an object, but after the first rotation, I can't do other rotations like i want.

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

If it's not possible to do rotation on the axis of the world, my second option is to reset the axis after the first rotation. Is there some function for this?

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

I can't use object.eulerOrderbecause it changes the orientation of my object when I set object.eulerOrder="YZX"after some rotations.

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

回答by Neil

THREE - r107

三 - r107

// select the Z world axis
this.myAxis = new Vector3(0, 0, 1);

// rotate the mesh 45 on this axis
this.mesh.rotateOnWorldAxis(this.myAxis, Math.degToRad(45));

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

回答by Most Wanted

Updated answer from @Neil (tested on r98)

来自@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);
}

回答by leonbloy

Here's a small variation. Tested with r56.

这是一个小的变化。用 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);
}

The three last lines are just to resync the params (position,rotation)from the matrix... I wonder if there is a more efficient way to do that...

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

回答by acarlon

Somewhere around r59 this gets a lot easier (rotate around x):

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

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

回答by Mark Scott Lavin

@acarlon Your answer might just have ended a week of frustration. I've refined your function a bit. Here are my variations. I hope this saves someone else the 20+ hours I spent trying to figure this out.

@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 );

}

This works beautifully in r91. Hope it helps.

这在 r91 中非常有效。希望能帮助到你。