/* 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 extern concurrency_control *shared_cntl; /*{{{ 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); } /*}}} */ static surface default_surf, obj_surf, patch_surf; static int patches=0, tesselations=0, triangles=0, points=0; 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] ); } /*}}} */ /*{{{ static void fix_vstrip_texture_coords( VSTRIP *strip )*/ static void fix_vstrip_texture_coords( VSTRIP *strip ) { VERTEX *v; int i; float tu, tv, minu, minv; return; if (strip->strip_shade & strip_shade_textured) { v=strip->head; for (i=0; ivertex_count; i++ ) { if (i==0) { minu=v->texcoords[0]; minv=v->texcoords[1]; } else { tu=v->texcoords[0]; tv=v->texcoords[1]; if (tunext; } tu=0; tv=0; /*{{{ fix o/flow*/ while(minu > 1.0f) { minu-=1.0f; tu -=1.0f; } while(minv > 1.0f) { minv-=1.0f; tv -=1.0f; } /*}}} */ /*{{{ and u/flow*/ while(minu < 0.0f) { minu+=1.0f; tu +=1.0f; } while(minv < 0.0f) { minv+=1.0f; tv +=1.0f; } /*}}} */ v=strip->head; for (i=0; ivertex_count; i++ ) { v->texcoords[0]+=tu; v->texcoords[1]+=tv; v=v->next; } } } /*}}} */ /*{{{ void _consolidate ( VSTRIP *v )*/ int _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; /*}}} */ return verts; } /*}}} */ /*{{{ void reconnectLODs ( OBJECT *obj )*/ void reconnectLODs ( OBJECT *obj ) { /* this function 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; /* take each lod, insert it sorted into LODhead list */ for (sortlod=sortlod->next; sortlod; sortlod=sortlod->next ) { PAZlist *insert, *compare, *patch; LOD *compareLOD; int inserting=1; insert = (PAZlist *) malloc(sizeof(PAZlist)); insert->data=sortlod; for (compare=LODhead, inserting=1; inserting; ) { compareLOD=(LOD *) (compare->data); if (sortlod->switch_in < compareLOD->switch_in) { /* insert before the compare data */ if (compare == LODhead) { insert->next=LODhead; LODhead=insert; inserting=0; } else { insert->next=patch->next; patch->next=insert; inserting=0; } } else if (compare->next==NULL) { /* end of list, so insert after the compare data */ compare->next=insert; insert->next=NULL; inserting=0; } else { /* keep looking */ patch =compare; compare=compare->next; } } } /* 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; PATCHISSIMO *pi; 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]; if (lod->switch_out == 0.0f) lod->switch_out=1024.0f * 1024.0f; data=(int *) gets_fn(0,6,0); while ((data[0]==viz_openBinPatch) || (data[0]==viz_openBinPmesh) || (data[0]==viz_openBinSmesh)) { if (data[0] == viz_openBinPatch) { /*{{{ patch*/ /*{{{ read patch*/ _InitPatch((PATCH *) (pi=_NewPatchissimo())); pi->sem=nextSem(); InitSem (pi->sem); p=(PATCH *) pi; 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*/ if (verts > shared_cntl->length_longest_strip) shared_cntl->length_longest_strip=verts; 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; } /*}}} */ dN_reply(); data=(int *) gets_fn(0,0,0); } /*}}} */ add_item(p, v); p->vertex_count+=v->vertex_count; fix_vstrip_texture_coords(v); } } /*}}} */ bound_patch ( p ); compute_plane_eqns ( p, 0 ); for (v=p->head; v!=NULL; v=v->next ) { compute_gnorms ( v ); } /*}}} */ } else if (data[0] == viz_openBinPmesh) { /*{{{ pmesh*/ VSTRIP *next; VSTRIP *tess, *connect; VERTEX *vert, *conn_list; int num, i, first_strip=1, mesh_verts, mesh_tris; /*{{{ read pmesh*/ _InitPatch((PATCH *) (pi=_NewPatchissimo())); pi->sem=nextSem(); InitSem (pi->sem); p=(PATCH *) pi; 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; } /*}}} */ dN_reply(); 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 ! ! ! ! */ fix_vstrip_texture_coords(p->head); tess=p->head; connect=tess->next; mesh_verts=tess->vertex_count; if (mesh_verts > shared_cntl->length_longest_verts) shared_cntl->length_longest_verts=mesh_verts; mesh_tris=connect->vertex_count; if (mesh_tris > shared_cntl->length_longest_tris) shared_cntl->length_longest_tris=mesh_tris; connect->next=NULL; p->head=tess; p->tail=connect; /*{{{ now check connexions list, and patch up pointers*/ conn_list=tess->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]); /* printf ("triangle %d,%d,%d\n", va, vb, vc ); */ if ((va < 0) || (va >= mesh_verts)) { mexico_68 ("Error - vertex 0 of triangle %d in pmesh out of range (%d,%d)\n", i, va, 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,%d)\n", i, vb, 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,%d)\n", i, vc, mesh_verts, NULL ); return NULL; } verta=&conn_list[va]; vertb=&conn_list[vb]; vertc=&conn_list[vc]; pos[0]=(int) verta; pos[1]=(int) vertb; pos[2]=(int) vertc; } /*}}} */ /*}}} */ tess->next=NULL; bound_patch ( p ); tess->next=connect; compute_pmesh_plane_eqns ( p, 0 ); /*}}} */ } else { /*{{{ sphere mesh*/ VSTRIP *next; VSTRIP *tess, *connect; VERTEX *vert, *conn_list; int num, i, first_strip=1, mesh_verts, mesh_tris; /*{{{ read smesh*/ _InitPatch((PATCH *) (pi=_NewPatchissimo())); pi->sem=nextSem(); InitSem (pi->sem); p=(PATCH *) pi; memcpy ( &patch_surf, (char *) &data[2], sizeof (surface) ); set_surface ( p, &patch_surf ); p->patch_type = patch_type_smesh; strip_shade=0; strip_shade|=strip_shade_smooth; /* expect just 1 strip, and do magic with it */ data=(int *) gets_fn(0,6,0); if (data[0] != viz_openBinStrip) { mexico_68 ("binRead DIDNT get strip\n" ); } else { /*{{{ 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]=*vptr++; vert=vert->next; } /*}}} */ dN_reply(); data=(int *) gets_fn(0,0,0); } /*}}} */ add_item(p, v); p->vertex_count+=v->vertex_count; first_strip=0; } /*}}} */ /*{{{ now do smesh magic rearrangement*/ tess=p->head; mesh_verts=tess->vertex_count; if (mesh_verts > shared_cntl->length_longest_verts) shared_cntl->length_longest_verts=mesh_verts; tess->next=NULL; p->head=tess; p->tail=tess; /*}}} */ bound_spatch ( p ); /*}}} */ } 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; } } /*}}} */