Dieser Artikel wurde maschinell übersetzt.

Silverlight 3D

Entwickeln von 3D-Objekten in Silverlight

Rajesh Lal

In diesem Artikel zeige ich Ihnen wie 3D-Objekte in Silverlight entwickelt.Ich werde beginnen mit einer kurzen Hintergrund auf 3D und dann betrachten Sie einige der erweiterten Features in Silverlight verfügbar, die Erstellung und Anzeige von 3D-Objekten.Ich nehmen Sie ein einfaches Beispiel für einen Cube und zeigen Ihnen drei verschiedene Möglichkeiten zum Erstellen von 3D-Transformationen.Ich werde auch erklären, welche Schlüsselelemente muss ein 3D-Objekt auf einem Computerbildschirm angezeigt werden.Zum Schluss werde ich untersuchen, wie Silverlight 5 können Sie das hinausgehen, was heute zur Verfügung steht und wesentlich umfangreichere 3D-Objekte erstellen.

Silverlight unterstützt ein rechtshändiges Koordinatensystem, d. h. die positiven Z-Achse in Richtung des Betrachters zeigt (siehe Abbildung1).Es gibt drei Hauptelemente der 3D, die erforderlich sind, um ein Objekt auf dem Bildschirm angezeigt:

  • Perspektive
  • Transformation
  • Wirkung von Licht

A Reference Cube, Showing Sides with PerspectiveAbbildung 1 A Reference Würfel, Anzeigen von Seiten mit Perspektive

Perspektive bedeutet, dass Teile von Objekten, die näher an uns größer als die angezeigt, die weiter entfernt sind.Z. B. in Abbildung 1, Seite bd größer als die Seite sieht Fh.Im wirklichen Leben-Perspektive erstellt einen Fluchtpunkt, d. h., wenn die Linien zu erweitern Ae, bf, cg und dh auf der Z-Achse, treffen sie weit zurück an einem beliebigen einzelnen Punkt.

Der zweite Aspekt ist die Transformation.Ein 3D-Objekt, bei der Anzeige auf einem Bildschirm sollten Bewegung in den dreidimensionalen Raum in alle Richtungen zulassen.Es kann in jeder einzelnen Achse verschoben werden – für Größe skaliert – unter Beibehaltung der Perspektive intakt.Es kann sein, um 360 Grad gedreht, in dem alle Achsen: X, y und Z.Flexibilität einem 3D-Objekts der muss für die Wiedergabe auf dem Bildschirm.

Das letzte Element der 3D ist die Wirkung von Licht.Licht in 3D erstellt Schattierung ist in der Nähe einer Lichtquelle heller und mit Abstand ausgeblendet wird.In 3D-Rendering sind die beiden gängigen Arten von Schattierung, Schattierung "flat" und "Farbverlauf" Schattierung.Ich werde erklären, wie sie später unterscheiden.Licht wird auch einen Schatten auf den Seiten gegenüber der Lichtquelle erstellen.

In den nächsten Beispielen werde ich drei verschiedene Arten untersuchen, in denen Sie 3D-Objekte in Silverlight erstellen können:

  • Perspektive verwenden 3D
  • Verwenden mehrere Frames und einen Zeitgeber
  • Verwenden von primitiven mit XNA-Bibliothek

In der ersten Methode wird ein Objekt mithilfe von zweidimensionale Elementen erstellt, aber es sieht aus und verhält sich so, als handele es sich im 3D-Raum.Perspektive-3D ist eine besondere Art von Transformation-Funktion, die in Silverlight 4, die für grundlegende Transformationen, z. B. Drehung, Skalierung und Übersetzung in einem dreidimensionalen Raum ermöglicht hinzugefügt.Die zweite Methode ist die brute-Force-Methode, dem nicht das 3D-Objekt zu erstellen, sondern stattdessen erstellt die endgültige Ausgabe-Frames für eine bestimmte Transformation und zeigt sie mithilfe eines Zeitgebers.Die letzte Methode ist die Erstellung von einem rich 3D-Objekt Stück für Stück mit primitiven (eine Liste der Dreiecke) mit XNA-Bibliotheken, die in Silverlight 5 erhältlich sein wird.Lassen Sie uns beginnen.

