#include #include #include #include #include "dpltypes.h" #include "dpl.h" #include "dpl_load.h" /*{{{ banner*/ /* ************************************************** Copyright DIVISION Limited (c) 1994 All rights reserved File : bizread.c Project : dpl interface host / platform independent section Author : PJA Date : 26/07/94 Function: Implements the b2z file reader for the dpl interface READ THE V2Z FILE FORMAT FOR DETAILS History : Rev 1.1, 26 / 07 / 1994 **************************** */ /*}}} */ /*{{{ some statics to aid the process*/ static int32 little_endian=1; static char material_name[256]; static char texture_name[256]; static char texmap_name[256]; static char ramp_name[256]; static char object_name[256]; static char patch_name[256]; static FILE *b2z_file=NULL; static float b2z_units=1.0f; static float b2z_scale=1.0f; static char buffer[(1024*8)*2]; static char *buff_p=NULL; static int buffered_bytes=0; static int buffer_read_start=0; static int b2z_ok = 1; static int blocks_read=0; static int b2z_open = 0; static dpl_TEXMAP *texmap=NULL; static dpl_TEXTURE *texture=NULL; static dpl_MATERIAL *material=NULL, *default_mtl=NULL, *f_mtl =NULL, *b_mtl =NULL, *of_mtl=NULL, *ob_mtl=NULL; static dpl_OBJECT *object=NULL; static dpl_LOD *lod=NULL; static dpl_GEOGROUP *geogroup=NULL; static dpl_GEOMETRY *geometry=NULL; static dpl_VERTEX_LIST *vertex_list=NULL; static dpl_CONNECTION_LIST *connection_list=NULL; static int32 draw_mode=0; dpl_superlist named_local_list; /*}}} */ static int b2z_trace = 0; #define trprintf if (b2z_trace) printf /*{{{ static void new_block ()*/ static void new_block () { if (b2z_open == 0) b2z_ok=0; if (b2z_ok == 0) return; /* copy whats left in buffer to beginning of buffer */ memcpy ( buffer, buff_p, buffered_bytes ); buff_p=buffer; if (fread ( &buffer[buffered_bytes], 1, 8*1024, b2z_file ) == 0) b2z_open=0; blocks_read++; buffered_bytes+=8*1024; trprintf ("new block, now buffered_bytes=%d\n", buffered_bytes ); } /*}}} */ /*{{{ buffer access with endian correction*/ /*{{{ static char get_char ()*/ static char get_char () { char v; if (buffered_bytes < 1) new_block(); v=*buff_p++; buffered_bytes--; return v; } /*}}} */ /*{{{ static char get_char ()*/ static char get_int8 () { int8 v; char *vp=(char *) &v; if (buffered_bytes < 1) new_block(); *vp=*buff_p++; buffered_bytes--; return v; } /*}}} */ /*{{{ static int16 get_int16 ( )*/ static int16 get_int16 ( ) { int16 v; char *cv=(char *) &v; if (buffered_bytes < 2) new_block(); if (little_endian) { cv[0]=*buff_p++; cv[1]=*buff_p++; buffered_bytes-=2; return v; } else { cv[1]=*buff_p++; cv[0]=*buff_p++; buffered_bytes-=2; return v; } } /*}}} */ /*{{{ static char *get_int32 ( char *b, int32 *v )*/ static int32 get_int32 () { int32 v; char *cv=(char *) &v; if (buffered_bytes < 4) new_block(); if (little_endian) { cv[0]=*buff_p++; cv[1]=*buff_p++; cv[2]=*buff_p++; cv[3]=*buff_p++; buffered_bytes-=4; return v; } else { cv[3]=*buff_p++; cv[2]=*buff_p++; cv[1]=*buff_p++; cv[0]=*buff_p++; buffered_bytes-=4; return v; } } /*}}} */ /*{{{ static float32 get_float32 ()*/ static float32 get_float32 () { float32 v; char *cv=(char *) &v; if (buffered_bytes < 4) new_block(); if (little_endian) { cv[0]=*buff_p++; cv[1]=*buff_p++; cv[2]=*buff_p++; cv[3]=*buff_p++; buffered_bytes-=4; return v; } else { cv[3]=*buff_p++; cv[2]=*buff_p++; cv[1]=*buff_p++; cv[0]=*buff_p++; buffered_bytes-=4; return v; } } /*}}} */ /*{{{ static void get_struct32 ( void *data, int n_words )*/ static void get_struct32 ( void *data, int n_words ) { char *cv=(char *) data; while (n_words) { n_words--; if (buffered_bytes < 4) new_block(); if (little_endian) { cv[0]=*buff_p++; cv[1]=*buff_p++; cv[2]=*buff_p++; cv[3]=*buff_p++; buffered_bytes-=4; cv+=4; } else { cv[3]=*buff_p++; cv[2]=*buff_p++; cv[1]=*buff_p++; cv[0]=*buff_p++; buffered_bytes-=4; cv+=4; } } } /*}}} */ /*{{{ static void get_string ( char *str, int32 length )*/ static void get_string ( char *str, int32 length ) { int8 l; int i; if (length == (-1)) { l=get_int8(); length=(int32) l; } for (i=0; i> 12) & 0xc) { case 0x8 : block_len=get_int32(); bytes+=4; break; case 0x4 : block_len=0xffff & get_int16(); bytes+=2; break; case 0x0 : block_len=0xff & get_int8(); bytes+=1; break; default : printf ("Unrecognised block header, exiting\n" ); b2z_ok=0; break; } trprintf ("block 0x%x of length %d bytes\n", block_hdr, block_len ); *hdr =block_hdr; *length=block_len; return bytes; } /*}}} */ /*{{{ static void skip_block ( int length )*/ static void skip_block ( int length ) { trprintf ("skip_block %d\n", length ); if (b2z_ok == 0) return; while (length > 2048) { skip_bytes(2048); length-=2048; } skip_bytes(length); } /*}}} */ /*{{{ static dpl_node *look_up ( dpl_type t, char *name, node_create_function *f )*/ static dpl_node *look_up ( dpl_type t, char *name, node_create_function f ) { dpl_node *n; trprintf ( "lookup %s\n", name ); if ((n = dpl_FindNamedTypedNode ( t, name )) == NULL) { trprintf ( "had to create it\n" ); n = f(); dpl_NameNode ( n, name ); } else trprintf ( "found it!\n" ); return n; } /*}}} */ /*{{{ defaultize ( dpl_MATERIAL *default_mtl )*/ static void defaultize ( dpl_MATERIAL *default_mtl ) { default_mtl->ambient[0]=1.0f; default_mtl->ambient[1]=0.0f; default_mtl->ambient[2]=0.0f; default_mtl->diffuse[0]=1.0f; default_mtl->diffuse[1]=0.0f; default_mtl->diffuse[2]=0.0f; default_mtl->specular[0]=0.0f; default_mtl->specular[1]=0.0f; default_mtl->specular[2]=0.0f; default_mtl->specular[3]=1.0f; default_mtl->emissive[0]=0.0f; default_mtl->emissive[1]=0.0f; default_mtl->emissive[2]=0.0f; default_mtl->ramp =NULL; default_mtl->texture=NULL; dpl_Flush ( default_mtl ); } /*}}} */ /*{{{ deal with multiple connection lists per pmesh*/ typedef int pre_connect[7]; static pre_connect *pre_connections=NULL; static int pre_connects=0; static pre_connect *grow_connections(int more) { int prev=pre_connects; pre_connect *new=(pre_connect *) malloc((prev+more)*sizeof(pre_connect)); trprintf ("grow %d connections\n", more ); if (pre_connections) { memcpy (new, pre_connections, prev*sizeof(pre_connect)); free(pre_connections); } pre_connects+=more; pre_connections=new; trprintf ("grew to %d connections\n", pre_connects ); return &new[prev]; } /*}}} */ /*{{{ static void read_vertices ( int32 n_vertices, int32 hdr )*/ static int normal_offset; static int texture_2doffset; static int texture_3doffset; static int color_offset; static int luminance_offset; static void read_vertices ( int32 floats_per_vertex, int32 n_vertices, int32 hdr ) { float this_vert[16]; int i, vix; dpl_VERTEX *vert; dpl_VERTEX_LIST *vl; trprintf ("read_vertices %d\n", n_vertices ); vl = vertex_list; vix = 0; vert = &vl->vertices[0]; for (i=0; inormcol[3]=1.0f; vert->texcoords[2]=1.0f; vert->position[0]=/* b2z_scale*b2z_units* */ this_vert[0]; vert->position[1]=/* b2z_scale*b2z_units* */ this_vert[1]; vert->position[2]=/* b2z_scale*b2z_units* */ this_vert[2]; if (normal_offset != (-1)) { /* move normal into place */ vert->normcol[0]=this_vert[normal_offset]; vert->normcol[1]=this_vert[normal_offset+1]; vert->normcol[2]=this_vert[normal_offset+2]; } if (texture_2doffset != (-1)) { /* move texture coords into place */ vert->texcoords[0]=this_vert[texture_2doffset]; vert->texcoords[1]=this_vert[texture_2doffset+1]; } if (texture_3doffset != (-1)) { /* move 3d texture coords into place */ vert->texcoords[0]=this_vert[texture_3doffset]; vert->texcoords[1]=this_vert[texture_3doffset+1]; vert->texcoords[2]=this_vert[texture_3doffset+2]; } if (color_offset != (-1)) { /* move cooked rgba values into place */ vert->normcol[0]=this_vert[color_offset]; vert->normcol[1]=this_vert[color_offset+1]; vert->normcol[2]=this_vert[color_offset+2]; vert->normcol[3]=this_vert[color_offset+3]; } if (luminance_offset != (-1)) { /* move cooked llla values into place */ vert->normcol[0]=this_vert[luminance_offset]; vert->normcol[1]=this_vert[luminance_offset]; vert->normcol[2]=this_vert[luminance_offset]; vert->normcol[3]=this_vert[luminance_offset+1]; } /*}}} */ vix++; if (vix==DPL_VERTICES_PER_BLOCK) { vix=0; vl=vl->next; if (vl) vert=&vl->vertices[0]; } else vert++; } } /*}}} */ /*{{{ static int parse_vertices ( int32 length )*/ static int parse_vertices ( int32 length, dpl_geo_type geotype ) { int32 bytes=0, hdr, len, n_connections, total_connections, v_per_c, i; dpl_CONNECTION *conn; dpl_CONNECTION_LIST *cl; pre_connect *pc; int cix=0; int pmesh_vert=0, pmesh_conn=0; while (b2z_ok && (bytes < length)) { int32 f_per_vertex, n_floats, n_vertices, verts_per_poly; normal_offset = -1; texture_2doffset = -1; texture_3doffset = -1; color_offset = -1; luminance_offset = -1; bytes+=b2z_block(&hdr, &len ); if (b2z_ok == 0) return 0; bytes+=len; n_floats=len>>2; switch ( hdr ) { /*{{{ pmesh triangle connectivity*/ case 0x0047 : case 0x4047 : case 0x8047 : trprintf ( "PMESH TRIANGLE CONNECTIVITY len=%d\n", len ); n_connections=len/12; pc=grow_connections(n_connections); for (i=0; iconnections[0]; cix=0; pc=pre_connections; for (i=0; in_verts=(*pc)[0]; trprintf ( "n_verts=%d\n", conn->n_verts ); for (j=0; j<(*pc)[0]; j++ ) { trprintf ( "vertex %d %d\n", j, (*pc)[j+1] ); conn->indices[j]=(*pc)[j+1]; } pc++; cix++; if (cix==DPL_CONNECTIONS_PER_BLOCK) { cix=0; cl=cl->next; if (cl) conn=&cl->connections[0]; } else conn++; } free(pre_connections); pre_connections=NULL; pre_connects=0; trprintf ("SETGEOMVERTICES WITH VERTEX AND CONNECTIONS\n" ); dpl_SetGeometryVertices ( geometry, vertex_list, connection_list ); trprintf ("did the setgeom thing\n" ); } } else { if (pmesh_vert) { pmesh_vert=0; dpl_SetGeometryVertices ( geometry, vertex_list, NULL ); } } /* } */ return 1; } /*}}} */ /*{{{ static int parse_patch ( int32 length )*/ static int parse_patch ( int32 length ) { int32 bytes=0, hdr, len; char c, *name_p=patch_name; int8 type; f_mtl=of_mtl; b_mtl=ob_mtl; if (lod == NULL) { lod=dpl_NewLod(); dpl_AddLodToObject ( object, lod ); } geogroup=dpl_NewGeogroup(); dpl_AddGeogroupToLod ( lod, geogroup ); geogroup->draw_mode=draw_mode; /* inherit from object */ while (b2z_ok && (bytes < length)) { bytes+=b2z_block(&hdr, &len ); if (b2z_ok == 0) return 0; bytes+=len; switch ( hdr ) { /*{{{ name*/ case 0x2008 : trprintf ( "PATCH NAME\n" ); while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("patch %s\n", patch_name ); break; /*}}} */ /*{{{ f_mtl*/ case 0x2030 : trprintf ( "FRONT MATERIAL\n" ); type=get_int8(); if (type == 0) f_mtl=NULL; else if (type == 2) f_mtl=default_mtl; else if (type==1) { name_p=material_name; while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("material %s\n", material_name ); f_mtl = (dpl_MATERIAL *) look_up ( dpl_type_material, material_name, (node_create_function) dpl_NewMaterial ); name_p=patch_name; } break; /*}}} */ /*{{{ b_mtl*/ case 0x2031 : trprintf ( "BACK MATERIAL\n" ); type=get_int8(); if (type == 0) b_mtl=NULL; else if (type == 2) b_mtl=default_mtl; else if (type==1) { name_p=material_name; while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("material %s\n", material_name ); b_mtl = (dpl_MATERIAL *) look_up ( dpl_type_material, material_name, (node_create_function) dpl_NewMaterial ); name_p=patch_name; } else if (type == 3) b_mtl=f_mtl; break; /*}}} */ /*{{{ plane*/ case 0x2032 : trprintf ( "PLANE\n" ); skip_block(len); break; /*}}} */ /*{{{ draw_mode*/ case 0x2033 : trprintf ( "DRAW MODE\n" ); skip_block(len); break; /*}}} */ /*{{{ decal*/ case 0x2034 : trprintf ( "DECAL\n" ); skip_block(len); break; /*}}} */ /*{{{ facet*/ case 0x2035 : trprintf ( "FACET\n" ); skip_block(len); break; /*}}} */ /*{{{ vertex format*/ case 0x2036 : trprintf ( "VERTEX FORMAT\n" ); geogroup->draw_mode=(int32) get_int8(); trprintf ("vertex format 0x%x\n", geogroup->draw_mode ); break; /*}}} */ /*{{{ voodoo*/ case 0x2037 : trprintf ( "SPECIAL VOODOO\n" ); skip_block(len); break; /*}}} */ /*{{{ polygon*/ case 0x4043 : case 0x8043 : case 0x0043 : trprintf ( "POLYGON\n" ); parse_vertices ( len, dpl_g_type_polystrip ); break; /*}}} */ /*{{{ tristrip*/ case 0x4044 : case 0x8044 : case 0x0044 : trprintf ( "TRISTRIP\n" ); parse_vertices ( len, dpl_g_type_tristrip ); break; /*}}} */ /*{{{ polystrip*/ case 0x4045 : case 0x8045 : case 0x0045 : trprintf ( "POLYSTRIP\n" ); parse_vertices ( len, dpl_g_type_polystrip ); break; /*}}} */ /*{{{ pmesh*/ case 0x4046 : case 0x8046 : case 0x0046 : trprintf ( "PMESH\n" ); parse_vertices ( len, dpl_g_type_pmesh ); break; /*}}} */ /*{{{ sphere NOT IMPLEMENTED*/ case 0x4048 : case 0x8048 : case 0x0048 : trprintf ( "SPHERE\n" ); skip_block(len); break; /*}}} */ /*{{{ line NOT IMPLEMENTED*/ case 0x404a : case 0x804a : case 0x004a : trprintf ( "LINE\n" ); skip_block(len); break; /*}}} */ /*{{{ text NOT IMPLEMENTED*/ case 0x404b : case 0x804b : case 0x004b : trprintf ( "TEXT\n" ); skip_block(len); break; /*}}} */ default : printf ( "Unexpected header 0x%x in patch\n", hdr ); skip_block(len); break; } } geogroup->f_material=f_mtl; geogroup->b_material=b_mtl; /* and the Bound flushes the geogroup */ dpl_BoundGeogroup ( geogroup ); dpl_BoundLod ( lod ); return 1; } /*}}} */ /*{{{ static int parse_lod ( int32 length )*/ static int parse_lod ( int32 length ) { lod=dpl_NewLod(); dpl_AddLodToObject ( object, lod ); skip_block(length); return 1; } /*}}} */ /*{{{ static int parse_object ( int32 length )*/ static int parse_object ( int32 length ) { int32 bytes=0, hdr, len; int8 type; char c, *name_p=object_name; of_mtl=NULL; ob_mtl=NULL; if (object == NULL) object=dpl_NewObject(); *name_p=0x0; while (b2z_ok && (bytes < length)) { bytes+=b2z_block(&hdr, &len ); if (b2z_ok == 0) return 0; switch ( hdr ) { /*{{{ name*/ case 0x2008 : trprintf ( "OBJECT NAME\n" ); while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("object %s\n", object_name ); break; /*}}} */ /*{{{ f_mtl*/ case 0x2030 : trprintf ( "FRONT MATERIAL\n" ); type=get_int8(); if (type == 0) of_mtl=NULL; else if (type == 2) of_mtl=default_mtl; else if (type==1) { name_p=material_name; while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("material %s\n", material_name ); of_mtl = (dpl_MATERIAL *) look_up ( dpl_type_material, material_name, (node_create_function) dpl_NewMaterial ); name_p=object_name; } break; /*}}} */ /*{{{ b_mtl*/ case 0x2031 : trprintf ( "BACK MATERIAL\n" ); type=get_int8(); if (type == 0) ob_mtl=NULL; else if (type == 2) ob_mtl=default_mtl; else if (type==1) { name_p=material_name; while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("material %s\n", material_name ); ob_mtl = (dpl_MATERIAL *) look_up ( dpl_type_material, material_name, (node_create_function) dpl_NewMaterial ); name_p=object_name; } else if (type == 3) ob_mtl=of_mtl; break; /*}}} */ /*{{{ plane*/ case 0x2032 : trprintf ( "PLANE\n" ); skip_block(len); break; /*}}} */ /*{{{ draw mode*/ case 0x2033 : trprintf ( "DRAW MODE\n" ); skip_block(len); break; /*}}} */ /*{{{ decal*/ case 0x2034 : trprintf ( "DECAL\n" ); skip_block(len); break; /*}}} */ /*{{{ facet*/ case 0x2035 : trprintf ( "FACET\n" ); skip_block(len); break; /*}}} */ /*{{{ vertex format*/ case 0x2036 : trprintf ( "VERTEX FORMAT\n" ); draw_mode=(int32) get_int8(); break; /*}}} */ /*{{{ special*/ case 0x2037 : trprintf ( "SPECIAL VOODOO\n" ); skip_block(len); break; /*}}} */ /*{{{ patch*/ case 0x4042 : case 0x8042 : case 0x0042 : trprintf ( "PATCH\n" ); parse_patch(len); break; /*}}} */ /*{{{ lod*/ case 0x4041 : case 0x8041 : case 0x0041 : trprintf ( "LOD\n" ); parse_lod(len); break; /*}}} */ /*{{{ comment*/ case 0x0000 : case 0x4000 : case 0x8000 : case 0x0001 : case 0x4001 : case 0x8001 : case 0x2000 : case 0x6000 : case 0xa000 : trprintf ( "COMMENT\n" ); skip_block(len); break; /*}}} */ default : printf ( "Unexpected header 0x%x in object, bytes=%d length=%d\n", hdr, bytes, length ); skip_block(len); break; } bytes+=len; } return 1; } /*}}} */ /*{{{ static int parse_texture ( int32 length )*/ static int parse_texture ( int32 length ) { /* always create a new texture, but try to chain it to an existing texmap */ dpl_TEXTURE *real_tex; int32 bilinear, bytes=0, hdr, len; int8 scope=0, minify=0, magnify=0, wrap_u=0, wrap_v=0, alpha=0, mode; char c, *full_name, *name_p=texture_name; *name_p=0x0; while (b2z_ok && (bytes < length)) { bytes+=b2z_block(&hdr, &len ); if (b2z_ok == 0) return 0; switch ( hdr ) { /*{{{ name*/ case 0x2008 : trprintf ( "TEXTURE NAME\n" ); name_p=texture_name; while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("texture %s\n", texture_name ); break; /*}}} */ /*{{{ scope*/ case 0x200a : trprintf ( "SCOPE\n" ); scope=get_int8(); trprintf ( "SCOPE = 0x%x\n", scope ); break; /*}}} */ /*{{{ file name*/ case 0x0011 : case 0x4011 : case 0x8011 : trprintf ( "TEXTURE FILE NAME\n" ); name_p=texmap_name; while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("map name %s\n", texmap_name ); break; /*}}} */ /*{{{ minify*/ case 0x0012 : trprintf ( "MINIFY\n" ); minify=get_int8(); trprintf ( "MODE = 0x%x\n", minify ); break; /*}}} */ /*{{{ magnify*/ case 0x0013 : trprintf ( "MAGNIFY\n" ); magnify=get_int8(); trprintf ( "MODE = 0x%x\n", magnify ); break; /*}}} */ /*{{{ alpha*/ case 0x0014 : trprintf ( "ALPHA\n" ); alpha=get_int8(); trprintf ( "MODE = 0x%x\n", alpha ); break; /*}}} */ /*{{{ wrap u*/ case 0x0015 : trprintf ( "WRAP_U\n" ); wrap_u=get_int8(); trprintf ( "MODE = 0x%x\n", wrap_u ); break; /*}}} */ /*{{{ wrap v*/ case 0x0016 : trprintf ( "WRAP_V\n" ); wrap_v=get_int8(); trprintf ( "MODE = 0x%x\n", wrap_v ); break; /*}}} */ /*{{{ detail*/ case 0x0017 : trprintf ( "DETAIL\n" ); mode=get_int8(); trprintf ( "MODE = 0x%x\n", mode ); skip_block(len-1); break; /*}}} */ default : printf ( "Unexpected header 0x%x in texture, bytes=%d length=%d\n", hdr, bytes, length ); skip_block(len); break; } bytes+=len; } texmap = (dpl_TEXMAP *) dpl_FindNamedTypedNode ( dpl_type_texmap, texmap_name ); if (texmap == NULL) { /*{{{ load up the texture map*/ /* first try to load the texture */ if ((magnify == 1) || (magnify == 0)) bilinear=0; else bilinear=1; texmap = dpl_NewTexMap (); dpl_NameNode ( (dpl_node *) texmap, texmap_name ); texmap->bits_per_texel=32; /* sorry about this hack */ full_name=dpl_FindTextureFile ( texmap_name, NULL ); if (load_svt((dpl_node *) texmap, full_name )) { int *map_texels=texmap->texels; /* this is HORRIBLE - i will fix it later....... */ texmap->texels=NULL; trprintf ("went load_svt, have u_size %d v_size %d\n", texmap->u_size, texmap->v_size ); dpl_SetTexmapTexels ( texmap, map_texels, texmap->u_size, texmap->v_size, bilinear ); /* and the call to SetTexMapTexels has flushed the node */ } /*}}} */ } real_tex = (dpl_TEXTURE *) look_up ( dpl_type_texture, texture_name, (node_create_function) dpl_NewTexture ); real_tex->minify = minify; real_tex->magnify = magnify; real_tex->alpha = alpha; real_tex->wrap_u = wrap_u; real_tex->wrap_v = wrap_v; real_tex->texmap = texmap; dpl_Flush(real_tex); return 1; } /*}}} */ /*{{{ static int parse_material ( int32 length )*/ static int parse_material ( int32 length ) { dpl_MATERIAL local_mtl, *real_mtl; dpl_TEXTURE *mtl_texture=NULL; dpl_RAMP *mtl_ramp=NULL; int32 bytes=0, hdr, len; int8 scope, mode; char c, *name_p=material_name; float32 r, g, b, pse; *name_p=0x0; /*{{{ init local_material*/ local_mtl.ambient[0]=1.0f; local_mtl.ambient[1]=1.0f; local_mtl.ambient[2]=1.0f; local_mtl.diffuse[0]=1.0f; local_mtl.diffuse[1]=1.0f; local_mtl.diffuse[2]=1.0f; local_mtl.emissive[0]=1.0f; local_mtl.emissive[1]=1.0f; local_mtl.emissive[2]=1.0f; local_mtl.specular[0]=0.0f; local_mtl.specular[1]=0.0f; local_mtl.specular[2]=0.0f; local_mtl.specular[3]=0.0f; local_mtl.opacity[0]=1.0f; local_mtl.opacity[1]=1.0f; local_mtl.opacity[2]=1.0f; /*}}} */ while (b2z_ok && (bytes < length)) { bytes+=b2z_block(&hdr, &len ); if (b2z_ok == 0) return 0; switch ( hdr ) { /*{{{ name*/ case 0x2008 : trprintf ( "MATERIAL NAME\n" ); while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("material %s\n", material_name ); break; /*}}} */ /*{{{ scope*/ case 0x200a : trprintf ( "SCOPE\n" ); scope=get_int8(); trprintf ( "SCOPE = 0x%x\n", scope ); break; /*}}} */ /*{{{ texture*/ case 0x0021 : trprintf ( "TEXTURE TYPE NAME\n" ); mode=get_int8(); trprintf ( " MODE = 0x%x\n", mode ); if (mode == 0) texture=NULL; else if (mode == 1) texture=NULL; else if (mode == 2) { name_p=texture_name; while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("texture %s\n", texture_name ); mtl_texture = (dpl_TEXTURE *) look_up ( dpl_type_texture, texture_name, (node_create_function) dpl_NewTexture ); name_p=material_name; } break; /*}}} */ /*{{{ environment*/ case 0x0022 : trprintf ( "ENVIRONMENT\n" ); skip_block(len); break; /*}}} */ /*{{{ ambient*/ case 0x0023 : trprintf ( "AMBIENT\n" ); local_mtl.ambient[0]=get_float32(); local_mtl.ambient[1]=get_float32(); local_mtl.ambient[2]=get_float32(); trprintf ( "is %f %f %f\n", local_mtl.ambient[0], local_mtl.ambient[1], local_mtl.ambient[2] ); break; /*}}} */ /*{{{ diffuse*/ case 0x0024 : trprintf ( "DIFFUSE\n" ); local_mtl.diffuse[0]=get_float32(); local_mtl.diffuse[1]=get_float32(); local_mtl.diffuse[2]=get_float32(); trprintf ( "is %f %f %f\n", local_mtl.diffuse[0], local_mtl.diffuse[1], local_mtl.diffuse[2] ); break; /*}}} */ /*{{{ specular*/ case 0x0025 : trprintf ( "SPECULAR\n" ); local_mtl.specular[0]=get_float32(); local_mtl.specular[1]=get_float32(); local_mtl.specular[2]=get_float32(); local_mtl.specular[3]=get_float32(); trprintf ( "is %f %f %f\n", local_mtl.specular[0], local_mtl.specular[1], local_mtl.specular[2] ); break; /*}}} */ /*{{{ emissive*/ case 0x0026 : trprintf ( "EMISSIVE\n" ); local_mtl.emissive[0]=get_float32(); local_mtl.emissive[1]=get_float32(); local_mtl.emissive[2]=get_float32(); trprintf ( "is %f %f %f\n", local_mtl.emissive[0], local_mtl.emissive[1], local_mtl.emissive[2] ); break; /*}}} */ /*{{{ opacity*/ case 0x0027 : trprintf ( "OPACITY\n" ); local_mtl.opacity[0]=get_float32(); local_mtl.opacity[1]=get_float32(); local_mtl.opacity[2]=get_float32(); break; /*}}} */ /*{{{ ramp*/ case 0x0028 : trprintf ( "RAMP\n" ); name_p=ramp_name; while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("ramp %s\n", texture_name ); mtl_ramp = (dpl_RAMP *) look_up ( dpl_type_ramp, ramp_name, (node_create_function) dpl_NewRamp ); name_p=material_name; break; /*}}} */ default : printf ( "Unexpected header 0x%x in material, bytes=%d length=%d\n", hdr, bytes, length ); skip_block(len); break; } bytes+=len; } real_mtl = (dpl_MATERIAL *) look_up ( dpl_type_material, material_name, (node_create_function) dpl_NewMaterial ); memcpy ( real_mtl->emissive, local_mtl.emissive, 3*sizeof(float32)); memcpy ( real_mtl->ambient, local_mtl.ambient, 3*sizeof(float32)); memcpy ( real_mtl->diffuse, local_mtl.diffuse, 3*sizeof(float32)); memcpy ( real_mtl->opacity, local_mtl.opacity, 3*sizeof(float32)); memcpy ( real_mtl->specular, local_mtl.specular, 4*sizeof(float32)); real_mtl->texture=mtl_texture; real_mtl->ramp=mtl_ramp; dpl_Flush ( real_mtl ); return 1; } /*}}} */ /*{{{ static int parse_ramp ( int32 length )*/ static int parse_ramp ( int32 length ) { dpl_RAMP local_ramp, *real_ramp; dpl_node *node; int32 bytes=0, hdr, len; int8 scope, mode; float32 r, g, b; char c, *name_p=material_name; *name_p=0x0; while (b2z_ok && (bytes < length)) { bytes+=b2z_block(&hdr, &len ); if (b2z_ok == 0) return 0; switch ( hdr ) { /*{{{ name*/ case 0x2008 : trprintf ( "RAMP NAME\n" ); while (c=get_char()) *name_p++=c; *name_p++=0x0; trprintf ("ramp %s\n", ramp_name ); break; /*}}} */ /*{{{ scope*/ case 0x200a : trprintf ( "SCOPE\n" ); scope=get_int8(); trprintf ( "SCOPE = 0x%x\n", scope ); break; /*}}} */ /*{{{ ramp data*/ case 0x0031 : trprintf ( "RAMP DATA\n" ); local_ramp.color0[0]=get_float32(); local_ramp.color0[1]=get_float32(); local_ramp.color0[2]=get_float32(); local_ramp.color1[0]=get_float32(); local_ramp.color1[1]=get_float32(); local_ramp.color1[2]=get_float32(); break; /*}}} */ default : printf ( "Unexpected header 0x%x in ramp, bytes=%d length=%d\n", hdr, bytes, length ); skip_block(len); break; } bytes+=len; } real_ramp = (dpl_RAMP *) look_up ( dpl_type_ramp, ramp_name, (node_create_function) dpl_NewRamp ); memcpy ( real_ramp->color0, local_ramp.color0, 3*sizeof(float)); memcpy ( real_ramp->color1, local_ramp.color1, 3*sizeof(float)); dpl_Flush ( real_ramp ); return 1; } /*}}} */ /*{{{ static int parse_header ( int32 length )*/ static int parse_header ( int32 length ) { int32 bytes=0, hdr, len; int8 precision, unit; while (b2z_ok && (bytes < length)) { bytes+=b2z_block(&hdr, &len ); if (b2z_ok == 0) return 0; bytes+=len; switch ( hdr ) { /*{{{ version*/ case 0x2002 : trprintf ( "VERSION\n" ); skip_block(len); break; /*}}} */ /*{{{ date*/ case 0x2003 : trprintf ( "DATE\n" ); skip_block(len); break; /*}}} */ /*{{{ time*/ case 0x2004 : trprintf ( "TIME\n" ); skip_block(len); break; /*}}} */ /*{{{ scale*/ case 0x2005 : trprintf ( "SCALE\n" ); b2z_scale=get_float32(); break; /*}}} */ /*{{{ precision*/ case 0x2006 : trprintf ( "PRECISION\n" ); precision=get_int8(); if (precision != 0) { printf ("Error, cannot process double-precision files\n" ); b2z_ok=0; return 0; } break; /*}}} */ /*{{{ filetype*/ case 0x2007 : trprintf ( "FILETYPE\n" ); skip_block(len); break; /*}}} */ /*{{{ unit*/ case 0x2009 : trprintf ( "UNIT\n" ); unit=get_int8(); if (unit == 0x0) b2z_units=1.0f; else if (unit == 0x1) b2z_units=1.0f / 25.4f; else { printf ("Error, unrecognized units 0x%x\n", unit ); b2z_ok=0; return 0; } break; /*}}} */ default : printf ("Unrecognized block 0x%x in header\n", hdr ); skip_block(len); break; } } trprintf ("Exiting parse_header\n" ); return 1; } /*}}} */ /*{{{ static void forget_local_names ()*/ static void forget_local_names () { /* should walk down named_local_list and forget all the names */ return; } /*}}} */ /*{{{ dpl_OBJECT *b2zread ( char *f )*/ dpl_OBJECT * b2zread ( dpl_OBJECT *param_object, char *f ) { FILE *fp=fopen(f, "rb" ); char biz_id[16]; /* determine endian-ness */ little_endian=0; *((char *) &little_endian)=0x1; little_endian&=0x1; if (fp==NULL) { printf ("Failed to open file %s\n", f ); return NULL; } else { /*{{{ do some inits*/ b2z_open = 1; b2z_file = fp; buff_p = NULL; buffered_bytes = 0; buffer_read_start= 0; little_endian = 1; b2z_ok = 1; blocks_read = 0; texmap = NULL; texture = NULL; material = NULL; object = param_object; lod = NULL; geogroup = NULL; geometry = NULL; vertex_list = NULL; connection_list = NULL; named_local_list.tail=NULL; named_local_list.head=NULL; named_local_list.last_accessed=NULL; /*}}} */ get_string ( biz_id, 8 ); if (strcmp ( biz_id, "DIV-BIZ2") != 0) { printf ( "Not a valid b2z file\n" ); fclose(fp); return NULL; } else { int32 block_hdr; int32 length; /*{{{ create a default material*/ default_mtl = (dpl_MATERIAL *) look_up ( dpl_type_material, "DEFAULT", (node_create_function) dpl_NewMaterial ); defaultize ( default_mtl ); /*}}} */ while (b2z_ok) { b2z_block ( &block_hdr, &length ); switch (block_hdr & 0xfff) { /*{{{ trailer*/ case 0x005 : trprintf ("Trailer, exiting\n" ); fclose(fp); if (b2z_ok) { forget_local_names(); return object; } else { forget_local_names(); return NULL; } break; /*}}} */ /*{{{ header*/ case 0x003 : trprintf ("Header\n" ); parse_header ( length ); break; /*}}} */ /*{{{ comment*/ case 0x004 : trprintf ("Comment\n" ); skip_block ( length ); break; /*}}} */ /*{{{ texture*/ case 0x010 : trprintf ("Texture\n" ); parse_texture ( length ); break; /*}}} */ /*{{{ material*/ case 0x020 : trprintf ("Material\n" ); parse_material ( length ); break; /*}}} */ /*{{{ ramp*/ case 0x030 : trprintf ("Ramp\n" ); parse_ramp ( length ); break; /*}}} */ /*{{{ object*/ case 0x040 : trprintf ("Object\n" ); parse_object ( length ); break; /*}}} */ default : skip_block ( length ); printf ("ERROR : unexpected tag 0x%x\n", block_hdr ); fclose(fp); return NULL; break; } } if (b2z_ok) { fclose(fp); return object; } else return NULL; } } } /*}}} */