brender-v1.1.2/FW/FILEOPS.C

2255 lines
45 KiB
C++
Raw Permalink Normal View History

2022-05-04 20:14:23 -05:00
/*
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* $Id: fileops.c 1.33 1995/08/31 16:29:25 sam Exp $
* $Locker: $
*
* Per-chunk file operations
*
*/
#include <stddef.h>
#include "fw.h"
#include "brassert.h"
#include "datafile.h"
static char rscid[] = "$Id: fileops.c 1.33 1995/08/31 16:29:25 sam Exp $";
/*
* For digging around in points etc - makes things slightly easier to read
*/
#define X 0
#define Y 1
#define Z 2
#define W 3
#define U 0
#define V 1
/**
** End Marker
**/
STATIC int FopRead_END(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
return 1;
}
STATIC int FopWrite_END(br_datafile *df)
{
df->prims->chunk_write(df,FID_END,0);
return 0;
}
/**
** File Info
**/
struct file_info {
br_uint_32 type;
br_uint_32 version;
};
STATIC br_file_enum_member file_type_FM[] = {
_ENUM_MEMBER(FILE_TYPE_NONE),
_ENUM_MEMBER(FILE_TYPE_ACTORS),
_ENUM_MEMBER(FILE_TYPE_PIXELMAP),
_ENUM_MEMBER(FILE_TYPE_LIGHT),
_ENUM_MEMBER(FILE_TYPE_CAMERA),
_ENUM_MEMBER(FILE_TYPE_MATERIAL),
_ENUM_MEMBER(FILE_TYPE_MODEL),
_ENUM_MEMBER(FILE_TYPE_ANIMATION),
_ENUM_MEMBER(FILE_TYPE_TREE),
};
STATIC _FILE_ENUM(file_type);
#define _STRUCT_NAME struct file_info
STATIC br_file_struct_member file_info_FM[] = {
_ENUM_32(type,file_type_F),
_UINT_32(version),
};
STATIC _FILE_STRUCT(file_info);
#undef _STRUCT_NAME
#if 0
STATIC int FopRead_FILE_INFO(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
struct file_info fi;
df->prims->struct_read(df,&file_info_F, &fi);
return fi.type;
}
#endif
STATIC int FopWrite_FILE_INFO(br_datafile *df, br_uint_32 type)
{
struct file_info fi;
fi.type = type;
fi.version = BR_FILE_VERSION;
df->prims->chunk_write(df,FID_FILE_INFO,df->prims->struct_size(df,&file_info_F, &fi));
df->prims->struct_write(df,&file_info_F, &fi);
return 0;
}
/**
** Vertices + UV
**/
#define _STRUCT_NAME struct br_vertex
STATIC br_file_struct_member br_vertex_FM[] = {
_SCALAR(p.v[X]),
_SCALAR(p.v[Y]),
_SCALAR(p.v[Z]),
};
STATIC _FILE_STRUCT(br_vertex);
#undef _STRUCT_NAME
/*
* Write out the vertices from a model
*/
STATIC int FopWrite_VERTICES(br_datafile *df, br_vertex *vertices, int nvertices)
{
df->prims->chunk_write(df,FID_VERTICES,
df->prims->count_size(df) + nvertices * df->prims->struct_size(df,&br_vertex_F,NULL));
df->prims->count_write(df,nvertices);
DfStructWriteArray(df,&br_vertex_F, vertices, nvertices);
return 0;
}
/*
* Adds an array of vertices to a model that is on the stack
*
*/
STATIC int FopRead_VERTICES(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_model *mp = DfTop(DFST_MODEL,0);
mp->vertices = BrResAllocate(mp, count * sizeof(br_vertex),BR_MEMORY_VERTICES);
DfStructReadArray(df,&br_vertex_F, mp->vertices, count);
mp->nvertices = (br_uint_16) count;
return 0;
}
/*
* Builds an array of vertices and pushes it onto the stack
*
*/
STATIC int FopRead_OLD_VERTICES(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
void *ptr;
count = length/df->prims->struct_size(df,&br_vertex_F,NULL);
ptr = BrResAllocate(fw.res, count* sizeof(br_vertex), BR_MEMORY_VERTICES);
DfStructReadArray(df,&br_vertex_F, ptr, count);
DfPush(DFST_VERTICES,ptr,count);
return 0;
}
/**
** Per Vertex UV
**/
#define _STRUCT_NAME struct br_vertex
STATIC br_file_struct_member br_vertex_uv_FM[] = {
_SCALAR(map.v[0]),
_SCALAR(map.v[1]),
};
STATIC _FILE_STRUCT(br_vertex_uv);
#undef _STRUCT_NAME
/*
* Write out an array of vertices and their texture coordinates
*/
STATIC int FopWrite_VERTEX_UV(br_datafile *df, br_vertex *vertices, int nvertices)
{
df->prims->chunk_write(df,FID_VERTEX_UV,
df->prims->count_size(df) + nvertices * df->prims->struct_size(df,&br_vertex_uv_F,NULL));
df->prims->count_write(df,nvertices);
DfStructWriteArray(df,&br_vertex_uv_F, vertices, nvertices);
return 0;
}
/*
* Read an array of texture components and add it to the model on the stack
*
* The incoming array has to be <= the existing vertex array
*/
STATIC int FopRead_VERTEX_UV(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_model *mp = DfTop(DFST_MODEL,0);
if(count > mp->nvertices)
BR_ERROR0("Vertex UV: too many entries");
DfStructReadArray(df,&br_vertex_uv_F, mp->vertices, count);
return 0;
}
#define _STRUCT_NAME struct br_vertex
STATIC br_file_struct_member br_old_vertex_uv_FM[] = {
_SCALAR(p.v[X]),
_SCALAR(p.v[Y]),
_SCALAR(p.v[Z]),
_SCALAR(map.v[0]),
_SCALAR(map.v[1]),
};
STATIC _FILE_STRUCT(br_old_vertex_uv);
#undef _STRUCT_NAME
/*
* Read an array of vertices and push it onto the stack
*/
STATIC int FopRead_OLD_VERTICES_UV(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
void *ptr;
count = length/df->prims->struct_size(df,&br_old_vertex_uv_F,NULL);
ptr = BrResAllocate(fw.res, count * sizeof(br_vertex),BR_MEMORY_VERTICES);
DfStructReadArray(df,&br_old_vertex_uv_F, ptr, count);
DfPush(DFST_VERTICES,ptr,count);
return 0;
}
/**
** Material Index
**/
/*
* Read a material index and push it onto the stack
*/
STATIC int FopRead_MATERIAL_INDEX(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
char name[BR_MAX_NAME];
br_material **mip;
br_uint_32 i;
/*
* Allocate block for pointers to materials. Include a NULL pointer
* at entry 0
*/
mip = BrResAllocate(fw.res, (count+1)*sizeof(*mip),BR_MEMORY_MATERIAL_INDEX);
mip[0] = NULL;
/*
* Read and lookup each name
*/
for(i=1; i< count+1; i++)
mip[i] = BrMaterialFind(df->prims->name_read(df,name));
/*
* Push index onto stack
*/
DfPush(DFST_MATERIAL_INDEX,mip,count+1);
return 0;
}
/*
* Write out the material naes from a table of material pointers
*
*/
STATIC int FopWrite_MATERIAL_INDEX(br_datafile *df, br_material **materials, int nmaterials)
{
int i,s;
/*
* Work out size of chunk
*/
s=df->prims->count_size(df);
for(i=0; i< nmaterials; i++)
s += df->prims->name_size(df,materials[i]->identifier);
df->prims->chunk_write(df,FID_MATERIAL_INDEX,s);
df->prims->count_write(df,nmaterials);
/*
* Go through materials table writing out identifiers
*/
for(i=0; i< nmaterials; i++)
df->prims->name_write(df,materials[i]->identifier);
return 0;
}
/*
* Read an old-style material index (no count) and push it onto the stack
*/
STATIC int FopRead_OLD_MATERIAL_INDEX(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
char *mblock,*cp;
int i,num_materials;
br_material **mip;
/*
* Read the index block into temporary buffer
*/
mblock = BrScratchAllocate(length);
if(BrFileRead(mblock, 1, length, df->h) != (int)length)
BR_ERROR0("could not read material index");
/*
* Count the number of 0's in buffer (== number of strings as
* each string is 0 or more chars terminated with 0)
*/
for(i=0, cp=mblock, num_materials=0; i< (int)length;i++)
if(*cp++ == '\0')
num_materials++;
/*
* Allocate block for pointers to materials
*/
mip = BrResAllocate(fw.res, num_materials * sizeof(*mip), BR_MEMORY_MATERIAL_INDEX);
/*
* Go through table looking up materials
*/
for(i=0, cp=mblock ; i < num_materials; i++) {
mip[i] = BrMaterialFind(cp);
while(*cp++);
}
/*
* Free working buffer
*/
BrScratchFree(mblock);
/*
* Push index onto stack
*/
DfPush(DFST_MATERIAL_INDEX,mip,num_materials);
return 0;
}
/**
** Faces
**/
#define _STRUCT_NAME struct br_face
STATIC br_file_struct_member br_face_FM[] = {
_UINT_16(vertices[0]),
_UINT_16(vertices[1]),
_UINT_16(vertices[2]),
_UINT_16(smoothing),
_UINT_8(flags),
};
STATIC _FILE_STRUCT(br_face);
#undef _STRUCT_NAME
/*
* Read an array of triangular faces and add it to model on the stack
*/
STATIC int FopRead_FACES(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
struct br_model *mp;
int i;
/*
* Get the model and material table
*/
mp = DfTop(DFST_MODEL,0);
mp->faces = BrResAllocate(mp, count * sizeof(br_face), BR_MEMORY_FACES);
mp->nfaces = (br_uint_16)count;
/*
* Read faces
*/
DfStructReadArray(df,&br_face_F, mp->faces, mp->nfaces);
/*
* make sure each face has at least one smoothing group
*/
for(i=0; i< mp->nfaces; i++)
if(mp->faces[i].smoothing == 0)
mp->faces[i].smoothing = (br_uint_16)~0;
return 0;
}
/*
* Write out an array of faces
*/
STATIC int FopWrite_FACES(br_datafile *df, br_face *faces, int nfaces)
{
df->prims->chunk_write(df,FID_FACES,
df->prims->count_size(df) + nfaces * df->prims->struct_size(df,&br_face_F,NULL));
df->prims->count_write(df,nfaces);
DfStructWriteArray(df,&br_face_F, faces, nfaces);
return 0;
}
/**
** Obselete Faces (before 16 bit smoothing values)
**/
#define _STRUCT_NAME struct br_face
STATIC br_file_struct_member br_old_face_1_FM[] = {
_UINT_16(vertices[0]),
_UINT_16(vertices[1]),
_UINT_16(vertices[2]),
_UINT_8(smoothing),
_UINT_8(flags),
};
STATIC _FILE_STRUCT(br_old_face_1);
#undef _STRUCT_NAME
/*
* Read an array of triangular faces and add it to model on the stack
*/
STATIC int FopRead_OLD_FACES_1(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
struct br_model *mp;
int i;
/*
* Get the model and material table
*/
mp = DfTop(DFST_MODEL,0);
mp->faces = BrResAllocate(mp, count * sizeof(br_face), BR_MEMORY_FACES);
mp->nfaces = (br_uint_16)count;
/*
* Read faces
*/
DfStructReadArray(df,&br_old_face_1_F, mp->faces, mp->nfaces);
/*
* Convert smoothing groups to bitmask
*/
for(i=0; i< mp->nfaces; i++) {
if(mp->faces[i].smoothing == 0)
mp->faces[i].smoothing = (br_uint_16)~0;
else
mp->faces[i].smoothing = 1 << ((mp->faces[i].smoothing-1) % 16);
}
return 0;
}
/*
* Old faces
*/
#define _STRUCT_NAME struct br_face
STATIC br_file_struct_member br_old_face_FM[] = {
_UINT_16(vertices[0]),
_UINT_16(vertices[1]),
_UINT_16(vertices[2]),
_UINT_16(material),
_UINT_32(smoothing),
};
STATIC _FILE_STRUCT(br_old_face);
#undef _STRUCT_NAME
STATIC int FopRead_OLD_FACES(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
struct br_face *fp;
br_material **mip;
int mi_count;
unsigned int i;
void *ptr;
count = length/df->prims->struct_size(df,&br_old_face_F,NULL);
/*
* Get the number of vertices and material table
*/
ptr = DfPop(DFST_VERTICES,(int *)&i);
mip = DfPop(DFST_MATERIAL_INDEX,&mi_count);
DfPush(DFST_VERTICES,ptr,i);
fp = BrResAllocate(fw.res, count * sizeof(br_face), BR_MEMORY_FACES);
DfStructReadArray(df,&br_old_face_F, fp , count);
/*
* Go through and convert materials to pointers
*/
for(i=0; i< count; i++) {
fp[i].material = mip[*((br_uint_16 *)&fp[i].material)];
/*
* make sure each face has at least one smoothing group
*/
if(fp[i].smoothing == 0)
fp[i].smoothing = (br_uint_16)~0;
}
/*
* Free up material index
*/
BrResFree(mip);
/*
* Leave allocated block on stack
*/
DfPush(DFST_FACES,fp,count);
return 0;
}
/**
** Per face material indices
**/
STATIC int FopWrite_FACE_MATERIAL(br_datafile *df, br_face *faces, int nfaces, br_material **mindex, int nmaterials)
{
br_uint_16 *block,*ip;
br_face *fp;
int i,j;
/*
* Make a block in memory for index
*/
block = BrResAllocate(fw.res, nfaces * sizeof(*block), BR_MEMORY_MATERIAL_INDEX);
/*
* Build index
*/
for(i=0, fp = faces, ip = block; i< nfaces; i++, fp++,ip++) {
*ip = 0;
/*
* Look up material in index if not NULL
*/
if(fp->material) {
for(j=0; j< nmaterials; j++) {
if(mindex[j] == fp->material) {
*ip = j+1; /* Index entries start at 1 */
break;
}
}
}
}
df->prims->chunk_write(df,FID_FACE_MATERIAL,df->prims->block_size(df,block,nfaces,0,1,sizeof(br_uint_16)));
/*
* Write index as a block
*/
df->prims->block_write(df,block,nfaces,0,1,sizeof(br_uint_16));
BrResFree(block);
return 0;
}
STATIC int FopRead_FACE_MATERIAL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_material **mindex;
int nmaterials;
br_model *mp;
br_face *fp;
br_uint_16 *block,*ip;
int block_count,i;
/*
* Grab material index of stack
*/
mindex = DfPop(DFST_MATERIAL_INDEX,&nmaterials);
mp = DfTop(DFST_MODEL,0);
/*
* Read block from file
*/
block = BrScratchAllocate(length);
block_count = mp->nfaces;
block = df->prims->block_read(df,block,&block_count,sizeof(br_uint_16),0);
if(block_count > mp->nfaces)
BR_ERROR0("Face Materials: too many entries");
/*
* Go through block looking up material pointers
*/
for(i=0, fp = mp->faces, ip = block; i< block_count; i++, fp++,ip++) {
fp->material = (*ip < nmaterials)?mindex[*ip]:NULL;
}
/*
* Release block
*/
BrScratchFree(block);
/*
* Release material index
*/
BrResFree(mindex);
return 0;
}
/**
** Model
**/
#define _STRUCT_NAME struct br_model
STATIC br_file_struct_member br_model_FM[] = {
_UINT_16(flags),
_ASCIZ(identifier),
};
STATIC _FILE_STRUCT(br_model);
#undef _STRUCT_NAME
STATIC int FopRead_MODEL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_model *mp;
/*
* Allocate and read in model structure
*/
mp = BrModelAllocate(NULL,0,0);
df->res = mp;
df->prims->struct_read(df,&br_model_F, mp);
df->res = NULL;
/*
* Make sure CUSTOM flag is _NOT_ set
*/
mp->flags &= ~(BR_MODF_CUSTOM | BR_MODF_PREPREPARED);
/*
* Leave model on stack
*/
DfPush(DFST_MODEL,mp,1);
return 0;
}
STATIC int FopWrite_MODEL(br_datafile *df, br_model *mp)
{
br_model temp_model = *mp;
/*
* Don't save the CUSTOM flag
*/
temp_model.flags &= ~(BR_MODF_CUSTOM | BR_MODF_PREPREPARED);
df->prims->chunk_write(df,FID_MODEL, df->prims->struct_size(df,&br_model_F, &temp_model));
df->prims->struct_write(df,&br_model_F, &temp_model);
return 0;
}
/**
** Old model
**/
#define _STRUCT_NAME struct br_model
STATIC br_file_struct_member br_old_model_1_FM[] = {
_ASCIZ(identifier),
};
STATIC _FILE_STRUCT(br_old_model_1);
#undef _STRUCT_NAME
STATIC int FopRead_OLD_MODEL_1(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_model *mp;
/*
* Allocate and read in model structure
*/
mp = BrModelAllocate(NULL,0,0);
df->res = mp;
df->prims->struct_read(df,&br_old_model_1_F, mp);
df->res = NULL;
/*
* Leave model on stack
*/
DfPush(DFST_MODEL,mp,1);
return 0;
}
STATIC int FopRead_OLD_MODEL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_model *mp;
int i;
/*
* Allocate and read in model structure
*/
mp = BrModelAllocate(NULL,0,0);
df->res = mp;
df->prims->struct_read(df,&br_model_F, mp);
df->res = NULL;
/*
* Hook up vertices and faces
*/
mp->faces = DfPop(DFST_FACES,&i);
mp->nfaces = i;
mp->vertices = DfPop(DFST_VERTICES,&i);
mp->nvertices = i;
BrResAdd(mp,mp->faces);
BrResAdd(mp,mp->vertices);
/*
* Make sure CUSTOM flag is _NOT_ set
*/
mp->flags &= ~(BR_MODF_CUSTOM | BR_MODF_PREPREPARED);
/*
* Leave model on stack
*/
DfPush(DFST_MODEL,mp,1);
return 0;
}
/**
** Pivot
**/
#define _STRUCT_NAME struct br_model
STATIC br_file_struct_member br_pivot_FM[] = {
_SCALAR(pivot.v[X]),
_SCALAR(pivot.v[Y]),
_SCALAR(pivot.v[Z]),
};
STATIC _FILE_STRUCT(br_pivot);
#undef _STRUCT_NAME
STATIC int FopRead_PIVOT(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_model *mp;
mp = DfPop(DFST_MODEL,0);
df->res = mp;
df->prims->struct_read(df,&br_pivot_F, mp);
df->res = NULL;
DfPush(DFST_MODEL,mp,1);
return 0;
}
/**
** Material
**/
#define _STRUCT_NAME struct br_material
STATIC br_file_struct_member br_material_FM[] = {
_COLOUR(colour),
_UINT_8(opacity),
_UFRACTION(ka),
_UFRACTION(kd),
_UFRACTION(ks),
_SCALAR(power),
_UINT_16(flags),
_VECTOR2(map_transform.m[0]),
_VECTOR2(map_transform.m[1]),
_VECTOR2(map_transform.m[2]),
_UINT_8(index_base),
_UINT_8(index_range),
_ASCIZ(identifier),
};
STATIC _FILE_STRUCT(br_material);
#undef _STRUCT_NAME
STATIC int FopRead_MATERIAL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_material *mp;
/*
* Allocate and read in material structure
*/
mp = BrMaterialAllocate(NULL);
df->res = mp;
df->prims->struct_read(df,&br_material_F, mp);
df->res = NULL;
/*
* Leave material on stack
*/
DfPush(DFST_MATERIAL,mp,1);
return 0;
}
STATIC int FopWrite_MATERIAL(br_datafile *df, br_material *mp)
{
df->prims->chunk_write(df,FID_MATERIAL, df->prims->struct_size(df,&br_material_F, mp));
df->prims->struct_write(df,&br_material_F, mp);
return 0;
}
/*
* Add a reference to a pixelmap to material on the stack
*/
/*
* Table of chunk id's versus offsets in material structure
*/
STATIC struct {
br_uint_32 id;
size_t offset;
int table;
} MaterialMaps[] = {
{FID_COLOUR_MAP_REF, offsetof(struct br_material,colour_map), 0},
{FID_INDEX_BLEND_REF, offsetof(struct br_material,index_blend), 1},
{FID_INDEX_SHADE_REF, offsetof(struct br_material,index_shade), 1},
{FID_SCREENDOOR_REF, offsetof(struct br_material,screendoor), 1},
};
STATIC int FopRead_PIXELMAP_REF(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_pixelmap *pm;
char name[BR_MAX_NAME];
char *mp;
int i;
/*
* Lookup ID in table
*/
for(i=0; i< BR_ASIZE(MaterialMaps); i++)
if(id == MaterialMaps[i].id)
break;
ASSERT(i < BR_ASIZE(MaterialMaps));
/*
* Get material from stack, get name, and look it up
*/
mp = DfTop(DFST_MATERIAL,0);
if(MaterialMaps[i].table)
pm = BrTableFind(df->prims->name_read(df,name));
else
pm = BrMapFind(df->prims->name_read(df,name));
*(br_pixelmap **)(mp+MaterialMaps[i].offset) = pm;
return 0;
}
/*
* Wrtie out a reference to a pixelmap
*/
STATIC int FopWrite_PIXELMAP_REF(br_datafile *df, int id, br_pixelmap *pixelmap)
{
ASSERT(pixelmap && pixelmap->identifier);
df->prims->chunk_write(df,id, df->prims->name_size(df,pixelmap->identifier));
df->prims->name_write(df,pixelmap->identifier);
return 0;
}
/**
** Pixelmap
**/
STATIC br_file_enum_member pixelmap_type_FM[] = {
_ENUM_MEMBER(BR_PMT_INDEX_1),
_ENUM_MEMBER(BR_PMT_INDEX_2),
_ENUM_MEMBER(BR_PMT_INDEX_4),
_ENUM_MEMBER(BR_PMT_INDEX_8),
_ENUM_MEMBER(BR_PMT_RGB_555),
_ENUM_MEMBER(BR_PMT_RGB_565),
_ENUM_MEMBER(BR_PMT_RGB_888),
_ENUM_MEMBER(BR_PMT_RGBX_888),
_ENUM_MEMBER(BR_PMT_RGBA_8888),
_ENUM_MEMBER(BR_PMT_YUYV_8888),
_ENUM_MEMBER(BR_PMT_YUV_888),
_ENUM_MEMBER(BR_PMT_DEPTH_16),
_ENUM_MEMBER(BR_PMT_DEPTH_32),
_ENUM_MEMBER(BR_PMT_ALPHA_8),
_ENUM_MEMBER(BR_PMT_INDEXA_88),
};
STATIC _FILE_ENUM(pixelmap_type);
#define _STRUCT_NAME struct br_pixelmap
STATIC br_file_struct_member br_pixelmap_FM[] = {
_ENUM_8(type,pixelmap_type_F),
_UINT_16(row_bytes),
_UINT_16(width),
_UINT_16(height),
_UINT_16(origin_x),
_UINT_16(origin_y),
_ASCIZ(identifier),
};
STATIC _FILE_STRUCT(br_pixelmap);
#undef _STRUCT_NAME
STATIC int FopWrite_PIXELMAP(br_datafile *df, br_pixelmap *pp)
{
br_pixelmap pixelmap = *pp;
pixelmap.row_bytes = pixelmap.width * BrPixelmapPixelSize(&pixelmap) / 8;
df->prims->chunk_write(df,FID_PIXELMAP, df->prims->struct_size(df,&br_pixelmap_F, &pixelmap));
df->prims->struct_write(df,&br_pixelmap_F, &pixelmap);
return 0;
}
STATIC int FopRead_PIXELMAP(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_pixelmap *pp;
/*
* Allocate and read in pixelmap structure
*/
pp = BrResAllocate(fw.res,sizeof(*pp),BR_MEMORY_PIXELMAP);
df->res = pp;
df->prims->struct_read(df,&br_pixelmap_F, pp);
df->res = NULL;
pp->row_bytes = pp->width * BrPixelmapPixelSize(pp) / 8;
/*
* Leave material on stack
*/
DfPush(DFST_PIXELMAP,pp,1);
return 0;
}
/**
** Pixel bytes
**/
STATIC int FopWrite_PIXELS(br_datafile *df, br_pixelmap *pixelmap)
{
int size = BrPixelmapFileSize(pixelmap);
int bpp = BrPixelmapPixelSize(pixelmap);
int block_count = (pixelmap->width * bpp / 8)/ size;
char *pixels;
int y;
pixels = (char *)(pixelmap->pixels)+
pixelmap->base_y*pixelmap->row_bytes+
(pixelmap->base_x * bpp) / 8;
df->prims->chunk_write(df,FID_PIXELS,
df->prims->block_size(df,
pixels,
block_count,
pixelmap->row_bytes,
pixelmap->height,
size));
df->prims->block_write(df,
pixels,
block_count,
pixelmap->row_bytes,
pixelmap->height,
size);
return 0;
}
STATIC int FopRead_PIXELS(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
int icount;
br_pixelmap *pp;
int size;
pp = DfTop(DFST_PIXELMAP,0);
size = BrPixelmapFileSize(pp);
df->res = pp;
pp->pixels = df->prims->block_read(df,NULL, &icount, size, BR_MEMORY_PIXELS);
pp->flags |= BR_PMF_LINEAR;
df->res = NULL;
return 0;
}
/**
** Connecting a map to an indexed pixelmap
**/
STATIC int FopWrite_ADD_MAP(br_datafile *df)
{
df->prims->chunk_write(df,FID_ADD_MAP,0);
return 0;
}
STATIC int FopRead_ADD_MAP(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_pixelmap *pp,*map;
map = DfPop(DFST_PIXELMAP,0);
pp = DfTop(DFST_PIXELMAP,0);
pp->map = map;
return 0;
}
/**
** Actor
**/
STATIC br_file_enum_member actor_type_FM[] = {
_ENUM_MEMBER(BR_ACTOR_NONE),
_ENUM_MEMBER(BR_ACTOR_MODEL),
_ENUM_MEMBER(BR_ACTOR_LIGHT),
_ENUM_MEMBER(BR_ACTOR_CAMERA),
_ENUM_MEMBER(_BR_ACTOR_RESERVED),
_ENUM_MEMBER(BR_ACTOR_BOUNDS),
_ENUM_MEMBER(BR_ACTOR_BOUNDS_CORRECT),
_ENUM_MEMBER(BR_ACTOR_CLIP_PLANE),
};
STATIC _FILE_ENUM(actor_type);
STATIC br_file_enum_member render_style_FM[] = {
_ENUM_MEMBER(BR_RSTYLE_DEFAULT),
_ENUM_MEMBER(BR_RSTYLE_NONE),
_ENUM_MEMBER(BR_RSTYLE_POINTS),
_ENUM_MEMBER(BR_RSTYLE_EDGES),
_ENUM_MEMBER(BR_RSTYLE_FACES),
_ENUM_MEMBER(BR_RSTYLE_BOUNDING_POINTS),
_ENUM_MEMBER(BR_RSTYLE_BOUNDING_EDGES),
_ENUM_MEMBER(BR_RSTYLE_BOUNDING_FACES),
};
STATIC _FILE_ENUM(render_style);
#define _STRUCT_NAME struct br_actor
STATIC br_file_struct_member br_actor_FM[] = {
_ENUM_8(type,actor_type_F),
_ENUM_8(render_style,render_style_F),
_ASCIZ(identifier),
};
STATIC _FILE_STRUCT(br_actor);
#undef _STRUCT_NAME
STATIC int FopWrite_ACTOR(br_datafile *df, br_actor *ap)
{
df->prims->chunk_write(df,FID_ACTOR, df->prims->struct_size(df,&br_actor_F, ap));
df->prims->struct_write(df,&br_actor_F, ap);
return 0;
}
STATIC int FopRead_ACTOR(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_actor *ap;
/*
* Allocate and read in actor structure
*/
ap = BrActorAllocate(BR_ACTOR_NONE,NULL);
df->res = ap;
df->prims->struct_read(df,&br_actor_F, ap);
df->res = NULL;
ap->t.type = BR_TRANSFORM_IDENTITY;
/*
* Leave actor on stack
*/
DfPush(DFST_ACTOR,ap,1);
return 0;
}
/**
** Actor's reference to a model
**/
STATIC int FopWrite_ACTOR_MODEL(br_datafile *df, br_model *model)
{
ASSERT(model && model->identifier);
df->prims->chunk_write(df,FID_ACTOR_MODEL, df->prims->name_size(df,model->identifier));
df->prims->name_write(df,model->identifier);
return 0;
}
STATIC int FopRead_ACTOR_MODEL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
char name[BR_MAX_NAME];
br_actor *a;
/*
* Get actor from stack
*/
a = DfTop(DFST_ACTOR,0);
a->model = BrModelFind(df->prims->name_read(df,name));
return 0;
}
/**
** Actor's reference to a material
**/
STATIC int FopWrite_ACTOR_MATERIAL(br_datafile *df, br_material *material)
{
ASSERT(material && material->identifier);
df->prims->chunk_write(df,FID_ACTOR_MATERIAL, df->prims->name_size(df,material->identifier));
df->prims->name_write(df,material->identifier);
return 0;
}
STATIC int FopRead_ACTOR_MATERIAL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
char name[BR_MAX_NAME];
br_actor *a;
/*
* Get actor from stack
*/
a = DfTop(DFST_ACTOR,0);
a->material = BrMaterialFind(df->prims->name_read(df,name));
return 0;
}
/**
** Actor's transform
**/
STATIC int FopWrite_ACTOR_TRANSFORM(br_datafile *df)
{
df->prims->chunk_write(df,FID_ACTOR_TRANSFORM,0);
return 0;
}
STATIC int FopRead_ACTOR_TRANSFORM(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_actor *a;
br_transform *tp;
/*
* Get transform and actor of the stack
*/
tp = DfPop(DFST_TRANSFORM,0);
a = DfTop(DFST_ACTOR,0);
/*
* Copy transform into actor
*/
a->t = *tp;
/*
* Free the translation
*/
BrResFree(tp);
return 0;
}
/**
** Add light to actor
**/
STATIC int FopWrite_ACTOR_LIGHT(br_datafile *df)
{
df->prims->chunk_write(df,FID_ACTOR_LIGHT,0);
return 0;
}
STATIC int FopRead_ACTOR_LIGHT(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_actor *a;
br_light *lp;
/*
* Get light and actor of the stack
*/
lp = DfPop(DFST_LIGHT,0);
a = DfTop(DFST_ACTOR,0);
/*
* Attach light to actor
*/
a->type_data = lp;
return 0;
}
/**
** Add camera to actor
**/
STATIC int FopWrite_ACTOR_CAMERA(br_datafile *df)
{
df->prims->chunk_write(df,FID_ACTOR_CAMERA,0);
return 0;
}
STATIC int FopRead_ACTOR_CAMERA(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_actor *a;
br_light *cp;
/*
* Get camera and actor of the stack
*/
cp = DfPop(DFST_CAMERA,0);
a = DfTop(DFST_ACTOR,0);
/*
* Attach camera to actor
*/
a->type_data = cp;
return 0;
}
/**
** Add bounds to actor
**/
STATIC int FopWrite_ACTOR_BOUNDS(br_datafile *df)
{
df->prims->chunk_write(df,FID_ACTOR_BOUNDS,0);
return 0;
}
STATIC int FopRead_ACTOR_BOUNDS(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_actor *a;
br_bounds *bp;
/*
* Get bounds and actor of the stack
*/
bp = DfPop(DFST_BOUNDS,0);
a = DfTop(DFST_ACTOR,0);
/*
* Attach bounds to actor
*/
a->type_data = bp;
return 0;
}
/**
** Add Clip plane to actor
**/
STATIC int FopWrite_ACTOR_CLIP_PLANE(br_datafile *df)
{
df->prims->chunk_write(df,FID_ACTOR_CLIP_PLANE,0);
return 0;
}
STATIC int FopRead_ACTOR_CLIP_PLANE(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_actor *a;
br_vector4 *vp;
/*
* Get clip vector and actor of the stack
*/
vp = DfPop(DFST_PLANE,0);
a = DfTop(DFST_ACTOR,0);
/*
* Attach bounds to actor
*/
a->type_data = vp;
return 0;
}
STATIC int FopWrite_ACTOR_ADD_CHILD(br_datafile *df)
{
df->prims->chunk_write(df,FID_ACTOR_ADD_CHILD,0);
return 0;
}
/*
* Add actor at top of stack as a child of actor next on stack
*/
STATIC int FopRead_ACTOR_ADD_CHILD(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_actor *a,*p;
a = DfPop(DFST_ACTOR,0);
p = DfTop(DFST_ACTOR,0);
BrActorAdd(p,a);
return 0;
}
/**
** Transforms
**/
#define _STRUCT_NAME struct br_transform
STATIC br_file_struct_member br_transform_matrix34_FM[] = {
/*
* XXX Assumes rows of matrix can be cast to vectors
*/
_VECTOR3(t.mat.m[0]),
_VECTOR3(t.mat.m[1]),
_VECTOR3(t.mat.m[2]),
_VECTOR3(t.mat.m[3]),
};
STATIC _FILE_STRUCT(br_transform_matrix34);
#undef _STRUCT_NAME
#define _STRUCT_NAME struct br_transform
STATIC br_file_struct_member br_transform_quat_FM[] = {
_SCALAR(t.quat.q.x),
_SCALAR(t.quat.q.y),
_SCALAR(t.quat.q.z),
_SCALAR(t.quat.q.w),
_VECTOR3(t.quat.t),
};
STATIC _FILE_STRUCT(br_transform_quat);
#undef _STRUCT_NAME
STATIC br_file_enum_member angle_order_FM[] = {
_ENUM_MEMBER(BR_EULER_XYZ_S),
_ENUM_MEMBER(BR_EULER_XYX_S),
_ENUM_MEMBER(BR_EULER_XZY_S),
_ENUM_MEMBER(BR_EULER_XZX_S),
_ENUM_MEMBER(BR_EULER_YZX_S),
_ENUM_MEMBER(BR_EULER_YZY_S),
_ENUM_MEMBER(BR_EULER_YXZ_S),
_ENUM_MEMBER(BR_EULER_YXY_S),
_ENUM_MEMBER(BR_EULER_ZXY_S),
_ENUM_MEMBER(BR_EULER_ZXZ_S),
_ENUM_MEMBER(BR_EULER_ZYX_S),
_ENUM_MEMBER(BR_EULER_ZYZ_S),
_ENUM_MEMBER(BR_EULER_ZYX_R),
_ENUM_MEMBER(BR_EULER_XYX_R),
_ENUM_MEMBER(BR_EULER_YZX_R),
_ENUM_MEMBER(BR_EULER_XZX_R),
_ENUM_MEMBER(BR_EULER_XZY_R),
_ENUM_MEMBER(BR_EULER_YZY_R),
_ENUM_MEMBER(BR_EULER_ZXY_R),
_ENUM_MEMBER(BR_EULER_YXY_R),
_ENUM_MEMBER(BR_EULER_YXZ_R),
_ENUM_MEMBER(BR_EULER_ZXZ_R),
_ENUM_MEMBER(BR_EULER_XYZ_R),
_ENUM_MEMBER(BR_EULER_ZYZ_R),
};
STATIC _FILE_ENUM(angle_order);
#define _STRUCT_NAME struct br_transform
STATIC br_file_struct_member br_transform_euler_FM[] = {
_ENUM_8(t.euler.e.order,angle_order_F),
_ANGLE(t.euler.e.a),
_ANGLE(t.euler.e.b),
_ANGLE(t.euler.e.c),
_VECTOR3(t.euler.t),
};
STATIC _FILE_STRUCT(br_transform_euler);
#undef _STRUCT_NAME
#define _STRUCT_NAME struct br_transform
STATIC br_file_struct_member br_transform_look_up_FM[] = {
_VECTOR3(t.look_up.look),
_VECTOR3(t.look_up.up),
_VECTOR3(t.look_up.t),
};
STATIC _FILE_STRUCT(br_transform_look_up);
#undef _STRUCT_NAME
#define _STRUCT_NAME struct br_transform
STATIC br_file_struct_member br_transform_translation_FM[] = {
_VECTOR3(t.translate.t),
};
STATIC _FILE_STRUCT(br_transform_translation);
#undef _STRUCT_NAME
/*
* Index (by transform type), of chunk ID and file struct to use
*/
STATIC struct transform_type {
int id;
struct br_file_struct *fs;
} TransformTypes[] = {
{FID_TRANSFORM_MATRIX34, &br_transform_matrix34_F},
{FID_TRANSFORM_MATRIX34_LP, &br_transform_matrix34_F},
{FID_TRANSFORM_QUAT, &br_transform_quat_F},
{FID_TRANSFORM_EULER, &br_transform_euler_F},
{FID_TRANSFORM_LOOK_UP, &br_transform_look_up_F},
{FID_TRANSFORM_TRANSLATION, &br_transform_translation_F},
{FID_TRANSFORM_IDENTITY, NULL},
};
STATIC int FopWrite_TRANSFORM(br_datafile *df, br_transform *t)
{
struct transform_type *tt;
ASSERT(t->type < BR_ASIZE(TransformTypes));
tt = TransformTypes+t->type;
if(tt->fs) {
df->prims->chunk_write(df,tt->id,df->prims->struct_size(df,tt->fs, t));
df->prims->struct_write(df,tt->fs, t);
} else {
df->prims->chunk_write(df,tt->id,0);
}
return 0;
}
STATIC int FopRead_TRANSFORM(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
int t;
br_transform *tp;
/*
* Look up ID in table
*/
for(t=0; t<BR_ASIZE(TransformTypes); t++)
if(TransformTypes[t].id == id)
break;
ASSERT(t < BR_ASIZE(TransformTypes));
/*
* Allocate transform and fill in type
*/
tp = BrResAllocate(fw.res,sizeof(*tp),BR_MEMORY_TRANSFORM);
tp->type = t;
df->res = tp;
if(TransformTypes[t].fs)
df->prims->struct_read(df,TransformTypes[t].fs, tp);
df->res = NULL;
/*
* Leave transform on stack
*/
DfPush(DFST_TRANSFORM,tp,1);
return 0;
}
/**
** Bounds
**/
#define _STRUCT_NAME struct br_bounds3
STATIC br_file_struct_member br_bounds3_FM[] = {
_VECTOR3(min),
_VECTOR3(max),
};
STATIC _FILE_STRUCT(br_bounds3);
#undef _STRUCT_NAME
STATIC int FopWrite_BOUNDS(br_datafile *df, br_bounds *bp)
{
df->prims->chunk_write(df,FID_BOUNDS, df->prims->struct_size(df,&br_bounds3_F, bp));
df->prims->struct_write(df,&br_bounds3_F, bp);
return 0;
}
int FopRead_BOUNDS(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_bounds3 *bp;
/*
* Allocate and read in bounds structure
*/
bp = BrResAllocate(fw.res,sizeof(*bp),BR_MEMORY_BOUNDS);
df->res = bp;
df->prims->struct_read(df,&br_bounds3_F, bp);
df->res = NULL;
/*
* Leave bounds on stack
*/
DfPush(DFST_BOUNDS,bp,1);
return 0;
}
/**
** Plane
**/
struct br_plane { br_vector4 *eqn; };
#define _STRUCT_NAME struct br_plane
STATIC br_file_struct_member br_plane_FM[] = {
_VECTOR4(eqn),
};
STATIC _FILE_STRUCT(br_plane);
#undef _STRUCT_NAME
STATIC int FopWrite_PLANE(br_datafile *df, br_vector4 *pp)
{
df->prims->chunk_write(df,FID_PLANE, df->prims->struct_size(df,&br_plane_F, pp));
df->prims->struct_write(df,&br_plane_F, pp);
return 0;
}
STATIC int FopRead_PLANE(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_vector4 *pp;
/*
* Allocate and read in vector
*/
pp = BrResAllocate(fw.res,sizeof(*pp),BR_MEMORY_CLIP_PLANE);
df->res = pp;
df->prims->struct_read(df,&br_plane_F, pp);
df->res = NULL;
/*
* Leave bounds on stack
*/
DfPush(DFST_PLANE,pp,1);
return 0;
}
/**
** Light
**/
STATIC br_file_enum_member light_type_FM[] = {
_ENUM_MEMBER(BR_LIGHT_POINT),
_ENUM_MEMBER(BR_LIGHT_DIRECT),
_ENUM_MEMBER(BR_LIGHT_SPOT),
_ENUM_MEMBER(BR_LIGHT_VIEW|BR_LIGHT_POINT),
_ENUM_MEMBER(BR_LIGHT_VIEW|BR_LIGHT_DIRECT),
_ENUM_MEMBER(BR_LIGHT_VIEW|BR_LIGHT_SPOT),
};
STATIC _FILE_ENUM(light_type);
#define _STRUCT_NAME struct br_light
STATIC br_file_struct_member br_light_FM[] = {
_ENUM_8(type,light_type_F),
_COLOUR(colour),
_SCALAR(attenuation_c),
_SCALAR(attenuation_l),
_SCALAR(attenuation_q),
_ANGLE(cone_inner),
_ANGLE(cone_outer),
_ASCIZ(identifier),
};
STATIC _FILE_STRUCT(br_light);
#undef _STRUCT_NAME
STATIC int FopWrite_LIGHT(br_datafile *df, br_light *lp)
{
df->prims->chunk_write(df,FID_LIGHT, df->prims->struct_size(df,&br_light_F, lp));
df->prims->struct_write(df,&br_light_F, lp);
return 0;
}
STATIC int FopRead_LIGHT(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_light *lp;
/*
* Allocate and read in light structure
*/
lp = BrResAllocate(fw.res,sizeof(*lp),BR_MEMORY_LIGHT);
df->res = lp;
df->prims->struct_read(df,&br_light_F, lp);
df->res = NULL;
/*
* Leave light on stack
*/
DfPush(DFST_LIGHT,lp,1);
return 0;
}
/**
** Camera
**/
STATIC br_file_enum_member camera_type_FM[] = {
_ENUM_MEMBER(BR_CAMERA_PARALLEL),
_ENUM_MEMBER(BR_CAMERA_PERSPECTIVE),
};
STATIC _FILE_ENUM(camera_type);
#define _STRUCT_NAME struct br_camera
STATIC br_file_struct_member br_camera_FM[] = {
_ENUM_8(type,camera_type_F),
_ANGLE(field_of_view),
_SCALAR(hither_z),
_SCALAR(yon_z),
_SCALAR(aspect),
_ASCIZ(identifier),
};
STATIC _FILE_STRUCT(br_camera);
#undef _STRUCT_NAME
STATIC int FopWrite_CAMERA(br_datafile *df, br_camera *cp)
{
df->prims->chunk_write(df,FID_CAMERA, df->prims->struct_size(df,&br_camera_F, cp));
df->prims->struct_write(df,&br_camera_F, cp);
return 0;
}
STATIC int FopRead_CAMERA(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count)
{
br_camera *cp;
/*
* Allocate and read in camera structure
*/
cp = BrResAllocate(fw.res,sizeof(*cp),BR_MEMORY_CAMERA);
df->res = cp;
df->prims->struct_read(df,&br_camera_F, cp);
df->res = NULL;
/*
* Leave camera on stack
*/
DfPush(DFST_CAMERA,cp,1);
return 0;
}
/**
** Public file operations
**/
/*
* Allocate memory and read the model from the file - bind and material
* references to the current loaded set - or default if the named material
* does not exist.
*/
STATIC br_chunks_table_entry ModelLoadEntries[] = {
{FID_END, 0,FopRead_END},
{FID_OLD_MATERIAL_INDEX, 0,FopRead_OLD_MATERIAL_INDEX},
{FID_OLD_VERTICES, 0,FopRead_OLD_VERTICES},
{FID_OLD_VERTICES_UV, 0,FopRead_OLD_VERTICES_UV},
{FID_OLD_FACES, 0,FopRead_OLD_FACES},
{FID_OLD_MODEL, 0,FopRead_OLD_MODEL},
{FID_OLD_FACES_1, 1,FopRead_OLD_FACES_1},
{FID_OLD_MODEL_1, 0,FopRead_OLD_MODEL_1},
{FID_MODEL, 0,FopRead_MODEL},
{FID_MATERIAL_INDEX, 1,FopRead_MATERIAL_INDEX},
{FID_VERTICES, 1,FopRead_VERTICES},
{FID_VERTEX_UV, 1,FopRead_VERTEX_UV},
{FID_FACES, 1,FopRead_FACES},
{FID_FACE_MATERIAL, 0,FopRead_FACE_MATERIAL},
{FID_PIVOT, 0,FopRead_PIVOT},
};
STATIC br_chunks_table ModelLoadTable = {
BR_ASIZE(ModelLoadEntries),
ModelLoadEntries,
};
br_uint_32 BR_PUBLIC_ENTRY BrModelLoadMany(char *filename,br_model **models,br_uint_16 num)
{
int count;
int r;
br_datafile *df;
df = DfOpen(filename,0);
if(df == NULL)
return 0;
for (count=0; count<num; ) {
r=DfChunksInterpret(df, &ModelLoadTable);
if(DfTopType() == DFST_MODEL)
models[count++] = DfPop(DFST_MODEL, 0);
if(r==0)
break;
}
DfClose(df);
return count;
}
/*
* Write a complete single model.
*
* Does not know about groups - which would be a quicker way of acquiring
* the material index, but makes this code dependant on the groups code
* staying the same.
*/
STATIC int BR_CALLBACK PtrCompare(const void *a, const void *b)
{
return *((char **)b) - *((char **)a);
}
STATIC br_uint_32 BR_CALLBACK WriteModel(br_model *mp, br_datafile *df)
{
br_material **mindex;
br_vertex *vp;
int nmaterials;
int i;
int has_uv;
/*
* Build material index - there will never be more materials than faces
*/
if(mp->faces) {
mindex = BrResAllocate(fw.res, mp->nfaces * sizeof(*mindex), BR_MEMORY_MATERIAL_INDEX);
/*
* make table of material pointers
*/
for(i=0; i< mp->nfaces; i++)
mindex[i] = mp->faces[i].material;
/*
* sort pointers (reverse by value - NULL should wind up at end)
*/
BrQsort(mindex, mp->nfaces, sizeof(*mindex), PtrCompare);
/*
* Count how many unique pointers there are and compact
* them to the base of the table
*/
for(i=1, nmaterials=1; i< mp->nfaces; i++)
if(mindex[i] != mindex[i-1])
mindex[nmaterials++] = mindex[i];
/*
* Remove any NULL from end of table
*/
if(mindex[nmaterials-1] == NULL)
nmaterials --;
}
/*
* See if model has any non zero U and V components
*/
has_uv = 0;
for(i=0, vp = mp->vertices; i< mp->nvertices; i++, vp++) {
if((vp->map.v[U] != BR_SCALAR(0.0)) ||
(vp->map.v[V] != BR_SCALAR(0.0))) {
has_uv = 1;
break;
}
}
/*
* Write out chunks
*/
FopWrite_MODEL(df, mp);
if(mp->nvertices) {
FopWrite_VERTICES(df, mp->vertices, mp->nvertices);
if(has_uv)
FopWrite_VERTEX_UV(df, mp->vertices, mp->nvertices);
}
if(mp->nfaces) {
FopWrite_FACES(df, mp->faces, mp->nfaces);
if(nmaterials) {
FopWrite_MATERIAL_INDEX(df, mindex,nmaterials);
FopWrite_FACE_MATERIAL(df, mp->faces,mp->nfaces,mindex,nmaterials);
}
}
FopWrite_END(df);
BrResFree(mindex);
return 0;
}
/*
* Save a set of models to the named file.
*
* if models == NULL, then all registered models are saved
*/
br_uint_32 BR_PUBLIC_ENTRY BrModelSaveMany(char *filename,br_model **models,br_uint_16 num)
{
br_datafile *df;
int i,m=0;
/*
* Open file and write header
*/
df = DfOpen(filename,1);
if(df == NULL)
return 0;
FopWrite_FILE_INFO(df, FILE_TYPE_MODEL);
if(models) {
for(i=0; i<num; i++)
WriteModel(models[i],df);
m = num;
} else {
BrModelEnum(NULL,(br_model_enum_cbfn *)WriteModel,(void *)df);
m = BrModelCount(NULL);
}
DfClose(df);
return m;
}
/*
* Load a hierachy of 1 or more actors and their transforms described in
* a file
*/
STATIC br_chunks_table_entry ActorLoadEntries[] = {
{FID_END, 0,FopRead_END},
{FID_ACTOR, 0,FopRead_ACTOR},
{FID_ACTOR_MODEL, 0,FopRead_ACTOR_MODEL},
{FID_ACTOR_TRANSFORM, 0,FopRead_ACTOR_TRANSFORM},
{FID_ACTOR_MATERIAL, 0,FopRead_ACTOR_MATERIAL},
{FID_ACTOR_LIGHT, 0,FopRead_ACTOR_LIGHT},
{FID_ACTOR_CAMERA, 0,FopRead_ACTOR_CAMERA},
{FID_ACTOR_BOUNDS, 0,FopRead_ACTOR_BOUNDS},
{FID_ACTOR_CLIP_PLANE, 0,FopRead_ACTOR_CLIP_PLANE},
{FID_ACTOR_ADD_CHILD, 0,FopRead_ACTOR_ADD_CHILD},
{FID_TRANSFORM_MATRIX34, 0,FopRead_TRANSFORM},
{FID_TRANSFORM_MATRIX34_LP, 0,FopRead_TRANSFORM},
{FID_TRANSFORM_QUAT, 0,FopRead_TRANSFORM},
{FID_TRANSFORM_EULER, 0,FopRead_TRANSFORM},
{FID_TRANSFORM_LOOK_UP, 0,FopRead_TRANSFORM},
{FID_TRANSFORM_TRANSLATION, 0,FopRead_TRANSFORM},
{FID_TRANSFORM_IDENTITY, 0,FopRead_TRANSFORM},
{FID_BOUNDS, 0,FopRead_BOUNDS},
{FID_LIGHT, 0,FopRead_LIGHT},
{FID_CAMERA, 0,FopRead_CAMERA},
{FID_PLANE, 0,FopRead_PLANE},
};
STATIC br_chunks_table ActorLoadTable = {
BR_ASIZE(ActorLoadEntries),
ActorLoadEntries,
};
br_uint_32 BR_PUBLIC_ENTRY BrActorLoadMany(char *filename, br_actor **actors, br_uint_16 num)
{
br_datafile *df;
int count;
int r;
df = DfOpen(filename,0);
if(df == NULL)
return 0;
for (count=0 ; count<num; ) {
r = DfChunksInterpret(df, &ActorLoadTable);
if(DfTopType() == DFST_ACTOR)
actors[count++] = DfPop(DFST_ACTOR,0);
if(r==0)
break;
}
DfClose(df);
return count;
}
/*
* Save a hierachy of 1 or more actors and their transforms described in a file
*/
STATIC int WriteActor(br_actor *a, br_datafile *df)
{
br_actor *ap;
/*
* Base actor structure
*/
FopWrite_ACTOR(df,a);
/*
* Transform
*/
if(a->t.type != BR_TRANSFORM_IDENTITY) {
FopWrite_TRANSFORM(df,&a->t);
FopWrite_ACTOR_TRANSFORM(df);
}
/*
* Model and material references, if they exist
*/
if(a->material)
FopWrite_ACTOR_MATERIAL(df,a->material);
if(a->model)
FopWrite_ACTOR_MODEL(df,a->model);
/*
* Type specific data
*/
if(a->type_data) {
switch(a->type) {
case BR_ACTOR_LIGHT:
FopWrite_LIGHT(df,a->type_data);
FopWrite_ACTOR_LIGHT(df);
break;
case BR_ACTOR_CAMERA:
FopWrite_CAMERA(df,a->type_data);
FopWrite_ACTOR_CAMERA(df);
break;
case BR_ACTOR_BOUNDS:
FopWrite_BOUNDS(df,a->type_data);
FopWrite_ACTOR_BOUNDS(df);
break;
case BR_ACTOR_CLIP_PLANE:
FopWrite_PLANE(df,a->type_data);
FopWrite_ACTOR_CLIP_PLANE(df);
break;
}
}
/*
* Children
*/
BR_FOR_SIMPLELIST(&a->children,ap) {
WriteActor(ap,df);
FopWrite_ACTOR_ADD_CHILD(df);
}
return 0;
}
/*
* Save a set of actors to the named file.
*/
br_uint_32 BR_PUBLIC_ENTRY BrActorSaveMany(char *filename, br_actor **actors, br_uint_16 num)
{
br_datafile *df;
int i;
/*
* Open file and write header
*/
df = DfOpen(filename,1);
if(df == NULL)
return 0;
FopWrite_FILE_INFO(df, FILE_TYPE_ACTORS);
/*
* Write out all the actors
*/
for(i=0; i<num; i++) {
WriteActor(actors[i], df);
FopWrite_END(df);
}
DfClose(df);
return num;
}
/*
* Load a group of materials from a file
*/
STATIC br_chunks_table_entry MaterialLoadEntries[] = {
{FID_END, 0,FopRead_END},
{FID_MATERIAL, 0,FopRead_MATERIAL},
{FID_COLOUR_MAP_REF, 0,FopRead_PIXELMAP_REF},
{FID_INDEX_BLEND_REF, 0,FopRead_PIXELMAP_REF},
{FID_INDEX_SHADE_REF, 0,FopRead_PIXELMAP_REF},
{FID_SCREENDOOR_REF, 0,FopRead_PIXELMAP_REF},
};
STATIC br_chunks_table MaterialLoadTable = {
BR_ASIZE(MaterialLoadEntries),
MaterialLoadEntries,
};
br_uint_32 BR_PUBLIC_ENTRY BrMaterialLoadMany(char *filename,br_material **materials,br_uint_16 num)
{
br_datafile *df;
int count;
int r;
df = DfOpen(filename,0);
if(df == NULL)
return 0;
for (count=0; count<num; ) {
r = DfChunksInterpret(df, &MaterialLoadTable);
if(DfTopType() == DFST_MATERIAL)
materials[count++] = DfPop(DFST_MATERIAL,0);
if(r==0)
break;
}
DfClose(df);
return count;
}
/*
* Save a set of materials to the named file.
*
* if materials == NULL, then all registered materials are saved
*/
STATIC br_uint_32 BR_CALLBACK WriteMaterial(br_material *mp, br_datafile *df)
{
/*
* Write base material structure
*/
FopWrite_MATERIAL(df, mp);
/*
* Write out any references to pixelmaps
*/
if(mp->colour_map)
FopWrite_PIXELMAP_REF(df,FID_COLOUR_MAP_REF,mp->colour_map);
if(mp->index_shade)
FopWrite_PIXELMAP_REF(df,FID_INDEX_SHADE_REF,mp->index_shade);
if(mp->index_blend)
FopWrite_PIXELMAP_REF(df,FID_INDEX_BLEND_REF,mp->index_blend);
if(mp->screendoor)
FopWrite_PIXELMAP_REF(df,FID_SCREENDOOR_REF,mp->screendoor);
FopWrite_END(df);
return 0;
}
br_uint_32 BR_PUBLIC_ENTRY BrMaterialSaveMany(char *filename,br_material **materials,br_uint_16 num)
{
br_datafile *df;
int i,count;
/*
* Open file and write header
*/
df = DfOpen(filename,1);
if(df == NULL)
return 0;
FopWrite_FILE_INFO(df,FILE_TYPE_MATERIAL);
if(materials) {
for(i=0; i<num; i++)
WriteMaterial(materials[i],df);
count = num;
} else {
BrMaterialEnum(NULL,(br_material_enum_cbfn *)WriteMaterial,df);
count = BrMaterialCount(NULL);
}
DfClose(df);
return count;
}
/*
* Load a group of pixelmaps from a file
*/
STATIC br_chunks_table_entry PixelmapLoadEntries[] = {
{FID_END, 0,FopRead_END},
{FID_PIXELMAP, 0,FopRead_PIXELMAP},
{FID_PIXELS, 0,FopRead_PIXELS},
{FID_ADD_MAP, 0,FopRead_ADD_MAP},
};
STATIC br_chunks_table PixelmapLoadTable = {
BR_ASIZE(PixelmapLoadEntries),
PixelmapLoadEntries,
};
br_uint_32 BR_PUBLIC_ENTRY BrPixelmapLoadMany(char *filename,br_pixelmap **pixelmaps,br_uint_16 num)
{
br_datafile *df;
int count;
int r;
df = DfOpen(filename,0);
if(df == NULL)
return 0;
for (count=0; count<num; ) {
r = DfChunksInterpret(df,&PixelmapLoadTable);
if(DfTopType() == DFST_PIXELMAP)
pixelmaps[count++] = DfPop(DFST_PIXELMAP,0);
if(r==0)
break;
}
DfClose(df);
return count;
}
/*
* Save a group of pixelmaps to a file
*/
STATIC int WritePixelmap(br_pixelmap *pp, br_datafile *df)
{
ASSERT(!(pp->flags & BR_PMF_NO_ACCESS));
/*
* Write base pixelmap structure
*/
FopWrite_PIXELMAP(df,pp);
/*
* Write any palette
*/
if(pp->map) {
WritePixelmap(pp->map,df);
FopWrite_ADD_MAP(df);
}
/*
* Write pixel data
*/
FopWrite_PIXELS(df,pp);
return 0;
}
br_uint_32 BR_PUBLIC_ENTRY BrPixelmapSaveMany(char *filename,br_pixelmap **pixelmaps,br_uint_16 num)
{
br_datafile *df;
int i;
ASSERT(filename != NULL);
ASSERT(pixelmaps != NULL);
/*
* Open file and write header
*/
df = DfOpen(filename,1);
if(df == NULL)
return 0;
FopWrite_FILE_INFO(df,FILE_TYPE_PIXELMAP);
for(i=0; i<num; i++) {
WritePixelmap(pixelmaps[i],df);
FopWrite_END(df);
}
DfClose(df);
return num;
}
br_model * BR_PUBLIC_ENTRY BrModelLoad(char *filename)
{
br_model *ptr;
return (BrModelLoadMany(filename,&ptr,1) != 1)?NULL:ptr;
}
br_uint_32 BR_PUBLIC_ENTRY BrModelSave(char *filename, br_model *ptr)
{
return BrModelSaveMany(filename,&ptr,1);
}
br_material * BR_PUBLIC_ENTRY BrMaterialLoad(char *filename)
{
br_material *ptr;
return (BrMaterialLoadMany(filename,&ptr,1) != 1)?NULL:ptr;
}
br_uint_32 BR_PUBLIC_ENTRY BrMaterialSave(char *filename, br_material *ptr)
{
return BrMaterialSaveMany(filename,&ptr,1);
}
br_pixelmap * BR_PUBLIC_ENTRY BrPixelmapLoad(char *filename)
{
br_pixelmap *ptr;
return (BrPixelmapLoadMany(filename,&ptr,1) != 1)?NULL:ptr;
}
br_uint_32 BR_PUBLIC_ENTRY BrPixelmapSave(char *filename, br_pixelmap *ptr)
{
return BrPixelmapSaveMany(filename,&ptr,1);
}
br_actor * BR_PUBLIC_ENTRY BrActorLoad(char *filename)
{
br_actor *ptr;
return (BrActorLoadMany(filename,&ptr,1) != 1)?NULL:ptr;
}
br_uint_32 BR_PUBLIC_ENTRY BrActorSave(char *filename, br_actor *ptr)
{
return BrActorSaveMany(filename,&ptr,1);
}