Compartilhar via


Visão geral de transformações 3D

Este tópico descreve como aplicar transformações a modelos 3D no sistema gráfico Windows Presentation Foundation (WPF). As transformações permitem ao desenvolvedor reposicionar, redimensionar e reorientar modelos sem alterar os valores base que os definem.

Espaço de coordenadas 3D

O conteúdo gráfico 3D no Windows Presentation Foundation (WPF) é encapsulado em um elemento , Viewport3D, que pode participar da estrutura de elemento bidimensional. O sistema gráfico trata Viewport3D como um elemento visual bidimensional como muitos outros no Windows Presentation Foundation (WPF). O Viewport3D funciona como uma janela (um visor) em uma cena tridimensional. Mais precisamente, é uma superfície na qual uma cena 3D é projetada. Embora você possa usar Viewport3D com outros objetos de desenho 2D no mesmo gráfico de cena, você não pode interpenetrar objetos 2D e 3D em um Viewport3D. Na discussão a seguir, o espaço de coordenadas descrito está contido pelo elemento Viewport3D.

O sistema de coordenadas do Windows Presentation Foundation (WPF) para gráficos 2D localiza a origem no canto superior esquerdo da superfície de renderização (normalmente a tela). No sistema 2D, os valores positivos do eixo x prosseguem para a direita e os valores positivos do eixo y prosseguem para baixo. No sistema de coordenadas 3D, no entanto, a origem está localizada no centro da tela, com valores positivos do eixo x prosseguindo para a direita, mas valores positivos do eixo y prosseguindo para cima, e valores positivos do eixo z procedendo para fora da origem, em direção ao visualizador.

Coordinate systems
Comparação do sistema de coordenadas

O espaço definido por esses eixos é o quadro de referência estacionário para objetos 3D no Windows Presentation Foundation (WPF). Ao criar modelos nesse espaço e criar luzes e câmeras para exibi-los, é útil distinguir este quadro estacionário de referência ou "espaço de mundo", do quadro de referência local que você cria para cada modelo, quando você aplica transformações a ele. Lembre-se também de que objetos no espaço de mundo podem parecer totalmente diferentes ou até mesmo não serem visíveis, dependendo das configurações de câmera e de luz, mas a posição da câmera não altera o local dos objetos no espaço de mundo.

Transformando modelos

Quando você cria modelos, eles têm uma localização específica na cena. Para mover esses modelos na cena, girá-los ou alterar seus tamanhos, não é prático alterar os vértices que definem os próprios modelos. Em vez disso, assim como em 2D, você aplica transformações a modelos.

Cada objeto de modelo tem uma Transform propriedade com a qual você pode mover, reorientar ou redimensionar o modelo. Ao aplicar uma transformação, você efetivamente desloca todos os pontos do modelo por meio de qualquer vetor ou valor que é especificado pela transformação. Em outras palavras, você transformou o espaço de coordenadas no qual o modelo está definido ("espaço do modelo"), mas você não alterou os valores que compõem a geometria do modelo no sistema de coordenadas de toda a cena ("espaço de mundo").

Transformações de translação

As transformações 3D herdam da classe Transform3Dbase abstrata, incluindo as classes TranslateTransform3Dde transformação afim , ScaleTransform3De RotateTransform3D. O sistema 3D do Windows Presentation Foundation (WPF) também fornece uma MatrixTransform3D classe que permite especificar as mesmas transformações em operações de matriz mais concisas.

TranslateTransform3D move todos os pontos no Model3D na direção do vetor de deslocamento especificado com as OffsetXpropriedades , OffsetYe OffsetZ . Por exemplo, dado um vértice de um cubo em (2,2,2), um vetor de deslocamento de (0,1.6,1) moveria esse vértice (2,2,2) para (2,3.6,3). O vértice o cubo do ainda é (2,2,2) no espaço do modelo, mas agora esse espaço do modelo mudou sua relação com espaço de mundo para que (2,2,2) no espaço de modelo seja (2,3.6,3) no espaço de mundo.

Translation figure
Translação com deslocamento

Os exemplos de código a seguir mostram como aplicar uma translação.

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

Dimensionar transformações

