Date Редакция Категория comp Теги pov-ray / графика

Графики и диаграммы давно стали привычными атрибутами научной литературы. Однако ими научная иллюстрация далеко не ограничивается. Нередко объект исследований настолько сложен (течение жидкости, движение системы твердых тел), что важно увидеть весь процесс происходящих в нем изменений целиком, иначе просто неясно какой график следует строить. Здесь на помощь ученым приходят средства трехмерной визуализации. Об одном из таких средств и пойдет наш рассказ.

kitchen.jpg

Обычная кухня... Нет, это не фотография, а изображение, созданное в программе POV-Ray методом трассировки лучей. Представьте, что экран вашего компьютера — это окно, за которым что-то происходит. Это «что-то» называется сценой. Цвет каждого пикселя на экране — это цвет луча, который выходит из глаза, проходит через этот пиксель и сталкивается со сценой. Луч может просто вернуться назад, а может отразиться от зеркальной поверхности или преломиться, проходя, например, из воздуха в стекло. Чтобы узнать цвет, в который окрасится пиксель, нужно запустить через него луч и проследить путь этого луча по сцене. Отсюда произошло название алгоритма: ray-tracing — трассировка лучей.

Точнее, это обратная трассировка лучей. Ведь, как мы знаем, луч не выходит из глаза, а наоборот, попадает в него, проделав свой путь от источника света. Однако такая (прямая) трассировка требует огромных вычислительных ресурсов, ведь большая часть лучей пропадает даром, не попав в наше поле зрения. Подробнее физические основы метода обратной трассировки лучей изложены в книге Е. В. Шикина и А. В. Борескова «Компьютерная графика. Динамика, реалистические изображения» (М.: Диалог-МИФИ, 1995).

POV-Ray или, полностью — The Persistence of Vision Ray-Tracer — использует обратную трассировку лучей для создания трехмерных фотореалистических изображений. Сцена в POV-Ray описывается на SDL (Scene Description Language) — интерпретируемом языке программирования с С-подобным синтаксисом. При помощью SDL пользователь задает положение камеры, источников света, размещение объектов и их свойства, атмосферные эффекты и т. п.

Применение POV-Ray для научной иллюстрации — лишь малая часть среди возможных направлений использования этой программы. И даже с этой малой частью мы в статье успеем лишь познакомимся. Что ж, приступим…

Векторы и система координат

POV-Ray работает с вещественными числами и векторами. Вектором называется точка в пространстве, задаваемая как <x,y,z>. Координаты вектора могут быть числами или переменными, например: <1,.2,cos(alpha)>.

Система координат, принятая в POV-Ray по умолчанию, выглядит так:

ref_frame.png

Ось Z направлена внутрь монитора.

Чтобы получить изображение, нам понадобится объект для съемки, освещение, и камера. Вот с нее и начнем.

Камера

«Фотографию» сцены невозможно создать без камеры (camera). Точка, в которой расположена камера, задается параметром location, а параметр look_at определяет точку, куда она направлена. В качестве примера, поместим камеру в точку <0,0,-10> и направим ее в начало отсчета. Записывается это так:

camera
{
  location <0,0,-10>
  look_at <0,0,0>
}

Источник света

Разместим позади и справа от камеры источник света light_source:

light_source
{ 
  <10,20,-20>
  color <1,1,1>
}

Вектор <10,20,-20> определяет положение источника света, а вектор color — его цвет <R,G,B>. Яркость каждой из компонент цвета изменяется от 0 (полное отсутствие соответствующего цвета) до 1 (максимальная яркость).

По умолчанию, источник света невидим — это просто светящаяся точка, но его можно сделать видимым, а также привязать к любому объекту, как встроенному, так и созданному пользователем.

Простые объекты

POV-Ray располагает обширной библиотекой готовых объектов. Вот, например, как задается сфера:

sphere
{
  <0,0,0>,2
}

Первый вектор определяет положение центра сферы, а следующее за ним число — ее радиус. Наша сфера расположена в начале координат и ее радиус равен 2.

Вставка готовых объектов POV-Ray при помощи меню Insert (POV-Ray для Windows)

По умолчанию, сфера окрашивается в черный цвет. Пигмент (краситель), задающий цвет объекта, определяется в блоке pigment:

