Files
CydandClaude Fable 5 db7745fcd0 sda4: commit the Glaze developer hard-drive dump
Un-ignored: the dev drive is the ground truth the restoration and
emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer
source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio
content). Kept in-repo for the pod-owner community.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:41:15 -05:00

1798 lines
47 KiB
C++

/*
File pazread
Phil Atkin
(c) Division Ltd. 1991
*/
/*{{{ includes*/
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include <dnc.h>
#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; i<NAMETABLE_SIZE; i++)
set_name ( i, "\0", -1);
set_name(tok_lcurly ,"{", tok_lcurly );
set_name(tok_rcurly ,"}", tok_rcurly );
set_name(tok_tristrip ,"TRISTRIP", tok_tristrip );
set_name(tok_polystrip ,"POLYSTRIP", tok_polystrip );
set_name(tok_patch ,"PATCH", tok_patch );
set_name(tok_lbracket ,"(", tok_lbracket );
set_name(tok_rbracket ,")", tok_rbracket );
set_name(tok_object ,"OBJECT", tok_object );
set_name(tok_assign ,"=", tok_assign );
set_name(tok_comment ,"/*", tok_comment );
set_name(tok_endcomment ,"*/", tok_endcomment );
set_name(tok_cooked ,"COOKED", tok_cooked );
set_name(tok_normals ,"NORMALS", tok_normals );
set_name(tok_colour ,"COLOUR", tok_colour );
set_name(tok_spec ,"KS", tok_spec );
set_name(tok_power ,"POWER", tok_power );
set_name(tok_texture ,"TEXTURE", tok_texture );
set_name(tok_opacity ,"OPACITY", tok_opacity );
set_name(tok_pmesh ,"PMESH", tok_pmesh );
set_name(tok_vertices ,"VERTICES", tok_vertices );
set_name(tok_connections ,"CONNECTIONS", tok_connections );
set_name(tok_fmaterial ,"F_MATERIAL", tok_fmaterial );
set_name(tok_bmaterial ,"B_MATERIAL", tok_bmaterial );
set_name(tok_material ,"MATERIAL", tok_material );
set_name(tok_switch_in ,"SWITCH_IN", tok_switch_in );
set_name(tok_switch_out ,"SWITCH_OUT", tok_switch_out );
}
/*}}} */
/*{{{ token reading / error handling*/
#define copy_token(a,b) memcpy (b,a,sizeof (token))
char *sep;
/*{{{ static int expected ( char *expect, char *found )*/
static int expected ( char *expect, char *found )
{
sprintf ( errmess, "Expected %s, encountered %s at line %d\n", expect, found,
__lineNo, NULL );
}
/*}}} */
/*{{{ static char *strip_head ( char *s)*/
static char *strip_head ( char *s)
{
char c;
for (c=*s; c==' ';c=*++s);
return(s);
}
/*}}} */
/*{{{ static char *strip_tail ( char *s)*/
static char *strip_tail ( char *s)
{
int i, l=strlen(s);
char c, *tail=s+l;
if (l!=0) {
for (i=0; i<l; i++ ) {
tail--;
/* nasty friggy check for cr, lf problems */
if ((*tail==' ')||(*tail=='\n')||(*tail==(char)13)) {
*tail=(char) 0x0;
}
else break;
}
}
return(s);
}
/*}}} */
/*{{{ static int token_type ( char *str )*/
static int token_type ( char *str )
{
int i;
for (i=0; i<NAMETABLE_SIZE; i++ ) {
if (strcmp(str, nameof(i))==0) {
return(i);
}
else if (valof(i)<0) {
return(tok_name);
}
}
return(tok_name);
}
/*}}} */
/*{{{ static int next_token ( FILE *fp, tokptr t, char *sep )*/
static int next_token ( FILE *fp, tokptr t, char *sep )
{
int read=(curr_pos==NULL);
/*
printf ("next_token\n" );
*/
if (read==0) {
/*
printf ("not going fgets, crack string instead\n" );
*/
curr_pos=strtok(NULL,sep);
if (curr_pos==NULL) read=1;
}
if (read) {
/*
printf ("about to go fgets, curr_pos = 0x%x\n", (int) curr_pos );
*/
while (curr_pos == NULL) {
/*
printf ("DEFINITELY about to go fgets\n" );
*/
curr_pos=gets_fn(string, 255, fp );
/*
printf ("PUNCHING 0x0 into end of string\n" );
*/
string[255]=(char) 0x0;
/*
printf ("fgets just returned %d chars, %s\n", strlen(string), string );
*/
__lineNo++;
if (curr_pos==NULL) {
sprintf ( errmess, "Reached end-of-file at line %d\n",
__lineNo, NULL );
return 0;
}
else {
curr_pos=strtok(curr_pos,sep);
}
}
}
/* t->name=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; i<tptr; i++ ) {
if (t->id==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; i<strip->vertex_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; i<verts; i++ ) {
VERTEX *prev=old;
/* copy old to new */
memcpy(vert,old,sizeof(VERTEX));
/* chain in new */
tail=vert;
vert->next=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; i<coords; i++ ) {
curr_pos=strtok(NULL,sep);
if (curr_pos==NULL) {
sprintf ( errmess, "NULL token in read_coords at line %d\n", __lineNo, NULL );
return 0;
}
else if (sscanf(curr_pos, "%f", s ) != 1) {
sprintf ( errmess, "Expected %d floats, found %s at line %d\n",
coords, curr_pos, __lineNo, NULL);
return 0;
}
s++;
}
return 1;
/*{{{ */
/*
tokptr t=&curr_token;
for (i=0; i<coords; i++ ) {
float f;
nexttoken(fp, spacecomma );
if (sscanf(t->name, "%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; i<mesh_verts; i++ ) {
_InitVertex(vert=_NewVtx());
add_item(clone, vert );
}
_consolidate ( clone );
clone->strip_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; i<verts; i++ ) {
v->tail=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; j<data[1]; j++ ) {
if (vert==NULL)
mexico_68 ( "DEEP bogosity - too many vertices\n" );
vert->position[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; i<verts; i++ ) {
v->tail=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; j<data[1]; j++ ) {
if (vert==NULL)
mexico_68 ( "DEEP bogosity - too many vertices\n" );
vert->position[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; i<mesh_verts; i++ ) {
_InitVertex(vert=_NewVtx());
add_item ( clone, vert );
}
_consolidate ( clone );
clone->strip_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;
}
}
/*}}} */