|
|
Неофициальная спецификация формата файлов «B3D» V0.2
Материал из Blitz Et Cetera
Введение
Этот документ представляет собой попытку описания на русском формата файлов B3D использующихся в Blitz Basic. Как вы уже догадались B3D - внутренний формат Блица, главным образом предназначенный для описания 3D моделей, материалов и ссылок на текстуры.
Надо заметить, что перевод оказался делом довольно непростым. Причем не из-за того что формат особо заумный (он напротив весьма дружественный), а из-за проблем с терминологией. Сложилась довольно стройная и универсальная английская терминология описания форматов файлов, а вот русской увы нет. Поэтому chunk обозван фрагментом, node - ветвью а кое-что - вообще никак.
B3D в целом
Файл можно представить в виде совокупности следующих элементов:
- Скелет модели (bones) необходимый для анимации.
- Совокупность субмоделей состоящих в свою очередь из поверхностей.
- Кадры анимации в виде ряда фиксированных положений скелета модели.
- Информация о текстурах и общем цвете модели.
При описании формата принята нотация в стиле C/C++ с учетом следующей специфики данных и их размеров.
- int (4 байта), целое со знаком. Любые целые числа (1, 2, 324382 и т. д.) в пределах от -2147483648 до 2147483647
- float (тоже 4 байта). Дробные числа с плавающей запятой (1.34, 2.345.0.0994), целые приведенные к этому типу имеют вид 1.0 2.0 и т. д.
- char (1 байт). Символы типа A,a,c,$,&,1 и т. д., в том виде как они обычно хранятся в файлах. Несколько отличается от строкового типа данных в Блице. Для трансляции можно воспользоваться функциями предоставлеенные Марком Сибли - B3dfile.bb. Кроме того, там можно найти функции для записи заголовка файла и отдельных его элементов - целых, дробных чисел и chunks
Каждому chunk предшествует 8 байт заголовка: B3D Chunk
| char tag [4]
| 4 байта - 4 буквы названия тега (BB3D, TEXS, BRUS и т. д.) )
|
| int length
| 4 байта размер фрагмента (не включая размера самого заголовка)
|
Каждый chunk содержит данные о размере и необязательные вложенные chunks. При написании собственного загрузчика необходимо предусмотреть пропуск всего тела неподдерживаемых chunks .
Составные части по отдельности
*ПРИМЕЧАНИЯ*
- Значения цвета (RGBA), берутся от 0 до 1. То есть берем цвет из Блица и делим на 255.
- string (char[]) значения представляют строку в стиле 'C' . По умолчанию Блиц читает строки из файлов не так!
- Quaternions используются для задания направления. Первое значение - параметр 'w', следующие 3 параметра 'vector'. Ноль ориентации описывается как 1,0,0,0. Самое время почитать подробнее о кватернионах...(Хм... Да уж! Хорошее место - документация по DirectX SDK)
- Все на что следует ссылка 'по индексу' всегда должно быть описано в файле РАНЬШЕ чем собственно ссылка. Т. е. не ссылаться на то чего еще не загружено.
- Ссылки типа brush_id могут быть -1: основной цвет модели по умолчанию.
- Все заключенное в фигурные скобки {} в последующих описаниях подразумевает что блок может неограниченно повторяться вплоть до следующего сhunk. Квадратные скобки [] означают необязательные элементы.
Основные фрагменты файла B3D
- [BB3D] Заголовок.
- [TEXS] Описание текстур.
- [BRUS] Информация об основном цвете модели.
- [NODE] Объекты (Blitz3D Entity).
- [VRTS] Информация о вершинах модели.
- [TRIS] Описание поверхности.
- [MESH] Описание собственно модели.
- [BONE] Анимационный скелет модели(кости).
- [KEYS] Описание кадров анимации.
- [ANIM] Описание анимации.
BB3D
| int version
| версия формата, по умочанию 1. На момент этого описания формат файла не изменялся со времени его разработки, а значит как минимум для версии Blitz3D 1.83 версия остается первой. Тег длины соответственно обозначает размер файла в байтах не считая заголовка. Формат записи версии файла выглядит так major*100+minor те: версия 1.0 обозначается как 1000 1.1 1001 и т. д.
|
TEXS
| ‹
|
|
| char file[ ]
| имя текстуры типа "wall.bmp" Online загрузка не поддерживается.
|
| int flags,blend
| флаги текстуры. Формируются на том же принципе,что и в Блице.
|
| float x_pos,y_pos
| положение текстуры: по умолчанию = 0,0.
|
| float x_scale,y_scale
| масштабирование текстуры: по умолчанию = 1,1.
|
| float rotation
| вращение текстуры (в радианах): по умолчанию = 0 радиан = 180/pi градусов
|
| ›
|
|
Такое описание должно быть для всех используемых текстур. Флаг текстуры 65536 не описанный Марком Сибли означает то, что текстура использует второй набор текстурных координат. Таких наборов в Блиц может быть не больше двух.
Пример:
If t\flags And 65536 Then
TextureCoords t\tex,1
Else TextureCoords t\tex,0
EndIf
BRUS
| int n_texs
|
|
| ‹
|
| char name[]
| Имя типа "WATER" - имя текстуры
|
| float red,green,blue,alpha
| Цвет, последняя составляющая которого - прозрачность: по умолчанию= 1,1,1,1
|
| float shininess
| Блик: по умолчанию= 0
|
| int blend,fx
| Смешивание(blending) и специальные эффекты: по умолчанию= 1,0
|
| int texture_id
| список идентификаторов всех используемых в данном материале текстур могут использоваься текстуры прозрачности, освещения, маска и т. д. Все ID должны вводится с типом int т.е по четыре байта.
|
| ›
|
|
Каждый материал должен содержать отдельный тег BRUS.
NODE
| char name[]
| имя ветви структуры
|
| float position
| локальная позиция...
|
| float scale
| масштабирование...
|
| float rotation
| общий поворот...
|
| BONE]
| тег типа описываемого ветвью структуры, если нераспознается, то принимается как центр масс (pivot).
|
| [KEYS[,KEYS...]]
| необязательные кадры анимации
|
| [NODE[,NODE...]]</td>
| необязательные вложенные иерархии
|
| [ANIM]
| необязательная анимация
|
VRTS
| int flags
| 1 = вершина с нормалями, 2 = цветная вершина
|
| int tex_coord_sets
| количество блоков текстурных координат на вершину (1 - простые U/V) max = 8
|
| int tex_coord_set_size
| размер блока (2 - простые U/V) max = 4
|
| ‹
|
|
| float x,y,z
| обязательны
|
| float nx,ny,nz
| нормаль вершины: только если flags=1
|
| float red,green,blue,alpha
| цвет вершины: если (flags= 2)
|
| float tex_coords
| текстурные координаты
|
| ›
|
|
Фрагмент VRTS содержит список вершин модели. Значение flags показывает какая и сколько дополнительной информации хранится с каждой вершиной (информация о нормали или цвет вершины). В tex_coord_sets и tex_coord_set_size хранится информация о текстурных координатах.
Если, по тем или иным причинам, доведется просматривать файл в шестнадцатиричном редакторе, не стоит удивляться тому, что вершины задаются нечитабельно. Число 1, например выглядит как 0000803F. На самом деле именно так в шестнадцатеричном виде записываются числа с плавающей запятой (Тип данных float в С/С++ и single в VB). Мне не известен алгоритм непосредственного преобразования таких чисел к нормальному виду, но как обходной маневр можно использовать чтение их из файла оператором ReadFloat с выводом на экран. Для обратной операции используем WriteFloat потом читаем это число побайтово (всего 4 байта), преобразуем при помощи Hex и выводим на экран в правильной последовательности.
Чтобы структура VERTS стала немного понятнее приводится следующий пример описания VRTS, в виде, в котором он должен быть в файле.
EXAMPLE:
| 1
| Флаг показывающий, что с каждой вершиной дополнительно хранится описание нормали, он должен быть равен 2 если модель цветная но без текстуры, и 3 если без текстуры но с нормалью
|
| 1
| простейший uvset.
|
| 2
| простейший uvset.
|
| ‹
|
|
| 2.3
| X \
|
| 3.2
| Y |--- координаты вершины.
|
| -1.34
| Z /
|
| 0.0096
|
|
| -0.9998
| нормаль к вершине.
|
| 0.0200
|
|
| 0.45
| текстурная координата U
|
| 0.23
| текстурная координата V
|
| ...
| и так для каждой вершины.
|
| ›
|
|
TRIS
| int brush_id
| общий цвет(кисть) модели: по умолчанию= -1
|
| ‹
|
|
| int vertex_id
| индексы вершин треугольника. Порядок обхода влияет на то, которая из сторон будет видимой.
|
| ›
|
|
Описывает треугольники составляющие модель.
MESH
| int brush_id
| основной цвет(кисть): по умолчанию=-1
|
| VRTS
| вершины
|
| TRIS
| 1 или более наборов треугольников
|
Описывает модель в общем. Имеет единственный фрагмент VRTS и один или более TRIS.
BONE
| ‹
|
|
| int vertex_id
| индекс вершины, которой управляет данный манипулятор
|
| float weight
| не поддерживается устанавливается в 1
|
| ›
|
|
Описывает манипуляторы(кости) скелетной анимации.
KEYS
| int flags
| 1=position, 2=scale, 4=rotation
|
| ‹
|
|
| int frame
| в каком кадре срабатывает
|
| float position
| если (flags=1)
|
| float scale
| если (flags=2)
|
| float rotation
| если (flags= 4)
|
| ›
|
|
Описывает ключевые моменты анимации. Изменение поворота, масштаба, координат модели не могут быть скомбинированы в одном фрагменте KEYS, но несколько KEYS могут указывать на один и тот же кадр
ANIM
| int flags
| не используется=0
|
| int frames
| сколько кадров в анимации
|
| float fps
| скорось анимации(кадры в секунду)= 60
|
Описывает анимацию. Каждый такой фрагмент является отдельной анимационной последовательностью. Каждая ветвь иерархической модели (типа персонажа) может иметь на каждую ветвь иерархии только одну анимационную последовательность.
Все, что нужно знать об иерархии модели
Специфика описываемого стандарта может привести к ошибкам доступа на этапе чтения модели в Блиц. Как уже говорилось Все на что следует ссылка 'по индексу' всегда должно быть описано в файле РАНЬШЕ чем собственно ссылка.. т.е.: Использования манипулятором(костью) индекса вершины, который идет в файле ниже, чем описание этого манипулятора вызовет горячо любимый некоторыми Illegal Memory Address.
Фрагмент NODE описывает Blitz3D Entity. Иерархия модели определяется системой вложенных элементов NODE.
Тип NODE должен определятся однозначно. Он может быть и MESH, и BONE, но не одновременно и тем и другим! Если тип не распознается, то принимается как центр масс (pivot).
Появление в NODE тега ANIM обозначает, что именно на этом уровне иерархии начинается ее анимация. Это предполагает возможность нескольких вложенных анимаций воспроизводящихся на разных скоростях.
Простейшая статическая нетекстурированная модель
| BB3D
| заголовок
|
| 1
| версия
|
| NODE
|
|
| "root_node"
| имя элемента иерархии
|
| 0,0,0
| положение
|
| 1,1,1
| масштаб
|
| 1,0,0,0
| вращение
|
| MESH
| 3D модель
|
| -1
| нет материала (brush)
|
| VRTS
| вершины
|
| 0
| с вершинами нет никакой дополнительной информации
|
| 0,0
| и координат текстуры нет
|
| (x,y,z...)
| координаты вершины
|
| TRIS
| треугольники модели
|
| -1
| без материала (brush)
|
| (v0,v1,v2...)
| перечисление индексов вершин
|
B3DFile.bb
;
;b3d file utils to be included
;
Dim b3d_stack(100)
Global b3d_file,b3d_tos
Function b3dSetFile( file )
b3d_tos=0
b3d_file=file
End Function
;***** functions for reading from B3D files *****
Function b3dReadByte()
Return ReadByte( b3d_file )
End Function
Function b3dReadInt()
Return ReadInt( b3d_file )
End Function
Function b3dReadFloat#()
Return ReadFloat( b3d_file )
End Function
Function b3dReadString$()
Repeat
ch=b3dReadByte()
If ch=0 Return t$
t$=t$+Chr$(ch)
Forever
End Function
Function b3dReadChunk$()
For k=1 To 4
tag$=tag$+Chr$(b3dReadByte())
Next
sz=ReadInt( b3d_file )
b3d_tos=b3d_tos+1
b3d_stack(b3d_tos)=FilePos( b3d_file )+sz
Return tag$
End Function
Function b3dExitChunk()
SeekFile b3d_file,b3d_stack(b3d_tos)
b3d_tos=b3d_tos-1
End Function
Function b3dChunkSize()
Return b3d_stack(b3d_tos)-FilePos( b3d_file )
End Function
;***** Functions for writing to B3D files *****
Function b3dWriteByte( n )
WriteByte( b3d_file,n )
End Function
Function b3dWriteInt( n )
WriteInt( b3d_file,n )
End Function
Function b3dWriteFloat( n# )
WriteFloat( b3d_file,n )
End Function
Function b3dWriteString( t$ )
For k=1 To Len( t$ )
ch=Asc(Mid$(t$,k,1))
b3dWriteByte(ch)
If ch=0 Return
Next
b3dWriteByte( 0 )
End Function
Function b3dBeginChunk( tag$ )
b3d_tos=b3d_tos+1
For k=1 To 4
b3dWriteByte(Asc(Mid$( tag$,k,1 )))
Next
b3dWriteInt( 0 )
b3d_stack(b3d_tos)=FilePos( b3d_file )
End Function
Function b3dEndChunk()
n=FilePos( b3d_file )
SeekFile b3d_file,b3d_stack(b3d_tos)-4
b3dWriteInt( n-b3d_stack(b3d_tos) )
SeekFile b3d_file,n
b3d_tos=b3d_tos-1
End Function
Авторы: Mark Sibly, Adam Templeton (DragoBC hotmail.com)
Дата создания: 2003 г.
Перевод: Александр Альрушди (e-mail: ork@indus.ru)
Дата перевода: 2005 г.
Благодарности: Beaker, Bloodlocust
|
|