Información general sobre gráficos 3D

La funcionalidad 3D de Windows Presentation Foundation (WPF) permite a los desarrolladores dibujar, transformar y animar gráficos 3D tanto en código de marcado como procedimental. Los desarrolladores pueden combinar gráficos 2D y 3D para crear controles enriquecidos, proporcionar ilustraciones complejas de datos o mejorar la experiencia del usuario de la interfaz de una aplicación. La compatibilidad con 3D en WPF no está diseñada para proporcionar una plataforma de desarrollo de juegos completa. En este tema se proporciona información general sobre la funcionalidad 3D en el sistema de gráficos de WPF.

3D en un contenedor 2D

El contenido de los gráficos 3D de WPF se encapsula en un elemento, Viewport3D, que puede participar en la estructura de elementos bidimensionales. El sistema de gráficos trata los objetos Viewport3D como elementos visuales bidimensionales, al igual que ocurre con muchos otros elementos de WPF. Viewport3D funciona como ventana (una ventanilla) de una escena tridimensional. Más concretamente, es una superficie en la que se proyecta una escena 3D.

En una aplicación 2D convencional, utilice Viewport3D como cualquier otro elemento contenedor, como Grid o Canvas. Aunque puede usar Viewport3D con otros objetos de dibujo 2D en el mismo gráfico de escena, no puede interpenetrar objetos 2D y 3D en un Viewport3D. Este tema se centrará en cómo dibujar gráficos 3D dentro de Viewport3D.

Espacio de coordenadas 3D

El sistema de coordenadas de WPF para gráficos 2D localiza el origen en la parte superior izquierda del área de representación (que suele ser la pantalla). En el sistema 2D, los valores positivos del eje X se extienden hacia la derecha, y los valores positivos del eje Y se extienden hacia abajo. En el sistema de coordenadas 3D, sin embargo, el origen se encuentra en el centro del área de representación, de manera que los valores positivos del eje X se extienden hacia la derecha, los valores positivos del eje Y se extienden hacia arriba (no hacia abajo) y los valores positivos del eje Z se extienden hacia el exterior partiendo del origen, es decir, hacia el espectador.

Sistemas de coordenadas
Representaciones convencionales de los sistemas de coordenadas 2D y 3D

El espacio definido por estos ejes es el marco estático de referencia para los objetos 3D en WPF. Cuando se generan modelos en este espacio y se crean luces y cámaras para verlos, es útil distinguir este marco estático de referencia, o "espacio universal", del marco de referencia local creado para cada modelo al aplicarle transformaciones. Recuerde también que los objetos del espacio universal podrían parecer completamente diferentes, o incluso no verse en absoluto, dependiendo de la configuración de las luces y la cámara, pero que la posición de la cámara no cambia la ubicación de los objetos en el espacio universal.

Cámaras y proyecciones

Los desarrolladores que trabajan en 2D están acostumbrados a colocar los elementos de dibujo primitivos en una pantalla bidimensional. Al crear una escena 3D, es importante recordar que, en realidad, se está creando una representación 2D de los objetos 3D. Dado que una escena 3D tiene un aspecto diferente dependiendo del punto de vista del espectador, debe especificar ese punto de vista. La clase Camera le permite especificar este punto de vista para una escena 3D.

Otra manera de entender cómo se representa una escena 3D en una superficie 2D consiste en describir dicha escena como una proyección sobre la superficie de visualización. ProjectionCamera permite especificar proyecciones diferentes y sus propiedades para cambiar la manera en que el espectador ve los modelos 3D. PerspectiveCamera especifica una proyección que escorza la escena. En otras palabras, PerspectiveCamera proporciona una perspectiva de punto de desvanecimiento. Puede especificar la posición de la cámara en el espacio de coordenadas de la escena, la dirección y el campo de visión de la cámara y un vector que define la dirección de "arriba" en la escena. En el diagrama siguiente se muestra la proyección de PerspectiveCamera.

Las propiedades NearPlaneDistance y FarPlaneDistance de ProjectionCamera limitan el intervalo de la proyección de la cámara. Dado que las cámaras se pueden ubicar en cualquier parte de la escena, es posible situarlas dentro de un modelo o muy cerca de él, con lo que resultaría difícil distinguir correctamente los objetos. NearPlaneDistance le permite especificar una distancia mínima desde la cámara más allá de la cual no se dibujarán objetos. A la inversa, FarPlaneDistance le permite especificar una distancia máxima a la cámara, más allá de la cual no se dibujarán objetos, lo que garantiza que no se incluyen en la escena aquellos objetos que estén demasiado lejos para ser reconocibles.

