Visão geral de elementos gráficos 3D

A funcionalidade 3D no Windows Presentation Foundation (WPF) permite que os desenvolvedores desenhem, transformem e animem gráficos 3D em código de marcação e procedimento. Os desenvolvedores podem combinar gráficos 2D e 3D para criar controles avançados, fornecer ilustrações complexas de dados ou melhorar a experiência do usuário da interface de um aplicativo. O suporte 3D no WPF não foi projetado para fornecer uma plataforma de desenvolvimento de jogos com todos os recursos. Este tópico fornece uma visão geral da funcionalidade 3D no sistema gráfico WPF.

3D em um contêiner 2D

O conteúdo gráfico 3D no WPF é encapsulado em um elemento, , Viewport3Dque pode participar da estrutura do elemento bidimensional. O sistema gráfico é Viewport3D tratado como um elemento visual bidimensional como muitos outros no WPF. Viewport3D funciona como uma janela — um visor — em uma cena tridimensional. Mais precisamente, é uma superfície na qual uma cena 3D é projetada.

Em um aplicativo 2D convencional, use Viewport3D como faria outro elemento de contêiner, como Grid ou Canvas. Embora você possa usar Viewport3D com outros objetos de desenho 2D no mesmo gráfico de cena, não é possível interpenetrar objetos 2D e 3D em um Viewport3Darquivo . Este tópico se concentrará em como desenhar gráficos 3D dentro do Viewport3D.

Espaço de coordenadas 3D

O sistema de coordenadas WPF para gráficos 2D localiza a origem no canto superior esquerdo da área 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 área de renderização, 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
Representações convencionais de sistemas de coordenadas 2D e 3D

O espaço definido por esses eixos é o quadro estacionário de referência para objetos 3D no 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.

Câmeras e projeções

Os desenvolvedores que trabalham em 2D estão acostumados a posicionar primitivas de desenho em uma tela bidimensional. Quando você cria uma cena 3D, é importante lembrar que você está realmente criando uma representação 2D de objetos 3D. Como uma cena 3D parece diferente dependendo do ponto de vista do espectador, você deve especificar esse ponto de vista. A Camera classe permite que você especifique esse ponto de vista para uma cena 3D.

Outra maneira de entender como uma cena 3D é representada em uma superfície 2D é descrevendo a cena como uma projeção na superfície de visualização. O ProjectionCamera permite que você especifique diferentes projeções e suas propriedades para alterar como o espectador vê modelos 3D. A PerspectiveCamera especifica uma projeção que encurta a cena. Em outras palavras, a PerspectiveCamera perspectiva fornece ponto de fuga. Você pode especificar a posição da câmera no espaço de coordenadas da cena, a direção e o campo de visão da câmera e um vetor que define a direção “para cima” na cena. O diagrama a seguir ilustra a PerspectiveCameraprojeção do .

As NearPlaneDistance propriedades e FarPlaneDistance de ProjectionCamera limitam o alcance da projeção da câmera. Como as câmeras podem estar localizadas em qualquer lugar na cena, é possível que a câmera esteja realmente posicionada dentro de um modelo ou muito próximo a ele, dificultando a distinção correta de objetos. NearPlaneDistance permite que você especifique uma distância mínima da câmera além da qual os objetos não serão desenhados. Por outro lado, permite especificar uma distância da câmera além da qual os objetos não serão desenhados, FarPlaneDistance o que garante que objetos muito distantes para serem reconhecíveis não sejam incluídos na cena.

Camera setup
Posição da câmera

OrthographicCamera especifica uma projeção ortogonal de um modelo 3D para uma superfície visual 2D. Como outras câmeras, ela especifica uma posição, direção de visualização e direção “para cima”. Ao contrário PerspectiveCamerade , no entanto, OrthographicCamera descreve uma projeção que não inclui o encurtamento de perspectiva. Em outras palavras, descreve uma caixa de visualização cujos lados são paralelos, OrthographicCamera em vez de um cujos lados se encontram em um ponto para a câmera. A imagem a seguir mostra o mesmo modelo exibido usando PerspectiveCamera e OrthographicCamera.

Orthographic and perspective projection
Projeções de perspectiva e ortográficas

O código a seguir mostra algumas configurações típicas da câmera.

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

Modelo e primitivos de malha

Model3D é a classe base abstrata que representa um objeto 3D genérico. Para criar uma cena 3D, você precisa de alguns objetos para exibir, e os objetos que compõem o gráfico de cena derivam de Model3D. Atualmente, o WPF suporta modelagem de geometrias com GeometryModel3Do . A Geometry propriedade deste modelo usa uma primitiva de malha.

Para compilar um modelo, comece criando um primitivo, ou uma malha. Uma primitiva 3D é uma coleção de vértices que formam uma única entidade 3D. A maioria dos sistemas 3D fornece primitivas modeladas na figura fechada mais simples: um triângulo definido por três vértices. Como os três pontos de um triângulo são coplanares, você pode continuar adicionando triângulos para modelar formas mais complexas, chamadas malhas.

