Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Программное рисование трёхмерных объектов ⇐ ПредыдущаяСтр 3 из 3
Цель работы: 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; Нарушение авторского права страницы