2013-04-08 9 views
6

Ich erstelle eine 3D-Grafik-Engine und eine der Anforderungen ist Seile, die sich wie in Valve Source-Engine verhalten.Quelle Motor gestylt Seil Rendering

In der Quellmaschine ist ein Teil des Seils ein Vierer, der sich entlang seiner Richtung dreht, um der Kamera zugewandt zu sein. Wenn der Seilabschnitt also in + Z-Richtung ist, dreht er sich entlang der Z-Achse Das Gesicht zeigt auf die mittlere Position der Kamera.

Im Moment habe ich die Abschnitte von Seilen definiert, so dass ich ein schönes gebogenes Seil haben kann, aber jetzt versuche ich, die Matrix zu konstruieren, die sie entlang ihres Richtungsvektors dreht.

Ich habe bereits eine Matrix für die auf der Grundlage dieser Technik Billboard Billboarding Sprites Rendering: Constructing a Billboard Matrix Und im Moment habe ich versucht, es zu umrüsten, so dass rechts, oben, nach vorne Vektor der Seil Segment Richtungsvektor entsprechen.

Mein Seil besteht aus mehreren Abschnitten, jeder Abschnitt ist ein Rechteck aus zwei Dreiecken, wie ich oben sagte, kann ich die Position und Abschnitte perfekt, es ist das Drehen der Kamera, die mich viel verursacht von Problemen.

Diese in OpenGL ES2 ist und in C.

geschrieben I Doom 3 des Strahls Rendering-Code in Model_beam.cpp studiert haben, verwendet das Verfahren dort der Offset auf Normalen zu berechnen ist eher als Matrizen, so dass ich habe eine ähnliche Technik in meinem C-Code erstellt und es funktioniert zumindest so, wie ich es gerade brauche.

Also für diejenigen, die auch versuchen, diese herauszufinden, verwenden Sie das Kreuzprodukt des Mittelpunkts des Seils gegen die Kameraposition, normalisieren Sie das und multiplizieren Sie es dann, wie breit Sie das Seil sein möchten Wenn Sie die Scheitelpunkte konstruieren, versetzen Sie jeden Scheitelpunkt entweder in + oder - Richtung des resultierenden Vektors.

Weitere Hilfe wäre toll, aber das ist nicht perfekt!

Danke

+2

Um etwas um einen bestimmten Winkel um eine bestimmte Achse zu drehen, verwenden Sie einen [quaternion] (https://en.wikipedia.org/wiki/Quaternion). –

+0

Ich verwende derzeit Quaternionen, aber ich bin mir nicht sicher, wie man es in Richtung der Kameraposition dreht –

+4

Lassen Sie die normale Rechteck/Abschnitt ist normal "N", und der Vektor entlang der Achse des Rechtecks ​​sein "V". Dann gibt "VxN" den dritten Vektor "U", wobei "U" und "N" eine "horizontale Ebene" relativ zu Ihrem Seilabschnitt bilden. Berechnen Sie nun 'EyePos - C' (wobei' C' der Schwerpunkt Ihres Rechtecks ​​ist) und normalisieren Sie es, um 'E', die Kamerarichtung, zu erhalten. Projizieren Sie 'E' auf die' UN'-Ebene, um 'E'zu erhalten. Schließlich ist die gewünschte Rotation (um die Achse "V") "Arccos (N. E ')". –

Antwort

1

Check out this related stackoverflow post on billboards in OpenGL Es zitiert eine lighthouse3d Tutorial, das eine ziemlich gute Lese ist. Hier sind die wichtigsten Punkte der Technik:

void billboardCylindricalBegin(
       float camX, float camY, float camZ, 
       float objPosX, float objPosY, float objPosZ) { 

     float lookAt[3],objToCamProj[3],upAux[3]; 
     float modelview[16],angleCosine; 

     glPushMatrix(); 

    // objToCamProj is the vector in world coordinates from the 
    // local origin to the camera projected in the XZ plane 
     objToCamProj[0] = camX - objPosX ; 
     objToCamProj[1] = 0; 
     objToCamProj[2] = camZ - objPosZ ; 

    // This is the original lookAt vector for the object 
    // in world coordinates 
     lookAt[0] = 0; 
     lookAt[1] = 0; 
     lookAt[2] = 1; 


    // normalize both vectors to get the cosine directly afterwards 
     mathsNormalize(objToCamProj); 

    // easy fix to determine wether the angle is negative or positive 
    // for positive angles upAux will be a vector pointing in the 
    // positive y direction, otherwise upAux will point downwards 
    // effectively reversing the rotation. 

     mathsCrossProduct(upAux,lookAt,objToCamProj); 

    // compute the angle 
     angleCosine = mathsInnerProduct(lookAt,objToCamProj); 

    // perform the rotation. The if statement is used for stability reasons 
    // if the lookAt and objToCamProj vectors are too close together then 
    // |angleCosine| could be bigger than 1 due to lack of precision 
     if ((angleCosine < 0.99990) && (angleCosine > -0.9999)) 
      glRotatef(acos(angleCosine)*180/3.14,upAux[0], upAux[1], upAux[2]); 
    } 
+0

Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz zur Verfügung zu stellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. – Brian

+0

Guter Punkt Brian. Ich habe den Kern der Technik hinzugefügt. – henderso