O sistema WPF 3D atualmente fornece a MeshGeometry3D classe, que permite especificar qualquer geometria, atualmente não suporta primitivas 3D predefinidas, como esferas e formas cúbicas. Comece a criar um MeshGeometry3D especificando uma lista de vértices de triângulo como sua Positions propriedade. Cada vértice é especificado como um Point3Darquivo . (Em XAML, especifique essa propriedade como uma lista de números agrupados em três que representam as coordenadas de cada vértice.) Dependendo de sua geometria, sua malha pode ser composta de muitos triângulos, alguns dos quais compartilham os mesmos cantos (vértices). Para desenhar a malha corretamente, o WPF precisa de informações sobre quais vértices são compartilhados por quais triângulos. Você fornece essas informações especificando uma lista de índices de triângulo com a TriangleIndices propriedade. Esta lista especifica a ordem em que os Positions pontos especificados na lista determinarão um 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>

No exemplo anterior, a Positions lista especifica quatro vértices para definir uma malha retangular. A TriangleIndices propriedade especifica uma lista de dois grupos de três índices. Cada número na lista refere-se a um deslocamento na Positions lista. Por exemplo, os três primeiros vértices especificados pela Positions lista são (-1,-1,0), (1,-1,0)e (-1,1,0). Os três primeiros índices especificados pela TriangleIndices lista são 0, 1 e 2, que correspondem ao primeiro, segundo e terceiro pontos da Positions lista. Como resultado, o primeiro triângulo que compõe o modelo retangular será composto de para (1,-1,0)(-1,1,0), e o segundo triângulo será determinado de (-1,-1,0) forma semelhante.

Você pode continuar definindo o modelo especificando valores para as Normals propriedades e TextureCoordinates . Para renderizar a superfície do modelo, o sistema de elementos gráficos precisa de informações sobre para qual direção a superfície está voltada em um triângulo específico. Ele usa essas informações para fazer cálculos de iluminação para o modelo: as superfícies voltadas diretamente para uma fonte de luz parecem mais brilhantes do que aquelas que têm ângulos distantes da luz. Embora o WPF possa determinar vetores normais padrão usando as coordenadas de posição, você também pode especificar diferentes vetores normais para aproximar a aparência de superfícies curvas.

A TextureCoordinates propriedade especifica uma coleção de Points que informam ao sistema gráfico como mapear as coordenadas que determinam como uma textura é desenhada para os vértices da malha. TextureCoordinates são especificados como um valor entre zero e 1, inclusive. Assim como a Normals propriedade, o sistema gráfico pode calcular coordenadas de textura padrão, mas você pode optar por definir coordenadas de textura diferentes para controlar o mapeamento de uma textura que inclui parte de um padrão de repetição, por exemplo. Encontre mais informações sobre coordenadas de textura nos próximos tópicos ou no SDK do Direct3D Gerenciado.

O exemplo a seguir mostra como criar uma face do modelo de cubo no código de procedimento. Você pode desenhar o cubo inteiro como um único GeometryModel3D, este exemplo desenha a face do cubo como um modelo distinto, a fim de aplicar texturas separadas para cada face mais tarde.

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

'

Aplicando materiais ao modelo

Para que uma malha tenha a aparência de um objeto tridimensional, ela deve ter uma textura aplicada para cobrir a superfície definida por seus vértices e triângulos, de forma que ela possa ser iluminada e projetada pela câmera. Em 2D, você usa a classe para aplicar cores, padrões, gradientes ou outro conteúdo visual a Brush áreas da tela. A aparência dos objetos 3D, no entanto, é uma função do modelo de iluminação, não apenas da cor ou padrão aplicado a eles. Objetos do mundo real refletem a luz de maneira diferente dependendo da qualidade de suas superfícies: superfícies brilhantes não têm a mesma aparência que superfícies ásperas ou foscas, e alguns objetos parecem absorver luz, enquanto outros brilham. Você pode aplicar todos os mesmos pincéis a objetos 3D que pode aplicar a objetos 2D, mas não pode aplicá-los diretamente.

Para definir as características da superfície de um modelo, o WPF usa a Material classe abstrata. As subclasses concretas de Material determinam algumas das características de aparência da superfície do modelo, e cada uma delas também fornece uma propriedade Brush para a qual você pode passar um SolidColorBrush, TileBrush ou VisualBrush.

  • DiffuseMaterial especifica que o pincel será aplicado ao modelo como se esse modelo estivesse aceso difusamente. Usar DiffuseMaterial mais se assemelha a usar pincéis diretamente em modelos 2D; As superfícies do modelo não refletem a luz como se fossem brilhantes.

  • SpecularMaterial especifica que o pincel será aplicado ao modelo como se a superfície do modelo fosse dura ou brilhante, capaz de refletir destaques. Você pode definir o grau em que a textura sugerirá essa qualidade reflexiva, ou "brilho", especificando um valor para a SpecularPower propriedade.

  • EmissiveMaterial permite especificar que a textura será aplicada como se o modelo estivesse emitindo luz igual à cor do pincel. Isso não faz do modelo uma luz; no entanto, ele participará de maneira diferente do sombreamento comparado ao que ocorreria caso fosse texturizado com DiffuseMaterial ou SpecularMaterial.

