8

Sto iniziando su Molehill e sto avendo un sacco di problemi nell'afferrare Matrix3D. Il mio primo problema è come gestire un Matrix3D che descrive l'orientamento di un singolo modello.Come si combinano le rotazioni X, Y e Z nello spazio locale di un modello (non globale)?

Uso Matrix3D.appendRotation() per eseguire questa operazione. Ma a seconda dell'ordine in cui appendo ottengo un risultato diverso (ovviamente, dato che sto ruotando uno alla volta nello spazio globale). So che questo è un problema comune, mi sono imbattuto in esso con la modellazione software 3d. Ma questa volta, devo sistemarlo programmaticamente. Questo è dove ho bisogno di aiuto.

In primo luogo, nel caso in cui non v'è alcuna confusione, qui è il problema in immagini:

Fase 1: I rendere un modello.

Start position

2a Fase: I ruotarla sul X-asse. Sembra corretto!

X-axis rotation

Fase 2b: Ho ruotarla sul Z-asse. Sembra corretto!

Z-axis rotation

Quindi ... se ho ruotare sull'asse X e Z del modello che voglio questo:

desired XZ rotation

Ma, sadface, ottengo questo:

enter image description here

Posso vedi il problema. Sto aggiungendo le rotazioni una alla volta nello spazio globale. Ho bisogno di ruotare nello spazio locale dell'oggetto. Non ho idea di come fare questo o cosa dovrei anche cercare (terminologia, ecc.). Il codice è semplice (e sbagliato):

modelLocalMatrix.identity(); 
modelLocalMatrix.appendRotation(modelZRot, Vector3D.Z_AXIS); 
modelLocalMatrix.appendRotation(modelXRot, Vector3D.X_AXIS); 
//eventually y-axis rotation as well... 
renderMatrix.append(modelLocalMatrix); 

Sto indovinando che invece di utilizzare le costanti assi Vector3D, voglio usare un po 'di vettore normalizzato e alcuni ... uh, cosa ... al posto di modelZRot , modelXRot e infine modelYRot. Qualcuno può dirmi qual è la soluzione migliore per applicare il tipo di rotazione desiderato sopra?

AGGIORNAMENTO: Dopo aver trascorso la giornata a colpire i "libri" (noti anche come KhanAcademy su YouTube) e iniziando da questa presentazione qui: The Mathematics of the 3d Rotation Matrix mi sono imbattuto in una sorta di metodo "look at" che è molto vicino alla mia soluzione desiderata. Purtroppo, ho capito solo il 50%. Spero ancora che qualcuno possa far luce su questo argomento!

var angleOfRotation:Number = Math.PI/2; //90 degrees... 
var axisOfRotation:Vector3D = new Vector3D(0, 1, 0); //some point to look at... 
//normalize the vector! 
axisOfRotation.normalize(); 
var x:Number = axisOfRotation.x; 
var y:Number = axisOfRotation.y; 
var z:Number = axisOfRotation.z; 
var c:Number = Math.cos(angleOfRotation); 
var s:Number = Math.sin(angleOfRotation); 
var t:Number = 1 - c; 

//Graphics Gems (Glassner, Academic Press, 1990). 
modelLocalMatrix = new Matrix3D(new <Number>[ 
    t * (x * x) + c, t * x * y - s * z, t * x * z + s * y, 0, 
    t * x * y + s * z, t * (y * y) + c, t * y * z - s * x, 0, 
    t * x * z - s * y, t * y * z + s * x, t * (z * z) + c, 0, 
    0,   0,   0,   1 
]); 

Il fatto è che questo sembra piuttosto goffo. Soprattutto perché l'angolo di rotazione di un Vector3D dovrebbe essere il quarto valore (w). Ancora più importante, Matrix3D sembra già avere un metodo lookAt(). Non ce l'ho ancora ... per favore qualcuno mi salvi da ore di prove ed errori!

risposta

2

Ok, ho praticamente capito come farlo. È MOLTO più semplice di quanto lo stavo facendo. Ha anche aiutato a rivedere l'API Matrix3D (ha alcune funzioni fantastiche!).

In primo luogo, il codice sorgente che ho usato per ruotare il mio modello sulle sue assi locali:

var raw:Vector.<Number> = modelLocalMatrix.rawData; 
var right:Vector3D = new Vector3D(raw[0], raw[1], raw[2]); 
var up:Vector3D = new Vector3D(raw[4], raw[5], raw[6]); 
var out:Vector3D = new Vector3D(raw[8], raw[9], raw[10]); 

modelLocalMatrix.appendRotation(modelXRot, right); 
modelLocalMatrix.appendRotation(modelYRot, up); 
modelLocalMatrix.appendRotation(modelZRot, out); 

La "up", "giusto", e "out" vettori normalizzati sono discussi nel link nella mia originale inviare. Sono fondamentalmente gli angoli di inclinazione, di imbardata e di rotazione del modello. Basti dire che quando si inizializza l'oggetto, questi vettori sono identici a Vector3D.X_AXIS, Y_AXIS e Z_AXIS. Li ho estratti usando la proprietà Matrix3D.rawData anche se potrebbe esserci un modo migliore.

Ora è possibile ruotare lungo uno di questi assi come si desidera, ma nel momento in cui si esegue l'operazione, l'orientamento degli altri due cambi immediatamente. Questo ha senso. Il tuo modello è stato ruotato e il suo "giusto", "alto" e "avanti" ora sono diversi! Quindi, se inizi a ruotare sull'asse "giusto" del modello (ricorda, questo inizia come il Global X_AXIS) e poi vuoi far rotolare il tuo modello sul suo asse "fuori", devi ottenerlo dal modello locale matrice. Ovviamente, non è più lo stesso di Z_AXIS globale. Nota che non chiamo Matrix3D.identity(). Se l'avessi fatto, allora gli assi del mio modello sarebbero stati ripristinati! Questo è ok per il mio ciclo di rendering, anche se ho dovuto cambiare il mio codice (e il mio modo di pensare) un po 'da quando avevo ripristinato tutte le mie matrici prima di applicare le trasformazioni e le rotazioni. Si noti che modelXRot, modelYRot e modelZRot memorizzano un valore di rotazione in gradi.

Spero davvero che questo aiuti qualcuno. Non riesco a credere che un problema così comune con una soluzione così semplice non sia stato trovato da nessuna parte. Ad ogni modo, sembra proprio che stia facendo quello che voglio.

Problemi correlati