Configuración de la cámara
Posición de la cámara

OrthographicCamera especifica una proyección ortogonal de un modelo 3D en una superficie visual 2D. Al igual que otras cámaras, especifica una posición, dirección de visualización y dirección "hacia arriba". Sin embargo, a diferencia de PerspectiveCamera, OrthographicCamera describe una proyección que no incluye el escorzamiento de la perspectiva. Es decir, OrthographicCamera describe un cuadro de vista cuyos lados son paralelos, en lugar de uno cuyos lados convergen en un punto de la cámara. En la imagen siguiente se muestra el mismo modelo tal y como se ve usando PerspectiveCamera y OrthographicCamera.

Proyección ortográfica y en perspectiva
Proyecciones ortográfica y en perspectiva

En el código siguiente se muestran algunas configuraciones de cámara típicas.

// Defines the camera used to view the 3D object. In order to view the 3D object,
// the camera must be positioned and pointed such that the object is within view
// of the camera.
PerspectiveCamera myPCamera = new PerspectiveCamera();

// Specify where in the 3D scene the camera is.
myPCamera.Position = new Point3D(0, 0, 2);

// Specify the direction that the camera is pointing.
myPCamera.LookDirection = new Vector3D(0, 0, -1);

// Define camera's horizontal field of view in degrees.
myPCamera.FieldOfView = 60;

// Asign the camera to the viewport
myViewport3D.Camera = myPCamera;
' Defines the camera used to view the 3D object. In order to view the 3D object,
' the camera must be positioned and pointed such that the object is within view 
' of the camera.
Dim myPCamera As New PerspectiveCamera()

' Specify where in the 3D scene the camera is.
myPCamera.Position = New Point3D(0, 0, 2)

' Specify the direction that the camera is pointing.
myPCamera.LookDirection = New Vector3D(0, 0, -1)

' Define camera's horizontal field of view in degrees.
myPCamera.FieldOfView = 60

' Asign the camera to the viewport
myViewport3D.Camera = myPCamera

Elementos primitivos de modelo y de malla

Model3D es la clase base abstracta que representa un objeto 3D genérico. Para compilar una escena 3D, necesita algunos objetos que ver; los objetos que componen el gráfico de escena se derivan de la clase Model3D. Actualmente, WPF admite geometrías de modelado con GeometryModel3D. La propiedad Geometry de este modelo toma un elemento primitivo de malla.

Para crear un modelo, comience por crear un elemento primitivo, o malla. Un elemento 3D primitivo es una colección de vértices que constituyen una entidad 3D única. La mayoría de los sistemas 3D proporcionan elementos primitivos modelados a partir de la figura cerrada más simple: un triángulo definido por tres vértices. Dado que los tres puntos de un triángulo son coplanares, puede seguir agregando triángulos para modelar formas más complejas, denominadas mallas.

El sistema 3D de WPF proporciona actualmente la clase MeshGeometry3D, que permite especificar cualquier geometría; en este momento, no admite elementos 3D primitivos predefinidos, tales como esferas o formas cúbicas. Empiece a crear un elemento MeshGeometry3D especificando una lista de vértices triangulares como su propiedad Positions. Cada vértice se especifica como un elemento Point3D. (En XAML, especifique esta propiedad como una lista de números agrupados en ternas, que representan las coordenadas de cada vértice). Según cuál sea la geometría, la malla puede estar compuesta de muchos triángulos, algunos de los cuales compartirán las mismas esquinas (vértices). WPF necesita información sobre qué triángulos comparten qué vértices para dibujar la malla correctamente. Esta información se proporciona especificando una lista de índices triangulares con la propiedad TriangleIndices. Esta lista especifica el orden en que los puntos especificados en la lista Positions determinarán un triángulo.

