Поделиться через


Обзор трехмерной графики

3D-функции в Windows Presentation Foundation (WPF) позволяют разработчикам создавать, преобразовывать и анимировать трехмерные рисунки как в разметке, так и в процедурном коде. Разработчики могут объединять трехмерные и трехмерные графические элементы для создания расширенных элементов управления, предоставления сложных иллюстраций данных или улучшения пользовательского интерфейса приложения. 3D-поддержка в WPF не предназначена для обеспечения полнофункциональный платформы разработки игр. В этом разделе представлен обзор трехмерных функций в графической системе WPF.

3D в 2D-контейнере

Трехмерное графическое содержимое в WPF инкапсулируется в элементе, Viewport3Dкоторый может участвовать в двухмерной структуре элементов. Графическая система рассматривает Viewport3D как двухмерный визуальный элемент, подобно многим другим в WPF. Viewport3D функционирует как окно — видовой экран — в трехмерной сцене. Более точно это поверхность, на которой проецируется трехмерная сцена.

В обычном 2D-приложении используйте Viewport3D так же, как вы бы использовали другой контейнерный элемент, например Grid или Canvas. Хотя вы можете использовать Viewport3D с другими трехмерными объектами рисования в том же графе сцены, вы не можете взаимодействовать с 2D-объектами и трехмерными объектами в пределах Viewport3D. В этом разделе будет рассмотрено, как рисовать трехмерную графику внутри Viewport3D.

Трехмерное пространство координат

Система координат WPF для трехмерной графики находит источник в верхнем левом углу области отрисовки (обычно на экране). В 2D-системе положительные значения оси x проходят справа, а положительные значения оси y опускаются вниз. Однако в 3D-системе координат начало расположено в центре области отрисовки: положительные значения оси x идут вправо, положительные значения оси y — вверх, а положительные значения оси z идут от начала к наблюдателю.

Координаты систем
Обычные представления системы координат 2D и трехмерных координат

Пространство, определенное этими осями, является системой отсчета для трехмерных объектов в WPF. При создании моделей в этом пространстве и создании источников света и камер для их просмотра полезно отличать эту стационарную систему отсчёта, или "пространство мира," от локальной системы отсчёта, которую вы создаете для каждой модели при применении к ней преобразований. Помните также, что объекты в мировом пространстве могут выглядеть совершенно иначе, или не отображаться вообще, в зависимости от параметров света и камеры, но положение камеры не изменяет расположение объектов в мировом пространстве.

Камеры и проекции

Разработчики, работающие в 2D, привыкли размещать примитивы рисования на двухмерном экране. При создании трехмерной сцены важно помнить, что на самом деле вы создаете двумерное представление трехмерных объектов. Так как трехмерная сцена выглядит по-разному в зависимости от точки зрения зрителя, необходимо указать эту точку зрения. Класс Camera позволяет указать эту точку зрения для трехмерной сцены.

Другой способ понять, как трехмерная сцена представлена на 2D-поверхности, описывая сцену как проекцию на поверхность просмотра. Элемент ProjectionCamera позволяет вам указать различные проекции и их свойства, чтобы изменить восприятие трехмерных моделей. PerspectiveCamera задает проекцию, которая сокращает перспективу сцены. Другими словами, PerspectiveCamera это обеспечивает исчезающую перспективу. Вы можете указать положение камеры в пространстве координат сцены, направление и поле зрения для камеры, а также вектор, определяющий направление "вверх" в сцене. На следующей PerspectiveCameraсхеме показана проекция.

Свойства NearPlaneDistance и FarPlaneDistance объекта ProjectionCamera ограничивают диапазон проекции камеры. Так как камеры могут находиться в любом месте сцены, камера может быть фактически размещена внутри модели или очень близко к модели, что делает его трудно правильно различать объекты. NearPlaneDistance позволяет указать минимальное расстояние от камеры, за пределами которого объекты не будут вырисовываться. И наоборот, FarPlaneDistance позволяет указать расстояние от камеры, за пределами которого объекты не отображаются, что позволяет гарантировать, что объекты, находящиеся слишком далеко, чтобы быть распознаваемыми, не будут включены в сцену.

