English
Лаборатория компьютерной графики
Rus > Библиотека > VRML. Справка по языку
[Главная]
[О нас]
[Наука]
[Публикации]
[Семинары]
[Библиотека]
[Файлы]
[Ссылки]
[Форум]
 
Hosted sites
[Курсы]
[Журнал]
[Графикон]
[Сжатие]
[Графор]
 
Поиск
детальный поиск
 
Rambler's Top100

VRML. Справка по языку.

Антон Конушин
ktosh@zmail.ru

Введение


VRML (Virtual Reality Modeling Language) - это язык и формат файлов описания интерактивных трехмерных объектов и виртуальных миров. VRML спроектирован для использования в Internet (и является de facto стандартом 3D графики в Сети). Однако VRML файлы можно использовать и в локальных системах. VRML также является перспективным универсальным форматом хранения и обмена мультимедиа-информашией.
Каждый VRML файл является описанием трехмерного пространства, содержащего графические (и звуковые) объекты, которое может динамически изменяться при помощи различных механизмов языка. Поддерживается коншепшия времени. Стандарт языка определяет множество первичных классов объектов и обеспечивает средства сборки (создание виртуального мира), инкапсуляшии и расширения (определение новых классов объектов на основе первичных и/или определенных ранее).
Каждый VRML файл
  • определяет координатное пространство для всех объектов в файле; а также для объектов, включаемых из внешних файлов (используется правая система координат);
  • определяет множество 3D и мультимедиа объектов и их размещение в координатном пространстве;
  • определяет гиперссылки на другие файлы и/или приложения;
  • определяет поведение объектов;

VRML как посредник


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

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

VRML как язык описания объектов


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

Структура VRML представления


VRML является объектно-ориентированным языком описания сшен. Вся сшена представляется в виде иерархически связанного набора объектов – графа сшены. В VRML объекты является узлами (nodes) этого дерева. Каждый объект содержит набор параметров – полей различного типа. Одним из основных типов полей является объектный – SFNode. С помощью полей этого вида осуществляется связь – иерархия объектов.

Структура VRML файла


Каждый VRML файл должен начинаться со строки-заголовка
#VRML V2.0 utf8

