Översikt över 3D-omvandlingar
Det här avsnittet beskriver hur du tillämpar transformeringar på 3D-modeller i grafiksystemet Windows Presentation Foundation (WPF). Transformeringar gör det möjligt för utvecklaren att flytta, ändra storlek på och omorientera modeller utan att ändra de basvärden som definierar dem.
3D-koordinatutrymme
3D-grafikinnehåll i Windows Presentation Foundation (WPF) är inkapslat i ett element, Viewport3D, som kan delta i den tvådimensionella elementstrukturen. Grafiksystemet behandlar Viewport3D som ett tvådimensionellt visuellt element som många andra i Windows Presentation Foundation (WPF). Viewport3D fungerar som ett fönster – ett visningsområde – till en tredimensionell scen. Mer exakt är det en yta där en 3D-scen projiceras. Även om du kan använda Viewport3D med andra 2D-ritobjekt i samma scendiagram kan du inte mellananvända 2D- och 3D-objekt i en Viewport3D. I följande diskussion beskrivs koordinatrymden som finns i elementet Viewport3D.
WPF-koordinatsystemet (Windows Presentation Foundation) för 2D-grafik lokaliserar ursprunget längst upp till vänster på återgivningsytan (vanligtvis skärmen). I 2D-systemet fortsätter positiva x-axelvärden till höger och positiva y-axelvärden fortsätter nedåt. I 3D-koordinatsystemet finns ursprunget i mitten av skärmen, med positiva x-axelvärden som fortsätter till höger men positiva y-axelvärden fortsätter uppåt i stället och positiva z-axelvärden fortsätter utåt från ursprunget, mot visningsprogrammet.
Koordinatsystemjämförelse
Det utrymme som definieras av dessa axlar är den stationära referensramen för 3D-objekt i Windows Presentation Foundation (WPF). När du skapar modeller i det här utrymmet och skapar lampor och kameror för att visa dem är det bra att skilja den här stationära referensramen eller "världsutrymmet" från den lokala referensram som du skapar för varje modell när du tillämpar transformeringar på den. Kom också ihåg att objekt i världsrymden kan se helt annorlunda ut, eller inte vara synliga alls, beroende på ljus- och kamerainställningar, men kamerans position ändrar inte platsen för objekt i världsrymden.
Transformera modeller
När du skapar modeller har de en viss plats i scenen. Om du vill flytta runt modellerna i scenen, rotera dem eller ändra deras storlek är det inte praktiskt att ändra hörnen som definierar själva modellerna. I stället, precis som i 2D, tillämpar du transformeringar på modeller.
Varje modellobjekt har en Transform egenskap som du kan flytta, omorientera eller ändra storlek på modellen med. När du tillämpar en transformering förskjuter du effektivt alla punkter i modellen med den vektor eller det värde som anges av transformeringen. Med andra ord har du omvandlat koordinatutrymmet där modellen definieras ("modellutrymme"), men du har inte ändrat de värden som utgör modellens geometri i koordinatsystemet för hela scenen ("världsrymd").
Översättningstransformeringar
3D-transformeringar ärver från den abstrakta basklassen Transform3D; dessa inkluderar transformeringsklasserna affine TranslateTransform3D, ScaleTransform3Doch RotateTransform3D. 3D-systemet (Windows Presentation Foundation) innehåller också en MatrixTransform3D-klass som gör att du kan ange samma transformeringar i mer koncisa matrisåtgärder.
TranslateTransform3D flyttar alla punkter i Model3D i riktning mot den förskjutningsvektor som du anger med egenskaperna OffsetX, OffsetYoch OffsetZ. Om du till exempel får ett hörn av en kub vid (2,2,2) skulle en förskjutningsvektor på (0,1,6,1) flytta det hörnet (2,2,2) till (2,3,6,3). Kubens hörn är fortfarande (2,2,2) i modellutrymmet, men nu har modellutrymmet ändrat sin relation till världsrymden så att (2,2,2) i modellutrymmet är (2,3,6,3) i världsrymden.
Översättning med offset
Följande kodexempel visar hur du tillämpar en översättning.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="600" Height="201">
<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="600" Height="150"
Canvas.Left="0" Canvas.Top="10">
<!-- Defines the camera used to view the 3D object. -->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>
<!-- The ModelVisual3D children contain the 3D models -->
<Viewport3D.Children>
<!-- This ModelVisual3D defines the light cast in the scene. Without light, the
3D object cannot be seen. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>
<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " />
</GeometryModel3D.Geometry>
<!-- The material specifies the material applied to the plane. In this case it is a linear gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- The Transform specifies how to transform the 3D object. The OffsetX property is animated
in the Storyboard below. -->
<GeometryModel3D.Transform>
<TranslateTransform3D x:Name="myTranslateTransform3D" OffsetX="0" OffsetY="0" OffsetZ="0" />
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
<!-- Trigger the TranslateTransform3D animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>
<!-- This animation animates the OffsetX property of the TranslateTransform3D. -->
<DoubleAnimation
Storyboard.TargetName="myTranslateTransform3D"
Storyboard.TargetProperty="OffsetX"
To="-0.8"
AutoReverse="True" RepeatBehavior="Forever" />
<!-- If you want to animate OffsetY and/or OffsetZ, create similar DoubleAnimations
respectively. -->
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>
Skalningstransformeringar
ScaleTransform3D ändrar modellens skala med en angiven skalningsvektor med referens till en mittpunkt. Ange en enhetlig skala som skalar modellen med samma värde i X-, Y- och Z-axlarna för att ändra modellens storlek proportionellt. Om du till exempel anger transformeringsegenskaperna ScaleX, ScaleYoch ScaleZ till 0,5 halveras modellens storlek. om samma egenskaper anges till 2 fördubblas skalan i alla tre axlarna.
ScaleVector-exempel
Genom att ange en icke-enhetlig skalningstransformation – en skalningstransformation vars X-, Y- och Z-värden inte är likadana – kan du få en modell att sträcka sig eller krympa i en eller två dimensioner utan att påverka de andra. Om du till exempel anger ScaleX till 1, ScaleY till 2 och ScaleZ till 1 skulle den transformerade modellen fördubblas i höjd men förbli oförändrad längs X- och Z-axlarna.
Som standardinställning gör ScaleTransform3D att hörnpunkterna expanderar eller kontraherar kring ursprungspunkten (0,0,0). Om den modell som du vill transformera inte hämtas från ursprunget kommer skalning av modellen från ursprunget dock inte att skala modellen "på plats". När modellens hörn multipliceras med skalningsvektorn får skalningsåtgärden i stället effekten att översätta modellen och skala den.
Exempel på skalningscenter
Om du vill skala en modell "på plats" anger du mitten av modellen genom att ange egenskaperna ScaleTransform3D CenterX, CenterYoch CenterZ. Detta säkerställer att grafiksystemet skalar modellutrymmet och sedan översätter det till mitten på den angivna Point3D. Om du däremot har skapat modellen om ursprunget och anger en annan mittpunkt kan du förvänta dig att se modellen översättas bort från ursprunget.
Rotationstransformationer
Du kan rotera en modell i 3D på flera olika sätt. En typisk rotationstransformation anger en axel och en rotationsvinkel runt den axeln. Med klassen RotateTransform3D kan du definiera en Rotation3D med dess egenskap Rotation. Du anger sedan egenskaperna Axis och Angle i Rotation3D, i det här fallet en AxisAngleRotation3D, för att definiera omvandlingen. I följande exempel roteras en modell med 60 grader runt Y-axeln.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Viewbox>
<Canvas Width="321" Height="201">
<!-- The Viewport3D provides a rendering surface for 3-D visual content. -->
<Viewport3D Name="MyAnimatedObject"
ClipToBounds="True" Width="150" Height="150"
Canvas.Left="0" Canvas.Top="10">
<!-- Defines the camera used to view the 3D object. -->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1"
FieldOfView="60" />
</Viewport3D.Camera>
<!-- The ModelVisual3D children contain the 3D models -->
<Viewport3D.Children>
<!-- Two ModelVisual3D define the lights cast in the scene. Without light, the
3D object cannot be seen. Also, the direction of the lights affect shadowing. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>
<!-- The geometry specifes the shape of the 3D plane. In this case, a flat sheet is created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " />
</GeometryModel3D.Geometry>
<!-- The material specifies the material applied to the plane. In this case it is a linear gradient.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- The Transform specifies how to transform the 3D object. The properties of the
Rotation object are animated causing the 3D object to rotate and "wobble" (see Storyboard below).-->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="myAngleRotation" Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
<!-- Trigger the rotation animation when the 3D object loads. -->
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<BeginStoryboard>
<Storyboard>
<!-- This animation animates the Angle property of the AxisAngleRotation3D
making the 3D object rotate from -60 degrees to 60 degrees. -->
<DoubleAnimation
Storyboard.TargetName="myAngleRotation"
Storyboard.TargetProperty="Angle"
From="-60" To="60" Duration="0:0:4" AutoReverse="True" RepeatBehavior="Forever"/>
<!-- This animation animates the Axis property of the AxisAngleRotation3D
making the 3D wobble as it rotates. -->
<Vector3DAnimation
Storyboard.TargetName="myAngleRotation"
Storyboard.TargetProperty="Axis"
From="0,3,0" To="1,0,1" Duration="0:0:4" AutoReverse="True" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
</Canvas>
</Viewbox>
</DockPanel>
</Page>
Obs! Windows Presentation Foundation (WPF) 3D är ett högerhänt system, vilket innebär att ett positivt vinkelvärde för en rotation resulterar i en motsols rotation om axeln.
Axel-vinkelrotationer förutsätter rotation kring ursprunget om ett värde inte har angetts för egenskaperna CenterX, CenterYoch CenterZ i RotateTransform3D. Precis som med skalning är det bra att komma ihåg att rotationen transformerar modellens hela koordinatutrymme. Om modellen inte skapades med ursprunget som referenspunkt, eller har översatts tidigare, kan rotationen "pivotera" runt ursprunget i stället för att rotera på plats.
Rotation med nytt center angivet
Om du vill rotera modellen "på plats" anger du modellens faktiska mittpunkt som rotationspunkt. Eftersom geometrin vanligtvis modelleras utifrån ursprunget kan du oftast få det förväntade resultatet av en uppsättning transformeringar genom att först ändra storlek på modellen (skala den), sedan ange dess orientering (rotera den) och slutligen flytta den till önskad plats (översätta den).
Rotationsexempel
Axelvinkelrotationer fungerar bra för statiska transformeringar och vissa animeringar. Överväg dock att rotera en kubmodell 60 grader runt X-axeln och sedan 45 grader runt Z-axeln. Du kan beskriva den här omvandlingen som två diskreta affintransformeringar eller som en matris. Det kan dock vara svårt att smidigt animera en rotation som definierats på det här sättet. Även om in- och slutpositionerna för modellen som beräknas med någon av dessa metoder är desamma, är de mellanliggande positionerna som modellen intagit beräkningsmässigt osäkra. Quaternions representerar ett alternativt sätt att beräkna interpolationen mellan början och slutet av en rotation.
En quaternion representerar en axel i 3D-utrymme och en rotation runt den axeln. En quaternion kan till exempel representera en (1,1,2) axel och en rotation på 50 grader. Quaternions förmåga att definiera rotationer kommer från de två åtgärder som du kan utföra på dem: sammansättning och interpolation. Kompositionen av två kvaternioner som tillämpas på en geometri betyder "rotera geometrin runt axel2 genom rotation2, och rotera den sedan runt axel1 genom rotation1." Genom att använda komposition kan du kombinera de två rotationerna på geometrin för att få en enda kvaternion som representerar resultatet. Eftersom quaternion-interpolation kan beräkna en smidig och rimlig väg från en axel och orientering till en annan, kan du interpolera från originalet till den sammansatta quaternionen för att uppnå en smidig övergång från en till en annan, så att du kan animera omvandlingen. För modeller som du vill animera kan du ange ett mål Quaternion för rotationen med hjälp av en QuaternionRotation3D för egenskapen Rotation.
Använda transformeringssamlingar
När du skapar en scen är det vanligt att tillämpa mer än en transformering på en modell. Lägg till transformeringar i samlingen Children av klassen Transform3DGroup för att enkelt gruppera transformeringarna och tillämpa dem på olika modeller i scenen. Det är ofta praktiskt att återanvända en transformering i flera olika grupper, på ungefär samma sätt som du kan återanvända en modell genom att tillämpa en annan uppsättning transformeringar på varje instans. Observera att ordningen i vilken omvandlingarna läggs till i samlingen är betydande: transformeringar i samlingen tillämpas från första till sista.
Animera transformationer
Windows Presentation Foundation (WPF) 3D-implementeringen deltar i samma tids- och animeringssystem som 2D-grafik. För att animera en 3D-scen animerar du med andra ord egenskaperna för dess modeller. Det är möjligt att animera egenskaper för primitiver direkt, men det är vanligtvis enklare att animera transformeringar som ändrar positionen eller utseendet på modeller. Eftersom transformationer kan tillämpas på Model3DGroup-objekt såväl som enskilda modeller, är det möjligt att tillämpa en uppsättning animeringar på barnobjekten i en Model3D-grupp och en annan uppsättning animeringar på en objektgrupp. Bakgrundsinformation om tids- och animeringssystemet för Windows Presentation Foundation (WPF) finns i översikterna Animering och Storyboards.
Om du vill animera ett objekt i Windows Presentation Foundation (WPF) skapar du en tidslinje, definierar en animering (vilket verkligen är en ändring i ett egenskapsvärde över tid) och anger den egenskap som animeringen ska tillämpas på. Den här egenskapen måste vara en egenskap för ett FrameworkElement. Eftersom alla objekt i en 3D-scen är barn till Viewport3D, är egenskaperna som riktar sig mot någon animering du vill tillämpa på scenen egenskaper hos dessa objekts egenskaper i Viewport3D. Det är viktigt att du utarbetar egenskapssökvägen för animeringen noggrant, eftersom syntaxen kan vara utförlig.
Anta att du vill rotera ett objekt på plats, men även använda en svängande rörelse för att exponera mer av objektet som ska visas. Du kan välja att använda en RotateTransform3D på modellen och animera axeln för dess rotation från en vektor till en annan. Följande kodexempel visar hur du tillämpar en Vector3DAnimation på egenskapen Axis för transformationens Rotation3D, förutsatt att RotateTransform3D är en av flera transformeringar som redan har tillämpats på modellen med en 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
Använd en liknande syntax för att rikta in dig på andra transformeringsegenskaper för att flytta eller skala objektet. Du kan till exempel använda en Point3DAnimation på egenskapen ScaleCenter på en skaltransform för att få en modell att smidigt förvränga sin form.
Även om föregående exempel transformerar egenskaperna för GeometryModel3D, är det också möjligt att transformera egenskaperna för andra modeller i scenen. Genom att animera översättningar som tillämpas på ljusobjekt kan du till exempel skapa rörliga ljus- och skuggeffekter som dramatiskt kan ändra utseendet på dina modeller.
Eftersom kameror också är modeller är det också möjligt att transformera kameraegenskaper. Även om du säkert kan ändra utseendet på scenen genom att transformera kamerans plats eller flygavstånd – i själva verket transformera hela scenprojektionen – bör du tänka på att många av de effekter som du uppnår på det här sättet kanske inte ger så mycket "visuell mening" för visningsprogrammet som transformeringar som tillämpas på modellernas plats eller position i scenen.
Se även
- 3D-grafiköversikt
- översikt över transformeringar
- 2D-transformationer exempel
.NET Desktop feedback