珈琲 さんが書きました:
もっと整理して、初期値がZ軸+方向にモデルが向いていて、Y+方向が上だと過程すると
MGetRotVec2( VGet(0,0,1), VGet(0,1,0) ) ;//Z軸からY軸に向くマトリクス
で手に入るマトリクスをMGetRotZ(θ)にMMult()すれば
方向ベクトルVを軸にθ回転した垂直な真上ベクトルを得られるマトリクスが出来て、
そのマトリクスと方向ベクトルをVTransform()して出来たベクトルが、飛行機で言うならコックピット真上だと思うんですけど
これを軸にしてヨーが出来たりそこから更に外積で作ったベクトルを軸にピッチをしたり出来そう、・・・・ですかね?
また、ヨーやピッチをした場合、MGetRotAxis(vector,float)で出来たマトリクスと方向ベクトルVをVTransform()すれば、
反映された方向ベクトルVとそれを軸に回転しているθで運用できると思うのですがどうでしょうか?
というのを思い切ってやってみましたが、画面真っ暗になって飛行機の計測系UIがうんともすんとも言わなくなりました(`;ω;´)
主な変更場所はカメラと戦闘機のクラスなんですが、
カメラのマトリクスはプレイヤーの飛行機に依存しているので、恐らく主原因は戦闘機の回転アルゴリズムだと予想してます。
コード:
//方向ベクトル(Direction)と角度(Angle)から
//真上方向と真横方向のベクトルを作る
MATRIX ZtoY = MGetRotVec2(VGet(0,0,1), VGet(0,1,0));
MATRIX Theta = MGetRotAxis(VGet(0,0,1) , Angle);
VECTOR AxisY = VTransform(Direction , MMult(ZtoY,Theta));
VECTOR AxisX = VCross(Direction,AxisY);
/////////
回転処理とそれぞれの軸で回転した分を方向ベクトル(Direction)に反映
AxisY=ReactionQuaternion(AxisX,AxisY,TURN_ROT_PITCH*TurnRatePitch);
Direction=ReactionQuaternion(AxisX,Direction,TURN_ROT_PITCH*TurnRatePitch);
AxisX=ReactionQuaternion(Direction,AxisX,TURN_ROT_ROLL*TurnRateRoll);
AxisY=ReactionQuaternion(Direction,AxisY,TURN_ROT_ROLL*TurnRateRoll);
AxisX=ReactionQuaternion(AxisY,AxisX,TURN_ROT_YAW*TurnRateYaw);
Direction=ReactionQuaternion(AxisY,Direction,TURN_ROT_YAW*TurnRateYaw);
11,12行目で使用しているReactionQuaternion関数
戻り値は、Axisを軸にしたEffectVectorのRotation分の回転後のベクトル
コード:
VECTOR ReactionQuaternion(VECTOR Axis,VECTOR EffectVector,float Rotation){
//Q = (q; V) 指定軸の回転
float rotaq=cos(Rotation/2);
VECTOR vectq=VGet(Axis.x*sin(Rotation/2),Axis.y*sin(Rotation/2),Axis.z*sin(Rotation/2));
//R = (r; W) Qのベクトルを反転したもの。
float rotar=cos(Rotation/2);
VECTOR vectr=VGet(-Axis.x*sin(Rotation/2),-Axis.y*sin(Rotation/2),-Axis.z*sin(Rotation/2));
//RとPの掛け算をしてCクォータニオンを合成
float rotac=-VDot(vectr,EffectVector);
VECTOR vectc=VAdd(VGet(EffectVector.x*rotar,EffectVector.y*rotar,EffectVector.z*rotar),VCross(vectr,EffectVector));
//CクォータニオンとQクォータニオンを合成してベクトルを返す
return VAdd(VAdd(VGet(vectq.x*rotac,vectq.y*rotac,vectq.z*rotac),VGet(rotaq*vectc.x,rotaq*vectc.y,rotaq*vectc.z)),VCross(vectc,vectq));
}