Erstellen eines Cubes mit Perspektive

Silverlight-4 unterstützt eine PlaneProjection-Klasse (finden Sie unter Abbildung 2), wie im Klassendiagramm angezeigt, für die Projektion-Eigenschaft, der UI-Element verwendet werden können.PlaneProjection-Klasse ermöglicht Perspektive 3D-Transformationen auf das Element der Benutzeroberfläche.Obwohl es direkt für das Erstellen eines 3D-Objekts nicht zulässt, können Sie mehrere "Wände" ein Objekt erstellen und es in einem dreidimensionalen Raum transformieren.

The PlaneProjection ClassAbbildung 2 die PlaneProjection-Klasse

PlaneProjection-Klasse ermöglicht LocalOffset und GlobalOffset, die verwendet werden, bzw. ein Objekt auf sich selbst und in Bezug auf ein anderes Element in der globalen Raum übersetzt.RotationX, RotationY und RotationZ ermöglichen drehen das Element in der x-, ermöglicht y- und Z-Achse und CenterOfRotation einen Mittelpunkt in Bezug auf die Element-Ebene.

In meinem Beispiel zum Erstellen eines "Cubes" ich vier Seiten des Cubes zu erstellen und verschieben Sie sie in einem dreidimensionalen Raum durch ihre PlaneProjection-Eigenschaften festlegen wie in gezeigt Abbildung 3.

Abbildung 3 Festlegen von PlaneProjection Eigenschaften

<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 Abbildung 4, werden die Seiten gedreht, um 90,-90 und-180 Grad, um die oberen, unteren und Vorderseite Projektion Ebenen des Cubes zu erstellen. Der Wert der CenterofRotationZ von 125 erstellt den Mittelpunkt, durch den alle die Flächen entlang der Z-Achse gedreht werden können.

Projecting the Sides to Simulate a 3D Wall
Abbildung 4 Seiten zu simulieren, 3D Wand projizieren

Nachdem der Cube erstellt wird, verwenden die Projektionsebene ich brauche So drehen Sie es durch die x-, y- und Z-Achse. Dies ist, wo ich das Storyboard-Objekt in Silverlight verwenden. Ich drei Storyboards, eines für jede Achse erzeugen, wie in gezeigt Abbildung 5.

Abbildung 5 drehen den Cube mit Storyboards

<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>

Jedes Drehbuch drehen ich jede der vier Projektion Flugzeuge, die Cubestruktur intakt zu halten. Beachten Sie, dass für die x Achse drehen, der RotationX-Wert aus dem ursprünglichen RotationX-Wert der Ebene beginnt, und ein anderes 360 Grad für ProjectionFront, geht, so dass es bei-180 Grad beginnt und bis 180 Grad geht. Wie Sie, in sehen können Abbildung 6, der Cube ist bereit für die Rotation entlang der x-, y- und Z-Achse, entlang einer beliebigen Achse verschoben werden können und Färbung Seiten unterstützt.

The Cube, Ready for Rotation
Abbildung 6 des Cubes bereit für die Rotation

In diesem Beispiel konnte ich einfach einen Cube zu erstellen und es in einem dreidimensionalen Raum ohne viel Code umzuwandeln. Dies ist die eigentliche Stärke der 3D-Transformation Perspektive. Für grundlegende Operationen 3D sollten Sie diese Option verwenden. Allerdings kommt es mit einer Reihe von Nachteilen. Erweiterte 3D-Objekte benötigt, die Anzahl der Ebenen der Projektion müssen Sie manuell herausfinden, bis die Winkel zwischen den einzelnen Projektionsebene und die CenterOfRotation und deren Einstellungen drastisch erhöhen können. Hier ein weiteres Problem ist, dass die Drehung des 3D-Objekts Storyboards, abhängt, die es CPU-Intensive macht; die GPU verwenden nicht, um das Objekt zu rendern. Ein weiteres Problem bei diesem Ansatz ist, dass Sie auch die Rückseite des Würfels rendern, auch wenn es nicht sichtbar ist – nicht für einen optimalen Ansatz.

