Werbetafel in Richtung Kamera drehen

7

Ich versuche, ein Partikelsystem in OpenGL zu erstellen, und als solches muss ich Werbetafeln verwenden.

Ich brauche diese Werbetafeln, um jederzeit vor der Kamera zu stehen.

In den Tutorials, denen ich gefolgt bin, wurde die Werbetafel nur um eine Achse gedreht, z. B. Werbetafeln, die als Gras oder Pflanzen verwendet werden. Ich benötige jedoch eine Methode zum Drehen des Quad, um immer zur Kamera zu schauen, auch wenn ich auf sie herabschaue.


Die Originalszene: Vor der Drehung

Gewünschte Szene: Gewünschte Szene

Bei der Suche nach einer Antwort habe ich nur die Technik gefunden, die mat3-Komponente der Ansichts- / Modellmatrix der Kamera wieder in eine Identitätsmatrix umzuwandeln. Dies ist nicht ganz das, was ich brauche, da sich die Position des Punktes im Raum dann nie ändert.

Falsche Szene: Falsche Drehung


Wie kann ich eine neue Rotationsmatrix berechnen, die ein Quad immer erfolgreich in Richtung Kamera dreht, oder eine vorhandene Matrix ändern?

Im Geometrie-Shader habe ich Zugriff auf die Position der Kamera, die Perspektivmatrix und die Ansichts- / Modellmatrix.

Ich habe keinen Shader-Code eingefügt, weil er wirklich trivial ist. Ich erstelle Eckpunkte, die einen Versatz der Position des gewünschten Punkts basierend auf der gewünschten Größe darstellen. Wenn das Quad also 50 x 50 sein sollte, ist der Scheitelpunkt die Position, die auf X und Y um 25 versetzt ist, multipliziert mit der Matrix Perspective x View der Kamera.


Lösung:

mat4 VP = pMatrix * vMatrix;       
vec3 CameraRight = vec3(vMatrix[0][0], vMatrix[1][0], vMatrix[2][0]);
vec3 CameraUp = vec3(vMatrix[0][1], vMatrix[1][1], vMatrix[2][1]);

vec3 Pos = gl_in[0].gl_Position.xyz;  // The desired point for the billboard

vec4 v1 = VP * vec4(Pos + CameraRight * 0.5 * Size + CameraUp * -0.5 * Size, 1.0);  
vec4 v2 = VP * vec4(Pos + CameraRight * 0.5 * Size + CameraUp * 0.5 * Size, 1.0);     
vec4 v3 = VP * vec4(Pos + CameraRight * -0.5 * Size + CameraUp * -0.5 * Size, 1.0); 
vec4 v4 = VP * vec4(Pos + CameraRight * -0.5 * Size + CameraUp * 0.5 * Size, 1.0);  

Fertig

Yattabyte
quelle
Außerdem habe ich ähnliche Fragen zu anderen Engines wie Unity gefunden. Ich verwende jedoch meine eigene Engine und dies muss in GLSL erfolgen, sodass ich nicht über alle ausgefallenen Lookat-Funktionen verfüge, die die Sache vereinfachen würden .
Yattabyte
Ich erinnere mich, dass Minecrafts Player-Namensschilder mit reinen OpenGL-Aufrufen gerendert werden und diese immer zur Kamera zeigen (und im perspektivischen Raum platziert sind). Ich bin jedoch nicht in meiner Modding-Umgebung, daher kann ich mich erst ... eesh, wahrscheinlich am Samstag, damit beschäftigen. Das heißt, Sie können es möglicherweise selbst anhand dieser Beschreibung finden.
Draco18s vertraut SE

Antworten:

1

Ich lasse dies hier nur für eine allgemeinere Lösung des Problems. Was Sie tun möchten, ist, die "globale" Übersetzung / Drehung / Skalierung des Objekts / der Werbetafel beizubehalten, damit es sich in der richtigen Weltposition befindet, aber lokal zurückzudrehen, so dass es der Kamera zugewandt ist. Das heißt, Sie möchten die übergeordnete Modellansichtsmatrix, wenden jedoch die Umkehrung ihres Rotationsteils auf das Objekt / die Werbetafel an. Folgendes habe ich getan (Pseudocode für Qt-Matheklassen, aber Sie werden auf die Idee kommen):

// Calculate object->world tranform with inverse parent->world rotation
QMatrix4x4 objectTransform;
objectTransform.setToIdentity();
objectTransform.translate(objectPosition);
// Get length of first row as scale factor. See: /programming/27655885/get-position-rotation-and-scale-from-matrix-in-opengl
float scaleFactor = parentModelView.row(0).toVector3D().length();
// get upper left 3x3 sub-matrix and unscale
QMatrix3x3 parentRotation = parentModelView.toGenericMatrix<3,3>();
parentRotation *= 1.0f / scaleFactor;
// convert to quaternion and invert
QQuaternion inverseParentRotation = QQuaternion::fromRotationMatrix(parentRotation).inverted();
// set as rotation
objectTransform.rotate(inverseParentRotation);
objectTransform.scale(objectScaleFactor); 

// Now for drawing calculate the combined object->world transform:
QMatrix4x4 objectModelView = parentModelView * objectTransform;

Vorsichtsmaßnahme: Funktioniert nur für eine gleichmäßige Skalierung und ohne Schertransformationen, wie hier angegeben .

Bim
quelle