<GeometryModel3D>
  <GeometryModel3D.Geometry>
          <MeshGeometry3D 
              Positions="-1 -1 0  1 -1 0  -1 1 0  1 1 0"
              Normals="0 0 1  0 0 1  0 0 1  0 0 1"
              TextureCoordinates="0 1  1 1  0 0  1 0   "
              TriangleIndices="0 1 2  1 3 2" />
      </GeometryModel3D.Geometry>
      <GeometryModel3D.Material>
          <DiffuseMaterial>
              <DiffuseMaterial.Brush>
                  <SolidColorBrush Color="Cyan" Opacity="0.3"/>
              </DiffuseMaterial.Brush>
          </DiffuseMaterial>
      </GeometryModel3D.Material>
  <!-- Translate the plane. -->
      <GeometryModel3D.Transform>
          <TranslateTransform3D
            OffsetX="2" OffsetY="0" OffsetZ="-1"   >
          </TranslateTransform3D>
      </GeometryModel3D.Transform>
  </GeometryModel3D>

En el ejemplo anterior, la lista de Positions especifica cuatro vértices para definir una malla de rectángulo. La propiedad TriangleIndices especifica una lista de dos grupos de tres índices. Cada número de la lista hace referencia a un desplazamiento en la lista Positions. Por ejemplo, los tres primeros vértices especificados por la lista de Positions son (-1,-1,0), (1,-1,0) y (-1,1,0). Los tres primeros índices especificados por la lista de TriangleIndices son 0, 1 y 2, que corresponden al primer, segundo y tercer puntos de la lista de Positions. Como resultado, el primer triángulo que compone el modelo de rectángulo se compondrá de (-1,-1,0) a (1,-1,0) a (-1,1,0), y el segundo triángulo se determinará de forma similar.

Puede continuar definiendo el modelo especificando valores para las propiedades Normals y TextureCoordinates. Para representar la superficie del modelo, el sistema de gráficos necesita información sobre en qué dirección mira la superficie de cualquier triángulo dado. Utiliza esta información para realizar los cálculos de iluminación del modelo: las superficies que miran directamente hacia una fuente de luz parecen más luminosas que las que tienen un ángulo que las oculta de la luz. Aunque WPF puede determinar los vectores normales predeterminados utilizando las coordenadas de posición, también es posible especificar vectores normales diferentes para crear un aspecto más aproximado de las superficies curvas.

La propiedad TextureCoordinates especifica una colección de Point que indican al sistema de gráficos cómo asignar las coordenadas que determinan cómo se dibuja una textura en los vértices de la malla. TextureCoordinates se especifican como un valor entre cero y uno, ambos incluidos. Como sucede con la propiedad Normals, el sistema de gráficos puede calcular las coordenadas de textura predeterminadas, pero si lo desea puede establecer coordenadas de textura diferentes a fin de controlar la asignación de una textura que incluya parte de un patrón repetitivo, por ejemplo. Encontrará más información sobre coordenadas de textura en los temas siguientes o en el SDK de Managed Direct3D.

En el ejemplo siguiente se muestra cómo crear una cara del modelo del cubo en código de procedimiento. Puede dibujar el cubo completo como un solo objeto GeometryModel3D; en este ejemplo se dibuja la cara del cubo como un modelo distinto a fin de aplicar después texturas independientes a cada cara.

MeshGeometry3D side1Plane = new MeshGeometry3D();
Private side1Plane As New MeshGeometry3D()
side1Plane.Positions.Add(new Point3D(-0.5, -0.5, -0.5));
side1Plane.Positions.Add(new Point3D(-0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, -0.5, -0.5));
side1Plane.Positions.Add(new Point3D(-0.5, -0.5, -0.5));

side1Plane.TriangleIndices.Add(0);
side1Plane.TriangleIndices.Add(1);
side1Plane.TriangleIndices.Add(2);
side1Plane.TriangleIndices.Add(3);
side1Plane.TriangleIndices.Add(4);
side1Plane.TriangleIndices.Add(5);

side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));

side1Plane.TextureCoordinates.Add(new Point(1, 0));
side1Plane.TextureCoordinates.Add(new Point(1, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 0));
side1Plane.TextureCoordinates.Add(new Point(1, 0));
side1Plane.Positions.Add(New Point3D(-0.5, -0.5, -0.5))
side1Plane.Positions.Add(New Point3D(-0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, -0.5, -0.5))
side1Plane.Positions.Add(New Point3D(-0.5, -0.5, -0.5))

