Traslazione
La trasformazione più semplice che possiamo apportare ad un oggetto è la traslazione lungo uno dei tre assi. Traslare una primitiva geometrica nello spazio significa muovere ogni suo punto di un'identica misura lungo i tre assi fino a raggiungere la nuova posizione (nell'immagine sotto vediamo una traslazione su due assi):
La classe Matrix
espone un apposito metodo per traslare i nostri oggetti nello spazio 3D:
public static Matrix CreateTranslation (
float xPosition,
float yPosition,
float zPosition
)
I tre parametri indicano la misura dello spostamento, rispettivamente lungo gli assi X, Y e Z. Per traslare la nostra texture, è dunque sufficiente impostare la matrice World come segue (ipotizziamo di volere spostare la texture lungo l'asse X di 10 unità e di altrettante unità lungo l'asse Y):
bfx.World = Matrix.CreateTranslation(10, 10, 0);
Scala
Possiamo anche disegnare i nostri oggetti in modo che risultino in scala. Scelto un punto C (punto fisso) di riferimento, scalare una primitiva geometrica significa riposizionare rispetto a C tutti i suoi punti in accordo ai fattori di scala lungo ciascuno dei tre assi (è infatti possibile scalare diversamente sui vari assi).
Per disegnare un oggetto in una scala che varia da -1 a 1 sulla base del tempo trascorso, è sufficiente utilizzare l'apposito metodo Matrix.CreateScale, passando come parametro la grandezza di scala (in questo caso variabile sulla base del tempo):
bfx.World = Matrix.CreateScale((float)Math.Sin((float)gameTime.TotalGameTime.TotalMinutes * 10.0f));
Rotazione
L'altra trasformazione importante è rappresentata dalla rotazione dell'oggetto intorno a uno (o più) dei suoi assi. Fissato un punto C (detto pivot) di riferimento e un verso di rotazione (orario o antiorario), ruotare una primitiva geometrica attorno a C significa muovere tutti i suoi punti nel verso assegnato in modo che si conservi, per ognuno di essi, la distanza da C.
Per fortuna, anche in questo caso XNA ci dà una mano, mettendoci a disposizione un metodo semplice per ruotare l'oggetto dell'angolo desiderato. In questo esempio, ruotiamo il nostro oggetto intorno all'asse Y sulla base del tempo trascorso dall'inizio del gioco:
bfx.World = Matrix.CreateRotationY(
(float)gameTime.TotalGameTime.TotalSeconds);
Dal momento che CreateRotation accetta come parametro il valore dell'angolo di rotazione espresso in radianti, il nostro modello completerà il giro ogniqualvolta il valore passato come parametro sarà multiplo di un angolo giro, ossia 2×π≅6.28
.
Rotazione e traslazione
Il vantaggio che deriva dall'esprimere le trasformazioni per mezzo di matrici è presto detto: ipotizziamo, ad esempio, di volere ruotare e traslare il nostro modello. Per farlo sarà sufficiente moltiplicare la matrice di rotazione per quella di traslazione, vale a dire:
bfx.World =
Matrix.CreateRotationY((float)gameTime.TotalGameTime.TotalSeconds) *
Matrix.CreateTranslation(Vector3.Right);
É fondamentale sottolineare però che, nel caso delle matrici, non vale la regola commutativa, per cui l'ordine con il quale applichiamo le nostre trasformazioni, lungi dall'essere irrilevante, condiziona in modo profondo il prodotto finale. Trasformazioni come scalature e rotazioni, infatti, vengono compiute relativamente al punto di origine iniziale.
Ad esempio, se invertissimo la rotazione con la traslazione, otterremmo un risultato completamente diverso, dal momento che il modello verrebbe prima traslato e poi ruotato, ma il centro di rotazione continuerebbe ad essere collocato nel punto originariamente occupato dal modello, cioè prima della traslazione:
bfx.World =
Matrix.CreateTranslation(Vector3.Right) *
Matrix.CreateRotationY((float)gameTime.TotalGameTime.TotalSeconds);