3.8. Implementació

3.8.1. Tipus de matrius en DirectX


Un cop explicats els conceptes generals de les transformacions a nivell teòric, cal saber que en DirectX totes les transformacions s’apliquen a una determinada matriu assignada. En DirectX11 hi ha tres tipus de matrius, la matriu de món (D3DTS_WORLD), la matriu de vista (D3DTS_VIEW) i la matriu de projecció (D3DTS_PROJECTION).

En qualsevol aplicació o paquet gràfic, per tant, també DirectX, tota la geometria es veu afectada per la CTM (Current Transformation Matrix) o matriu de transformació actual. Aquesta guarda la informació sobre totes les matrius que s’han anat acumulant. Qualsevol vèrtex que passi per el pipeline serà multiplicat per aquesta matriu i conseqüentment transformat.

A DirectX la CTM es composa de dues matrius: La "Model-View matrix" o matriu de transformació y la "Projection matrix" o matriu de projecció. Les dues es concatenen i del seu producte es crea la CTM per el pipeline que controla DirectX. De la segona ja profunditzarem més endavant ja que és la que s’encarrega de la conversió 3D (món virtual) a 2D (pantalla), és a dir, de la projecció.

3.8.2. Creació de matrius per aplicar transformacions en DirectX


Com hem mencionat anteriorment, existeixen varis tipus de transformacions. Traslladar, escalar i rotar són les més usades. Cada operació de transformació té assignada un codi en DirectX:
Si el que es vol és traslladar, s’usarà la següent funció:

D3DXMatrixTranslation(D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z);

On *pOut és sobre la matriu on s’aplica la transformació i les coordenades (x, y i z) són les dades amb les quals podrem aplicar la transformació al nostre gust.
Si el que volem és escalar, crearem la matriu d’escalat:

D3DXMatrixScaling(D3DXMATRIX *pOut, FLOAT sx, FLOAT sy, FLOAT sz);

On *pOut novament és la matriu on s’aplica la transformació i les dades sc, sy i sz ens permeten aplicar la transformació al nostre gust sobre els vèrtexs de la geometria.

Si ens interessa rotar, hi ha vàries opcions (Nota: Els angles de les rotacions s’escriuen en radiants):

1)      Rotar a través de l’eix X:

D3DXMatrixRotationX(D3DXMATRIX *pOut, FLOAT Angle);

2)      Rotar a través de l’eix Y:

D3DXMatrixRotationY(D3DXMATRIX *pOut, FLOAT Angle);

3)      Rotar a través de l’eix Z:

D3DXMatrixRotationZ(D3DXMATRIX *pOut, FLOAT Angle);

4)      Rotar al voltant  d’un vector determinat (on *pV és el vector):

D3DXMatrixRotationAxis( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pV, FLOAT Angle);

Per obtenir l’efecte de vàries transformacions a la vegada hem de multiplicar les matrius entre si, procés conegut com a concatenació de matrius explicat anteriorment. Per exemple, si desitgem rotar i després traslladar, s’efectuarà la següent operació:

M = R * T, on R és la matriu de rotació i T la matriu de translació.

Una vegada obtinguda i establerta la matriu del model i de la vista, les transformacions s’observaran en pantalla en l’ordre d’esquerra a dreta, és a dir, en l’ordre que s’efectuen les multiplicacions. Això és de vital importància, perquè per exemple, en OpenGL les transformacions passen en l’ordre contrari en que s’invoquen les multiplicacions: les transformacions passen de dreta a esquerra.
En DirectX també es poden crear matrius a la nostre manera.

Les matrius en Direct3D es defineixen mitjançant D3DMATRIX ,però per conveniència usarem la definició de Direct3DX. A continuació mostrem com es defineix una matriu en DirectX:


S’observa que es podrà accedir a un element mitjançant _XY, on X és la fila i Y és la columna, o també mitjançant [X] [Y].

