/* File pazread Phil Atkin (c) Division Ltd. 1991 */ /*{{{ includes*/ #include #include #include #include #include #include #include #include "pazpl5.h" #include "viz.h" #include "macros.h" #include "geometry.h" #include "lighting.h" #include "pazstore.h" #include "material.h" /*}}} */ #define NAMETABLE_SIZE 64 #define STRING_SIZE 256 /*{{{ error handling*/ static int __lineNo=1; stream_open open_fn=(stream_open) fopen; stream_gets gets_fn=(stream_gets) fgets; stream_close close_fn=(stream_close) fclose; static OBJECT *obj; char errmess[STRING_SIZE]; static jmp_buf bob_beamon; static void mexico_68 ( char *fmt, ... ) { char *e=&errmess[0]; va_list args; e+=sprintf(errmess,"ERROR : " ); va_start(args, fmt); vsprintf(e,fmt, args ); va_end(args); obj=NULL; longjmp(bob_beamon, 1); } /*}}} */ /*{{{ variables*/ static token curr_token; static char string [STRING_SIZE]; static char *curr_pos=NULL, *remainder; static char *spaces=" \t\r\n", *spacecomma=", \t\r\n"; static name_entry name_table[NAMETABLE_SIZE]; static surface default_surf, obj_surf, patch_surf; static int patches=0, tesselations=0, triangles=0, points=0; /*}}} */ #if 0 /*{{{ housekeeping*/ #define nameof(v) name_table[(v)].name #define valof(v) name_table[(v)].type #define set_name(n,s,v) { nameof(n)=s; valof(n)=(v); } static void init () { int i; __lineNo = 1; errmess[0]='\0'; curr_pos=NULL; patches=0; tesselations=0; triangles=0; points=0; default_surf.COOKED = 0; default_surf.NORMALS = 0; default_surf.TEXTURE = 0; strcpy ( &default_surf.fmaterial[0], "immaterial" ); default_surf.bmaterial[0]=0x0; for (i=0; iname=strip_tail(strip_head(curr_pos)); */ /* t->name=strip_tail(curr_pos); */ /* printf ("get token returning %s\n", curr_pos ); */ t->name=curr_pos; t->id=token_type(t->name); return 1; } /*}}} */ /*{{{ static int nexttoken ( FILE *fp, char *sep )*/ static int nexttoken ( FILE *fp, char *sep ) { int read=1; tokptr t=&curr_token; while (read) { if (next_token(fp, t, sep ) == 0) return 0; while (t->id==tok_comment) { while (t->id!=tok_endcomment) if (next_token (fp, t, spaces ) == 0) return 0; if (next_token(fp, t, sep ) == 0) return 0; } if (strlen(t->name)!=0) read=0; } return 1; } /*}}} */ /*{{{ static int checkfor ( FILE *fp, int type )*/ static int checkfor ( FILE *fp, int type ) { if (nexttoken(fp, sep) == 0) return 0; if (curr_token.id!=type) expected ( nameof(type), curr_token.name); return 1; } /*}}} */ /*{{{ static int checktwo ( FILE *fp, int typeA, int typeB )*/ static int checktwo ( FILE *fp, int typeA, int typeB ) { tokptr t=&curr_token; if (nexttoken(fp, sep) == 0) return (-1); if ((t->id!=typeA)&(t->id!=typeB)) { sprintf ( errmess, "Expected %s or %s, found %s at line %d\n", nameof(typeA), nameof(typeB), t->name, __lineNo, NULL ); return (-1); } return(t->id); } /*}}} */ /*{{{ static int check ( FILE *fp, char *fmt, ... )*/ static int check ( FILE *fp, char *fmt, ... ) { int i, tptr=0; int types [16]; char *p; tokptr t=&curr_token; va_list ap; /* first process the va_arg list */ va_start (ap, fmt); for (p=fmt; *p; p++) { if (*p=='%') { p++; switch(*p) { case 'd' : types[tptr++]=va_arg(ap, int ); break; case '\0': default : { sprintf ( errmess, "Bad arguments to check\n", NULL ); return -1; } } } } va_end(ap); if (nexttoken(fp, sep) == 0) return -1; for (i=0; iid==types[i]) return(types[i]); } sprintf ( errmess, "Unexpected token %s at line %d\n", t->name, __lineNo, NULL ); return -1; } /*}}} */ /*}}} */ #endif float lod_switch_in, lod_switch_out; /*{{{ static void set_surface ( PATCH *p, surfptr surf )*/ static void set_surface ( PATCH *p, surfptr surf ) { strcpy ( p->fmaterial_name, &surf->fmaterial[0] ); strcpy ( p->bmaterial_name, &surf->bmaterial[0] ); } /*}}} */ /*{{{ static int planar ( VSTRIP *strip )*/ static int planar ( VSTRIP *strip ) { VERTEX *v=strip->head; float a, b, c, d; int i; a=v->planeEqn[0]; b=v->planeEqn[1]; c=v->planeEqn[2]; d=v->planeEqn[3]; for (i=1; ivertex_count; i++ ) { float aa, bb, cc, dd; aa=v->planeEqn[0] - a; bb=v->planeEqn[1] - b; cc=v->planeEqn[2] - c; dd=v->planeEqn[3] - d; if ((aa*aa) + (bb*bb) + (cc * cc) + (dd * dd) < 0.001) v++; else return 0; } return 1; } /*}}} */ /* dumping */ /*{{{ void matrix_dump ( MATRIX m )*/ void matrix_dump ( MATRIX m ) { int i; float *p=(float *)m; printf(" Matrix dump\n"); for (i=0; i<4; i++ ) { printf(" { %f, %f, %f, %f }\n", p[0], p[1], p[2], p[3] ); p+=4; } } /*}}} */ /*{{{ void point_dump ( POINT p )*/ void point_dump ( POINT p ) { printf(" { %f, %f, %f }\n", p[0], p[1], p[2] ); } /*}}} */ /*{{{ void bound_dump ( POINT *p )*/ void bound_dump ( POINT *p ) { int i; for (i=0; i<8; i++ ) point_dump ( *p++ ); } /*}}} */ /*{{{ void point_dump4 ( POINT p )*/ void point_dump4 ( POINT p ) { printf(" { %f, %f, %f, %f }\n", p[0], p[1], p[2], p[3] ); } /*}}} */ /*{{{ void _consolidate ( VSTRIP *v )*/ void _consolidate ( VSTRIP *v ) { /*{{{ about consolidate*/ /* this will consolidate the VERTEX list associated with the VSTRIP first - count all vertices then malloc a set of n vertices, linking them all together now copy each vertex data into the consolidated strip, freeing the isolated vertex */ /*}}} */ int i, verts=0; VERTEX *solid, *vert, *old, *tail; /*{{{ count the vertices*/ for (vert=v->head; vert!=NULL; verts++ ) vert=vert->next; /*}}} */ /*{{{ malloc new store*/ solid=_NewVertices(verts); if (solid==NULL) mexico_68 ("failed to malloc %d vertices (points=%d triangles=%d)\n", verts, points, triangles, NULL ); /*}}} */ /*{{{ copy new into old*/ vert=solid; tail=solid; old=v->head; for (i=0; inext=vert+1; vert=vert->next; /* free old */ old=old->next; free (prev); } /*}}} */ /*{{{ tidy up*/ tail->next=NULL; v->head=solid; v->vertex_count=verts; /*}}} */ } /*}}} */ #if 0 /*{{{ static int read_coords ( FILE *fp, float *s, int coords )*/ static int read_coords ( FILE *fp, float *s, int coords ) { int i; for (i=0; iname, "%f", &f ) != 1) mexico_68 ("Expected float, found %s coord %d at line %d\n", t->name, i, __lineNo, NULL); *s++=f; } */ /*}}} */ } /*}}} */ /*{{{ static int read_int ( FILE *fp )*/ static int read_int ( FILE *fp ) { tokptr t=&curr_token; int j; if (nexttoken(fp, spaces ) == 0) return 0; if (sscanf(t->name, "%d", &j ) != 1) { sprintf ( errmess, "Expected int, found %s at line %d\n", t->name, __lineNo, NULL); return 0; } return(j); } /*}}} */ /*{{{ static float read_float ( FILE *fp )*/ static float read_float ( FILE *fp ) { tokptr t=&curr_token; float j; if (nexttoken(fp, spaces ) == 0) return 0; if (sscanf(t->name, "%f", &j ) != 1) { sprintf ( errmess, "Expected int, found %s at line %d\n", t->name, __lineNo, NULL); return 0; } return(j); } /*}}} */ /*{{{ static int read_header ( FILE *fp, surfptr s )*/ static int read_header ( FILE *fp, surfptr s ) { tokptr tok=&curr_token; int check2; s->pointsize=3; check2=checktwo ( fp, tok_lbracket, tok_lcurly); if (check2==tok_lbracket) { /* we have the first arg - read until close bracket */ nexttoken(fp, spacecomma); while (tok->id!=tok_rbracket) { char *mtlname=s->fmaterial; switch (tok->id) { /*{{{ case tok_cooked :*/ case tok_cooked : if (checkfor ( fp, tok_assign ) == 0) return 0; if (s->COOKED = read_int ( fp )) s->pointsize+=3; break; /*}}} */ /*{{{ case tok_normals :*/ case tok_normals : if (checkfor ( fp, tok_assign ) == 0) return 0; if (s->NORMALS = read_int ( fp )) { /* printf("normals = %d\n", s->NORMALS ); */ s->pointsize+=3; } break; /*}}} */ /*{{{ case tok_texture :*/ case tok_texture : if (checkfor ( fp, tok_assign ) == 0) return 0; { int tmp; tmp=read_int(fp); if (tmp) { s->TEXTURE=1; s->pointsize+=2; } } break; /*}}} */ /*{{{ case tok_switch_in :*/ case tok_switch_in : if (checkfor ( fp, tok_assign ) == 0) return 0; lod_switch_in=read_float(fp); break; /*}}} */ /*{{{ case tok_switch_out :*/ case tok_switch_out : if (checkfor ( fp, tok_assign ) == 0) return 0; lod_switch_out=read_float(fp); break; /*}}} */ /*{{{ case tok_f / bmaterial :*/ case tok_bmaterial : printf ( "read_header...bmaterial\n" ); mtlname=s->bmaterial; if (checkfor ( fp, tok_assign ) == 0) return 0; nexttoken ( fp, spacecomma ); strcpy ( mtlname, tok->name ); break; case tok_fmaterial : printf ( "read_header...fmaterial\n" ); mtlname=s->fmaterial; if (checkfor ( fp, tok_assign ) == 0) return 0; nexttoken ( fp, spacecomma ); strcpy ( mtlname, tok->name ); break; /*}}} */ default : mexico_68 ("Unexpected argument in header : %s (%d) at line %d\n", tok->name, tok->id, __lineNo, NULL); return 0; } sep=spaces; nexttoken(fp, spacecomma); } if (checkfor ( fp, tok_lcurly ) == 0) return 0; } else if (check2 == -1) return 0; return 1; } /*}}} */ /*{{{ static int read_material ( FILE *fp )*/ static int read_material ( FILE *fp ) { MATERIAL *m=create_material(); float *f=(float *) &m->kd[0]; char *texname; tokptr tok=&curr_token; nexttoken ( fp, spacecomma); if (strlen(tok->name)>=MATERIAL_NAME_LENGTH) tok->name[MATERIAL_NAME_LENGTH-1]=(char) 0x0; strcpy ( (char *) m->material_name, tok->name ); if (checkfor ( fp, tok_lcurly ) == 0) return 0; nexttoken(fp, spacecomma); while (tok->id != tok_rcurly) { switch (tok->id) { /*{{{ case tok_power :*/ case tok_power : checkfor ( fp, tok_assign ); m->power = read_float ( fp ); break; /*}}} */ /*{{{ case tok_spec :*/ case tok_spec : checkfor ( fp, tok_assign ); m->ks = read_float ( fp ); break; /*}}} */ /*{{{ case tok_colour*/ case tok_colour : checkfor ( fp, tok_assign ); checkfor ( fp, tok_lcurly ); sep=spacecomma; read_coords ( fp, f, 3 ); f=&m->kd[0]; checkfor ( fp, tok_rcurly ); break; /*}}} */ /*{{{ case tok_opacity :*/ case tok_opacity : checkfor ( fp, tok_assign ); { float opaque; m->opacity=read_float ( fp ); } break; /*}}} */ /*{{{ case tok_texture*/ case tok_texture : texname =(char *) &m->texture_name[0]; checkfor ( fp, tok_assign ); nexttoken ( fp, spacecomma ); strcpy ( texname, tok->name ); break; /*}}} */ default : mexico_68 ("Unexpected argument in material : %s at line %d\n", tok->name, __lineNo, NULL); return 0; } sep=spaces; nexttoken(fp, spacecomma); } add_material ( m ); return 1; } /*}}} */ /*{{{ static VERTEX *read_point ( FILE *fp, int cooked, int norm, int tex )*/ static VERTEX *read_point ( FILE *fp, int cooked, int norm, int tex ) { VERTEX *v; float pos [8]; int i, tex_base, coords=3; tokptr t=&curr_token; _InitVertex(v=_NewVtx()); if (v==NULL) { printf ("NewVtx returned NULL\n" ); exit(666); } if (cooked) coords+=3; else if (norm) coords+=3; if (tex) coords+=2; read_coords ( fp, pos, coords ); points++; checkfor ( fp, tok_rcurly ); memcpy ( v->position, pos, 3*sizeof(float)); v->position[3]=1; v->normcol[0]=0; v->normcol[1]=0; v->normcol[2]=0; tex_base=3; if (norm) { float hyp; hyp=(pos[3]*pos[3]) + (pos[4]*pos[4]) + (pos[5]*pos[5]); hyp=1.0f/sqrt(hyp); v->normcol[0]=pos[3]*hyp; v->normcol[1]=pos[4]*hyp; v->normcol[2]=pos[5]*hyp; tex_base+=3; } else if (cooked) { #define min_col 0.0f #define max_col 1.0f if (pos[3] < min_col) pos[3]=min_col; if (pos[3] > max_col) pos[3]=max_col; if (pos[4] < min_col) pos[4]=min_col; if (pos[4] > max_col) pos[4]=max_col; if (pos[5] < min_col) pos[5]=min_col; if (pos[5] > max_col) pos[5]=max_col; v->normcol[0]=255.99f*pos[3]; v->normcol[1]=255.99f*pos[4]; v->normcol[2]=255.99f*pos[5]; tex_base+=3; } if (tex) { v->texcoords[0]=pos[tex_base ]*0.125f; v->texcoords[1]=pos[tex_base+1]*0.125f; } else { v->texcoords[0]=0; v->texcoords[1]=0; } return(v); } /*}}} */ /*{{{ static VERTEX *read_tri ( FILE *fp )*/ static VERTEX *read_tri ( FILE *fp ) { VERTEX *v; float pos [8]; int i, coords=3; tokptr t=&curr_token; _InitVertex(v=_NewVtx()); read_coords ( fp, pos, coords ); points++; checkfor ( fp, tok_rcurly ); memcpy ( v->position, pos, 3*sizeof(float)); v->position[3]=1; return(v); } /*}}} */ /*{{{ static VSTRIP *read_tesselation (FILE *fp)*/ static VSTRIP *read_tesselation (FILE *fp) { VSTRIP *v; int count=points+2; _InitVstrip(v=_NewVstrip()); if (v==NULL) { printf ("NewVstrip returned NULL\n" ); exit(666); } /* this should see just coordinates */ checkfor ( fp, tok_lcurly ); while (checktwo (fp, tok_lcurly, tok_rcurly)==tok_lcurly) { /* read a point */ VERTEX *vert; sep=spacecomma; vert=read_point (fp, patch_surf.COOKED, patch_surf.NORMALS, patch_surf.TEXTURE & 1 ); sep=spaces; add_item(v, vert); } if ((points-count)<1) mexico_68 ("Less than 3 points in tesselation at line %d\n", __lineNo, NULL); else triangles+=points-count; /* printf("calling consolidate\n" ); */ _consolidate(v); return(v); } /*}}} */ /*{{{ static VSTRIP *read_connections (FILE *fp)*/ static VSTRIP *read_connections (FILE *fp) { VSTRIP *v; int triangles=0; _InitVstrip(v=_NewVstrip()); if (v==NULL) { printf ("NewVstrip returned NULL\n" ); exit(666); } /* this should see just coordinates */ checkfor ( fp, tok_lcurly ); while (checktwo (fp, tok_lcurly, tok_rcurly)==tok_lcurly) { /* read a point */ VERTEX *vert; sep=spacecomma; vert=read_tri (fp); sep=spaces; add_item(v, vert); triangles++; } _consolidate(v); /* printf ("read %d triangles in pmesh\n", triangles ); */ return(v); } /*}}} */ /*{{{ static PATCH *read_patch ( FILE *fp )*/ static PATCH *read_patch ( FILE *fp ) { PATCH *p; VSTRIP *tess; int count=points, tcount=triangles, tess_type; tokptr t=&curr_token; /* printf ( "read_patch " ); */ _InitPatch(p=_NewPatch()); if (p==NULL) { printf ("NewPatch returned NULL\n" ); exit(666); } p->vertex_count=0; p->head=NULL; p->next=NULL; p->patch_type=patch_type_patch; /* inherit object surface properties */ memcpy ( &patch_surf, &obj_surf, sizeof (surface) ); if (read_header ( fp, &patch_surf ) == 0) return NULL; set_surface ( p, &patch_surf ); /* read all tesselations */ check ( fp, "%d %d %d", tok_polystrip, tok_tristrip, tok_rcurly, NULL ); while (t->id!=tok_rcurly) { tess_type=strip_type_tri; switch (t->id) { case tok_polystrip : tess_type=strip_type_poly; case tok_tristrip : tess=read_tesselation (fp); tess->strip_type=tess_type; tess->normals=patch_surf.NORMALS; tess->strip_shade=0; if (patch_surf.TEXTURE & 1) tess->strip_shade|=strip_shade_textured; if (patch_surf.COOKED) tess->strip_shade|=strip_shade_coloured; else if (patch_surf.NORMALS) tess->strip_shade|=strip_shade_smooth; else tess->strip_shade|=strip_shade_flat; add_item(p, tess); p->vertex_count+=tess->vertex_count; check ( fp, "%d %d %d", tok_polystrip, tok_tristrip, tok_rcurly, NULL ); break; case tok_rcurly : break; default : expected ( "POLYSTRIP or TRISTRIP", t->name ); return NULL; } } return(p); } /*}}} */ /*{{{ static PATCH *read_pmesh ( FILE *fp )*/ static int pmeshes_read=0; static PATCH *read_pmesh ( FILE *fp ) { PATCH *p; VSTRIP *tess, *clone, *connect; VERTEX *vert, *clone_list; int i, mesh_verts; int count=points, tcount=triangles, tess_type; tokptr t=&curr_token; _InitPatch(p=_NewPatch()); if (p==NULL) { printf ("NewPatch returned NULL\n" ); exit(666); } printf ( "read_pmesh 0x%x - now %d\n", p, pmeshes_read ); pmeshes_read++; p->vertex_count=0; p->head=NULL; p->patch_type=patch_type_pmesh; p->next=NULL; /* inherit object surface properties */ memcpy ( &patch_surf, &obj_surf, sizeof (surface) ); if (read_header ( fp, &patch_surf ) == 0) return NULL; set_surface ( p, &patch_surf ); /*{{{ read vertex list*/ /* read all vertices */ checkfor ( fp, tok_vertices ); tess=read_tesselation (fp); tess->strip_type=strip_type_tri; tess->normals=patch_surf.NORMALS; tess->strip_shade=0; if (patch_surf.TEXTURE & 1) tess->strip_shade|=strip_shade_textured; if (patch_surf.COOKED) tess->strip_shade|=strip_shade_coloured; else if (patch_surf.NORMALS) tess->strip_shade|=strip_shade_smooth; else tess->strip_shade|=strip_shade_flat; add_item(p, tess); /*}}} */ /*{{{ clone vertex list*/ _InitVstrip(clone=_NewVstrip()); mesh_verts=tess->vertex_count; for (i=0; istrip_type =tess->strip_type; clone->strip_shade =tess->strip_shade; clone->normals =tess->normals; clone->vertex_count=tess->vertex_count; pmesh_vertex_copy ( clone->head, tess->head, mesh_verts ); add_item(p, clone); /*}}} */ /*{{{ read connexions list*/ checkfor ( fp, tok_connections ); connect=read_connections (fp); add_item(p, connect ); /*}}} */ /*{{{ now check connexions list, and patch up pointers*/ clone_list=clone->head; for (vert=connect->head, i=0; vert; i++, vert=vert->next ) { float *fpos=&vert->position[0]; int *pos=(int *) &vert->position[0]; int va, vb, vc; VERTEX *verta, *vertb, *vertc; va=(int) (fpos[0]); vb=(int) (fpos[1]); vc=(int) (fpos[2]); if ((va < 0) || (va >= mesh_verts)) { printf ("Error - vertex 0 of triangle %d in pmesh out of range (%d)\n", i, mesh_verts ); return NULL; } if ((vb < 0) || (vb >= mesh_verts)) { printf ("Error - vertex 1 of triangle %d in pmesh out of range (%d)\n", i, mesh_verts ); return NULL; } if ((vc < 0) || (vc >= mesh_verts)) { printf ("Error - vertex 2 of triangle %d in pmesh out of range (%d)\n", i, mesh_verts ); return NULL; } verta=&clone_list[va]; vertb=&clone_list[vb]; vertc=&clone_list[vc]; pos[0]=(int) verta; pos[1]=(int) vertb; pos[2]=(int) vertc; } /*}}} */ checkfor ( fp, tok_rcurly ); return(p); } /*}}} */ /*{{{ void obj_info ( OBJECT *o )*/ void obj_info ( OBJECT *o ) { PATCH *p; SURFACE *s; VSTRIP *v; /*{{{ dump object info*/ printf ( "OBJECT - vertex_count %d instance_count %d bounds -\n", o->vertex_count, o->instance_count ); bound_dump ( o->bound ); /*}}} */ for (p=o->head; p!=NULL; p=p->next ) { /*{{{ dump patch info*/ printf ( " PATCH 0x%x - vertex_count %d bound -\n", p, p->vertex_count ); bound_dump ( p->bound ); s=&p->front; printf (" FRONT " ); printf (" kd %f %f %f ks %f power %f texture 0x%x\n", s->kd[0], s->kd[1], s->kd[2], s->ks, s->power, s->tex ); s=&p->back; printf (" BACK " ); printf (" kd %f %f %f ks %f power %f texture 0x%x\n", s->kd[0], s->kd[1], s->kd[2], s->ks, s->power, s->tex ); /*}}} */ for (v=p->head; v!=NULL; v=v->next ) { VERTEX *vert; printf ( " VSTRIP - vertex_count %d norm %d type %d rend %d shade %d\n", v->vertex_count, v->normals, v->strip_type, v->strip_render, v->strip_shade ); for (vert=v->head; vert!=NULL; vert=vert->next ) point_dump ( vert->position ); } } } /*}}} */ /*{{{ void obj_info ( OBJECT *o )*/ void obj_info ( OBJECT *o ) { LOD *l; PATCH *p; SURFACE *s; VSTRIP *v; /*{{{ dump object info*/ printf ( "OBJECT - vertex_count %d instance_count %d bounds -\n", o->vertex_count, o->instance_count ); bound_dump ( o->bound ); /*}}} */ for (p=o->head; p!=NULL; p=p->next ) { /*{{{ dump patch info*/ printf ( " PATCH 0x%x - vertex_count %d bound -\n", p, p->vertex_count ); bound_dump ( p->bound ); s=&p->front; printf (" FRONT " ); printf (" kd %f %f %f ks %f power %f texture 0x%x\n", s->kd[0], s->kd[1], s->kd[2], s->ks, s->power, s->tex ); s=&p->back; printf (" BACK " ); printf (" kd %f %f %f ks %f power %f texture 0x%x\n", s->kd[0], s->kd[1], s->kd[2], s->ks, s->power, s->tex ); /*}}} */ for (v=p->head; v!=NULL; v=v->next ) { VERTEX *vert; printf ( " VSTRIP - vertex_count %d norm %d type %d rend %d shade %d\n", v->vertex_count, v->normals, v->strip_type, v->strip_render, v->strip_shade ); for (vert=v->head; vert!=NULL; vert=vert->next ) point_dump ( vert->position ); } } } /*}}} */ /* _read being munged to do MATERIALs */ /*{{{ int ascii_read ( char *fname, OBJECT **objects, int max )*/ int ascii_read ( char *fname, OBJECT **objects, int max ) { int objects_read=0; int materials_read=0; __lineNo=0; printf ( "in _read\n" ); if (setjmp(bob_beamon)==0) { FILE *obj_file; LOD *lod; PATCH *p; VSTRIP *v; OBJECT *returnObj=NULL; init(); sep=spaces; _InitObject(obj=_NewObject()); if ((obj_file=open_fn(fname, "rt"))==0) { printf ( "failed to fopen it\n" ); mexico_68 ("Couldnt open %s\n", fname, NULL ); } else { while (nexttoken ( obj_file, spaces )) { int patch_tok; if ( curr_token.id == tok_material ) { printf ( "material ...\n" ); /*{{{ read material*/ read_material ( obj_file ); materials_read++; sprintf ( errmess, "Read %d materials\n", materials_read ); /*}}} */ } else if ( curr_token.id == tok_object ) { int patches=0; printf ( "object, read LOD...\n" ); /*{{{ read LOD*/ _InitLOD(lod=_NewLOD()); memcpy ( &obj_surf, &default_surf, sizeof (surface) ); obj_surf.pointsize=3; printf ( "object, read_header...\n" ); read_header ( obj_file, &obj_surf ); patch_tok=check(obj_file, "%d %d %d", tok_patch, tok_pmesh, tok_rcurly ); while ((patch_tok == tok_patch) || (patch_tok == tok_pmesh)) { if (patch_tok == tok_patch) { p=read_patch ( obj_file); bound_patch ( p ); compute_plane_eqns ( p, 0 ); for (v=p->head; v!=NULL; v=v->next ) { compute_gnorms ( v ); } } else { VSTRIP *next=NULL; p=read_pmesh ( obj_file); if (p->head) { next=p->head->next; p->head->next=NULL; } bound_patch ( p ); if (next) { p->head->next=next; } compute_pmesh_plane_eqns ( p, 0 ); } patches++; p->next=NULL; add_item (lod, p); lod->vertex_count+=p->vertex_count; patch_tok=check (obj_file, "%d %d %d", tok_patch, tok_pmesh, tok_rcurly ); } /* did we just read a good file ? */ if (curr_token.id == tok_rcurly) { sprintf ( errmess, "OBJECT of %d points %d triangles\n", points, triangles); reboundLOD ( lod ); lod->switch_in =lod_switch_in; lod->switch_out=lod_switch_out; objects_read++; add_item (obj, lod); *objects=obj; } /*}}} */ } else { printf ( "huh ? %s ...\n", curr_token.name ); /*{{{ bad token in file*/ sprintf ( errmess, "Unexpected token %s, expected MATERIAL or OBJECT\n", curr_token.name ); break; /*}}} */ } } reconnectLODs ( *objects ); close_fn (obj_file); return (objects_read); } } else { obj=NULL; printf (" bob beamon failure\n" ); } return (objects_read); } /*}}} */ #endif /*{{{ void reconnectLODs ( OBJECT *obj )*/ void reconnectLODs ( OBJECT *obj ) { /* this funtion walks down a LOD list, sorts the LODs by distance */ PAZlist *LODhead, *PAZlod; LOD *sortlod; sortlod=obj->head; LODhead = (PAZlist *) malloc(sizeof(PAZlist)); LODhead->next=NULL; LODhead->data=sortlod; sortlod=sortlod->next; /* take each lod, insert it sorted into LODhead list */ for (; sortlod; sortlod=sortlod->next ) { PAZlist *insert, *compare=LODhead, *patch=NULL; LOD *compareLOD; int inserting=1; insert = (PAZlist *) malloc(sizeof(PAZlist)); insert->data=sortlod; while (inserting) { compareLOD=(LOD *) compare->data; if (sortlod->switch_in < compareLOD->switch_in) { /* insert before the compare data */ if (patch == NULL) { PAZlist *oldnext=LODhead; LODhead=insert; insert->next=oldnext; } else { PAZlist *oldnext=patch->next; patch->next=insert; insert->next=oldnext; } inserting=0; } else if (compare->next==NULL) { /* insert after the compare data */ compare->next=insert; insert->next=NULL; inserting=0; } else { compare=compare->next; if (patch) patch=patch->next; else patch=LODhead; } } } /* put list back into object */ obj->head=NULL; while (LODhead) { PAZlist *p; LOD *tail=obj->tail, *this=(LOD *) LODhead->data; p=LODhead->next; add_item (obj, this ); this->prev=tail; free(LODhead); LODhead=p; } } /*}}} */ /*{{{ OBJECT *bin_read ( int *data )*/ OBJECT *bin_read ( int *data ) { extern int scene_resolved; int objects_read=0; int materials_read=0; /* NB we have read the viz_binOpenGeometry */ if (setjmp(bob_beamon)==0) { /*{{{ locals*/ FILE *obj_file; PATCH *p; VSTRIP *v; VERTEX *solid, *vert; /*}}} */ /*{{{ bits of init()*/ patches=0; tesselations=0; triangles=0; points=0; /*}}} */ _InitObject(obj=_NewObject()); data=(int *) gets_fn(0,6,0); while ((data[0]==viz_openBinMaterial)||(data[0]==viz_openBinLOD)) { if (data[0]==viz_openBinMaterial) { /*{{{ new mtl*/ { MATERIAL *m=create_material (); MATERIAL *remote=(MATERIAL *) &data[2]; memcpy ( m, remote, sizeof(MATERIAL)); m->tex=NULL; m->triangle_fn=NULL; add_material ( m ); } /*}}} */ data=(int *) gets_fn(0,6,0); } else if (data[0]==viz_openBinLOD) { /*{{{ new LOD*/ /* new LOD */ int strip_shade; float *lod_switch=(float *) &data[1]; LOD *lod; _InitLOD(lod=_NewLOD()); lod->vertex_count=0; lod->switch_in =lod_switch[0]; lod->switch_out=lod_switch[1]; data=(int *) gets_fn(0,6,0); while ((data[0]==viz_openBinPatch) || (data[0]==viz_openBinPmesh)) { if (data[0] == viz_openBinPatch) { /*{{{ patch*/ /*{{{ read patch*/ _InitPatch(p=_NewPatch()); memcpy ( &patch_surf, (char *) &data[2], sizeof (surface) ); set_surface ( p, &patch_surf ); p->patch_type = patch_type_patch; strip_shade=0; if (patch_surf.TEXTURE) strip_shade|=strip_shade_textured; if (patch_surf.COOKED) strip_shade|=strip_shade_coloured; else if (patch_surf.NORMALS) strip_shade|=strip_shade_smooth; else strip_shade|=strip_shade_flat; data=(int *) gets_fn(0,6,0); if (data[0] != viz_openBinStrip) { mexico_68 ("binRead DIDNT get strip\n" ); } else { while (data[0] == viz_openBinStrip) { /*{{{ read each strip*/ int i, stype=data[1], verts=data[2], nfloats=data[3], accum=0; float *vptr; points+=verts; triangles+=verts-2; _InitVstrip(v=_NewVstrip()); /*{{{ malloc, init and listize new store*/ solid=_NewVertices(verts); if (solid==NULL) mexico_68 ("failed to malloc %d vertices (points=%d triangles=%d)\n", verts, points, triangles, NULL ); vert=solid; for (i=0; itail=vert; vert->next=vert+1; vert=vert->next; } v->tail->next=NULL; v->head=solid; v->vertex_count=verts; v->strip_shade=strip_shade; v->strip_type=stype; v->normals=patch_surf.NORMALS; vert=v->head; /*}}} */ data=(int *) gets_fn(0,0,0); while (data[0] == viz_binGeometry) { /*{{{ put these items into strip*/ int j; /* extract vertices from structure */ /* copy each of verts into new structure */ accum+=data[1]; vptr=(float *) &data[2]; for (j=0; jposition[0]=*vptr++; vert->position[1]=*vptr++; vert->position[2]=*vptr++; vert->position[3]=1.0f; vert->normcol[0]=0; vert->normcol[1]=0; vert->normcol[2]=0; if (patch_surf.COOKED) { vert->normcol[0]=*vptr++; vert->normcol[1]=*vptr++; vert->normcol[2]=*vptr++; } else if (patch_surf.NORMALS) { vert->normcol[0]=*vptr++; vert->normcol[1]=*vptr++; vert->normcol[2]=*vptr++; } if (patch_surf.TEXTURE & 1) { vert->texcoords[0]=0.5f*(*vptr++); vert->texcoords[1]=0.5f*(*vptr++); } vert=vert->next; } /*}}} */ data=(int *) gets_fn(0,0,0); } /*}}} */ add_item(p, v); p->vertex_count+=v->vertex_count; } } /*}}} */ bound_patch ( p ); compute_plane_eqns ( p, 0 ); for (v=p->head; v!=NULL; v=v->next ) { compute_gnorms ( v ); } /*}}} */ } else { /*{{{ pmesh*/ VSTRIP *next; VSTRIP *tess, *clone, *connect; VERTEX *vert, *clone_list; int i, first_strip=1, mesh_verts; /*{{{ read pmesh*/ _InitPatch(p=_NewPatch()); memcpy ( &patch_surf, (char *) &data[2], sizeof (surface) ); set_surface ( p, &patch_surf ); p->patch_type = patch_type_pmesh; strip_shade=0; if (patch_surf.TEXTURE & 1) strip_shade|=strip_shade_textured; if (patch_surf.COOKED) strip_shade|=strip_shade_coloured; else if (patch_surf.NORMALS) strip_shade|=strip_shade_smooth; else strip_shade|=strip_shade_flat; /* expect just 2 strips, and do magic with them */ data=(int *) gets_fn(0,6,0); if (data[0] != viz_openBinStrip) { mexico_68 ("binRead DIDNT get strip\n" ); } else { while (data[0] == viz_openBinStrip) { /*{{{ read each strip*/ int i, stype=data[1], verts=data[2], nfloats=data[3], accum=0; float *vptr; points+=verts; triangles+=verts-2; _InitVstrip(v=_NewVstrip()); /*{{{ malloc, init and listize new store*/ solid=_NewVertices(verts); if (solid==NULL) mexico_68 ("failed to malloc %d vertices (points=%d triangles=%d)\n", verts, points, triangles, NULL ); vert=solid; for (i=0; itail=vert; vert->next=vert+1; vert=vert->next; } v->tail->next=NULL; v->head=solid; v->vertex_count=verts; v->strip_shade=strip_shade; v->strip_type=stype; v->normals=patch_surf.NORMALS; vert=v->head; /*}}} */ data=(int *) gets_fn(0,0,0); while (data[0] == viz_binGeometry) { /*{{{ put these items into strip*/ int j; /* extract vertices from structure */ /* copy each of verts into new structure */ accum+=data[1]; vptr=(float *) &data[2]; for (j=0; jposition[0]=*vptr++; vert->position[1]=*vptr++; vert->position[2]=*vptr++; vert->position[3]=0; vert->normcol[0]=0; vert->normcol[1]=0; vert->normcol[2]=0; if (first_strip) { if (patch_surf.COOKED) { vert->normcol[0]=*vptr++; vert->normcol[1]=*vptr++; vert->normcol[2]=*vptr++; } else if (patch_surf.NORMALS) { vert->normcol[0]=*vptr++; vert->normcol[1]=*vptr++; vert->normcol[2]=*vptr++; } if (patch_surf.TEXTURE & 1) { vert->texcoords[0]=0.5f*(*vptr++); vert->texcoords[1]=0.5f*(*vptr++); } } vert=vert->next; } /*}}} */ data=(int *) gets_fn(0,0,0); } /*}}} */ add_item(p, v); p->vertex_count+=v->vertex_count; first_strip=0; } } /*}}} */ /*{{{ now do pmesh magic rearrangement*/ /* NBB pmeshes have the vertex W-coordinate ZEROED ! ! ! ! */ /* we need to clone the contents of p->head */ tess=p->head; connect=tess->next; /*{{{ clone vertex list*/ _InitVstrip(clone=_NewVstrip()); mesh_verts=tess->vertex_count; for (i=0; istrip_type =tess->strip_type; clone->strip_shade =tess->strip_shade; clone->normals =tess->normals; clone->vertex_count=tess->vertex_count; pmesh_vertex_copy ( clone->head, tess->head, mesh_verts ); /*}}} */ tess->next=clone; clone->next=connect; connect->next=NULL; p->head=tess; p->tail=connect; /*{{{ now check connexions list, and patch up pointers*/ clone_list=clone->head; for (vert=connect->head, i=connect->vertex_count; i; i--, vert=vert->next ) { float *fpos=&vert->position[0]; int *pos=(int *) fpos; int va, vb, vc; VERTEX *verta, *vertb, *vertc; va=(int) (fpos[0]); vb=(int) (fpos[1]); vc=(int) (fpos[2]); if ((va < 0) || (va >= mesh_verts)) { mexico_68 ("Error - vertex 0 of triangle %d in pmesh out of range (%d)\n", i, mesh_verts, NULL ); return NULL; } if ((vb < 0) || (vb >= mesh_verts)) { mexico_68 ("Error - vertex 1 of triangle %d in pmesh out of range (%d)\n", i, mesh_verts, NULL ); return NULL; } if ((vc < 0) || (vc >= mesh_verts)) { mexico_68 ("Error - vertex 2 of triangle %d in pmesh out of range (%d)\n", i, mesh_verts, NULL ); return NULL; } verta=&clone_list[va]; vertb=&clone_list[vb]; vertc=&clone_list[vc]; pos[0]=(int) verta; pos[1]=(int) vertb; pos[2]=(int) vertc; } /*}}} */ /*}}} */ tess->next=NULL; bound_patch ( p ); tess->next=clone; compute_pmesh_plane_eqns ( p, 0 ); /*}}} */ } lod->vertex_count+=p->vertex_count; add_item (lod, p); reboundLOD ( lod ); } /*}}} */ add_item (obj, lod); } } if (data[0]!=viz_closeBinGeometry) mexico_68 ( "Unexpected tag 0x%x, expected closeBinGeometry\n", data[0] ); else { OBJLIST *sg=&sceneGeometry; reconnectLODs ( obj ); reboundObject ( obj ); add_item ( sg, obj ); scene_resolved=0; sprintf ( errmess, "OBJECT of %d points %d triangles\n", points, triangles ); return obj; } } else { /* longjmp comes here */ while (data[0] !=viz_closeBinGeometry) data=(int *) gets_fn(0,0,0); return NULL; } } /*}}} */