Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Программное рисование трёхмерных объектов



Цель работы:

1). Изучить: общие принципы программного построения простейших трёхмерных моделей; использование аффинных преобразований для получения проекций вращения трёхмерных моделей; использование фокусного расстояния при расчёте перспективного проецирования.

2). Создать приложение для управления вращением трёхмерного графического объекта вдоль осей X, Y и Z на плоском фоне.

Порядок выполнения работы:

1. Создайте новый проект с названием " lab10".

2. Используйте классы Main и Graphics2D из предыдущей работы.

3. По аналогии класса Graphics2D создайте новый класс Graphics3D для рисования трёхмерных графических объектов с помощью полигонов.

4. В конструкторе класса Graphics3D определите следующие прототипы:

MovieClip.prototype.vertex3D = new Array();

MovieClip.prototype.polygons = new Array();

MovieClip.prototype.setVertex = setVertex;

MovieClip.prototype.setPolygon = setPolygon;

MovieClip.prototype.render = render;

MovieClip.prototype.rotate = rotate;

5. Так же используются следующие глобальные переменные:

var vertex3D, polygons: Array;

var rgb, alpha: Number;

var matrix: Object;

6. Методы setVertex() и setPolygon() предназначены соответственно для заполнения массивов координат вершин и порядок построения полигонов по этим вершинам (четыре вершины – a, b, c, d):

public function setVertex(x: Number, y: Number, z: Number) {

vertex3D.push({x: x, y: y, z: z});

}

public function setPolygon(a: Number, b: Number, c: Number, d: Number, rgb, alpha) {

polygons.push({vertices: [a, b, c, d], rgb: rgb, alpha: alpha});

}

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

public function render(focalLength: Number) {

...

var vertex2D: Array = new Array();

var depths: Array = new Array();

for (var i = 0; i< polygons.length; i++) {

var zDepth: Number = 0;

for (var j = 0; j< polygons[i].vertices.length; j++) {

var zVertex: Array = polygons[i].vertices[j];

if (! vertex2D[zVertex]) {

vertex2D[zVertex] = new Object();

var scale: Number = focalLength/(focalLength-vertex3D[zVertex].z);

vertex2D[zVertex].x = vertex3D[zVertex].x*scale;

vertex2D[zVertex].y = vertex3D[zVertex].y*scale;

}

zDepth += vertex3D[zVertex].z;

}

depths.push([polygons[i], zDepth]);

}

depths.sort(function (a: Number, b: Number) {

return a[1]> b[1];

});

for (var i = 0; i< depths.length; i++) {

var zPolygon: Array = depths[i][0].vertices;

this.moveTo(vertex2D[zPolygon[0]].x, vertex2D[zPolygon[0]].y);

this.beginFill(depths[i][0].rgb, depths[i][0].alpha);

for (var j = 1; j< zPolygon.length; j++) {

this.lineTo(vertex2D[zPolygon[j]].x, vertex2D[zPolygon[j]].y);

}

this.lineTo(vertex2D[zPolygon[0]].x, vertex2D[zPolygon[0]].y);

this.endFill();

}

}

8. Единственным аргументом метода render() является переменная focalLength, которая учитывается при расчёте перспективной проекции.

9. Теперь, например, для того, чтобы задать некоторый четырёхугольный полигон в трёхмерной системе координат, в классе Main необходимо сделать вызов следующих методов:

var cube: MovieClip = bounds.createEmptyMovieClip(" cube", 1);

cube.setVertex(-75, -75, 75);

cube.setVertex(75, -75, 75);

cube.setVertex(75, -75, -75);

cube.setVertex(-75, -75, -75);

cube.setPolygon(0, 1, 2, 3, 0xff0000, 50);

10. Прорисовку графического объекта с помощью метода render() необходимо делать в каждом кадре, очищая перед выводом экран с помощью метода clear(), а также указывать тип линии рисования lineStyle().

11. Задайте рисование правильного куба в пространстве. Все грани закрасьте шестью основными цветами. Измените степень прозрачности (рис. 13).

 

 

Рис. 13. Куб с разной степенью прозрачности граней: 0% (слева), 100%(в центре) и 50% (справа)

12. Для того, чтобы вращать или перемещать трёхмерный объект в пространстве, необходимо использовать аффинные преобразования. Для этого необходимо создать новый класс Matrix, конструктор которого будет пустым, а основным методом будет transformMatrix() следующей структуры:

private function transformMatrix(matrix: Object) {

if (complete) {

var move: Object = new Object();

move.a = matrix.a*a+matrix.b*d+matrix.c*g;

...

a = move.a;

...

} else {

a = matrix.a;

...

}

complete = true;

}

13. Переменная matrix представляет собой объект с девятью свойствами: a, b, c, d, e, f, g, h, i для хранения текущей матрицы аффинных преобразований.

14. Три других метода rotateX(), rotateY() и rotateZ() соответственно будут представлять собой аффинные преобразования при вращении вдоль соответствующих осей. Из каждого такого метода должно быть задано обращение к методу transformMatrix() с соответствующей матрицей аффинных преобразований, например, для метода rotateX(angle):

sin = Math.sin(angle*Math.PI/180);

cos = Math.cos(angle*Math.PI/180);

transformMatrix({a: 1, b: 0, c: 0, d: 0, e: cos, f: sin, g: 0, h: -sin, i: cos});

15. Для вызова этих методов из класса Main одновременно в классе Graphics3D создайте один метод rotate() с тремя аргументами – углами.

16. В самое начало метода render() необходимо добавить следующий фрагмент умножения матрицы трансформации на координаты вершин, взятых из массива vertex3D. При условии наличия заполненного объекта matrix должен выполняться цикл и последующее удаление объекта:

for (var i = 0; i< vertex3D.length; i++) {

var move: Object = vertex3D[i];

var x: Number = matrix.a*move.x+matrix.b*move.y+matrix.c*move.z;

...

move.x = x;

...

}

delete matrix;

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

Также можно включить управление значением focalLength для метода render() с помощью колёсика прокрутки мыши на площади фонового объекта bounds, к которому должен быть прикреплён объект cube.

Контрольные вопросы:

1). Для чего используется переменная zDepth в методе render()?

2). Каким образом происходит сортировка элементов массива depths?

3). В чём смысл использования логической переменной complete?

4). Для чего используется переменная move’ в методе render()?

5). Что происходит при уменьшении значения focalLength?

Лабораторная работа 11


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-05-03; Просмотров: 647; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.014 с.)
Главная | Случайная страница | Обратная связь