PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Rotationsmatrix zur Überfühung von Quell- in Zielvektor?


Nasenbaer
2011-03-15, 12:39:07
Hi,
ich habe folgendes Problem:

Ich habe Vektoren p und p' gegeben und suche nun die zugehörige Roationsmatrix R, die folgender Gleichung genügt:

p' = R * p

Leider weiß ich absolut nicht mehr wie man dabei vorgeht und eine Google hat mich auch nicht viel gebracht.

Hintergrund
Der Hintergrund ist, dass ich Samples über der Hemisphäre von einzelnen Vertices erzeuge. Bei der Erzeugung der Samples gehe ich davon aus, dass die Normale der Vertices gleich dem Up-Vektor (0, 1, 0) ist. Anschließend möchte ich die erzeugten Samples, dann aber so ausrichten, dass die Hemisphäre, die sie aufspannen um die Normale des Vertex orientiert sind.

Coda
2011-03-15, 16:36:06
Kreuzprodukt zwischen den Vektoren, dann hast du die Rotationsachse.

Anschließend den Winkel zwischen den Vektoren bestimmen und dann eine Rotationsmatrix um die Achse mit dem entsprechende Winkel erzeugen:
http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/

Vielleicht hilft dir auch Code (für den 3x3 Fall):
Matrix33 arbitaryRotationMatrix33(float angle, Vector3 axis)
{
Matrix33 matrix;

const float c = cos(angle);
const float s = sin(angle);

matrix(0, 0) = c + axis(0) * axis(0) * (1.0f - c);
matrix(0, 1) = axis(0) * axis(1) * (1.0f - c) - axis(2)*s;
matrix(0, 2) = axis(0) * axis(2) * (1.0f - c) + axis(1)*s;

matrix(1, 0) = axis(0) * axis(1) * (1.0f - c) + axis(2)*s;
matrix(1, 1) = c + axis(1) * axis(1) * (1.0f - c);
matrix(1, 2) = axis(1) * axis(2) * (1.0f - c) - axis(0)*s;

matrix(2, 0) = axis(0) * axis(2) * (1.0f - c) - axis(1)*s;
matrix(2, 1) = axis(1) * axis(2) * (1.0f - c) + axis(0)*s;
matrix(2, 2) = c + axis(2) * axis(2) * (1.0f - c);

return matrix;
}

Quaternionen könnten hier aber einfacher sein.

Nasenbaer
2011-03-15, 16:42:43
Thx und clevere Idee. So gesehen ist das eigentlich ziemlich einfach. Danke!

Hab zwischenzeitlich auch in "Real-Time Rendering - 3rd Ed." ne Variante mit Quaternionen gefunden - mit den Dingern hab ich aber noch nie gearbeitet. :)

Coda
2011-03-15, 16:52:36
Das ganze müsste aber auch irgendwie mit nem Basiswechsel deutlich günstiger gehen. Ich komm grad nur nicht drauf :)

Falls du den Speed braucht gibt's hier auch noch ein Paper: http://www.cs.brown.edu/~jfh/papers/Moller-EBA-1999/paper.pdf

Nasenbaer
2011-03-15, 16:59:14
Thx aber ist nich nötig. Wird eh in nem präprozess ausgeführt.

ScottManDeath
2011-03-15, 17:20:02
Aehnlich dem was Coda beschrieben hat, kann man das Problem darin sehen, zu einer gegebenen Richtung die entprechenden 2 anderen Achsen einer orthonormalen Basis zu finden. Dies ist insofern tricky, da es fuer eine Richtung unendlich viele Rotationsmatrizen gibt, deswegen fixiert man eine Achse z.B. als (1,0,0) mit der man durch Kreuzprodukte entsprechend die Basis berechnet. Der folgende Code waehlt anstelle von (1,0,0) einen Vektor aus, der garantiert nicht parallel zur gegebenen Richtung ist.

Mit v1 gleich der Normale sind v2 und v3 dann die Basisvektoren der Rotationsmatrix. v1 zeigt dann entlang der "Z"-Achse, v2 und v3 entlang der "X" und "Y" Achsen respektive.


template < typenameT>
void OrthonormalBasis(const Vector3<T>& v1, Vector3<T>& v2, Vector3<T>& v3)
{
using namespace std;
if( (abs(v1.x) > abs(v1.y)) && (abs(v1.x) > abs(v1.z)))
{
T inv_length = 1 / sqrt(v1.x * v1.x + v1.z * v1.z);
v2 = Vector3<T>(-v1.z * inv_length,0, v1.x * inv_length);
}
else
{
T inv_length = 1 / sqrt(v1.y * v1.y + v1.z * v1.z);
v2 = Vector3<T>(0,v1.z * inv_length,-v1.y * inv_length);
}
v3 = Cross(v1,v2);
}