Il presente articolo è stato tradotto automaticamente.
Silverlight 3D
Sviluppo di oggetti 3D in Silverlight
Rajesh Lal
Scaricare il codice di esempio
In questo articolo verrà illustrato come sviluppare gli oggetti 3D in Silverlight.Verrà iniziare con uno sfondo breve in 3D e quindi osservare alcune delle funzionalità avanzate disponibili in Silverlight che consentono la creazione e la visualizzazione degli oggetti 3D.Verrà prendere un semplice esempio di un cubo e mostra tre diversi modi per creare trasformazioni 3D.Spiegherò anche gli elementi chiavi, è necessario visualizzare un oggetto 3D sullo schermo di un computer.Infine, verrà esaminato come Silverlight 5 verrà consentono di andare oltre a quanto disponibile oggi e creare oggetti 3D molto più ricco.
Silverlight supporta un sistema di coordinate la mano destra, significa che l'asse z positivo è che punta verso il Visualizzatore (vedere Figura1).Esistono tre elementi principali di 3D sono necessari per la visualizzazione di un oggetto sullo schermo:
- Punto di vista
- Trasformazione
- Effetto di luce
Figura 1 cubo di riferimento A, che mostra i lati con punto di vista
Prospettiva significa che le parti di oggetti più vicino a noi visualizzate più grandi di quelle che sono più lontani.Ad esempio, in nella figura 1, laterale bd ha un aspetto più grande rispetto al lato fh.Nella vita reale, viene creato un punto di fuga, si potrà estendere le linee di prospettiva ae, bf, cg e dh sull'asse z verrà soddisfano fino a un singolo punto arbitrario.
Il secondo aspetto è la trasformazione.Un oggetto 3D, quando viene visualizzato sullo schermo, deve consentire lo spostamento nello spazio 3D in tutte le direzioni.Può essere spostata in qualsiasi singolo asse, ovvero adattata per dimensione, mantenendo intatta la prospettiva.Può essere ruotata di 360 gradi in tutti gli assi: x, y e z.In questo modo un oggetto 3D la flessibilità che necessarie per il rendering sullo schermo.
L'ultimo elemento di 3D è l'effetto di luce.Luce 3D crea lo sfondo, che è più luminoso nelle vicinanze di una sorgente luminosa e applica una dissolvenza con distanza.Durante il rendering 3D, i due tipi comuni di sfondo sono uno sfondo "flat" e "sfumato" sfondo.Spiegherò come si differenziano in un secondo momento.Luce creerà inoltre un'ombreggiatura sui lati opposti della sorgente di luce.
Negli esempi di prossima usciti, verrà esaminato tre diversi modi in cui è possibile creare gli oggetti 3D in Silverlight:
- Utilizzo della prospettiva 3D
- Utilizzo di più fotogrammi e un timer
- Utilizzando primitive con la libreria XNA
Nel primo metodo, viene creato un oggetto utilizzando gli elementi bidimensionali, ma ha un aspetto e si comporta come se fossero nello spazio 3D.Prospettiva 3D è un tipo speciale di feature di trasformazione aggiunta 4 di Silverlight consente le trasformazioni di base, ad esempio la rotazione, adattamento e traduzione nello spazio 3D.Il secondo metodo è il metodo "brute force", in cui non creare l'oggetto 3D, ma invece creare i fotogrammi di output finale per una particolare trasformazione e visualizzarli mediante un timer.Il metodo finale consiste nel creare un oggetto 3D RTF bit per bit utilizzando primitive (ad esempio, un elenco di triangoli) con le librerie di XNA saranno disponibile in Silverlight 5.che ci permetterà di assistere a un round trip completo dal server al client. Iniziamo.
Creazione di un cubo utilizzando la prospettiva 3D
4 Silverlight supporta una classe di PlaneProjection (vedere nella figura 2), può essere utilizzato per la proprietà di proiezione di qualsiasi elemento dell'interfaccia utente, come illustrato nel diagramma classi.La classe PlaneProjection consente di trasformazioni 3D prospettiva sull'elemento dell'interfaccia utente.Sebbene non consenta direttamente per la creazione di un oggetto 3D, è possibile utilizzare più "pareti" per creare un oggetto e trasformarlo in uno spazio 3D.
Figura 2 la classe PlaneProjection
La classe PlaneProjection consente di LocalOffset e GlobalOffset, utilizzato per convertire un oggetto rispetto a se stesso e rispetto a un altro elemento nello spazio globale, rispettivamente.RotationX, RotationY e RotationZ consentire per la rotazione dell'elemento in x, y e z assi e CenterOfRotation consente un punto centrale rispetto al piano dell'elemento.
Nel mio esempio, per creare un cubo"" verrà creare quattro i lati del cubo e spostarli nello spazio 3D, impostando le proprietà di PlaneProjection, come illustrato nella nella figura 3.
Figura 3 proprietà delle impostazione di PlaneProjection
<Grid x:Name="LayoutRoot" Background="White" Width="800" Height="700">
<Rectangle Fill="#9900FF00" Width="250" Height="250" Visibility="Visible">
<Rectangle.Projection>
<PlaneProjection x:Name=
"projectionFront" CenterOfRotationZ="125" RotationX="-180"/>
</Rectangle.Projection>
</Rectangle>
<Rectangle Fill="#99FF0000" Width="250" Height="250" Visibility="Visible">
<Rectangle.Projection>
<PlaneProjection x:Name=
"projectionBottom" CenterOfRotationZ="125" RotationX="-90" />
</Rectangle.Projection>
</Rectangle>
<Rectangle Fill="#990000FF" Width="250" Height="250" Visibility="Visible">
<Rectangle.Projection>
<PlaneProjection x:Name="projectionBack" CenterOfRotationZ="125" />
</Rectangle.Projection>
</Rectangle>
<Rectangle Fill="#99FFFF00" Width="250" Height="250" Visibility="Visible">
<Rectangle.Projection>
<PlaneProjection x:Name=
"projectionTop" CenterOfRotationZ="125" RotationX="90"/>
</Rectangle.Projection>
</Rectangle>
</Grid>
In nella figura 4, i lati sono ruotati di 90, -90 e -180 gradi per creare i piani di proiezione superiore, inferiore e la parte anteriore del cubo. Il valore di CenterofRotationZ di 125 crea il punto centrale mediante il quale tutti i piani possono essere ruotati lungo l'asse z.
Figura 4 proiettando i lati per simulare una parete 3D
Una volta creato il cubo utilizzando il piano di proiezione, è necessario ruotarlo da x, y e z di assi. Si tratta, in cui utilizzare l'oggetto storyboard in Silverlight. Creazione di tre storyboard, uno per ciascun asse, come illustrato nella nella figura 5.
Figura 5 ruotando il cubo con storyboard
<Storyboard x:Name="storyboardRotateX">
<DoubleAnimation Storyboard.TargetName="projectionFront"
Storyboard.TargetProperty="RotationX" From="-180.0" To="180.0" Duration="0:0:10"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="projectionBottom"
Storyboard.TargetProperty="RotationX" From="-90.0" To="270.0" Duration="0:0:10"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="projectionBack"
Storyboard.TargetProperty="RotationX" From="0.0" To="360.0" Duration="0:0:10"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="projectionTop"
Storyboard.TargetProperty="RotationX" From="90.0" To="450.0" Duration="0:0:10"
RepeatBehavior="Forever" />
</Storyboard>
<Storyboard x:Name="storyboardRotateY">
<DoubleAnimation Storyboard.TargetName="projectionFront"
Storyboard.TargetProperty="RotationY" From="0.0" To="360.0" Duration="0:0:10"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="projectionBottom"
Storyboard.TargetProperty="RotationY" From="0.0" To="360.0" Duration="0:0:10"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="projectionBack"
Storyboard.TargetProperty="RotationY" From="0.0" To="360.0" Duration="0:0:10"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="projectionTop"
Storyboard.TargetProperty="RotationY" From="0.0" To="360.0" Duration="0:0:10"
RepeatBehavior="Forever" />
</Storyboard>
<Storyboard x:Name="storyboardRotateZ">
<DoubleAnimation Storyboard.TargetName="projectionFront"
Storyboard.TargetProperty="RotationZ" From="0.0" To="360.0" Duration="0:0:10"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="projectionBottom"
Storyboard.TargetProperty="RotationZ" From="0.0" To="360.0" Duration="0:0:10"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="projectionBack"
Storyboard.TargetProperty="RotationZ" From="0.0" To="360.0" Duration="0:0:10"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="projectionTop"
Storyboard.TargetProperty="RotationZ" From="0.0" To="360.0" Duration="0:0:10"
RepeatBehavior="Forever" />
</Storyboard>
Su ogni storyboard, è possibile ruotare ciascuno dei piani di quattro proiezione per mantenere intatta la struttura del cubo. Notare che per la rotazione dell'asse x, il valore di RotationX inizia dal valore originale RotationX del piano e passa un altro di 360 gradi per ProjectionFront, in modo che inizia a-180 gradi e si passa a 180 gradi. Come può vedere nella nella figura 6, il cubo è pronto per la rotazione lungo gli assi z, x e y, che può essere spostata lungo un asse e supporta la colorazione di ciascuno dei lati.
Figura 6, il cubo, pronto per la rotazione
In questo esempio, ho potuto facilmente creare un cubo e trasformarlo in uno spazio 3D senza una grande quantità di codice. Questo è il vero punto di forza di trasformazione 3D prospettiva. Per le operazioni 3D di base, è consigliabile utilizzare questa opzione. Tuttavia, è dotato di una serie di svantaggi. Per gli oggetti 3D avanzati, il numero di piani di proiezione necessari e le relative impostazioni possono aumentare notevolmente e hai manualmente a scoprire gli angoli tra ogni piano di proiezione e la CenterOfRotation. Un altro problema è che la rotazione dell'oggetto 3D dipende gli storyboard in modo intensivo della CPU; non viene utilizzata la GPU per eseguire il rendering dell'oggetto. Un altro problema con questo approccio è il rendering anche back del cubo anche se non è visibile, ovvero non è un approccio ottimale.
Il terzo elemento principale necessario per la visualizzazione degli oggetti 3D sullo schermo è l'effetto di luce. Nella vita reale, luce, si hanno come scopo è simulare che nello spazio 3D sullo schermo? Come accennato, due metodi per eseguire questa operazione sono uno sfondo a schermo piatto e uno sfondo sfumato.
Ombreggiatura semplice prende in considerazione la superficie del piano e si applica un'ombreggiatura Media lungo il piano. Sfumatura ombreggiatura (shading di Gouraud) utilizza una sfumatura per ombreggiare la superficie e tiene conto dei vertici del piano. Il piano non è piano ombreggiato, ma i colori piuttosto "uniforme" vertice ombreggiata, in base alle diverse.
In questo esempio, ognuno dei piani consente per colore riempimento (sfondo piatto (Flat)), nonché di sfumatura riempimento (sfondo sfumato), che può essere utilizzato per simulare l'effetto di luce. Tratterò sono disponibili più avanti. Un modo rapido per simulare l'effetto di luce è sovrapponendo un rettangolo di sfumato radiale con trasparenza utilizzando il seguente codice dopo l'oggetto 3D:
<Rectangle x:Name=
"BulbGradient" Height="700" Width="800" Margin="0 50 0 0" Grid.Row="1"
Visibility="Collapsed">
<Rectangle.Fill>
<RadialGradientBrush RadiusX="0.5" RadiusY="0.5" GradientOrigin="0.25,0.25">
<GradientStop Color="#00000000" Offset="0"/>
<GradientStop Color="#FF000000" Offset="2"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
Creazione di un cubo utilizzando fotogrammi
Il secondo modo per creare un'esperienza 3D consiste nell'utilizzare i frame finali. In questo caso, non si crea l'oggetto 3D stesso, ma inizia con l'output finale richiesto ed esportarla come singoli fotogrammi. Un numero di programmi software di modellazione 3D consentono di creare oggetti 3D e le trasformazioni che possono essere esportate come più fotogrammi e quindi importate in Silverlight.
In questo esempio verrà richiedere un'animazione semplice cubo ed esportare la rotazione x, gli assi y e z in più frame di immagini. Figura 7 indica otto frame diversi di rotazione di una cubo sull'asse x. In questo esempio si utilizza un set minimo di fotogrammi per creare una rotazione di cubo, ma una rotazione più uniforme e semplice di creare più fotogrammi al secondo.
Fotogrammi diversi nella figura 7, 8, simulando la rotazione sull'asse x
Per simulare la rotazione in Silverlight, è necessario utilizzare un timer come illustrato nel codice riportato di seguito:
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
timer.Tick += new EventHandler(Tick);
private void Tick(object o, EventArgs sender)
{
string imageuri = "cube/" + axis + "/" + currentImageIndex + ".png";
bgImage.Source = new BitmapImage(new Uri(imageuri, UriKind.RelativeOrAbsolute));
if (currentImageIndex <= 8)
currentImageIndex++;
else
currentImageIndex = 1;
}
Si tratta di una versione semplificata di cosa può fare con questo metodo. In questo caso uso immagini esportate per semplicità, ma consentire a un numero di softwares 3D per l'esportazione XAML, che consente di creare poligoni con colori e sfumature invece di immagini, fornendo un'animazione più fluida di perfetta. Il timer può anche essere sostituito da storyboard con animazioni.
Questo approccio è molto semplice. Si dispone di un requisito specifico di trasformazione con un particolare oggetto 3D. Non è necessario preoccuparsi di creazione dell'oggetto 3D e questa tecnica può essere utilizzata per creare qualsiasi tipo di oggetto 3D, ovvero non si è più limitato a un cubo semplice. Questo metodo può essere utilizzato per tutti i tipi di trasformazioni. È possibile traslare, ruotare o ridimensionare gli oggetti 3D sofisticati. Anche simula l'effetto di luce, che inoltre si traduce direttamente dal software di modellazione.
Il limite principale di questo approccio è la flessibilità di programmazione per l'oggetto 3D. Una volta che si esporta l'oggetto 3D, genera il codice statico che può essere difficile da codice in base a. Non è possibile spostare l'oggetto con rispetto ad altri elementi nell'applicazione Silverlight. Un altro svantaggio è che il numero di fotogrammi richiesto aumenta linearmente con ogni trasformazione. Inoltre, si verifica il rendering della CPU, aumentano le animazioni con un maggior numero di fotogrammi sarebbero hanno sulle prestazioni raggiunto.
Ciò provoca il terzo approccio dell'utilizzo della libreria XNA nei prossimi 5 di Silverlight, che, come si vedrà in seguito, è possibile superare la maggior parte dei problemi con i primi due approcci. Ma prima che, spiegherò come un oggetto 3D converte in una schermata 2D matematicamente, la logica di genius dietro 3D.
Informazioni su World, la visualizzazione e la matrice di proiezione
Per visualizzare l'oggetto, è necessario comprendere tre concetti principali o "spazi" e modalità di mapping dell'oggetto da un proprio spazio dell'oggetto sullo schermo:
- World
- Guarda
- Proiezione
Figura 8 indica l'ordine in cui è associato un oggetto sullo schermo.
Figura 8 l'ordine in cui un oggetto 3D viene mappato sullo schermo
Il primo insieme di coordinate per un oggetto 3D è x, y e z coordinate nello spazio di oggetto (denominato anche spazio modello). Queste coordinate sono uno rispetto a altro con i loro centri (0, 0, 0). Tenere presente che con le coordinate cartesiane, a destra, l'asse z positivo è verso l'osservatore.
Per un cubo 3D, l'angolo in alto a destra del lato anteriore sarà (1,1,1) e l'angolo inferiore sinistro della parte posteriore sarà (-1, -1, -1), come illustrato nella nella figura 9. Nello spazio dell'oggetto, le coordinate sono uno rispetto a altro e loro posizione solo compreso tra -1 e + 1. Per il cubo per l'utilizzo del 75% dello spazio di oggetto, è necessario moltiplicare ogni coordinata da 75, pertanto il nuovo bsarà (.75,.75,.75) e il nuovo g sarà (-.75,-.75,-.75).
Figura 9 coordinate nello spazio 3D
Quando l'oggetto viene collocato nello spazio mondo, l'oggetto stesso non viene spostato, ma piuttosto mappato con per quanto riguarda le coordinate world moltiplicando le relative coordinate con la matrice globale. Nello spazio mondo, è possibile trasformare l'oggetto 3D spostando le coordinate per convertire l'oggetto, la modifica delle dimensioni in scala e la modifica dell'angolo per ruotare l'oggetto. Per esprimere le coordinate dell'oggetto nello spazio mondo, è necessario moltiplicare ogni posizione di vertice con la matrice globale:
Oggetto coordinate complessive = coordinate dell'oggetto * matrice globale
L'elemento successivo è la visualizzazione della fotocamera, che indica il punto da cui si sta esaminando l'oggetto. Questo punto potete modificare nello spazio 3D senza modificare le coordinate dell'oggetto effettivo spazio dell'oggetto, nonché spazio mondo. Per calcolare le coordinate dell'oggetto per quanto riguarda la visualizzazione della fotocamera, è possibile moltiplicare la matrice di visualizzazione con matrice globale dell'oggetto:
Oggetto di visualizzazione coordinate = coordinate complessive * matrice di visualizzazione
Infine, la visualizzazione dell'oggetto dispone di cui eseguire il rendering sullo schermo; si tratta, in cui è necessario calcolare la vista prospettica creata a causa della distanza. Finora, l'oggetto utente è in proiezione parallela (i lati sono paralleli), ma è necessario visualizzare l'oggetto nella proiezione prospettica (lati unione in un punto di fuga), in modo che moltiplica il prodotto della matrice di visualizzazione dell'oggetto e la matrice globale con la matrice di proiezione:
Oggetto coordinate finale = coordinate complessive * matrice visualizzazione * matrice di proiezione
Questa è la posizione finale dell'oggetto 3D sullo schermo, che è l'acronimo di WorldViewProjection.
La matrice
Una struttura di matrice, disponibile in Microsoft.Xna.Framework, è incluso in Silverlight 5. Dispone di una matrice di produzione omogenea 4 x 4 16 numeri a virgola mobile come campi e una serie di metodi per generare una matrice di trasformazione (vedere nella figura 10).
Figura 10 A Silverlight 5 Matrix Struct
Le prime tre righe per colonne (M11 - M33) vengono utilizzate per la scala e rotazione delle trasformazioni e la quarta riga (M41-M43) viene utilizzata per la traduzione (vedere nella figura 11).
Figura 11 la 4x4 matrice
M11 | M12 | M13 | M14 |
M21 | M22 | M23 | M24 |
M31 | M32 | M33 | M34 |
M41 | M42 | M43 | M44 |
Per comprendere meglio la matrice, vediamo come utilizzarlo rispetto a una trasformazione. Esistono cinque tipi diversi di matrici: struttura di 4x4 matrice, matrice di identità, matrice di traslazione, matrice di scala e matrice di rotazione.
Matrice di identità (vedere nella figura 12) è la matrice di unità della dimensione 4, che diventa la posizione originale dell'oggetto 3D nello spazio mondo. Se si moltiplica qualsiasi matrice con matrice di identità, si otterrà la matrice originale senza alcun cambiamento. Struttura della matrice fornisce una proprietà semplice che restituisce un Matrix.Identity.
Figura 12 la matrice di identità
1 | 0 | 0 | 0 |
0 | 1 | 0 | 0 |
0 | 0 | 1 | 0 |
0 | 0 | 0 | 1 |
Per ridimensionare l'oggetto matrix, fornire un metodo denominato Matrix.CreateScale. La matrice di scala viene utilizzata per la trasformazione in scala di un oggetto 3D, così quando è possibile moltiplicare un oggetto con matrice di scala (vedere nella figura 13), la matrice risultante viene ridimensionato di conseguenza.
Figura 13 la matrice di scala
SX | 0 | 0 | 0 |
0 | SY | 0 | 0 |
0 | 0 | Sz | 0 |
0 | 0 | 0 | 1 |
L'oggetto matrix offre inoltre un metodo Matrix.CreateTranslate per lo spostamento dell'oggetto nello spazio mondo. Quando viene moltiplicata per la matrice di traslazione (vedere nella figura 14), l'oggetto viene convertito nello spazio mondo.
Figura 14, la matrice di traslazione
1 | 0 | 0 | 0 |
0 | 1 | 0 | 0 |
0 | 0 | 1 | 0 |
TX | Ty | TZ | 1 |
Per la rotazione, sono disponibili diversi metodi. Il metodo Matrix.CreateFromYawPitchRoll viene utilizzato per la rotazione di ciascuno degli assi per un valore di numero mobile. I metodi Matrix.CreateRotationX, Matrix.CreateRotationY e Matrix.CreateRotationZ sono per la rotazione dell'oggetto lungo x, y e z di assi. La matrice di rotazione rispetto al teta angolo prevede gli elementi M11-M33, come illustrato nella nella figura 15.
Matrice di rotazione figura 15 lungo X, Y e z assi
1 | 0 | 0 | 0 |
0 | COS θ | SEN θ | 0 |
0 | -Sin θ | COS θ | 0 |
0 | 0 | 0 | 1 |
Rotazione X |
COS θ | 0 | SEN θ | 0 |
0 | 1 | 0 | 0 |
-Sin θ | 0 | COS θ | 0 |
0 | 0 | 0 | 1 |
Rotazione Y |
COS θ | SEN θ | 0 | 0 |
-Sin θ | COS θ | 0 | 0 |
0 | 0 | 1 | 0 |
0 | 0 | 0 | 1 |
Rotazione Z |
La tubazione 3D di formazione per Silverlight XNA
5 Di Silverlight con librerie XNA fornisce una procedura guidata per la creazione di oggetti 3D con le coordinate dei vertici per il rendering sullo schermo. Ciò può essere suddiviso in cinque passaggi principali (vedere nella figura 16) che riguardano i componenti illustrati di seguito:
- Buffer di vertice
- Coordinate WorldViewProjection
- Sfondo: vertice, pixel e trama
- L'elaborazione grafica: rasterizzare, ritagliare e da riforma
- Output finale: il buffer di frame
Figura 16 creazione di oggetti 3D con le librerie di Silverlight 5 XNA
Illustrerò brevemente ogni passaggio e i relativi componenti.
Vertex Buffer di nella creazione di un vertex buffer dall'insieme di vertice, il primo passaggio consiste nella creazione dell'ossatura dell'oggetto 3D utilizzando un insieme di vertici. Ogni vertice contiene almeno x, y e z coordinate, ma in genere dispone anche di altre proprietà, ad esempio il colore e la trama. Questo insieme di vertici quindi viene utilizzato per creare un vertex buffer, passa al passaggio successivo del processo.
Coordinate WorldViewProjection le coordinate finale vengono calcolate moltiplicando i vertici con matrici di proiezione, visualizzazione e globale. In questo caso, viene calcolata la relazione dell'oggetto con lo spazio mondo, la visualizzazione e la proiezione e applicato. Controllare le ultime due sezioni per ulteriori dettagli. Dopo aver configurato le coordinate finale, il processo effettivo di uno sfondo ha luogo.
Sfondo vertice lo sfondo, lo sfondo di pixel e lo sfondo di trama vengono utilizzati. In questo passaggio, viene eseguita la colorazione del prima vertice e quindi viene eseguita la sfumatura pixel per pixel. Lo sfondo di texture viene applicato anche in questo passaggio. Queste coordinate ombreggiate finale vengono quindi utilizzate per creare un buffer di frame.
Rasterizza, ritagliare e da riforma durante la rasterizzazione un'immagine viene convertita in pixel e la riforma e clip vengono quindi utilizzate per rimuovere lo scheletro del object, unitamente ai livelli nascosti e invisibili. Infine viene visualizzato sullo schermo.
Buffer di frame dopo che l'immagine viene rasterizzata, ritagliate e riformati, un buffer di frame viene generato, che viene quindi inviato allo schermo per la visualizzazione.
Creazione di un cubo utilizzando primitive
Con la conoscenza di matrici, world, visualizzazione, proiezione e la tubazione 3D 5 Silverlight con librerie XNA, creare un cubo 3D e vedere come proviene tra loro.
Il vantaggio principale di questo approccio è l'accelerazione GPU, che consente l'accelerazione hardware, liberando la CPU di eseguire il rendering dell'oggetto 3D. Questa opzione è attivata, impostando il parametro EnableGPUAcceleration nel tag Object su true nel codice HTML utilizzato per configurare il plug-in Silverlight, come illustrato di seguito:
<object data="data:application/x-silverlight-2,"
type="application/x-silverlight-2" width="100%" height="100%">
<param name="EnableGPUAcceleration" value="true" />
<param name="source" value="ClientBin/Cube3d.xap"/>
<param name="minRuntimeVersion" value="5.0.60211.0" />
</object>
In XAML, aggiungerà un oggetto DrawingSurface all'interno della griglia, che viene utilizzato per eseguire il rendering 3D in Silverlight con la Guida in linea del metodo DrawPrimitives dell'oggetto GraphicsDevice (vedere nella figura 17):
<DrawingSurface Loaded="OnLoad" SizeChanged="OnSizeChanged" Draw="OnDraw"/>
Figura 17 il metodo DrawPrimitives della classe GraphicsDevice
Si utilizzerà tre metodi nella classe DrawingSurface per creare ed eseguire il rendering del cubo. Il metodo OnLoad viene utilizzato per la creazione del cubo e l'inizializzazione di tutti gli shader e la matrice di visualizzazione non cambia in questa applicazione. Si noti che l'oggetto 3D è centrato a (0, 0,0) utilizzando il 75% dello spazio oggetto con le coordinate che vanno da (.75,.75,.75) (-.75,-.75,-.75). In questo caso, creerà un vertex buffer per contenere l'insieme di vertice e inizializzare shaderStream, pixelStream e imageStream flussi, verranno essere utilizzati in un secondo momento nel passaggio di un'ombreggiatura. Inoltre verrà inizializzare la matrice di visualizzazione è l'angolo con cui la telecamera sta guardando l'oggetto utilizzando cameraPosition e cameraTarget con il parametro Vector3.Up (ovvero che si dirige verso l'alto la camera). Questo codice è riportato in nella figura 18.
Figura 18 di impostazione delle shaderStream, pixelStream e imageStream
VertexBuffer vertexBuffer;
VertexShader vertexShader;
PixelShader pixelShader;
Texture2D texture;
private void OnLoad(object sender, RoutedEventArgs e)
{
vertexBuffer = CreateCube();
Stream shaderStream = Application.GetResourceStream(new
Uri(@"Cube3d;component/shader/shader.vs", UriKind.Relative)).Stream;
vertexShader = VertexShader.FromStream(resourceDevice, shaderStream);
Stream pixelStream = Application.GetResourceStream(new
Uri(@"Cube3d;component/shader/shader.ps", UriKind.Relative)).Stream;
pixelShader = PixelShader.FromStream(resourceDevice, pixelStream);
Stream imageStream = Application.GetResourceStream(new
Uri(@"Cube3d;component/scene.jpg",
UriKind.Relative)).Stream;
var image = new BitmapImage();
image.SetSource(imageStream);
texture = new Texture2D(resourceDevice, image.PixelWidth,
image.PixelHeight, false, SurfaceFormat.Color);
image.CopyTo(texture);
Vector3 cameraPosition = new Vector3(0, 0, 5.0f);
Vector3 cameraTarget = Vector3.Zero;
view = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);
}
Il passaggio successivo consiste nel creare il vertex buffer per il cubo 3D. Creerò un metodo di CreateCube come illustrato nella Figura 19 che restituisce un VertexBuffer. Creerò due rettangoli nello spazio 3D con ABCD che costituiscono la parte anteriore del cubo ed EFGH back del cubo. Utilizzare la struttura VertexPositionColor per creare un insieme di vertici e i colori associati a ciascuno di essi.
Figura 19 creazione il VertexBuffer nel metodo CreateCube
VertexBuffer CreateCube()
{
var vertexCollection = new VertexPositionColor[36];
// Front coordinates
Vector3 cubeA = new Vector3(-0.75f, 0.75f, 0.75f);
Vector3 cubeB = new Vector3(0.75f, 0.75f, 0.75f);
Vector3 cubeC = new Vector3(-0.75f, -0.75f, 0.75f);
Vector3 cubeD = new Vector3(0.75f, -0.75f, 0.75f);
// Back coordinates
Vector3 cubeE = new Vector3(-0.75f, 0.75f, -0.75f);
Vector3 cubeF = new Vector3(0.75f, 0.75f, -0.75f);
Vector3 cubeG = new Vector3(-0.75f, -0.75f, -0.75f);
Vector3 cubeH = new Vector3(0.75f, -0.75f, -0.75f);
// Colors
Color cRed = Color.FromNonPremultiplied(255, 0, 0, 156);
Color cGreen = Color.FromNonPremultiplied(0, 255, 0, 156);
Color cBlue = Color.FromNonPremultiplied(0, 0, 255, 156);
Color cYellow = Color.FromNonPremultiplied(255, 255, 0, 156);
Color cBlack = Color.FromNonPremultiplied(0, 0, 0, 156);
Color cWhite = Color.FromNonPremultiplied(255, 255, 255, 156);
// Front
vertexCollection[0] = new VertexPositionColor(cubeA, cGreen);
vertexCollection[1] = new VertexPositionColor(cubeB, cGreen);
vertexCollection[2] = new VertexPositionColor(cubeC, cGreen);
vertexCollection[3] = new VertexPositionColor(cubeB, cBlue);
vertexCollection[4] = new VertexPositionColor(cubeD, cBlue);
vertexCollection[5] = new VertexPositionColor(cubeC, cBlue);
// Back
vertexCollection[6] = new VertexPositionColor(cubeG, cBlue);
vertexCollection[7] = new VertexPositionColor(cubeF, cBlue);
vertexCollection[8] = new VertexPositionColor(cubeE, cBlue);
vertexCollection[9] = new VertexPositionColor(cubeH, cGreen);
vertexCollection[10] = new VertexPositionColor(cubeF, cGreen);
vertexCollection[11] = new VertexPositionColor(cubeG, cGreen);
// Top
vertexCollection[12] = new VertexPositionColor(cubeE, cRed);
vertexCollection[13] = new VertexPositionColor(cubeF, cRed);
vertexCollection[14] = new VertexPositionColor(cubeA, cRed);
vertexCollection[15] = new VertexPositionColor(cubeF, cYellow);
vertexCollection[16] = new VertexPositionColor(cubeB, cYellow);
vertexCollection[17] = new VertexPositionColor(cubeA, cYellow);
// Bottom
vertexCollection[18] = new VertexPositionColor(cubeH, cRed);
vertexCollection[19] = new VertexPositionColor(cubeG, cRed);
vertexCollection[20] = new VertexPositionColor(cubeC, cRed);
vertexCollection[21] = new VertexPositionColor(cubeD, cYellow);
vertexCollection[22] = new VertexPositionColor(cubeH, cYellow);
vertexCollection[23] = new VertexPositionColor(cubeC, cYellow);
// Left
vertexCollection[24] = new VertexPositionColor(cubeC, cBlack);
vertexCollection[25] = new VertexPositionColor(cubeG, cBlack);
vertexCollection[26] = new VertexPositionColor(cubeA, cBlack);
vertexCollection[27] = new VertexPositionColor(cubeA, cWhite);
vertexCollection[28] = new VertexPositionColor(cubeG, cWhite);
vertexCollection[29] = new VertexPositionColor(cubeE, cWhite);
// Right
vertexCollection[30] = new VertexPositionColor(cubeH, cWhite);
vertexCollection[31] = new VertexPositionColor(cubeD, cWhite);
vertexCollection[32] = new VertexPositionColor(cubeB, cWhite);
vertexCollection[33] = new VertexPositionColor(cubeH, cBlack);
vertexCollection[34] = new VertexPositionColor(cubeB, cBlack);
vertexCollection[35] = new VertexPositionColor(cubeF, cBlack);
var vb = new VertexBuffer(resourceDevice,
VertexPositionColor.VertexDeclaration,
vertexCollection.Length, BufferUsage.WriteOnly);
vb.SetData(0, vertexCollection, 0, vertexCollection.Length, 0);
return vb;
}
Il metodo OnSizeChanged della superficie di disegno viene utilizzato per aggiornare la proiezione e le proporzioni dello schermo in base alle dimensioni di superficie:
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
DrawingSurface surface = sender as DrawingSurface;
float sceneAspectRatio = (float)surface.ActualWidth / (float)surface.ActualHeight
projection = Matrix.CreatePerspectiveFieldOfView
(MathHelper.PiOver4, sceneAspectRatio, 1.0f, 100.0f);
}
L'ultimo metodo è OnDraw, che consente la trasformazione dinamica sul cubo 3D. Si tratta, in cui viene applicata la Matrix.CreateScale per ridimensionare il cubo, Matrix.CreateFromYawPitchRoll ruotarlo e Matrix.CreateTranslate per spostarlo. In questo caso, viene calcolata la matrice di worldViewProjection e inviati al metodo vertexShader per sfondo i vertici, che a sua volta trasferisce pixelShader per ombreggiare "pareti" del cubo. Questo a sua volta può anche essere inviato a textureShader, che può essere basata su un'immagine. Infine, l'oggetto GraphicDevice chiama un metodo DrawPrimitives per il rendering dei fotogrammi di output, come illustrato nella figura 20.
Figura 20 chiamando il metodo DrawPrimitives per eseguire il rendering di fotogrammi di Output
void OnDraw(object sender, DrawEventArgs args)
{
Matrix position = Matrix.Identity;
Matrix scale = Matrix.CreateScale(1.0f);
float xf = 0.0f; float yf = 0.0f; float zf = 0.0f;
if (cubeXAxis) xf = MathHelper.PiOver4 * (float)args.TotalTime.TotalSeconds;
if (cubeYAxis) yf = MathHelper.PiOver4 * (float)args.TotalTime.TotalSeconds;
if (cubeZAxis) zf = MathHelper.PiOver4 * (float)args.TotalTime.TotalSeconds;
Matrix rotation = Matrix.CreateFromYawPitchRoll(xf, yf, zf);
Matrix world;
if (translateZ != 0)
world = rotation * Matrix.CreateTranslation(0, 0, (float)translateZ);
else
world = scale * rotation * position;
// Calculate the final coordinates to pass to the shader.
Matrix worldViewProjection = world * view * projection;
args.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer,
new Microsoft.Xna.Framework.Color(0, 0, 0, 0), 10.0f, 0);
// Set up vertex pipeline.
args.GraphicsDevice.SetVertexBuffer(vertexBuffer);
args.GraphicsDevice.SetVertexShader(vertexShader);
args.GraphicsDevice.SetVertexShaderConstantFloat4(0, ref worldViewProjection);
// Set up pixel pipeline.
args.GraphicsDevice.SetPixelShader(pixelShader);
args.GraphicsDevice.Textures[0] = texture;
args.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 12);
args.InvalidateSurface();
}
Questo rende in modo dinamico il cubo 3D finale sulla superficie di disegno (vedere nella figura 21).
Figura 21, il cubo 3D finale sulla superficie di disegno
Questo approccio utilizza l'accelerazione GPU e non esegue il rendering i lati dell'oggetto 3D che sono nascosti o la parte posteriore, a differenza del mio primo approccio. Questo utilizza anche il buffer di frame in memoria per il rendering dell'output finale, come il secondo approccio, ma con controllo completo e la flessibilità di programmazione per l'oggetto come con il metodo OnDraw.
Dopo avere appreso tre diversi modi per creare oggetti 3D in Silverlight, ciascuna con propri punti di forza e punti deboli. Esplorando il mondo di 3D in Silverlight, questi deve essere aggiunte utili per la casella degli strumenti.
Rajesh Lal è appassionato di tecnologie Web e Silverlight. Ha scritto più libri su Windows gadget, widget Web e alle tecnologie Web mobili, in un libro di prossima pubblicazione, "Fun con Silverlight 4" (CreateSpace, 2011). Per ulteriori informazioni, contattare mconnectrajesh@hotmail.com o visitare silverlightfun.com.
Grazie per i seguenti esperti tecnici per la revisione di questo articolo: Marc Clifton, Kingslan di Rick e Josh Smith