Шаг 17 - Экструзии или вытягивание контуров, узел Extrusion

Для начала давайте разберемся с тем, что же такое вообще экструзия. Экструзия представляет собой тело полученной проведением контура вдоль какого-то пути. Контур может быть замкнутым, для получения объемного тела, а может быть незамкнутым, в таком случае получится какой-то рельеф. На рисунке ниже представлена "формула" экструзии:

17_1.gif (1524 b)

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

Описывается данный узел так:

Extrusion { 
	eventIn MFVec2f    set_crossSection
	eventIn MFRotation set_orientation
	eventIn MFVec2f    set_scale
	eventIn MFVec3f    set_spine
	field   SFBool     beginCap         TRUE
	field   SFBool     ccw              TRUE
	field   SFBool     convex           TRUE
	field   SFFloat    creaseAngle      0
	field   MFVec2f    crossSection     [ 1 1, 1 -1, -1 -1, -1 1, 1  1 ]
	field   SFBool     endCap           TRUE
	field   MFRotation orientation      0 0 1 0
	field   MFVec2f    scale            1 1
	field   SFBool     solid            TRUE
	field   MFVec3f    spine            [ 0 0 0, 0 1 0 ]
}

Набор полей богатый, так что давайте обо всем по порядку. Самое главное у экструзии это контур и путь протягивания.

Контур задается в поле crossSection. Он представляет собой набор двухмерных точек контура записанных по часовой стрелке, это связано с правильными направлениями нормалей граней полученных протягиванием, поэтому такое следование описания вершин важно. Чтобы наш процесс обучения не был простыми словами давайте создадим какой-нибудь сложный объект вращения. Для этого нам понадобится контур в виде окружности. Чтобы он был более гладким и имел меньше изломов поделим его на 16 частей, если Вам хочется, то для практики попробуйте поделить его на 32 части. Ох, сколько же вам придется считать синусов и косинусов %).

17_2.gif (1064 b)

Данная фигура будет записываться так:

crossSection [
	1 0, .92 -.38, .70 -.70, .38 -.92,
	0 -1, -.38 -.92 ,-.70 -.70, -.92 -.38, 
	-1 0, -.92 .38,-.70 .70, -.38 .92,
	0 1, .38 .92, .70 .70, .92 .38, 1 0
]

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

Путь вытягивания задается в поле spine. Это поле представляет собой массив из трехмерных вершин, вдоль которого будет протянута фигура заданная в crossSection.

Если вы думали, что свойства для протягивания фигуры на этом кончились, то вы ошибаетесь. Разработчики ввели еще один очень полезный параметр scale. Он представляет собой массив из парных значений увеличения для протягиваемой фигуры. Первое значение устанавливает коэффициент увеличения по горизональной оси, а второй по вертикальной. Таким образом можно увеличивать или уменьшать протягиваемую фигуру во всех направлениях, что придает очень большие возможности.

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

17_3.gif (4198 b)

Данный образ создает некоторую дрожь в коленках... Однако это далеко не самое сложное, что можно сотворить. Давайте разберемся как задавать поля spine и scale. Первым делом скажу то, что в действительности путь протягивания у нас выглядит как вертикальная прямая, поэтому в задании пути будут играть роль только вертикальные координаты точек (Y). Вторая координата каждой точки (X) будет получаться посредством поля scale, так как каждая из этих точек представляет собой сечение чашки, а в сечении она круглая. Вобщем давайте запишем все это не теряя времени:

spine [
	0 0 0, 0 2 0, 0 3 0, 0 6 0, 0 9 0,
	0 14 0, 0 19 0, 0 25 0, 0 30 0, 0 30.01 0,
	0 25 0, 0 21 0, 0 16 0,0 13 0, 0 9 0,
	0 6 0, 0 3 0
]
scale [
	8 8, 8 8, 11 11, 14 14, 16 16, 19 19,
	20 20, 20 20, 20 20, 19 19, 19 19,
	19 19, 18 18, 17 17, 15 15, 12 12,
	7 7
]

Как я и говорил, все координаты X и Z у каждой точки пути равны 0. Коэффициенты увеличения для каждой точки также равны, потому что нам нужно получать круглое сечение, а не овальное.

После создания всех путей и фигур можно описывать узел Extrusion полностью:

WorldInfo { 
  info  ["Extrusion Example"]
  title "Step 17 Example"
}

Background{
	skyColor 1 1 1
}

