2010-09-28 16 views
13

So che la rotazione 3D è ben documentata su SO e molti altri siti, ma nonostante la lettura di numerose spiegazioni, non ho ancora capito dove sto andando male. Il mio background è nell'arte e nel design, non nella matematica e nella programmazione, e non sono mai veramente sicuro se il mio angolo di attacco (nessun gioco di parole) sia quello giusto. Piuttosto che incollare un patchwork del mio triste codice, includo un'immagine che descrive il mio problema. Quello che mi piacerebbe davvero è una ripartizione dettagliata di come risolverlo. Lo pseudo codice è utile, ma imparerò di più se qualcuno mi indirizzerà nella giusta direzione o indicherà le insidie ​​più comuni.Rotazione 3D con asse e angolo


alt text

Red = asse X, Verde = Y, Blu = Z-Axis

Magenta vettori = origine -> qualche X, Y, Z Punto

Cubo magenta = media dei punti finali dei due vettori magenta (c'è un nome migliore per questo?)

Vettore bianco = prodotto incrociato dei due vettori magenta (esteso per displ ay, effettivo vettore è normalizzato)

ciano cubo oggetto = rotazione sicuro


Ho usato precedentemente Away3D e Papervision; in queste librerie, applicando angoli di Eulero alle proprietà rotationX, rotationY o rotationZ di un oggetto ruoterà l'oggetto localmente, come se fosse all'origine indipendentemente dalla sua posizione attuale. Con Three.js, questo non è il caso. La modifica delle proprietà rotation.x e rotation.y di un oggetto produce un effetto bizzarro in cui l'oggetto apparentemente si inclina leggermente sull'asse Z. Ancora più confuso è che ciò accade quando l'oggetto si trova all'origine. Ho pensato che forse usando le funzioni di Quaternion -> Matrix o Axis/Angle -> Matrix avrei risolto il mio problema, ma niente da fare. Sembra che ci sia un concetto centrale che non sto ottenendo.

Ad ogni modo, quello che mi piacerebbe fare è orientare il cubo al vettore prodotto vettoriale (bianco), in modo che la parte superiore del cubo si trova ad affrontare la direzione di quel vettore. Quindi vorrei ruotare il cubo lungo lo stesso asse. L'immagine che ho allegato mostra il risultato di più ore di quelle che vorrei ammettere cercando di ottenere questo risultato. Il mio codice è vagamente simile a questo:

axis = Vector3.cross(a, b) 
axis.normalize() 
angle = 45 * TO_RADIANS; 
quat = AxisAngle2Quaternion(axis, angle) 
rot = Quaternion2Matrix(quat) 
cube.matrix = rot 

Grazie in anticipo,

Casey


Edit: Avvio di una taglia

Forse sto equivoco come questo dovrebbe lavoro. Ecco un'altra immagine:

alt text

Am I errato nel ritenere che questo magenta vettore è l'asse, e le frecce arancioni indicano la rotazione attorno a questo asse in base all'angolo? Un modo o nell'altro, voglio orientare il cubo ciano sulla base di qualche vettore direzionale e spin. Che cosa sto facendo di sbagliato!?

+0

Nessuno reagisce, ma io in realtà penso, che la tua domanda è una dei migliori formulati che ho visto qui finora. Forse solo nessuno lo sa? Sarei anche curioso di vedere una risposta qui. – erikbwork

+0

Forse si stanno allontanando dall'aspetto Three.js ... Mi aspettavo che questo fosse un problema piuttosto semplice – Casey

+0

Sono stato in grado di avvicinarmi al metodo "Utils3D.pointTowards()" in Flash: http: // help. adobe.com/en_US/AS3LCR/Flash_10.0/flash/geom/Utils3D.html Ma non so come applicare la rotazione attorno all'asse e non riesco a trovare alcuna funzione OSS comparabile – Casey

risposta

4

Il tuo approccio sembra corretto ma non mostri quali sono i vettori a, b e l'angolo costante è, suppongo, solo per il test. L'ho fatto prima così ho scavato il mio codice e questo è la matematica che ho trovato ...

dato:
originalVec = versore rivolta verso l'alto dell'asse Y (direzione superiore del cubo/normale)
targetVec = vettoriale

Ora si desidera l'asse e l'angolo che ruoterà originalVec per l'allineamento con targetVec. L'asse di rotazione più diretto è perpendicolare a entrambi i vettori di input, quindi prendi il loro prodotto incrociato. Quell'asse non è un vettore unitario, quindi normalizzalo. L'angolo di rotazione (in radianti) è l'inverso-coseno del prodotto-punto.

axis = Vector3.cross(originalVec, targetVec) 
axis.normalise 
angle = inversecos(Vector3.dot(originalVec, targetVec)) 

quat = AxisAngle2Quaternion(axis, angle) 
rot = Quaternion2Matrix(quat) 
cube.matrix = rot 

Invece di sostituire matrice del cubo Penso che si desidera comporre con la nuova trasformare ...

cube.matrix.multiplyBy(rot) 

... ma io non sono sicuro al 100% di questo. Inoltre, ho visto implementazioni in cui AxisAngle2Quaternion prende un angolo in gradi. Quando i vettori di input sono paralleli o opposti l'asse è < 0,0,0> quindi è necessario testarlo. Se il cubo ruota nel modo sbagliato, i parametri del vettore del prodotto incrociato sono nell'ordine sbagliato, non ricordo mai quale e li provo entrambi. hth.

Modifica
che ho avuto la possibilità di giocare con Three.js e fatto uno degli esempi per orientare un cubo. I commenti mostrano dove ho aggiunto delle cose e tutte le operazioni matematiche di orientamento avvengono in alignCube().
Align and Spin example
Il mouse su/giù sposta la linea di destinazione. Mousing left/right gira sulla linea.

Gli oggetti scena in Three.js sembrano ereditare tutti da Object3D che ha una proprietà autoUpdateMatrix impostata su true per impostazione predefinita. Questo deve essere impostato su false altrimenti viene chiamata la funzione updateMatrix che ricalcola la matrice dalle proprietà di posizione, scala e rotazione dell'oggetto. In alternativa è possibile assegnare una funzione updateMatrix diversa.

Sarebbe bello se Tre.js avuto qualche documentazione :)

