\\ Home : Articoli : Stampa
Progressive Mesh
Di RobyDx (del 08/02/2007 @ 21:21:27, in DirectX9, linkato 1725 volte)

Quando si programma una qualunque applicazione 3D che deve essere renderizzare grafica in tempo reale è necessario prestare sempre attenzione al numero dei poligoni da utilizzare per non appesantire troppo il sistema. Risulta comunque innegabile che più poligoni ci sono e più bella è la scena. L'idea sarebbe quindi quella di visualizzare oggetti più dettagliati quando sono vicini e meno quando sono lontani. Le progressive mesh sono una forma potenziata delle normali mesh che sono in grado di variare dinamicamente il numero dei poligoni dell'oggetto che contengono. In questo modo potrete variare il numero dei poligoni dell'oggetto per variarlo ad esempio con la distanza o in base al sistema giovando notevolmente sulla leggerezza del motore grafico (se saprete adoperarlo bene). Una progressive mesh viene creata da una normale mesh e di conseguenza sarà necessario prima creare una mesh e da questa generare la progressive mesh.

Dim adiacenza As GraphicsStream = Nothing
mesh = mesh.FromFile(fileSrc, MeshFlags.Managed, device, adiacenza, materiali)

Come vedete per creare la mesh ho utilizzato un'istruzione che restituisce anche un oggetto GraphicsStream che ho chiamato adiacenza (ricordo che fileSrc è un stringa con la posizione del file X da caricare). Questo viene caricato con un array che conterrà l'adiacency buffer ovvero un array di interi che contiene informazioni sui confini dei poligoni. Senza entrare troppo in dettagli per ogni triangolo vengono indicati i 3 triangoli confinanti con questo. Ora dichiarate la progressive mesh e createla

Dim Pmesh As ProgressiveMesh
Pmesh = New ProgressiveMesh(mesh, adiacenza, Nothing, 1, MeshFlags.SimplifyFace)

Come vedete ho passato al costruttore la mesh precedentemente creata, lo stream con le adiacenze, un nothing per i pesi (non necessari).
L'opzione SimplifyFace indica che la mesh verrà semplificata in base alle facce (poligoni o triangoli). SimplifyVertex indica che la stessa cosa verrà fatta con i vertici. Il valore 1 indica il numero di elementi a cui ridurre l'oggetto alla creazione. Nel mio caso 1 significa che voglio che esso abbia 1 solo triangolo.
Attenzione, il valore non sarà mai quello che chiedete ma directX cercherà di avvicinarsi il più possibile a tale valore.
Ora la progressive mesh generata potrà effettuare in ogni momento la semplificazione impostando alcune proprietà della progressive mesh.
NumFaces o NumVertices: a secondo del tipo di semplificazione scelta date un valore a una di queste proprietà e la mesh cercherà di avvicinarsi a quel valore. Attenzione che le proprietà sono solo in scrittura non possono essere usate per conoscere il numero di facce o di vertici ma solo ad per impostarle.
MaxNumFaces o MaxNumVertices: valori massimi raggiungibili dalla mesh. Chiedere più facce o più vertici sarebbe inutile (ma non genererà errori).
MinNumFaces o MinNumVertices: valori minimi raggiungibili dalla mesh. Anche se chiedete meno vertici o facce la mesh non scenderà sotto quelli.
Dato che le progressiveMesh di solito vengono usate insieme a materiali e texture vi mostro una struttura simile a quella usata per le mesh che conterrà tutto e una funzione che la genera.

Structure oggPX
'struttura per la gestione semplice delle progressiveMesh
Public mesh As progressiveMesh
Public numX As Integer
Public tex() As Texture
Public mat() As Material
Public numF As Integer
End Structure

numF è una comoda variabile per tenere a mente il numero di facce.

Function creaProgMesh(ByVal fileSrc As String, ByVal materialiOn As Boolean, ByVal textureOn As Boolean, ByVal TexPath As String) As oggPX
'crea un oggetto oggX che gestisce le mesh e i suoi materiali.
'filesrc è il nome del file con path, materialiOn e textureOn indicano se si vuole
'caricare quel componente
'texPath è il path della cartella senza / finale dove si trovano le texture
With creaProgMesh
Dim mesh As Mesh
'crea una mesh dichiarando i materiali in un extendMaterial
Dim materiali() As ExtendedMaterial
Dim adiacenza As GraphicsStream = Nothing
         mesh = mesh.FromFile(fileSrc, MeshFlags.Managed, device, adiacenza, materiali)
'numero iniziale uguale al massimo
         .mesh = New ProgressiveMesh(mesh, adiacenza, Nothing, 1, MeshFlags.SimplifyFace)
         .mesh.NumberFaces = .mesh.MaxFaces
         .numF = .mesh.MaxFaces
'setta il numero di materiali e ridimensiona gli array
         .numX = UBound(materiali)
ReDim .tex(.numX)
ReDim .mat(.numX)
Dim i As Integer
'con un loop carica i materiali da file
For i = 0 To .numX
If textureOn Then
'solo se il nome della è texture non è vuoto eseguo il caricamento
If materiali(i).TextureFilename <> "" Then
                     .tex(i) = TextureLoader.FromFile(device, TexPath & "\" &_
                                                materiali(i).TextureFilename)
End If
End If
If materialiOn Then
                 .mat(i) = materiali(i).Material3D
                 .mat(i).Ambient = .mat(i).Diffuse 'pongo l'ambiente uguale alla diffuse
End If
         Next
     End With
End Function

Se la volete semplificata per vertici basta cambiare l'argomento nel costruttore della progressive mesh (SimplifyVertex invece di SimplifyFace).
Vi lascio all'esempio che mostra un modello di 13000 poligoni che viene ridimensionato dinamicamente.

Esempio VB.Net

Esempio C#