Журнал о программированнии на языках Blitz3D, BlitzPlus, BlitzMax

Неофициальная спецификация формата файлов «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_sobaka_hotmail.com)
Дата создания: 2003 г.
Перевод: Александр Альрушди (e-mail: ork@indus.ru)
Дата перевода: 2005 г.
Благодарности: Beaker, Bloodlocust

Другие

Друзья