2013-04-08 10 views
6

Sto creando un motore grafico 3D e uno dei requisiti è quello delle corde che si comportano come nel motore sorgente di Valve.Rendering della corda in stile Source Engine

Quindi nel motore sorgente, una sezione di corda è un quad che ruota lungo il suo asse di direzione per affrontare la telecamera, quindi se la sezione di corda è nella direzione + Z, ruoterà lungo l'asse Z in modo che sia la faccia è rivolta verso la posizione centrale della fotocamera.

Al momento, ho definito le sezioni di corde, quindi posso avere una bella corda curva, ma ora sto provando a costruire la matrice che la ruoterà lungo il suo vettore di direzione.

Ho già una matrice per il rendering sprite cartellone basati su questa tecnica billboarding: Constructing a Billboard Matrix E al momento ho cercato di riorganizzare in modo che Destra, Su, avanti vettore corrisponde vettore direzione del segmento di corda.

La mia corda è composta da più sezioni, ogni sezione è un rettangolo composto da due triangoli, come ho detto sopra, posso ottenere la posizione e le sezioni perfette, è la rotazione per affrontare la telecamera che mi sta causando molto di problemi.

Questo è in OpenGL ES2 e scritto in C.

ho studiato codice di rendering fascio di Doom 3 nel Model_beam.cpp, il metodo utilizzato che c'è da calcolare l'offset basata su normali invece di usare le matrici, in modo da ho creato una tecnica simile nel mio codice C e questo tipo di opere, almeno, funziona tanto quanto ne ho bisogno in questo momento.

Quindi, per coloro che stanno anche cercando di capire questo, usa il prodotto incrociato del punto medio della corda contro la posizione della telecamera, normalizzalo e poi moltiplicalo per quanto vuoi che la corda sia , quindi quando si costruiscono i vertici, sfalsare ciascun vertice in direzione + o - del vettore risultante.

Ulteriore aiuto sarebbe grande anche se questo non è perfetto!

Grazie

+2

Per ruotare qualcosa di un certo angolo di un asse specifico, utilizzare un [quaternione] (https://en.wikipedia.org/wiki/Quaternion). –

+0

Attualmente sto usando i quaternioni, ma non sono sicuro di come ruotarlo verso la posizione della telecamera –

+4

Lascia che il rettangolo/sezione corrente sia "N", e il vettore lungo l'asse del rettangolo sia "V". Quindi, 'VxN' ti darà il terzo vettore' U', con 'U' e' N' formando un "piano orizzontale" relativo alla tua sezione di corda. Ora calcola 'EyePos - C' (dove' C' è il centroide del rettangolo) e normalizza per ottenere 'E', la direzione della telecamera. Proietta 'E' sull'aereo' UN' per ottenere 'E''. Infine, la rotazione desiderata (attorno all'asse 'V') è' arccos (N. E ') '. –

risposta

1

Partenza this related stackoverflow post on billboards in OpenGL Si cita un tutorial lighthouse3d che è una bella buona lettura. Ecco i punti salienti della tecnica:

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

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. – Brian

+0

Buon punto Brian. Ho aggiunto il punto cruciale della tecnica .. – henderso