web-dev-qa-db-ja.com

軸ワールドthree.jsでオブジェクトを回転させる方法は?

オブジェクトではなく世界の軸をとって回転することは可能ですか?

オブジェクトのいくつかの回転を行う必要がありますが、最初の回転の後、私が望むように他の回転を行うことができません。

世界の軸上で回転を行うことができない場合、私の2番目のオプションは、最初の回転後に軸をリセットすることです。このための機能はありますか?

object.eulerOrderを設定すると、オブジェクトの方向が変わるため、object.eulerOrder="YZX"を使用できません。

15
EnZo

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

私の例を参照してください- https://codesandbox.io/s/threejs-bare-example-4dqmm

16
Neil

@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);
}
2
Most Wanted

これが小さなバリエーションです。 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);
}

最後の3行は、マトリックスからparams (position,rotation)を再同期するためのものです...それを行うためのより効率的な方法があるかどうか疑問に思います...

2
leonbloy

R59あたりのどこかで、これははるかに簡単になります(xの周りを回転します):

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

@acarlonあなたの答えはちょうど1週間の欲求不満を終えたかもしれません。私はあなたの機能を少し洗練しました。これが私のバリエーションです。これにより、私がこれを理解するために費やした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で美しく機能します。それが役に立てば幸い。

0