0

間違っていたら訂正しますが...

任意のソース平面の法線と、目的の回転を適用した後の平面の法線が与えられた場合:

Vector3F sourceNormal = (x, y, z).normalize()
Vector3F desiredNormal = (0, 0, 1).normalize()

1) 2 つの法線の外積から「回転軸」を見つけることができます。

Vector3F rotationAxis = Vector3F.cross(sourceNormal, desiredNormal).normalize()

2) 2 つの法線の内積の逆余弦から「回転角」を求めることができます。

// Thanks nico - it was there in my project source, but it was omitted here.
float theta = Math.acos(Vector3F.dot(sourceNormal, desiredNormal))

3) ソース平面を目的の平面に向けるために、一連の点に回転を適用できます。

float[] rotationMatrix = new float[16];

// X component
rotationMatrix[5] = rotationMatrix[10] = (float)Math.cos(theta);
rotationMatrix[9] = (float)Math.sin(theta);
rotationMatrix[6] = -rotationMatrix[9];

// Y component
rotationMatrix[0] = rotationMatrix[10] = (float)Math.cos(theta);
rotationMatrix[2] = (float)Math.sin(theta);
rotationMatrix[8] = -rotationMatrix[2];

// Z component
rotationMatrix[0] = rotationMatrix[5] = (float)Math.cos(theta);
rotationMatrix[1] = (float)Math.sin(theta);
rotationMatrix[4] = -rotationMatrix[1];

for(Point3F point : polygon)
{
    float x = pt.getX();
    float y = pt.getY();
    float z = pt.getZ();
    float[] xs = new float[3];
    float[] ys = new float[3];
    float[] zs = new float[3];
    for(int j = 0; j < 3; ++j)
    {
    xs[j] = rotationMatrix[j] * x;
    ys[j] = rotationMatrix[j + 4] * y;
    zs[j] = rotationMatrix[j + 8] * z;
    }
    x = 0; y = 0; z = 0;
    for(int j = 0; j < 3; ++j)
    {
    x += xs[j];
    y += ys[j];
    z += zs[j];
    }
    pt.set(x, y, z);
}

私の出力は正しくありません。

ポイント:

(-56.00, 72.01, 48.02)
(-48.00, 72.01, 48.02)
(-48.00, 86.01, 24.02)
(-56.00, 86.01, 24.02)

アウトポイント:

(-124.960010, -88.105451, 24.185812)
(-107.108590, -88.105451, 24.185812)
(-107.108590, -105.237051, 12.0929052)
(-124.960010, -105.237051, 12.0929052)

推測する必要がある場合は、回転をポイントに間違って適用していると言えます...おそらく、この記事 ( http://en.wikipedia.org/wiki/Rotation_matrix )にある回転行列を解釈しました。間違って?

ご意見ありがとうございます。

...これが回転行列を設定する正しい方法であると仮定すると、出力はまだ正しくありません。

Vector3F axis = Vector3F.cross(sourceNormal, desiredNormal).normalize();
float angle = (float) Math.acos(p.normal.dot(new Vector3F(0, 0, 1)));
float s = (float)Math.sin(angle);
float c = (float)Math.cos(angle);
float x = axis.getX(), y = axis.getY(), z = axis.getZ();
float[] matrix = new float[16];
matrix[0] = x * x * (1 - c) + c;
matrix[1] = x * y * (1 - c) - (z * s);
matrix[2] = x * z * (1 - c) + (y * s);

matrix[4] = y * x * (1 - c) + (z * s);
matrix[5] = y * y * (1 - c) + c;
matrix[6] = y * z * (1 - c) - (x * s);

matrix[8] = x * z * (1 - c) - (y * s);
matrix[9] = y * z * (1 - c) + (x * s);
matrix[10] = z * z * (1 - c) + c;


float nx = x * matrix[0] + y * matrix[1] + z * matrix[2];
float ny = x * matrix[4] + y * matrix[5] + z * matrix[6];
float nz = x * matrix[8] + y * matrix[9] + z * matrix[10];

In: (-56.00, 56.01, -16.02)
In: (-48.00, 56.01, -16.02)
In: (-48.00, 72.01, -8.02)
In: (-56.00, 72.01, -8.02)
Out: (-51.270340, 46.887921, -25.5108342)
Out: (-43.9460070, 46.887921, -25.5108342)
Out: (-43.9460070, 62.798761, -21.5554182)
Out: (-51.270340, 62.798761, -21.5554182)
4

2 に答える 2

1

回転行列が間違っています。

回転は、リンク先のウィキペディアの記事のセクション 10 の式に従って組み合わせる必要があります (「軸と角度からの回転行列」)。

このマトリックスの簡略化されたバージョンは、glRotate関数のマニュアル ページにもあります。

注: ローテーションを何度も繰り返す場合を除き、再度実行acos(dotp)するだけで実行する必要はcosありませんsin。としてドット積を直接cos(theta)使用し、関係sin(theta)^2 = 1 - cos(theta)^2を使用して解決しsin(theta)ます。

于 2013-10-06T18:25:44.413 に答える
0

結局のところ、多くの問題がありました。Alnitak はそれらの大部分を解決し、私は最後の問題を見つけました。

要するに、以下が間違っていました。

1) マトリックスの作成

2) 行列乗算

3) 浮動小数点の切り捨て

ハッキーな解決策かもしれませんが、私の目的には問題ありません。作業スニップは以下のとおりです。

Vector3F axis = new Vector3F(p.normal);
// Seems to work when adding precision...but NOT with (0, 0, 1)
Vector3F target = new Vector3F(0.000000000000000001f, 0.000000000000001f, 1.0f);
axis.cross(target);
axis.normalize();
float angle = (float) Math.acos(p.normal.dot(new Vector3F(0, 0, 1)));
float s = (float) Math.sin(angle);
float c = (float) Math.cos(angle);
float x = axis.getX(), y = axis.getY(), z = axis.getZ();
float[] matrix = new float[16];
matrix[0] = x * x * (1 - c) + c;
matrix[1] = x * y * (1 - c) - (z * s);
matrix[2] = x * z * (1 - c) + (y * s);
matrix[4] = y * x * (1 - c) + (z * s);
matrix[5] = y * y * (1 - c) + c;
matrix[6] = y * z * (1 - c) - (x * s);
matrix[8] = x * z * (1 - c) - (y * s);
matrix[9] = y * z * (1 - c) + (x * s);
matrix[10] = z * z * (1 - c) + c;

float nx = x * matrix[0] + y * matrix[1] + z * matrix[2];
float ny = x * matrix[4] + y * matrix[5] + z * matrix[6];
float nz = x * matrix[8] + y * matrix[9] + z * matrix[10];

// triangulate (now 2D) polygon
// Rotate the points back
angle = -angle;
s = (float) Math.sin(angle);
c = (float) Math.cos(angle);
matrix[0] = x * x * (1 - c) + c;
matrix[1] = x * y * (1 - c) - (z * s);
matrix[2] = x * z * (1 - c) + (y * s);
matrix[4] = y * x * (1 - c) + (z * s);
matrix[5] = y * y * (1 - c) + c;
matrix[6] = y * z * (1 - c) - (x * s);
matrix[8] = x * z * (1 - c) - (y * s);
matrix[9] = y * z * (1 - c) + (x * s);
matrix[10] = z * z * (1 - c) + c;
nx = x * matrix[0] + y * matrix[1] + z * matrix[2];
ny = x * matrix[4] + y * matrix[5] + z * matrix[6];
nz = x * matrix[8] + y * matrix[9] + z * matrix[10];
// All's well that ends well
于 2013-10-06T23:25:45.553 に答える