Para um melhor desempenho, os backfaces de um GeometryModel3D (aqueles rostos que estão fora de vista porque estão no lado oposto do modelo da câmera) são retirados de cena. Para especificar um a ser aplicado à face de fundo de um modelo como um Material plano, defina a propriedade do BackMaterial modelo.

Para obter algumas qualidades de superfície, como efeitos brilhantes ou reflexivos, talvez você deseje aplicar vários pincéis diferentes a um modelo em sucessão. Você pode aplicar e reutilizar vários materiais usando a MaterialGroup classe. Os filhos do MaterialGroup são aplicados do primeiro ao último em várias aplicações de renderização.

Os exemplos de código a seguir mostram como aplicar uma cor sólida e um desenho como pincéis a 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))

Iluminando a cena

As luzes em gráficos 3D fazem o que as luzes fazem no mundo real: tornam as superfícies visíveis. Mais especificamente, as luzes determinam qual parte de uma cena será incluída na projeção. Os objetos de luz no WPF criam uma variedade de efeitos de luz e sombra e são modelados de acordo com o comportamento de várias luzes do mundo real. Inclua pelo menos uma luz em sua cena, ou nenhum modelo será visível.

As seguintes luzes derivam da classe Lightbase:

  • AmbientLight: Fornece iluminação ambiente que ilumina todos os objetos uniformemente, independentemente de sua localização ou orientação.

  • DirectionalLight: Ilumina como uma fonte de luz distante. As luzes direcionais têm um Direction local especificado como Vector3D, mas nenhum local especificado.

  • PointLight: Ilumina como uma fonte de luz próxima. As PointLights têm uma posição e lançam uma luz a dessa posição. Os objetos na cena são iluminados dependendo de sua posição e distância com relação à luz. PointLightBase expõe uma propriedade, que determina uma Range distância além da qual os modelos não serão iluminados pela luz. O PointLight também expõe propriedades de atenuação, que determinam como a intensidade da luz diminui ao longo da distância. Você pode especificar interpolações constantes, lineares ou quadráticas para a atenuação da luz.

  • SpotLight: Herda de PointLight. Os destaques iluminam como PointLight e têm posição e direção. Eles projetam a luz em uma área em forma de cone definida por InnerConeAngle e OuterConeAngle propriedades, especificadas em graus.

As luzes são Model3D objetos, portanto, você pode transformar e animar as propriedades da luz, incluindo posição, cor, direção e 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)

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 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").

Para obter mais informações sobre como transformar modelos, consulte Visão geral de transformações 3D.

Animando modelos

A implementação do WPF 3D 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 a um filho de um Model3DGroup e outro conjunto de animações a Model3DGroup um grupo de objetos filho. Você também pode obter uma variedade de efeitos visuais animando as propriedades de iluminação da cena. Por fim, é possível optar por animar a própria projeção animando a posição ou o campo de visão da câmera. Para obter informações básicas sobre o sistema de tempo e animação do WPF, consulte os tópicos Visão geral da animação, Visão geral dos storyboards e Visão geral dos objetos congeláveis.

Para animar um objeto no WPF, você cria uma linha do tempo, define uma animação (que na verdade é uma alteração em algum valor de propriedade ao longo do tempo) e especifica a propriedade à qual aplicar a animação. Como todos os objetos em uma cena 3D são filhos do Viewport3D, as propriedades direcionadas por qualquer animação que você deseja aplicar à cena são propriedades de Viewport3D.

Suponha que você deseje fazer com que um modelo pareça se mexer no lugar. Você pode optar por aplicar um ao modelo e animar o eixo de sua rotação de um RotateTransform3D vetor para outro. O exemplo de código a seguir demonstra a aplicação de uma Vector3DAnimation à propriedade do Eixo da Rotation3D da transformação, supondo que a 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
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)

Adicionar conteúdo 3D à janela

Para renderizar a cena, adicione modelos e luzes a um , em seguida, defina o como o Model3DGroup de um Model3DGroupModelVisual3D.Content Adicione o ModelVisual3D à Children coleção do Viewport3D. Adicione câmeras ao Viewport3D definindo sua Camera propriedade.

Finalmente, adicione o Viewport3D à janela. Quando o for incluído como o Viewport3D conteúdo de um elemento de layout como Canvas, especifique o tamanho do Viewport3D definindo suas Height propriedades e Width (herdadas 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>

Confira também