Опубликован: 07.11.2006 | Доступ: свободный | Студентов: 3397 / 338 | Оценка: 3.94 / 3.71 | Длительность: 37:11:00
Лекция 11:

Реализация 3D-графики с помощью рисования API

Создание куба

В этом упражнении мы будем создавать файл Flash 3D для демонстрации концепций, рассмотренных до сих пор, а также для создания основы, от которой мы сможем отталкиваться в дальнейшем: это будет вращающийся куб.


Установка вершин

  1. Создайте новый фильм и сохраните его в файле spinning_cube_0.fla. Создайте новый символ фильма с центральной точкой регистрации с именем vertex и нарисуйте небольшой круг (я нарисовал круг диаметром 12,5). В меню Linkage Properties отметьте опцию Export for ActionScript и введите имя идентификатора vertex.

    Теперь у нас есть символ vertex в Library. В конечном счете, вершины будут лишь объектами в памяти и больше не будут символами фильма, однако в этом упражнении мы используем их в качестве символов. Теперь перейдем к программе.

  2. Вернитесь в главную точку временной шкалы и переименуйте слой по умолчанию, присвоив ему имя actions. В кадре 1 введите следующий код.
    this.createEmptyMovieClip("center", 0);
    center._x = Stage.width/2; 
    center._y = Stage.height/2; 
    focalLength = 400;

    Мы создали фильм, который будет содержать наш трехмерный мир, и расположили его по центру рабочего места. Также установим переменную focalLength (которую используем для имитации глубины) на значение 400.

  3. Далее мы создаем модель куба, определяя вершины. Добавьте следующий код под предыдущим кодом программы.
    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 для создания трехмерных визуальных эффектов.

  4. Теперь нам нужно написать код, который будет располагать вершины на корректных позициях на экране.
    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, а рисуем вершины, которые будут определять полигоны. Вершины сами по себе не меняют размер.

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

  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 нашего угла (в градусах, поэтому необходимо преобразовать число в радианы), а затем обрабатываем каждую вершину в нашей модели и перемещаем вершину по установленному углу. Формулы для поворота вокруг осей известны, и для экономии времени я продолжу рассказ, подразумевая, что вы согласны с их правильностью.

  6. Наконец, замените последнюю строку render(cube); следующим кодом.
    center.onEnterFrame = function() { 
      rotateY(cube, 3); 
      render(cube);
    };

    Этот окончательный код поворачивает наш куб на три градуса около оси y и затем перерисовывает его на экране. Запустите ваш фильм, чтобы отобразить вращающийся куб. (Если здесь вы получите какие-либо неожиданные результаты, вы можете сравнить ваш файл с файлом spinning_cube_0.fla, находящимся на компакт-диске).

Игорь Хан
Игорь Хан

у меня аналогичная ситуация. Однако, если взять пример из приложения (ball_motion_04_click for trial.fla) то след остается. при этом заметил, что в моем проекте в поле "One item in library" виден кружок, в то время как в приложенном примере такого кружка нет.

Вопрос знатокам, что не так?

Александр Коргапольцев
Александр Коргапольцев

объект созданый мной упорно не желает оставлять след(единственное что добился, так это то что шарик резво гоняется за курсором) функция duplicateMovieClip остаётся не активной, т.е. следа от объекта не остаётся, но если я тоже самый код вбиваю в учебный файл всё работает, не могу понять где я ошибаюсь и почему в документе созданном заново, не работает код начиная от функции duplicateMovieClip?