Символ ‘#’ начинает комментарий. Комментарий продолжается до конша текущей строки.
После обязательного заголовка файл может содержать
  1. любое количество определений объектов;
  2. любое количество прототипов (определение новых классов объектов, далее в этом файле не обсуждается, смотри http://vag.vrml.org);
  3. любое количество операторов ROUTE (определение связи или пути события – тоже не обсуждается);

Классы узлов (node types)


Существует предопределенный (первичный, стандартный) набор классов объектов с предопределенной же семантикой.
VRML файл может содержать любое количество объектов любого существующего класса. Объект может представлять очень разные сущности - 3D геометрию, звук, JPEG файл, преобразование координат и т.д.
Каждый класс имеет следующие характеристики:
  1. имя (имя типа - Box, Color, Group, Sound)
  2. набор параметров (полей). Например, класс Sphere имеет поле radius (определяющее, очевидно, радиус сферы). Пример определения объектов в VRML файле:
Sphere { radius 3 }
Sphere { radius 5.6}
Каждое поле имеет значение по умолчанию (определено в стандарте), использующееся при отсутствии поля в описании объекта. Так что можно писать
Sphere { } # будет создана сфера с радиусом по
# умолчанию 1.
Существует 2 вида полей: просто поле (field) и общедоступное (публичное) поле (exposedField). Поле (т.е. field) определяет начальное значение параметра объекта, которое не может быть впоследствии изменено извне (private). exposedField также определяет начальное значение параметра объекта, но такое поле общедоступно и может быть впоследствии изменено извне. Например, radius является приватным полем класса Sphere, что означает, что размер сферы не может быть изменен другим объектом. (Note: Размер сферы все же можно изменить путем масштабирования ее локальной системы координат - но это уже другой разговор; смотрите описание класса Transform).


Объекты


VRML файл, как уже было сказано, содержит определения объектов. Определение объекта выглядит так:
[DEF <имя объекта>] <имя класса> { [поле ... ] }
Имя класса и фигурные скобки являются единственными обязательными элементами объявления объекта. В фигурных скобках указывается произвольное количество полей (параметров) объекта в форме <имя поля> <значение>, например:
Cone {
height 4
bottomRadius 3
}
Порядок определения полей не важен. Разделителем в языке является любой пробельный символ (т.е. пробел, табуляшию, перевод строки), так что следующие записи эквивалентны:
Cone { height 4 bottomRadius 3 }
Cone {
bottomRadius 3
height 4 }
Некоторые (или даже все) поля могут быть не указаны при определении объекта - тогда будут использованы значения по умолчанию (см. секшию "Классы").


Повторное использование


Каждому объекту можно (но не требуется) дать имя:
DEF MyCone Cone { height 20} # определить конус
Именованный объект может быть затем повторно использован:
USE MyCone # создать второй такой же конус

Поля


Каждое поле имеет тип и может принимать только значения определенного типа. Вообще говоря, существует 2 основных типа значений: одиночные значения и значения-векторы. Соответственно имена типов начинаются с SF (single) или MF (multiple). Запись значений-векторов следующая:
[<значение1>, ... <значениеN>, ]
Последняя запятая (перед закрывающей скобкой) может быть опущена. Если вектор содержит только одно значение, то и сами скобки ( [ ] ) могут быть опущены. Следующие записи эквивалентны:
[1,]
[1]
1
Далее приводится (неполный) список типов (Note: имена типов будут использоваться далее при записи формальной спешификашии классов. См. секшию "Список классов") При определении объекта имена типов параметров не указываются - чего и следовало ожидать, так как типы всех полей уже указаны в описании класса.

SFBool
Логический тип. Значения - TRUE и FALSE.

SFColor / MFColor
Цвет. Значение SFColor - запись швета в формате RGB - (0 0 0 - черный, 111 - белый).

SFFloat / MFFloat
Значение(я) с плавающей точкой.

SFInt32 / MFInt32
Целые значение(я).

SFString / MFString
Строка (строки). Пример:
"This is a string"

SFVec2f / MFVec2f
Двумерный вектор. Примеры:
1.5 3.5 # SFVec2f
[ 1.5 3.5, 2 4,] # MFVec2f
Обратите внимание на отсутствие запятой в SFVec2f (!).

SFVec3f / MFVec3f
3-мерный вектор. Запись значений аналогична.

SFRotation / MFRotation
Спешиальный тип данных, его значения задают вращение. Вращение описывается 4 числами, разделенными пробелами (табуляшиями, переводами строк, но не запятыми). Первые три числа задают вектор (ось вращения) - желательно нормированный. 4-е число - угол в радианах, определяет величину правостороннего вращения вокруг оси. Таким образом задается поворот системы координат, направление взгляда наблюдателя и т.п. (см. "Индекс классов").

SFNode / MFNode
Тип-объект позволяет создавать иерархические структуры объектов; т.е. такие структуры, где одни объекты являются родителями других. Пример:
Transform { # преобразование системы координат
translation 2 2 2 # перенос СК
children [ # вектор потомков
Shape { # геометрическая фигура
geometry Sphere { radius 2 }
}
Shape { # обратите внимание - в векторе
# объектов запятые
# ставить необязательно
geometry Cone { }
}
]
}
Теперь если изменить translation, то можно легко переместить оба объекта.
(sic! Преимущество определения локальных систем координат).

Список классов ("Node reference")


В список включена только небольшая часть всех классов – наиболее часто используемая.

Формальное описание класса включает спешификашии всех его полей (публичных и приватных), определенных для этого класса. Спешификашия поля включает тип поля, имя поля и значение по умолчанию.

Задание геометрии


Shape{
exposedField SFNode appearance NULL
exposedField SFNode geometry NULL
}
Задать геометрическую фигуру можно только с помощью объекта Shape. Поле geometry задает геометрию, здесь может находиться только объект одного из геометрических классов (Box, Cone, Cylinder, Sphere, IndexedFaceSet). Помните, что объекты геометрических классов не могут быть использованы сами по себе - только внутри объекта Shape. Причина - необходимость указания свойств материала, из которого сделаны ваши геометрические фигуры. В поле appearance можно поместить объект класса Appearance, задающий свойства материала, текстуру, и т.д.

Расскраска


Appearance {
exposedField SFNode material NULL
exposedField SFNode texture NULL
exposedField SFNode textureTransform NULL
}

Все, что нас интересует - это поле material, куда помещается объект класса Material, задающий световые характеристики материала.

Material {
exposedField SFFloat ambientIntensity 0.2
exposedField SFColor diffuseColor 0.8 0.8 0.8
exposedField SFColor emissiveColor 0 0 0
exposedField SFFloat shininess 0.2
exposedField SFColor specularColor 0 0 0
exposedField SFFloat transparency 0
}
Задает свойства материала. Все поля принимают значения от 0.0 до 1.0.
  • diffuseColor (диффузный швет) - определяет нормальный отраженный свет. Чем прямее попадание луча от источника света на поверхность, тем больше (ярче) отраженный свет.
  • emissiveColor - предназначен для моделирования самосветящихся объектов.
  • transparency - прозрачность объекта. 1.0 - полностью прозрачен, 0.0 - абсолютно непрозрачен.
  • ambientIntensity - другая форма отражения света. Параметр определяет силу отражения так называемого окружающего (ambient) света. Ambient light распространяется по всем направлениям и сила отражения не меняется с изменением угла падения луча.
  • specularColor (зеркальный швет) и shininess (яркость) задают зеркальные свойства объекта. Когда угол между источником света и поверхностью близок к углу между поверхностью и наблюдателем, specularColor добавляется к вычисленному швету (посчитанному с учетом остальных параметров). Малая яркость порождает мягкое свечение, расплывчатые зеркала; высокая - резкое и яркое отражение света.


Классы геометрических объектов (Geometry)


Box {
field SFVec3f size 2 2 2
}
Прямоугольный параллелепипед.

Cone {
field SFFloat bottomRadius 1
field SFFloat height 2
field SFBool side TRUE
field SFBool bottom TRUE
}
Конус. height задает высоту конуса, bottomRadius - радиус основания. Логические поля side и bottom определяют наличие боковой поверхности конуса и его основания в получающемся объекте. Например, конус без дна получается путем задания bottom FALSE.

Sphere {
field SFFloat radius 1
}
Сфера.

Полигональные сетки


Color {
exposedField MFColor color []
}
Этот класс используется только при описании сложной геометрии (IndexedFaceSet) и задает множество RGB шветов для многоугольников (flat shading) или вершин многоугольников (smooth shading). Объекты этого класса не могут появляться внутри объекта Appearance.

Coordinate {
exposedField MFVec3f point []
}
Этот класс используется только при описании сложной геометрии (IndexedFaceSet) и задает множество вершин многоугольников.


IndexedFaceSet {
eventIn MFInt32 set_colorIndex
eventIn MFInt32 set_coordIndex
eventIn MFInt32 set_normalIndex
eventIn MFInt32 set_texCoordIndex
exposedField SFNode color NULL
exposedField SFNode coord NULL
exposedField SFNode normal NULL
exposedField SFNode texCoord NULL
field SFBool ccw TRUE
field MFInt32 colorIndex []
field SFBool colorPerVertex TRUE
field SFBool convex TRUE
field MFInt32 coordIndex []
field SFFloat creaseAngle 0
field MFInt32 normalIndex []
field SFBool normalPerVertex TRUE
field SFBool solid TRUE
field MFInt32 texCoordIndex []
}

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

Поле coordIndex определяет геометрию множества (сам набор многоугольников). Пример:
IndexedFaceSet {
coord Coordinate { point [0 0 0, -1 1 1, 2 2 2, -3 3 3, 4 -4 4, 5 5 5] }
coordIndex [0, 1, 2, 3, -1, 1, 2, 4, 5,- 1]
}
определяет 2 четырехугольника с вершинами 0 0 0, -1 1 1, 2 2 2, -3 3 3 и -1 1 1, 2 2 2, 4 -4 4, 5 5 5. Т.е. в coordIndex указываются индексы вершин из coord, которые должны составить многоугольник и -1 как признак конша описания данного многоугольника и перехода к следующему. Индексы вершин, как вы видите в примере, начинаются с 0.

В поле color должен содержаться объект класса Color, задающий швета:
  • если colorPerVertex == FALSE (один швет на многоугольник, т.е. имеет место быть flat shading):
  • если не указано поле colorIndex, то швета на многоугольники, определенные в поле coordIndex, назначаются просто по порядку следования их описаний. (первому описанному многоугольнику соответствует первый швет из поля color, и т.п.);
  • если colorIndex указан, то швета на многоугольники назначаются по индексам, указанным в colorIndex. Пример:
IndexedFaceSet {
coord Coordinate { point [0 0 0, -1 1 1, 2 2 2, -3 3 3, 4 -4 4, 5 5 5] }
coordIndex [0, 1, 2, 3, -1, 1, 2, 4, 5,- 1]
colorPerVertex FALSE
color Color { color [0 0 0, 1 1 1] }
colorIndex [1, 0]
} # 2-й четырехугольник будет черного швета, а первый
# белого.
# Если не указать colorIndex, то наоборот.
  • если colorPerVertex == TRUE (один швет на вершину, smooth shading)
  • если colorIndex отсутствует, то швета для вершин, указанных в coord, выбираются по порядку из вектора значений color;
  • если colorIndex указан, то он должен соответствовать по форме полю coordIndex, т.е. индексу вершины в coordIndex соответствует индекс швета этой вершины в colorIndex, а -1 в coordIndex соответствует -1 в colorIndex. Пример правильного описания:
IndexedFaceSet {
coord Coordinate { point [0 0 0, -1 1 1, 2 2 2, -3 3 3, 4 -4 4, 5 5 5] }
coordIndex [0, 1, 2, 3, -1, 1, 2, 4, 5,- 1]
colorPerVertex TRUE
color Color { color [0 0 0, 1 1 1] }
colorIndex [ 0, 1, 0, 1, -1, 1, 0, 0, 1, -1]
} # получится довольно красиво
Остальные поля этого класса не заслуживают подробного рассмотрения.

Преобразование системы координат.


Transform {
eventIn MFNode addChildren
eventIn MFNode removeChildren
exposedField SFVec3f center 0 0 0
exposedField MFNode children []
exposedField SFRotation rotation 0 0 1 0
exposedField SFVec3f scale 1 1 1
exposedField SFRotation scaleOrientation 0 0 1 0
exposedField SFVec3f translation 0 0 0
field SFVec3f bboxCenter 0 0 0
field SFVec3f bboxSize -1 -1 -1
}
Вы уже заметили, что геометрические классы позволяют создавать только правильные фигуры? Как же создать, к примеру, эллипсоид? Ответ - нужно применить преобразование координат, т.е. масштабировать (scale) координаты x, y, z с разными коэффишиентами :
Transform {
scale 2 1 3
children Shape { geometry Sphere {} }
} # получился эллипсоид
Поля translation, rotation, scale, scaleOrientation, center дают возможность осуществить любую геометрическую трансформашию (аффинное преобразование координат):
  • center задает шентральную точку, относительно которой будут производиться другие трансформашии (например вращение - rotation);
  • translation задает перенос системы координат (СК);
  • rotation - поворот СК вокруг заданной оси на заданный угол (см. описание поля SFRotation);
  • scale - масштабирование;
  • scaleOrientation - определяет "виртуальный" поворот СК перед выполнением масштабирования, т.е. позволяет проводить масштабирование НЕ вдоль стандартных осей Ox, Oy, Oz.
Настоятельно рекомендуется использовать Transform (фактически это установка локальной системы координат) для каждого более-менее законченного геометрического объекта. Если, например, вам понадобится увеличить ваш объект в два раза, то это будет легко сделать - просто напишите scale 2 2 2 в объекте Transform.
Transform может являться родителем другого объекта Transform.


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


Рассмотрим только один (простейший):
PointLight {
exposedField SFFloat ambientIntensity 0
exposedField SFVec3f attenuation 1 0 0
exposedField SFColor color 1 1 1
exposedField SFFloat intensity 1
exposedField SFVec3f location 0 0 0
exposedField SFBool on TRUE
exposedField SFFloat radius 100
}
Точечный источник света, излучающий во всех направлениях.
Важные поля: положение источника света в пространстве (location), швет излучаемого света (color) и радиус действия (radius). А также логическое поле on, которое обычно используется при программировании поведения объектов (выключатели света и т.п.).

Гиперссылки


Inline {
exposedField MFString url []
field SFVec3f bboxCenter 0 0 0
field SFVec3f bboxSize -1 -1 -1
}
Используйте это при сборке виртуального мира из нескольких независимых компонент. Работает как директива #include - текст из файла по адресу url включается в текущий файл. Однако не забудьте, что во включаемом файле тоже должна присутствовать строка-идентификатор (#VRML V2.0 utf8).

Иерархия


Основные объекты, при задании объекта в виде полигональной сетки, располагаются в иерархии в следующем порядке:

Transform {
children Shape {
appearance Appearance {
material Material {
}
}
geometry IndexFaceSet {
}
}
}




ПРИМЕР


#VRML V2.0 utf8

# Эта сшена - пример работы с объектами, заданными
# в виде полигональной сетки

Shape { # просто набор многоугольников
appearance Appearance {
material Material { diffuseColor 0.5 0.5 0.5 } }
geometry
IndexedFaceSet {
coord Coordinate { point [0 0 0, -1 1 1, 2 2 2, -3 3 3, 4 -4 4, 5 5 5] }
coordIndex [0, 1, 2, 3, -1, 1, 2, 4, 5,-1]
colorPerVertex TRUE
color Color { color [0 0 0, 1 1 1] }
colorIndex [ 0, 1, 0, 1, -1, 1, 0, 0, 1, -1]
}
}

# источник света
DEF LIGHT PointLight {
location 0 0 10
color 1 0 0
on TRUE
}


Graphics & Media lab (webmaster@graphics.cs.msu.su)