- •Методы использования 3d
- •Предварительная прорисовка
- •Приближенные иллюстрации
- •3D в реальном времени
- •Обзор концепций трехмерной графики
- •Вершины
- •Глубина
- •Добавление линий слияния
- •Матрицы преобразования
- •Сортировка глубины
- •Закрашивание сторон
- •Выбраковка задних поверхностей
- •Прорисовка только необходимых объектов Подсветка полигонов
- •Подсветка куба
Вершины
Наименьшим объектом в трехмерном мире является вершина, которая представляет из себя точку в трехмерном пространстве, имеющую три координаты x, y и z. Вершины являются составными частями трехмерных объектов.
Глубина
Так как мы имеем дело с двухмерным выводом информации (экран монитора), нам необходим способ преобразования 3D координат в 2D пространство. Это делается настройкой параметров _x и _y наших вершин (не путать с трехмерными координатами вершины x и y) по значению z вершины. Чем больше значение z, тем ближе вершина находится к наблюдателю, и, следовательно, тем дальше вершина отодвинута от центра нашего пространства, играющего роль двумерной удаляющейся точки. Ниже приведена упрощенная схема этого процесса.
Несмотря на то, что у вершин 1 и 2 одинаковые 3D-значения x и y (вспомните, что трехмерные значения являются отдельными от координат экрана Flash), их z-значение изменяется, поэтому нам нужно моделировать глубину между двумя точками. Вершина 1, имеющая большее значение z, находится дальше от центра пространства. Так достигается моделирование глубины. Вот формула для выяснения того, каким образом перемещается вершина.
scale = focalLength/(focalLength-z);
_x = x*scale;
_У = У*scale;
focalLength - это расстояние между наблюдателем и экраном. Для случая, описанного выше, мы установили focalLength на значение 100. Для вершины 2 переменная размера равна 1.33, при этом параметры _x и _y равны -66.5 и 133, соответственно. Это расстояние до вершины от центра в пикселях. Вершина 1 с переменной размера, имеющей значение 2, установит значения _x и _y на величины -100 и 200, соответственно. Координаты вершины (их координаты отличны от 3D-координат) заданы от центра пространства. Настраивая focalLength, мы можем увеличивать или уменьшать искажение перспективы.
Векторы
Мы будем говорить об этих объектах далее, при обсуждении света, однако сейчас надо иметь в виду, что вектор - это количественная величина в трехмерном пространстве, состоящая из направления и модуля. Представьте себе прожектор в театре, светящий вниз на артиста, находящегося на сцене. Это вектор, так как у света прожектора есть направление, а луч имеет определенную длину.
Матрицы
Матрицы, как вы помните - это прямоугольные массивы чисел. Мы будем использовать матрицы в преобразовании нашего трехмерного мира.
Создание куба
В этом упражнении мы будем создавать файл Flash 3D для демонстрации концепций, рассмотренных до сих пор, а также для создания основы, от которой мы сможем отталкиваться в дальнейшем: это будет вращающийся куб.
Установка
вершин
Создайте новый фильм и сохраните его в файле spinning_cube_0.fla. Создайте новый символ фильма с центральной точкой регистрации с именем vertex и нарисуйте небольшой круг (я нарисовал круг диаметром 12,5). В меню Linkage Properties отметьте опцию Export for ActionScript и введите имя идентификатора vertex.
Теперь у нас есть символ vertex в Library. В конечном счете, вершины будут лишь объектами в памяти и больше не будут символами фильма, однако в этом упражнении мы используем их в качестве символов. Теперь перейдем к программе.
Вернитесь в главную точку временной шкалы и переименуйте слой по умолчанию, присвоив ему имя actions. В кадре 1 введите следующий код.
this.createEmptyMovieClip("center", 0);
center._x = Stage.width/2;
center._y = Stage.height/2;
focalLength = 400;
Мы создали фильм, который будет содержать наш трехмерный мир, и расположили его по центру рабочего места. Также установим переменную focalLength (которую используем для имитации глубины) на значение 400.
Далее мы создаем модель куба, определяя вершины. Добавьте следующий код под предыдущим кодом программы.
cube = {};
cube .vertexList = [];
cube.vertexList.push({x:-50, y:-50, z:50});
cube.vertexList.push({x:50, y:-50, z:50});
cube.vertexList.push({x:50, y:-50, z:-50});
cube.vertexList.push({x:-50, y:-50, z:-50});
cube.vertexList.push({x:-50, y:50, z:50});
cube.vertexList.push({x:50, y:50, z:50});
cube.vertexList.push({x:50, y:50, z:-50});
cube.vertexList.push({x:-50 , y:50, z:-50});
vertices = [];
for (i=0; i<cube.vertexList.length; i++) {
center.attachMovie("vertex", "v"+i, i);
vertices.push(center["v"+i]);
}
cube - это новый объект, которому мы присвоили единственный параметр vertexList. Это будет массив для содержания каждой отдельной вершины. В следующих восьми строках мы вставляем вершины в массив. Заметьте, что каждая вершина является отдельным объектом, имеющим три параметра: x, y и z. С использованием длины нашего массива мы располагаем физические вершины (символ, хранимый в Library) на рабочем месте для представления вершин нашего куба. Мы вставляем ссылку на этот фильм в наш массив vertices. Это то, с чем мы будем иметь дело при использовании рисования API для создания трехмерных визуальных эффектов.
Теперь нам нужно написать код, который будет располагать вершины на корректных позициях на экране.
render = function (model) {
for (var i = 0; i<model.vertexList.length; i++) {
var scale = focalLength/(focalLength-model.vertexList[i].z) ;
vertices[i]._x = model.vertexList[i].x*scale;
vertices[i]._y = model.vertexList[i].y*scale;
}
};
render(cube);
render выполняется для vertexList нашей модели и устанавливает позицию на экране каждой вершины с использованием формулы глубины, о которой говорилось ранее. После этого наша функция вызывается. Запустите фильм и посмотрите на результат.
spinning_cube_0.swf показывает искажение перспективы, примененное к восьми вершинам, определяющим куб. Моделирование глубины необходимо при отображении 3D-объекта на двухмерном устройстве вывода, которым является монитор компьютера.
Имейте в виду, что мы не меняем размер или глубины наших вершин, как вы можете предположить. Это по той причине, что мы не пытаемся рисовать перспективные сферы, как это часто наблюдалось в экспериментах с Flash 5, а рисуем вершины, которые будут определять полигоны. Вершины сами по себе не меняют размер.
Все до сих пор не слишком впечатляет: куб не вращается, поэтому сейчас трудно наблюдать расположение вершин. Сейчас мы это изменим.
Введите этот код сразу после функции render.
rotateY = function (model, degree) {
var sin = Math.sin(degree*Math.PI/180);
var cos = Math.cos(degree*Math.PI/180);
for (var i = 0; i<model.vertexList.length; i++) {
var x = cos*model.vertexList[i].x-sin*model.vertexList[i].z;
var z = cos*model.vertexList[i].z+sin*model.vertexList[i].x;
model.vertexList[i].z = z;
model.vertexList[i].x = x;
}
};
Этот фрагмент кода будет поворачивать вершины нашей модели около оси y пространства. Сначала мы находим sin и cos нашего угла (в градусах, поэтому необходимо преобразовать число в радианы), а затем обрабатываем каждую вершину в нашей модели и перемещаем вершину по установленному углу. Формулы для поворота вокруг осей известны, и для экономии времени я продолжу рассказ, подразумевая, что вы согласны с их правильностью.
Наконец, замените последнюю строку render(cube); следующим кодом.
center.onEnterFrame = function() {
rotateY(cube, 3);
render(cube);
};
Этот окончательный код поворачивает наш куб на три градуса около оси y и затем перерисовывает его на экране. Запустите ваш фильм, чтобы отобразить вращающийся куб. (Если здесь вы получите какие-либо неожиданные результаты, вы можете сравнить ваш файл с файлом spinning_cube_0.fla, находящимся на компакт-диске).
