Omówienie grafiki 3D

Funkcja 3D w programie Windows Presentation Foundation (WPF) umożliwia deweloperom rysowanie, przekształcanie i animowanie grafiki 3D zarówno w znaczników, jak i w kodzie proceduralnym. Deweloperzy mogą łączyć grafikę 2D i 3D w celu tworzenia zaawansowanych kontrolek, udostępniania złożonych ilustracji danych lub ulepszania środowiska użytkownika interfejsu aplikacji. Obsługa 3D w WPF nie została zaprojektowana w celu zapewnienia w pełni funkcjonalnej platformy do tworzenia gier. Ten temat zawiera omówienie funkcji 3D w systemie graficznym WPF.

3D w kontenerze 2D

Zawartość graficznej 3D w WPF jest hermetyzowana w elemedycie , Viewport3Dktóry może uczestniczyć w dwuwymiarowej strukturze elementów. System graficzny traktuje Viewport3D jako dwuwymiarowy element wizualny, jak wiele innych w WPF. Viewport3D funkcja jako okno — widokport — do trójwymiarowej sceny. Dokładniej jest to powierzchnia, na której jest projektowana scena 3D.

W konwencjonalnej aplikacji 2D użyj Viewport3D innego elementu kontenera, takiego jak Grid lub Canvas. Chociaż można używać Viewport3D z innymi obiektami rysunkowymi 2D w tym samym grafie sceny, nie można przeplatać obiektów 2D i 3D w obiekcie Viewport3D. W tym temacie skupimy się na tym, jak narysować grafikę 3D wewnątrz elementu Viewport3D.

Przestrzeń współrzędna 3-W

Układ współrzędnych WPF grafiki 2D lokalizuje początek w lewym górnym rogu obszaru renderowania (zazwyczaj ekran). W systemie 2D dodatnie wartości osi x są kontynuowane do prawej i dodatniej wartości osi y w dół. Jednak w układzie współrzędnych 3D źródło znajduje się w środku obszaru renderowania, z dodatnimi wartościami osi x przechodzącymi do prawej, ale dodatniej wartości osi y w górę, a dodatnie wartości osi Z są kontynuowane na zewnątrz od źródła w kierunku osoby przeglądanej.

Coordinate systems
Konwencjonalne reprezentacje układu współrzędnych 2D i 3D

Przestrzeń zdefiniowana przez te osie to nieruchoma rama odniesienia dla obiektów 3D w WPF. Podczas tworzenia modeli w tej przestrzeni i tworzenia świateł i kamer do ich wyświetlania warto odróżnić tę nieruchomą ramę odniesienia lub "przestrzeń światową" z lokalnej ramki odniesienia tworzonej dla każdego modelu podczas stosowania przekształceń do niego. Należy również pamiętać, że obiekty w przestrzeni światowej mogą wyglądać zupełnie inaczej lub w ogóle nie być widoczne, w zależności od ustawień światła i aparatu, ale pozycja aparatu nie zmienia lokalizacji obiektów w przestrzeni światowej.

Aparat i projekcje

Deweloperzy pracujący w 2D są przyzwyczajeni do pozycjonowania elementów pierwotnych rysunku na ekranie dwuwymiarowym. Podczas tworzenia sceny 3D należy pamiętać, że naprawdę tworzysz reprezentację 2D obiektów 3D. Ponieważ scena 3D wygląda inaczej w zależności od punktu widzenia gapiów, musisz określić ten punkt widzenia. Klasa Camera umożliwia określenie tego punktu widzenia dla sceny 3D.

Innym sposobem zrozumienia, jak scena 3D jest reprezentowana na powierzchni 2D, jest opisanie sceny jako projekcji na powierzchni wyświetlania. Umożliwia ProjectionCamera określenie różnych projekcji i ich właściwości w celu zmiany sposobu, w jaki onlooker widzi modele 3D. A PerspectiveCamera określa projekcję, która foreshortens sceny. Innymi słowy, PerspectiveCamera zapewnia znikającą perspektywę punktu. Możesz określić położenie aparatu w przestrzeni współrzędnej sceny, kierunku i pola widoku dla kamery oraz wektor, który definiuje kierunek "w górę" w scenie. Na poniższym diagramie przedstawiono projekcję PerspectiveCamera.

