GLScene
GLScene — это бесплатный для коммерческого и некоммерческого использования OpenGL-ориентированный графический движок для Дельфи с открытым исходным кодом. С его помощью программирование трёхмерной графики становится более простым и быстрым.
Разработка данного движка началась в 1999 году Майком Лишке (Mike Lischke) [1], а с версии 0,5 была выложена с открытым исходным кодом и передана на попечение администратору проекта Эрику Гранжу (Eric Grange). В настоящий момент версия движка имеет номер 1.0.0.x, он избавился от массы ошибок, пополнился многими фичами и стал быстрее благодаря различным оптимизациям.
GLScene позволяет программистам создавать 3D-объекты OpenGL в дизайн-тайме с использованием интерфейса показаного на картинке. Большое количество объектов и дополнительных визуальных компонентов VCL, помогает программистам создавать мощные 3D-приложения для Дельфи.
Поддерживаемые для загрузки форматы файлов: 3ds, obj, vrml, smd, md2, md3, nmf, oct, lwo, b3d, gl2, gls, ms3d, Nurbs, lod, и некоторые другие.
Поддерживаемые для сохранения форматы файлов obj и smd.
Поддерживаемая физика: ODE, Newton Dynamics. Также есть небольшой собственный движок расчёта коллизий DCE.
Некоторые объекты GLScene
правитьTGLCamera — объект камера. Это точка, из которой смотрят на трёхмерный мир. Камере можно задавать положение и целевой объект на который она смотрит. Варьируя её параметр FocalLength, можно изменять фокусное расстояние камеры. Параметры DepthOfView и NearPlane отсекают дальние и ближние объекты. Отсечение дальних объектов может сильно повысить скорость работы.
Таким образом поле зрения камеры — это усечённый конус, ограниченный с обоих строн параметрами DepthOfView и NearPlane, и чей угол задан через параметр FocalLength.
TGLSceneViewer — объект просмотрщик трёхмерного мира. Его нужно кинуть на форму, и установить ему свойство Camera, то есть указав камеру с которой надо смотреть на мир. После этого он будет показывать то, что видит указанная камера.
TGLLightSource — источник освещения, который освещает всю трёхмерную сцену. Их в OpenGL может быть максимум восемь. Поэтому в GLScene их тоже восемь. Светит данный источник освещения или нет, определяется параметром Shining (светимость).
За цвет освещения отвечают три параметра Ambient, Diffuse и Specular. Ambient — это общее освещение сцены. Не зависящее от положения источника света. Как освещённость в тени в солнечный день. Diffuse — направленный свет, зависит от положения источника. То есть, если поверхность отвёрнута от него, то он её не освещает. Specular — зеркальный свет. Зависит ещё и от нормали поверхности. С его помощью можно делать яркие блики, как например яркая точка на железном блестящем шарике он лампочки.
За ослабление яркости света в зависимости от удаления от источника отвечают три параметра: ConstAttenuation, LinearAttenuation, QuadraticAttenuation. Первый — это постоянное ослабление (в общем то не зависит от расстояния, а просто можно считать, что управляет яркостью источника света), второй — линейное ослабление, третий — квадратичное.
Источник света может быть прожектором. Для этого его параметр SpotDirection нужно выставить в lsSpot и указать параметры прожектора. SpotDirection — указывает направление света прожектора. SpotCutOff — угол конуса прожектора. Если он 180 градусов, то считается, что это не прожектор, а обычный источник освещения. Если меньше 90, то прожектор. SpotExponent — коэффициент изменения яркости от центральной точки пятна прожектора, до его краёв.
Прожекторы часто используются, в качестве фар автомобилей или фонариков в руках героя в играх.
TGLDummyCube — объект не содержащий графики, но имеет позицию (position), ротацию в виде векторов направления (direction) и верха (up), и масштаб (scale). При помощи этих свойств объекту можно придавать различные положения в пространстве. А используя несколько TGLDummyCube’ов прикреплённых друг к другу можно создавать сложные пространственные конструкции, как например скелет, в котором кости прикреплены друг к другу.
Кроме того TGLDummyCube удобен для использования в качестве целевого объекта камеры TGLCamera.
Включение свойства объекта VisibleAtRunTime позволяет отобразить его проволочный каркас в трёхмерной сцене. Это часто облегчает отладку программы.
TGLMaterialLibrary — библиотека материалов. Находящиеся в ней материалы переносятся в видеопамять видеокарты. Все материалы могут использоваться разными объектами GLScene одновременно. Каждый материал может иметь свою текстуру, или использовать текстуры других материалов, со своими настройками её отображения. Таким образом, например, загрузив текстуру машины зелёного цвета, можно использовать её в другом материале, но изменив её цвет на, скажем, синий.
TGLFreeForm — статичная трёхмерная модель. Используется, чтобы загрузить, например, здания, ландшафты, деревья, и прочие подобные объекты. Чтобы загрузить 3D-модель в GLScene достаточно двух строчек кода:
// Указываем какую библиотеку материалов использовать.
GLFreeForm1.MaterialLibrary := GLMaterialLibrary1;
// Загружаем 3D-модель.
GLFreeForm1.LoadFromFile('mymodel.3ds');
Также надо добавить в uses модуль загрузчика моделей. Для моделей 3ds — это GLFile3DS. Для моделей smd — это GLFileSMD, и т. д. по аналогии. После загрузки модель полностью попадает в видеопамять, и процессорное время на её отображение практически не тратится. При изменении матрицы этого объекта, в видеопамять пересылается только новая матрица.
TGLActor — анимированная трёхмерная модель. Используется, чтобы загрузить модели людей, монстров, других движущихся объектов. Загрузка аналогична загрузке модели в TGLFreeForm. Чтобы запустить анимацию достаточно двух строчек.
// Грузим модель со скелетной анимацией 'mymodel.smd'.
GLActor1.LoadFromFile('mymodel.smd');
// Добавляем анимацию хотьбы из файла 'walk.smd'.
GLActor1.AddDataFromFile('walk.smd');
// Переключаемся на анимацию хотьбы 'walk'.
GLActor1.SwitchToAnimation('walk');
// Запускаем проигрывание анимации в циклическом режиме.
GLActor1.AnimationMode := aamLoop;
В отличии от моделей находящихся в TGLFreeForm, здесь рендеринг частично возложен на центральный процессор. Когда происходит анимирование модели со скелетной анимацией, то для каждого положения каждой кости, в каждый момент времени, происходит перерасчёт положения вершин модели, после чего они пересылаются в видеопамять и отображаются на экране. Этот подоход более медленный, но зато позволяет добиться практически идеальной плавности движений.
TGLSprite — спрайт, прямоугольник, по-умолчанию — квадрат, всегда повёрнутый на камеру.
Может быть повёрнут вокруг перпендикулярной ему оси, свойством Rotation, которое задаётся в градусах. Свойство MirrorV — позволяет перевернуть его текстуру по вертикали, а MirrorU — по горизонтали.
Размеры спрайта можно изменить свойствами Height и Width. Тоже самое можно сделать через параметр Size.
Свойство AlphaChanel задаёт прозрачность спрайта. Работает если свойство материала спрайта Material.FrontProperties.BlendingMode не bmOpaque и не bmModulate. Также освещение в TGLSceneViewer должно быть включено.
TGLPoints — позволяет рисовать на экране точки. Добавлять точки нужно в список Positions. Чтобы точки были цветными, нужно добавлять цвета в список Colors. Если в него добавлен только один цвет, то все точки будут этого цвета. Если количество цветов равно количеству точек, то каждая точка будет своего цвета.
TGLLines — позволяет рисовать линии и сплайны. Линии задаются точками, добавлять которые можно в список Nodes через процедуру NodesAdd. Линии по заданным точкам рисуются в зависимости от способа отображения LineSplineMode. Если это lsmSegments, то каждые две точки означают отдельную линию. Если lsmLines, то линии проводятся от точки к точке. Если какой-то другой режим, то по точкам рисуется сплайн. То есть плавная линия проходящая через все заданные точки. Плавность линии зависит от параметра Division. Чем он больше, тем линия плавнее. Если в опции LinesOption, включен параметр loUseNodeColorForLines, то для каждой точки линии можно будет использовать свой цвет. Цвета задаются в NodeColor.
Также есть возможность выделять разными способами точки по которым строятся линии. Способ задаётся в параметре LineNodesAspect.
- lnaInvisible — выделение отсутствует.
- lnaAxes — выделение осями.
- lnaCube — выделение кубами
- lnaDodecahedron — выделение двенадцатигранниками.
Общие свойства многих 3D-объектов GLScene
правитьВ основном это свойства класса TGLSceneObject, являющегося предком для многих других классов 3D-объектов в GLScene.
Position — позиция объекта. По умолчанию (0, 0, 0)
Direction — вектор направления объекта. По умолчанию (0, 0, 1).
Up — вектор верха объекта. По умолчанию (0, 1, 0).
Scale — вектор масштаба. По умолчанию (1, 1, 1).
PitchAngle — поворот объекта вокруг оси X углами Эйлера. По умолчанию 0.
TurnAngle — поворот объекта вокруг Y углами Эйлера. По умолчанию 0.
RollAngle — поворот объекта вокруг оси Z углами Эйлера. По умолчанию 0.
Visible — видимость объекта в сцене. По умолчанию True.
ShowAxis — показывать ось объекта. Тремя разноцветными, взаимоперпендикулярными линиями. По умолчанию False.
Normals — как показывать нормали.
- nsNone — никак.
- nsSmooth — сглаживать. То есть для общих точек нескольких треугольников, вычисляется одна общая нормаль.
- nsFlat — без сглаживания, острые грани. То есть обычно по принципу один треугольник — одна нормаль.
По умолчанию nsSmooth.
NormalDirection — направления нормалей объекта.
- ndOutside — наружу.
- ndInside — внутрь. Объект как бы вывернут наизнанку.
По умолчанию ndInside.
Примитивы в GLScene
правитьПростые геометрические объекты присутствующие в GLScene.
TGLCube — параллелепипед, по умолчнанию — куб.
Свойство куба CubeParts позволяет скрывать или показывать его стороны.
Свойство куба CubeSize задаёт размер сторон. В принципе можно обходиться и без него задавая размеры сторон в свойстве Size, общем для массы объектов в GLScene.
TGLSphere — сфера (по умолчанию) или сфероид.
Имеет радиус Radius. Если изменять её свойство Size, то можно превратить сферу в сфероид, растянув или сжав её по одной из осей или по двум.
Свойства Slices и Stacks позволяют задавать количество сегментов из которых сфера состоит. Чем больше, тем качественнее, и тем медленее прорисовка.
Свойства Top, Bottom, Start, Stop, позволяют вырезать из сферы сегменты, указывая углы отсечения.
Свойство CapType позволяет изменять отображение срезанных верхушек сферы. Они могут отсутствовать, быть дисками, или конусами сходящимися в центре сферы.
TGLPlane — плоскость, прямоугольник, по умолчанию квадратный.
Ей можно задавать размер в свойствах Width, Height. Но можно вместо этого воспользоваться и свойством Size, общим для массы объектов в GLScene.
TGLDisk — диск состоящий из множества треугольников.
Свойство Slices задаёт количество сегментов диска. Loops — количество элементов сегмента.
Свойства OuterRadius и InnerRadius задают внутренний и внешний радиусы диска.
Свойства StartAngle и FSweepAngle задают начальные и конечные его углы.
TGLCylinder — цилиндр.
Его свойства Slices и Stacks задают из скольких сегментов он должен состоять.
Свойство Parts определяет какие его части нужно отображать (верх, низ, середину).
Свойства BottomRadius и TopRadius задают его верхний и нижний радиусы.
TGLFrustrum — пирамида, по умолчанию — усечённая (без верхушки).
Свойство ApexHeight задаёт высоту пирамиды. BaseDepth и BaseWidth размеры её основанияи. Свойство Height определяет на какой высоте пирамиде надо обрезать верхушку. Он должен быть меньше или равен ApexHeight.
Свойство Parts определяет какие стороны пирамиды показывать, а какие нет.
TGLCone — конус.
BottomRadius — это его нижний радиус. Slices и Stacks определяют число сегментов из которых должна состоять конусообразная часть. Loops — сколько сегментов должно быть в донышке. Параметр Parts позволяет показывать или скрывать отдельные части конуса (конусообразную часть, донышко)
TGLDodecahedron — двенадцатигранник. Состоит из 12 пятиугольников.
TGLIcosahedron — Икосаэдр (двадцатигранник). Состоит из двадцати треугольников.
TGLArrowLine — стрелка. Направлена вдоль вектора Direction.
Свойство Parts позволяет показывать или скрывать стрелку с одного конца, стрелку с другого конца и середину стрелки.
Свойства TopArrowHeadHeight и TopArrowHeadRadius позволяют задавать длину и радиус конуса стрелки направленного по направлению Direction. Свойства BottomArrowHeadHeight и BottomArrowHeadRadius позволяют задавать длину и радиус конуса стрелки направленного против направления Direction.
Стрелка удобна для указания направления движения или положения какого-либо объекта.
TGLTorus — тор (бублик).
Свойства MajorRadius и MinorRadius задают его большой и малый радиусы. Малый — это половина толщины тора, большой — это так сказать, половина размера дырки от бублика плюс половина его толщины.
Свойства Sides (стороны) и Rings (кольца), определяют из скольких сегментов тор должен состоять.
Векторы в GLScene
правитьВекторы используемые в GLScene описаны в файлах VectorGeometry.pas [2] и VectorTypes.pas[3].
Наиболее частоиспользуемые векторы — это TVector и TAffineVector. Это статичные массивы из трёх или четырёх чисел типа Single. Первые три числа — это координаты по осям X, Y, Z. Четвёрное число, обычно обозначается как W и по-умолчанию равно нулю. Реже единице. Смысл его в том, чтобы задавать в нём длину вектора, если вектор в X, Y, Z нормализованный (длиной равной единице). Но чаще всего это число никак не используется. Описаны векторы так:
type
// TAffineVector.
TVector3f = array [0..2] of single;
TAffineVector = TVector3f;
// TVector.
TVector4f = array[0..3] of single;
THomogeneousFltVector = TVector4f;
TVector = THomogeneousFltVector;
Для установки векторов обычно используют функции AffineVectorMake и VectorMake. С помощью этих же функций можно преобразовывать TVector в TAffineVector и наоборот.
var
v1, v2 : TVector;
af1, af2 : TAffineVector;
begin
af1 := AffineVectorMake(1, 2, 3); // af1 = (1, 2, 3)
v1 := VectorMake(4, 5, 6, 7); // v1 = (4, 5, 6, 7)
af2 := AffineVectorMake(v1); // af2 = (4, 5, 6)
v2 := VectorMake(af1); // v2 = (1, 2, 3, 0)
Также для установки векторов можно использовать процедуры SetVector и MakeVector.
var
v1 : TVector;
af1 : TAffineVector;
begin
SetVector(af1, 1, 2, 3); // af1 = (1, 2, 3)
MakeVector(v1, 4, 5, 6); // v1 = (4, 5, 6, 0)
GLDummyCube1.Position.SetPoint(af1);
GLDummyCube1.Direction.SetVector(v1);
Сложение и вычитание векторов осуществляется функциями VectorAdd, VectorSubtract и процедурами AddVector и SubtractVector.
var
v1, v2 : TVector;
af1, af2 : TAffineVector;
begin
af1 := AffineVectorMake(1, 2, 3); // af1 = (1, 2, 3)
af2 := AffineVectorMake(4, 5, 6); // af2 = (4, 5, 6)
af3 := VectorAdd(af1, af2); // af3 = (5, 7, 9)
SubtractVector(af3, af2); // af3 = (1, 2, 3)
Длину вектора и квадрат длины вектора можно узнать функциями VectorLength и VectorNorm. Знание квадрата длины вектора часто помогает ускорить вычисления, избавившись от команды извлечения корня, при сравнении длины вектора с каким-либо значением. То есть вместо
if VectorLength(af1) > 3 then
пишут
if VectorNorm(af1) > 3*3 then
что эквивалентно.
Другие векторные функции:
VectorScale и ScaleVector — изменяют длину вектора (произведение координат вектора на заданное число). Параметр — величина во сколько раз вектор надо увеличить.
DivideVector — деление координат вектора на заданное число.
CombineVector, VectorCombine, VectorCombine3 — комбинация функций сложения и масштабирования векторов. Каждый из векторов сначала масштабируется на заданную величину, а потом они складываются. Функции написаны на ассемблере, поэтому работают быстрее.
VectorNormalize и NormalizeVector — приводят длины векторов к единице.
NegateVector — направляет вектор в обратную сторону.
AbsVector, VectorAbs — сделать все координаты вектора положительными.
VectorLerp(const v1, v2 … t: Single) — сдвигает точку с координатами v1 в сторону точки с координатами v2 на t*100 %. То есть, если t = 1, то точка v1 попадает в v2. Если t = 0.5, то на половину и т. д.
Удобен для плавного приближения одной точки к другой.
VectorDistance — вычисляет расстояние между двумя векторами.
VectorDistance2 — вычисляет квадрат расстояния между двумя векторами. Работает быстрее чем VectorDistance, так как не используется операция взятия квадратного корня.
VectorSpacing — вычисляет сумму расстояний между векторами по осям X, Y и Z. Работает быстрее чем VectorDistance2.
Смысл этой функции в том, что если результат функции VectorDistance позволяет очертить шар вокруг одного из векторов, и второй вектор может лежать на поверхности этого шара, то результат функции VectorSpacing позволяет очертить вокруг вектора октаэдр [4] сориентированный по осям, на поверхности которого может находиться второй вектор. Таким образом расстояние между векторами полученное с помощью этой функции может находиться в области от N до Sqrt(3)*N. Если такая погрешность не имеет особого значения, например, если расстояние между векторами сравнивается с неким очень маленьким числом, то можно использовать вместо VectorDistance и VectorDistance2 эту функцию, так как она работает быстрее.
VectorEquals, AffineVectorEquals — проверяет равенство двух векторов.
Если с векторами производились сложные преобразования, то где-то в последнем знаки после запятой, может возникнуть погрешность на единичку, и вектора не будут равными.
Чтобы избежать такой ситуации лучше пользоваться функциями VectorDistance или VectorDistance2, сравнивая их результат с каким-нибудь очень маленьким значением.
VectorIsNull — проверяет нулевой ли вектор. Иногда может возникать та же проблема, что и с функциями VectorEquals и AffineVectorEquals.
VectorDotProduct — Длина проекции первого вектора на второй. Если вектора нормализованы, то равна ещё и косинусу угла между этими векторами.
VectorAngleCosine — вычисляет косинус угла между двумя не нормализованными векторами.
VectorCrossProduct — вычисляет вектор перпендикулярный двум заданным. Имеет значения порядок задания векторов в этой функции. От него зависит в какую сторону будет смотреть результирующий перпендикулярный вектор.
Если смотреть на плоскость в которой находятся два заданных вектора и соединить конец первого с концом второго вектора третьим вектором, то если этот вектор будет закручиваться по часовой стрелки вокруг начала координат, то перпендикуляр будет смотреть на нас, а если против часовой стрелки, то от нас.
Часто встречающаяся ошибка, когда вычисляют перпендикуляр к не нормализованным векторам.
VectorPerpendicular(const V, N: TAffineVector) — повернуть вектор V так, чтобы он оказался перпендикулярным к вектору N. Поворот осуществляется в плоскости заданной обоими этими векторами. Поскольку в этой плоскости есть два перпендикуляра к N, то сдвиг осуществляется к ближайшему.
Вектор N обязательно должен быть нормализованным. Длина вектора V влияет только на длину результирующего вектора. Также длина результирующего вектора зависит от угла. между V и N.
Функция удобна когда надо подравнять отклонившийся от перпендикуляра вектор.
VectorReflect(const V, N: TAffineVector) — отражённый вектор. Вектор N задаёт нормаль поверхности от которой надо отразить вектор V. Вектор N должен быть нормализованным, а то угол отражения будет посчитан неверно. Вектор V нормализовывать не обязательно. Его длина влияет только на длину результирующего вектора.
Если оба векторы нормализованные, то результат тоже нормализованный.
PointProject(const p, origin, direction … — вычисляет проекцию точки p на луч заданный точкой origin и направлением direction, при этом направление должно быть нормализованным.
PointProject(const p, origin, direction … — вычисляет проекцию точки p на луч заданный точкой origin и направлением direction, при этом направление должно быть нормализованным.
Функции вращения векторов:
VectorRotateAroundX, VectorRotateAroundY, RotateVectorAroundY, VectorRotateAroundZ — вращают вектор вокруг осей X, Y и Z на угол заданный в радианах.
Для этого сначала вычисляется матрица вращения вокруг соответствующих осей, а потом вектор умножается на эту матрицу вращения.
RotateVector — вращать вектор вокруг заданной оси на угол заданный в радианах.
Для этого сначала вычисляется матрица вращения вокруг заданной оси функцией CreateRotationMatrix, а потом вектор умножается на эту матрицу вращения.
Часто задаваемые вопросы
правитьВ: Где справка? Как проще всего изучить GLScene?
О: Изучить движок проще всего запуская демо исходники из пакета GLScene и изучая их работу — многое можно почерпнуть изучая исходники GLScene. На сайте GLScene.ru в теме «Форум»>"Общие вопросы">"Книжки и учебники"; так же есть интернет учебник где-то в интернете.