\\ Home : Articoli : Stampa
Geometry Blending
Di RobyDx (del 10/04/2007 @ 10:24:33, in DirectX9, linkato 1857 volte)

L’animazione dei modelli in 3D è sempre stata una delle caratteristiche più difficili da gestire. Infatti una delle tecniche più usate nei giochi 3D della precedente generazione (esempio Quake 3) per deformare un oggetto era il tweening. Un vero spreco di risorse visto che la quasi totalità del processo veniva fatto a livello software ossia utilizzando quasi esclusivamente il processore. Nel tweening infatti noi estraiamo i vertici dal modello per modificarli nel codice del programma. Inoltre il processo veniva utilizzato anche per la deformazione di semplici oggetti come ad esempio la superficie dell’acqua che segue regole di deformazione ben più semplici di quello di un modello complesso. Il geometry blending è un sistema di deformazione hardware abbastanza semplice da usare che non solo permette di piegare un modello in modo molto leggero per la macchina ma addirittura conferisce un grande morbidezza alle curve. La deformazione di un oggetto viene eseguita attraverso l’uso di più world matrix (le matrici usate per muovere un oggetto) e di valori chiamati weight (pesi). Il vertice deve essere infatti modificato per avere oltre a posizione, normali e texture dei single chiamati weight che determinano quanto il vertice viene influenzato dalle varie matrici. Se un oggetto viene deformato da 3 matrici ogni vertice avrà 2 pesi, con 4 matrici 3 pesi e così via. I pesi sono single che variano da 0 a 1: maggiore è il valore e maggiore sarà l’influenza del vertice da quella matrice.
Le formule matematiche per il calcolo del blending sono le seguenti.

 
1 peso: V1W1 + V2(1-W1)
2 pesi:  V1W1 + V2W2 + V3(1-W1-W2)
3 pesi:  V1W1 + V2W2 + V3W3 + V4(1-W1-W2-W3)

Dove i V sono le posizioni in cui si troverebbe il vertice con la matrice n mentre W è il peso n-esimo. Come vedete fa una interpolazione tra le posizioni dei vertici trasformati con tutte le matrici. L’ultimo vertice non ha però peso che viene generato in modo automatico tramite i precedenti in modo che la somma dei pesi sia uguale a 1. La somma sarà il risultato. Capite quindi che con molte matrici può essere difficile settare bene i pesi. Osservate questa immagine.

Geometry Blending

La figura ha un solo peso quindi 2 matrici. Nella prima il settaggio è secco: 1 o 0. Il risultato sarà un angolo netto. Nel secondo invece i vertici hanno nella zona centrale un valore che varia da 0 a 1 e la curva è più morbida (a patto ovviamente che i poligoni della figura siano in numero sufficiente nella zona flessa). DirectX supporta fino a 3 pesi, io ne userò 1.

Codice

Carichiamo una mesh come di consueto. Creiamo un tipo di vertice per il geometry blending.

Private Structure BlendedVertex
    Public P As Vector3
    Public weight As Single
    Public n As Vector3
    Public tu, tv As Single
    Const FVF_Blended = VertexFormats.PositionBlend1 Or VertexFormats.Normal Or VertexFormats.Texture1
End Structure

Come vedete tra la posizione e la normale ho inserito 1 single che è appunto il peso. Se si volessero usare più pesi aggiungete altri weight (weight1, weight2..) e modificate il numero di PositionBlend nel formato. Ora convertite la mesh a questo formato tramite un clone.

oggetto.mesh = oggetto.mesh.Clone(MeshFlags.Managed, BlendedVertex.FVF_Blended, device)

Ora l’oggetto è convertito ed ha i 1 peso. Usate l’accesso diretto alla memoria per estrarre i vertici ed assegnare al peso un valore compreso tra 0 e 1.

Function getBVertexArray(ByVal m As Mesh) As System.Array
    'restituisce un array di vertici
    Dim vertexBuffer As VertexBuffer = m.VertexBuffer
    getBVertexArray = vertexBuffer.Lock(0, GetType(BlendedVertex), 0, m.NumberVertices)
    vertexBuffer.Unlock()
End Function
Private Sub setBVertexArray(ByVal m As Mesh, ByVal v As BlendedVertex())
    'imposta la mesh con un array di D3DVertex
    Dim vertici As BlendedVertex()
    Dim vertexBuffer As VertexBuffer = m.VertexBuffer
    vertici = vertexBuffer.Lock(0, GetType(BlendedVertex), 0, m.NumberVertices)
    Dim i As Integer
    For i = 0 To vertici.Length - 1
        vertici(i) = v(i)
    Next
    vertexBuffer.Unlock()
End Sub

Queste sono le funzioni per estrarre ed inserire i vertici modificate per il blending. Modifate il peso secondo una vostra logica (ad esempio io ho messo i pesi dei vertici a destra uguali a 1, quelli di sinistra uguali a zero e la zona centrale che varia da 1 a 0). Attivate l’effetto

device.RenderState.VertexBlend = VertexBlend.OneWeights

Il numero da usare è pari al numero dei pesi. Two e Three sono per 2 o 3 pesi.
Ora impostate le matrici

device.Transform.World = matrice1
device.Transform.World1 = matrice2

Ora renderizzate l’oggetto come di consueto e questo sarà piegato secondo le matrici. Modificate dinamicamente le matrice per creare gli effetti che volete.
L’uso del geometry blending è comodo per la deformazione di oggetti semplici (superfici d’acqua ad esempio) o che seguono delle regole semplici (esempio gli alberi che si piegano con il vento). Può con molta astuzia diventare un sistema di animazione efficiente e spettacolare: lo skinning mesh che verrà trattato nel prossimo tutorial.

Esempio VB.Net

Esempio C#