Właściwości NearPlaneDistanceProjectionCamera i FarPlaneDistance ograniczają zakres projekcji aparatu. Ponieważ kamery mogą znajdować się w dowolnym miejscu na scenie, aparat może być rzeczywiście umieszczony wewnątrz modelu lub w pobliżu modelu, co utrudnia prawidłowe odróżnienie obiektów. NearPlaneDistance umożliwia określenie minimalnej odległości od kamery, poza którą obiekty nie będą rysowane. FarPlaneDistance Z drugiej strony pozwala określić odległość od kamery, poza którą obiekty nie zostaną narysowane, co gwarantuje, że obiekty zbyt daleko, aby były rozpoznawalne, nie zostaną uwzględnione w scenie.

Camera setup
położenie Aparat

OrthographicCamera określa ortogonalną projekcję modelu 3D na powierzchnię wizualizacji 2D. Podobnie jak inne kamery, określa położenie, kierunek widzenia i "kierunek w górę". W przeciwieństwie do PerspectiveCamerametody opisuje jednak projekcję, OrthographicCamera która nie obejmuje perspektywy dlahorteningu. Innymi słowy, opisuje pole wyświetlania, OrthographicCamera którego boki są równoległe, zamiast jednego, którego boki spotykają się w punkcie w aparacie. Na poniższej ilustracji przedstawiono ten sam model, który został wyświetlony przy użyciu elementów PerspectiveCamera i OrthographicCamera.

Orthographic and perspective projection
Projekcje perspektywiczne i ortograficzne

Poniższy kod przedstawia niektóre typowe ustawienia aparatu.

// 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;
' 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

Modele i elementy pierwotne siatki

Model3D jest abstrakcyjną klasą bazową, która reprezentuje ogólny obiekt 3D. Aby utworzyć scenę 3D, potrzebujesz niektórych obiektów do wyświetlenia, a obiekty tworzące graf sceny pochodzą z Model3D. Obecnie platforma WPF obsługuje modelowanie geometrii za pomocą polecenia GeometryModel3D. Właściwość Geometry tego modelu przyjmuje siatkę pierwotną.

Aby utworzyć model, zacznij od utworzenia pierwotnego lub siatki. Typ pierwotny 3D to kolekcja wierzchołków, które tworzą pojedynczą jednostkę 3D. Większość systemów 3D zapewnia typy pierwotne wzorowane na najprostszej zamkniętej postaci: trójkąt zdefiniowany przez trzy wierzchołki. Ponieważ trzy punkty trójkąta są współpłatne, można kontynuować dodawanie trójkątów w celu modelowania bardziej złożonych kształtów, nazywanych siatkami.

System WPF 3D obecnie udostępnia klasę MeshGeometry3D , która pozwala określić dowolną geometrię. Obecnie nie obsługuje wstępnie zdefiniowanych elementów pierwotnych 3D, takich jak sfer i formularze sześcienne. Rozpocznij tworzenie obiektu MeshGeometry3D , określając listę wierzchołków trójkątów jako jej Positions właściwość. Każdy wierzchołek jest określony jako Point3D. (W języku XAML określ tę właściwość jako listę liczb pogrupowanych w trzech, które reprezentują współrzędne każdego wierzchołka). W zależności od geometrii siatka może składać się z wielu trójkątów, z których część ma te same rogi (wierzchołki). Aby poprawnie narysować siatkę, WPF potrzebuje informacji o tym, które wierzchołki są współużytkowane przez trójkąty. Te informacje należy podać, określając listę indeksów trójkątów z właściwością TriangleIndices . Ta lista określa kolejność, w jakiej punkty określone na Positions liście określają trójkąt.

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