Das dritte Hauptelement für die Anzeige von 3D-Objekten auf dem Bildschirm erforderlich ist, die Wirkung von Licht. Im wirklichen Leben haben Sie Licht, wie Sie, die in einem dreidimensionalen Raum auf dem Bildschirm simulieren tun? Wie bereits erwähnt, sind zwei verbreitete Methoden zu tun, normale Schattierung und Farbverlauf Schattierung.

Normale Schattierung die Oberfläche der Ebene berücksichtigt und Schattierung durchschnittliche entlang der Ebene. Gradientenschattierung (Gouraud-Shading) mithilfe eines Farbverlaufs schattieren die Fläche und berücksichtigt dabei die Scheitelpunkte des Flugzeugs. Das Flugzeug nicht flach, sondern eher "Glatt" schattierte, basierend auf verschiedenen Scheitelpunkt Farben schattiert.

In diesem Beispiel die Ebenen können für die Farbe zu füllen (flache Schattierung) sowie die graduelle Füllung (Gradientenschattierung), die benutzt werden kann, um den Lichteffekt zu simulieren. Ich werde diese später behandelt. Eine schnelle Möglichkeit zum Simulieren des Lichteffekts wird durch einen radialen Farbverlauf Rechteck mit Transparenz, die mit dem folgenden Code nach dem 3D Objekt überlappen:

<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>

Erstellen eines Cubes, die Verwendung von Frames

Die zweite Möglichkeit, erstellen Sie eine Erfahrung 3D wird mithilfe der letzten Frames. Hier erstellen Sie nicht, das 3D-Objekt selbst, sondern beginnen Sie mit der erforderlichen endgültigen Ausgabe und als individuelle Frames zu exportieren. Eine Anzahl von Softwareprogrammen für die 3D-Modellierung können Sie zum Erstellen von 3D-Objekten und Transformationen, die als mehrere Frames exportiert und anschließend in Silverlight importiert werden können.

In diesem Beispiel ich nehmen Sie eine einfachen Cube Animation und seine Drehung auf das X, y und Z-Achse in mehrere Frames Bilder exportieren. Abbildung 7 zeigt acht verschiedene Frames eine Cube-Rotation auf der x-Achse. In diesem Beispiel ich einen minimalen Satz von Frames verwenden, um eine Rotation Cube zu erstellen, aber mehr Frames pro Sekunde eine glattere und nahtlose Drehung zu erstellen.

Eight Different Frames Simulating Rotation in the X Axis
Abbildung 7 acht verschiedene Frames simulieren die Rotation auf der X-Achse

Um die Drehung in Silverlight zu simulieren, verwende ich einen Zeitgeber, wie im folgenden Code gezeigt:

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;
}

Beachten Sie, dass dies eine vereinfachte Version ist der Möglichkeiten mit dieser Methode. Hier kann ich verwende exportierten Bilder der Einfachheit halber, aber eine Anzahl von 3D Software ermöglichen, für den XAML-Export, die Polygone mit Farbe und Farbverläufen anstelle von Bildern, die eine nahtlose und gleichmäßigere Animation erstellt. Der Zeitgeber kann auch durch Storyboards mit Animationen ersetzt werden.

Dieser Ansatz ist einfach. Sie haben eine bestimmte Transformation-Anforderung mit einem bestimmten 3D-Objekt. Sie müssen keine Sorgen machen über das 3D-Objekt erstellen und diese Technik kann verwendet werden, um jede Art von 3D-Objekt zu erstellen – Sie sind nicht mehr auf einen einfachen Cube beschränkt. Diese Methode kann für alle Arten von Transformationen verwendet werden. Sie können zu übersetzen, drehen und skalieren hochentwickelte 3D-Objekte. Es simuliert auch die Wirkung von Licht, das auch direkt aus der Modellierung Software übersetzt.

Die größte Einschränkung dieses Ansatzes ist die Flexibilität des Programmierens in Abhängigkeit des 3D-Objekts. Sobald Sie das 3D-Objekt exportiert haben, wird die statische Codeanalyse, die schwierig, Code gegen sein kann generiert. Sie können nicht das Objekt in Bezug auf andere Elemente in der Silverlight-Anwendung verschieben. Ein weiterer Nachteil ist, dass die Anzahl der Frames benötigt, mit jeder Transformation linear erhöht wird. Abgesehen davon, das Rendering findet auf die CPU größer Animationen mit einer größeren Anzahl von Frames würde eine Leistung getroffen haben.

