Sdílet prostřednictvím


Přehled 3D transformací

Toto téma popisuje, jak použít transformace na 3D modely v grafickém systému Windows Presentation Foundation (WPF). Transformace umožňují vývojáři přemístit, změnit velikost a změnit orientaci modelů beze změny základních hodnot, které je definují.

Prostor souřadnic 3D

3D grafický obsah ve Windows Presentation Foundation (WPF) je zapouzdřen v elementu, Viewport3D, který se může účastnit dvourozměrné struktury elementu. Grafický systém považuje Viewport3D za dvojrozměrný vizuální prvek jako mnoho dalších ve Windows Presentation Foundation (WPF). Viewport3D funguje jako okno – oblast zobrazení – do trojrozměrné scény. Přesněji řečeno, jedná se o povrch, na kterém se promítá 3D scéna. I když můžete použít Viewport3D s jinými 2D objekty ve stejném grafu scény, nemůžete spojovat ani prolínat 2D a 3D objekty v rámci Viewport3D. V následující diskuzi je souřadnicový prostor popsaný elementem Viewport3D.

Souřadnicový systém WINDOWS Presentation Foundation (WPF) pro 2D grafiku vyhledá původ v levém horním rohu vykreslovacího povrchu (obvykle na obrazovce). V 2D systému se kladné hodnoty osy x posunou doprava a kladné hodnoty osy y se posunou směrem dolů. V 3D souřadnicovém systému je však původ umístěn ve středu obrazovky, s pozitivními hodnotami osy x směřujícími doprava, zatímco kladné hodnoty osy y směřují nahoru, a kladné hodnoty osy z směřují od počátku směrem ven, k divákovi.

souřadnicové systémy CoordSystem-1
Porovnání souřadnicového systému

Prostor definovaný těmito osami je nepohyblivá soustava souřadnic pro 3D objekty ve Windows Presentation Foundation (WPF). Při vytváření modelů v tomto prostoru a vytváření světel a kamer pro jejich prohlížení je užitečné odlišit tento statický rámec odkazu nebo "světový prostor" od místního rámce odkazu, který vytvoříte pro každý model při použití transformací. Mějte také na paměti, že objekty ve světě mohou vypadat úplně jinak, nebo nemusí být viditelné vůbec v závislosti na nastavení světla a kamery, ale umístění kamery nezmění umístění objektů ve světě vesmíru.

Transformace modelů

Modely mají při vytváření ve scéně konkrétní umístění. Pokud chcete tyto modely přesunout ve scéně, otočit je nebo změnit jejich velikost, není praktické změnit vrcholy, které definují samotné modely. Místo toho stejně jako v 2D použijete transformace na modely.

Každý objekt modelu má Transform vlastnost, pomocí které můžete model přesunout, znovu orientovat nebo změnit jeho velikost. Při použití transformace efektivně posunete všechny body modelu jakýmkoli vektorem nebo hodnotou určenou transformací. Jinými slovy jste transformovali souřadnicový prostor, ve kterém je model definovaný ("prostor modelu"), ale nezměnili jste hodnoty, které tvoří geometrii modelu v souřadnicovém systému celé scény ("světový prostor").

Transformace překladu

3D transformace dědí z abstraktní základní třídy Transform3D; patří mezi ně například třídy afinní transformace TranslateTransform3D, ScaleTransform3Da RotateTransform3D. Systém Windows Presentation Foundation (WPF) 3D také poskytuje třídu MatrixTransform3D, která umožňuje určit stejné transformace v stručnějších maticových operacích.

TranslateTransform3D přesune všechny body ve 3D modelu ve směru posunutí vektoru, který zadáte pomocí vlastností OffsetX, OffsetYa OffsetZ. Například, s ohledem na jeden vrchol krychle v bodě (2,2,2), by posunový vektor (0,1.6,1) přemístil tento vrchol z (2,2,2) na (2,3.6,3). Vrchol krychle je stále (2,2,2) v prostoru modelu, ale nyní se vztah tohoto prostoru modelu ke světovému prostoru změnil tak, že (2,2,2) v prostoru modelu je (2,3.6,3) ve světovém prostoru.

Překladový obrázek
Překlad s posunem

Následující příklady kódu ukazují, jak použít překlad.

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

Transformace škál

