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>
491 lines
10 KiB
C++
491 lines
10 KiB
C++
|
|
|
|
/*
|
|
FILE pazstore.c
|
|
|
|
declarations of functions to play with
|
|
paz storage types
|
|
|
|
Phil Atkin
|
|
|
|
(c) Division Ltd. 1991
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <setjmp.h>
|
|
#include <stdarg.h>
|
|
#include "pazpl5.h"
|
|
#include "macros.h"
|
|
#include "matrix.h"
|
|
|
|
|
|
/*{{{ static float vertex_max ( VERTEX *p, int axis)*/
|
|
static float vertex_max ( VERTEX *p, int axis)
|
|
{
|
|
float t=p->position[axis];
|
|
|
|
for (p=p->next; p!=NULL; p=p->next )
|
|
t=max_of(p->position[axis], t);
|
|
return(t);
|
|
}
|
|
/*}}} */
|
|
/*{{{ static float vertex_min ( VERTEX *p, int axis)*/
|
|
static float vertex_min ( VERTEX *p, int axis)
|
|
{
|
|
float t=p->position[axis];
|
|
|
|
for (p=p->next; p!=NULL; p=p->next )
|
|
t=min_of(p->position[axis], t);
|
|
return(t);
|
|
}
|
|
/*}}} */
|
|
/*{{{ void build_bound ( POINT *bound, POINT mini, POINT maxi )*/
|
|
void build_bound ( POINT *bound, POINT mini, POINT maxi )
|
|
{
|
|
/* this leaves mini in 0, maxi in 7 */
|
|
int i, j, k;
|
|
|
|
for (i=0; i<2; i++ ) {
|
|
for (j=0; j<2; j++ ) {
|
|
for (k=0; k<2; k++ ) {
|
|
float *b=(float *) bound;
|
|
|
|
if (k&1) b[X]=maxi[X];
|
|
else b[X]=mini[X];
|
|
if (j&1) b[Y]=maxi[Y];
|
|
else b[Y]=mini[Y];
|
|
if (i&1) b[Z]=maxi[Z];
|
|
else b[Z]=mini[Z];
|
|
|
|
b[W]=1.0f;
|
|
bound++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ void bound_patch ( PATCH *p )*/
|
|
void bound_patch ( PATCH *p )
|
|
{
|
|
int axis;
|
|
POINT mini, maxi;
|
|
VSTRIP *v=p->head;
|
|
if (p==NULL) {
|
|
printf ("Attempt to bound NULL patch\n" );
|
|
return;
|
|
}
|
|
else if (p->head == NULL) {
|
|
printf ("Attempt to bound empty patch\n" );
|
|
return;
|
|
}
|
|
|
|
for (axis=X; axis<W; axis++ ) {
|
|
mini[axis]=vertex_min(v->head, axis );
|
|
maxi[axis]=vertex_max(v->head, axis );
|
|
}
|
|
|
|
if (p->patch_type == patch_type_patch) {
|
|
for (v=v->next; v!=NULL; v=v->next ) {
|
|
for (axis=X; axis<W; axis++ ) {
|
|
mini[axis]=min_of(mini[axis], vertex_min(v->head, axis ));
|
|
maxi[axis]=max_of(maxi[axis], vertex_max(v->head, axis ));
|
|
}
|
|
}
|
|
}
|
|
|
|
build_bound ( p->bound, mini, maxi );
|
|
}
|
|
/*}}} */
|
|
/*{{{ static float sphere_max ( VERTEX *p, int axis)*/
|
|
static float sphere_max ( VERTEX *p, int axis)
|
|
{
|
|
float t=p->position[axis]+p->position[W];
|
|
|
|
for (p=p->next; p!=NULL; p=p->next ) {
|
|
float tt=p->position[axis]+p->position[W];
|
|
t=max_of(tt, t );
|
|
}
|
|
return(t);
|
|
}
|
|
/*}}} */
|
|
/*{{{ static float sphere_min ( VERTEX *p, int axis)*/
|
|
static float sphere_min ( VERTEX *p, int axis)
|
|
{
|
|
float t=p->position[axis]-p->position[W];
|
|
|
|
for (p=p->next; p!=NULL; p=p->next ) {
|
|
float tt=p->position[axis]-p->position[W];
|
|
t=min_of(tt, t);
|
|
}
|
|
return(t);
|
|
}
|
|
/*}}} */
|
|
/*{{{ void bound_spatch ( PATCH *p )*/
|
|
void bound_spatch ( PATCH *p )
|
|
{
|
|
int axis;
|
|
POINT mini, maxi;
|
|
VSTRIP *v=p->head;
|
|
if (p==NULL) {
|
|
printf ("Attempt to bound NULL patch\n" );
|
|
return;
|
|
}
|
|
else if (p->head == NULL) {
|
|
printf ("Attempt to bound empty patch\n" );
|
|
return;
|
|
}
|
|
|
|
for (axis=X; axis<W; axis++ ) {
|
|
mini[axis]=sphere_min(v->head, axis );
|
|
maxi[axis]=sphere_max(v->head, axis );
|
|
}
|
|
|
|
for (v=v->next; v!=NULL; v=v->next ) {
|
|
for (axis=X; axis<W; axis++ ) {
|
|
mini[axis]=min_of(mini[axis], sphere_min(v->head, axis ));
|
|
maxi[axis]=max_of(maxi[axis], sphere_max(v->head, axis ));
|
|
}
|
|
}
|
|
build_bound ( p->bound, mini, maxi );
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void reboundLOD ( LOD *o )*/
|
|
void reboundLOD ( LOD *o )
|
|
{
|
|
int axis;
|
|
POINT mini, maxi;
|
|
PATCH *p=o->head;
|
|
|
|
memcpy(mini, p->bound, sizeof(POINT));
|
|
memcpy(maxi, p->bound[7], sizeof(POINT));
|
|
|
|
for (p=p->next; p!=NULL; p=p->next ) {
|
|
POINT *vmin=p->bound;
|
|
POINT *vmax=vmin+7;
|
|
|
|
for (axis=X; axis<W; axis++ ) {
|
|
|
|
mini[axis]=min_of(mini[axis], (*vmin)[axis] );
|
|
maxi[axis]=max_of(maxi[axis], (*vmax)[axis] );
|
|
}
|
|
}
|
|
for (axis=X; axis<W; axis++ )
|
|
o->bound[8][axis]=(mini[axis]+maxi[axis]) * 0.5f;
|
|
|
|
build_bound ( o->bound, mini, maxi );
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _BoundLOD ( LOD *o )*/
|
|
void _BoundLOD ( LOD *o )
|
|
{
|
|
int axis;
|
|
POINT mini, maxi;
|
|
PATCH *p=o->head;
|
|
|
|
bound_patch ( p );
|
|
|
|
memcpy(mini, p->bound, sizeof(POINT));
|
|
memcpy(maxi, p->bound[7], sizeof(POINT));
|
|
|
|
for (p=p->next; p!=NULL; p=p->next ) {
|
|
POINT *vmin=p->bound;
|
|
POINT *vmax=vmin+7;
|
|
|
|
bound_patch ( p );
|
|
|
|
for (axis=X; axis<W; axis++ ) {
|
|
|
|
mini[axis]=min_of(mini[axis], (*vmin)[axis] );
|
|
maxi[axis]=max_of(maxi[axis], (*vmax)[axis] );
|
|
}
|
|
}
|
|
|
|
for (axis=X; axis<W; axis++ )
|
|
o->bound[8][axis]=(mini[axis]+maxi[axis]) * 0.5f;
|
|
|
|
build_bound ( o->bound, mini, maxi );
|
|
}
|
|
/*}}} */
|
|
|
|
/* PAZ library calls */
|
|
/*{{{ void reboundObject ( OBJECT *o )*/
|
|
void reboundObject ( OBJECT *o )
|
|
{
|
|
int axis;
|
|
POINT mini, maxi;
|
|
LOD *l=o->head;
|
|
|
|
memcpy(mini, l->bound, sizeof(POINT));
|
|
memcpy(maxi, l->bound[7], sizeof(POINT));
|
|
|
|
for (l=l->next; l!=NULL; l=l->next ) {
|
|
POINT *vmin=l->bound;
|
|
POINT *vmax=vmin+7;
|
|
|
|
for (axis=X; axis<W; axis++ ) {
|
|
|
|
mini[axis]=min_of(mini[axis], (*vmin)[axis] );
|
|
maxi[axis]=max_of(maxi[axis], (*vmax)[axis] );
|
|
}
|
|
}
|
|
build_bound ( o->bound, mini, maxi );
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _BoundObject ( OBJECT *o )*/
|
|
void _BoundObject ( OBJECT *o )
|
|
{
|
|
int axis;
|
|
POINT mini, maxi;
|
|
LOD *l=o->head;
|
|
|
|
_BoundLOD ( l );
|
|
|
|
memcpy(mini, l->bound, sizeof(POINT));
|
|
memcpy(maxi, l->bound[7], sizeof(POINT));
|
|
|
|
for (l=l->next; l!=NULL; l=l->next ) {
|
|
POINT *vmin=l->bound;
|
|
POINT *vmax=vmin+7;
|
|
|
|
_BoundLOD ( l );
|
|
|
|
for (axis=X; axis<W; axis++ ) {
|
|
|
|
mini[axis]=min_of(mini[axis], (*vmin)[axis] );
|
|
maxi[axis]=max_of(maxi[axis], (*vmax)[axis] );
|
|
}
|
|
}
|
|
build_bound ( o->bound, mini, maxi );
|
|
}
|
|
/*}}} */
|
|
|
|
|
|
/*{{{ void _InitVertex ( VERTEX *v )*/
|
|
void _InitVertex ( VERTEX *v )
|
|
{
|
|
checkNull ( v, " initVertex" );
|
|
v->next=NULL;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _InitVstrip ( VSTRIP *v )*/
|
|
void _InitVstrip ( VSTRIP *v )
|
|
{
|
|
checkNull ( v, " initVstrip" );
|
|
v->next=NULL;
|
|
v->head=NULL;
|
|
v->tail=NULL;
|
|
v->vertex_count=0;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _InitPatch ( PATCH *p )*/
|
|
void _InitPatch ( PATCH *p )
|
|
{
|
|
checkNull ( p, " initPatch" );
|
|
|
|
p->fmaterial=NULL;
|
|
p->bmaterial=NULL;
|
|
|
|
p->next=NULL;
|
|
p->head=NULL;
|
|
p->tail=NULL;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _InitObject ( OBJECT *p )*/
|
|
void _InitObject ( OBJECT *p )
|
|
{
|
|
checkNull ( p, " initObject" );
|
|
p->next=NULL;
|
|
p->head=NULL;
|
|
p->tail=NULL;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _InitLOD ( LOD *l )*/
|
|
void _InitLOD ( LOD *l )
|
|
{
|
|
checkNull ( l, " initLOD" );
|
|
|
|
l->next=NULL;
|
|
l->head=NULL;
|
|
l->tail=NULL;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _InitLight ( LIGHTSOURCE *l )*/
|
|
void _InitLight ( LIGHTSOURCE *l )
|
|
{
|
|
checkNull ( l, " initLight" );
|
|
l->next=NULL;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _InitView ( VIEW *v )*/
|
|
void _InitView ( VIEW *v )
|
|
{
|
|
int *t;
|
|
char *s=" initView";
|
|
checkNull ( v, s );
|
|
|
|
t=(int *) malloc(32); /* URGH link_poly_list ? */
|
|
checkNull ( t, s );
|
|
v->buffer_A=t;
|
|
|
|
v->buffer_B=v->buffer_A; /* this is IMPORTANT */
|
|
|
|
_idmatrix( v->f );
|
|
_idmatrix( v->b );
|
|
|
|
v->next=NULL;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _InitInstance ( INSTANCE *p )*/
|
|
void _InitInstance ( INSTANCE *p )
|
|
{
|
|
int i;
|
|
|
|
checkNull ( p, " initInstance" );
|
|
p->next=NULL;
|
|
|
|
p->nest=NULL;
|
|
p->link=NULL;
|
|
p->daddy=NULL; /* uplink to parent */
|
|
|
|
p->obj=NULL;
|
|
p->lastLODscale=0.0f;
|
|
p->lastLODindex=0;
|
|
|
|
p->enable=3;
|
|
p->billboard=0;
|
|
|
|
p->f_material=NULL;
|
|
p->b_material=NULL;
|
|
|
|
p->f_texture=NULL;
|
|
p->b_texture=NULL;
|
|
|
|
_idmatrix( p->f );
|
|
_idmatrix( p->b );
|
|
}
|
|
/*}}} */
|
|
/*{{{ void _InitScene ( SCENE *p )*/
|
|
void _InitScene ( SCENE *p )
|
|
{
|
|
checkNull ( p, " initScene" );
|
|
p->next=NULL;
|
|
p->instances.head=NULL;
|
|
p->lights.head=NULL;
|
|
p->eyes.head=NULL;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void _LinkVertices ( VERTEX *start, int vertices )*/
|
|
void _LinkVertices ( VERTEX *start, int vertices )
|
|
{
|
|
VERTEX *v=start;
|
|
int i;
|
|
|
|
for (i=1; i<vertices; i++ ) {
|
|
v->next=v+1;
|
|
v=v->next;
|
|
}
|
|
v->next=NULL;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ PAZlist manipulation*/
|
|
/*
|
|
PAZlists are generic lists, with next, prev and data pointers.
|
|
The data pointer is cast to a void*, so we can link together
|
|
anything
|
|
*/
|
|
|
|
/*{{{ PAZlist *findPAZitem ( void *item, PAZlist **head, PAZlist **tail )*/
|
|
PAZlist *findPAZitem ( void *item, PAZlist **head, PAZlist **tail )
|
|
{
|
|
PAZlist *p=*head;
|
|
|
|
while (p) {
|
|
if (p->data == item) return p;
|
|
p=p->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*}}} */
|
|
/*{{{ void addPAZitem ( void *item, PAZlist **head, PAZlist **tail )*/
|
|
void addPAZitem ( void *item, PAZlist **head, PAZlist **tail )
|
|
{
|
|
PAZlist *p=(PAZlist *) malloc ( sizeof(PAZlist));
|
|
|
|
if (*head == NULL) {
|
|
*head=p;
|
|
*tail=p;
|
|
p->next=NULL;
|
|
p->prev=NULL;
|
|
p->data=item;
|
|
}
|
|
else {
|
|
p->prev=NULL;
|
|
p->next=*head;
|
|
p->next->prev=p;
|
|
*head=p;
|
|
p->data=item;
|
|
}
|
|
}
|
|
|
|
/*}}} */
|
|
/*{{{ void *removePAZitem ( PAZlist *p, PAZlist **head, PAZlist **tail )*/
|
|
void *removePAZitem ( PAZlist *p, PAZlist **head, PAZlist **tail )
|
|
{
|
|
PAZlist *prevItem, *nextItem;
|
|
void *contents;
|
|
|
|
/* printf ("removePAZitem\n" ); */
|
|
|
|
if (p==NULL) {
|
|
/* printf ( "NULL parameter, returning\n" ); */
|
|
return NULL;
|
|
}
|
|
else {
|
|
contents=p->data;
|
|
}
|
|
|
|
prevItem=p->prev;
|
|
nextItem=p->next;
|
|
|
|
if (prevItem==NULL) {
|
|
/* printf ( "prev==NULL, I am HEAD\n" ); */
|
|
*head=nextItem;
|
|
}
|
|
else {
|
|
/* printf ( "prev NOT NULL, patching prev->next to old next\n" ); */
|
|
prevItem->next=nextItem;
|
|
}
|
|
|
|
if (nextItem==NULL) {
|
|
/* printf ( "next==NULL, I am TAIL\n" ); */
|
|
*tail=prevItem;
|
|
}
|
|
else {
|
|
/* printf ( "next NOT NULL, patching next->prev to old prev\n" ); */
|
|
nextItem->prev=prevItem;
|
|
}
|
|
|
|
free(p);
|
|
|
|
return contents;
|
|
}
|
|
/*}}} */
|
|
|
|
|
|
/*}}} */
|
|
|
|
/*{{{ declare globals*/
|
|
VIEW *left=NULL, *right=NULL;
|
|
VERTEX *render_strip=NULL;
|
|
int output_device=0;
|
|
int link_A=0, link_B=0;
|
|
int raster=0, flip=0;
|
|
OBJLIST sceneGeometry;
|
|
/*}}} */
|