sphere
{ 
  <0,0,0>,2
  pigment
  { color <1,1,1> }
}

Цвет пигмента задается точно также как цвет источника света. В нашем случае сфера будет окрашена в белый цвет.

Собирая все фрагменты вместе, получим:

camera
{ 
  location <0,0,-10>
  look_at <0,0,0>
  angle 35
}

light_source
{ 
  <10,20,-20>
  color 1
}

sphere
{ 
  <0,0,0>,2
  pigment
  { color <1,1,1> }
}

Пора «попросить» POV-Ray оттрассировать это. Сохраним сцену в файле test.pov и запустим POV-Ray командой:

povray +itest +w320 +h240

Опция +i задает имя файла, из которого вводятся данные (input): test.pov (расширение указывать не обязательно, POV-Ray предполагает, что это будет .pov). Опции +w и +h с последующими цифрами задают ширину (width) и высоту (height) изображения в пикселах.

В POV-Ray для Windows трассировку можно выполнить с помощью меню:

Запуск трассировки сцены с помощью кнопки Run

Вот что у нас получилось:

first.png

Для начала неплохо. Напоминает планету в космосе. Можно усилить это сходство, нанеся на поверхность сферы рельеф и текстуру. Как это сделать, описано здесь, а мы пойдем дальше.

Конструктивная геометрия

Новые тела можно получать из уже имеющихся при помощи операций объединения, слияния, разности, пересечения и т. п. Такой способ создания новых объектов называется конструктивной блочной геометрией (Constructive solid geometry, CSG).

Создадим изображение молекулы воды, состоящее из большой сферы — атома кислорода и двух малых сфер — атомов водорода:

sphere
{
  <0,0,0>,2
  pigment
  { color Red }
}

sphere
{
  <1.5,0,0>,1.5
  pigment
  { color White }
}

sphere
{
  <1.5,0,0>,1.5
  pigment
  { color White }
  rotate <0,0,104.45> // угол между атомами водорода
}

Команда rotate вращает объект относительно начала отсчета. В данном случае мы повернули вторую из малых сфер на 104.45 градуса (т. е. на угол между атомами водорода в молекуле воды). Как видно, в POV-Ray, в отличие от многих языков программирования, углы задаются в градусах, а не в радианах.

Объединим теперь сферы в единый объект командой union. Полученному объекту можно присвоить имя и затем использовать его под этим именем в дальнейших расчетах. Назовем наш объект — H2O.

Объявляется объект командой declare, а непосредственно создается — командой object{имя_объекта}. Покажем, как построить объединение трех сфер:

#include "colors.inc"
...
#declare H2O =
union
{
  sphere { <0,0,0>,2 pigment { color Red } }
  sphere { <1.5,0,0>,1.5 pigment { color White } }
  sphere { <1.5,0,0>,1.5 
           pigment { color White }  
           rotate <0,0,104.45>
         }
}

object
{ 
  H2O 
  rotate <0,0,36>
}  

и получим:

water.png

Заметим, что после своего создания объект H2O поворачивается как единое целое на 36 градусов:

Названия цветов вроде Red и White — это имена векторов, объявленные в подключаемом файле colors.inc.

Применяя этот подход можно легко создать несколько объектов:

water_molecules.png

Немудрено, что POV-Ray активно используется для визуализации молекулярных структур (пример){rel="nofollow"}.

Анимация

POV-Ray позволяет создавать анимацию в виде последовательности кадров. Чтобы на этих кадрах что-то изменялось, нужна переменная, задающая время — она называется clock. Кроме того, нужно задать некоторые настройки, например, количество кадров. О настройках поговорим чуть позже, а пока рассмотрим пример:

camera
{
  location <0, 3, -6>
  look_at <0, 0, 0>
}

light_source { <20, 20, -40> color White }

plane
{
  y, 0
  pigment { checker color White color Black }
}

box
{
  <-1, 0, -1> , <1, 2, 1>
  pigment { color Green }
  translate <clock, 0, 0>
}

Здесь вводятся два новых объекта — бокс box и плоскость plane. y — это вектор нормали к поверхности и равен он <0,1,0>.

Ключевой момент здесь — строка translate <clock, 0, 0>. Переменная clock, по умолчанию, равна 0 в начале анимации и 1 — в конце. Благодаря этому бокс должен переместиться на одну клетку вправо.

