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

903 lines
25 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
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; 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] );
}
/*}}} */
/*{{{ 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; i<strip->vertex_count; i++ ) {
if (i==0) {
minu=v->texcoords[0];
minv=v->texcoords[1];
}
else {
tu=v->texcoords[0];
tv=v->texcoords[1];
if (tu<minu) minu=tu;
if (tv<minv) minv=tv;
}
v=v->next;
}
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; i<strip->vertex_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; 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;
/*}}} */
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; 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;
}
/*}}} */
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; 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;
}
/*}}} */
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; 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]=*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;
}
}
/*}}} */