Главная » WPF » Принципы трехмерной графики

0

Поскольку в текущей версии WPF поддержка трехмерной графики  ограничена, будет правильно сначала познакомиться с базовыми строительными блоками и по нять, что можно надстроить над ними. Мы уже говорили, что в трехмерной графике есть четыре основных концепции: модель, материал, камера и источник освещения.

Модели

Все трехмерные  объекты  в конечном  итоге составлены  из треугольников. В WPF ничего, кроме треугольников, нет. Отметим,  что изображение в WPF фор мируется  в результаты  работы трехмерного конвейера. Текст, фигуры, элементы управления, рисунки  – все отрисовывается в виде набора треугольников. В слу чае двумерных  конструкций декомпозиция (тесселяция в терминологии 3D) производится системой. Напротив, автор трехмерной  модели должен  самостоя тельно составить ее из треугольников. Набор треугольников, из которых склады вается трехмерная  модель, называется сеткой (mesh).

Строго говоря, источники освещения – это тоже модели (а в некоторых систе мах моделями  являются и камеры).  Однако мы пока ограничимся классами GeometryModel3D и  MeshGeometry3D, которые  при  создании  любой  модели всегда идут рука об руку.

Чтобы определить объект класса MeshGeometry3D, нам нужны координаты пос ледовательности точек в трехмерном пространстве. Затем, выбирая из этой последо вательности тройки  точек, мы можем  определить  треугольники. Материал  точек описывается с помощью текстур. Чтобы понять, как все это увязано, создадим более сложный  трехмерный  объект: часть куба (мы рассмотрим только три видимых гра ни, а построение трех оставшихся  я оставляю читателю в качестве упражнения).

Свойство Positions определяет  последовательность точек16. У куба восемь вер шин, но, поскольку  нас интересуют  только три грани, то нужно лишь семь точек (рис. 5.33).

<MeshGeometry3D>

<MeshGeometry3D.Positions>

<Point3D>0,0,0</Point3D>

<Point3D>1,0,0</Point3D>

<Point3D>0,1,0</Point3D>

<Point3D>1,1,0</Point3D>

<Point3D>0,1, 1</Point3D>

<Point3D>1,1, 1</Point3D>

<Point3D>1,0, 1</Point3D>

</MeshGeometry3D.Positions>

</MeshGeometry3D>

Эта последовательность точек не определяет  никаких треугольников, пока мы не сообщим сетке порядок их обхода (см. рис. 5.33). С помощью свойства TriangleIndices мы сопоставляем треугольнику три индекса. Поскольку нужно создать три грани, понадобится по меньшей мере шесть треугольников. Сначала создадим левую нижнюю половину передней грани17:

<MeshGeometry3D>

<MeshGeometry3D.TriangleIndices>

<sys:Int32>0</sys:Int32>

<sys:Int32>1</sys:Int32>

<sys:Int32>2</sys:Int32>

</MeshGeometry3D.TriangleIndices>

</MeshGeometry3D>

Затем  – правую верхнюю половину:

<MeshGeometry3D>

<MeshGeometry3D.TriangleIndices>

<sys:Int32>3</sys:Int32>

<sys:Int32>2</sys:Int32>

<sys:Int32>1</sys:Int32>

</MeshGeometry3D.TriangleIndices>

</MeshGeometry3D>

Повторим эту процедуру для оставшихся  четырех треугольников.

16 Напомним, что результат существенно зависит от ориентации камеры. В данном случае мы предполагаем, что положительное направление оси Y обозначает «верх». На рис. 5.33 показа но также, что чем больше координата Z, тем дальше объект отстоит от камеры.

17 В WPF для определения поверхности треугольника применяется правило правой руки. Чтобы понять его, согните правую руку, подняв вверх большой палец. Если провести координатные оси вдоль остальных пальцев, то большой палец определит нормаль к поверхности. Можно представить и по другому: когда вы смотрите на поверхность, расположенную прямо перед глазами, вершины треугольника должны быть упорядочены против часовой стрелки.

И еще нужно сопоставить точкам материал (иногда он называется текстурой). С помощью TextureCoordinate свойства мы определяем, как координаты матери ала относительно охватывающего  прямоугольника соотносятся с точкой. Для каждой точки сетки мы собираемся  ассоциировать двумерную точку из диапазо на от (0,0) до (0,1) с точкой на материале.

Рис. 5.34. Первая попытка воспользоваться текстурой, не указав координаты на ней