Dies führt zu der dritte Ansatz der Verwendung von XNA-Bibliothek in den kommenden Silverlight-5, die, wie Sie sehen werden, die meisten Probleme mit der ersten beiden Ansätzen überwindet. Aber davor, sprechen wir über mathematisch wie ein 3D-Objekt in einem zweidimensionalen Bildschirm übersetzt – der Genius-Logik hinter 3D.

Grundlegendes zu World, Ansicht und Projektionsmatrix

Um das Objekt anzuzeigen, müssen Sie verstehen, drei Hauptkonzepte oder "Leerzeichen" und wie das Objekt aus seiner eigenen Objektraum auf dem Bildschirm zugeordnet wird:

  • World
  • View
  • Projektion

Abbildung 8 zeigt die Reihenfolge, in dem ein Objekt auf dem Bildschirm zugeordnet wird.

The Order in Which a 3D Object Is Mapped to the Screen
Abbildung 8 die Reihenfolge, in der ein 3D-Objekt zugeordnet ist, auf dem Bildschirm

Der erste Satz von Koordinaten für ein 3D-Objekt ist die x-, y- und Z-Koordinaten in den Objektraum (auch als modelspace). Diese Koordinaten sind relativ zueinander mit ihren Mittelpunkten (0, 0, 0). Denken Sie daran, mit der rechten kartesischen Koordinaten, die positive Z-Achse in Richtung des Betrachters.

Für einen Cube 3D werden oben rechts auf der Vorderseite (1,1,1), und die unteren linken Ecke an der Rückwand werden (-1,-1,-1), siehe in Abbildung 9. In den Objektraum Koordinaten sind relativ zueinander und ihre Position kann nur zwischen-1 und + 1. Dem Cube um 75 Prozent des Speicherplatzes-Objekt verwenden, muss ich bei jedem multiplizieren Koordinieren von.75, also die neue b(.75,.75,.75) werden und die neue g werden (-.75,-.75,-.75).

Coordinates in 3D Space
Abbildung 9 Koordinaten im 3D-Raum

Wenn das Objekt auf der Welt-Raum gelegt wird, nicht das Objekt selbst verschoben, aber eher in Bezug auf die globalen Koordinaten multipliziert seine Koordinaten mit die Weltmatrix zugeordnet. Im Raum der Welt können Sie das 3D-Objekt transformieren, indem die Koordinaten übersetzt das Objekt verschieben, Ändern der Größe skalieren und ändern den Winkel, um das Objekt drehen. Koordinaten des Objekts, im Raum der Welt ausgedrückt werden, müssen Sie jede Vertexposition mit die Weltmatrix multiplizieren:

Globale Koordinaten Object = Objektkoordinaten * Weltmatrix

Das nächste Element ist die Kameraansicht, die den Punkt bezeichnet, von dem Sie das Objekt suchen. Dieser Punkt kann in einem dreidimensionalen Raum ändern, ohne die Koordinaten des eigentlichen Objekts in den Objektraum sowie Raum der Welt. Um die Koordinaten des Objekts in Bezug auf die Kameraansicht zu berechnen, multiplizieren Sie die Ansichtsmatrix mit Weltmatrix für das Objekt:

Koordinaten der Strukturansicht Objekt globale Koordinaten = * Ansichtsmatrix

Schließlich muss die Objektansicht des auf dem Bildschirm gerendert werden; Dies ist, wo Sie müssen die perspektivische Ansicht erstellt aufgrund der Entfernung zu berechnen. So weit mein Objekt befindet sich in Parallelprojektion (die Seiten sind parallel), aber ich brauche, um das Objekt anzuzeigen, in der perspektivischen Projektion (die Seiten-Zusammenführung zu einem Fluchtpunkt hin), so dass ich das Produkt aus des Objekts Ansichtsmatrix und Weltmatrix mit die Projektionsmatrix multiplizieren:

Objekt endgültige Koordinaten globalen Koordinaten = * Ansichtsmatrix * Projektionsmatrix