Настройка камеры
Позиция камеры

OrthographicCamera задает ортогональную проекцию трехмерной модели на трехмерную визуальную поверхность. Как и другие камеры, он указывает положение, направление просмотра и направление вверх. В отличие от PerspectiveCamera, однако OrthographicCamera описывает проекцию, которая не включает искажение перспективы. Другими словами, OrthographicCamera описывает окно просмотра, стороны которого параллельны, а не одна сторона, чьи стороны встречаются в точке на камере. На следующем рисунке показана та же модель, что и при просмотре с помощью PerspectiveCamera и OrthographicCamera.

Орфографическая и перспективная проекции
Перспектива и ортографические проекции

В следующем коде показаны некоторые типичные параметры камеры.

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

Примитивы моделей и сеток

Model3D — абстрактный базовый класс, представляющий универсальный трехмерный объект. Чтобы создать трехмерную сцену, необходимо иметь объекты для отображения, а объекты, составляющие граф сцены, происходят от Model3D. В настоящее время WPF поддерживает моделирование геометрий с GeometryModel3Dпомощью . Свойство Geometry этой модели принимает примитив сетки.

Чтобы создать модель, сначала создайте примитив или сетку. Трехмерный примитив — это коллекция вершин, которые образуют одну трехмерную сущность. Большинство трехмерных систем предоставляют примитивы, моделироваемые на простейшей закрытой фигуре: треугольник, определенный тремя вершинами. Поскольку три точки треугольника являются сопланарными, вы можете продолжать добавлять треугольники, чтобы моделировать более сложные фигуры, называемые сетками.

В настоящее время система WPF 3D предоставляет MeshGeometry3D класс, который позволяет указать любую геометрию. В настоящее время она не поддерживает предопределенные трехмерные примитивы, такие как сферы и кубические формы. Начните создание MeshGeometry3D , указав список вершин треугольника в качестве его Positions свойства. Каждая вершина указана Point3Dв виде . (В XAML укажите это свойство в виде списка чисел, сгруппированных в три, которые представляют координаты каждой вершины.) В зависимости от геометрии сетка может состоять из множества треугольников, некоторые из которых имеют одинаковые угла (вершины). Чтобы правильно нарисовать сетку, WPF нуждается в сведениях о том, какие вершины разделяются треугольниками. Эти сведения предоставляются путем указания списка индексов треугольников со свойством TriangleIndices . Этот список указывает порядок, в котором точки, указанные в списке Positions , определяют треугольник.

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

В предыдущем примере Positions список задает четыре вершины для определения прямоугольной сетки. Свойство TriangleIndices задает список двух групп из трех индексов. Каждое число в списке ссылается на смещение в Positions список. Например, первые три вершины, указанные в спискеPositions, : (-1,-1,0)(1,-1,0)и (-1,1,0). Первые три индекса, указанные TriangleIndices в списке, имеют значение 0, 1 и 2, которые соответствуют первым, вторым и третьим пунктам в списке Positions . В результате первый треугольник, составляющий модель прямоугольника, будет состояться от (-1,-1,0) до (1,-1,0)(-1,1,0), а второй треугольник будет определен аналогичным образом.

Вы можете продолжить определение модели, указав значения для Normals свойств и TextureCoordinates свойств. Чтобы отрисовка поверхности модели, графические системы нуждались в информации о том, в каком направлении поверхность сталкивается с любым заданным треугольником. Эта информация используется для расчета освещения для модели: поверхности, которые сталкиваются непосредственно к источнику света, отображаются ярче, чем те, углы от света. Хотя WPF может определить обычные векторы по умолчанию с помощью координат положения, можно также указать различные обычные векторы, чтобы приблизить внешний вид кривых поверхностей.

