/* * 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 #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; ttype = 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; countfaces) { 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; it.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; icolour_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; iflags & 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