+0

Grazie - è bello sapere che sono sulla strada giusta. Sfortunatamente non l'ho fatto funzionare. Sto sostituendo la matrice del cubo perché sto cercando di semplificare le cose per ora e farlo funzionare all'origine. Va bene, o sta solo introducendo problemi? – Casey

+0

Questo esempio è fantastico! Non ho il tempo di farlo subito, ma ho il sospetto che riceverai la taglia :) Grazie! – Casey

+0

Funziona, dolcezza. Ho frainteso il modo in cui funzionano le matrici assi/angolari. Stavo cercando di fare tutto con una singola matrice. Sto postando la funzione di allineamento qui sotto per chiunque sia interessato. – Casey

0

Perché nessuno ha una soluzione molto buona, posso almeno consigli su come avvicinarsi.

Ci sono 3 possibili problemi e si dispone di uno di loro:

  1. La matematica non è giusto, o non si capisce. (Non dovrebbe essere tanto un problema qui)
  2. L'aritmetica dei punti fluttuanti è sempre un problema per i computer (non dovrebbe essere un problema, perché è piuttosto semplice. Se il tuo framework non può fornire una soluzione, allora il framework non ha alcun valore a tutti per la programmazione 3d)
  3. non si utilizza il giusto quadro

Perché è abbastanza probabile che n ° 3 è il caso, provare a trovare una mailing list o forum di supporto o qualsiasi altra cosa per il quadro e parla con le persone lì. Dovrebbero essere in grado di spiegarti cosa hai sbagliato con il loro quadro. Quindi torna indietro e pubblica la soluzione qui!

+0

Grazie per il suggerimento - Ho contattato l'autore del framework e sto andando a vedere se un codice simile produce un risultato simile in Away3D – Casey

+0

Sto chiaramente facendo qualcosa di sbagliato - Non riesco a farlo funzionare in Flash . – Casey

+0

Controlla il link di esempio da Trochoid, funziona bene! – Casey

3

dall'esempio di trocoidale, ecco la funzione che uso per raggiungere l'allineamento ed effetti la seconda immagine:

//object, normalized direction vector, rotation in radians 
function align(target, dir, rot) { 
    //Three.js uses a Y up coordinate system, so the cube inits with this vector 
    var up = new THREE.Vector3(0, 1, 0); 

    //euler angle between direction vector and up vector 
    var angle = Math.acos(up.dot(dir)); 

    //cross product of the up vector and direction vector 
    var axis = new THREE.Vector3(); 
    axis.cross(up, dir); 
    axis.normalize(); 

    //rotation to aligns the target with the direction vector 
    var rotate = THREE.Matrix4.rotationAxisAngleMatrix(axis, angle); 

    //rotation around direction vector 
    var revolve = THREE.Matrix4.rotationAxisAngleMatrix(dir, rot); 

    //compose the rotations (order matters, can be done other ways) 
    revolve.multiplySelf(rotate); 

    //assign matrix (autoUpdateMatrix = false) 
    target.matrix = revolve; 
} 
+0

Sono felice che tu abbia finalmente trovato un modo per farlo funzionare! – erikbwork

Problemi correlati