Урок 3
Иерархия объектов
Уровень: начинающий
Версия Xtreme3D: 3.0.x
Автор урока: Gecko
Понятие иерархии нам уже встречалось, но до сих мы не рассматривали ее на практике. Многие, кто не знаком с данным подходом организации объектов, и не подозревают, о какой громадной экономии сил и времени здесь идет речь. Иерархия позволяет безо всякого труда сделать то, что слишком тяжело или вообще невозможно без ее использования. Дело касается специфики перемещений объектов в некоторых особых случаях.
Представьте себе, к примеру, такую ситуацию: необходимо смоделировать простейшую звездную систему - солнце и вращающуюся вокруг нее планету. Вокруг планеты, в свою очередь, вращается спутник. Для простоты будем пока мыслить в двумерном пространстве. Как можно поступить?
Пусть Sun - солнце, Planet - планета, Moon - спутник. У каждого объекта есть две координаты - X и Y, а также угол вращения вокруг своей оси - A. Тогда (в псевдокоде)
Sun.X = 0
Sun.Y = 0
Planet.X = Sun.X + cos(Sun.A) * 10
Planet.Y = Sun.Y + sin(Sun.A) * 10
Принимая во внимание, что расстояние между солнцем и планетой равно 10 условным единицам. При повороте солнца вокруг своей оси, планета будет вращаться вокруг нее, перемещаясь на координаты, вычисленные из угла поворота солнца и искомого расстояния. Нетрудно теперь аналогично рассчитать и координаты спутника:
Moon.X = Planet.X + cos(Planet.A) * 2
Moon.Y = Planet.Y + sin(Planet.A) * 2
Но вручную это делать не всегда удобно. Особенно, если в системе не три объекта, а, скажем, все десять. Или расположение объектов периодически меняется (например, спутник отрывается от одной планеты и переходит к другой). Разумнее будет автоматизировать процесс, введя для каждого объекта свойство родителя (Parent):
Planet.Parent = Sun
Moon.Parent = Planet
И обновлять координаты объектов одинаковой для всех формулой:
Object.X = Object.Parent.X + cos(Object.Parent.A) * 2
Object.Y = Object.Parent.Y + sin(Object.Parent.A) * 2
Так и реализуется простейшая иерархия.
С двумерной графикой все относительно просто. Но как быть с трехмерной? В трехмерной графике вдобавок к синусам и косинусам используются векторы и матрицы. Операции с ними довольно ресурсоемки и чрезвычайно сложны для осмысления новичком. К тому же, слишком часто осуществлять такие операции на уровне GML нерационально: для хранения массивов под матрицы потребуется больше памяти, а математические операции с ними снизят FPS. Но не все так ужасно. Xtreme3D берет на себя все ресурсоемкие вычисления, исполняя их на уровне машинного кода, поэтому ее иерархия будет работать гораздо быстрее и точнее, чем написанная вручную на GML.
При использовании встроенной иерархии Xtreme3D вся работа сводится к указанию родителей для объектов. Весь фокус в том, что потомок наследует координатную систему родителя. Например, координаты родителя (X, Y, Z) становятся координатами центра, относительно которого ведется отсчет собственных координат его потомка (X+x, Y+y, Z+z). Потомок, в свою очередь, передает собственные координаты своим потомкам, и так далее. Собственные координаты объекта называются локальными.
Координатная система может быть трансформирована перемещением, поворотом или масштабированием. Поворот локальной координатной системы родителя вызывает изменение направления осей в унаследованной координатной системе потомка, что автоматически приводит к его вращению в пространстве. Если в момент вращения потомок был на некотором расстоянии от центра унаследованной им системы координат, это будет выглядеть, как вращение потомка вокруг своего родителя. Совсем как в нашем примере!
Для создания системы с солнцем и планетами в нашем случае достаточно написать что-то вроде этого:
sun=SphereCreate(4, 24, 24, global.scene);
ObjectSetPosition(sun, 0, 0, 0);
planet=SphereCreate(1, 24, 24, sun);
ObjectSetPosition(planet, 0, 0, 10);
moon=SphereCreate(0.5, 24, 24, planet);
ObjectSetPosition(moon, 0, 0, 2);
Функция SphereCreate создает сферу. Необходимо указать ее радиус, а также количество меридиан и параллелей. У нашего солнца радиус равен 4, у планеты — 1, у спутника — 0.5. Меридианы и параллели (slices, stacks) делят сферу на квадраты, количество которых задает качество внешнего вида сферы. Обычно достаточно указать 24 меридиана и 24 параллели.
Теперь можно в событии Step поворачивать солнце и планету:
ObjectTurn(sun, 2);
ObjectTurn(planet ,6);
...И наблюдать за проявлением одного из самых важных свойств объектной иерархии. Грамотное использование этих свойств является основной задачей работы с Xtreme3D. Такого рода проявления можно наблюдать не только в космосе, но и вообще на каждом шагу, поэтому так важно иметь эффективное средство их моделирования.