ScaleTransform3D Altera a escala do modelo por um vetor de escala especificado com referência a um ponto central. Especifique uma escala uniforme, que ajusta a escala do modelo com o mesmo valor nos eixos X, Y e Z, para alterar o tamanho do modelo proporcionalmente. Por exemplo, definir as propriedades , e ScaleZ da ScaleYScaleXtransformação como 0,5 reduz pela metade o tamanho do modelo, definir as mesmas propriedades como 2 dobra sua escala em todos os três eixos.

Uniform ScaleTransform3D
Exemplo de ScaleVector

Ao especificar uma transformação de escala não uniforme (uma transformação de escala cujos valores X, Y e Z não são todos iguais), você pode fazer com um modelo se alongue ou contraia em uma ou duas dimensões sem afetar as outras. Por exemplo, definir ScaleX como 1, ScaleY para 2 e para 1 faria com que o modelo transformado dobrasse de altura, mas permanecesse inalterado ao longo dos eixos X e ScaleZ Z.

Por padrão, o ScaleTransform3D faz com que os vértices se expandam ou contraiam em relação à origem (0,0,0). No entanto, se o modelo que você deseja transformar não for extraído da origem, dimensionar o modelo a partir da origem não dimensionará o modelo "no lugar". Em vez disso, quando os vértices do modelo são multiplicados pelo vetor de escala, a operação de escala terá o efeito de traduzir o modelo, bem como dimensioná-lo.

Three cubes scaled with center point specified
Exemplo de centro de escala

Para dimensionar um modelo "no local", especifique o centro do modelo definindo as propriedades , CenterYe CenterZ de ScaleTransform3DCenterX. Isso garante que o sistema gráfico dimensione o espaço do modelo e, em seguida, o converta para centralizar no Point3D. Por outro lado, se você tiver criado o modelo sobre a origem e especificar um ponto central diferente, observe que o modelo será movido para longe da origem.

Transformações de rotação

Você pode girar um modelo em 3D de várias maneiras diferentes. Uma típica transformação de rotação especifica um eixo e um ângulo de rotação em torno desse eixo. A RotateTransform3D classe permite que você defina um Rotation3D com sua Rotation propriedade. Em seguida, especifique Axis e Angle propriedades no Rotation3D, neste caso um AxisAngleRotation3D, para definir a transformação. Os exemplos a seguir giram um modelo por 60 graus em torno do eixo 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>

Nota:Windows Presentation Foundation (WPF) 3D é um sistema destro, o que significa que um valor de ângulo positivo para uma rotação resulta em uma rotação no sentido anti-horário em torno do eixo.

As rotações de ângulo de eixo pressupõem rotação sobre a origem se um valor não for especificado para as CenterXpropriedades , CenterYe em CenterZ RotateTransform3D. Assim como na colocação em escala, é útil lembrar que a rotação transforma todo espaço de coordenadas do modelo. Se o modelo não tiver sido criado sobre a origem ou tiver sido movido anteriormente, a rotação poderá "girar" em relação à origem em vez de rotacionar no lugar.

Rotation with new center point
Rotação com o novo centro especificado

Para girar o modelo "in-loco", especifique o centro real do modelo como o centro de rotação. Como a geometria normalmente é modelada em relação à origem, você geralmente poderá obter o resultado esperado de um conjunto de transformações primeiro dimensionando o modelo (colocando-o em escala), em seguida, configurando sua orientação (girando-o) e, finalmente, movendo-o para o local desejado (transladando-o).

Rotation by 60 degrees in x- and y-axes
Exemplo de rotação

As rotações eixo-ângulo funcionam bem para transformações estáticas e para algumas animações. No entanto, considere girar um modelo de cubo em 60 graus ao redor do eixo X e, em seguida, 45 graus em torno do eixo Z. Você pode descrever essa transformação como duas transformações afins discretas ou como uma matriz. No entanto, pode ser difícil animar suavemente uma rotação definida dessa maneira. Embora as posições inicial e final do modelo, calculadas por qualquer uma das abordagens, sejam as mesmas, as posições intermediárias assumidas pelo modelo são computacionalmente incertas. Os quatérnions representam uma maneira alternativa para calcular a interpolação entre o início e fim de uma rotação.

