Дисципліна: Засоби програмування комп'ютерної графіки

Тема: Робота з текстурами

План

1. Текстури.

2. Математика перетворень з текстурами.

1. Текстури.

Текстури – це растрові малюнки, які накладаються на грань об'ємної фігури (рис.9.1). У цьому розділі ми будемо використовувати паралельну проекцію (без урахування перспективних спотворень, які суттєво ускладнюють справу). У цьому прикладі текстури використовуються на кожній грані куба, його можна обертати в різні боки мишкою і клавішами-стрілками. Натиснувши на кнопці із зображенням маленького кубика можна встановити його в початкове положення, яке відповідає ізометричній проекції, яка не спотворює пропорції. Довжини всіх ребер куба тут однакові, кут між ребрами дорівнює 120 °. Для побудови ізометрії кубик потрібно спочатку повернути на 45 ° щодо осі Y, а потім – на 30 ° щодо осі X:

rotate3D (vert, pt3D (0, 45, 0));

rotate3D (vert, pt3D (30, 0, 0));

2. Математика перетворень з текстурами.

Тепер настав час спробувати розібратися в математиці такого перетворення. Зліва на схемі показаний бажаний паралелограм, а праворуч – вихідний прямокутник, повернений на 45 ° (рис.9.2). Тут через p0 позначена точка реєстрації кліпів, а через pH і pW – кутові точки, що визначають висоту і ширину паралелограма. Тангенси кутів α1 і α2 можуть бути знайдені з формул, а самі кути – за допомогою функції Math.atan2. Тут через Δx позначена різниця x-координат точок, а через Δy – різниця їх y-координат. Тоді внутрішній кут паралелограма, позначений як 2α, обчислюється як різниця 2 • α = 180 ° - α1 - α2. Цей кут потрібно отримати масштабуванням вихідного прямокутника (на малюнку праворуч) тільки по осі Y. Позначимо коефіцієнт масштабу через k, він дорівнює масштабному коефіцієнту, який потрібно застосувати для головного кліпу. При y-масштабуванні всі вертикальні розміри множаться на k, а горизонтальні – зберігаються. Тепер знайдемо масштабні коефіцієнти kx і ky для вкладеного кліпу. Позначимо через w – довжину ребра, що з'єднує точки p0 і pW, а через w0 – потрібну ширину внутрішнього кліпу-прямокутника. З огляду на масштабування головного кліпу, аналогічні вирази можна записати і для висоти. Створіть новий файл типу ActionScript File, запишіть в нього код функції зсуву:

function skewClip (clip, p0, pW, pH, w, h) {

function dX (p1, p2) {return p1.x - p2.x;

}

function dY (p1, p2) {return p1.y - p2.y;

}

function dist (p1, p2) {

var dx = dX (p1, p2), dy = dY (p1, p2);

return Math.sqrt (dx * dx + dy * dy);

}

var a, a1, a2, da, s, scale;

clip._x = p0.x; clip._y = p0.y;

clip._xscale = 100;

clip._rotation = 0;

a1 = Math.atan2 (dX (pW, p0), dY (p0, pW));

a2 = Math.atan2 (dX (pH, p0), dY (pH, p0));

a = (Math.PI - a1 - a2) / 2;

scale = Math.tan (a);

clip._yscale = 100 * scale;

da = Math.PI / 2 - a - a1;

clip._rotation - = da * 180 / Math.PI;

s = dist (p0, pW);

q = Math.sin (a) /scale*Math.sqrt (2);

clip.inner._xscale = 100 * s * q / w;

s = dist (p0, pH);

clip.inner._yscale = 100 * s * q / h;

}

Збережемо файл під ім'ям skew.as. Ця функція в точності реалізує описаний вище алгоритм. У ній введені внутрішні функції dX, dY і dist, які дозволяють визначити різницю x-координат, різницю y-координат і відстань між двома точками. Розглянемо приклад, в якому обертається одна грань з накладеною текстурою. Відкрємо файл texture.fla:

#include "3d.as" #include "skew.as" this.createEmptyMovieClip ( "scene", 1);

scene._x = 275; scene._y = 200;

Цей код стандартний і не вимагає пояснень. Додайте до кадру 1 код:

fig = new Object ();

fig.vert = [pt3D (-50,50,0),

pt3D (-50, -50,0),

pt3D (50, -50,0),

pt3D (50,50,0)];

fig.faucet = [[0, 1, 2, 3]];

fig.bitmap = [1];

Тут створюється об'єкт, який має поля vert (вершини), faucet (межі) і bitmap (малюнки). Важливо, що в масиві faucet перший номер вершини відповідає точці pH, другий – точці p0, а третій – точці pW (рис.9.2). Цей порядок буде використовуватися при накладенні текстури. Всі малюнки записані в бібліотеку у вигляді кліпів pic1, pic2, ..., pic6. Додайте до кадру 1 код:

scene.createEmptyMovieClip ( "faucet0", 1);

scene.faucet0.attachMovie ( "pic" + fig.bitmap [0], "inner", 1);

scene.faucet0.inner._rotation = -45;

Усередині кліпу scene створюється кліп faucet0, що представляє грань. Символ з текстурою приєднується до нього як внутрішній кліп inner. Ім'я кліпу в бібліотеці будується з рядка "pic" і номера рисунка для даної грані, який зберігається в масиві bitmap. Внутрішній кліп відразу повертається на 45 ° проти годинникової стрілки. Додайте до кадру 1 код:

w0 = 100;

h0 = 100;

rotate3D (fig.vert, pt3D (0,45,45));

showFigureBmp (fig);

function showFigureBmp (fig) {

var v = fig.faucet [0];

var pH = fig.vert [v [0]];

var p0 = fig.vert [v [1]];

var pW = fig.vert [v [2]];

skewClip (scene.faucet0, p0, pW, pH, w0, h0);

}

Змінні w0 і h0 задають ширину і висоту малюнків. Грань відразу повертається на 45 ° по осях Y і Z і виводиться за допомогою функції showFigureBmp. Ця функція зводиться до визначення потрібних вершин і викликом функції skewClip. Додайте до кадру 1 код обробника:

scene.onEnterFrame = function () {

rotate3D (fig.vert, pt3D (2,0,2));

showFigureBmp (fig);

}

Збережіть файл і перевірте роботу кліпу При зміні кадру фігура повертається на 2 ° по осях X і Z. Виникає питання: «Як накласти текстуру на фігуру іншої форми (трикутник, трапецію тощо). Найпростіший спосіб – використовувати маску, тобто накладати текстуру на прямокутник, але непотрібну частину відсікати за допомогою маски. Збережемо файл під ім'ям cube_texture.fla і доопрацюємо його так, щоб на екрані вийшов куб, що обертається, всі 6 граней якого залиті текстурами. При виконанні цієї роботи потрібно враховувати, що видимість граней тепер визначається не порядком малювання, а глибиною кожної грані-кліпу. Тому після Z-сортування потрібно використовувати метод swapDepths, який переводить кліп на потрібний рівень.

Дисципліна: Засоби програмування комп'ютерної графіки

Тема: Робота з текстурами