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

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

Добавление линий слияния

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

  1. Сохраните имеющийся фильм в файле spinning_cube_1.fla. Теперь мы добавим код в нашу функцию прорисовки для рисования линий между вершинами. Для этого необходимо знать, какие вершины должны быть соединены друг с другом. Это сделать, добавив стороны к нашей модели, состоящие из выделенных вершин. Введите следующий код сразу после предыдущих строк, определяющих вершины cube (под последней строкой, начинающейся с cube.vertex.push ).
    cube.side = [];
    cube.side.push([0, 1, 2, 3]);
    cube.side.push([2, 1, 5, 6]);
    cube.side.push([1, 0, 4, 5]);
    cube.side.push([5, 4, 7, 6]);
    cube.side.push([0, 3, 7, 4]);
    cube.side.push([3, 2, 6, 7]);

    side - это еще один параметр массива нашей модели. Каждый индекс состоит из четырех вершин, которые формируют сторону куба (попробуйте растянуть ее, чтобы увидеть, как это повлияет на связанные вершины). Порядок, в котором расположены вершины в каждом индексе side, очень важен, и вы убедитесь в этом, когда мы будем рассматривать процесс выбраковывания, заключающийся в том, что все стороны, не наблюдаемые пользователем, становятся невидимыми (это снижает загрузку процессора). Скоро мы это обсудим. А сейчас просто убедитесь в том, что вы сохранили порядок вершин для каждой стороны (порядок сторон неважен).

  2. Теперь нужно отредактировать нашу функцию вручную для непосредственного рисования линий между вершинами. С определенными сторонами данный процесс является очень простым. Добавленный код выделен жирным шрифтом.
    render = function (model) { 
      center.clear(); 
      center.lineStyle(2, 0, 100);
      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;
      }
      for (var i = 0; i<model.side.length; i++) {
        center.moveTo (vertices [model.side[i][0]]._x, 
        vertices [model.side[i][0] ]._y); 
        for (var j = 1; j <model.side[i] .length; j++) {
          center.lineTo(vertices[model.side[i][j]]._x, 
          vertices [model.side[i][j]]._y);
        }
        center.lineTo(vertices[model.side[i][0]]._x,
        vertices [model.side[i][0]]._y);
      }
    };

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


    Линии, нарисованные в API, добавлены для определения граней нашей модели.

    Теперь, когда есть линии каркаса, фильмы вершин стали несколько лишними. Мы можем удалить их все вместе и сделать так, чтобы вершины существовали отдельно в памяти компьютера. Нужно будет найти экранные координаты x и y вершин, не имея возможности посмотреть параметры _x и _y фильма.

  3. Удалите символ вершины из Library, так как он больше не понадобится. Также удалите следующий код из вашего сценария (это строки 23-26 в панели Script).
    for (i=0; i<cube.vertexList.length; i++) {
      center.attachMovie("vertex", "v"+i, i);
      vertices.push(center["v"+i]);
    }
  4. Теперь обновите вашу функцию render следующим образом.
    render = function (model) {
      center.clear ();
      center.lineStyle(2, 0, 100);
      verts2D = [];
      for (var i = 0; i<model .vertexList.length; i++) {
        verts2D[i] = {};
        var scale = focalLength/(focalLength-model.vertexList[i].z); 
        verts2D[i].x = model.vertexList[i].x*scale;
        verts2D[i].y = model.vertexList[i].y*scale;
      }
      for (var i = 0; i<model.side.length; i++) {
        center.moveTo(verts2D[model.side[i][0]] .x, 
          verts2D [model.side [i][0]] .y); 
        for (var j =1; j<model.side[i] .length; j++) {
          center.lineTo(verts2D[model.side[i][j]] .x, 
            verts2D [model. side [i][j]] .y);
        }
          center. lineTo(verts2D [model .side [i][0]] .x, 
          verts2D [model. side [i][0]] .y);
        }
    };

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


  5. После удаления вершин фильма трехмерная модель вращается около оси y, и это результат работы только лишь рисования API.
  6. Сохраните ваш фильм и оставьте его открытым, так как мы будем изменять его еще раз, когда разберем еще немного теории.
Игорь Хан
Игорь Хан

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

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

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

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