W poprzednim przykładzie Positions lista określa cztery wierzchołki, aby zdefiniować siatkę prostokąta. Właściwość TriangleIndices określa listę dwóch grup trzech indeksów. Każda liczba na liście odnosi się do przesunięcia na Positions liście. Na przykład pierwsze trzy wierzchołki określone przez Positions listę to (-1,-1,0), (1,-1,0)i (-1,1,0). Pierwsze trzy indeksy określone przez TriangleIndices listę to 0, 1 i 2, które odpowiadają pierwszemu, drugiemu i trzeciemu punktowi na Positions liście. W rezultacie pierwszy trójkąt składający się na model prostokąta będzie składał się z (-1,-1,0) do (1,-1,0)(-1,1,0), a drugi trójkąt zostanie określony podobnie.

Możesz kontynuować definiowanie modelu, określając wartości właściwości Normals i TextureCoordinates . Aby renderować powierzchnię modelu, system graficzny potrzebuje informacji o kierunku, w którym powierzchni znajduje się dany trójkąt. Wykorzystuje te informacje do wykonywania obliczeń oświetlenia dla modelu: powierzchnie bezpośrednio w kierunku źródła światła wydają się jaśniejsze niż te kątowe od światła. Chociaż WPF może określić domyślne wektory normalne przy użyciu współrzędnych położenia, można również określić różne wektory normalne, aby przybliżyć wygląd zakrzywionych powierzchni.

Właściwość TextureCoordinates określa kolekcję Points, która informuje system graficzny, jak mapować współrzędne, które określają, jak tekstura jest rysowana do wierzchołków siatki. TextureCoordinates są określane jako wartość z zakresu od zera do 1 włącznie. Podobnie jak w przypadku Normals właściwości, system graficzny może obliczyć domyślne współrzędne tekstury, ale można wybrać ustawienie różnych współrzędnych tekstury, aby kontrolować mapowanie tekstury, która zawiera część powtarzającego się wzorca, na przykład. Więcej informacji na temat współrzędnych tekstur można znaleźć w kolejnych tematach lub w zarządzanym zestawie SDK Direct3D.

W poniższym przykładzie pokazano, jak utworzyć jedną twarz modelu modułu w kodzie proceduralnym. Cały sześcian można narysować jako pojedynczy GeometryModel3D. W tym przykładzie twarz modułu jest odrębnym modelem, aby później zastosować oddzielne tekstury do każdej twarzy.

MeshGeometry3D side1Plane = new MeshGeometry3D();
Private side1Plane As 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))

'

Stosowanie materiałów do modelu

Aby siatka wyglądała jak obiekt trójwymiarowy, musi mieć zastosowaną teksturę, aby pokryć powierzchnię zdefiniowaną przez wierzchołki i trójkąty, aby można było je zapalić i rzutować przez aparat. W 2D używasz Brush klasy do stosowania kolorów, wzorców, gradientów lub innej zawartości wizualnej do obszarów ekranu. Wygląd obiektów 3D jest jednak funkcją modelu oświetlenia, a nie tylko koloru lub wzorca zastosowanego do nich. Rzeczywiste obiekty odzwierciedlają światło inaczej w zależności od jakości ich powierzchni: błyszczące i błyszczące powierzchnie nie wyglądają tak samo jak szorstkie lub matowe powierzchnie, a niektóre obiekty wydają się pochłaniać światło, podczas gdy inne świecą. Wszystkie te same pędzle można zastosować do obiektów 3D, które można zastosować do obiektów 2D, ale nie można ich zastosować bezpośrednio.

