2010-07-08 11 views
9

Quando ho un QUAD in una determinata posizione, come posso ruotarlo in modo tale che i suoi punti normali verso un punto dato? Immagina che i blocchi colorati siano solo quadrati rettangolari, quindi questa immagine mostra un po 'quello che intendo. I quad sono tutti orientati in modo tale che puntano verso il centro della sfera.C++/openGL: rotazione di un QUAD verso un punto utilizzando quaternioni

alt text http://emrahgunduz.com/wp-content/uploads/2009/01/material_id_gui-600x364.jpg

Forse questa seconda immagine mostra un po 'più di quello che sto cercando di fare: alt text http://img689.imageshack.us/img689/3130/screenshot20100708at555.png

sto usando OpenGL/C++ (e la lib Eigen). E ho questo codice per disegnare un semplice quad:

#include "ofMain.h" 
#include "Quad.h" 
Quad::Quad(Vector3f oPosition):position(oPosition) { 
} 

void Quad::update() { 
} 

void Quad::draw() { 
    float size = 1.3; 
    glColor3f(1.0f, 0.0f, 0.6f); 
    glPushMatrix(); 
     glTranslatef(position.x(), position.y(), position.z()); 
     glScalef(size, size,size); 
     glBegin(GL_QUADS); 
      glVertex3f(0,0,0); 
      glVertex3f(1,0,0); 
      glVertex3f(1,1,0); 
      glVertex3f(0,1,0); 
     glEnd(); 
    glPopMatrix(); 
} 

Aggiornamento 17-07 Caro lettore,

appena ricevuto un po 'più avanti con la rotazione dei quad. Sto posizionamento di un paio di quad in modo casuale e poi li ho ruotare verso un look_at Vector3f utilizzando questo codice usando le descrizioni dalle risposte di seguito:

void Quad::draw() { 
    float size = 0.5; 
    glColor3f(1.0f, 0.0f, 0.6f); 
    glPushMatrix(); 
     Vector3f center = look_at - position; 
     Vector3f center_norm = center.normalized(); 
     float r_angle = acos(center_norm.dot(normal)); 
     Vector3f axis = normal.normalized().cross(center_norm); 

     glPointSize(8); 
     glLineWidth(4.0f); 

     // draw the center point 
     glColor3f(1.0f, 0.0f, 0.0f); 
     glBegin(GL_POINTS); 
      glVertex3fv(look_at.data()); 
     glEnd(); 

     // draw the quad 
     glColor4f(0.0f, 0.0f, 0.0f, 0.85f); 
     glTranslatef(position.x(), position.y(), position.z()); 
     glRotatef(r_angle * RAD_TO_DEG, axis.x(), axis.y(), axis.z()); 
     glScalef(size, size,size); 
     glBegin(GL_QUADS); 
      glVertex3f(-0.5,-0.5,0); 
      glVertex3f(0.5,-0.5,0); 
      glVertex3f(0.5,0.5,0); 
      glVertex3f(-0.5,0.5,0); 
     glEnd(); 

    glPopMatrix(); 
} 

Il risultato è simile al seguente: alt text http://img688.imageshack.us/img688/711/3drotatedquads.png

Come si posso vedere che sono quasi arrivato, anche se la rotazione dei quad è ancora un po '"strana". Vedo l'immagine qui sotto con i quad colorati che vedi chiaramente la differenza di rotazione. Come posso ruotare il quad in modo da ottenere lo stesso risultato della sfera colorata sottostante?

+0

+1: Perché adoro le immagini 3D :) – ereOn

+0

Questi collegamenti di immagine sono tutti interrotti. –

risposta

1

asse di rotazione = normalizzare (CrossProduct (currentNormal, desiredNormal)) Angolo

rotazione = acos (dotproduct (normalizzare (currentNormal), normalizzare (desiredNormal)).

È possibile costruire sia matrice di rotazione o quaternione dall'asse e l'angolo. formula esatta può essere trovato in qualsiasi risorsa su quaternioni.

potrebbe essere necessario capovolgere angolo o assi a seconda se si ruota attorno alla sua normale base o attorno al suo punta.

Anche la risorsa THIS sembra avere informazioni sufficienti su quaternioni, rotazioni e spazio 3d in generale.

+0

Ciao SigTerm, ma come faccio a risolverlo quando non conosco il mio currentNormal? Ho solo ricevuto il codice che ho incollato (la classe 'Quad'). – pollux

+1

Per un quad abcd normale si può trovare usando cross product = normalize (cross (c-a, d-b)) o normalize (Crossproduct (b-a, c-a)). È possibile utilizzare qualsiasi due vettori non paralleli da quad per eseguire la perpendicolare. Nel tuo esempio normale è o (0, 0, 1) o (0, 0, -1). (dipende dal fatto che i quad usano lo stesso ordine di avvolgimento, unilaterale o bilaterale, ecc.). – SigTerm

+0

SigTerm, cosa intendi con rotazione attorno alla sua 'base' o 'punta'? Questo potrebbe causare il risultato che ho ottenuto ora (vedi i quad neri sopra) – pollux

0

Se "in una certa posizione" significa che si conosce la corrente normale, che qui è la cosa:

  1. Dot prodotto di un vecchio e nuovo normale è un coseno di un angolo tra di loro.
  2. Il loro prodotto trasversale è un asse attorno al quale è necessario eseguire la rotazione desiderata
  3. La costruzione del quaternione di rotazione dall'asse e dall'angolazione dati è ben documentata e di base.
  4. La rotazione del quad stesso è complicata e dipende da come esattamente ruotare.
Problemi correlati