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

916 lines
22 KiB
C++

/*{{{ about sfx.c*/
/* ***************************************************************
Create, initialize and time-step explosions and other paz fx's
Organizing these is going to be fun.
Ideally, the PAZ effects should look just like instances in the display
list, but should reference effects rather than objects. In fact, they
should reference objects whos geometry is warped every frame. Then
everything else works, they can be enabled and disabled, and can be
inserted into right and left eye displaylists just fine. The random
number generator MUST be consistent between the eyes, or all hell will
break loose. For efficiency needs a prime-number sized random number
table, primed from a random function. So lets put a random table
into static space, and index off it.
*/
/*}}} */
/*{{{ includes / externs*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "macros.h"
#include "pazpl5.h"
#include "pazstore.h"
#include "matrix.h"
#include "names.h"
#include "i860sem.h"
#include "viz.h"
#include "material.h"
extern concurrency_control *shared_cntl;
extern int scene_resolved;
/*}}} */
/*{{{ reproducible random number support*/
/* as always, this is CASIO calculator output */
static float sfx_random_numbers[67] = { 0.990f, 0.196f, 0.030f, 0.452f,
0.165f, 0.663f, 0.737f, 0.774f,
0.996f, 0.269f, 0.676f, 0.786f,
0.123f, 0.474f, 0.755f, 0.919f,
0.873f, 0.603f, 0.628f, 0.045f,
0.089f, 0.509f, 0.413f, 0.416f,
0.304f, 0.011f, 0.083f, 0.110f,
0.177f, 0.602f, 0.810f, 0.181f,
0.723f, 0.394f, 0.035f, 0.873f,
0.678f, 0.331f, 0.407f, 0.499f,
0.132f, 0.210f, 0.081f, 0.550f,
0.344f, 0.894f, 0.469f, 0.307f,
0.641f, 0.936f, 0.779f, 0.833f,
0.373f, 0.915f, 0.972f, 0.887f,
0.019f, 0.613f, 0.540f, 0.898f,
0.755f, 0.689f, 0.076f, 0.173f,
0.870f, 0.825f, 0.364f };
static int sfx_random_ix = 0;
static int sfx_random_base = 0;
static float float_0to1 ()
{
sfx_random_ix++;
if (sfx_random_ix >= 67)
sfx_random_ix=0;
return sfx_random_numbers[sfx_random_ix];
}
/*}}} */
#define PAZ_X X
#define PAZ_Y Y
#define PAZ_Z Z
/*{{{ explosion structure*/
#define FRAG_TRIANGLES 24
#define FRAG_SPHERES 32
#define bang_type_poly 0
#define bang_type_sphere 1
typedef struct s_bang {
int type;
INSTANCE *inst;
POINT velocity [ FRAG_SPHERES];
POINT translate [ FRAG_SPHERES];
int below_ground[ FRAG_SPHERES];
float blast_radius;
float switch_off;
int n_below;
int cool;
float sphere_rad;
float dt;
int frame_number;
} big_bang;
/*}}} */
#define MAX_PAZ_EXPLOSIONS 8
#define MAX_PAZ_FIRES 8
big_bang *paz_explosions[MAX_PAZ_EXPLOSIONS];
int paz_explosions_active=0;
static int first_bang=1;
static int first_mtl =1;
/*{{{ static void makeBangMtls(void)*/
static void makeBangMtls(void)
{
MATERIAL *mtl;
if (first_mtl==0)
return;
/* printf ("makeBangMtls\n" ); */
first_mtl=0;
mtl=create_material();
add_material(mtl);
strcpy ( mtl->material_name, "bang_50_perc" );
mtl->kd[0]=1.0f;
mtl->kd[1]=0.8f;
mtl->kd[2]=0.5f;
mtl->opacity=0.51f;
mtl=create_material();
add_material(mtl);
strcpy ( mtl->material_name, "bang_frag" );
mtl->kd[0]=0.99f;
mtl->kd[1]=0.99f;
mtl->kd[2]=0.99f;
mtl=create_material();
add_material(mtl);
strcpy ( mtl->material_name, "bang_gore" );
mtl->kd[0]=0.99f;
mtl->kd[1]=0.1f;
mtl->kd[2]=0.1f;
/* printf ("made bangMtls\n" ); */
}
/*}}} */
/*{{{ static VERTEX *vertex_block ( int verts, VSTRIP *v )*/
static VERTEX *vertex_block ( int verts, VSTRIP *v )
{
VERTEX *solid, *vert;
int i;
solid=_NewVertices(verts);
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;
return solid;
}
/*}}} */
/*{{{ static void initBang ( big_bang *bang, int bang_type,*/
static void initBang ( big_bang *bang,
int bang_type,
float blast_radius,
float frag_size,
float frag_velocity,
float vertical_bias,
float switch_off,
float cook_r, float cook_g, float cook_b,
float variance,
int cool )
{
int i, j;
OBJECT *obj;
LOD *lod;
PATCH *p;
VSTRIP *v;
VERTEX *vert;
int limit=FRAG_TRIANGLES;
obj = nameToAddress ( bang->inst->obj, viz_createObject );
lod = obj->head;
p = lod->head;
v = p->head;
vert = v->head;
sfx_random_ix=sfx_random_base;
sfx_random_base++;
cook_r*=255.9f;
cook_g*=255.9f;
cook_b*=255.9f;
if (sfx_random_base >= 67)
sfx_random_base=0;
bang->dt=0.15f;
bang->cool=cool;
bang->type=bang_type;
bang->inst->enable=0;
bang->frame_number=0;
bang->switch_off = switch_off;
bang->blast_radius=blast_radius;
bang->n_below=0;
bang->sphere_rad=0.35f;
if (bang->type == bang_type_poly)
limit=FRAG_TRIANGLES;
else
limit=FRAG_SPHERES;
frag_velocity*=39.0f;
for (i=0; i<limit; i++ ) {
float rest, t;
bang->below_ground[i]=0;
bang->velocity[i][PAZ_X]=frag_velocity * (float_0to1() - 0.5f);
bang->velocity[i][PAZ_Y]=frag_velocity * ((float_0to1() - 0.5f) + vertical_bias);
bang->velocity[i][PAZ_Z]=frag_velocity * (float_0to1() - 0.5f);
vert->position[0]=frag_size * (float_0to1() - 0.5f);
vert->position[1]=frag_size * (float_0to1() - 0.3f);
vert->position[2]=frag_size * (float_0to1() - 0.5f);
vert->position[3]=0;
/*{{{ */
rest =1.0f - (variance * float_0to1());
t=rest*cook_r;
if (t>255.9f) t=255.9f;
/*}}} */
vert->normcol[0]=t;
/*{{{ */
rest =1.0f - (variance * float_0to1());
t=rest*cook_g;
if (t>255.9f) t=255.9f;
/*}}} */
vert->normcol[1]=t;
/*{{{ */
rest =1.0f - (variance * float_0to1());
t=rest*cook_b;
if (t>255.9f) t=255.9f;
/*}}} */
vert->normcol[2]=t;
if (bang->type == bang_type_poly) {
vert++;
vert->position[0]=frag_size * (float_0to1() - 0.5f);
vert->position[1]=frag_size * (float_0to1() - 0.3f);
vert->position[2]=frag_size * (float_0to1() - 0.5f);
vert->position[3]=0;
/*{{{ */
rest =1.0f - (variance * float_0to1());
t=rest*cook_r;
if (t>255.9f) t=255.9f;
/*}}} */
vert->normcol[0]=t;
/*{{{ */
rest =1.0f - (variance * float_0to1());
t=rest*cook_g;
if (t>255.9f) t=255.9f;
/*}}} */
vert->normcol[1]=t;
/*{{{ */
rest =1.0f - (variance * float_0to1());
t=rest*cook_b;
if (t>255.9f) t=255.9f;
/*}}} */
vert->normcol[2]=t;
vert++;
vert->position[0]=frag_size * (float_0to1() - 0.5f);
vert->position[1]=frag_size * (float_0to1() - 0.3f);
vert->position[2]=frag_size * (float_0to1() - 0.5f);
vert->position[3]=0;
/*{{{ */
rest =1.0f - (variance * float_0to1());
t=rest*cook_r;
if (t>255.9f) t=255.9f;
/*}}} */
vert->normcol[0]=t;
/*{{{ */
rest =1.0f - (variance * float_0to1());
t=rest*cook_g;
if (t>255.9f) t=255.9f;
/*}}} */
vert->normcol[1]=t;
/*{{{ */
rest =1.0f - (variance * float_0to1());
t=rest*cook_b;
if (t>255.9f) t=255.9f;
/*}}} */
vert->normcol[2]=t;
vert++;
}
else {
vert->position[3]=bang->sphere_rad;
vert++;
}
}
bound_patch ( p );
compute_pmesh_plane_eqns ( p, 0 );
reboundLOD ( lod );
reboundObject ( obj );
}
/*}}} */
/*{{{ static big_bang *createBang ( int type, float qual )*/
static big_bang *createBang ( int type, float qual )
{
surface s;
int i, strip_shade;
float *fp;
big_bang *bang;
OBJECT *obj;
LOD *lod;
PATCH *p;
PATCHISSIMO *pi;
VSTRIP *v;
VERTEX *vert;
VERTEX *tess;
OBJLIST *sg=&sceneGeometry;
/*{{{ initialize bang structure*/
makeBangMtls();
bang=(big_bang *) malloc(sizeof(big_bang));
bang->type=type;
bang->inst=PAZcreateInstance();
bang->inst->obj=NULL;
bang->inst->enable=0;
s.COOKED=1;
/*}}} */
/*{{{ start up the PAZ stuff, object and lod*/
_InitObject(obj=_NewObject());
_InitLOD(lod=_NewLOD());
lod->vertex_count=0;
lod->switch_in =0.0f;
lod->switch_out=1024.0f * 1024.0f;
bang->inst->obj=(OBJECT *) newName ( obj, viz_createObject );
/*}}} */
/*{{{ build frag geometry*/
/* printf ("createBang making frag geometry\n" ); */
if (type == bang_type_poly) {
/*{{{ pmesh*/
/*{{{ build pmesh header*/
/* printf ("createBang went InitPatch\n" ); */
_InitPatch((PATCH *) (pi=_NewPatchissimo()));
pi->sem=nextSem();
InitSem (pi->sem);
p=(PATCH *) pi;
strcpy ( p->fmaterial_name, "bang_frag" );
strcpy ( p->bmaterial_name, "bang_frag" );
p->patch_type = patch_type_pmesh;
strip_shade=strip_shade_coloured;
/*}}} */
/* printf ("createBang building vertices\n" ); */
/*{{{ build vertices*/
_InitVstrip(v=_NewVstrip());
vertex_block ( FRAG_TRIANGLES*3, v );
tess=v->head;
vert=tess;
v->strip_shade=strip_shade;
add_item(p, v);
p->vertex_count=v->vertex_count;
if (v->vertex_count > shared_cntl->length_longest_verts)
shared_cntl->length_longest_verts=v->vertex_count;
/*}}} */
/* printf ("createBang building connections\n" ); */
/*{{{ build connexions*/
_InitVstrip(v=_NewVstrip());
v->strip_shade=strip_shade;
vertex_block ( FRAG_TRIANGLES, v );
vert=v->head;
for ( i=0; i<FRAG_TRIANGLES; i++ ) {
int three_i = 3*i;
int *ipos = (int *) &(vert->position[0]);
ipos[0]=(int) (&tess[three_i]);
ipos[1]=(int) (&tess[three_i+1]);
ipos[2]=(int) (&tess[three_i+2]);
vert++;
}
add_item(p, v);
if (v->vertex_count > shared_cntl->length_longest_tris)
shared_cntl->length_longest_tris=v->vertex_count;
/*}}} */
/*}}} */
}
else {
#if 0
/*{{{ 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;
/*}}} */
/*}}} */
initBang ( bang, bang->type, qual, 20.0f, 12.0f, 3.0f, -10.0f );
bound_spatch ( p );
#endif
}
lod->vertex_count+=p->vertex_count;
add_item ( lod, p );
/*}}} */
add_item (obj, lod);
reconnectLODs ( obj );
add_item ( sg, obj );
initBang ( bang, bang_type_poly, 20.0f, 8.0f, 2.5f, -8.0f,
0.2f, 0.2, 0.2, 0.2, 0.3, 0 );
scene_resolved=0;
return bang;
}
/*}}} */
/*{{{ static int step_bang ( big_bang *bang )*/
static int step_bang ( big_bang *bang )
{
int i, ret;
float g=9.8f;
int xforms, stop_count;
OBJECT *obj;
LOD *lod;
PATCH *p;
VSTRIP *v;
VERTEX *vert;
float rcool_factor=0.985f;
float gcool_factor=0.96f;
float bcool_factor=0.935f;
int tweak_colour=bang->cool;
/* printf ("step_bang 0x%x\n", bang ); */
if (bang->inst==NULL) {
return;
}
else {
obj=(OBJECT *) nameToAddress(bang->inst->obj, viz_createObject );
if (obj==NULL) return;
}
lod = obj->head;
p = lod->head;
v = p->head;
vert = v->head;
/* right - v is now the vertex list for the frags */
if (bang->type == bang_type_poly) {
stop_count=FRAG_TRIANGLES;
xforms =FRAG_TRIANGLES;
}
else {
stop_count=FRAG_SPHERES;
xforms =FRAG_SPHERES;
/* bang->sphere_rad*=0.982; */
}
for (i=0; i<xforms; i++) {
/*{{{ do a frag (triangle or sphere)*/
float dx, dy, dz;
bang->velocity[i][PAZ_Y]-=bang->dt*g;
dx=bang->translate[i][PAZ_X]=bang->dt*bang->velocity[i][PAZ_X];
dy=bang->translate[i][PAZ_Y]=bang->dt*bang->velocity[i][PAZ_Y];
dz=bang->translate[i][PAZ_Z]=bang->dt*bang->velocity[i][PAZ_Z];
vert->position[0]+=dx;
vert->position[1]+=dy;
vert->position[2]+=dz;
if (tweak_colour) {
vert->normcol[0]*=rcool_factor;
vert->normcol[1]*=gcool_factor;
vert->normcol[2]*=bcool_factor;
}
if (vert->position[1] < bang->switch_off) {
if (bang->below_ground[i] == 0) {
bang->below_ground[i]=1;
bang->n_below++;
}
}
if (bang->type==bang_type_poly) {
float r=vert->normcol[0],
g=vert->normcol[1],
b=vert->normcol[2];
vert++;
vert->position[0]+=dx;
vert->position[1]+=dy;
vert->position[2]+=dz;
vert->normcol[0]=r;
vert->normcol[1]=g;
vert->normcol[2]=b;
vert++;
vert->position[0]+=dx;
vert->position[1]+=dy;
vert->position[2]+=dz;
vert->normcol[0]=r;
vert->normcol[1]=g;
vert->normcol[2]=b;
}
else {
vert->position[3]=bang->sphere_rad;
}
/*}}} */
vert++;
}
if (bang->type == bang_type_poly)
bound_patch ( p );
else
bound_spatch ( p );
bang->frame_number++;
bang->dt=0.15; /* 1/8th sec */
reboundLOD ( lod );
reboundObject ( obj );
if (bang->n_below == stop_count) {
bang->inst->enable=0;
}
else {
ret=1;
}
return ret;
}
/*}}} */
/*{{{ int sfx_init()*/
int sfx_inited=0;
int sfx_init ()
{
int i;
if (sfx_inited)
return;
sfx_inited=1;
for (i=0; i<MAX_PAZ_EXPLOSIONS; i++ ) {
int j;
INSTANCE *inst;
paz_explosions[i]=createBang(bang_type_poly, 0.99f);
initBang ( paz_explosions[i],
bang_type_poly,
20.0f + 3.0f*float_0to1(),
10.0f + 3.0f*float_0to1(),
1.0f + 3.0f*float_0to1(),
0.4f,
-3.0f - 3.0f*float_0to1(),
0.2f, 0.3f, 0.2f, 0.3, 0 );
inst=paz_explosions[i]->inst;
_idmatrix ( inst->f );
_translate ( inst->f,
(float_0to1() - 0.5f) * 30*(i&3),
30.0f,
(float_0to1() + 0.5f) * 30*(i>>2),
1 );
_invert ( inst->b, inst->f );
}
}
/*}}} */
/*{{{ void PAZsfx ( int code, float qual, MATRIX m )*/
static int active_fx=0;
void PAZsfx ( int code, float qual, MATRIX m )
{
big_bang *bang;
if (sfx_inited == 0)
return;
bang=paz_explosions[active_fx];
active_fx++;
if (active_fx == MAX_PAZ_EXPLOSIONS)
active_fx=0;
if (code == 0) {
/*{{{ small explosion, small frags*/
initBang ( bang, bang->type,
18.0f, 13.0f, 1.2f,
0.2f,
-6.0f-m[3][1],
0.19f, 0.2f, 0.2f, 0.3, 0 );
bang->inst->enable=1;
memcpy ( bang->inst->f, m, sizeof(MATRIX));
_invert ( bang->inst->b, bang->inst->f );
/*}}} */
}
else if (code == 1) {
/*{{{ medium explosion, medium frags*/
MATRIX tmp;
/* explosion 0 - hi-velocity, not much upward bias */
memcpy ( tmp, m, sizeof(MATRIX));
initBang ( bang, bang->type,
42.0f, 41.0f, 3.5f,
0.31f,
-36.0f-m[3][1],
0.99f, 0.99f, 0.91f, 0.2, 1 );
bang->inst->enable=1;
_rotY ( tmp, 56.0f, 0 );
_translate ( tmp,
0,
30.0f + (float_0to1() * 30.0f),
0, 0 );
/* explosion 1 - lower-velocity, more upward bias */
memcpy ( bang->inst->f, tmp, sizeof(MATRIX));
_invert ( bang->inst->b, bang->inst->f );
bang=paz_explosions[active_fx];
active_fx++;
if (active_fx == MAX_PAZ_EXPLOSIONS)
active_fx=0;
memcpy ( tmp, m, sizeof(MATRIX));
initBang ( bang, bang->type,
42.0f, 41.0f, 2.8f,
0.75f,
-36.0f-m[3][1],
0.91f, 0.91f, 0.91f, 0.2, 1 );
bang->inst->enable=1;
memcpy ( bang->inst->f, tmp, sizeof(MATRIX));
_invert ( bang->inst->b, bang->inst->f );
bang=paz_explosions[active_fx];
active_fx++;
if (active_fx == MAX_PAZ_EXPLOSIONS)
active_fx=0;
/*}}} */
}
else if (code == 2) {
/*{{{ small explosion, red frags*/
initBang ( bang, bang->type,
18.0f, 14.0f, 1.3f,
0.3f,
-6.0f-m[3][1],
0.99f, 0.2f, 0.2f, 0.3, 0 );
bang->inst->enable=1;
memcpy ( bang->inst->f, m, sizeof(MATRIX));
_invert ( bang->inst->b, bang->inst->f );
/*}}} */
}
else if (code == 3) {
/*{{{ big explosion(s), big frags*/
int i;
MATRIX tmp;
for (i=0; i<4; i++ ) {
memcpy ( tmp, m, sizeof(MATRIX));
initBang ( bang,
bang->type,
80.0f + 10.0f*float_0to1(),
45.0f + 15.0f*float_0to1(),
4.3f + 1.6f*float_0to1(),
0.25f + 0.2f*float_0to1(),
-36.0f-m[3][1],
0.99, 0.8, 0.85, 0.2, 1 );
bang->inst->enable=1;
_rotY ( tmp, (float) i * 56.0f, 0 );
_translate ( tmp,
60.0f*(float_0to1() - 0.5f),
float_0to1() * 30.0f,
60.0f*(float_0to1() - 0.5f), 0 );
memcpy ( bang->inst->f, tmp, sizeof(MATRIX));
_invert ( bang->inst->b, bang->inst->f );
bang=paz_explosions[active_fx];
active_fx++;
if (active_fx == MAX_PAZ_EXPLOSIONS)
active_fx=0;
}
/*}}} */
}
else {
printf ("Unknown sfx type\n" );
}
}
/*}}} */
/*{{{ void step_fx()*/
static int frig=0;
void step_fx()
{
int i;
big_bang *bang;
if (sfx_inited) {
for (i=0; i<MAX_PAZ_EXPLOSIONS; i++ ) {
bang=paz_explosions[i];
if (bang->inst->enable)
step_bang ( bang );
}
}
else
sfx_init();
}
/*}}} */