Aby zdefiniować cechy powierzchni modelu, WPF używa klasy abstrakcyjnej Material . Podklasy betonowe materiału określają niektóre cechy wyglądu powierzchni modelu, a każda z nich zapewnia również właściwość Brush, do której można przekazać SolidColorBrush, TileBrush lub VisualBrush.

  • DiffuseMaterial określa, że szczotka zostanie zastosowana do modelu tak, jakby model był oświetlony dyfuzornie. Korzystanie z dyfuzorów Najbardziej przypomina używanie pędzli bezpośrednio w modelach 2D; powierzchnie modelu nie odzwierciedlają światła, jakby błyszczące.

  • SpecularMaterial określa, że szczotka zostanie zastosowana do modelu, tak jakby powierzchnia modelu była twarda lub błyszcząca, w stanie odzwierciedlać wyróżnienia. Można ustawić stopień, w jakim tekstura będzie sugerować tę jakość refleksywną lub "blask", określając wartość właściwości SpecularPower .

  • EmissiveMaterial pozwala określić, że tekstura będzie stosowana tak, jakby model emitowały światło równe kolorowi pędzla. Nie sprawia to, że model jest jasny; jednak będzie on uczestniczyć inaczej w cieniowaniu niż w przypadku teksturowania z Dyfuzorem lub SpecularMaterial.

Aby uzyskać lepszą wydajność, backfaces obiektu GeometryModel3D (te twarze, które są poza widokiem, ponieważ znajdują się one po przeciwnej stronie modelu z aparatu) są uśmiercewane z sceny. Aby określić element Material , który ma być stosowany do tyłu modelu, takiego jak płaszczyzna BackMaterial , ustaw właściwość modelu.

Aby osiągnąć niektóre cechy powierzchni, takie jak świecące lub odbijające efekty, możesz zastosować kilka różnych pędzli do modelu z rzędu. Można stosować i ponownie używać wielu materiałów przy użyciu MaterialGroup klasy . Elementy podrzędne grupy MaterialGroup są stosowane najpierw do ostatniego w wielu przebiegach renderowania.

W poniższych przykładach kodu pokazano, jak zastosować jednolity kolor i rysunek jako pędzle do modeli 3D.

<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>
DiffuseMaterial side5Material = new DiffuseMaterial((Brush)Application.Current.Resources["patternBrush"]);
Dim side5Material As New DiffuseMaterial(CType(Application.Current.Resources("patternBrush"), Brush))

Podświetlanie sceny

Światła w grafice 3D robią to, co robią światła w świecie rzeczywistym: sprawiają, że powierzchnie są widoczne. Więcej do punktu, światła określają, która część sceny zostanie uwzględniona w projekcji. Obiekty lekkie w WPF tworzą różne efekty światła i cienia i są modelowane po zachowaniu różnych rzeczywistych świateł. Uwzględnij co najmniej jedno światło w scenie lub nie będą widoczne żadne modele.

Następujące światła pochodzą z klasy Lightbazowej :

  • AmbientLight: Zapewnia oświetlenie otoczenia, które oświetla wszystkie obiekty jednolicie niezależnie od ich lokalizacji lub orientacji.

  • DirectionalLight: Świeci jak odległe źródło światła. Światła kierunkowe mają Direction określony jako Vector3D, ale nie ma określonej lokalizacji.

  • PointLight: Świeci jak pobliskie źródło światła. Kontrolki PointLight mają położenie i odlewa światło z tej pozycji. Obiekty na scenie są oświetlone w zależności od ich położenia i odległości w odniesieniu do światła. PointLightBase uwidacznia Range właściwość, która określa odległość, poza którą modele nie będą oświetlone światłem. Kontrolka PointLight uwidacznia również właściwości tłumienia, które określają, jak intensywność światła zmniejsza się w odległości. Można określić stałe, liniowe lub kwadratowe interpolacje dla tłumienia światła.

  • SpotLight: Dziedziczy z PointLightelementu . Reflektory świecą jak PointLight i mają zarówno położenie, jak i kierunek. Projektują światło w kształcie stożka ustawionego przez InnerConeAngle właściwości i OuterConeAngle określone w stopniach.

Światła to Model3D obiekty, dzięki czemu można przekształcać i animować właściwości światła, w tym położenie, kolor, kierunek i zakres.

<ModelVisual3D.Content>
    <AmbientLight Color="#333333" />
</ModelVisual3D.Content>
DirectionalLight myDirLight = new DirectionalLight();
Private myDirLight As 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)

Przekształcanie modeli