side1Plane.TriangleIndices.Add(0)
side1Plane.TriangleIndices.Add(1)
side1Plane.TriangleIndices.Add(2)
side1Plane.TriangleIndices.Add(3)
side1Plane.TriangleIndices.Add(4)
side1Plane.TriangleIndices.Add(5)

side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))

side1Plane.TextureCoordinates.Add(New Point(1, 0))
side1Plane.TextureCoordinates.Add(New Point(1, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 0))
side1Plane.TextureCoordinates.Add(New Point(1, 0))

'

Aplicación de materiales al modelo

Para que una malla parezca un objeto tridimensional, debe tener una textura aplicada que cubra la superficie definida por sus vértices y triángulos, de manera que se pueda iluminar y proyectar por la cámara. En 2D, se usa la clase Brush para aplicar colores, patrones, degradados y otro contenido visual en áreas de la pantalla. El aspecto de los objetos 3D, sin embargo, depende del modelo de iluminación, no solo del color o del patrón que se les aplica. Los objetos reales reflejan la luz de manera distinta según la calidad de su superficie: las superficies satinadas y brillantes no tienen el mismo aspecto que las superficies ásperas o mates, y algunos objetos parecen absorber la luz, mientras que otros la emiten. Puede aplicar a los objetos 3D los mismos pinceles que a los objetos 2D, pero no directamente.

Para definir las características de la superficie de un modelo, WPF usa la clase abstracta Material. Las subclases concretas de Material determinan algunas de las características del aspecto de la superficie del modelo y, además, cada una de ellas proporciona una propiedad Brush a la que puede pasar SolidColorBrush, TileBrush o VisualBrush.

  • DiffuseMaterial especifica que el pincel se aplicará al modelo como si estuviera iluminado con una luz difusa. Utilizar DiffuseMaterial es lo que más se parece al uso directo de pinceles en los modelos 2D; las superficies del modelo no reflejan la luz como si brillasen.

  • SpecularMaterial especifica que el pincel se aplicará al modelo como si la superficie de este fuese dura o brillante, capaz de reflejar la iluminación. Puede establecer el grado en que la textura sugerirá esta cualidad de reflexión, o "brillo", especificando un valor para la propiedad SpecularPower.

  • EmissiveMaterial permite especificar que la textura se aplicará como si el modelo estuviera emitiendo luz del mismo color que el pincel. Esto no convierte el modelo en una luz; sin embargo, participará de manera diferente en el sombreado que si se aplica textura con DiffuseMaterial o SpecularMaterial.

Para mejorar rendimiento, las caras ocultas de GeometryModel3D (aquellas que están fuera de la vista porque se encuentran en el lado del modelo opuesto a la cámara) se seleccionan de la escena. Para especificar un elemento Material que se va a aplicar en la cara posterior de un modelo como un plano, establezca la propiedad BackMaterial del modelo.

Para lograr algunas cualidades de la superficie, como el brillo o los efectos de reflejo, puede ser conveniente aplicar sucesivamente varios pinceles diferentes a un modelo. Puede aplicar y reutilizar varios materiales mediante la clase MaterialGroup. Los elementos secundarios de MaterialGroup se aplican del primero al último en varias pasadas de representación.

En los ejemplos de código siguientes se muestra cómo aplicar un color sólido y un dibujo como pinceles a los modelos 3D.

<GeometryModel3D.Material>
    <DiffuseMaterial>
        <DiffuseMaterial.Brush>
            <SolidColorBrush Color="Cyan" Opacity="0.3"/>
        </DiffuseMaterial.Brush>
    </DiffuseMaterial>
</GeometryModel3D.Material>
<DrawingBrush x:Key="patternBrush" Viewport="0,0,0.1,0.1" TileMode="Tile">
  <DrawingBrush.Drawing>
    <DrawingGroup>
      <DrawingGroup.Children>
        <GeometryDrawing Geometry="M0,0.1 L0.1,0 1,0.9, 0.9,1z"
          Brush="Gray" />
        <GeometryDrawing Geometry="M0.9,0 L1,0.1 0.1,1 0,0.9z"
          Brush="Gray" />
        <GeometryDrawing Geometry="M0.25,0.25 L0.5,0.125 0.75,0.25 0.5,0.5z"
          Brush="#FFFF00" />
        <GeometryDrawing Geometry="M0.25,0.75 L0.5,0.875 0.75,0.75 0.5,0.5z"
          Brush="Black" />
        <GeometryDrawing Geometry="M0.25,0.75 L0.125,0.5 0.25,0.25 0.5,0.5z"
          Brush="#FF0000" />
        <GeometryDrawing Geometry="M0.75,0.25 L0.875,0.5 0.75,0.75 0.5,0.5z"
          Brush="MediumBlue" />
      </DrawingGroup.Children>
    </DrawingGroup>
  </DrawingBrush.Drawing>