Напомним,  что при определении кисти  (например, LinearGradientBrush)  мы можем задать начальную и конечную точки в системе координат, связанной с ох ватывающим  прямоугольником, то есть в той же системе, в которой определяют ся  свойства  GradientStop.Offset.  Поскольку материал  должен  охватывать  нес колько  треугольников и часто приходится  выполнять его рендеринг  несколько раз (как в в случае куба, имеющего шесть граней), то необходимо сообщить сис теме, каким образом сопоставить  материал каждому треугольнику. Так как свой ства TriangleIndices уже отображают  точки на треугольники, то остается  только определить  материал для каждой точки.

По умолчанию для каждой точки свойству TextureCoordinate присваивается значение (0,0). Поэтому, если применить  кисть LinearGradientBrush, то будет ис пользован  лишь  цвет  в точке  с нулевым  смещением  (рис.  5.34).  Однако,  если взять  тот же градиент, которым  мы заливали прямоугольник, то результат  ока жется совсем другим (рис. 5.35):

<DiffuseMaterial>

<DiffuseMaterial.Brush>

<LinearGradientBrush EndPoint=’1,0’>

<LinearGradientBrush.GradientStops>

<GradientStop Offset=’0’ Color=’White’ />

<GradientStop Offset=’1’ Color=’Black’ />

</LinearGradientBrush.GradientStops>

</LinearGradientBrush>

</DiffuseMaterial.Brush>

</DiffuseMaterial>

Рис. 5.35. Тот же прямоугольник, к которому применена градиентная текстура

Правильно задав для сетки свойство TextureCoordinates, мы сможем получить такой  же результат  (плоскости, освещение  и т.д.) с помощью  прямоугольника, составленного из двух треугольников:

<MeshGeometry3D>

<MeshGeometry3D.TextureCoordinates>

<Point2D>0,0</Point2D>

<Point2D>1,0</Point2D>

<Point2D>0,1</Point2D>

<Point2D>1,1</Point2D>

</MeshGeometry3D.TextureCoordinates>

</MeshGeometry3D>

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

<MeshGeometry3D

TextureCoordinates=’0,0 1,0 0,1 1,1 0,0 1,1 1,1 1,1’ Positions=’0,0,0 1,0,0 0,1,0 1,1,0 0,1, 1 1,1, 1 1,0, 1’ TriangleIndices=’0,1,2 3,2,1 4,2,3 5,4,3 5,3,1 6,5,1’ />

Теперь соберем все вместе и запишем окончательную разметку для отображе

ния нашей первой трехмерной  фигуры (рис. 5.36):

<Viewport3D Width=’200’ Height=’200’>

<Viewport3D.Camera>

<PerspectiveCamera LookDirection=’ .7, .8, 1’ Position=’3.8,4,4’ FieldOfView=’17’ UpDirection=’0,1,0’ />

</Viewport3D.Camera>

<ModelVisual3D>

<ModelVisual3D.Content>

<Model3DGroup>

<PointLight Position=’3.8,4,4’ Color=’White’ Range=’7’

ConstantAttenuation=’1.0’ />

<GeometryModel3D>

<GeometryModel3D.Geometry>

<MeshGeometry3D

TextureCoordinates=’0,0 1,0 0,1 1,1 0,0 1,1 1,1 1,1’ Positions=’0,0,0 1,0,0 0,1,0 1,1,0 0,1, 1 1,1, 1 1,0, 1’ TriangleIndices=’0,1,2 3,2,1 4,2,3 5,4,3 5,3,1 6,5,1’ />

</GeometryModel3D.Geometry>

<GeometryModel3D.Material>

<DiffuseMaterial>

<DiffuseMaterial.Brush>

<LinearGradientBrush EndPoint=’1,0’>

<LinearGradientBrush.GradientStops>

<GradientStop Offset=’0’ Color=’Black’ />

<GradientStop Offset=’1’ Color=’White’ />

</LinearGradientBrush.GradientStops>

</LinearGradientBrush>

</DiffuseMaterial.Brush>

</DiffuseMaterial>

</GeometryModel3D.Material>

</GeometryModel3D>

</Model3DGroup>

</ModelVisual3D.Content>

</ModelVisual3D>

</Viewport3D>

Рис. 5.36. Куб с тремя гранями, к которому применена линейно градиентная текстура

Создание  сложных  моделей  – это и есть искусство  трехмерной  графики.  Но так же, как понимание  устройства  кривых Безье, градиентов и цветов не поможет нарисовать  красивую картину, так и понимание  треугольников и текстур не сде лает из вас истинного виртуоза трехмерной графики. Трехмерные модели неверо ятно сложны, они состоят из сотен и тысяч (и даже сотен тысяч!) треугольников.

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

Источник: К. Андерсон  Основы  Windows Presentation Foundation. Пер. с англ. А. Слинкина — М.: ДМК Пресс, 2008 — 432 с.: ил.

По теме:

  • Комментарии