Dies ist die endgültige Position des 3D-Objekts, auf dem Bildschirm, die auch die WorldViewProjection aufgerufen wird.

Die Matrix

Eine Matrix-Struktur Microsoft.Xna.Framework, ist in Silverlight 5 enthalten.  Es wurde eine homogene 4 x 4-Matrix mit 16 Gleitkommazahlen als Felder und eine Reihe von Methoden zum Generieren einer Transformationsmatrix (finden Sie unter Abbildung 10).

A Silverlight 5 Matrix Struct
Abbildung 10 eine Silverlight-5-Matrix-Struktur

Die ersten drei Zeilen und Spalten (M11 - M33) dienen zum Skalieren und Rotieren-Transformationen und die vierte Zeile (M41-M43) wird für die Übersetzung verwendet (siehe Abbildung 11).

Abbildung 11 4 x 4-Matrix

M11 M12 M13 M14
M21 M22 M23 M24
M31 M32 M33 M34
M41 M42 M43 M44

Zum besseren Verständnis die Matrix müssen Sie Mal sehen, wie es in Bezug auf eine Transformation verwendet wird. Es gibt fünf verschiedene Arten von Matrizen: 4 x 4-Matrix-Struktur, Identitätsmatrix, Verschiebungsmatrix, Scale-Matrix und Rotationsmatrix.

Identitätsmatrix (siehe in Abbildung 12) ist die Matrix Einheit Größe 4, und dies wird die ursprüngliche Position des 3D-Objekts im Raum der Welt. Wenn Sie eine Matrix mit der Identitätsmatrix multiplizieren, erhalten Sie ohne Änderung die ursprüngliche Matrix. Matrix-Struktur bietet eine einfache Eigenschaft, die ein Matrix.Identity zurückgibt.

Abbildung 12 die Identitätsmatrix

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Geben Sie eine Methode namens Matrix.CreateScale, um das Matrixobjekt zu skalieren. Die Scale-Matrix wird zum Skalierungstransformation auf ein 3D-Objekt so Wenn Sie ein Objekt mit der Scale-Matrix multiplizieren (finden Sie unter Abbildung 13), die resultierende Matrix entsprechend ändert.

Abbildung 13 die Scale-Matrix

SX 0 0 0
0 SY 0 0
0 0 Sz 0
0 0 0 1

Das Matrix-Objekt bietet auch eine Matrix.CreateTranslate-Methode zum Verschieben des Objekts im Welt-Raum. Beim Multiplizieren mit der Übersetzungsmatrix (finden Sie unter in Abbildung 14), das Objekt im Welt-Raum übersetzt.

Abbildung 14 die Übersetzungsmatrix

1 0 0 0
0 1 0 0
0 0 1 0
TX Ty Tz 1

Für die Rotation gibt es mehrere Methoden. Die Matrix.CreateFromYawPitchRoll-Methode wird verwendet, für jede Achse für ein schwebendes Zahlenwert drehen. Die Methoden Matrix.CreateRotationX, Matrix.CreateRotationY und Matrix.CreateRotationZ sind für das Drehen des Objekts entlang der x-, y- und Z-Achse. Die Rotationsmatrix hinsichtlich Winkel Theta M11-M33-Elemente umfasst, wie in dargestellt Abbildung 15.

Abbildung 15 Rotationsmatrix entlang der X-, Y- und Z-Achse

1 0 0 0
0 COs θ Sinus θ 0
0 -Sinus θ COs θ 0
0 0 0 1
X-Drehung      
COs θ 0 Sinus θ 0
0 1 0 0
-Sinus θ 0 COs θ 0
0 0 0 1
Y-Drehung      
COs θ Sinus θ 0 0
-Sinus θ COs θ 0 0
0 0 1 0
0 0 0 1
Z-Drehung      

Lernen die 3D-Rohrleitung für Silverlight XNA

Silverlight-5 mit XNA-Bibliotheken bietet einen schrittweisen Prozess zum Erstellen von 3D-Objekten mit Scheitelpunktkoordinaten der auf dem Bildschirm gerendert. Dies kann in fünf Hauptschritte unterteilt werden (siehe Abbildung 16) im Zusammenhang mit die hier dargestellten Komponenten:

  1. Vertexpuffer
  2. WorldViewProjection-Koordinaten
  3. Schattierung: Scheitelpunkt, Pixel und Textur
  4. Grafische Verarbeitung: Rastern, clip und ausgemerzte
  5. Endgültige Ausgabe: Einzelbild-Puffer