Group {
	children[
Shape {
	appearance Appearance {
# назначаем белый материал, разберемся чуть позже
	material Material {
	diffuseColor 1 1 1
	}
	}

geometry Extrusion {
	creaseAngle 1
	solid FALSE
	crossSection [
# сюда надо вписать значение координат точек фигуры
		# ...
		# ...
		# ...
	]
	spine [
# сюда надо вписать значение координат точек пути
		# ...
		# ...
		# ...
	]
	scale [
# сюда надо вписать значения коэффициентов увеличения
		# ...
		# ...
		# ...
	]
}
}
]
}

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

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

17_4.gif (4503 b)

Чашку А вы получите в любом случае. А вот чтобы получить чашку Б надо знать технологию вытягивания. Для того, чтобы понять загвоздку надо посмотреть на точки 9 и 10 нашего пути.

17_5.gif (2645 b)

Первое, что пришлось исправить, это поле solid. На рисунке А поле solid равно TRUE и нормали к граням (показаны синим) направлены наружу чашки, поэтому внутреннюю стенку чашки (под точкой 10) мы никогда не увидим. Для того, чтобы ее было видно надо поменять направление нормали. Делается это только с помощью установки поля solid в FALSE, таким образом появляется вторая нормаль. Следующий момент в том, что поле solid не влияет на поверхность закрывающую внутренность чашки (она показана жирной красной линией). Это связано с тем, что направление вытягивания (розовые стрелки) до точки 9 направлено вверх и эта точка порождает поверхность закрывающую углубление. Если точку 10 немного поднять вверх, то противиположное направление вытягивания "вырежет" отверстие в этой плоскости, а в случае Б она не может этого сделать, так как плоскость находится непосредственно на развороте. Из-за этого вы можете наблюдать в примере выделенную жирным шрифтом точку 10 с координатами 0 30.01 0. Всего лишь одна сотая доля может решить проблему, и при этом практически не повлияет на вытягивание.

Следущее, что нужно нам до полноценной чашки это ручка:

17_6.gif (2246 b)

Создается она с помощью второго узла Extrusion, с новым значение поля spine:

spine [
	0 0 0, 0 2 0, 1 4 0, 3 5 0, 8 8 0,
	13 12 0, 15 14 0, 16 17 0, 15.5 20 0,
	14 22 0, 12 23.5 0, 9 24 0, 6 23 0,
	4 21 0, 3 18 0, 3 16 0
]

Поле crossSection надо скопировать из предыдущих примеров, а scale вообще не нужен.

После использования узла Transform (мы с ним познакомимся позже) и правильной установки двух экструзий относительно друг друга можно получить виртуальную чашку (без чая :).

17_7.gif (6726 b)

Поля beginCap и endCap управляют отображением начальной и конечной плоскостей в экструзии. Например, если протянуть окружность вдоль прямой, то можно получить цилиндр. Тогда эти поля будут управлять отображением оснований цилиндра. Если их значения равны TRUE, то закрывающие повержности отображаются, иначе (FALSE) нет. (по аналогии см. "Шаг 13 - Цилиндры и сферы, узлы Cylinder и Sphere").

Поле creaseAngle задает коэффициент сглаживания экструзии. Поля ccw и convex впринципе можно не трогать. В большинстве нормальных тел они роли не играют.

Осталось одно очень интересное поле orientation, которое позволяет изменять направление и поворот протягивающегося контура в каждой точке пути во время протягивания. Например:

#VRML V2.0 utf8
Background{ skyColor 1 1 1 }
Group { children[ Shape {
	appearance Appearance {
		material Material {
		diffuseColor 1 1 1
		}
	}
	geometry Extrusion {
		creaseAngle 1
		spine [ 0 0 0, 0 0 3, 0 0 6, 0 0 9, 0 0 12 ]
		orientation [ 0 0 1 0, 0 1 0 1.0, 0 1 0 2.0,
			 0 1 0 3.0, 0 1 0 4.0]
	}
}]}

Получится следующее интересное тело:

17_8.gif (2415 b)

Это поле предоставляет еще большие возможности по созданию экструзий, но значения векторов вручную иногда сложно рассчитать, поэтому требуются специальные вычисления. Ну, вобщем-то почти все об узле Extrusion я рассказал. Конечно же Вы встретите еще очень много всяких тонкостей при работе с этим узлом, потому что он сложный, но очень действенный.

Примеры из шага вы можете взять из архивного файла.


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Кузин Андрей - 10.09.2001