Формат файлов *.omf — S.T.A.L.K.E.R. Inside Wiki

Формат файлов *.omf

Материал из S.T.A.L.K.E.R. Inside Wiki

Версия от 15:15, 10 июня 2020; Pavel (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

В этой статье описан формат omf из ТЧ, ЧН и ЗП.

OMF файлы содержат скелетные анимации.

Имеют формат RIFF. То есть файл разбит на чанки.

Файл omf состоит из двух чанков:

0xE - хранит анимации (вращение, перемещение костей)

0xF - хранит Bone Parts и параметры анимаций


Эти чанки могут встечаться внутри ogf файлов.

То есть omf файл - это кусок ogf файла, который вынесен во внешний файл.

Структура 0xE и 0xF чанков в ogf идентична этим же чанкам в omf.

Структура чанка 0xE

Данный чанк состоит из вложенных чанков.

Первый вложенный чанк - это чанк с идентификатором 0x0.

Нулевой чанк хранит целое беззнаковое 32 битное число.

Это число указывает на количество анимаций в omf файле.

Идентификатор каждого последущего чанка на единицу больше предыдущего.

То есть после вложенного чанка 0x0 идёт чанк 0x1, потом 0x2, 0x3 и т. д.

Все чанки, идущие после 0x0, содержат анимации.

Описание вложенного чанка, который хранит анимации

В самом начале идёт имя анимации, которое является строкой, оканчивающейся нулевым байтом.

Далее идёт целое беззнаковое 32 битное число, которое указывает количество кадров анимации.

Следующие данные - это трансформации костей. Для каждой кости хранится вращение, перемещение, флаги.

На первом месте идут флаги. Флаги - это целое беззнаковое 8 битное число.

Первый бит этого байта указывает, является ли перемещение изменяемым.

Если бит равен 1, то на протяжении всех кадров перемещение имеет значения.

Если бит равен 0, то перемещение имеет только одно значение для всего промежутка анимации.

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

Второй бит этого байта указывает, является ли вращение статичным (не меняющимся на протяжении всей анимации).

Третий бит - это флаг High Quality. Если равен 0, то позиция имеет 8 битное представление иначе 16 битное.

Далее идёт информация о вращении.

То, что будет записано в файле дальше, зависит от флагов.

Если второй бит флага равен 0, то в файле будет следующее:

одно значение вращения в виде кватерниона с двухбайтовыми знаковыми компонентами.

То есть QXYZ, каждый по 2 байта, в сумме 8 байт.

А если второй бит флага равен 1, то далее идёт следующее:

crc32 сумма в виде 4 байтового целого беззнакового.

А после неё идут значения кватерниона вращения для каждого кадра.

Формат вращения такой же, как описан выше (теже 8 байт).

Теперь идёт информация о перемещении.

Если первый бит флага равен 1, то далее следует 32 битное целое беззнаковое число, которое является crc32 суммой.

После идёт 3 восьмибитных числа, которые указывают позицию кости по осям x, y, z.

Эти позиции записаны для каждого кадра.

То есть считывать позиции нужно в цикле, который повторяется столько раз, сколько кадров содержит анимация.

После всех этих позиций идут данные о начальных условиях перемещения:

Амплитуда или размер перемещения.

Это 3 числа float (4 байта каждое).

А далее идёт начальное значение перемещения. Тоже 3 числа float.

Эти начальные условия хранятся в единственном экземпляре для каждой кости в данной анимации.

То есть эти значения не меняются на протяжении всей анимации.

Если первый бит флага равен 0, то для всех кадров идёт одно значение перемещения.

Это перемещение хранится в 3 числах float (4 байта каждое).

Ниже написан псевдокод, который описывает одну анимацию:

name = string
length = uint32
for bone in bones {
flags = uint8
translate_present = flags(0) // get bit 0
rotate_absent = flags(1) // get bit 1
high_quality = flags(2) // get bit 2
if rotate_absent {
quaternion = int16, int16, int16, int16 // Q, X, Y, Z
} else {
motion_crc32 = int32
for (i=0, i<length, i++) {
quaternion = int16, int16, int16, int16 // Q, X, Y, Z
}
}
if translate_present {
motion_crc32 = int32
if high_quality {
for (i=0, i<length, i++) {
translation = int16, int16, int16 // X, Y, Z
}
} else {
for (i=0, i<length, i++) {
translation = int8, int8, int8 // X, Y, Z
}
}
translate_size = float, float, float // X, Y, Z
translate_init = float, float, float // X, Y, Z
} else {
translate = float, float, float // X, Y, Z
}

Структура чанка 0xF

Хранит bone parts и параметры анимаций.

Ниже показан код, который описывает этот чанк.

params_version = uint16   // версия формата параметров
partition_count = uint16 // количество bone parts
for (i=0, i<partition_count, i++) {
partition_name = string // имя bone part
bone_count = uint16 // количество костей в данном bone part
for (j=0, j<bone_count, j++) {
if params_version == 3 {
bone_name = string // имя кости
bone_id = uint32 // идентификатор кости
}
}
motion_count = uint16 // количество анимаций
for (j=0, i<motion_count, j++) {
// параметры анимации
motion_name = string
motion_flags = uint32
bone_or_part = uint16
motion = uint16 // идентификатор анимации из чанка 0xE
speed = float32
power = float32
accrue = float32
falloff = float32
}
}

Участник: Pavel

Другие места
LANGUAGE