Теперь зададим число кадров. Номера первого и последнего кадров задаются параметрами Initial_Frame и Final_Frame. Initial_Frame по умолчанию равен 1, и менять его мы не собираемся, а Final_Frame зададим равным 20. Это делается в командной строке с помощью опции +KFF так: +KFF20.

Чтобы не писать каждый раз настройки в командной строке, поместим их в отдельный текстовый файл — my.ini. Настройки можно записывать точно так же, как в командной строке, или в более читабельном виде. В нашем примере INI-файл имеет вид:

Width=320
Height=240
Final_Frame=20

Теперь командная строка будет выглядеть так:

povray +iимя_файла my.ini

В результате получится последовательность из 20 кадров — графических файлов, которые затем можно будет преобразовать в видео. Для этого есть масса инструментов, например Virtualdub — широко распространенный, свободный и кроссплатформенный.

Вот что у нас получилось в итоге:

translate_box.gif

Цикл while

Допустим, нам нужно выполнять анимацию вплоть до заданного момента времени. Тогда нам пригодится цикл с условием:

#while (логическое_условие)
  ...
#end

Он будет выполняться до тех пор, пока остается истинным логическое условие, стоящее в скобках.

Давайте нарисуем бокс, поместим на его вершину шар, столкнем его и нарисуем что из этого получится:

#include "colors.inc"

light_source { <0,5,-50> color White }
light_source { <0,50,0> color White }
light_source { <10,2.5,0> color White }

camera { location <5,3,-10> look_at <1,3,0> } 

#declare time = 0.0;
#declare px = 0.0;
#declare py = 5.0;
#declare vx = 5;
#declare vy = 0.0;
#declare g = 9.8; 

box { <-5,py,2>, <0,-2,-2> pigment {Blue} }
plane { y, 0 pigment {Gray} } 

#while (time <= clock)
  #declare dt = clock_delta;
  #declare px = px+vx*dt;
  #declare py = py+vy*dt-0.5*dt*dt;
  #declare vy = vy-g*dt;

  sphere { <px,py,0>, 0.2 pigment {Green} }

  #declare time = time + clock_delta;
#end

Координаты шара задаются переменными px, py, а его скорость — vx, vy. g — ускорение свободного падения. Если это вам ни о чем не говорит, то просто примите формулы на веру и сосредоточьтесь на рисовании.

Здесь в цикле изменяется «пользовательское» время time, увеличиваясь на каждом шаге на clock_delta. Я назвал это время так, потому что его состоянием пользователь может управлять по своему желанию, тогда как для clock можно задавать только диапазон изменения. На каждом шаге цикла рисуется все больше и больше шаров, до тех пор пока время рисования не закончится (т. е. достигнет значения Final_Clock).

animate_while.gif

Чтобы не рисовать «след» из шаров, достаточно вынести команду sphere за пределы цикла и поместить ее после #end.

Обратите внимание на то, что сцена освещена сразу тремя источниками света. Первый источник дает нам обычное освещение. Зачем тогда нужны два других? А вот зачем. Второй источник освещает сцену сверху и позволяет получить «дорожку» из теней шаров в горизонтальной плоскости. Третий — светит сбоку и дает тени шаров на вертикальной стенке бокса. Теперь мы можем увидеть, что вдоль координаты X шар движется равномерно, а вдоль Y — ускоряется. Пригодится в качестве наглядного примера на уроке физики, не так ли?

Заметим, что POV-Ray — не лучшее средство для моделирования движения, он все-таки только «рисователь». Обычно, движение моделируется с помощью какого-то из языков программирования (например, С), результаты сохраняются в виде команд POV-Ray, а уж тот рисует как двигалось тело. Но, как видим, если нужно, то простое моделирование можно выполнить и в самом POV-Ray.

Кроме цикла с условием #while, в POV-Ray есть и цикл со счетчиком — #for, есть условный оператор #if и блок выбора #switch, есть... Ну, вы поняли: много чего есть в POV-Ray, а статья не резиновая. Но перед тем как попрощаться…

Немного ссылок

Исходный код примеров

Впервые опубликовано в KV.by. Здесь приводится в авторской редакции.



Комментарии

comments powered by Disqus