Wie dreht man einen Vektor von einem gegebenen Richtung
Ich bin momentan dabei, einige zufällige Vektoren/Anweisungen in einer Schleife als eine Kuppel-Form wie diese:
void generateDome(glm::vec3 direction)
{
for(int i=0;i<1000;++i)
{
float xDir = randomByRange(-1.0f, 1.0f);
float yDir = randomByRange(0.0f, 1.0f);
float zDir = randomByRange(-1.0f, 1.0f);
auto vec = glm::vec3(xDir, yDir, zDir);
vec = glm::normalize(vec);
...
//some transformation with direction-vector
}
...
}
Dies schafft Vektoren als eine Kuppel-Form in +y
Richtung (0,1,0)
:
Ich möchte jetzt drehen Sie den vec
-Vektor von einer bestimmten Richtung-Vektor wie (1,0,0)
.
Dies sollte drehen Sie die "dome" zu der x-Richtung wie dieses:
Wie kann ich das erreichen? (vorzugsweise mit glm)
InformationsquelleAutor Bastl | 2014-01-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einer Drehung ist in der Regel definiert über irgendeine Art von Verschiebung (Achse-Winkel, quaternion, euler-Winkel, etc.) aus einer Ausgangsposition. Was du suchst wäre genauer beschrieben werden (meiner Meinung nach) als eine re-Orientierung. Zum Glück ist dies nicht allzu schwer zu tun. Was Sie brauchen, ist eine änderung-der-basis-matrix.
Ersten, können Sie nur definieren, was wir im code arbeiten:
Zur Berechnung der matrix, müssen Sie erstellen unit-Vektoren für die neuen Achsen. Aus dem obigen Beispiel wird deutlich, dass Sie wollen, dass der Vektor bereitgestellt, um die neue Y-Achse:
Nun, die Berechnung der X-und Z-Achse werden ein bisschen komplizierter. Wir wissen, dass Sie orthogonal zu einander und zu der Y-Achse, die oben berechnet. Die logischste Art und Weise zu konstruieren, die Z-Achse ist zu vermuten, dass die rotation in der Ebene definiert, die von der alten Y-Achse, die neue Y-Achse. Durch die Verwendung der cross-Produkt können wir berechnen diese Ebene normalen Vektor und verwenden, die für die Z-Achse:
Technisch ist die Normalisierung nicht notwendig ist, da hier sowohl input-Vektoren bereits normiert, aber aus Gründen der übersichtlichkeit habe ich es gelassen. Beachten Sie auch, dass es ein Sonderfall ist, wenn der input Vektor ist colinear mit der Y-Achse, in dem Fall das Kreuzprodukt oben nicht definiert ist. Die einfachste Möglichkeit dieses Problem zu beheben ist zu behandeln, als einen besonderen Fall. Anstelle von dem, was wir bisher haben, wir würden verwenden:
Für die X-Achse, können wir über unsere neue Y-Achse mit dem neuen Z-Achse. Dies ergibt einen Vektor, der senkrecht zu den beiden anderen Achsen:
Wieder, die Normalisierung ist in diesem Fall nicht wirklich notwendig, aber wenn
y
oderz
waren die nicht schon einheitsvektoren, es wäre.Schließlich, kombinieren wir die neue Achse-Vektoren in eine basis-Wechsel-matrix:
Multiplizieren eines Punkt-Vektors (
vec3 vec
) von dies ergibt einen neuen Punkt in der gleichen position, aber bezogen auf die neue basis-Vektoren (Achsen):Tun, diesen letzten Schritt für jede Ihrer zufällig generierten Punkte und du bist fertig! Keine Notwendigkeit zu berechnen, die Winkel der rotation oder ähnliches.
Als eine Randnotiz, Ihre Methode der Generierung von Zufallszahlen einheitsvektoren werden voreingenommen gegenüber Richtungen Weg von den Achsen. Dies ist, weil die Wahrscheinlichkeit, eine bestimmte Richtung, die gewählt wird, ist proportional zu dem Abstand zu dem am weitesten Punkt möglich in eine bestimmte Richtung. Für die Achsen, das ist
1.0
. Für Richtungen wie zB.(1, 1, 1)
ist dieser Abstandsqrt(3)
. Dies kann behoben werden, indem alle Vektoren liegen außerhalb der Einheit Sphäre:Dies würde sicherstellen, dass alle Richtungen haben die gleiche Wahrscheinlichkeit, an den Kosten, wenn Sie extrem unglücklich, die Punkte abgeholt, liegen außerhalb der Einheit Sphäre über und über wieder, und es dauert eine lange Zeit zu erzeugen, das im inneren. Wenn das ein problem ist, könnte es geändert werden, begrenzen der Iterationen:
while (++i < 4 && ...)
oder durch die Erhöhung des radius, an dem ein Punkt wird akzeptiert jeder iteration. Wenn es >=sqrt(3)
alle möglichen Punkte würde als gültig angesehen werden, so dass die Schleife enden würde. Diese beiden Methoden würden eine leichte Vorspannung, Weg von den Achsen, aber in fast jeder realen situation, es wäre nicht nachweisbar.Setzen alle obigen code zusammen, kombiniert mit Ihren code ein, erhalten wir:
if (input.x == 0 && input.z == 0) {...}
Was sind die x -, y -, z-Werte gibt es? Meinst du Eingang.x,input.y-Eingang.z? Und so berechnen Sie die x -, y -, z-Achse in diesem speziellen Fall?Sorry, meine Variablennamen wahrscheinlich hätte ein wenig mehr beschreibend.
input.x
hat nichts zu tun mitvec3 x
wird später festgelegt. GLM bietet Zugriff auf die Komponenten einervec3
mit einer Vielzahl von Methoden.input.x
,input.r
, undinput[0]
beziehen sich alle auf die erste Komponente des Vektors,input.y
,input.g
, undinput[1]
beziehen sich auf das zweite, usw..Die
if (input.x == 0 ...)
Sie haben erwähnt, führt der erste code-block nur, wenn die X-und Z-Koordinaten derinput
sind beide gleich null ist, d.h. der Vektor muss in exakt die gleiche Richtung (oder Gegenrichtung) als die Y-Achse.Sorry, ich meine die Werte, die innerhalb der Wenn:
input = vec3(-x, -y, z);
Nicht dieinput.x
"notation" 🙂 Wenn y poiting "-1": Derinput = vec3(-x, -y, z);
code wird ausgeführt. Was sind x,y,z gibt es? Und wie berechne ich die x -, y -, z-Achse in diesem Fall?Oops mir ist gerade aufgefallen, dass ich hatte
input = vec3(-x, -y, z);
stattinput = vec3(-input.x, -input.y, input.z);
Das war wahrscheinlich der Grund dafür, dass etwas war verwirrend, nicht wahr?InformationsquelleAutor bcrist
Müssen Sie zum erstellen einer rotationsmatrix. Daher benötigen Sie eine identity-Matrix. Erstellen Sie es wie folgt mit
Nun Ihr drehen kann, die vectorspacec mit
Dreht die vectorspace durch 45.0 Grad um die z-Achse (wie in deinem screenshot). Jetzt ist Ihr fast fertig. Drehen Sie Ihre
vec
schreiben SieHinweis: Da hast du eine 4x4-matrix, die Sie benötigen, ein vec4, es zu multiplizieren mit der matrix. Generell ist es eine gute Idee, immer vec4 bei der Arbeit mit OpenGL, da Vektoren in der kleineren dimension umgewandelt werden zu homogenen vertex-Koordinaten sowieso.
EDIT: Du kannst auch versuchen, GTX-Erweiterungen (Experimentelle) indem
<glm/gtx/rotate_vector.hpp>
EDIT 2: Wenn Sie wollen, drehen Sie den dome "in Richtung" eine Richtung gegeben, die Sie können Ihre totation Achse durch die Verwendung der cross-Produkt zwischen der Richtung und Sie die "up" - Vektor, der die Kuppel. Können sagen, Sie wollen drehen Sie die Kuppel "Richtung" (1.0, 1.0, 1.0) und den "auf" - Richtung (0.0, 1.0, 0.0):
Um Ihre rotation matrix. Das Kreuzprodukt liefert einen Vektor, der orthogonal zu "bis" und "Richtung" und das ist die, die Sie wollen, zu drehen. Hoffe, das wird helfen.
In welche Richtung Vektor meinst du? zu drehen, den ganzen Bereich nur pass-pass-die rotationsmatrix, um Ihre vertex-shader mit
glUniformMatrix4fv(uniformRotMatrix, 1, GL_FALSE, glm::value_ptr(rotationMat))
. Die shader dann dreht man jeden Eckpunkt mit dieser matrix und den ganzen Bereich gedreht.Ich habe eine Funktion zu generieren, diese Kuppel-Form. Möchte ich weitergeben eine Richtung-Vektor für die Kuppel dieser Funktion. Die Kuppel sollte dann eine Stelle in dieser Richtung.
Sie können die Winkel mit
glm::angle (up, direction)
und umfassen die Erweiterung GLM_GTX_vector_angleDer Kreuzprodukt-Vektor ist die Arbeit für Richtungen wie (0,0,+-1), (+-1,0,0) aber nicht (0,-1,0).
glm::vec3 cross = glm::cross(glm::vec3(0, 1, 0), glm::vec3(0, -1, 0)); glm::mat4 rotationMat = glm::rotate(glm::mat4(1.0f), 90.0f, cross); dir = glm::vec3(rotationMat * glm::vec4(dir, 1.0f));
der entstehenden Kuppel ist nach oben nicht nach untenInformationsquelleAutor joschuck