シナリオは次のとおりです。
オブジェクトは次のように記述されます:
- 位置
- 規模
- 回転
最初に OpenGL からモデル ビュー (カメラ) を適用し、次に次のマトリックスを使用して移動と回転を適用します。
private Matrix4d AnglesToMatrix(Vector3d angles)
{
Vector3d left = Vector3d.UnitX;
Vector3d up = Vector3d.UnitY;
Vector3d forward = Vector3d.UnitZ;
AnglesToAxes(angles, ref left, ref up, ref forward);
return new Matrix4d(
new Vector4d(left.X, up.X, forward.X, 0),
new Vector4d(left.Y, up.Y, forward.Y, 0),
new Vector4d(left.Z, up.Z, forward.Z, 0),
new Vector4d(0, 0, 0, 1));
}
private void AnglesToAxes(Vector3d angles, ref Vector3d left, ref Vector3d up, ref Vector3d forward)
{
const double DEG2RAD = 0.0174532925;
double sx, sy, sz, cx, cy, cz, theta;
// rotation angle about X-axis (pitch)
theta = angles.X * DEG2RAD;
sx = Math.Sin(theta);
cx = Math.Cos(theta);
// rotation angle about Y-axis (yaw)
theta = angles.Y * DEG2RAD;
sy = Math.Sin(theta);
cy = Math.Cos(theta);
// rotation angle about Z-axis (roll)
theta = angles.Z * DEG2RAD;
sz = Math.Sin(theta);
cz = Math.Cos(theta);
// determine left axis
left.X = cy * cz;
left.Y = sx * sy * cz + cx * sz;
left.Z = -cx * sy * cz + sx * sz;
// determine up axis
up.X = -cy * sz;
up.Y = -sx * sy * sz + cx * cz;
up.Z = cx * sy * sz + sx * cz;
// determine forward axis
forward.X = sy;
forward.Y = -sx * cy;
forward.Z = cx * cy;
}
で、最後にスケールを適用します。グローバル軸に基づく回転を除いて、すべてが見栄えがします。
ローカル軸を使用してオブジェクトを回転するには?
質問を正確にするため。オブジェクトを Y 軸で 45 度回転すると、X 軸と Z 軸が回転し、別の回転を適用して新しい軸を使用します。
マイナスの形での罰を避けるために... 3D空間での回転に関連するすべての主題を読みましたが、解決策はありませんでした。上記のコードは、さまざまな試行を適用した結果ですが、次のような結果が得られます。
GL.Rotate(Rotation.X, Vector3d.UnitX);
GL.Rotate(Rotation.Y, Vector3d.UnitY);
GL.Rotate(Rotation.Z, Vector3d.UnitZ);
編集: 結局のところ 、私たちのデザイナーは 3D でのオブジェクトの回転について悪い期待を持っていましたが、それでも問題は存在します。使用する言語に関しては、これを C# で記述しますが、C または C++ で解決策を教えていただければ、私が対応します :D
現在使用しています (順序を構成できます):
GL.Rotate(Rotation.X, Vector3d.UnitX);
GL.Rotate(Rotation.Y, Vector3d.UnitY);
GL.Rotate(Rotation.Z, Vector3d.UnitZ);
しかし、これはワールド軸を中心にオブジェクトを回転させます。XYZ 軸の回転があると仮定して、ローカル オブジェクト軸を次のように使用します。
GL.Rotate(Rotation.X, Vector3d.UnitX);
GL.Rotate(Rotation.Y, newYaxis);
GL.Rotate(Rotation.Z, newZaxis);
または、YXZ 軸の回転があると仮定します
GL.Rotate(Rotation.Y, Vector3d.UnitY);
GL.Rotate(Rotation.X, newXaxis);
GL.Rotate(Rotation.Z, newZaxis);
最も効率的な方法は、回転行列を事前に計算することですが、回転後に新しい軸を決定する方法はまだ疑問に思っています。(三角法の本を再訪する必要があるようです)。誰かが回転行列を非常に高速に計算するソリューションを持っていれば、私は感謝しています。今のところ、各パスで三角法の計算を使用してみます。