Podczas tworzenia modeli mają one określoną lokalizację w scenie. Aby przenieść te modele w scenie, obrócić je lub zmienić ich rozmiar, nie jest praktyczne, aby zmienić wierzchołki, które definiują same modele. Zamiast tego, podobnie jak w przypadku 2D, stosujesz przekształcenia do modeli.

Każdy obiekt modelu ma właściwość, za pomocą Transform której można przenosić, zmieniać orientację lub zmieniać rozmiar modelu. Po zastosowaniu przekształcenia skutecznie zrównoważysz wszystkie punkty modelu za pomocą dowolnego wektora lub wartości określonej przez przekształcenie. Innymi słowy, przekształcono przestrzeń współrzędnych, w której zdefiniowano model ("przestrzeń modelu"), ale nie zmieniono wartości tworzących geometrię modelu w układzie współrzędnych całej sceny ("przestrzeń światowa").

Aby uzyskać więcej informacji na temat przekształcania modeli, zobacz Omówienie przekształceń 3D.

Animowanie modeli

Implementacja WPF 3D uczestniczy w tym samym chronometrażu i systemie animacji co grafika 2D. Innymi słowy, aby animować scenę 3D, animować właściwości swoich modeli. Można animować właściwości pierwotnych bezpośrednio, ale zazwyczaj łatwiej jest animować przekształcenia, które zmieniają położenie lub wygląd modeli. Ponieważ przekształcenia można stosować do Model3DGroup obiektów, a także poszczególnych modeli, można zastosować jeden zestaw animacji do elementu podrzędnego grupy Model3DGroup, a drugi zestaw animacji do grupy obiektów podrzędnych. Możesz również osiągnąć różne efekty wizualne, animując właściwości oświetlenia sceny. Na koniec możesz animować samą projekcję, animując położenie aparatu lub pole widoku. Aby uzyskać podstawowe informacje na temat systemu chronometrażu i animacji WPF, zobacz Tematy Omówienie animacji, Storyboards Overview i Freezable Objects Overview (Omówienie scenorysów) i Freezable Objects Overview (Omówienie scenorysów).

Aby animować obiekt w WPF, należy utworzyć oś czasu, zdefiniować animację (która jest naprawdę zmianą w niektórych wartościach właściwości w czasie) i określić właściwość, do której ma zostać zastosowana animacja. Ponieważ wszystkie obiekty w scenie 3D są elementami podrzędnymi Viewport3D, właściwości przeznaczone dla każdej animacji, którą chcesz zastosować do sceny, są właściwościami Viewport3D.

Załóżmy, że chcesz, aby model wyglądał na chwiejny. Możesz zastosować element RotateTransform3D do modelu i animować oś jego obrotu z jednego wektora do drugiego. W poniższym przykładzie kodu pokazano zastosowanie właściwości Vector3DAnimation do właściwości Axis elementu Rotation3D przekształcenia, przy założeniu, że wartość RotateTransform3D ma być jedną z kilku przekształceń zastosowanych do modelu z grupą TransformGroup.

//Define a rotation
RotateTransform3D myRotateTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 1));
'Define a rotation
Dim myRotateTransform As New RotateTransform3D(New AxisAngleRotation3D(New Vector3D(0, 1, 0), 1))
Vector3DAnimation myVectorAnimation = new Vector3DAnimation(new Vector3D(-1, -1, -1), new Duration(TimeSpan.FromMilliseconds(5000)));
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever;
Dim myVectorAnimation As 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)

Dodawanie zawartości 3D do okna

Aby renderować scenę, dodaj modele i światła do Model3DGroupelementu , a następnie ustaw jako ContentModel3DGroupModelVisual3Delement . Dodaj element ModelVisual3D do Children kolekcji obiektu Viewport3D. Dodaj aparaty do obiektu Viewport3D , ustawiając jego Camera właściwość.

Na koniec dodaj element Viewport3D do okna. Viewport3D Gdy element jest dołączany jako zawartość elementu układu, taki jak Canvas, określ rozmiar viewport3D, ustawiając jego Height właściwości i Width (dziedziczone z FrameworkElementelementu ).

<UserControl x:Class="HostingWpfUserControlInWf.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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>

Zobacz też