Creating 3D Objects with the Silverlight 5 XNA Libraries
Abbildung 16 Erstellen von 3D-Objekten mit den Silverlight 5 XNA-Bibliotheken

Jeder Schritt und seiner Komponenten wird kurz erläutert.

Vertexpuffer bei der Erstellung eines Vertexpuffers aus der Auflistung der Scheitelpunkt, der erste Schritt ist, um das Skelett des 3D-Objekts zu erstellen, mithilfe eines Satzes von Vertices. Jeder Eckpunkt enthält mindestens die x-, y- und z koordiniert, aber normalerweise hat auch andere Eigenschaften wie Farbe und Struktur. Diese Sammlung von Scheitelpunkten wird dann verwendet, einen Vertexpuffer erstellen, die mit dem nächsten Schritt im Prozess geht.

Koordinaten des WorldViewProjection letzten Koordinaten durch Multiplikation von Eckpunkten mit World, Ansichts-und Projektionsmatrix. Hier wird das Objekt-Beziehung mit der Welt-Raum, Ansichts- und Projektionsmatrix berechnet und angewendet. Überprüfen Sie die letzten beiden Abschnitten für weitere Details. Sobald Sie die endgültigen Koordinaten haben, und klicken Sie dann der tatsächliche Schattierung Prozess stattfindet.

Shading- Vertex Schattierung, Pixel-Schattierung und Schattierung der Textur verwendet. In diesem Schritt vom ersten Scheitelpunkt Codefarben erfolgt und dann die x-Pixel-Schattierung geschieht. Textur-Schattierung wird auch in diesem Schritt angewendet. Diese endgültigen schattierten Koordinaten werden dann verwendet, erstellen Sie einen Framepuffer.

Rastern, Clip und ausgemerzte während der Rasterung ein Bildes in Pixel umgewandelt wird, und klicken Sie dann Clip und ausgemerzte entfernen das Skelett des 
object, zusammen mit ausgeblendeten und nicht sichtbare Ebenen verwendet. Dies ist schließlich auf dem Bildschirm gerendert.

Frame Buffer nach das Bild gerastert wird abgeschnitten und aus, Einzelbild-Puffer wird generiert, die wird dann auf dem Bildschirm für die Anzeige gesendet.

Erstellen eines Cubes mit primitiven

Lassen Sie mit dem Wissen von Matrizen, World, Ansicht, Projektion und die 3D Pipeline in Silverlight-5 mit XNA-Bibliotheken uns einen 3D Cube erstellen, und sehen Sie, wie alles zusammen ausgeliefert.

Der wichtigste Vorteil dieses Ansatzes ist die GPU-Beschleunigung, die Hardware-Beschleunigung, Freigeben von die CPU des 3D-Objekts Rendering ermöglicht. Dies wird durch Festlegen von EnableGPUAcceleration-Parameter im Object-Tag in der HTML-Code verwendet, um das Silverlight-Plug-in, zu konfigurieren, wie hier gezeigt auf True aktiviert:

<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, füge ich ein DrawingSurface-Objekt innerhalb des Rasters, die zum Rendern von 3D in Silverlight mit Hilfe der DrawPrimitives-Methode des GraphicsDevice-Objekts verwendet wird (siehe in Abbildung 17):

<DrawingSurface Loaded="OnLoad" SizeChanged="OnSizeChanged" Draw="OnDraw"/>

The DrawPrimitives Method of the GraphicsDevice Class
Abbildung 17 DrawPrimitives-Methode der Klasse GraphicsDevice

