Cenni preliminari sulla grafica tridimensionale
La funzionalità di 3-D in Windows Presentation Foundation (WPF) consente agli sviluppatori di creare, trasformare e animare grafica 3D nel markup e nel codice procedurale. Gli sviluppatori possono combinare grafica 2-D e 3-D per creare controlli dettagliati, fornire illustrazioni complesse di dati o migliorare l'esperienza utente dell'interfaccia di un'applicazione. Il supporto 3-D in WPF non è progettato come piattaforma per lo sviluppo di giochi con funzionalità complete. In questo argomento vengono forniti cenni preliminari sulla funzionalità di 3-D nel sistema grafico di WPF.
Nel presente argomento sono contenute le seguenti sezioni.
- Grafica 3D in un contenitore bidimensionale
- Spazio delle coordinate tridimensionali
- Fotocamere e proiezioni
- Modello e primitive mesh
- Applicazione di materiali al modello
- Illuminazione della scena
- Trasformazione di modelli
- Animazione di modelli
- Aggiungere contenuto tridimensionale alla finestra
- Argomenti correlati
Grafica 3D in un contenitore bidimensionale
Il contenuto grafico 3-D in WPF è incapsulato nell'elemento Viewport3D, che può far parte della struttura dell'elemento bidimensionale. Il sistema grafico considera Viewport3D come un elemento visivo bidimensionale come molti altri in WPF. Viewport3D funziona come una finestra, o un riquadro di visualizzazione, in una scena tridimensionale. Più precisamente, si tratta di una superficie sulla quale viene proiettata una scena 3-D.
In un'applicazione 2-D convenzionale, utilizzare Viewport3D come qualsiasi altro elemento contenitore, ad esempio Grid o Canvas. Benché sia possibile utilizzare Viewport3D con altri oggetti disegno 2-D nello stesso grafico, non è possibile inserire oggetti 2-D e 3-D all'interno di un oggetto Viewport3D. In questo argomento verrà illustrato come disegnare grafica 3-D in Viewport3D.
Spazio delle coordinate tridimensionali
Il sistema di coordinate WPF per la grafica 2-D individua l'origine nella parte superiore sinistra dell'area di rendering, in genere lo schermo. Nel sistema 2-D, i valori positivi dell'asse x procedono verso destra, mentre i valori positivi dell'asse y procedono in direzione discendente. Nel sistema di coordinate 3-D, tuttavia, l'origine viene individuata al centro dell'area di rendering, con i valori positivi dell'asse x che procedono verso destra, i valori positivi dell'asse y che procedono verso l'alto e i valori positivi dell'asse z che procedono verso l'esterno dell'origine, in direzione del visualizzatore.
Rappresentazioni convenzionali dei sistemi di coordinate bidimensionali e tridimensionali
Lo spazio definito da questi assi è il frame di riferimento fisso per oggetti 3-D in WPF. Quando si compilano modelli in questo spazio e si creano luci e fotocamere per visualizzarli, è consigliabile distinguere il frame di riferimento fisso, o spazio globale, dal frame di riferimento locale creato per ciascun modello quando vi si applicano trasformazioni. Si ricordi inoltre che gli oggetti dello spazio globale possono avere un aspetto completamente diverso, o non essere visibile a tutti, a seconda delle impostazioni di luce e fotocamera, ma la posizione della fotocamera non modifica la posizione degli oggetti nello spazio globale.
Fotocamere e proiezioni
Gli sviluppatori che lavorano in 2-D sono abituati a posizionare le primitive del disegno su uno schermo bidimensionale. Nella creazione di una scena 3-D, è importante tenere presente che in realtà si sta creando una rappresentazione 2-D di oggetti 3-D. Poiché una scena 3-D ha un aspetto diverso a seconda del punto di vista dello spettatore, è necessario specificare tale punto di vista. La classe Camera consente di specificare il punto di vista per una scena 3-D.
Per comprendere la modalità di rappresentazione di una scena 3-D su una superficie 2-D è inoltre possibile descrivere la scena come proiezione sulla superficie di visualizzazione. ProjectionCamera consente di specificare proiezioni diverse e le relative proprietà per modificare la modalità di visualizzazione dei modelli 3-D da parte dello spettatore. Un oggetto PerspectiveCamera specifica una proiezione che rappresenta uno scorcio della scena. In altre parole, PerspectiveCamera offre la prospettiva del punto di fuga. È possibile specificare la posizione della fotocamera nello spazio delle coordinate della scena, la direzione e il campo visivo per la fotocamera e un vettore che definisce la direzione verso l'alto nella scena. Nel diagramma riportato di seguito viene illustrata la proiezione dell'oggetto PerspectiveCamera.
Le proprietà NearPlaneDistance e FarPlaneDistance di ProjectionCamera limitano l'intervallo della proiezione della fotocamera. Poiché le fotocamere si possono trovare in qualunque punto della scena, è possibile che la fotocamera venga posizionata all'interno di un modello o accanto a esso, rendendo difficile distinguere correttamente gli oggetti. NearPlaneDistance consente di specificare una distanza minima dalla fotocamera oltre la quale non verranno disegnati oggetti. Al contrario, FarPlaneDistance consente di specificare una distanza dalla fotocamera oltre la quale non verranno disegnati oggetti per garantire che non vengano inclusi nella scena oggetti troppo lontani per essere riconoscibili.
Posizione della fotocamera
OrthographicCamera specifica una proiezione ortogonale di un modello 3-D su una superficie visiva 2-D. Analogamente ad altre fotocamere, specifica una posizione, una direzione di visualizzazione e una direzione verso l'alto. A differenza di PerspectiveCamera, tuttavia, la classe OrthographicCamera descrive una proiezione che non include lo scorcio prospettico. In altri termini, OrthographicCamera descrive un riquadro di visualizzazione con i lati paralleli, anziché un riquadro i cui lati si incontrano in un punto in corrispondenza della fotocamera. Nell'immagine riportata di seguito viene illustrato lo stesso modello visualizzato tramite PerspectiveCamera e OrthographicCamera.
Proiezioni prospettiche e ortografiche
Nel codice riportato di seguito vengono illustrate alcune impostazioni tipiche della fotocamera.
' Defines the camera used to view the 3D object. In order to view the 3D object,
' the camera must be positioned and pointed such that the object is within view
' of the camera.
Dim myPCamera As New PerspectiveCamera()
' Specify where in the 3D scene the camera is.
myPCamera.Position = New Point3D(0, 0, 2)
' Specify the direction that the camera is pointing.
myPCamera.LookDirection = New Vector3D(0, 0, -1)
' Define camera's horizontal field of view in degrees.
myPCamera.FieldOfView = 60
' Asign the camera to the viewport
myViewport3D.Camera = myPCamera
// Defines the camera used to view the 3D object. In order to view the 3D object,
// the camera must be positioned and pointed such that the object is within view
// of the camera.
PerspectiveCamera myPCamera = new PerspectiveCamera();
// Specify where in the 3D scene the camera is.
myPCamera.Position = new Point3D(0, 0, 2);
// Specify the direction that the camera is pointing.
myPCamera.LookDirection = new Vector3D(0, 0, -1);
// Define camera's horizontal field of view in degrees.
myPCamera.FieldOfView = 60;
// Asign the camera to the viewport
myViewport3D.Camera = myPCamera;
Modello e primitive mesh
Model3D è la classe base astratta che rappresenta un oggetto 3-D generico. Per compilare una scena 3-D sono necessari alcuni oggetti da visualizzare e gli oggetti che compongono il grafico della scena derivano da Model3D. Attualmente, WPF supporta le geometrie di modellazione con GeometryModel3D. La proprietà Geometry di questo modello accetta una primitiva mesh.
Per compilare un modello, iniziare dalla compilazione di una primitiva o mesh. Una primitiva 3-D è un insieme di vertici che costituiscono una sola entità 3-D. La maggior parte dei sistemi 3-D offre primitive modellate sulla figura chiusa più semplice, ovvero un triangolo definito da tre vertici. Poiché i tre punti di un triangolo sono complanari, è possibile continuare ad aggiungere triangoli per modellare forme più complesse, dette mesh.
Nel sistema 3-D WPF è disponibile attualmente la classe MeshGeometry3D che consente di specificare qualsiasi geometria. Attualmente, non sono supportate primitive 3-D predefinite, quali sfere e forme cubiche. Creare un oggetto MeshGeometry3D specificando un elenco di vertici di triangolo come proprietà Positions. Ciascun vertice viene specificato come Point3D. In Extensible Application Markup Language (XAML), specificare questa proprietà come elenco di numeri in gruppi di tre che rappresentano le coordinate di ciascun vertice. A seconda della geometria, la mesh potrebbe essere composta da molti triangoli, alcuni dei quali condividono gli stessi angoli (vertici). Per disegnare correttamente la mesh, in WPF sono necessarie informazioni sui vertici condivisi e sui triangoli che li condividono. Fornire queste informazioni specificando un elenco di indici di triangoli con la proprietà TriangleIndices. In questo elenco viene specificato in quale ordine i punti definiti nell'elenco Positions determinano un triangolo.
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0"
Normals="0 0 1 0 0 1 0 0 1 0 0 1"
TextureCoordinates="0 1 1 1 0 0 1 0 "
TriangleIndices="0 1 2 1 3 2" />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<!-- Translate the plane. -->
<GeometryModel3D.Transform>
<TranslateTransform3D
OffsetX="2" OffsetY="0" OffsetZ="-1" >
</TranslateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
Nell'elenco Positions dell'esempio precedente vengono specificati otto vertici per definire una mesh a forma di cubo. Tramite la proprietà TriangleIndices viene specificato un elenco di dodici gruppi di tre indici. Ogni numero nell'elenco fa riferimento a un offset nell'elenco Positions. Ad esempio, i primi tre vertici specificati dall'elenco Positions sono (1,1,0), (0,1,0) e (0,0,0). I primi tre indici specificati dall'elenco TriangleIndices sono 0, 2 e 1, che corrispondono al primo, terzo e secondo punto nell'elenco Positions. Di conseguenza, il primo triangolo che costituisce il modello di cubo sarà composto da (1,1,0) a (0,1,0) a (0,0,0) e gli undici triangoli rimanenti saranno determinati in modo analogo.
È possibile continuare a definire il modello specificando i valori delle proprietà Normals e TextureCoordinates. Per eseguire il rendering della superficie del modello, è necessario che il sistema grafico disponga delle informazioni per stabilire in quale direzione è rivolta la superficie in corrispondenza di tutti i triangoli specificati. Tali informazioni vengono utilizzate dal sistema per eseguire calcoli di illuminazione per il modello, con le superfici rivolte direttamente verso una sorgente di luce più brillanti rispetto a quelle angolate rispetto alla luce. Sebbene WPF sia in grado di determinare i vettori normali predefiniti utilizzando le coordinate di posizione, è anche possibile specificare vettori normali diversi per avvicinarsi all'aspetto delle superfici curve.
La proprietà TextureCoordinates specifica un insieme di Point che fornisce al sistema grafico la modalità di mapping delle coordinate che determinano in che modo viene disegnata una trama sui vertici della mesh. TextureCoordinates viene specificata come valore compreso tra zero e 1, inclusi. Analogamente a quanto avviene con la proprietà Normals, le coordinate di trama predefinite possono essere calcolate dal sistema grafico, ma è possibile decidere di impostare coordinate di trama diverse per controllare, ad esempio, il mapping di una trama che include parte di un pattern ripetitivo. Per ulteriori informazioni sulle coordinate di trama, vedere gli argomenti successivi o Managed Direct3D SDK.
Nell'esempio riportato di seguito viene illustrato come creare una faccia del modello di cubo in codice procedurale. Si noti che è possibile disegnare l'intero cubo come oggetto GeometryModel3D singolo. In questo esempio viene disegnata la faccia del cubo come modello distinto per applicare in un secondo momento trame separate a ogni faccia.
Private side1Plane As New MeshGeometry3D()
MeshGeometry3D side1Plane = new MeshGeometry3D();
side1Plane.Positions.Add(New Point3D(-0.5, -0.5, -0.5))
side1Plane.Positions.Add(New Point3D(-0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, -0.5, -0.5))
side1Plane.Positions.Add(New Point3D(-0.5, -0.5, -0.5))
side1Plane.TriangleIndices.Add(0)
side1Plane.TriangleIndices.Add(1)
side1Plane.TriangleIndices.Add(2)
side1Plane.TriangleIndices.Add(3)
side1Plane.TriangleIndices.Add(4)
side1Plane.TriangleIndices.Add(5)
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.TextureCoordinates.Add(New Point(1, 0))
side1Plane.TextureCoordinates.Add(New Point(1, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 0))
side1Plane.TextureCoordinates.Add(New Point(1, 0))
side1Plane.Positions.Add(new Point3D(-0.5, -0.5, -0.5));
side1Plane.Positions.Add(new Point3D(-0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, -0.5, -0.5));
side1Plane.Positions.Add(new Point3D(-0.5, -0.5, -0.5));
side1Plane.TriangleIndices.Add(0);
side1Plane.TriangleIndices.Add(1);
side1Plane.TriangleIndices.Add(2);
side1Plane.TriangleIndices.Add(3);
side1Plane.TriangleIndices.Add(4);
side1Plane.TriangleIndices.Add(5);
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.TextureCoordinates.Add(new Point(1, 0));
side1Plane.TextureCoordinates.Add(new Point(1, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 0));
side1Plane.TextureCoordinates.Add(new Point(1, 0));
Applicazione di materiali al modello
Affinché una mesh assuma l'aspetto di oggetto tridimensionale, è necessario che a essa venga applicata una trama per coprire la superficie definita dai relativi vertici e triangoli, in modo che possa essere illuminata e proiettata dalla fotocamera. In 2-D, utilizzare la classe Brush per applicare colori, modelli, sfumature o altro contenuto visivo alle aree dello schermo. L'aspetto degli oggetti 3-D, tuttavia, è una funzione del modello di illuminazione, non solo del colore o del pattern applicato. Gli oggetti reali riflettono la luce in modo diverso a seconda della qualità delle superfici. Le superfici lucide e brillanti non hanno infatti lo stesso aspetto delle superfici grezze o opache. Alcuni oggetti, inoltre, sembrano assorbire la luce, mentre altri la riflettono. È possibile applicare agli oggetti 3-D gli stessi pennelli applicabili agli oggetti 2-D, ma non direttamente.
Per definire le caratteristiche di superficie di un modello, in WPF viene utilizzata la classe astratta Material. Le sottoclassi concrete di Material determinano alcune delle caratteristiche di aspetto della superficie del modello e ognuna fornisce anche una proprietà Brush alla quale è possibile passare un oggetto SolidColorBrush, TileBrush o VisualBrush.
DiffuseMaterial specifica che il pennello verrà applicato al modello come se tale modello fosse illuminato in modo diffuso. L'utilizzo di DiffuseMaterial è simile all'utilizzo diretto di pennelli su modelli 2-D. Le superfici dei modelli non riflettono luce come se fossero brillanti.
SpecularMaterial specifica che il pennello verrà applicato al modello come se la superficie del modello fosse dura o brillante, in grado di riflettere le evidenziazioni. È possibile impostare il grado di qualità riflettente, o luminosità, della trama specificando un valore per la proprietà SpecularPower.
EmissiveMaterial consente di specificare che la trama sarà applicata come se il modello emettesse una luce uguale al colore del pennello. In questo modo, il modello non viene trasformato in luce ma partecipa in modo diverso allo shadowing rispetto a quanto accade nel caso di trama applicata con DiffuseMaterial o SpecularMaterial.
Per prestazioni ottimali, le facce posteriori di un oggetto GeometryModel3D, ovvero le facce esterne alla visualizzazione poiché si trovano sul lato opposto del modello rispetto alla fotocamera, vengono rimosse dalla scena. Per specificare un oggetto Material da applicare alla faccia posteriore di un modello come un piano, impostare la proprietà BackMaterial del modello.
Per ottenere alcune qualità della superficie, come l'effetto alone o riflettente, è necessario applicare in successione a un modello più pennelli diversi. È possibile applicare e riutilizzare più materiali tramite la classe MaterialGroup. Gli elementi figlio di MaterialGroup vengono applicati dal primo all'ultimo in più passaggi di rendering.
Negli esempi di codice riportati di seguito viene illustrato come applicare un colore a tinta unita e un disegno come pennelli ai modelli 3-D.
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<DrawingBrush x:Key="patternBrush" Viewport="0,0,0.1,0.1" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Geometry="M0,0.1 L0.1,0 1,0.9, 0.9,1z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.9,0 L1,0.1 0.1,1 0,0.9z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.25,0.25 L0.5,0.125 0.75,0.25 0.5,0.5z"
Brush="#FFFF00" />
<GeometryDrawing Geometry="M0.25,0.75 L0.5,0.875 0.75,0.75 0.5,0.5z"
Brush="Black" />
<GeometryDrawing Geometry="M0.25,0.75 L0.125,0.5 0.25,0.25 0.5,0.5z"
Brush="#FF0000" />
<GeometryDrawing Geometry="M0.75,0.25 L0.875,0.5 0.75,0.75 0.5,0.5z"
Brush="MediumBlue" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
Dim side5Material As New DiffuseMaterial(CType(Application.Current.Resources("patternBrush"), Brush))
DiffuseMaterial side5Material = new DiffuseMaterial((Brush)Application.Current.Resources["patternBrush"]);
Illuminazione della scena
Le luci nella grafica 3-D hanno la stessa funzione delle luci reali, rendono visibili le superfici. Più precisamente, le luci determinano quale parte di una scena verrà inclusa nella proiezione. Gli oggetti luce in WPF creano una varietà di luci e di effetti di ombreggiatura e sono modellati in base al comportamento di varie luci reali. È necessario includere almeno una luce nella scena, altrimenti nessun modello sarà visibile.
Le luci elencate di seguito derivano dalla classe base Light:
AmbientLight: fornisce illuminazione di ambiente che illumina tutti gli oggetti in modo uniforme indipendentemente dalla posizione o dall'orientamento.
DirectionalLight: illumina come una sorgente di luce lontana. Le luci direzionali hanno una proprietà Direction specificata come Vector3D, ma nessuna posizione.
PointLight: illumina come una sorgente di luce vicina. Gli oggetti PointLight hanno una posizione dalla quale proiettano la luce. Gli oggetti nella scena vengono illuminati a seconda della posizione e della distanza rispetto alla luce. PointLightBase espone una proprietà Range che determina una distanza oltre la quale i modelli non verranno illuminati dalla luce. PointLight espone anche proprietà di attenuazione che determinano la modalità in cui l'intensità della luce diminuisce a distanza. È possibile specificare interpolazioni costanti, lineari o quadratiche per l'attenuazione della luce.
SpotLight: eredita da PointLight. Gli oggetti Spotlight illuminano come gli oggetti PointLight e dispongono di posizione e direzione. Proiettano luce in un'area a forma di cono impostata dalle proprietà InnerConeAngle e OuterConeAngle, specificate in gradi.
Le luci sono oggetti Model3D, pertanto è possibile trasformarne e animarne le proprietà, tra cui posizione, colore, direzione e intervallo.
<ModelVisual3D.Content>
<AmbientLight Color="#333333" />
</ModelVisual3D.Content>
Private myDirLight As New DirectionalLight()
DirectionalLight myDirLight = new DirectionalLight();
myDirLight.Color = Colors.White
myDirLight.Direction = New Vector3D(-3, -4, -5)
myDirLight.Color = Colors.White;
myDirLight.Direction = new Vector3D(-3, -4, -5);
modelGroup.Children.Add(myDirLight)
modelGroup.Children.Add(myDirLight);
Trasformazione di modelli
Quando vengono creati, i modelli hanno una determinata posizione nella scena. Per spostare i modelli nella scena, per ruotarli o per modificarne la dimensione, è poco pratico modificare i vertici che li definiscono. Vengono invece applicate trasformazioni ai modelli, come in 2-D.
Ogni oggetto modello dispone di una proprietà Transform con la quale è possibile spostare, orientare nuovamente o ridimensionare il modello. Quando si applica una trasformazione, si esegue in effetti l'offset di tutti i punti del modello con qualsiasi vettore o valore specificato dalla trasformazione. In altre parole, viene trasformato lo spazio delle coordinate nel quale il modello è definito ("spazio modello"), ma non vengono modificati i valori che costituiscono la geometria del modello nel sistema di coordinate dell'intera scena ("spazio globale").
Per ulteriori informazioni sulla trasformazione dei modelli, vedere Cenni preliminari sulle trasformazioni tridimensionali.
Animazione di modelli
L'implementazione 3-D di WPF fa parte dello stesso sistema di temporizzazione e animazione della grafica 2-D. In altre parole, per animare una scena tridimensionale, è necessario animare le proprietà dei relativi modelli. È possibile animare direttamente proprietà di primitive, ma generalmente è più semplice animare trasformazioni che modificano la posizione o l'aspetto di modelli. Poiché le trasformazioni possono essere applicate a oggetti Model3DGroup oltre che a singoli modelli, è possibile applicare un insieme di animazioni a un elemento figlio di un oggetto Model3DGroup e un altro insieme di animazioni a un gruppo di oggetti figlio. Inoltre, è possibile realizzare numerosi effetti visivi animando le proprietà dell'illuminazione della scena. È infine possibile scegliere di animare la proiezione stessa animando la posizione della fotocamera o il campo visivo. Per informazioni di base sul sistema di temporizzazione e di animazione WPF, vedere gli argomenti Cenni preliminari sull'animazione, Cenni preliminari sugli storyboard e Cenni preliminari sugli oggetti Freezable.
Per animare un oggetto in WPF, creare una sequenza temporale, definire un'animazione (che rappresenti una modifica reale del valore di alcune proprietà nel tempo) e specificare la proprietà alla quale applicare l'animazione. Poiché tutti gli oggetti in una scena 3-D sono elementi figlio di Viewport3D, le proprietà interessate da qualsiasi animazione che si desidera applicare alla scena sono proprietà di proprietà di Viewport3D.
Si supponga di voler fare in modo che un modello oscilli sul posto. È possibile scegliere di applicare un oggetto RotateTransform3D al modello e animare l'asse di rotazione da un vettore a un altro. Nell'esempio di codice riportato di seguito viene illustrata l'applicazione di un oggetto Vector3DAnimation alla proprietà Axis dell'oggetto Rotation3D della trasformazione, presupponendo che RotateTransform3D sia una delle numerose trasformazioni applicate al modello con un oggetto TransformGroup.
'Define a rotation
Dim myRotateTransform As New RotateTransform3D(New AxisAngleRotation3D(New Vector3D(0, 1, 0), 1))
//Define a rotation
RotateTransform3D myRotateTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 1));
Dim myVectorAnimation As New Vector3DAnimation(New Vector3D(-1, -1, -1), New Duration(TimeSpan.FromMilliseconds(5000)))
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever
Vector3DAnimation myVectorAnimation = new Vector3DAnimation(new Vector3D(-1, -1, -1), new Duration(TimeSpan.FromMilliseconds(5000)));
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever;
myRotateTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AxisProperty, myVectorAnimation)
myRotateTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AxisProperty, myVectorAnimation);
'Add transformation to the model
cube1TransformGroup.Children.Add(myRotateTransform)
//Add transformation to the model
cube1TransformGroup.Children.Add(myRotateTransform);
Aggiungere contenuto tridimensionale alla finestra
Per eseguire il rendering della scena, aggiungere modelli e luci a un oggetto Model3DGroup, quindi impostare Model3DGroup come proprietà Content di un oggetto ModelVisual3D. Aggiungere ModelVisual3D all'insieme Children di Viewport3D. Aggiungere fotocamere a Viewport3D impostandone la proprietà Camera.
Infine, aggiungere Viewport3D alla finestra. Quando si include Viewport3D come contenuto di un elemento di layout quale Canvas, specificare le dimensioni di Viewport3D impostandone le proprietà Height e Width (ereditate da FrameworkElement).
<UserControl x:Class="HostingWpfUserControlInWf.UserControl1"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
>
<Grid>
<!-- Place a Label control at the top of the view. -->
<Label
HorizontalAlignment="Center"
TextBlock.TextAlignment="Center"
FontSize="20"
Foreground="Red"
Content="Model: Cone"/>
<!-- Viewport3D is the rendering surface. -->
<Viewport3D Name="myViewport" >
<!-- Add a camera. -->
<Viewport3D.Camera>
<PerspectiveCamera
FarPlaneDistance="20"
LookDirection="0,0,1"
UpDirection="0,1,0"
NearPlaneDistance="1"
Position="0,0,-3"
FieldOfView="45" />
</Viewport3D.Camera>
<!-- Add models. -->
<Viewport3D.Children>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup >
<Model3DGroup.Children>
<!-- Lights, MeshGeometry3D and DiffuseMaterial objects are added to the ModelVisual3D. -->
<DirectionalLight Color="#FFFFFFFF" Direction="3,-4,5" />
<!-- Define a red cone. -->
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="0.293893 -0.5 0.404509 0.475528 -0.5 0.154509 0 0.5 0 0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 0.475528 -0.5 0.154509 0.475528 -0.5 -0.154509 0 0.5 0 0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 0.475528 -0.5 -0.154509 0.293893 -0.5 -0.404509 0 0.5 0 0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 0.293893 -0.5 -0.404509 0 -0.5 -0.5 0 0.5 0 0 -0.5 -0.5 0 0.5 0 0 0.5 0 0 -0.5 -0.5 -0.293893 -0.5 -0.404509 0 0.5 0 -0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 -0.293893 -0.5 -0.404509 -0.475528 -0.5 -0.154509 0 0.5 0 -0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 -0.154509 -0.475528 -0.5 0.154509 0 0.5 0 -0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 0.154509 -0.293892 -0.5 0.404509 0 0.5 0 -0.293892 -0.5 0.404509 0 0.5 0 0 0.5 0 -0.293892 -0.5 0.404509 0 -0.5 0.5 0 0.5 0 0 -0.5 0.5 0 0.5 0 0 0.5 0 0 -0.5 0.5 0.293893 -0.5 0.404509 0 0.5 0 0.293893 -0.5 0.404509 0 0.5 0 0 0.5 0 "
Normals="0.7236065,0.4472139,0.5257313 0.2763934,0.4472138,0.8506507 0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 -0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.5308242,0.4294462,0.7306172 0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.7236065,0.4472139,0.5257313 -0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.858892,0.429446,0.279071 -0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.8944269,0.4472139,0 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.858892,0.429446,-0.279071 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.7236065,0.4472139,-0.5257313 -0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.5308242,0.4294462,-0.7306172 -0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.2763934,0.4472138,-0.8506507 -0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 -0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.5308249,0.4294459,-0.7306169 0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.7236068,0.4472141,-0.5257306 0.5308249,0.4294459,-0.7306169 0.7236068,0.4472141,-0.5257306 0.8588922,0.4294461,-0.27907 0.5308249,0.4294459,-0.7306169 0.7236068,0.4472141,-0.5257306 0.8944269,0.4472139,0 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0 0.858892,0.429446,0.279071 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0 0.7236065,0.4472139,0.5257313 0.858892,0.429446,0.279071 0.7236065,0.4472139,0.5257313 0.5308242,0.4294462,0.7306172 0.858892,0.429446,0.279071 " TriangleIndices="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 " />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush
Color="Red"
Opacity="1.0"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
</GeometryModel3D>
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
</Viewport3D>
</Grid>
</UserControl>
Vedere anche
Riferimenti
Concetti
Cenni preliminari sulle trasformazioni tridimensionali
Ottimizzazione delle prestazioni tridimensionali di WPF
Cenni preliminari sugli oggetti Shape e sulle funzionalità di disegno di base di WPF
Disegnare con oggetti Image, Drawing e Visual