</DrawingBrush>
DiffuseMaterial side5Material = new DiffuseMaterial((Brush)Application.Current.Resources["patternBrush"]);
Dim side5Material As New DiffuseMaterial(CType(Application.Current.Resources("patternBrush"), Brush))

Iluminación de la escena

Las luces de los gráficos 3D hacen lo mismo que las luces en el mundo real: permiten ver las superficies. Más concretamente, las luces determinan qué parte de una escena se incluye en la proyección. Los objetos de luz en WPF crean gran variedad de efectos de luz y sombra y siguen el modelo de comportamiento de diversas luces del mundo real. Incluya por lo menos una luz en la escena, pues de lo contrario no habrá ningún modelo visible.

Las siguientes luces se derivan de la clase base Light:

  • AmbientLight: proporciona iluminación de ambiente que ilumina uniformemente todos los objetos sin tener en cuenta su ubicación u orientación.

  • DirectionalLight: ilumina como una fuente de luz distante. Las luces direccionales tienen un elemento Direction especificado como un vector 3D, pero no tienen una ubicación especificada.

  • PointLight: ilumina como una fuente de luz cercana. Las luces puntuales tienen posición y emiten la luz desde esa posición. Los objetos de la escena se iluminan dependiendo de su posición y distancia con respecto a la luz. PointLightBase expone una propiedad Range, que determina una distancia más allá de la cual no la luz no iluminará los modelos. PointLight también expone propiedades de atenuación, que determinan cómo disminuye la intensidad de la luz con la distancia. Puede especificar interpolaciones constantes, lineales o cuadráticas para la atenuación de la luz.

  • SpotLight: se hereda de PointLight. Los focos de luz iluminan como las luces puntuales, y tienen posición y dirección. Proyectan la luz en un área cónica establecida mediante las propiedades InnerConeAngle y OuterConeAngle, que se especifica en grados.

Las luces son objetos Model3D, por lo que puede transformar y animar las propiedades de la luz, incluidas su posición, color, dirección y alcance.

<ModelVisual3D.Content>
    <AmbientLight Color="#333333" />
</ModelVisual3D.Content>
DirectionalLight myDirLight = new DirectionalLight();
Private myDirLight As New DirectionalLight()
myDirLight.Color = Colors.White;
myDirLight.Direction = new Vector3D(-3, -4, -5);
myDirLight.Color = Colors.White
myDirLight.Direction = New Vector3D(-3, -4, -5)
modelGroup.Children.Add(myDirLight);
modelGroup.Children.Add(myDirLight)

Transformación de modelos

Al crear modelos, estos tienen una ubicación determinada en la escena. Para mover esos modelos por la escena, girarlos o cambiar su tamaño, no es práctico cambiar los vértices que definen los propios modelos. En lugar de ello, al igual que en 2D, se aplican transformaciones a los modelos.

Cada objeto del modelo tiene una propiedad Transform con la que puede mover, reorientar o dimensionar el modelo. Al aplicar una transformación, en realidad lo que se hace es desplazar todos los puntos del modelo según un vector o valor especificado por la transformación. Es decir, se transforma el espacio de coordenadas en el que se ha definido el modelo ("espacio del modelo"), pero no se cambian los valores que constituyen la geometría del modelo en el sistema de coordenadas de la escena completa ("espacio universal").

Para obtener más información acerca de la transformación de modelos, consulte Información general sobre transformaciones de modelos 3D.

Animación de modelos

La implementación 3D en WPF utiliza el mismo sistema de control de tiempo y animación que los gráficos 2D. En otras palabras, para animar una escena 3D, se animan las propiedades de sus modelos. Es posible animar directamente las propiedades de los elementos primitivos, pero suele ser más fácil animar las transformaciones que cambian la posición o el aspecto de los modelos. Dado que las transformaciones se pueden aplicar a los objetos Model3DGroup así como a los modelos individuales, es posible de aplicar un conjunto de animaciones a un elemento secundario de Model3DGroup y otro conjunto de animaciones a un grupo de objetos secundarios. También puede lograr gran variedad de efectos visuales animando las propiedades de iluminación de la escena. Finalmente, si lo desea, puede animar la propia proyección, animando la posición de la cámara o el campo de visión. Para obtener información general sobre el sistema de control de tiempo y animación de WPF, consulte los temas Información general sobre animaciones, Información general sobre guiones gráficos e Información general sobre objetos Freezable.

