これらの変換行列の結果である同次座標変換行列を分解しようとしています (書き込み順序で適用されます): 不均一 スケール -> 回転 -> 移動 から移動座標を抽出するのに問題はありません結果の 4x4 変換行列 (最後の列の最初の 3 つの値) が得られましたが、回転行列とスケーリング行列を抽出する方法が見つかりませんでした。
Web で次の行列分解アルゴリズムを見つけました。
- 行列の最初の 3 つの基底ベクトル (列または行) の大きさとしてスケーリング係数を計算します。
- 最初の 3 つの基底ベクトルをこれらの値で割ります (したがって、それらを正規化します)。
- 行列の左上の 3x3 部分が回転を表すようになりました (これをそのまま使用することも、クォータニオン形式に変換することもできます)。
- 平行移動は、行列の 4 番目の基底ベクトルです (同次座標では、関心のある最初の 3 つの要素になります)。
これが私のJava実装です
public void decompose(Vec3 translation, Vec4 rotationAxisAndAngle, Vec3 scale) {
translation = this.getTranslation();
Vec3 c0 = new Vec3(values[ 0], values[ 1], values[ 2]);
Vec3 c1 = new Vec3(values[ 4], values[ 5], values[ 6]);
Vec3 c2 = new Vec3(values[ 8], values[ 9], values[10]);
scale.x = Vec3.len(c0.x, c0.y, c0.z);
scale.y = Vec3.len(c1.x, c1.y, c1.z);
scale.z = Vec3.len(c2.x, c2.y, c2.z);
Matrix4 mat = new Matrix4();
mat.values[ 0] = c0.x / scale.x; mat.values[ 4] = c1.x / scale.y; mat.values[ 8] = c2.x / scale.z; mat.values[12] = 0;
mat.values[ 1] = c0.y / scale.x; mat.values[ 5] = c1.y / scale.y; mat.values[ 9] = c2.y / scale.z; mat.values[13] = 0;
mat.values[ 2] = c0.z / scale.x; mat.values[ 6] = c1.z / scale.y; mat.values[10] = c2.z / scale.z; mat.values[14] = 0;
mat.values[ 3] = 0; mat.values[ 7] = 0; mat.values[11] = 0; mat.values[15] = 1;
rotationAxisAndAngle = mat.toAxisAngle();
System.out.println("<Transform translation=\"" + translation.x + " " + translation.y + " " + translation.z + "\">");
System.out.println("<Transform rotation=\"" + rotationAxisAndAngle.x + " " + rotationAxisAndAngle.y + " " + rotationAxisAndAngle.z + " " + rotationAxisAndAngle.w + "\">");
System.out.println("<Transform scale=\"" + scale.x + " " + scale.y + " " + scale.z + "\">");
}
しかし、それが取得する軸角度と倍率は正しくありません。
どうしたの?