Javascript 如何在Three.JS中控制网格的偏航和俯仰?

Javascript 如何在Three.JS中控制网格的偏航和俯仰?,javascript,3d,three.js,Javascript,3d,Three.js,我有一个网格,我想通过用户输入来控制它的偏航和俯仰。我天真地尝试绕z轴和y轴旋转网格,这似乎可以控制偏航,但上下不稳定 function checkKeys(keys) { if (keys.left) spaceship.rotation.z += .05; if (keys.right) spaceship.rotation.z -= .05; if (keys.up) spaceship.rotation.y += .05; if (keys.down) s

我有一个网格,我想通过用户输入来控制它的偏航和俯仰。我天真地尝试绕z轴和y轴旋转网格,这似乎可以控制偏航,但上下不稳定

function checkKeys(keys) {
    if (keys.left) spaceship.rotation.z += .05;
    if (keys.right) spaceship.rotation.z -= .05;
    if (keys.up) spaceship.rotation.y += .05;
    if (keys.down) spaceship.rotation.y -= .05;
}
如何使左/右控制飞机的偏航和上/下控制俯仰

更新:我简化了wagerfield提到的FlyControls.js,因此它遵守我的游戏板,只处理旋转。以下是我最终得到的结果():

THREE.FlyControls=函数(对象){
this.object=对象;
//原料药
此值为0.movementSpeed=1.0;
该速度为0.005;
//禁用默认目标对象行为
this.object.useQuaternion=true;
//内部构件
this.tmpQuaternion=新的三个四元数();
this.moveState={up:0,down:0,left:0,right:0,forward:0,back:0,pitchUp:0,pitchDown:0,yawLeft:0,yawRight:0,rollLeft:0,rollRight:0};
this.moveVector=新的三个.Vector3(0,0,0);
this.rotationVector=新的三个向量3(0,0,0);
this.handleEvent=函数(事件){
if(此[event.type]=“函数”的类型){
此[事件类型](事件);
}
};
this.update=函数(增量){
this.moveState.yawLeft=-gamepad.axes[2];
this.moveState.pitchDown=gamepad.axes[3];
this.moveState.rollLeft=(Math.abs(gamepad.axes[0])<0.15?0:gamepad.axes[0])||
gamepad.按钮[15]/2;
this.moveState.rollRight=(Math.abs(gamepad.axes[1])<0.15?0:gamepad.axes[1])||
gamepad.按钮[14]/2;
this.updateRotationVector();
var moveMult=delta*this.movementSpeed;
var rotMult=delta*this.rollSpeed;
this.object.translateX(this.movevevector.x*moveMult);
this.object.translateY(this.movevevector.y*moveMult);
this.object.translateZ(this.movevevector.z*moveMult);
this.tmpQuaternion.set(this.rotationVector.x*rotMult,this.rotationVector.y*rotMult,this.rotationVector.z*rotMult,1).normalize();
this.object.quaternion.multiply(this.tmpQuaternion);
//为了方便起见,公开旋转向量
this.object.rotation.setEulerFromQuaternion(this.object.quaternion,this.object.eulerOrder);
};
this.updateRotationVector=函数(){
this.rotationVector.x=(-this.moveState.pitchDown+this.moveState.pitchUp);
this.rotationVector.y=(-this.moveState.yawRight+this.moveState.yawLeft);
this.rotationVector.z=(-this.moveState.rollRight+this.moveState.rollLeft);
};
函数绑定(范围,fn){
返回函数(){
fn.适用(范围、参数);
};
};
this.updateRotationVector();
};

在这种情况下,偏航轴是向上轴或y轴,因此您需要旋转宇宙飞船几何体,使其水平:

geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) ); 
然后,您需要更改飞船的
eulerOrder
,使偏航(Y)为第一,俯仰(X)为第二:

spaceship.rotation.order = "YXZ"; // three.js r.65
然后,您需要相应地调整钥匙代码


three.js r.65

在本例中,偏航轴是向上轴或y轴,因此您需要旋转您的宇宙飞船几何体,以使其水平:

geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) ); 
然后,您需要更改飞船的
eulerOrder
,使偏航(Y)为第一,俯仰(X)为第二:

spaceship.rotation.order = "YXZ"; // three.js r.65
然后,您需要相应地调整钥匙代码


three.js r.65

您遇到的问题是由于three.js中旋转计算和应用于对象的方式(通常是3D引擎)。对于每个旋转轴(x、y和z),将旋转矩阵乘以对象的矩阵(其中包含其位置、比例和旋转)

因为矩阵是非交换的;意思是A*B!=乘法的顺序很重要。默认情况下,这个“欧拉顺序”是X,然后是Y,然后是Z。这就是为什么你的Z旋转似乎是有意义的,但你的Y旋转不是你直觉上期望的那样

不要害怕,有解决办法!我假设您希望您的飞机以与本演示中相机相同的方式旋转,其中旋转的每个附加更改都是相对于当前旋转应用的。在3D程序(如3D Studio Max)中,这称为局部旋转:

如果查看此演示的源代码,您将看到相机的控件创建在第76行上:

控件=新的三个。第一个人控件(摄像头)

还有FlyControl,哪个更适合您

不管是哪种方式,我都会先玩一下这些现成的控件,然后在构造函数中使用平面对象,而不是摄影机


希望能有所帮助。

您遇到的问题是由于three.js中旋转计算和应用于对象的方式(通常是3D引擎)。对于每个旋转轴(x、y和z),将旋转矩阵乘以对象的矩阵(其中包含其位置、比例和旋转)

因为矩阵是非交换的;意思是A*B!=乘法的顺序很重要。默认情况下,这个“欧拉顺序”是X,然后是Y,然后是Z。这就是为什么你的Z旋转似乎是有意义的,但你的Y旋转不是你直觉上期望的那样

不要害怕,有解决办法!我假设您希望您的飞机以与本演示中相机相同的方式旋转,其中旋转的每个附加更改都是相对于当前旋转应用的。在3D程序(如3D Studio Max)中,这称为局部旋转:

如果查看此演示的源代码,您将看到相机的控件创建在第76行上:

控件=新的三个。第一个人控件(摄像头)

还有FlyControl,哪个更适合您