Формат файла пока сравнительно молодой и может претерпевать некоторые изменения. Те параметры которые были изменены или добавлены в этой редакции по сравнению с предыдущей редакций, отмечены жёлтым цветом или красным словом New ! . Новые добавленные блоки размечены как New ! begin в начале и New ! end в конце.
Файлы типа *.LOD состоят из сигнатуры и блоков.
Каждый LOD-файл начинается сигнатурой "LODka3D1". Это означает, что это именно LOD-Файл, а не что-нибудь другое. Далее идут блоки ...
Каждый блок состоит из заголовка и данных идущих за ним. Заголовок занимает 12 байт. В нём описан тип данных ( ID ), их длина ( Size ), и один дополнительный параметр данных названный Count, так как часто используется как счётчик.
При помощи Size удобно пропускать ненужные блоки. Считываем из файла/потока только заголовок, и если блок не нужен, то смещаемся по файлу/потоку на Size, таким образом оказываясь перед заголовком следующего за этим блока.
Заголовок имеет формат :
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
ID | 4 | 0 | string |
Идентефикатор блока. Определяет тип данных идущих за заголовком. Например "LOD1" - означает что данные содержит LOD-файл, PHS1 - означает, что данные содержит описание физики. И т. д. |
Size | 4 | 4 | Integer | Размер данных идущих за заголовком. Сам заголовок в эту величину не входит. Если надо получить размер данных с заголовком, то к этой величине надо прибавить 12 ( длина заголовка ). |
Count | 4 | 8 | Integer | Дополнительный параметр данных. Часто используется как счётчки, поэтому и назван Count. |
На Паскале описание заголовка выглядит так:
type TLODChunk = packed record ID : array [0..3] of Char; Size : Integer; Count : Integer; end;
Данные некоторых блоков ( LOD1, MAL1, TXTL, SHDL, MSL1, ANS1, LGS1, PXL1, CLL1 ) могут состоять исключительно из других блоков. Данные других блоков ( INF1, MAT1, SHDR, TXTR, MSH1, SK1, ANM1, PSH1, LIG1, PXI1, COL1, IMG1 ) - нет.
Типы данных, которые используются при описании формата.
Тип данных | Размер ( байт ) | Значения | Описание |
Integer | 4 | -2147483648..2147483647 | Целое знаковое 32-битное число. |
Smallint | 2 | -32768..32767 | Целое знаковое 16-битное число. |
Byte | 1 | 0..255 | Байт. Целое беззнаковое 8-битное число. |
ShortInt | 1 | -128..127 | Целое знаковое 8-битное число. |
Boolean | 1 | 0..1 | Тот же байт, но принимает только два значения, 0 или 1. Чтобы определять включено что-то или выключено. |
Single | 4 | 1.5 x 10^-45 .. 3.4 x 10^38 | Вещественное знаковое 32-битное число. Значащих цифр - 7-8. |
string | произвольный | 0..255 | Строка символов. Состоит из байтов. |
Array | произвольный | произвольное | Массив. Любые произваольные данные. |
LOD1 - блок содержит LOD-файл. Его данные это блоки типов : INF1, MAL1, MSL1, SKL1, ANS1, MAN1, MMD1, PHS1, LGS1, PXL1, CLL1. Параметр заголовка блока Count определяет количество этих блоков.
Блок "LOD1" нужен только для того, чтобы в один файл можно было бы впихнуть много LOD-файлов подряд. Тогда чтобы считать допустим второй файл, не читая первого, можно было бы считать заголовок первого, и сдвинувшись на Size указанный в нём, оказаться в начале второго файла блока LOD1. И т. д. Программа такую мультимодельность не поддерживает. А сделано скорее на будущее.
INF1 - его данные содержат дополнительную текстовую информацию о файле. Описания, копирайты, некоторые параметры модели, и т. д. В принципе данные могут быть не только текстовые, а какие угодно, так как для них есть только один параметр - длина. Но программа считывает и выводит их как текст ( пока, по крайней мере ).
Также этот блок может быть использован как контейнер для дополнительных блоков созданных пользователем для своих нужд.
Параметр заголовка блока Count должен быть равен единице. Параметр заголовка блока Size, определяет размер данных.
SKL1 - содержит информацию о cкелете. О иерархии костей ( какая к какой крепится ) и их имена. Положения и ротации костей описываются в блоке анимаций ANM1. Блок не обязательный и может отсутствовать, если модель не анимированная.
Этот блок ( если он есть ) должен всегда предшествовать блокам ANM1 ( амимация ) и MSL1 ( меши модели ), так как иначе будет непонятно сколько всего костей, к каким костям относятся загружаемые анимации, и к каким костям крепятся точки модели.
В параметре заголовка блока Count записано количество костей скелета BonesCnt.
Данные блока - это:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
SkelType | 1 | 0 | Byte | Тип скелета. Должен быть равен 1. Это резерв на будущее. |
Далее в зависимости от количества костей BonesCnt указанного в параметре Count заголовка блока, записаны следующие данные для каждой кости.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
BoneID | 2 | 0 | SmallInt 0..32767 | Идентефикатор кости. |
BoneParentID | 2 | 2 | SmallInt -1..32767 | Идентефикатор родительской кости. То есть той кости, к которой эта должна быть прикрпелена. Если = -1, то значит эта кость корневая. Этот параметр должен указывать только на идентефикаторы уже встречавшихся костей или на корень ( -1 ). То есть первая загружаемая кость, должна иметь BoneParentID равный -1. Вторая - либо -1, либо ParentID первой, и т. д. Это нужно для того, чтобы можно было крепить кости по мере чтения файла. |
BoneNameLength | 4 | 4 | Integer | Длина имени этой кости. |
BoneName | BoneNameLength | 8 | string | Имя кости. |
Прочитав данные в соответствии с этой таблицей для первой кости, читаем данные для второй, и так далее в соответсвии с количеством заданном в параметре Count = BonesCnt, заголовка блока SKL1.
ANS1 - содержит информацию о списке анимаций. Данные этого блока - это последовательно идущие блоки типа ANM1. Количество которых указано в параметре заголовка блока Count.
Этот блок должен идти после блока SKL1, в котором описана иерархия костей и указано их количество. Так как иначе будет непонятно к какой кости какое положение/ротация относятся, и сколько их всего.
ANМ1 - содержит информацию о единичной анимации. Параметр заголовка блока Count - указывает количество фреймов FramesCnt анимации в этом блоке.
Данные блока - это:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
AnimType | 1 | 0 | Byte | Тип анимации. Должен быть равен 1. Это резерв на будущее. |
AnimInterval | 4 | 4 | Integer | Интервал анимации. Чем больше, тем медленнее она проигрывается. |
AnimMode | 1 | 8 | Byte 0..6 | Режим анимации. Может быть следующих типов. TLODAnimationMode = ( aamLODNone, aamLODPlayOnce, aamLODLoop, aamLODBounceForward, aamLODBounceBackward, aamLODLoopBackward, aamLODExternal); Тип aamLODNone = 0, тип aamLODPlayOnce = 1 и т. д. |
AnimNameLength | 4 | 9 | Integer | Длина имени анимации. |
AnimName | AnimNameLength | 13 | string | Имя анимации |
BonesRotPos | 24 *BonesCnt *FramesCnt | 13 +AnimNameLength | Array |
Далее идут позиции и ротации последовательно всех костей ( от первой до
последней ) для первого фрейма, потом для второго фрейма, потом для
третьего и т. д. до последнего.
|
MAL1 - список библиотек материалов. Данные блока - это блоки типа MAT1 содержащие библиотеки материалов. Правда в программе реализована поддержка только одного такого блока. Поэтому блок должен быть один. А параметр Count означающий количество таких блоков должен быть равен единице.
MAT1 - единичная библиотка материалов. Её Count - это количество материалов в ней. Параметр продублирован ниже, так что здесь он скорее только для информации.
Данные библиотеки материалов:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MaterialsType | 1 | 0 | Byte | Тип материала. Должен быть равен 3. Резерв на будущее. |
MaterialsCount | 4 | 1 | Integer | Количество материалов. Дублирует Count в заголовке блока MAT1. |
Далее в соответствии с количеством материалов MaterialsCount читаем последовательно для каждого материала :
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MatNameLen | 4 | 0 | Integer | Размер имени материала. |
MatName | MatNameLen | 4 | string | Имя материала. |
TextrNameLen | 4 | 4 +MatNameLen | Integer | Размер имени файла текстуры (текстур) TextureName задействованной в материале. См. следующий параметр. |
TextrName | TextrNameLen | 8 +MatNameLen | string | Имя файла текстуры. Либо если в материале есть вторая текстура, то пишется и её имя через двоеточие. То есть имя файла первой текстуры, двоеточие ":", и имя второй текстуры. |
MaterialOptions | 101 | 8 +MatNameLen +TextrNameLen | Array | Структура описывающая различные параметры материала. Расшифровка что в ней чего значит даётся далее в таблице. |
Назначение некоторых параметров в MaterialOptions я сам знаю не слишком точно. За тем, что они означают в OpenGL, лучше обращаться к его документации.
Некоторые комментарии перенесены в описание, из исходников GLScene. В них же можно посмотреть как это работает на практике.
Параметры MaterialOptions в виде таблицы:
Параметр | Размер ( байт ) | Смещение | Тип | Описание |
Ambient | 16 | 0 | 4 Single | Фоновый цвет Ambient. |
Diffuse | 16 | 16 | 4 Single | Цвет Diffuse. |
Emission | 16 | 32 | 4 Single | Цвет Emission. |
Specular | 16 | 48 | 4 Single | Цвет Specular. |
EnvColor | 16 | 64 | 4 Single | Цвет EnvColor. |
Shininess | 1 | 80 | Byte 0>=...>=128 | Shininess. |
ImageBrightness | 4 | 81 | Single | Яркость текстуры ImageBrightness. Из исходников GLScene: Texture brightness correction. This correction is applied upon loading a TGLTextureImage, it's a simple saturating scaling applied to the RGB components of the 32 bits image, before it is passed to OpenGL, and before gamma correction (if any). |
ImageGamma | 4 | 85 | Single | Гамма текстуры ImageGamma. Из исходников GLScene: Texture gamma correction. The gamma correction is applied upon loading a TGLTextureImage, applied to the RGB components of the 32 bits image, before it is passed to OpenGL, after brightness correction (if any). |
NormalMapScale | 4 | 89 | Single | NormalMapScale. Из исходников GLScene: Normal Map scaling. Only applies when TextureFormat is tfNormalMap, this property defines the scaling that is applied during normal map generation (ie. controls the intensity of the bumps). |
BlendingMode | 1 | 93 | Byte 0..5 | BlendingMode. Может быть следующих значений. TBlendingMode = (bmOpaque, bmTransparency, bmAdditive, bmAlphaTest50, bmAlphaTest100, bmModulate); Из исходников GLScene: Simplified blending options.
|
ImageAlpha | 1 | 94 | Byte 0..8 | Представление альфа-канала текстуры ImageAlpha. Может быть следующих значений. TGLTextureImageAlpha = (tiaDefault, tiaAlphaFromIntensity, tiaSuperBlackTransparent, tiaLuminance, tiaLuminanceSqrt, tiaOpaque, tiaTopLeftPointColorTransparent, tiaInverseLuminance, tiaInverseLuminanceSqrt); Из исходников GLScene: Defines how and if Alpha channel is defined for a texture image.
|
TextureMode | 1 | 95 | Byte 0..3 | TextureMode. Способ наложения текстуры. Может быть следующих значений: TGLTextureMode = (tmDecal, tmModulate, tmBlend, tmReplace); Соответствует параметрам OpenGL: GL_DECAL, GL_MODULATE, GL_BLEND, GL_REPLACE. Замещающая текстурная функция (GL_REPLACE) просто берет цвет, которым объект был бы нарисован без текстурирования (цвет фрагмента), отбрасывает его и замещает цветом текстуры. Функцию замещения следует использовать в случаях, когда на объект нужно наложить непрозрачную текстуру. Функция GL_DECAL (переводная картинка) похожа на замещение за исключением того, что она работает только для внутренних форматов RGB и RGBA и обрабатывает альфа величины иначе. В формате RGBA результирующий цвет является результатом наложения цвета текстуры на цвет фрагмента, причем доли этих цветов определяются альфа компонентом текстуры, а альфа фрагмента в расчетах не участвует и не изменяется. Эта функция может использоваться для наложения таких текстур, как знак авиакомпании на крыле самолета (исходный цвет крыла виден везде, кроме того места, где нарисован знак). При модуляции (GL_MODULATE) цвет фрагмента модулируется содержимым текстурной карты. Модуляция хороша для использования с освещением, поскольку цвет освещенного полигона может быть использован для ослабления цвета текстуры. Белые зеркальные полигоны часто используются для визуализации освещенных объектов, а карта текстуры предоставляет диффузный цвет. |
TextureWrap | 1 | 96 | Byte 0..3 | TextureWrap. Замощает поверхность текстурой, или накладывает её один раз. Может быть следующих значений. TGLTextureWrap = (
); |
TextureFormat | 1 | 97 | Byte 0..11 | TextureFormat. Может быть следующих значений. TGLTextureFormat = (tfDefault, tfRGB, tfRGBA, tfRGB16, tfRGBA16, tfAlpha, tfLuminance, tfLuminanceAlpha, tfIntensity, tfNormalMap, tfRGBAFloat16, tfRGBAFloat32); Из исходников GLScene: Texture format for OpenGL (rendering) use. Internally, GLScene handles all "base" images as 32 Bits RGBA, but you can specify a generic format to reduce OpenGL texture memory use:
The actual representation may differ, f.i. old 16bits boards may convert everything to 16bit formats, GeForce boards don't have a 24 bits format internally and will convert to 32 bits, etc. |
TextureEnabled | 1 | 98 | Boolean | TextureEnabled. Включена или нет текстура. |
Enabled | 1 | 99 | Boolean | Enabled. Включён или нет материал. |
MappingMode | 1 | 100 | Byte 0..7 | MappingMode. Может быть следующих значений. TGLTextureMappingMode = (tmmUser, tmmObjectLinear, tmmEyeLinear, tmmSphere, tmmCubeMapReflection, tmmCubeMapNormal, tmmCubeMapLight0, tmmCubeMapCamera); Из исходников GLScene: Texture coordinates mapping mode. This property controls automatic texture coordinates generation. |
Типы, например, TGLTextureMode = (tmDecal, tmModulate, tmBlend, tmReplace);, означают, что tmDecal - это соответсвует нулю. tmModulate - единице. tmBlend - двойке. И т. д.
Прочитав эти данные для первого материала. Переходим к чтению для второго, и так далее в соответсвии с количеством заданном в MaterialsCount.
TXTL - список библиотек материалов, используемых библиотекой материалов MAL1. Параметр Count означающий количество таких блоков и должен быть равен единице, так как и блок MAL1 - один. Данные блока - это блоки типа TXTR содержащие библиотеки текстур.
TXTR - единичная библиотка текстур. Её Count - это количество текстур в ней.
Данные библиотеки текстур:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
TexturesType | 1 | 0 | Byte | Тип библиотеки. Должен быть равен 0. Резерв на будущее. |
Далее идут данные для каждой текстуры ( по числу Count ) в отдельности:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
TextureOptionSize | 4 | 0 | Integer | Размер блока с опциями текстуры. Этот и последующий блок нужны чтобы быстро переходить к следующей текстуре увеличив указатель в потоке данных на TextureOptionSize +TextureDataSize. |
TextureDataSize | 4 | 4 | Integer | Размер блока с данными текстуры. |
TextureOptionType | 4 | 8 | Integer | Тип опция текстуры. Должен быть равен 0. Резерв на будущее. |
TextureMaterialNameLen | 4 | 12 | Integer | Длина имени материала в библиотеке материалов MAL1, в который загружается эта текстура. |
TextureMaterialName | string | 16 | Integer | Имя материала в библиотеке материалов MAL1, в который загружается эта текстура. |
TextureNameLen | 4 | 16 +TextureMaterialNameLen | Integer | Длина имени файла текстуры. |
TextureName | string | 20 +TextureMaterialNameLen | Integer | Имя файла текстуры. |
TextureOptionRezerv | TextureOptionSize -20 -TextureMaterialNameLen -TextureNameLen | 20 +TextureMaterialNameLen +TextureNameLen | Array | Резервный блок переменного размера, который может быть равен нулю. В будущем, для расширения формата сюда могут записываться дополнительные данные. Старые загрузчики не смогут их прочитать, но смогут пропустить, так, что их наличие не помешает загружать новые файлы в старые программы. |
TextureData | TextureDataSize | TextureOptionSize | Array | Данные текстуры. |
Прочитав данные для первой текстуры, они читаются для второй, и так по числу Count.
SHDL - список библиотек шейдеров, подключаемых к библиотеке материалов MAL1. Параметр Count означающий количество таких блоков и должен быть равен единице, так как и блок MAL1 - один. Данные блока - это блоки типа SHDR содержащие библиотеки шейдеров.
SHDR - единичная библиотка шейдеров. Её Count - это количество шейдеров в ней.
Данные библиотеки шейдеров:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
ShaderLibType | 1 | 0 | Byte | Тип библиотеки. Должен быть равен 1. Резерв на будущее. |
Далее идут данные для каждого шейдера в отдельности:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
ShaderSize | 4 | 0 | Integer | Размер блока отведённого под параметры этого шейдера в байтах. Нужен, чтобы во-первых можно было быстро перейти к следующему шейдеру, сместив указатель в потоке данных на ShaderSize байт; во-вторых, это даёт возможность дополнять шейдер новыми параметрами, без потери совместимости со старыми загрузчиками, в которых эти новые параметры не будут прочитываться, но не будут вызывать ошибок. |
ShaderType | 1 | 4 | Byte | Пока поддерживается только Bump-шейдеры, для которых этот параметр равен единице. |
Последующие данные справедливы только для шейдеров типа Bump.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
BumpNameLen | 4 | 0 | Integer | Размер имени материала из библиотеки материалов MAT1, к которому должен быть прикреплён этот шейдер. |
BumpName | BumpNameLen | 4 | string | Имя материала из библиотеки материалов MAT1, к которому должен быть прикреплён этот шейдер. |
BumpNormalNameLen | 4 | 4 +BumpNameLen | Integer | Размер имени материала из библиотеки материалов MAT1, текстура которого является картой нормальей для этого bump-шейдера. |
BumpNormalName | BumpNormalNameLen | 8 +BumpNameLen | string | Имя материала из библиотеки материалов MAT1, текстура которого является картой нормальей для этого bump-шейдера. |
BumpSpecularNameLen | 4 | 8 +BumpNameLen +BumpNormalNameLen | Integer | Размер имени материала из библиотеки материалов MAT1, текстура которого является картой блеска для этого bump-шейдера. |
BumpSpecularName | BumpSpecularNameLen | 12 +BumpNameLen +BumpNormalNameLen | string | Имя материала из библиотеки материалов MAT1, текстура которого является картой блеска для этого bump-шейдера. |
BumpLightPower | 4 | 12 +BumpNameLen +BumpNormalNameLen +BumpSpecularNameLen | Single | Яркость bump-шейдера. |
BumpSpecularPower | 4 | 16 +BumpNameLen +BumpNormalNameLen +BumpSpecularNameLen | Single | Степень блеска bump-шейдера. |
BumpRezerv | ShaderSize -21 -BumpNameLen -BumpNormalNameLen -BumpSpecularNameLen | 20 +BumpNameLen +BumpNormalNameLen +BumpSpecularNameLen | Array | Место зарезервированное для будущих параметров. Если размер больше нуля, значит в формат были добавлены ещё какие-то новые параметры, которые загрузчик не знает и потому не может считать. Однако это не мешает их пропустить. |
Далее считываются те же данные для второго шейдера, потом для третьего, и так по числу записанному в параметр Count, в заголовок блока SHDR.
MSL1 - библиотека мешей. Данные этого блока состоят из блоков "MSH1" содержащих единичные меши модели. Параметр Count показывает количество этих мешей.
MSH1 - единичный меш. Данные блока содержат меш модели. Параметр Count показывает количество фэйс-групп в меше. Далее этот параметр дублируется, а здесь нужен больше для информации. Просто чтобы узнать количество фэйсов не читая данных блока.
Данные блока:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MeshNameLen | 4 | 0 | Integer | Размер имени меша. |
MeshName | MeshNameLen | 4 | string | Имя меша. |
isSkeletonExists | 1 | 4 +MeshNameLen | Boolean |
Есть ли в модели скелет. Нужно потому, что скелетная анимация и
статичный меш, могут быть реализованы в разных классах. И тогда, по этой
опции можно будет определить какой класс создавать.
|
MeshMode | 1 | 5 +MeshNameLen | Integer | Тип меша. Должен быть равен 3. В предыдущей версии было: Тип меша. Должен быть равен 2. |
isMeshVisible | 1 | 6 +MeshNameLen | Boolean | Видимость/включённость меша. Если True, то галочка в программе напротив меша ставится, если False, то нет. |
MeshVertexCnt | 4 | 7 +MeshNameLen | Integer | Количество точек/вершин в меше. |
MeshPointsPos | MeshVertexCnt *12 | 11 +MeshNameLen | Array | Позиции точек. Позиция каждой точки задаётся тремя вещественными числами типа Single. По осям X, Y и Z. Таким образом всего по 12 байт на каждую точку. Общее количество точек задано предыдущей переменной MeshVertexCnt. |
MeshNormalsCnt | 4 | 11 +MeshNameLen +(12*MeshVertexCnt) | Integer | Количество нормалей в этом меше. |
MeshNormals | MeshNormalsCnt *12 | 15 +MeshNameLen +(12*MeshVertexCnt) | Array | Нормали меша. Каждая нормаль - это 3 числа типа Single, описывающие вектор нормали в трёхмерном мире. Таким образом на каждую нормаль приходится по 12 байт. Общее количество нормалей задано предыдущей переменной MeshNormalsCnt. |
MeshTextureNumber | 1 | 15 +MeshNameLen +(12*MeshVertexCnt) +(12*MeshNormals) | Byte [1..2] | Количество текстур в данном меше. Программой поддерживается только две текстуры разом, но в принципе их может быть и больше. В предыдущей версии этот параметр отсутствовал. |
New ! Далее данные повторяются столько раз, сколько указано текстур в MeshTextureNumber. То есть идут MeshTxCrdCnt и MeshTxCrd сначала для первой текстуры, а потом для второй, ( если текстур две ).
В предыдущей версии эти данные повторялись всегда только один раз.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MeshTxCrdCnt | 4 | 0 | Integer | Количество текстурных координат в данном меше. |
MeshTxCrd | MeshTxCrdCnt *8 | 4 | Array | Текстурные координаты меша. Каждая текстурная координата - это 2 числа типа Single, описывающие её положение на плоскости текстуры. Таким образом на каждую текстурную координату приходится по 8 байт. Общее количество текстурных координат задано предыдущей переменной MeshTxCrdCnt. |
Дальнейшие данные идут без повтора.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
PntBnAssocCnt | 4 | 0 | Integer | Количество ассоциаций точек/вершин с костями скелета, в случае когда на каждую вершину приходится только по одной кости ( развесовки при этом отсутствуют ). Может быть равно либо нулю либо MeshVertexCnt. Если нулю, то значит, что либо точки со скетелом модели никак не ассоциированы ( например, статичная, не анимированная модель), либо что костей на вершину больше одной, и используются развесовки, которые читаются ниже. Если значение параметра равно MeshVertexCnt, то значит, что для каждой точки указывается по одному номеру связанной с ней кости. Номер - по списку костей в скелете. |
PntBnAssoc |
= PntBnAssocCnt, если BonesCnt<255 = PntBnAssocCnt*2, если BonesCnt>=255 | 4 | Array | Целые числа. Определяют номер кости, которая данной точке соответствует. То есть первая из этого списка - это номер кости соответствующей первой точки. Вторая - второй. И т. д. Размерность этого массива зависит от количества костей. Если костей меньше 255, то на кость отводится по байту, если больше ( что крайне редко ), то по два байта. |
PntBnWeightType | 4 | размер PntBnAssoc +0 | Integer |
Тип развесовок костей. |
New ! begin
Следующие данные читаются только если PntBnWeightType равен единице, и пропускаются если PntBnWeightType равен нулю.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
BonesPerVertix | 4 | 0 | Integer | Максимальное количество костей на вершину. Должно быть больше 1, так как в случае равенства единице, вершины не имеют весов и пишутся в PntBnAssoc, а в случае нуля PntBnWeightType должен быть равен нулю. |
BonesWeigthArLen | 4 | 4 | Integer | Размер массива записей с данными отводимыми под кости и их веса. |
BonesWeigthArray |
BonesWeigthArLen*5
если BonesCnt <= 127 BonesWeigthArLen*6 если BonesCnt > 127 | 8 | Array | Масив записей с данными отводимыми под кости и их веса. Размер записи зависит от числа костей. Если костей <= 127, то он равен 5, если от 128 до 32767, то 6. |
Если костей на вершину <= 127, то каждая запись выглядит так:
type TVertexBoneWeightBA = packed record // Размер - 5 байт. BoneID : Byte; // Размер - 1 байт. 7 нижних бит - BoneID. Weight : Single; // Размер - 4 байта. Вес. end;
Если костей от 128 до 32767, то каждая запись выглядит так:
type TVertexBoneWeightWA = packed record // Размер - 6 байт. BoneID : Word; // Размер - 2 байта. 15 нижних бит - BoneID. Weight : Single; // Размер - 4 байта. Вес. end;
, где Weight - вес для указанной кости. а 7 и 15 соответственно нижних бит из BoneID - это номера костей в списке костей скелета.
Таким образом каждая запись задаёт для вершины кость и вес. На каждую вершину может приходиться от одной такой записи до BonesPerVertix записей. Первая запись относится к первой вершине, последняя к последней, промежуточные, соответственно к промежуточным от первой до последней вершины.
Верхний бит из BoneID выставленный в единицу означает, что следующий элемент из массива записей BonesWeigthArray будет относиться к следующей вершине, а не к этой же.
Это нужно, чтобы подсократить общий размер массива BonesWeigthArray в случаях, когда, например, на сто вершин приходится по одной кости, а на одну из вершин - десять костей. Если бы это был простой двумерный массив, то его размер бы был MeshVertexCnt * BonesPerVertix = 101 *10 = 1010 записей, причём большинство этих записей были бы пустыми. А благодаря верхнему биту позволяющему пропускать пустые записи размер будет 100*1 +1*10 = 110 записей, то есть меньше на порядок.
Если верхние биты из BoneID равны нулю, то при считывании для каждой вершины BonesPerVertix записей, нужно переходить к считыванию записей для следующей вершины, и т. д. до конца массива.
Дальнейшие данные читаются вне зависимости от параметра PntBnWeightType.
New ! end
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
FaceGroupsCnt | 4 | 0 | Integer | Количество фэйс-групп. |
Описания фэйс-группы:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
FaceType | 4 | 0 | Integer | Тип фэйса. Должен быть равен двойке. |
FaceMode | 1 | 4 | Integer | Мод фэйса. Должен быть равен нулю. Это значит, что здесь не стрипы, не квадры, а обычные треугольники. |
FaceNameLength | 4 | 5 | Integer | Длина имени фэйса. |
FaceName | FaceNameLength | 9 | string | Имя фэйса. |
isFaceVisible | 1 | 9 +FaceNameLength | Boolean | Видимость/включённость фэйса. |
New ! Следующий параметр повторяется количество раз записанное в параметре MeshTextureNumber. Первый раз - длина имени первого материала, второй - второго.
В предыдущей версии эти данные повторялись всегда только один раз.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
FaceMatNameLen | 4 | 0 | Integer | Длина имени материала используемого этим фэйсом. |
New ! Следующий параметр повторяется количество раз записанное в параметре MeshTextureNumber. Первый раз - имя первого материала. Второй - второго.
В предыдущей версии эти данные повторялись всегда только один раз.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
FaceMatName | FaceMatNameLen | 0 | string | Имя материала используемого фэйсом. |
Далее идут параметры повтояющиеся один раз.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
VertexIndCnt | 4 | 0 | Integer | Количество индексов вершин. Три индекса - треугольник, три индекса - треугольник, и т. д. Должно быть кратно трём. |
VertexIndex |
VertexIndCnt*1 при MeshVertexCnt<=256
VertexIndCnt*2 при 256<MeshVertexCnt<=65536 VertexIndCnt*4 при MeshVertexCnt>65536 | 4 | Array | Массив индексов вершин. Три индекса определяют треугольник. Следующие три индекса определяют следующий треугольник. И т. д. Таким образом VertexIndex должен быть кратен трём. Размерность параметра зависит от количества точек в меше MeshVertexCnt ( Не путать с VertexIndCnt ! ). Если их меньше 255, то на каждый индекс отводится по байту. Если больше 255, но меньше 65535, то по два. Если больше 65535, то по четыри. Такой подход позволяет делать файлы меньшего размера. |
SmoothDataCnt | 4 | Integer | Количество параметров групп сглаживания. Должно быть равно либо нулю, либо количеству треугольников ( = втрое меньше чем VertexIndCnt ). | |
SmoothData | SmoothDataCnt *4 | Array | Данные группы сглаживания. Первое целое в массиве задаёт группу сглаживания для первой вершины, второе целое - для второй. И т. д. Всего групп сглаживания - 32. Если в числе установлен первый бит, то значит включена первая группа сглаживания. Если второй, то вторая. И т. д. Если ни один бит не установлен, то треугольник не сглаживается. То есть вычисляется одна нормаль для всех трёх вершин треугольника. | |
NormalsIndCnt | 4 | Integer | Количество индексов нормалей. Три нормали - треугольник, три нормали - треугольник. и т. д. Должно быть кратно трём. | |
NormalIndex |
NormalsIndCnt*1 при MeshNormalsCnt<=256
NormalsIndCnt*2 при 256<MeshNormalsCnt<=65536 NormalsIndCnt*4 при MeshNormalsCnt>65536 | Array | Массив индексов нормалей. Полная аналогия с индексами вершин. Три индекса - треугольник. Следующие три индекса - ещё треугольник. И т. д. Размерность зависит от количества нормалей в меше MeshNormalsCnt ( Не путать с NormalsIndCnt и MeshVertexCnt ! ). . Если их меньше 255, то на каждый индекс отводится по байту. Если больше 255, но меньше 65535, то по два. Если больше 65535, то по четыри. Такой подход позволяет делать файлы меньшего размера. |
New ! Далее данные повторяются столько раз, сколько было указано текстур в параметре MeshTextureNumber. Сначлала TxCrdsIndCnt для первой текстуры, потом для второй ( если она есть ) и т. д.
В предыдущей версии эти данные повторялись всегда только один раз.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
TxCrdsIndCnt | 4 | 0 | Integer | Количество индексов текстурных координат. Три текстурные координаты - тругольник, три текстурные координаты - треугольник и т. д. Должно быть кратно трём. |
New ! Далее данные повторяются столько раз, сколько было указано текстур в параметре MeshTextureNumber. Сначлала TxCrdsInd для первой текстуры, потом для второй ( если она есть ) и т. д.
В предыдущей версии эти данные повторялись всегда только один раз.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
TxCrdsInd |
TxCrdsIndCnt*1 при MeshTxCrdsCnt<=256
TxCrdsIndCnt*2 при 256<MeshTxCrdsCnt<=65536 TxCrdsIndCnt*4 при MeshTxCrdsCnt>65536 | 0 | Array | Массив индексов текстурных координат. Полная аналогия с индексами и нормалями вершин. Три индекса - треугольник. Следующие три индекса - ещё треугольник. И т. д. Размерность зависит от количества нормалей в меше. Если их меньше 255, то на каждый индекс отводится по байту. Если больше 255, но меньше 65535, то по два. Если больше 65535, то по четыри. Такой подход позволяет делать файлы меньшего размера. |
После считывания первой фэйс-группы, считываем вторую. И так далее в соответствии со значением FaceGroupsCnt, в котором записано сколько всего фэйс-групп.
MAN1 - содержит информацию о коллекциях морф-анимаций. Программой записывается после блока MSL1. Параметр Count содержит число морф-анимаций. Далее идут несколько блоков данных.
Сначала читаем тип данных.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MorphCollType | 4 | 0 | Integer | Тип морф коллекций. Должен быть равен нулю. |
Далее блок с описанием коллекций анимаций. Число его элементов записано в параметре Count заголовка этого блока.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MCNameLen | 4 | 0 | Integer | Длина имени коллекции. |
MCCollNameLen | 4 | 4 | Integer | Длина имени коллайдера коллекции. Как в Quake3. Зачем нужно - не знаю. |
MCBonesCount | 4 | 8 | Integer | Число костей в этой коллекции. |
MCAnimCount | 4 | 12 | Integer | Число анимаций в этой коллекции. |
MCParentID | 4 | 20 | Integer | Идентефикатор предка. То есть номер элемента этого массива, который является предком для этого. Если равен -1, значит предка нет, а эта коллекция привязана к корню. |
MCParentBone | 4 | 24 | Integer | Номер кости предка. То, к какой кости предка, должна быть привязана эта коллекция. |
MCProxyID | 4 | 28 | Integer | Идентефикатор элемента, данные которого эта коллекция использует. Если равен -1, то это обычный элемент, а не прокси. |
Прочитав все эти даныне для первого элемента, читаем данные для второго, и так далее, пока не будет прочитано столько элементов, сколько задано в параметре Count заголовка блока.
Далее идёт блок в котором записаны длины имён костей и индексы элементов которые являются предками этих костей. Так как кости являются древовидным списком. Число элементов этого блока получается суммированием числа костей во всех коллекциях MCBonesCount.
Элементы этого блока выглядят:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MCBoneNamesLen | 4 | 0 | Integer | Сначала идут длины имён костей с первой до последней первой коллекции, далее длины имён костей с первой до последней для второй коллекции, и т. д. пока не считаем длины имён для всех костей всех коллекций. |
MCBoneParentID | 4 | 4 | Integer | Сначала идут индексы предков для костей с первой до последней, для первой коллекции, потом для второй, и так до последней. Индексы - это порядковые номера костей в их списках. Если равно -1, то значит у кости предка нет, и она привязана к корню. |
Читаем первый элемент, потом второй, и так до последнего.
Далее читаем структуру с данными анимаций. Число элементов вычисляется суммированием элементов MCAnimCount во всех коллекциях.
Единичный элемент выглядит так:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MCAnimNameLen | 4 | 0 | Integer | Длина имени анимации. |
MCAnimMode | 1 | 4 | Byte | Тип анимации. Может быть: aamLODNone, aamLODPlayOnce, aamLODLoop, aamLODBounceForward, aamLODBounceBackward, aamLODLoopBackward, aamLODExternal. |
MCAnimInterval | 4 | 5 | Integer | Интервал между сменой кадров в миллисекундах. |
MCAnimFramesCount | 4 | 9 | Integer | Число фреймов в анимации. |
Читаем первый элемент, потом второй, и так до последнего.
Далее читаем все имена.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MCAllNames | MCNameLen + MCCollNameLen + MCBoneNamesLen + MCAnimNameLen | 0 | string | Размер массива символов вычисляется суммированием всех вышеперечисленных длин имён. Далее читаем сначала для первой коллекции, имя коллекции, имя коллайдера, имена всех костей с первой до последней, имена всех анимаций с первой до последней. Потом делается тоже самое для второй коллекции, потом для третьей и так далее до последней. |
Далее читаем все матрицы всех костей всех коллекций.
Единичный элемент выглядит так:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MCMatRotPos | Count *MCBonesCount *MCAnimCount *MCAnimFramesCount | 0 | 12 Single | 12 Single - это матрица вращений размером 3x3 и три координаты X, Y, Z позиции. То есть матрица размером 3x4. |
Сначала читаем все матрицы для первой кости всех с первого до последнего фрейма первой анимации первой коллекции, потом для второй анимации первой кости первой коллекции, и так далее до последней анимации, Потом всё точно также читаем для второй кости первой коллекции, потом для третьей, и так далее до последней. Потом читаем всё также для второй коллекции, потом для третьей и так далее до последней.
Далее читаем данные всех коллайдеров всех костей всех коллекций. Каждый коллайдер - это:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MCMins | 12 | 0 | 3 *Single | Минимальная координата Bounding Box. То есть коробки ориентированной по осям. |
MCMaxs | 12 | 12 | 3 *Single | Максимальная координата Bounding Box. То есть коробки ориентированной по осям. |
MCPosition | 12 | 24 | 3 *Single | Позиция коллайдера. |
MCRadius | 4 | 36 | Single | Радиус сферы-коллайдера. |
Число коллайдеров вычисляется сложением числа всех фреймов, всех анимаций, всех коллекций. На каждый фрейм приходится по одному коллайдеру. Читаются они сначала для всех с первого до последнего фрейма первой анимации, первой коллекции, потом также для всех анимаций первой коллекции, потом также для всех коллекций.
MMD1 - содержит информацию о фреймах морф-анимаций мешей. Программой записывается после блока MAN1. Параметр Count содержит число мешей для которых записаны данные. Далее идут несколько блоков данных.
Сначала читаем тип данных.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MorphCollType | 4 | 0 | Integer | Тип. Должен быть равен нулю. |
Далее блок с информацией к какому мешу в файле и коллекции относится фреймы. Число этих блоков задано в параметре Count блока.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MMFramesCount | 4 | 0 | Integer | Число фреймов. |
MMVertexCount | 4 | 4 | Integer | Число вершин. |
MMMeshIndex | 4 | 8 | Integer | Индекс меша в файле в блоке MSL1. |
MMMeshNameLen | 4 | 12 | Integer | Длина имени меша. Нужно на будущее, если в файле будут храниться только анимации без мешей. |
MMMorphColNameLen | 4 | 16 | Integer | Длина имени коллекции, к которой подключён меш с нижеследующими фреймами. |
Прочитав первый блок, читаем второй, и так до последнего.
Далее читаем все имена.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MMAllNames | MMMeshNameLen + MMMorphColNameLen | 0 | string | Размер массива символов вычисляется суммированием всех вышеперечисленных длин имён. Сначала читаем имя меша и имя коллекции для первого блока, потом для втого и так далее до последнего. |
Далее читаем положения всех вершин всех мешей.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MMVertexCount | 4 | 0 | Integer | Читаем число вершин. В принципе оно не нужно, так как может быть вычислено. |
Сами вершины. Единичный элемент выглядит так:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
MMVertex | MMVertexCount | 4 | 3 Single | Все вершины всех фреймов всех мешей. Сначала читаем для меша MMMeshIndex из первого блока все его вершины, всех фреймов всех анимаций, потом для второго и т. д. до последнего. |
PHS1 - содержит информацию о физике. Параметр Count должен быть равен 2. Означает версию блока.
Данные блока - это:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
PhysType | 1 | 0 | Byte | Тип физики. Должен быть равен единице. Резерв на будущее. |
BodyNameLengnt | 4 | 1 | Integer | Длина строки с именами тел. |
GeomsNameLength | 4 | 5 | Integer | Длина строки с именами геометрий. |
MeshLinksCount | 4 | 9 | Integer | Количество элементов массива с ссылками на меши. |
BodyCount | 4 | 13 | Integer | Количество тел. |
GeomsCount | 4 | 17 | Integer | Количество геометрий. |
JointsCount | 4 | 21 | Integer | Количество жоинтов. |
BodysNames | BodyNameLengnt | 25 | string | Строка с именами всех физических тел. Имена тел записаны последовательно в одну строку, и отделены друг от друга двумя символами перевода строки "#13#10". Первое имя - соответствует первому телу, второе - второму, и т. д. |
GeomsNames | GeomsNameLengnt | 25 +BodyNameLengnt | string | Строка с именами всех геометрий. Имена геометрий записаны в одну строку, и отделены друг от друга двумя символами перевода строки "#13#10". Первое имя - соответствует первой геометрии, второе - второй, и т. д. |
MeshLinks | MeshLinksLength |
25 +BodyNameLengnt +GeomsNameLengnt | MeshLinksLength*4 | Это массив целых типа Integer. Количество элементов опеределено в MeshLinksLength. А умножать на четыри нужно потому, что Integer - это 4-ёх байтовое, 32-битное целое. Записанные в массиве числа - это порядковые номера мешей, на которые ссылаются геометрии. |
TBodys | 78 *BodyCount |
25 +BodyNameLengnt +GeomsNameLengnt +(MeshLinksLength *4) | Array | Массив структур содержащих параметры тел. Один элемент структуры - одно тело. Размер каждой структуры - 78 байтов. Расшифровка значений структуры даётся ниже в отдельной таблице. |
TGeoms | 70 *GeomsCount |
25 +BodyNameLengnt +GeomsNameLengnt +(MeshLinksLength *4) +(BodyCount *78) | Array | Массив структур содержащих параметры геометрий. Один элемент структуры - одна геомтерия. Размер каждой структуры - 70 байтов. Расшифровка значений структуры даётся ниже в отдельной таблице. |
TJoints | 101 *JointsCount |
25 +BodyNameLengnt +GeomsNameLengnt +(MeshLinksLength *4) +(BodyCount *78) +(GeomsCount *70) | Array | Массив структур содержащих параметры жоинтов. Один элемент структуры - один жоинт. Размер каждой структуры - 101 байт. Расшифровка значений структуры даётся ниже в отдельной таблице. |
Расшифровка структуры TBody:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
BodyTypeA | 1 | 0 | Byte 0..4 | Тип тела. Может принимать следующие значения : TBodyTypeA = ( bdtNone, bdtBox, bdtSphere, bdtCylinder, bdtCapsule ); , где bdtNone - ноль, bdtBox - один, и т. д. |
BodyPosition | 12 | 1 | 3*Single | Позиция тела. Три числа типа Single, определяющих позицию по трём направлениям X, Y и Z. |
BodyScale | 12 | 13 | 3*Single | Масштаб тела. Три числа типа Single, определяющих масштабирование тела по трём направлениям X, Y и Z. |
BodyRotation | 16 | 25 | 4*Single | Ротация тела. Четыри числа типа Single, определяющих квантернион вращения ( X, Y, Z, W ). |
BodyAxis | 4 | 41 | Integer 0..4 | Направление оси. Параметр можно игнорировать. |
BodyMass | 4 | 45 | Single | Масса тела. |
BodyDensity | 4 | 49 | Single | Плотность тела. |
isBodyTagFloat | 4 | 53 | Single | Tag. Параметр задающийся пользователем. |
BodyEnabled | 1 | 57 | Boolean | Включённость тела. |
isBodyGravity | 1 | 58 | Boolean | Действует ли на тело гравитация. |
isBodyFinRotMode | 1 | 59 | Boolaen | Параметр ODE dBodySetFiniteRotationMode. Контролирует то каким образом будет меняться ориентация тела на каждом шаге симуляции. Из справки ODE:
|
isBodyAutoDisable | 1 | 60 | Boolean | Включённость автовыключения тела. |
isBodyAutoDisableDef | 1 | 61 | Boolean | Включённость автовыключение тела по-умолчанию. |
BodyADLinearThr | 4 | 62 | Single | Значения для параметра ODE, устанавливаемого функцией dBodySetAutoDisableLinearThreshold . То есть пороговое значение линейной скорости для тела, которое используется для автовыключения. |
BodyADAngularThr | 4 | 66 | Single | Значения для параметра ODE, устанавливаемого функцией dBodySetAutoDisableAngularThreshold . То есть пороговое значение линейной скорости для тела, которое используется для автовыключения. |
BodyADisableTime | 4 | 70 | Single | Значения для параметра ODE, устанавливаемого функцией dBodySetAutoDisableTime . То есть время симуляции в течении которого тело должно бездействовать что бы быть автоматически отключенным. |
BodyADSteps | 4 | 74 | Integer | Значения для параметра ODE, устанавливаемого функцией dBodySetAutoDisableSteps . То есть количество шагов симуляции, в течение которых тело должно бездействовать, что бы быть автоматически отключенным. |
Расшифровка структуры TGeoms:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
GeomType | 1 | 0 | Byte 0..9 | Тип геометрии. Может принимать следующие значения : TGeomTypeA = ( bdtNone, bdtBox, bdtSphere, bdtCylinder, bdtCapsule , bdtCone , bdtPlane, bdtTriMesh , bdtCCylinder , bdtRay); , где bdtNone - ноль, bdtBox - один, и т. д. |
GeomBodyIndex | 4 | 1 | Integer | Номер тела в списке тел, к которому прикреплена эта геометрия. |
GeomPosition | 12 | 5 | 3*Single | Позиция геометрии относительно позиции тела, к которому она прикреплена. Три числа типа Single, определяющих позицию по трём направлениям X, Y и Z. |
GeomScale | 12 | 17 | 3*Single | Масштаб геометрии. Три числа типа Single, определяющих масштабирование тела по трём направлениям X, Y и Z. |
GeomRotation | 16 | 29 | 4*Single | Ротация геометрии. Четыри числа типа Single, определяющих квантернион вращения ( X, Y, Z, W ). |
GeomAxis | 4 | 45 | Integer 0..4 | Направление оси. Параметр можно игнорировать. |
GeomMass | 4 | 49 | Single | Масса геометрии. |
GeomsDensity | 4 | 53 | Single | Плотность геомтерии. |
GeomMeshLink | 4 | 57 | Integer | Номер элемента массива MeshLinks, в котором собраны ссылки на меши. Таким образом можно узнать какой меш первым прикреплён к этой геометрии. |
GeomMeshLinkCount | 4 | 61 | Integer | Количестов мешей прикреплённых к этой геометрии. Если первый меш задан через GeomMeshLink, то второй - это GeomMeshLink+1, третий - GeomMeshLink+2, и т. д. В соответствии с количеством GeomMeshLinkCount |
GeomsTagFloat | 4 | 65 | Single | Tag. Параметр задаваемый пользователем. |
GeomsEnabled | 1 | 69 | Boolean | Включённность геометрии. |
Расшифровка структуры TJoints:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
JointType | 1 | 0 | Byte 0..7 | Тип жоинта. Может принимать следующие значения : TJointTypeA = (jtaNone, jtaBall, jtaSlider, jtaHinge, jtaHinge2, jtaUniversal, jtaCorkscrew, jtaUpVector); , где jtaNone - ноль, jtaBall - один, и т. д. |
Joint2BodyIndex | 8 | 1 | 2 * Integer | Первое целое - это номер, в списке тел, первого соединяемого этим жоинтом тела. Второе целое - это номер второго соединяемого этим жоинтом тела. |
JointAxis | 32 | 9 | 8*Single | Два квантерниона определяющих оси жоинта. Если жоинт такого типа, что имеет только одну ось, или не имеет их вообще, то остальные данные игнорируются. Квантернион - это четыри числа типа Single ( X, Y, Z, W ). |
JointPosition | 12 | 41 | 3*Single | Позиция жоинта. Три числа типа Single, определяющих позицию по трём направлениям X, Y и Z. |
JointdParamLoStop | 4 | 53 | Single | Параметр жоинта dParamLoStop. |
JointdParamHiStop | 4 | 57 | Single | Параметр жоинта dParamHiStop. |
JointdParamVel | 4 | 61 | Single | Параметр жоинта dParamVel. |
JointdParamFMax | 4 | 65 | Single | Параметр жоинта dParamFMax. |
JointdParamFudgeFactor | 4 | 69 | Single | Параметр жоинта dParamFudgeFactor. |
JointdParamBounce | 4 | 73 | Sinlge | Параметр жоинта dParamBounce. |
JointdParamCFM | 4 | 77 | Single | Параметр жоинта dParamCFM. |
JointdParamStopERP | 4 | 81 | Single | Параметр жоинта dParamStopERP. |
JointdParamStopCFM | 4 | 85 | Sinlge | Параметр жоинта dParamStopCFM. |
JointdParamSuspensionERP | 4 | 89 | Sinlge | Параметр жоинта dParamSuspensionERP. |
JointdParamSuspensionCFM | 4 | 93 | Single | Параметр жоинта dParamSuspensionCFM. |
JointdTagFloat | 4 | 97 | Sinlge | Tag. Параметр задаваемый пользователем. |
LGS1 - содержит информацию о списке схем освещения. Данные этого блока - это последовательно идущие блоки типа LIG1. Количество которых указано в параметре Count заголовка блока.
Параметр заголовка блока Size, определяет размер данных.
LIG1 - содержит информацию о единичной схеме освещения. То есть о восьми источниках освещения, и их параметрах. Число восемь идёт из OpenGL, где число источников не должно превышать восьми.
Параметр Count заголовка блока должен быть строго равен 8. Это не число источников освещения, а скорее тип блока.
Параметр Size заголовка блока, определяет размер данных.
Данные этого блока - это:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
LightSchemeNameLength | 4 | 0 | Integer | Длина имени схемы. |
Name | LightSchemeNameLength | 4 | Array | Имя схемы освещения. |
Далее последовательно идут параметры каждого из восьми источника освещения. Сначала для первого, потом для второго и т. д.
Данные для каждого источинка освещения - это:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
Enabled | 1 | 0 | Boolean | Включён или нет этот источник освещения. |
LigthStyle | 1 | 1 | Byte [0..2] | Тип освещения. Может принимать следующие значения : 0 - Spot, 1 - Omni, 2 - Parallel. |
Position | 12 | 2 | 3*Single | Позиция источника света. Координаты по X, Y и Z. |
SpotDirection | 12 | 14 | 3*Single | Направление света прожектора. Используется при типе освещения Spot. |
Ambient | 16 | 26 | 4*Single | Интенсивность фонового света. |
Diffuse | 16 | 42 | 4*Single | Интенсивность диффузного света ( значение в OpenGL по умолчанию для 0-го источника - белый свет, для остальных - черный ). |
Specular | 16 | 58 | 4*Single | Интенсивность зеркального света ( значение в OpenGL по умолчанию для 0-го источника - белый свет, для остальных - черный ). |
SpotCutOff | 4 | 74 | Single [0..90,180] | Угол светового конуса. Действует при типе освещения Spot. Может принимать значения от 0 до 90 градусов. А также быть равным 180, что означает, что источник светит во все стороны. |
SpotExponent | 4 | 78 | Single [>=0] | Концентрация светового луча. В OpenGL по умолчанию равен 0, Свет имеет самую высокую интенсивность в центре конуса. При движении от центра к ребрам он ослабляется с коэффициентом равным косинусу угла между направлением света и направлением от источника света к освещаемой вершине, возведенному в степень SpotExponent. Таким образом, больший экспоненциальный коэффициент разброса света (SpotExponent) ведет к более фокусированному свету. |
ConstAtt | 4 | 82 | Single [>=0] | Постоянный фактор ослабления. |
LinearAtt | 4 | 86 | Single [>=0] | Линейный фактор ослабления. |
QuadAtt | 4 | 90 | Single [>=0] | Квадратичный фактор ослабления. |
Все вышеприведённые данные читаются 8 раз. Для каждого источника освещения.
PXL1 - содержит информацию о списке прокси. Данные этого блока - это последовательно идущие блоки типа PXI1. Количество которых указано в параметре Count заголовка блока.
Параметр заголовка блока Size, определяет размер данных.
Блок всегда должен располагаться после блока мешей MSL1, так как содержит ссылки на его элементы, и создать модель по прокси, без мешей не получится.
PXI1 - содержит информацию о единичном прокси. А именно, древовидную структуру элементов, каждый из которых имеет матрицу ( позицию, ротацию, масштаб ), некоторые параметры и индекс меша-источника в блоке мешей MSL1.
Для каждого элемента указанный меш должен быть расположен по указанной матрице с указанными параметрами.
Параметр Count заголовка блока указывает индекс меша в блоке мешей MSL1, вместо которого должен располагаться этот прокси. Таковой элемент в списке мешей MSL1 должен быть пустым.
Параметр Size заголовка блока, определяет размер данных.
Данные этого блока - это:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
ProxyItemsCount | 4 | 0 | Integer | Число элементов дерева прокси. |
ProxyItemNameLengths | ProxyItemsCount *4 | 4 | array of Integer | Длины имён элементов прокси. Первое число - длина первого имени, второе - второго и т. д. При желании можно считать этот список, просуммировать цифры и пропустить имена, так как они нужны только для понятности. |
ProxyItemNames | 4 +ProxyItemsCount*4 | string | В одну строчку имена элементов. |
Далее идут блоки данных с описаниями параметров всех элементов. Число элементов задано в ProxyItemsCount.
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
ProxyParentIndex | 2 | 0 | SmallInt | Предок этого элемента в древовидной структуре. Если равен -1, то значит элемент крепится к корню дерева. При сохранении из ЛОДки элементы располагаются в той же последовательности, в которой идут в редакторе прокси. |
SourceMeshIndex | 2 | 4 | SmallInt | Индекс меша-источника в списке мешей в блоке мешей MSL1. Который надо рассположить по матрице этого элемента с параметрами этого элемента. Если параметр равен -1, значит источник отсутствует, и этот элемент используется, просто как промежуточная матрица, для более удобного рассположения элементов. |
ProxyReserved1 | 2 | 6 | SmallInt | Резерв. Должен быть равен -1. |
ProxyReserved2 | 2 | 8 | SmallInt | Резерв. Должен быть равен -1. |
ProxyReserved3 | 2 | 10 | SmallInt | Резерв. Должен быть равен -1. |
ProxyReserved4 | 2 | 12 | SmallInt | Резерв. Должен быть равен 0. |
ProxyPosition | 12 | 14 | 3*Single | Позиция элемента прокси. X, Y, Z. |
ProxyRotation | 16 | 26 | 4*Single | Ротация элемента прокси. Задана кватернионом. X, Y, Z, W. |
ProxyScale | 12 | 42 | 3*Single | Масштаб элемента прокси. X, Y, Z. |
ProxyVisible | 1 | 54 | Byte | Видимость элемента прокси. Может быть 0 или 1. Если элемент не видим, то все его потомки тоже должны быть не видны. |
ProxyExpanded | 1 | 55 | Byte | Раскрытость/закрытость ветки элемента прокси. Может быть 0 или 1. В принципе элемент не нужный. |
Считав первый элемент прокси, нужно читать второй, и т. д. по числу ProxyItemsCount
CLL1 - содержит информацию о списке наборов коллайдеров. Данные этого блока - это последовательно идущие блоки типа COL1. Количество которых указано в параметре Count заголовка блока.
Параметр заголовка блока Size, определяет размер данных.
Блок всегда должен располагаться после блока мешей SKL1. так как содержит ссылки на идентефикатор костей скелета BoneID.
Наборов коллайдеров может быть много в рассчёте на разные дистанции до актёра. Если дистанция большая, то можно исользовать набор из одного коллайдера в форме бокса или сферы, если ближе, то набор из нескольких коллайдеров, если совсем близко, то набор из большого количества коллайдеров.
Таким образом, за счёт варьирования наборов коллайдеров, можно получить выигрыш в скорости. Если же скорость не критична, то можно обходиться и одним набором.
COL1 - содержит информацию о единичном наборе коллайдеров.
Параметр заголовка блока Size, определяет размер данных.
Набор коллайдеров - это список примитивов (сфера, кубов, цилиндров и капсул) которые должны крепиться к определённым костям скелета.
Параметр заголовка блока Count, указывает число коллайдеров в блоке.
Данные этого блока - это:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
ColListNameLen | 4 | 0 | Integer | Длина имени набора коллайдеров. |
ColListName | 4 | 4 | string | Имя набора коллайдеров. |
ColItemNameLengths | ColCount*4 | 8 | array of Integer | Длины имён коллайдеров. Первое число - длина первого имени, второе - второго и т. д. При желании можно считать этот список, просуммировать цифры и пропустить имена, так как они нужны только для понятности. |
ProxyItemNames | 8 +ColCount*4 +ProxyItemsCount*4 | string | В одну строчку имена элементов. |
Далее последовательно идут параметры каждого коллайдера. Один за другим, от первого до последнего:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
ColBoneID | 2 | 0 | SmallInt | Ссылка на кость BoneID скелета модели. Это именно та кость, к которой должен быть привязан этот коллайдер. |
SkelCollType | 1 | 2 | Byte | Тип коллайдера. 0 - сфера, 1 - капсула, 2 - цилиндр, 3 - бокс. |
CollMatrix | 64 | 3 | 16*Single | Матрица коллайдера размером 4х4. Это матрица относительно кости к которой привязан коллайдер. |
ColTag | 4 | 67 | Integer | Tag типа Integer. Cодержит дополнительную информацию о коллайдере, может использоваться по усмотрению пользователя. Например, отслеживать число попаданий. |
ColTagFloat | 4 | 71 | Single | Tag типа Float. Cодержит дополнительную информацию о коллайдере, может использоваться по усмотрению пользователя. Например, отслеживать уровень повреждений. |
ColVisible | 1 | 75 | Byte | Видимость коллайдера или включённость. |
ColJointAxis1 | 16 | 76 | 4*Single | Ось 1 коллайдера. Задаётся кватернионом. X, Y, Z, W. |
ColJointAxis1MinAngle | 4 | 92 | Single | Минимальный угол для оси 1. |
ColJointAxis1MaxAngle | 4 | 96 | Single | Максимальный угол для оси 1. |
ColJointAxis2 | 16 | 100 | 4*Single | Ось 2 коллайдера. Задаётся кватернионом. X, Y, Z, W. |
ColJointAxis2MinAngle | 4 | 116 | Single | Минимальный угол для оси 2. |
ColJointAxis2MaxAngle | 4 | 120 | Single | Максимальный угол для оси 2. |
Последние 6 параметров сделаны больше на будущее, и пока реально не использовались.
После считывания вышеуказанных параметров для первого коллайдера, считываются теже параметры для второго коллайдера, и так до последнего.
IMG1 - содержит информацию о скриншоте модели. В параметре Count всегда записана единица. Означающая, что скриншот один.
Данные блока - это:
Параметр | Размер ( байт ) | Смещение ( байт ) | Тип | Описание |
ScreenshotType | 4 | 0 | Integer | Тип скриншота. Параметр должен быть равен нулю. |
ScreenshotNameLen | 4 | 4 | Integer | Длина имени скриншота. |
ScreenshotName | ScreenshotNameLen | 8 | string | Имя скриншота. |
ScreenshotDataLen | 4 | 8+ScreenshotNameLen | Integer | Длина блока данных с картинкой скриншота. |
ScreenshotData | ScreenshotDataLen | 12 +ScreenshotNameLen | Array | Файл картинки. |
Если вы найдёте какие-либо ошибки в формате или в этом описании, или что-то здесь объяснено не однозначно, или у вас есть пожелания как формат можно улучшить/дополнить - пишите .
Об орфографических ошибках просьба не сообщать.