Ich verwende drei Methoden in der DrawingSurface-Klasse erstellen und Rendern des Cubes. Die OnLoad-Methode wird verwendet, für den Cube zu erstellen und initialisieren alle Shader und die Ansichtsmatrix, das in dieser Anwendung nicht geändert wird. Beachten Sie, dass das 3D-Objekt an (0,0,0) zentriert wird mit 75 Prozent des Speicherplatzes Objekt mit Koordinaten von (.75,.75,.75) (-.75,-.75,-.75). Ich werde hier erstellen einen Vertexpuffer zu halten die Vertex-Auflistung, und initialisieren die ShaderStream, PixelStream und ImageStream-Streams, die alle in der Schattierung Schritt verwendet werden. Ich werde auch die Ansichtsmatrix initialisieren, die den Winkel ist, an dem die Kamera, auf das Objekt mithilfe von CameraPosition und CameraTarget mit dem Parameter Vector3.Up suchen (d. h., dass die Kamera nach oben sucht). Dieser Code wird angezeigt, in Abbildung 18.

Abbildung 18 ShaderStream, PixelStream und ImageStream einrichten

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);
}

Der nächste Schritt ist die Erstellung den Vertexpuffer für den Cube 3D. Ich erstelle eine CreateCube-Methode, wie in gezeigt in Abbildung 19 ein VertexBuffer zurückgibt. Ich werde zwei Rechtecke in den dreidimensionalen Raum mit ABCD, aus denen die vordere Fläche der Cube und EFGH der Rückseite des Cubes erstellen. Ich verwende die VertexPositionColor-Struktur, erstellen Sie eine Auflistung der Scheitelpunkte und die Farben, die jeder von ihnen zugeordnet.

Abbildung 19 VertexBuffer erstellen, in der CreateCube-Methode

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;
}

Die OnSizeChanged-Methode der Zeichenoberfläche wird verwendet, um die Projektion und das Seitenverhältnis des Bildschirms auf der Grundlage von Flächenbemaßung zu aktualisieren:

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);
}

Die letzte Methode ist die OnDraw, die dynamische Transformation auf dem 3D Cube ermöglicht. Dies ist, wo ich mich Matrix.CreateScale, ändern Sie die Größe den Cube, Matrix.CreateFromYawPitchRoll, um es zu drehen und Matrix.CreateTranslate, um ihn zu verschieben bewerben. Hier wird die Matrix WorldViewProjection berechnet und an die VertexShader-Methode für die Schattierung die Scheitelpunkte, die wiederum auf PixelShader schattieren "Wände" des Cubes überträgt. Dies kann wiederum auch an TextureShader, gesendet werden auf einem Bild basiert. Schließlich ruft das GraphicDevice-Objekt eine DrawPrimitives-Methode, um die Ausgabe-Frames zu rendern, wie in gezeigt in Abbildung 20.

Abbildung 20 Aufrufen der DrawPrimitives-Methode, um die Ausgabe rendern

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();
}

Dadurch werden dynamisch den endgültigen 3D Cube auf der Zeichenoberfläche (finden Sie unter Abbildung 21).

The Final 3D Cube on the Drawing Surface
Abbildung 21 endgültig 3D Cube auf der Zeichenoberfläche

Dieser Ansatz wird die GPU-Beschleunigung verwendet und nicht gerendert werden, die Seiten des 3D-Objekts, die ausgeblendet sind oder die Rückseite, im Gegensatz zu meinem ersten Ansatz. Dies verwendet auch den Frames Puffer im Arbeitsspeicher zum Rendern der endgültigen Ausgabe wie der zweite Ansatz, aber vollständige Kontrolle und Flexibilität der Programmierung für das Objekt wie bei der OnDraw-Methode.

Sie haben nun drei verschiedene Möglichkeiten zum Erstellen von 3D-Objekten in Silverlight mit eigenen Stärken und Schwächen gelernt. Wenn Sie die Welt der 3D in Silverlight ausprobieren, sollte diese nützliche Ergänzungen zu der Toolbox.

Rajesh Lal ist begeistert von Silverlight und Web-Technologien. Er hat mehrere Bücher über Windows-Minianwendung, Web-Widgets und mobile Web-Technologien, einschließlich einer bevorstehenden Buchs "Spaß mit Silverlight 4" (CreateSpace, 2011) geschrieben. Weitere Informationen erhalten Sie unter mconnectrajesh@hotmail.com , oder besuchen Sie silverlightfun.com.

Dank der folgenden technischen Experten für die Überprüfung dieses Artikels: Marc Clifton, Rick Kingslan und Josh Smith