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>
1798 lines
47 KiB
C++
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;
|
|
}
|
|
}
|
|
/*}}} */
|
|
|