Свойство TextureCoordinates указывает коллекцию Points, которая сообщает графической системе, как сопоставить координаты, определяющие, как текстура рисуется на вершины сетки. TextureCoordinates указываются в качестве значения от нуля до 1, включительно. Как и в случае с Normals свойством, графические системы могут вычислять координаты текстур по умолчанию, но можно задать различные координаты текстур для управления сопоставлением текстуры, которая включает часть повторяющегося шаблона, например. Дополнительные сведения о координатах текстур можно найти в последующих разделах или в пакете SDK managed Direct3D.

В следующем примере показано, как создать одно лицо модели куба в процедурном коде. Вы можете нарисовать весь куб как один GeometryModel3D. В этом примере лицо куба рисуется как отдельная модель, чтобы применить отдельные текстуры к каждому лицу позже.

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

'

Применение материалов к модели

Для того чтобы сетка выглядела как трехмерный объект, она должна иметь примененную текстуру для покрытия поверхности, определенной вершинами и треугольниками, чтобы она была освещена и проецирована камерой. В 2D класс используется Brush для применения цветов, шаблонов, градиентов или другого визуального содержимого к областям экрана. Однако внешний вид трехмерных объектов является функцией модели освещения, а не только цвета или шаблона, примененного к ним. Реальные объекты отражают свет по-разному в зависимости от качества их поверхностей: глянцевые и блестящие поверхности не выглядят так же, как грубые или матовые поверхности, и некоторые объекты, кажется, поглощают свет, а другие светятся. Вы можете применить все те же кисти к трехмерных объектов, которые можно применить к 2D-объектам, но их нельзя применить напрямую.

Для определения характеристик поверхности модели WPF использует абстрактный Material класс. Конкретные подклассы "Материал" определяют некоторые характеристики внешнего вида поверхности модели, а также предоставляет свойство Кисти, в которое можно передать SolidColorBrush, TileBrush или VisualBrush.

  • DiffuseMaterial указывает, что кисть будет применена к модели, как будто эта модель была диффузно освещена. Использование диффузного материала больше всего напоминает использование кистей непосредственно на 2D-моделях, так как поверхности модели не отражают свет, как блестящие.

  • SpecularMaterial указывает, что кисть будет применена к модели так, будто поверхность модели твердая или блестящая, способная отражать блики. Вы можете задать степень, в которой текстура будет предлагать это отражающее качество или "блеск", указав значение для SpecularPower свойства.

  • EmissiveMaterial позволяет указать, что текстура будет применена, как будто модель генерирует свет, равный цвету кисти. Это не делает модель светом; однако она будет по-другому участвовать в обработке теней, чем если бы она была покрыта диффузным материалом или SpecularMaterial.

Для повышения производительности задние части GeometryModel3D (те лица, которые находятся вне зрения, потому что они находятся на противоположной стороне модели с камеры) отбрасываются с сцены. Чтобы указать Material, который нужно применить к задней стороне модели, например плоскости, установите свойство BackMaterial модели.

Чтобы достичь некоторых качеств поверхности, таких как светящиеся или отражающие эффекты, может потребоваться применить несколько разных кистей к модели в последовательности. Вы можете применить и повторно использовать несколько материалов с помощью MaterialGroup класса. Дочерние элементы MaterialGroup применяются в порядке от первого до последнего в нескольких проходах отрисовки.

В следующих примерах кода показано, как применить сплошной цвет и рисунок в виде кистей к трехмерной модели.

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

Освещение сцены

Свет в трехмерной графике делает то, что свет делает в реальном мире: они делают поверхности видимыми. Более того, свет определяет, какая часть сцены будет включена в проекцию. Световые объекты в WPF создают различные световые и теневые эффекты и моделироваются после поведения различных реальных светов. Включите по крайней мере один источник света в свою сцену, иначе модели не будут видны.

