Vue d'ensemble des transformations 3D
Mise à jour : novembre 2007
Cette rubrique décrit comment appliquer des transformations à des modèles 3D dans le système graphique Windows Presentation Foundation (WPF). Les transformations permettent au développeur de repositionner, redimensionner et réorienter des modèles sans modifier les valeurs de base qui les définissent.
Cette rubrique comprend les sections suivantes.
- Espace de coordonnées 3D
- Transformation de modèles
- Translations
- Transformations d'échelle
- Transformations
- Utilisation de collections de transformations
- Animation de transformations
- Rubriques connexes
Espace de coordonnées 3D
Le contenu graphique 3D Windows Presentation Foundation (WPF) est encapsulé dans un élément, Viewport3D, cette boîte participe à la structure du document à deux dimensions. Le système graphique traite Viewport3D comme un élément visuel à deux dimensions comme de nombreux autres dans Windows Presentation Foundation (WPF). Viewport3D fonctionne comme une fenêtre – une fenêtre d'affichage – dans une scène tridimensionnelle. Plus précisément, c'est une surface sur laquelle une scène 3D est projetée. Même si vous pouvez utiliser Viewport3D avec d'autres objets de dessin 2D dans la même scène graphique, vous ne pouvez pas interpénétrer d'objets 2D et 3D dans un Viewport3D. Dans la discussion suivante, l'espace de coordonnées décrit est contenu par l'élément Viewport3D.
Le système de coordonnées Windows Presentation Foundation (WPF) pour les graphiques 2D localise l'origine dans la partie supérieure gauche de la surface de rendu (en général l'écran). Dans le système 2D, les valeurs d'axe des abscisses positives continuent à droite et les valeurs d'axe des ordonnées positives continuent vers le bas. Dans le système de coordonnées 3D toutefois, l'origine est située dans le centre de l'écran, avec les valeurs d'axe des abscisses positives qui continuent à droite mais les valeurs d'axe des ordonnées positives qui continuent vers le haut, et les valeurs d'axe z positives qui continuent vers l'extérieur de l'origine, vers la visionneuse.
Comparaison de systèmes de coordonnées
L'espace défini par ces axes est le système de référence stationnaire pour les objets 3D dans Windows Presentation Foundation (WPF). Comme vous générez des modèles dans cet espace et créez des lumières et des caméras pour les consulter, il est utile de distinguer ce système de référence stationnaire, ou « espace universel », du système de référence local que vous créez pour chaque modèle lorsque vous lui appliquez des transformations. Souvenez-vous également que les objets dans espace universel peuvent sembler entièrement différents, ou ne pas être visibles du tout, selon les paramètres de lumière et de caméra, mais la position de la caméra ne modifie pas l'emplacement d'objets dans l'espace universel.
Transformation de modèles
Lorsque vous créez des modèles, ils ont un emplacement particulier dans la scène. Pour déplacer ces modèles dans la scène, pour les faire pivoter ou pour modifier leur taille, il n'est pas pratique de modifier les vertex qui définissent les modèles eux-mêmes. À la place, comme en 2D, vous appliquez des transformations aux modèles.
Chaque objet modèle a une propriété Transform avec laquelle vous pouvez déplacer, réorienter ou redimensionner le modèle. Lorsque vous appliquez une transformation, vous compensez efficacement tous les points du modèle par n'importe quel vecteur ou valeur spécifié par la transformation. En d'autres termes, vous avez transformé l'espace de coordonnées dans lequel le modèle est défini (« espace modèle »), mais vous n'avez pas modifié les valeurs qui composent la géométrie du modèle dans le système de coordonnées de la scène entière (« espace universel »).
Translations
Les transformations 3D héritent de la classe de base abstraite Transform3D ; elles incluent les classes de transformation affines TranslateTransform3D, ScaleTransform3D et RotateTransform3D. Le système 3D Windows Presentation Foundation (WPF) fournit également une classe MatrixTransform3D qui vous permet de spécifier les mêmes transformations en opérations de matrice plus concises.
TranslateTransform3D déplace tous les points du modèle 3D dans le sens du vecteur d'offset que vous spécifiez avec les propriétés OffsetX, OffsetY et OffsetZ. Par exemple, avec un vertex de cube à (2,2,2), un vecteur d'offset de (0,1.6,1) déplacerait ce vertex (2,2,2) à (2,3.6,3). Le vertex du cube est toujours (2,2,2) dans l'espace modèle, mais désormais cet espace modèle a modifié sa relation avec l'espace universel de sorte que (2,2,2) dans l'espace modèle devient (2,3.6,3) dans l'espace universel.
Translation avec offset
Les exemples de code suivants montrent comment appliquer une translation.
<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>
Transformations d'échelle
ScaleTransform3D modifie l'échelle du modèle à l'aide d'un vecteur d'échelle spécifié avec une référence à un point central. Spécifiez une échelle uniforme, qui met le modèle à l'échelle avec la même valeur pour les axes X, Y et Z, pour modifier la taille du modèle proportionnellement. Par exemple, affecter la valeur 0,5 aux propriétés ScaleX, ScaleY et ScaleZ de la transformation divise par deux la taille du modèle ; affecter la valeur 2 aux mêmes propriétés double son échelle pour les trois axes.
Exemple de vecteur d'échelle
En spécifiant une transformation d'échelle non uniforme – une transformation d'échelle dont les valeurs X, Y et Z ne sont pas les mêmes – une ou deux dimensions du modèle peuvent être étirées ou contractées sans que cela n'affecte les autres. Par exemple, affecter la valeur 1 à ScaleX, la valeur 2 à ScaleY et la valeur 1 à ScaleZ doublerait la hauteur du modèle sans le modifier au niveau des axes X et Z.
Par défaut, ScaleTransform3D entraîne l'étirement ou la contraction des vertex autour de l'origine (0,0,0). Si le modèle que vous souhaitez transformer n'est pas dessiné à partir de l'origine, toutefois, la mise à l'échelle du modèle à partir de l'origine ne mettra pas le modèle à l'échelle « sur place ». À la place, lorsque les vertex du modèle sont multipliés par le vecteur d'échelle, l'opération de mise à l'échelle entraînera la translation du modèle ainsi que sa mise à l'échelle.
Exemple de centre d'échelle
Pour mettre un modèle à l'échelle « sur place », spécifiez le centre du modèle en définissant les propriétés CenterX, CenterY et CenterZ de ScaleTransform3D. Cela garantit que le système graphique met l'espace modèle à l'échelle puis le translate vers le centre du Point3D spécifié. Inversement, si vous avez généré le modèle par rapport à l'origine et que vous spécifiez un autre point, vous devez vous attendre à ce que la transformation du modèle l'éloigne de l'origine.
Transformations
Vous pouvez faire pivoter un modèle en 3D de différentes manières. Une rotation classique spécifie un axe et un angle de rotation autour de cet axe. La classe RotateTransform3D vous permet de définir une Rotation3D avec sa propriété Rotation. Vous spécifiez ensuite les propriétés Axis et Angle sur la Rotation3D, dans ce cas AxisAngleRotation3D, pour définir la transformation. Les exemples suivants font pivoter un modèle de 60 degrés autour de l'axe 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>
Remarque : Windows Presentation Foundation (WPF) 3D est un système situé à droite, c'est-à-dire qu'une valeur d'angle positive pour une rotation entraîne une rotation dans le sens inverse des aiguilles d'une montre autour de l'axe.
Les rotations d'axe/d'angle effectuent une rotation autour de l'origine si une valeur n'est pas spécifiée pour les propriétés CenterX, CenterY et CenterZ sur RotateTransform3D. Comme pour la mise à l'échelle, n'oubliez pas que la rotation transforme la totalité de l'espace de coordonnées du modèle. Si le modèle n'a pas été créé par rapport à l'origine ou qu'il a d'abord été translaté, la rotation peut s'effectuer autour de l'origine au lieu de s'effectuer sur place.
Rotation avec spécification d'un nouveau centre
Pour faire pivoter le modèle « sur place », spécifiez l'actuel centre du modèle comme centre de la rotation. Étant donné que la géométrie est généralement modelée par rapport à l'origine, vous pouvez, la plupart du temps, obtenir le résultat attendu d'un ensemble de transformations en redimensionnant d'abord le modèle (mise à l'échelle), puis en définissant son orientation (rotation) et en le déplaçant enfin à l'emplacement souhaité (translation).
Exemple de rotation
Les rotations d'axe/d'angle fonctionnent bien pour les transformations statiques et certaines animations. Toutefois, envisagez la rotation d'un modèle de cube de 60 degrés autour de l'axe X, puis de 45 degrés autour de l'axe Z. Vous pouvez décrire cette transformation sous forme de deux transformations affines discrètes ou sous forme de matrice. Toutefois, il peut être difficile d'animer souplement une rotation définie de cette façon. Même si les positions de début et de fin du modèle calculées par chacune des approches sont les mêmes, les positions intermédiaires par lesquelles passe le modèle sont incertaines en terme de calcul. Les quaternions représentent une autre façon de calculer l'interpolation entre le début et la fin d'une rotation.
Un quaternion représente un axe dans un espace en trois dimensions et une rotation autour de cet axe. Par exemple, un quaternion peut représente un axe (1,1,2) et une rotation de 50 degrés. La capacité des quaternions à définir des rotations vient des deux opérations qu'ils peuvent gérer : composition et interpolation. La composition de deux quaternions appliquée à une géométrie signifie « fait pivoter la géométrie autour de l'axe2 via la rotation2, puis la fait pivoter autour de l'axe1 via la rotation1 ». À l'aide de la composition, vous pouvez combiner les deux rotations sur la géométrie pour obtenir un seul quaternion qui représente le résultat. Étant donné que l'interpolation de quaternion peut calculer un chemin souple et raisonnable à partir d'un axe et un sens vers un autre, vous pouvez interpoler à partir de l'original vers le quaternion composé pour effectuer une transition en souplesse de l'un à l'autre, ce qui vous permet d'animer la transformation. Pour les modèles que vous souhaitez animer, vous pouvez spécifier une destination Quaternion pour la rotation à l'aide de QuaternionRotation3D pour la propriété Rotation.
Utilisation de collections de transformations
Lorsque vous générez une scène, il est courant d'appliquer plusieurs transformations à un modèle. Ajoutez des transformations à la collection Children de la classe Transform3DGroup pour regrouper facilement les transformations à appliquer aux différents modèles de la scène. Il est souvent commode de réutiliser une transformation dans plusieurs groupes, de même que vous pouvez réutiliser un modèle en appliquant un ensemble de transformations différent à chaque instance. Notez que l'ordre dans lequel les transformations sont ajoutées à la collection est important : les transformations dans la collection sont appliquées de la première à la dernière.
Animation de transformations
L'implémentation Windows Presentation Foundation (WPF) 3D participe au même système de minutage et d'animation que les graphiques 2D. En d'autres termes, pour animer une scène 3D, animez les propriétés de ses modèles. Il est possible d'animer directement des propriétés de primitives, mais il est en général plus facile d'animer des transformations qui modifient la position ou l'apparence de modèles. Étant donné que les transformations peuvent être appliquées aux objets Model3DGroup aussi bien qu'aux modèles individuels, il est possible d'appliquer un ensemble d'animations à l'enfant d'un Model3DGroup et un autre ensemble d'animations à un groupe d'objets. Pour plus d'informations générales sur le système Windows Presentation Foundation (WPF) de minutage et d'animation, consultez les rubriques Vue d'ensemble de l'animation et Vue d'ensemble des tables de montage séquentiel.
Pour animer un objet dans Windows Presentation Foundation (WPF), créez une chronologie, définissez une animation (qui est en fait une modification de quelques valeurs de propriété dans le temps) et spécifiez la propriété à laquelle appliquer l'animation. Cette propriété doit être une propriété d'un FrameworkElement. Étant donné que tous les objets dans une scène 3D sont enfants de Viewport3D, les propriétés ciblées par toute animation que vous souhaitez appliquer à la scène sont des propriétés de propriétés de Viewport3D. Il est important d'élaborer le chemin de la propriété pour l'animation avec précaution, car la syntaxe peut être détaillée.
Supposons que vous souhaitez faire pivoter un objet sur place, mais également lui appliquer un mouvement de balancier pour afficher une plus grande partie de l'objet. Vous pouvez choisir d'appliquer un RotateTransform3D au modèle et d'animer l'axe de sa rotation d'un vecteur à un autre. L'exemple de code suivant montre l'application d'un Vector3DAnimation à la propriété Axis du Rotation3D de la transformation, en supposant que le RotateTransform3D soit l'une des multiples transformations appliquées au modèle avec un 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;
Utilisez une syntaxe similaire pour cibler d'autres propriétés de transformation pour déplacer l'objet ou le mettre à l'échelle. Par exemple, vous pouvez appliquer un Point3DAnimation à la propriété ScaleCenter sur une mise à l'échelle pour entraîner une légère distorsion de la forme d'un modèle.
Même si les exemples précédents transforment les propriétés de GeometryModel3D, il est également possible de transformer les propriétés d'autres modèles dans la scène. En animant des translations appliquées aux objets Light, par exemple, vous pouvez créer des effets de lumière et d'ombre mobiles qui peuvent modifier l'apparence de vos modèles de manière significative.
Étant donné que les caméras sont également des modèles, il est également possible de transformer les propriétés de caméra. Même si vous pouvez certainement modifier l'apparence de la scène en modifiant l'emplacement de la caméra ou les distances du plan – en réalité, en modifiant toute la projection de scène – notez que bon nombre des effets que vous obtenez de cette façon peuvent ne pas avoir autant d'impact visuel sur la visionneuse que les transformations appliquées à l'emplacement ou à la position des modèles dans la scène.