ScaleTransform3D změní měřítko modelu podle zadaného vektoru měřítka s odkazem na středový bod. Zadejte jednotné měřítko, které model v osách X, Y a Z škáluje podle stejné hodnoty, aby se velikost modelu změnila úměrně. Například nastavování vlastností transformací ScaleX, ScaleYa ScaleZ na 0,5 zmenší velikost modelu na polovinu; nastavení stejných vlastností na 2 zdvojnásobí měřítko ve všech třech osách.

Uniform ScaleTransform3D
Příklad scaleVectoru

Zadáním ne uniformní transformace měřítka – transformace měřítka, jejíž hodnoty X, Y a Z nejsou stejné – můžete model roztáhnout nebo uzavřít do jedné nebo dvou dimenzí, aniž by to ovlivnilo ostatní. Například nastavení ScaleX na 1, ScaleY na 2 a ScaleZ na 1 způsobí, že se transformovaný model zdvojnásobí ve výšce, ale zůstane beze změny podél os X a Z.

Ve výchozím nastavení ScaleTransform3D způsobí rozšíření nebo zmenšení vrcholů kolem počátku (0,0,0). Pokud model, který chcete transformovat, nepochází z počátku, škálování modelu z tohoto počátku nebude model škálovat „na místě“. Místo toho, když se vrcholy modelu vynásobí vektorem měřítka, operace škálování bude mít za následek jak posunutí modelu, tak jeho škálování.

tři krychle škálované s určeným středovým bodem
Příklad služby Scale Center

Pokud chcete model škálovat přímo na místě, zadejte střed modelu nastavením vlastností CenterX, CenterYa CenterZ v ScaleTransform3D. Tím zajistíte, že grafický systém škáluje prostor modelu a pak ho posune na střed určený bodem Point3D. Pokud jste naopak vytvořili model o původu a zadali jiný středový bod, počítejte s tím, že se model přeloží mimo původní zdroj.

Transformace obměny

Model můžete otáčet v 3D několika různými způsoby. Typická transformace otočení určuje osu a úhel otočení kolem této osy. Třída RotateTransform3D umožňuje definovat Rotation3D s jeho vlastností Rotation. Potom zadáte vlastnosti Axis a Angle v objektu Rotation3D, v tomto případě AxisAngleRotation3Ddefinující transformaci. Následující příklady otočí model o 60 stupňů kolem osy Y.

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

Poznámka: Windows Presentation Foundation (WPF) 3D je pravotočivý systém, což znamená, že kladná hodnota úhlu otáčení vede k otočení proti směru hodinových ručiček kolem osy.

Otočení osy-úhel předpokládá rotaci kolem počátku, pokud není zadána hodnota pro vlastnosti CenterX, CenterYa CenterZ v RotateTransform3D. Stejně jako u škálování je užitečné si uvědomit, že rotace transformuje celý prostor souřadnic modelu. Pokud model nebyl vytvořen vzhledem k počátku, nebo byl přeložen dříve, může se rotace "otáčet" kolem počátku místo rotování na místě.

Otočení s novým středovým bodem
Otočení se zadaným novým středem

Pokud chcete model otočit "na místě", zadejte skutečný střed modelu jako střed otáčení. Vzhledem k tomu, že geometrie je obvykle modelována o původu, můžete nejčastěji získat očekávaný výsledek sady transformací tak, že model nejprve nastavíte (škálujete ho), nastavíte jeho orientaci (otočíte) a nakonec ho přesunete do požadovaného umístění (přeložíte ho).

otočení o 60 stupňů v osách x a y
Příklad rotace

Otočení úhlu osy dobře funguje pro statické transformace a některé animace. Zvažte ale otočení modelu datové krychle o 60 stupňů kolem osy X a 45 stupňů kolem osy Z. Tuto transformaci můžete popsat jako dvě diskrétní affinové transformace nebo jako matici. Může ale být obtížné hladce animovat otočení definované tímto způsobem. I když počáteční a koncové pozice modelu vypočítané některým z přístupů jsou stejné, přechodné pozice, které model přebírá, jsou výpočetně nejisté. Kvaterniony představují alternativní způsob, jak vypočítat interpolaci mezi začátkem a koncem rotace.

