Visão Geral Sobre Transformações 3D
Este tópico descreve como aplicar transformações a modelos 3D no sistema de elementos gráficos Windows Presentation Foundation (WPF). As transformações permitem ao desenvolvedor reposicionar, redimensionar e reorientar modelos sem alterar os valores base que os definem.
Este tópico contém as seguintes seções.
- Espaço de coordenadas 3D
- Transformando modelos
- Transformações de Translação
- Transformações de Escala
- Transformações de rotação
- Usando coleções de transformações
- Animando Transformações
- Tópicos relacionados
Espaço de coordenadas 3D
Conteúdo de elementos gráficos 3D em Windows Presentation Foundation (WPF) é encapsulado num elemento, Viewport3D, que pode participar da estrutura bidimensional do elemento. O sistema de elementos gráficos trata Viewport3D como um elemento visual bidimensional como muitos outros em Windows Presentation Foundation (WPF). Viewport3D funciona como uma janela — uma porta de visualização — em uma cena tridimensional. Mais precisamente, ele é uma superfície na qual uma cena 3D é projetada. Embora seja possível usar Viewport3D com outros objetos de desenho 2D no mesmo gráfico da cena, não é possível interpenetrar objetos 2D e 3D em um Viewport3D. Na discussão a seguir, o espaço de coordenadas descrito está contido no elemento Viewport3D.
O sistema de coordenadas Windows Presentation Foundation (WPF) para gráficos 2D localiza a origem na parte superior esquerda da superfície de processamento (geralmente a tela). No sistema 2D, valores positivos do eixo x aumentam para a direita e valores positivos do eixo y aumentam 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 positvos do eixo y prosseguindo para cima dessa vez, e valores positivos do eixo z prosseguindo para fora a partir de origem, em direção ao usuário.
Comparação do Sistema de Coordenadas
O espaço definido por esses eixos é o quadro estacionário de referência para objetos 3D em 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 do mundo", do quadro local de referência que você cria para cada modelo quando você aplica transformações a ele. Lembre-se também que objetos no espaço do mundo podem parecer totalmente diferentes, ou nem mesmo serem visíveis, dependendo das configurações de câmera e de luz, mas a posição da câmera não altera a localização dos objetos no espaço do mundo.
Transformando modelos
Quando você cria modelos, eles têm uma localização específica na cena. Para mover esses modelos pela cena, girá-los ou alterar seu tamanho, não é prático alterar os vértices que definem os próprios modelos. Em vez disso, apenas como em 2D, você aplica transformações a modelos.
Cada objeto de modelo tem uma propriedade Transform com a qual você pode mover, reorientar ou redimensionar o modelo. Quando você aplica uma transformação, você efetivamente desloca todos os pontos do modelo por qualquer vetor ou valor especificado pela transformação. Em outras palavras, o espaço de coordenadas no qual o modelo é definido ("espaço do modelo") foi transformado, mas os valores que formam a geometria do modelo no sistema de coordenadas de toda a cena ("espaço do mundo") não foram alterados.
Transformações de Translação
Transformações 3D herdam da classe de base abstrata Transform3D; estes incluem as classes de transformação afim TranslateTransform3D, ScaleTransform3D e RotateTransform3D. O sistema 3D Windows Presentation Foundation (WPF) também fornece uma classe MatrixTransform3D que permite especificar as mesmas transformações em operações de matrizes mais concisas.
TranslateTransform3D move todos os pontos no Model3D na direção do vetor de deslocamento especificado com as propriedades OffsetX, OffsetY e OffsetZ. Por exemplo, dado um vértice de um cubo em (2,2,2), um vetor de deslocamento de (0,1.6,1) moveria aquele vértice (2,2,2) para (2,3.6,3). O cubo do vértice é ainda (2,2,2) no espaço modelo, mas agora que espaço modelo mudou sua relação com espaço mundo de modo que (2,2,2) no espaço do modelo seja (2,3.6,3) no espaço mundo.
Translação com deslocamento
Os seguintes exemplos de código mostram como aplicar uma translação.
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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>
Transformações de Escala
ScaleTransform3D altera a escala do modelo por um vetor de escala especificado com referência a um ponto central. Especifique uma escala uniforme, que redimensiona o modelo com o mesmo valor nos eixos X, Y e Z, para alterar o tamanho do modelo proporcionalmente. Por exemplo, definindo as propriedades ScaleX,ScaleY e ScaleZ da transformação como 0,5, reduz à metade o tamanho do modelo; definindo as mesmas propriedades como 2, dobra sua escala em todos os três eixos.
Exemplo Vetor de Escala
Especificando uma transformação de escala não uniforme — uma transformação de escala cujos valores X, Y e Z não são todos os mesmos — é possível fazer com que um modelo se alongue ou se contraia em uma ou duas dimensões sem afetar as outras. Por exemplo, definindo ScaleX como 1, ScaleY como 2 e ScaleZ como 1, faria com que o modelo transformado dobrasse sua altura, mas permanecesse inalterado junto os eixos X e Z.
Por padrão, ScaleTransform3D faz com que os vértices expandam ou contraiam sobre a origem (0,0,0). Se o modelo que deseja transformar não é desenhado a partir de origem, no entanto, dimensionar o modelo a partir de origem não irá dimensionar o modelo "no local". 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 transladar o modelo, bem como de dimensioná-lo.
Exemplo do Centro de escala
Para dimensionar um modelo "no local", especifique o centro do modelo, definindo as propriedades CenterX, CenterY e CenterZ do ScaleTransform3D. Isso garante que o sistema de elementos gráficos dimensiona o espaço do modelo e, em seguida, translada-o para o centro no Point3D especificado. Por outro lado, se você tiver criado o modelo sobre a origem e tiver especificado um ponto central diferente, espere ver o modelo convertido longe da origem.
Transformações de rotação
É possível 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 ao redor desse eixo. A classe RotateTransform3D permite definir um Rotation3D com sua propriedade Rotation. Em seguida, especifique propriedades Axis e Angle no Rotation3D, neste caso uma AxisAngleRotation3D, para definir a transformação. Os exemplos a seguir giram um modelo de 60 graus ao redor do eixo Y.
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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>
Observação: Windows Presentation Foundation (WPF) 3D é um sistema destro, o que significa que um valor de ângulo positivo para uma rotação resultados em uma rotação no sentido anti-horário sobre o eixo.
Rotações eixo-ângulo pressupõem rotação sobre a origem se não for especificado um valor para as propriedades CenterX, CenterY e CenterZ no RotateTransform3D. Assim como no dimensionamento, é útil lembrar que a rotação transforma todo o espaço de coordenadas do modelo. Se o modelo não foi criado sobre a origem, ou foi traduzido anteriormente, a rotação pode "dinamizar" sobre a origem em vez de rotacionar no lugar.
Rotação com novo centro especificado
Para girar o modelo "no local", especifique o centro real do modelo como o centro de rotação. Como a geometria normalmente é modelada sobre a origem, é possível obter o resultado esperado de um conjunto de transformações com mais frequência, primeiro ajustando o tamanho do modelo (dimensionando-o), e em seguida, definindo sua orientação (girando-o) e finalmente movendo-o para o local desejado (transladando-o).
Exemplo de rotação
Rotações eixo-ângulo funcionam bem para transformações estáticas e algumas animações. No entanto, considere girar um modelo de cubo 60 graus ao redor do eixo X, em seguida, 45 graus ao redor do eixo Z. É possível descrever essa transformação como duas transformações afins discretas, ou como uma matriz. No entanto, talvez seja difícil animar suavemente uma rotação definida dessa maneira. Embora as posições inicial e final do modelo calculadas por quaisquer das abordagem sejam iguais, as posições intermediárias tomadas pelo modelo são computacionalmente incertas. Quaternions representam uma maneira alternativa para calcular a interpolação entre o início e fim de uma rotação.
Um quaternion representa um eixo no espaço 3D em uma rotação ao redor desse eixo. Por exemplo, um quaternion pode representar um eixo (1,1,2) e uma rotação de 50 graus. potência os quatérnios ’ na definição de rotações é proveniente das duas operações que podem ser executadas neles: composição e da interpolação. A composição de dois quaternions aplicados a uma geometria significa "girar a geometria ao redor de axis2 por rotation2, em seguida, girá-la ao redor de axis1 por rotation1." Usando a composição, é possível combinar as duas rotações na geometria para obter um único quaternion que represente o resultado. Como a interpolação de quaternions pode calcular um caminho suave e razoável de um eixo e uma orientação para outros, é possível interpolar do original para o quaternion composto para atingir uma transição suave de um para o outro, permitindo que você anime a transformação. Para modelos a serem animados, é possível especificar um destino Quaternion para a rotação usando um QuaternionRotation3D para a propriedade Rotation.
Usando coleções de transformações
Ao criar uma cena, é comum aplicar mais de uma transformação a um modelo. Adicionar transformações à coleção Children da classe Transform3DGroup para agrupar transformações convenientemente para aplicar a diversos modelos em cena. Muitas vezes é conveniente reutilizar uma transformação em vários grupos diferentes, de uma maneira que você possa reutilizar um modelo aplicando um conjunto diferente de transformações para cada caso. Observe que a ordem na qual as transformações são adicionadas à coleção é significativo: transformações na coleção são aplicadas do primeiro ao último.
Animando Transformações
A implementação 3D Windows Presentation Foundation (WPF) participa do mesmo sistema de animação e tempo que os elementos 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 alterem a posição ou a aparência de modelos. Como as transformações podem ser aplicadas a objetos Model3DGroup bem como a modelos individuais, é possível aplicar um conjunto de animações a um filho de um Model3DGroup e um outro conjunto de animações a um grupo de objetos. Para obter informações detalhadas no sistema de tempo e animação Windows Presentation Foundation (WPF), consulte Revisão de Animação e Visão geral sobre Storyboards.
Para animar um objeto em Windows Presentation Foundation (WPF), crie uma linha de tempo, defina uma animação (que é realmente uma alteração em alguns valores de propriedade ao longo do tempo) e especifique a propriedade à qual deve-se aplicar a animação. Esta propriedade deve ser uma propriedade de um FrameworkElement. Como todos os objetos em uma cena 3D são filhos de ViewPort3D, as propriedades alvo de qualquer animação que se deseja aplicar à cena são propriedades do Viewport3D. É importante preparar o caminho da+ propriedade para a animação cuidadosamente, porque a sintaxe pode ser detalhada.
Suponha que se deseje girar um objeto no local, mas também aplicar um movimento de giro para expor mais do objeto a+ ser visto. É possível 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 aplicando um Vector3DAnimation à propriedade do eixo da Rotation3D da transformação, supondo que o 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));
Vector3DAnimation myVectorAnimation = 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 dimensionar o objeto. Por exemplo, é possível aplicar um Point3DAnimation à propriedade ScaleCenter em uma transformação de escala para fazer com que um modelo distorça suavemente sua forma.
Embora os exemplos anteriores transformem as propriedades de GeometryModel3D, também é possível transformar as propriedades de outros modelos na cena. Animando translações aplicadas a objetos de luz, por exemplo, é possível criar efeitos de luz e sombra com movimento que podem alterar a aparência do seus modelos significativamente.
Como 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 a localização da câmera ou a distância dos planos — com efeito, transformando a projeção toda da cena — observe que muitos dos efeitos conseguidos dessa maneira podem não fazer tanto “sentido visual” para o visualizador como transformações aplicadas ao local ou posição dos modelos em cena.