解決済み
エンジンで 3D ポータル システムを作成しています (ポータル ゲームなど)。各ポータルには、クォータニオンに保存された独自の向きがあります。ポータルの 1 つで仮想シーンをレンダリングするには、2 つの四元数の差を計算する必要があり、その結果を使用して仮想シーンを回転させます。
左の壁に最初のポータルを作成し、右の壁に 2 つ目のポータルを作成する場合、一方から他方への回転は 1 つの軸でのみ行われますが、たとえば、最初のポータルが床に作成され、2 つ目のポータルが床に作成される場合などです。右の壁では、一方から他方への回転が 2 軸になる可能性があります。これが問題です。回転がうまくいかないからです。
たとえば、X
軸と軸の向きが1つのクォータニオンに一緒に格納されており、 * (または* )Z
を手動で乗算するために個別に必要があるため、問題が存在すると思いますが、1つのクォータニオンのみでそれを行う方法(差分クォータニオン)? または、シーンを正しく回転させる他の方法はありますか?X
Z
Z
X
編集:
この写真には 2 つのポータル P1 と P2 があり、矢印はそれらがどのように回転しているかを示しています。P1 を見ていると、何が P2 を見ているかがわかります。この写真の仮想シーンのようにメイン シーンを回転させるために必要な回転を見つけるには、次のようにします。
- クォータニオン P2 からクォータニオン P1 への差の取得
- 結果を Y 軸で 180 度回転 (ポータルの UP)
- 結果を使用して仮想シーンを回転させる
上記の方法は、違いが 1 つの軸だけで発生する場合にのみ機能します。1 つのポータルが床または天井にある場合、差分クォータニオンが複数の軸で構築されているため、これは機能しません。示唆されているように、P1 の四元数を P2 の四元数に乗算しようとしましたが、逆に、これは機能しません。
編集2:
P2 と P1 の違いを見つけるために、次のことを行っています。
Quat q1 = P1->getOrientation();
Quat q2 = P2->getOrientation();
Quat diff = Quat::diff(q2, q1); // q2 * diff = q1 //
Quat::diff 関数は次のとおりです。
GE::Quat GE::Quat::diff(const Quat &a, const Quat &b)
{
Quat inv = a;
inv.inverse();
return inv * b;
}
逆:
void GE::Quat::inverse()
{
Quat q = (*this);
q.conjugate();
(*this) = q / Quat::dot((*this), (*this));
}
共役:
void GE::Quat::conjugate()
{
Quat q;
q.x = -this->x;
q.y = -this->y;
q.z = -this->z;
q.w = this->w;
(*this) = q;
}
内積:
float GE::Quat::dot(const Quat &q1, const Quat &q2)
{
return q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
}
オペレーター*:
const GE::Quat GE::Quat::operator* ( const Quat &q) const
{
Quat qu;
qu.x = this->w*q.x + this->x*q.w + this->y*q.z - this->z*q.y;
qu.y = this->w*q.y + this->y*q.w + this->z*q.x - this->x*q.z;
qu.z = this->w*q.z + this->z*q.w + this->x*q.y - this->y*q.x;
qu.w = this->w*q.w - this->x*q.x - this->y*q.y - this->z*q.z;
return qu;
}
オペレーター/:
const GE::Quat GE::Quat::operator/ (float s) const
{
Quat q = (*this);
return Quat(q.x / s, q.y / s, q.z / s, q.w / s);
}
GLMライブラリでテストしたので、これらすべてが機能します