Para animar un objeto en WPF, se crea una escala de tiempo, se define una animación (que, en realidad, es un cambio de algún valor de propiedad a lo largo del tiempo) y se especifica la propiedad a la que aplicar la animación. Dado que todos los objetos de una escena 3D son elementos secundarios de Viewport3D, las propiedades de destino de cualquier animación que desea aplicar a la escena son propiedades de Viewport3D.

Supongamos que desea hacer que un modelo parezca tambalearse en su lugar. Podría aplicar RotateTransform3D al modelo y animar el eje de giro de un vector a otro. En el ejemplo de código siguiente se muestra cómo aplicar Vector3DAnimation a la propiedad Axis de la propiedad Rotation3D de la transformación, suponiendo que RotateTransform3D es una de las diversas transformaciones aplicadas al modelo con 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
myRotateTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AxisProperty, myVectorAnimation);
myRotateTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AxisProperty, myVectorAnimation)
//Add transformation to the model
cube1TransformGroup.Children.Add(myRotateTransform);
'Add transformation to the model
cube1TransformGroup.Children.Add(myRotateTransform)

Incorporación de contenido 3D a la ventana

Para representar la escena, agregue modelos y luces a Model3DGroup y, a continuación, establezca Model3DGroup como Content de ModelVisual3D. Agregue ModelVisual3D a la colección Children de Viewport3D. Agregue cámaras a Viewport3D estableciendo su propiedad Camera.

Finalmente, agregue Viewport3D a la ventana. Cuando Viewport3D se incluye como contenido de un elemento de diseño como Canvas, especifique el tamaño de Viewport3D estableciendo sus propiedades Height y Width (heredadas de FrameworkElement).