Kvaternion představuje osu ve 3D prostoru a otočení kolem této osy. Například kvaternion může představovat osu (1,1,2) a otočení o 50 stupňů. Síla quaternionů při definování rotací pochází ze dvou operací, které s nimi můžete provádět: složení a interpolace. Složení dvou kvaternionů použitých na geometrii znamená "otočit geometrii kolem osy2 rotací2 a potom ji otočit kolem osy1 rotací1". Pomocí složení můžete zkombinovat dvě rotace na geometrii, abyste získali jeden kvaternion, který představuje výsledek. Vzhledem k tomu, že interpolace kvazternionu dokáže vypočítat plynulou a rozumnou cestu z jedné osy a orientace na jinou, můžete interpolovat z původního do složeného kvazternionu, abyste dosáhli hladkého přechodu z jedné na druhou, což vám umožní animovat transformaci. U modelů, které chcete animovat, můžete určit cíl otočení jako Quaternion a použitím QuaternionRotation3D jako vlastnost Rotation.

Použití transformačních kolekcí

Při vytváření scény je běžné použít u modelu více než jednu transformaci. Přidejte transformace do kolekce Children třídy Transform3DGroup pro pohodlné seskupení transformací a jejich aplikaci na různé modely v rámci scény. Často je vhodné opakovaně použít transformaci v několika různých skupinách, a to způsobem, jakým můžete model znovu použít použitím jiné sady transformací na každou instanci. Všimněte si, že pořadí, ve kterém jsou transformace přidány do kolekce, je důležité: transformace v kolekci se použijí od prvního do posledního.

Animace transformací

3D implementace Windows Presentation Foundation (WPF) se účastní stejného časování a animačního systému jako 2D grafika. Jinými slovy, pokud chcete animovat 3D scénu, animujte vlastnosti svých modelů. Vlastnosti primitiv je možné animovat přímo, ale obvykle je jednodušší animovat transformace, které mění pozici nebo vzhled modelů. Vzhledem k tomu, že transformace lze použít jak na Model3DGroup objekty, tak na jednotlivé modely, je možné použít jednu sadu animací na podřízené objekty Model3DGroup a jinou sadu animací na skupinu objektů. Základní informace o časování a animačním systému Windows Presentation Foundation (WPF) najdete v tématu Přehled animací a Přehled scénářů.

Pokud chcete animovat objekt ve Windows Presentation Foundation (WPF), vytvořte časovou osu, definujte animaci (což je opravdu změna hodnoty některých vlastností v průběhu času) a určete vlastnost, na kterou se má animace použít. Tato vlastnost musí být vlastností FrameworkElement. Vzhledem k tomu, že všechny objekty ve 3D scéně jsou podřízené objektu Viewport3D, vlastnosti, na které cílí jakákoli animace, kterou chcete na scénu aplikovat, jsou vlastnostmi Viewport3D. Pro animaci je důležité pečlivě vytvořit vlastnostní cestu, protože syntaxe může být značně rozvláčná.

Pokud chcete objekt otočit na místě a zároveň použít houpavý pohyb pro lepší zobrazení objektu. U modelu můžete použít RotateTransform3D a animovat osu jeho otočení z jednoho vektoru do druhého. Následující příklad kódu ukazuje použití Vector3DAnimation na vlastnost Axis Rotation3D transformace za předpokladu, že RotateTransform3D je jednou z několika transformací použitých v modelu s 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

Pokud chcete přesunout nebo škálovat objekt, použijte podobnou syntaxi k cílení dalších vlastností transformace. Například můžete použít Point3DAnimation na vlastnost ScaleCenter v transformaci měřítka, aby model hladce zkresloval svůj tvar.

I když předchozí příklady transformují vlastnosti GeometryModel3D, je také možné transformovat vlastnosti jiných modelů ve scéně. Animací překladů použitých u světlých objektů můžete například vytvořit pohyblivé světlé a stínové efekty, které mohou výrazně změnit vzhled modelů.

Vzhledem k tomu, že kamery jsou také modely, je také možné transformovat vlastnosti kamery. Vzhled scény můžete určitě změnit tak, že změníte umístění kamery nebo vzdálenosti roviny – v důsledku transformace celé projekce scény – všimněte si, že mnoho efektů, které tímto způsobem dosáhnete, nemusí pro diváka dělat tolik "vizuálního smyslu" jako transformace použité na umístění nebo pozici modelů ve scéně.

Viz také