Следующие световые индикаторы являются производными от базового класса Light:

  • AmbientLight: обеспечивает окружающее освещение, которое освещает все объекты равномерно независимо от их расположения или ориентации.

  • DirectionalLight: создает эффект дальнего источника света. Направленные источники света имеют заданный Direction в виде Vector3D, но их местоположение не определено.

  • PointLight: освещает, как соседний источник света. PointLights занимают определённое место и освещают из этого положения. Объекты в сцене освещаются в зависимости от их положения и расстояния относительно света. PointLightBase предоставляет свойство, определяющее Range расстояние, за пределами которого модели не будут освещены светом. PointLight также предоставляет свойства аттенуации, которые определяют, как интенсивность света уменьшается на расстоянии. Вы можете указать константные, линейные или квадратные интерполяции для атенуации света.

  • SpotLight: наследует от PointLight. Прожекторы освещают подобно PointLight и имеют и положение, и направление. Они проектируют свет в конусообразной области, заданной InnerConeAngle и OuterConeAngle свойствами, указанными в градусах.

Свет — это Model3D объекты, поэтому можно преобразовывать и анимировать свойства света, включая положение, цвет, направление и диапазон.

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

Преобразование моделей

При создании моделей они имеют определенное расположение в сцене. Чтобы переместить эти модели в сцене, повернуть их или изменить их размер, нецелесообразно изменять вершины, которые определяют сами модели. Вместо этого, как и в 2D, вы применяете преобразования к моделям.

Каждый объект модели имеет Transform свойство, с помощью которого можно перемещать, перенабирать или изменять размер модели. При применении преобразования вы эффективно смещаете все точки модели по вектору или значению, заданному преобразованием. Другими словами, вы преобразовали пространство координат, в котором определена модель ("пространство модели"), но вы не изменили значения, составляющие геометрию модели в системе координат всей сцены ("пространство мира").

Дополнительные сведения о преобразовании моделей см. в обзоре трехмерных преобразований.

Анимация моделей

Реализация WPF 3D участвует в той же системе времени и анимации, что и трехмерная графика. Другими словами, чтобы анимировать трехмерную сцену, изменяйте свойства ее моделей. Можно анимировать свойства примитивов напрямую, но обычно проще анимировать преобразования, которые изменяют положение или внешний вид моделей. Так как преобразования могут применяться к Model3DGroup объектам, а также отдельным моделям, можно применить один набор анимаций к дочернему элементу Model3DGroup и другому набору анимаций к группе дочерних объектов. Вы также можете достичь различных визуальных эффектов, анимируя свойства освещения сцены. Наконец, можно выбрать анимацию проекции, анимируя положение камеры или поле зрения. Дополнительные сведения о системе времени и анимации WPF см. в разделах "Обзор анимации", "Обзор раскадровок" и "Обзор замораживаемых объектов".

Чтобы анимировать объект в WPF, создайте временную шкалу, определите анимацию (которая действительно изменяется в некотором значении свойства с течением времени) и укажите свойство, к которому применяется анимация. Так как все объекты в трехмерной сцене являются дочерними Viewport3Dэлементами, свойства, предназначенные для любой анимации, которую вы хотите применить к сцене, являются свойствами Viewport3D.

Предположим, что вы хотите сделать так, чтобы модель казалась покачивающейся на месте. Вы можете применить RotateTransform3D к модели и анимировать ось её вращения от одного вектора к другому. В следующем примере кода показано, как применение Vector3DAnimation к свойству Axis в Rotation3D преобразования, предполагает, что RotateTransform3D является одним из нескольких преобразований, применяемых к модели с помощью 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)

Добавление трехмерного содержимого в окно

Чтобы отрисовать сцену, добавьте модели и освещение в Model3DGroup, а затем установите Model3DGroup как Content для ModelVisual3D. Добавьте ModelVisual3D в коллекцию Children для Viewport3D. Добавьте камеры в Viewport3D, задав его свойство Camera.

Наконец, добавьте его Viewport3D в окно. Если Viewport3D включен в качестве содержимого такого элемента макета, как Canvas, укажите размер Viewport3D, установив его свойства Height и Width (унаследованные от 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>

См. также