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

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

Преобразования с помощью матриц

  1. Сохраните фильм из прошлого упражнения в файле spinning_cube_2.fla. Затем введите следующий код после функции render.
    rotateX = function (model, degree) { 
      var rad = degree*Math.PI/180; 
      var sin = Math.sin(rad); 
      var cos = Math.cos(rad);
      var matrix = {a:1, b:0, c:0, d:0, e:cos, f:sin, g:0, h:-sin, i:cos}; 
      transform(matrix, model);
    };
    rotateY = function (model, degree) {
      var rad = degree*Math.PI/180;
      var sin = Math.sin(rad);
      var cos = Math.cos(rad);
      var matrix = {a:cos, b:0, c:-sin, d:0, e:1, f:0, g:sin, h:0, i:cos};
      transform(matrix, model);
    };
    rotateZ = function (model, degree) { 
      var rad = degree*Math.PI/180; 
      var sin = Math.sin(rad); 
      var cos = Math.cos(rad);
      var matrix = {a:cos, b:sin, c:0, d:-sin, e:cos, f:0, g:0, h:0, i:1};
      transform(matrix, model);
    };
    scale = function (model, percent) { 
      var rad = degree*Math.PI/180;
      var matrix = {a:percent, b:0, c:0, d:0, 
        e:percent, f:0, g:0, h:0, i:percent}; 
      transform(matrix, model);
    };

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

  2. Под определениями матриц, добавленными в предыдущем шаге, введите следующий код.
    transform = function (matrix, model) { 
      if (transformMatrix) {
        var a = matrix.a*transformMatrix.a+matrix.b*transf onrmMatrix.d
        +matrix.c* transformMatrix.g ;
        var b = matrix.a*transformMatrix.b+matrix.b*transf ormMatrix.e
        +matrix.c*transformMatrix.h;
        var c = matrix.a*transformMatrix.c+matrix.b*transformMatrix.f
        +matrix.c*transformMatrix.i;
        var d = matrix.d*transformMatrix.a+matrix.e*transformMatrix.d
        +matrix.f*transformMatrix.g;
        var e = matrix.d*transformMatrix.b+matrix.e*transformMatrix.e
        +matrix.f*transformMatrix.h;
        var f = matrix.d*transformMatrix.c+matrix.e*transformMatrix.f
        +matrix.f*transformMatrix.i;
        var g = matrix.g*transformMatrix.a+matrix.h*transformMatrix.d
        +matrix.i*transformMatrix.g;
        var h = matrix.g*transformMatrix.b+matrix.h* transformMatrix.e
        +matrix.i*transformMatrix.h;
        var i = matrix.g*transformMatrix.c+matrix.h*transformMatrix.f
        +matrix.i*transformMatrix.i;
        transformMatrix = {a:a, b:b, c:c, d:d, e:e, f:f, g:g, h:h,i:i};
      } else {
        transformMatrix = matrix; 
      }
    };

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

  3. Введите следующий код в функцию render.
    render = function (model) { 
      if (transfonriMatrix) { 
      for (var i = 0; i<model.vertexList.length; i++) {
        var vert = model.vertexList[i];
        var x = transformMatrix.a*vert.x+transformMatrix.b*vert.y
        +transformMatrix.c*vert.z;
        var y = transformMatrix.d*vert.x+transformMatrix.e*vert.y
        +transformMatrix.f*vert.z;
        var z = transformMatrix.g*vert.x+transformMatrix.h*vert.y
        +transformMatrix.i*vert.z;
        vert.x = x;
        vert.y = y;
        vert.z = z;
      }
      delete transformMatrix;
    }
      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);
      }
    };
    Пример 10.1.

    Наконец, перед прорисовкой модели на экране нужно применить наши преобразования (которые удобным образом сохранены в одной матрице) к вершинам. Дополнительным кодом является основная формула умножения матрицы 3х3 (нашего преобразования) на матрицу 3х1 (координаты каждой вершины). После этого мы удаляем наше преобразование для подготовки к дальнейшим преобразованиям.

  4. Для вызова наших новых функций преобразования измените функцию onEnterFrame в конце кода следующим образом.
    center.onEnterFrame = function() { 
      rotateX(cube, 3); 
      rotateY(cube, 6); 
      rotateZ(cube, 10);
      render(cube); 
    };

    Несмотря на то, что мы осуществляем три отдельных преобразования, они не будут применены к модели, пока не будет вызвана функция render, один раз в каждом кадре. Запустите фильм, чтобы увидеть результат работы.


    С помощью матриц преобразования размером 3х3, вращение нашей каркасной модели вокруг всех трех осей осуществляется более эффективно.

    Если вы получите какие-либо неожиданные результаты, сверьте ваш код с написанной мной программой в файле spinning_cube_2.fla на компакт-диске.

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

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

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

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

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

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