Um quaternião representa um eixo no espaço 3D e uma rotação em torno desse eixo. Por exemplo, um quatérnion pode representar um eixo (1,1,2) e uma rotação de 50 graus. O poder dos quatérnions ao definir rotações é proveniente das duas operações que você pode realizar neles: composição e interpolação. A composição de dois quaterniões aplicados a uma geometria significa "girar a geometria em torno do eixo 2 por rotação2, depois girá-la em torno do eixo 1 por rotação1". Usando a composição, você pode combinar as duas rotações na geometria para obter um único quaternião que representa o resultado. Como a interpolação de quatérnions pode calcular um caminho suave e razoável de um eixo e de uma orientação à outra, é possível interpolar do quatérnion original para o composto para alcançar uma transição suave de um para outro, permitindo que você anime a transformação. Para modelos que você deseja animar, você pode especificar um destino Quaternion para a rotação usando um QuaternionRotation3D para a Rotation propriedade.

Usando coleções de transformações

Ao criar uma cena, é comum aplicar mais de uma transformação a um modelo. Adicione transformações à Children coleção da Transform3DGroup classe para agrupar transformações convenientemente para aplicar a vários modelos na cena. Muitas vezes, é conveniente reutilizar uma transformação em vários grupos diferentes, da mesma maneira que você pode reutilizar um modelo, aplicando um conjunto diferente de transformações para cada instância. Observe que a ordem na qual as transformações são adicionadas à coleção é significativa: as transformações na coleção são aplicadas da primeira à última.

Animando transformações

A implementação 3D do Windows Presentation Foundation (WPF) participa do mesmo sistema de tempo e animação que os gráficos 2D. Em outras palavras, para animar uma cena 3D, anime as propriedades de seus modelos. É possível animar propriedades de primitivas diretamente, mas é geralmente mais fácil animar transformações que alteram a posição ou a aparência de modelos. Como as transformações podem ser aplicadas a objetos, bem como a modelos individuais, é possível aplicar um conjunto de animações aos filhos de um Model3Dgroup e outro conjunto de animações a Model3DGroup um grupo de objetos. Para obter informações básicas sobre o sistema de tempo e animação do Windows Presentation Foundation (WPF), consulte Visão geral da animação e Visão geral dos storyboards.

Para animar um objeto no Windows Presentation Foundation (WPF), crie uma linha do tempo, defina uma animação (que é realmente uma alteração em algum valor de propriedade ao longo do tempo) e especifique a propriedade à qual aplicar a animação. Essa propriedade deve ser uma propriedade de um FrameworkElement. Como todos os objetos em uma cena 3D são filhos de Viewport3D, as propriedades direcionadas por qualquer animação que você deseja aplicar à cena são propriedades de propriedades de Viewport3D. É importante preparar o caminho da propriedade para a animação cuidadosamente, porque a sintaxe pode ser detalhada.

Suponha que você deseja girar um objeto no local, mas também deseja aplicar um movimento de balanço para expor mais do objeto para a exibição. Você pode optar por aplicar uma RotateTransform3D ao modelo e animar o eixo de sua rotação de um vetor para outro. O exemplo de código a seguir demonstra a aplicação de a Vector3DAnimation à propriedade Axis de Rotation3D da transformação, supondo que RotateTransform3D seja uma das várias transformações aplicadas ao modelo com um 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

Use uma sintaxe semelhante para direcionar outras propriedades de transformação para mover ou ajustar a escala o objeto. Por exemplo, você pode aplicar um à propriedade ScaleCenter em uma transformação de escala para fazer com que um Point3DAnimation modelo distorça suavemente sua forma.

Embora os exemplos anteriores transformem as propriedades do GeometryModel3D, também é possível transformar as propriedades de outros modelos na cena. Ao animar translações aplicadas a objetos de luz, por exemplo, você pode criar luz em movimento e efeitos de sombra que podem alterar drasticamente a aparência de seus modelos.

Como as câmeras são modelos, também é possível transformar propriedades de câmeras. Enquanto você certamente pode alterar a aparência da cena transformando as distâncias de plano ou o local da câmera (com efeito, transformando toda a projeção da cena), observe que muitos dos efeitos conseguidos dessa maneira podem não fazer tanto "sentido visual" para o visualizador como as transformações aplicadas ao local ou à posição dos modelos na cena.

Confira também