Un bon exemple de com es creen matrius en DirectX és el següent, on el primer que es fa és declarar les variables que usarem: totes les matrius de DirectX i un booleà que més tard s’usarà per a comprovar si el pintat (també anomenat renderitzat) de l’escena s’ha produït correctament, a continuació es netegen els buffers  per a començar a pintar l’escena creada; després cridem una funció la qual ens genera la viewMatrix (la qual necessitarem més tard a l’hora de pintar) segons la posició de la càmera en aquell moment; com que per a pintar es necessita la matriu de món, de vista i de projecció cridem a unes funcions les quals ens donen aquestes matrius respecte la càmera i els objectes creats al nostre món; finalment creem les matrius de transformació: la primera es tracta d’una matriu d’escalat que augmenta el volum de la figura per dos en la direcció de les x, la segona és una matriu que defineix una translació de 1 en la direcció de les x i de les y i finalment creem la nostra pròpia matriu de translació la qual ens aplica el mateix efecte que l’anterior.

A continuació tenim l'exemple:


3.8.3. Creació de la modelview en DirectX


Per a explicar la creació de la matriu de món (modelview) en DirectX ens basarem en l’exemple anterior, en ell es declaren les matrius:

D3DXMATRIX worldMatrix, viewMatrix, projectionMatrix, mattrans, matsca,mattrans2;

Dins d’aquesta declaració ens fixem que ja tenim les tres matrius que mouen la CTM de DirectX: la worldMatrix, la viewMatrix i la projectionMatrix. Un cop declarades començaran a contenir dades segons l’escena que haurem creat, això succeeix amb aquestes tres funcions (no incloem la projectionMatrix ja que no té a veure amb la creació de la modelview, més endavant s’explicarà l’ús d’aquesta matriu):

m_Camera->GetViewMatrix(viewMatrix);
m_D3D->GetWorldMatrix(worldMatrix);

Més tard s’apliquen les transformacions a la worldMatrix (a la viewMatrix no se li aplica cap transformació):

D3DXMatrixScaling(&matsca, 2.0f, 1.0f, 1.0f); D3DXMatrixTranslation(&mattrans, 1.0f, 1.0f, 0.0f);

En cas de voler concatenar les matrius i modificar la modelview el que es farà és multiplicar les matrius tenint en compte que postmultipliquem, per exemple:

worldMatrix = mattrans*matrot;

Després un cop ja es tenen definides la worldMatrix i la viewMatrix el que es farà és posar-les dins una funció la qual crearà i aplicarà la modelview a partir de la worldMatrix i la viewMatrix, les funcions són les següents:

   //Col·loca el model vertex i els indexs del buffer al pipeline gràfic per preparar-los pel pintat
      m_Model->Render(m_D3D->GetDeviceContext());
   // Renderitza el model usant un shader de color.
      result = m_ColorShader->Render(m_D3D->GetDeviceContext(), m_Model->GetIndexCount(),    mmmmmmmmmmmmmmmmmmmworldMatrix, viewMatrix, projectionMatrix);

La primera introdueix els vèrtexs i els index buffers del model en el pipeline gràfic i així ja es prepara per a pintar, la segona funció la qual ens retorna un booleà segons si l’operació de pintar l’escena creada a sortit bé o no, el que fa és simplement pintar la nostra escena usant shader, a partir de les matrius que li introdueixes et crea la modelview i la projection matrix automàticament i les aplica a l’escena 3D creada per a poder-la pintar.


3.8.4. Aplicació de la modelview en DirectX


A continuació tenim un exemple complet de creació i aplicació de la modelview. Com a programadors hem de pensar sempre segons les tres matrius fonamentals: la worldMatrix, la viewMatrix i la projectionMatrix, després gràcies a l’ús de funcions la creació i aplicació de les matrius que afecten el pipeline de DirectX es fa automàticament.

A continuació tenim l'exemple:

Per a descarregar-se un exemple fes click en aquest enllaç.
Anterior capítol

No hay comentarios:

Publicar un comentario