<UserControl x:Class="HostingWpfUserControlInWf.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    >
  
    <Grid>

      <!-- Place a Label control at the top of the view. -->
      <Label 
                HorizontalAlignment="Center" 
                TextBlock.TextAlignment="Center" 
                FontSize="20" 
                Foreground="Red" 
                Content="Model: Cone"/>

      <!-- Viewport3D is the rendering surface. -->
      <Viewport3D Name="myViewport" >

        <!-- Add a camera. -->
        <Viewport3D.Camera>
          <PerspectiveCamera 
                        FarPlaneDistance="20" 
                        LookDirection="0,0,1" 
                        UpDirection="0,1,0" 
                        NearPlaneDistance="1" 
                        Position="0,0,-3" 
                        FieldOfView="45" />
        </Viewport3D.Camera>

        <!-- Add models. -->
        <Viewport3D.Children>

          <ModelVisual3D>
            <ModelVisual3D.Content>

              <Model3DGroup >
                <Model3DGroup.Children>

                  <!-- Lights, MeshGeometry3D and DiffuseMaterial objects are added to the ModelVisual3D. -->
                  <DirectionalLight Color="#FFFFFFFF" Direction="3,-4,5" />

                  <!-- Define a red cone. -->
                  <GeometryModel3D>

                    <GeometryModel3D.Geometry>
                      <MeshGeometry3D 
    Positions="0.293893 -0.5 0.404509  0.475528 -0.5 0.154509  0 0.5 0  0.475528 -0.5 0.154509  0 0.5 0  0 0.5 0  0.475528 -0.5 0.154509  0.475528 -0.5 -0.154509  0 0.5 0  0.475528 -0.5 -0.154509  0 0.5 0  0 0.5 0  0.475528 -0.5 -0.154509  0.293893 -0.5 -0.404509  0 0.5 0  0.293893 -0.5 -0.404509  0 0.5 0  0 0.5 0  0.293893 -0.5 -0.404509  0 -0.5 -0.5  0 0.5 0  0 -0.5 -0.5  0 0.5 0  0 0.5 0  0 -0.5 -0.5  -0.293893 -0.5 -0.404509  0 0.5 0  -0.293893 -0.5 -0.404509  0 0.5 0  0 0.5 0  -0.293893 -0.5 -0.404509  -0.475528 -0.5 -0.154509  0 0.5 0  -0.475528 -0.5 -0.154509  0 0.5 0  0 0.5 0  -0.475528 -0.5 -0.154509  -0.475528 -0.5 0.154509  0 0.5 0  -0.475528 -0.5 0.154509  0 0.5 0  0 0.5 0  -0.475528 -0.5 0.154509  -0.293892 -0.5 0.404509  0 0.5 0  -0.293892 -0.5 0.404509  0 0.5 0  0 0.5 0  -0.293892 -0.5 0.404509  0 -0.5 0.5  0 0.5 0  0 -0.5 0.5  0 0.5 0  0 0.5 0  0 -0.5 0.5  0.293893 -0.5 0.404509  0 0.5 0  0.293893 -0.5 0.404509  0 0.5 0  0 0.5 0  " 
    Normals="0.7236065,0.4472139,0.5257313  0.2763934,0.4472138,0.8506507  0.5308242,0.4294462,0.7306172  0.2763934,0.4472138,0.8506507  0,0.4294458,0.9030925  0.5308242,0.4294462,0.7306172  0.2763934,0.4472138,0.8506507  -0.2763934,0.4472138,0.8506507  0,0.4294458,0.9030925  -0.2763934,0.4472138,0.8506507  -0.5308242,0.4294462,0.7306172  0,0.4294458,0.9030925  -0.2763934,0.4472138,0.8506507  -0.7236065,0.4472139,0.5257313  -0.5308242,0.4294462,0.7306172  -0.7236065,0.4472139,0.5257313  -0.858892,0.429446,0.279071  -0.5308242,0.4294462,0.7306172  -0.7236065,0.4472139,0.5257313  -0.8944269,0.4472139,0  -0.858892,0.429446,0.279071  -0.8944269,0.4472139,0  -0.858892,0.429446,-0.279071  -0.858892,0.429446,0.279071  -0.8944269,0.4472139,0  -0.7236065,0.4472139,-0.5257313  -0.858892,0.429446,-0.279071  -0.7236065,0.4472139,-0.5257313  -0.5308242,0.4294462,-0.7306172  -0.858892,0.429446,-0.279071  -0.7236065,0.4472139,-0.5257313  -0.2763934,0.4472138,-0.8506507  -0.5308242,0.4294462,-0.7306172  -0.2763934,0.4472138,-0.8506507  0,0.4294458,-0.9030925  -0.5308242,0.4294462,-0.7306172  -0.2763934,0.4472138,-0.8506507  0.2763934,0.4472138,-0.8506507  0,0.4294458,-0.9030925  0.2763934,0.4472138,-0.8506507  0.5308249,0.4294459,-0.7306169  0,0.4294458,-0.9030925  0.2763934,0.4472138,-0.8506507  0.7236068,0.4472141,-0.5257306  0.5308249,0.4294459,-0.7306169  0.7236068,0.4472141,-0.5257306  0.8588922,0.4294461,-0.27907  0.5308249,0.4294459,-0.7306169  0.7236068,0.4472141,-0.5257306  0.8944269,0.4472139,0  0.8588922,0.4294461,-0.27907  0.8944269,0.4472139,0  0.858892,0.429446,0.279071  0.8588922,0.4294461,-0.27907  0.8944269,0.4472139,0  0.7236065,0.4472139,0.5257313  0.858892,0.429446,0.279071  0.7236065,0.4472139,0.5257313  0.5308242,0.4294462,0.7306172  0.858892,0.429446,0.279071  "                   TriangleIndices="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 " />
                    </GeometryModel3D.Geometry>

                    <GeometryModel3D.Material>
                      <DiffuseMaterial>
                        <DiffuseMaterial.Brush>
                          <SolidColorBrush 
                            Color="Red" 
                            Opacity="1.0"/>
                        </DiffuseMaterial.Brush>
                      </DiffuseMaterial>
                    </GeometryModel3D.Material>

                  </GeometryModel3D>

                </Model3DGroup.Children>
              </Model3DGroup>

            </ModelVisual3D.Content>

          </ModelVisual3D>

        </Viewport3D.Children>

      </Viewport3D>
    </Grid>
  
</UserControl>

Vea también