Программа использует скритовый язык IFS для задания аттракторов (фракталов)
и параметров трёхмерной сцены
Структура ifs-файла
camera <атрибуты камеры>;
light <атрибуты источника света1>;
light <атрибуты источника света2>;
...
background(r,g,b,l); // цвет/яркость фона
<формулы, отображения, подстановки>
set s1 = <структура множества1>;
set s2 = <структура множества2>;
...
build <структура множества3> <материал1>;
build <структура множества4> <материал2>;
Приведём сначала работающий пример скрипта и, затем, объясним обозначения.
Пример: Снежинка Коха
camera position (0,0,-80) vertical(0,1,0) fov(50);
light color (0,1,0) position (1, 1,-3) shadows(0);
light color (1, 1, 0) position (3,-1,-1) shadows(0);
ambient(1,1,1,.05);
background(0,1,1,0.5); // цвет фона
s=sqrt(3);
f1 := translate(1/2, 1/2/s,0)*scale(1/s)*rotate(0,0,-1,150);
f2 := translate(1,0,0)*scale(1/s)*rotate(0,0,-1,-150);
f3 := translate(-1/2,s/2,0)*scale(s)*rotate(0,0,-1,30);
f4 := translate(-1/2,-s/2,0)*scale(s)*rotate(0,0,-1,-90);
f5 := translate(1,0,0)*scale(s)*rotate(0,0,-1,150);
set KochCurve = (f1 + f2) KochCurve; // задание кривой Коха
set Snowflake = (f3 + f4 + f5) KochCurve;
build Snowflake;
Данный скрипт сначала опрделяет структуру кривой Коха (KochCurve), состоящей из двух своих уменьшенных копий
KochCurve = f1(KochCurve) ∪ f2(KochCurve).
Затем определяет и саму снежинку Коха (Snowflake), состоящую из трёх образов кривой Коха:
Snowflake = f3(KochCurve) ∪ f4(KochCurve) ∪ f5(KochCurve).
Примечание: для пояснения различия между знаком присваивания '=' и знаком ':=' см. раздел подстановки.
Множества и отображения
Под множеством понимается произвольный набор точек в трёхмерном пространстве.
Отображение - любое преобразование множеств в другие множества.
Например, отображение scale(k) сжимает все точки (x,y,z) в (k*x,k*y,k*z).
Множества в программе задаются уравнениями вида: set S = f1(S) + f2(S) + ... + fn(S);
Здесь S обозначает множество в 3-х мерном пространстве, знак '+' обозначает объединение множеств,
и f1,...,fn - аффинные или мёбиусовы отображения множеств в трёхмерном пространстве,
каждое из которых задаётся, как композиция базовых отображений.
Заметим, что математики обозначают объединение знаком ∪,
т.е. правильная математическая запись приведённого выше уравнения:
S = f1(S) ∪ f2(S) ∪ ... ∪ fn(S).
Программа (исторически) использует знак плюса из-за ограничений клавиатуры и таблицы символов (ASCII).
Композиция отображений обозначается знаком суперпозиции '*'.
Например translate(tx,ty,tz) * scale(k) * M
означает сжать множество M с коэффициентом сжатия k и сдвинуть затем на вектор (tx,ty,tz)..
Знак суперпозиции отображений можно опускать.
Более того, работает ассоциативность операций '+' и '*', т.е.
запись f1*(f2+f3) эквивалентна f1*f2+f1*f3.
Ассоциативность работает также с множествами, например, запись f1(S)+f2(S) эквивалентна (f1+f2)S.
Пример отображения:
f1 := translate(-1,0,0) * scale(1/2);
Пример задания множества (отрезка [-1,1]):
Segment = scale(0.5) * (translate(1,0,0) + translate(-1,0,0)) Segment;
Базовые отображения множеств.
Отображение | Тип* | Описание |
id() | S |
Тождественное отображение. |
scale(k) | S |
Сжатие к началу координат с коэффициентом k. |
scale(kx,ky,kz) | A |
Сжатие к началу координат с коэффициентами kx,ky,kz вдоль соответствующих осей. |
rotate(x,y,z,angle) | S |
Поворот на угол angle вокруг оси проходящей через начало координат и точку (x,y,z). |
rotate(x,y,z,angle,along,across) | A |
То же что и предыдущее, но дополнительно происходит сжатие вдоль оси
с коэффициентом along и поперек с коэффициентом across. |
rotate(angle) | S |
Поворот на угол angle вокруг оси (0,0,1) |
translate(x,y,z) | S |
Сдвиг на вектор (x,y,z). |
translate(x,y) | S |
Сдвиг на вектор (x,y,0). |
reflect(x,y,z) | S |
Отражение относительно плоскости проходящей через начало координат и имеющей нормаль (x,y,z). |
matrix(ax,ay,az,bx,by,bz,cx,cy,cz) | A |
Линейное преобразование заданное матрицей 3x3:
|
affine2d(ax,ay,bx,by,tx,ty) | A |
Композиция отображений translate(tx,ty,0) * matrix(ax,ay,0,bx,by,0,0,0,0).
Удобна для задания двумерных самоаффинных фракталов. |
stretch(x,y,z,k) | M |
Сохраняющее ориентацию мёбиусово преобразование переводящее шар единичного радиуса
с центром в начале координат сам на себя и сдвигающее его центр в направлении (x,y,z) на расстояние k. |
inverse(x,y,z,r) | M |
Отражение относительно сферы с центром (x,y,z) и радиусом r.
Это мёбиусово преобразование, меняющее ориентацию. |
bound(x,y,z,r) | M |
Это не совсем отображение. Ограничивающий оператор bound помечает,
что мёбиусово-порождённое множество, на которое он действует, лежит в шаре с
центром (x,y,z) и радиусом r. Мёбиусовы отображения, порождающие
данное множество, должны быть сжимающими в этом шаре. Каждому
мёбиусово-инвариантному множеству (аттрактору) должен быть сопоставлен
оператор bound, если это множество в заданной IFS или Digraph-IFS
системе выражается через себя. |
empty() | |
Ставит в соответствие любому множеству пустое.
Удобно для задания случайно-порождённых фракталов. |
section(nx,ny,nz,d) | |
Пересекает множество с плоскостью заданной уравнением x*nx+y*ny+z*nz=d. |
*Примечание: A - аффинное, S - подобие, M - мебиусово.
Программа не разрешает при задании любого множества смешивать аффинные и мебиусовы отображения.
Камера.
Вид сцены существенно зависит от положения наблюдателя (камеры).
Описание параметров камеры начинается с ключевого слова camera, после которого
перечисляются атрибуты.
Атрибут | По умолчанию | Описание |
position(x,y,z) | обязателен |
Точка (x,y,z) задает положение камеры(наблюдателя). |
direction(x,y,z) | выбирается автоматически |
Вектор (x,y,z) задает направление взгляда. |
vertical(x,y,z) | обязателен |
Вектор (x,y,z) задает вертикальное направление. |
fov(angle) | 50 градусов |
Число angle задает угол обзора по вертикали. |
stereo(eyeDist, scrDist) | режим 'mono' |
Включить режим стереоизображения,
eyeDist - расстояние между глазами,
scrDist - расстояние от наблюдателя до экрана. |
Освещённость.
Освещённость сцены рассчитывается широко известным методом трассировки лучей (ray-tracing),
который требует чтобы были заданы источники света и отражающие свойства поверхности
объектов (цвет, зеркальность и т.п.)
Цвет/яркость в программе задаются в виде (r,g,b,lum), где r,g,b - цвет, lum - яркость.
Параметр lum можно не указывать в этом случае lum=1.
1. Параметры освещенности сцены.
Параметр | По умолчанию | Описание |
ambient(r,g,b,lum) | (0,0,0,0) |
Цвет/яркость фонового освещения сцены. |
background(r,g,b,lum) | Цвет/яркость фона. |
tracing_depth(n) | 0 |
Кол-во последовательных отражений лучей. n=0 (нет отражений),1,2,3 ... |
antialiasing(n) | 0 |
Сглаживание эффекта 'пикселизации'. n=0(выключено),1,2,3 ... |
screen_size(width, heght) | from UI |
Задать разрешение вычисляемого изображения, игнорируя настройки интерфеса. |
reflect_background | off |
Включает отражение фона в фрактале. Работает только при расчёте отражений (tracing_depth>1) |
2. Источники света.
- Программа поддерживает 3 типа источников света: Лампа, Прожектор, Солнце
(точечный, направленный и параллельный источники).
- Добавить источник в сцену можно указав слово light и перечислив после него
соответствующие атрибуты.
- Тип источника определится автоматически по заданным атрибутам.
- Количество источников в сцене может быть произвольным, при этом они могут быть разных типов.
Следующая таблица поясняет назначение атрибутов.
Атрибут | Лампа | Прожектор | Солнце | Описание |
position (x,y,z) | R | R | N/A |
Точка (x,y,z) задает положение источника. |
direction (dx,dy,dz) | N/A | R | R |
Вектор (x,y,z) задает направление, в котором светит источник. |
spot_angles (a1,a2) | N/A | R | N/A |
Углы задающие размеры пятна у направленного источника света. |
attenuation (qa,la,ca) |
по умолчанию (1,0,0) | N/A |
Коэффициент квадратичного, линейного и постоянного ослабления яркости источника от расстояния. |
shadows (1 | 0) |
по умолчанию (1) |
1 - источник загораживается объектами, 0 - не загораживается. |
attachment (1 | 0) |
1 - источник привязан к системе координат объекта, 0 - камеры. |
diffuse (r,g,b,lum) |
Требуется хотя бы один.
По умолчанию (0,0,0,0) |
Задает рассеяный цвет/яркость источника. |
specular (r,g,b,lum) |
Задает зеркальный цвет/яркость источника. |
color (r,g,b,lum) |
Задает одновременно рассеяный и зеркальный цвет/яркость источника |
Примечание: N/A - атрибут нельзя задавать, R - атрибут требуется задавать.
3. Отражающие свойства поверхностей.
Свойства поверхности задаются после команды build.
Так как слово build может встречаться несколько раз, имеется возможность строить в одной
сцене объекты с разными свойствами поверхности.
Свойство | Примечания | Описание |
ambient(r,g,b,lum) |
Аргументы можно задать в виде (r,g,b) или (lum) |
Устанавливает цвет/яркость фоновой составляющей. |
diffuse(r,g,b,lum) |
Устанавливает цвет/яркость рассеянной составляющей. |
specular(r,g,b,lum) |
Устанавливает цвет/яркость зеркальной составляющей. |
color(r,g,b) |
для простоты |
Задает цвет фоновой и рассеянной составляющей.Зеркальная устанавливается в (1,1,1). |
metall(r,g,b) | |
Задает металлическую поверхность : устанавливает цвет рассеянной и зеркальной составляющей. |
Подстановки
Подстановки позволяют упростить задание множеств и отображений. Общая запись подстановки:
<name> := <value>;
Данная запись означает, что все последующие вхожения слова <name> в скрипте
будут заменены на строку <value>.
Например код
sum := a + b;
result = sum * 3;
эквивалентен
result = a + b * 3;
Арифметические выражения
В формулах принят синтаксис общий для языков C++/Java/Perl/PHP.
- Имена переменных могут состоять из символов a-z,A-Z и подчёркивания "_"
- Вещественные функции:
ln(x), exp(x), sqrt(x), abs(x), sign(x), sin(x), cos(x), tan(x), atan(x)
atan2(y,x), arg(x,y) - эти две функции возвращают arctg(y/x)
rnd(x) - случайное вещественное число на отрезке [0,x]
- Поддерживаемые вещественные, логические и битовые операции:
= += -= *= /= + - * / , () ?: ++ -- == != < <= > >=
- Константы: PI и E.
Случайно-порождённые фракталы
При построении аттрактора IFS системы, можно указать, что
отображения дробящие множество (атрактор) на кусочки (далее называемые порциями),
необходимо выбирать случайным образом из некоторого заданного набора отображений.
Правила задания случайного фрактала:
-
При построении, всему множеству, каждой его порции, каждой подпорции и т.п. сопоставляется псевдослучайное число.
Число соответсвующее всему множеству можно задать вызвав перед оператором build функцию
randState(аргумент), где вещественный аргумент лежит на отрезке [0,1].
Например: randState(rnd(1));
- Оператор (...)%n , где n - целое число, выбирает из скобок
n отображений (или n порций), остальные выкидывает.
Для выбора использует псевдослучайное число соотвествующее порции, которая дробится.
Пример: (f1+f2+f3)%2.
- В операторе (...)%n после каждого отображения можно в фигурных скобках
указать вес отображения (вещественное число большее нуля).
Вероятность, с которой это отображение будет выбираться, вычисляется,
как вес отображения делённый на сумму весов.
Если вес не указан, он полагается равным единице.
Например: (f1{2}+f2{3})%1
- При дроблении некоторой порции, по умолчанию псевдослучайное число передаётся её подпорциям без
изменений. Но если встретилась конструкция f|m, то "случайное" число для
подпорции, полученной применением отображения f, изменяется способом m,
точнее изменяется под действием псевдослучайного генератора, зависящего от параметра m.
Так, если у двух отображений номер m совпадает
(например, в конструкции (f1|1+f2|1) ), то соответсвующие подпорции,
получаемые под действием отображений f1,f2, получат одинаковое псевдослучайное число,
и будут дробиться одинаковым образом.
Управляющие конструкции
- { оператор1; оператор2; ... }
Составной оператор. Выполняет последовательность операторов, расположенных в фигурных скобках.
- if(выражение) оператор1; [ else оператор2;]
Выполняет оператор1, если выражение отлично от нуля, иначе выполняет оператор2.
Раздел else необязателен.
Вместо любого из операторов можно использовать составной оператор.
- for(инициализация; выражение; итерация) тело;
Сначала выполняется инициализация. Затем, в цикле вычисляется выражение
и пока оно отлично от нуля выполняются тело цикла и итерация.
- while(условие) тело;
Пока условие отлично от нуля, выполняется тело цикла.
- do { тело; } while(условие);
Выполяет тело цикла, затем проверяет условие,
и если оно отлично от нуля, снова выполнянет тело, затем снова проверяет условие и т.д.
- echo <переменные и строки>;
Печатает в лог вывода переменные и текст, размещённый в двойных кавычках.
Текст и имена переменных должны разделяться пробелом.
Единицы измерения углов
angles ( degree | radian ) - устанавливает единицы измерения углов,
влияет на fov, rotate, spot_angles и тригонометрические функции.
Значение по умолчанию: degree.
Анимация
Для записи кадра анимации нужно вызвать функцию save_frame().
Для записи последовательности кадров рекомендуется использовать оператор цикла for.