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>
574 lines
13 KiB
C++
574 lines
13 KiB
C++
/*
|
|
FILE : testf15.c
|
|
PROJECT : pxpl5 renderer example - F15 squadron
|
|
Author : Phil Atkin
|
|
|
|
|
|
(C) Division Ltd 1994.
|
|
|
|
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
#include <math.h>
|
|
#include "dpl5.h"
|
|
#include "boot.h"
|
|
#include "startup.h"
|
|
#include "spline.h"
|
|
#include "camera.h"
|
|
|
|
char *progname;
|
|
|
|
int860 link_A, link_B;
|
|
extern int magicLeftVal,
|
|
magicRightVal;
|
|
/*{{{ void eyeStuff ( VIEW *view )*/
|
|
void eyeStuff ( VIEW *view, int left )
|
|
{
|
|
float scale=1.0;
|
|
|
|
PAZidMatrix(view->f);
|
|
PAZidMatrix(view->b);
|
|
if (left) scale *= -1.0f;
|
|
|
|
if (left != (-1))
|
|
PAZtranslatePair (view->f, view->b, scale*1.275, 0, 0 );
|
|
PAZrotatePair (view->f, view->b, 180, PAZ_Y );
|
|
PAZtranslatePair (view->f, view->b, 0, 0, -102 );
|
|
|
|
if (left == (-1)) view->shift_x=0.0;
|
|
else if (left) view->shift_x=0.2147;
|
|
else view->shift_x=-0.2147;
|
|
|
|
/* view->shift_y = 0.0f; */
|
|
|
|
PAZwriteView ( view );
|
|
}
|
|
/*}}} */
|
|
|
|
#define MAX_PLANES 5
|
|
|
|
static int planes_inited=0;
|
|
static int camera_inited=0;
|
|
cntl_point *splinehead=NULL;
|
|
static float flight_t;
|
|
static MATRIX flight_m;
|
|
|
|
typedef struct s_plane {
|
|
cntl_point *cntl;
|
|
float t;
|
|
MATRIX orig;
|
|
} plane_cntl_type;
|
|
|
|
plane_cntl_type plane_cntl[16];
|
|
|
|
static void check_matrix ( MATRIX m, char *s )
|
|
{
|
|
MATRIX tmp;
|
|
MATRIX res;
|
|
float hyp;
|
|
int i, j;
|
|
|
|
PAZinvert ( tmp, m );
|
|
PAZconcat ( res, m, tmp, 1 );
|
|
|
|
for (i=0; i<4; i++ ) {
|
|
for (j=0; j<4; j++ ) {
|
|
float t=res[i][j];
|
|
hyp+=t*t;
|
|
}
|
|
}
|
|
|
|
if ((hyp < 3.99f) || (hyp > 4.01f)) {
|
|
printf("MATRIX %s >>>>>\n", s );
|
|
printf ( " [ %3.3f, %3.3f, %3.3f, %3.3f ]\n", m[0][0], m[0][1], m[0][2], m[0][3] );
|
|
printf ( " [ %3.3f, %3.3f, %3.3f, %3.3f ]\n", m[1][0], m[1][1], m[1][2], m[1][3] );
|
|
printf ( " [ %3.3f, %3.3f, %3.3f, %3.3f ]\n", m[2][0], m[2][1], m[2][2], m[2][3] );
|
|
printf ( " [ %3.3f, %3.3f, %3.3f, %3.3f ]\n", m[3][0], m[3][1], m[3][2], m[3][3] );
|
|
printf("concat with inverse %s >>>>>\n", s );
|
|
printf ( " [ %3.3f, %3.3f, %3.3f, %3.3f ]\n", res[0][0], res[0][1], res[0][2], res[0][3] );
|
|
printf ( " [ %3.3f, %3.3f, %3.3f, %3.3f ]\n", res[1][0], res[1][1], res[1][2], res[1][3] );
|
|
printf ( " [ %3.3f, %3.3f, %3.3f, %3.3f ]\n", res[2][0], res[2][1], res[2][2], res[2][3] );
|
|
printf ( " [ %3.3f, %3.3f, %3.3f, %3.3f ]\n", res[3][0], res[3][1], res[3][2], res[3][3] );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
static float atan2deg ( float dz, float dx )
|
|
{
|
|
float angle;
|
|
if ((dx*dx) < 0.0001f) {
|
|
angle=(dz>0) ? 90.0f : -90.0f;
|
|
return angle;
|
|
}
|
|
else {
|
|
return (180.0f / 3.1415926535f) * atan2 ( dz, dx );
|
|
/*
|
|
if (dx>0)
|
|
return angle;
|
|
else
|
|
return 180.0f + angle;
|
|
*/
|
|
}
|
|
}
|
|
|
|
static void xformpoint ( POINT q, POINT p, MATRIX m )
|
|
{
|
|
POINT r;
|
|
int i;
|
|
|
|
for (i=0; i<4; i++ ) {
|
|
r[i]=(p[0]*m[0][i])+
|
|
(p[1]*m[1][i])+
|
|
(p[2]*m[2][i])+
|
|
(p[3]*m[3][i]);
|
|
}
|
|
memcpy ( q, r, sizeof(POINT));
|
|
}
|
|
|
|
void look_at ( VIEW *v, float *from, float *at, float z_spin )
|
|
{
|
|
/* construct a view from 2 points */
|
|
float dx, dy, dz;
|
|
float px, py, pz;
|
|
float thetax, thetay, thetaz;
|
|
float yaw, roll;
|
|
MATRIX m;
|
|
POINT p, q;
|
|
|
|
/* put 'at' at origin, construct a vector from 'from' */
|
|
px=from[0]; py=from[1]; pz=from[2];
|
|
|
|
dx=at[0]-px;
|
|
dy=at[1]-py;
|
|
dz=at[2]-pz;
|
|
|
|
thetaz=0.0f;
|
|
thetay=0.0f;
|
|
thetax=0.0f;
|
|
|
|
p[0]=dx;
|
|
p[1]=dy;
|
|
p[2]=dz;
|
|
p[3]=1;
|
|
|
|
yaw=-atan2deg ( dz, dx );
|
|
PAZidMatrix ( m );
|
|
PAZrotate ( m, -yaw, PAZ_Y, 1 );
|
|
xformpoint ( q, p, m );
|
|
|
|
roll=atan2deg(q[1], q[0] );
|
|
|
|
/* project onto x-z plane, assuming camera is initially looking down -z */
|
|
PAZidMatrix ( v->f );
|
|
|
|
/* apply angles to matrix */
|
|
|
|
PAZrotate ( v->f, z_spin, PAZ_Z, 1 );
|
|
PAZrotate ( v->f, roll, PAZ_X, 1 );
|
|
PAZrotate ( v->f, yaw-90.0f, PAZ_Y, 1 );
|
|
|
|
PAZtranslate( v->f, px, py, pz, 1 );
|
|
|
|
}
|
|
|
|
float evalx, evaly, evalz;
|
|
float tx, ty, tz, theta=0, dtheta=0, flight_r;
|
|
static float camera_t=0.0f;
|
|
static cntl_point *camerahead=NULL;
|
|
|
|
|
|
void cameradicking ( VIEW *eye,
|
|
INSTANCE *look_at_me,
|
|
float scale_fac,
|
|
float dt )
|
|
{
|
|
cntl_point *p=camerahead;
|
|
float t=camera_t;
|
|
float px, py, pz, rx, ry, rz;
|
|
POINT evalp;
|
|
|
|
if (camera_inited == 0) {
|
|
camera_inited=1;
|
|
p=init_splines("camera.spl");
|
|
t=0;
|
|
}
|
|
|
|
px=eval(p->x_pos_cubic, t );
|
|
py=eval(p->y_pos_cubic, t );
|
|
pz=eval(p->z_pos_cubic, t );
|
|
|
|
rx=eval(p->x_rot_cubic, t );
|
|
ry=eval(p->y_rot_cubic, t );
|
|
rz=eval(p->z_rot_cubic, t );
|
|
|
|
camerahead=walk_spline ( p, &t, dt );
|
|
camera_t=t;
|
|
|
|
/* we have wobbled the spline according to the file - now build the
|
|
view matrix */
|
|
|
|
eye->f[3][0]=px+look_at_me->f[3][0];
|
|
eye->f[3][1]=py+look_at_me->f[3][1];
|
|
eye->f[3][2]=pz+look_at_me->f[3][2];
|
|
|
|
evalp[0]=evalx;
|
|
evalp[1]=evaly;
|
|
evalp[2]=evalz;
|
|
|
|
/*
|
|
look_at ( eye, &eye->f[3][0], &look_at_me->f[3][0], rz );
|
|
*/
|
|
look_at ( eye, &eye->f[3][0], evalp, rz );
|
|
PAZwriteViewMatrix ( eye );
|
|
/* check_matrix ( eye->f, "view" ); */
|
|
}
|
|
|
|
void planedicking ( INSTANCE *inst, int planeId,
|
|
float scale, float dt, float dplane )
|
|
{
|
|
float px, py, pz, rx, ry, rz;
|
|
cntl_point *p;
|
|
float t;
|
|
int i;
|
|
MATRIX camera_target;
|
|
|
|
|
|
if (planes_inited == 0) {
|
|
planes_inited=1;
|
|
splinehead=init_splines("planes.spl");
|
|
|
|
for (i=1; i<MAX_PLANES; i++) {
|
|
float angle;
|
|
float fi=(float) i;
|
|
|
|
angle=fi * (3.1415926f * 2.0f) / (MAX_PLANES-1);
|
|
|
|
plane_cntl[i].cntl=splinehead;
|
|
plane_cntl[i].t=fi * dplane;
|
|
|
|
PAZidMatrix ( plane_cntl[i].orig );
|
|
PAZtranslate ( plane_cntl[i].orig,
|
|
10.3f*cos(angle), 0, 11.7f*sin(angle), 1 );
|
|
}
|
|
PAZidMatrix ( plane_cntl[0].orig );
|
|
|
|
plane_cntl[0].cntl=splinehead;
|
|
plane_cntl[0].t=dplane;
|
|
}
|
|
|
|
p=plane_cntl[planeId].cntl;
|
|
t=plane_cntl[planeId].t;
|
|
|
|
PAZidMatrix ( inst->f );
|
|
|
|
px=eval(p->x_pos_cubic, t );
|
|
py=eval(p->y_pos_cubic, t );
|
|
pz=eval(p->z_pos_cubic, t );
|
|
|
|
rx=eval(p->x_rot_cubic, t );
|
|
ry=eval(p->y_rot_cubic, t );
|
|
rz=eval(p->z_rot_cubic, t );
|
|
|
|
|
|
plane_cntl[planeId].cntl=walk_spline ( p, &plane_cntl[planeId].t, dt );
|
|
|
|
PAZscale ( inst->f, scale, scale, scale, 1 );
|
|
if (planeId == 0) {
|
|
PAZidMatrix ( camera_target );
|
|
PAZscale ( camera_target, scale, scale, scale, 1 );
|
|
}
|
|
/* the above scale should have brought us up to 1.0 ish in plane space */
|
|
/* now apply the spline */
|
|
|
|
PAZtranslate ( inst->f, px, py, pz, 1 );
|
|
PAZrotate ( inst->f, rz, PAZ_Z, 1 );
|
|
PAZrotate ( inst->f, rx, PAZ_X, 1 );
|
|
PAZrotate ( inst->f, ry, PAZ_Y, 1 );
|
|
PAZconcat ( inst->f, inst->f, plane_cntl[planeId].orig, 1 );
|
|
|
|
|
|
if (planeId==0) {
|
|
float rad=theta*3.1415926535f/180.0f;
|
|
|
|
theta+=dtheta;
|
|
tx=flight_r*cos(rad);
|
|
tz=flight_r*sin(rad);
|
|
}
|
|
|
|
PAZrotate ( inst->f, 180.0f-theta, PAZ_Y, 1 );
|
|
PAZtranslate ( inst->f, tx, 0, tz, 1 );
|
|
PAZscale ( inst->f, 6, 6, 6, 1 );
|
|
|
|
if (planeId == 0) {
|
|
PAZconcat ( camera_target, camera_target, plane_cntl[planeId].orig, 1 );
|
|
PAZrotate ( camera_target, 180.0f-theta, PAZ_Y, 1 );
|
|
PAZtranslate ( camera_target, tx, 0, tz, 1 );
|
|
PAZscale ( camera_target, 6, 6, 6, 1 );
|
|
evalx=camera_target[3][0];
|
|
evaly=camera_target[3][1];
|
|
evalz=camera_target[3][2];
|
|
}
|
|
}
|
|
|
|
|
|
void squadron_antics ( INSTANCE **planes, VIEW *eye, VIEW *rye, float scale_fac, int base, int times )
|
|
{
|
|
float theta;
|
|
int i, j;
|
|
float then, now;
|
|
|
|
if (rye == NULL)
|
|
eyeStuff ( eye, -1 );
|
|
else {
|
|
eyeStuff ( eye, 0 );
|
|
eyeStuff ( rye, 1 );
|
|
}
|
|
|
|
|
|
flight_r=26000;
|
|
dtheta=0.13;
|
|
|
|
for (i=base; i<times; i++) {
|
|
int nulls=0;
|
|
|
|
for (j=0; j<MAX_PLANES; j++) {
|
|
planedicking ( planes[j], j,
|
|
scale_fac, (j/392.0f)+0.034f, (j/283.0f)+0.007f );
|
|
PAZwriteMatrix ( planes[j] );
|
|
}
|
|
cameradicking(eye, planes[0], scale_fac, 0.02f );
|
|
PAZrenderScene();
|
|
}
|
|
}
|
|
|
|
/*{{{ char *makeVizName ( char *name )*/
|
|
char vizStr [256];
|
|
|
|
char *makeVizName ( char *name )
|
|
{
|
|
char *root;
|
|
|
|
if ((root=getenv("VIZPATH")) == NULL)
|
|
return(name);
|
|
else {
|
|
strcpy ( vizStr, root );
|
|
strcat ( vizStr, name );
|
|
return ( vizStr );
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ char *makeTexName ( char *name )*/
|
|
char texStr [256];
|
|
|
|
char *makeTexName ( char *name )
|
|
{
|
|
char *root;
|
|
|
|
if ((root=getenv("TEXTURE")) == NULL)
|
|
return(name);
|
|
else {
|
|
strcpy ( vizStr, root );
|
|
strcat ( vizStr, name );
|
|
if (strchr(vizStr, '.')==NULL) {
|
|
strcat(vizStr, ".svt");
|
|
}
|
|
return ( vizStr );
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ char *makedplName ( char *name )*/
|
|
char *makedplName ( char *dplstr, char *name )
|
|
{
|
|
char *root;
|
|
|
|
if ((root=getenv("DVIEWBIN")) == NULL)
|
|
return(name);
|
|
else {
|
|
strcpy ( dplstr, root );
|
|
strcat ( dplstr, name );
|
|
|
|
return ( dplstr );
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ int env2hex ()*/
|
|
int env2hex ( char *env_str, int default_v )
|
|
{
|
|
char *s;
|
|
int v;
|
|
|
|
if (s = getenv(env_str)) {
|
|
if (sscanf(s, "%x", &v) == 1) {
|
|
return v;
|
|
}
|
|
}
|
|
|
|
printf ("Defaulting on %s to 0x%x\n", env_str, default_v );
|
|
|
|
return default_v;
|
|
}
|
|
/*}}} */
|
|
/*{{{ static OBJECT *load_flames( char *fname )*/
|
|
static OBJECT *load_flames( char *fname )
|
|
{
|
|
OBJECT *flame;
|
|
|
|
FILE *fp=fopen(makeTexName(fname), "rb" );
|
|
int texels[32];
|
|
int total_texels=0, n_read;
|
|
|
|
|
|
if (fp) {
|
|
printf ("load flames\n" );
|
|
|
|
for (n_read=fread ( texels, 1, 32*4, fp ); n_read; n_read=fread(texels,1,32*4,fp )) {
|
|
PAZfxtexels ( texels, 32 );
|
|
total_texels+=32;
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
printf ( "%d texels read\n", total_texels );
|
|
|
|
flame=PAZcreateObject ( makeVizName("flame.v2z"), makeTexName );
|
|
return flame;
|
|
}
|
|
/*}}} */
|
|
/*{{{ int nain ( int argc, char *argv[])*/
|
|
int nain ( int argc, char *argv[])
|
|
{
|
|
LIGHTSOURCE *bulb1, *bulb2, *bulb3, *bulb4, *bulb5, *bulb6;
|
|
INSTANCE *planes[MAX_PLANES];
|
|
INSTANCE *groundinst[25];
|
|
OBJECT *obj;
|
|
OBJECT *groundobj[25];
|
|
SCENE *s;
|
|
VIEW *eye, *rye;
|
|
OBJECT *F15, *F16, *flames;
|
|
float t, scale_fac=0.1;
|
|
char *objname;
|
|
int g, i, j, made, ramp;
|
|
|
|
|
|
s = initialize_all ( 0, -1, &eye, &rye );
|
|
|
|
sscanf(argv[1], "%f", &scale_fac );
|
|
|
|
PAZfog ( 1, 15000.0f, 26244.0f, 0.4, 0.5, 0.6 );
|
|
flames=load_flames("allovem.svt");
|
|
|
|
printf ("Making hills\n" );
|
|
g=0;
|
|
for (i=0; i<5; i++) {
|
|
for (j=0; j<5; j++) {
|
|
INSTANCE *terrinst;
|
|
OBJECT *terrobj;
|
|
|
|
char hilly[256];
|
|
sprintf(hilly, "terr%1d%1d.b2z", i*2, j*2 );
|
|
|
|
terrobj=PAZcreateObject(makeVizName(hilly), makeTexName);
|
|
terrinst=PAZcreateInstance();
|
|
terrinst->enable=1;
|
|
terrinst->obj=terrobj;
|
|
PAZwriteInstance ( terrinst );
|
|
|
|
PAZscale ( terrinst->f,
|
|
10*scale_fac, 0.41*scale_fac, 10*scale_fac, 1 );
|
|
PAZtranslate ( terrinst->f, 10.0, -14*scale_fac, 10.0, 1 );
|
|
PAZwriteMatrix ( terrinst );
|
|
groundobj[g]=terrobj;
|
|
groundinst[g]=terrinst;
|
|
g++;
|
|
}
|
|
}
|
|
printf ("Made hills\n" );
|
|
printf ("Making sky\n" );
|
|
{
|
|
OBJECT *skyobj;
|
|
INSTANCE *skyinst;
|
|
|
|
skyobj=PAZcreateObject(makeVizName("mtl_frig.v2z"), makeTexName);
|
|
skyinst=PAZcreateInstance();
|
|
skyinst->obj=skyobj;
|
|
skyinst->enable=1;
|
|
PAZscalePair ( skyinst->f, skyinst->b,
|
|
50*scale_fac, 50*scale_fac, 50*scale_fac );
|
|
PAZtranslatePair ( skyinst->f, skyinst->b, 0, 8*scale_fac, 0 );
|
|
PAZwriteInstance ( skyinst );
|
|
}
|
|
|
|
F15=PAZcreateObject ( makeVizName("F15.v2z"), makeTexName );
|
|
F16=PAZcreateObject ( makeVizName("F16.v2z"), makeTexName );
|
|
|
|
for (i=0; i< MAX_PLANES; i++) {
|
|
INSTANCE *p=(planes[i]=PAZcreateInstance());
|
|
if ((i&1) ==0)
|
|
p->obj=F15;
|
|
else
|
|
p->obj=F16;
|
|
p->enable=1;
|
|
PAZidMatrixPair ( p->f, p->b );
|
|
PAZwriteInstance ( p );
|
|
}
|
|
|
|
/* create 3 light bulbs */
|
|
|
|
bulb1=PAZcreateLight ();
|
|
PAZinitLight ( bulb1, light_directional, 0.99, 0.99, 0.79, 0, 1, 0 );
|
|
PAZwriteLight ( bulb1 );
|
|
|
|
|
|
bulb2=PAZcreateLight ();
|
|
PAZinitLight ( bulb2, light_ambient, 0.2, 0.3, 0.4, 0, 0, 0 );
|
|
PAZwriteLight ( bulb2 );
|
|
|
|
PAZsetBackGND ( 0.2, 0.3, 0.6 );
|
|
|
|
while (1) {
|
|
squadron_antics ( planes, eye, rye, scale_fac, 0, 1000 );
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ int main ( int argc, char *argv[] )*/
|
|
|
|
int main ( int argc, char *argv[] )
|
|
{
|
|
link_A= 1;
|
|
link_B=-1;
|
|
|
|
progname=argv[0];
|
|
|
|
if (argc < 3) {
|
|
printf ("usage %s: <scale> <v2zfile>\n", argv[0] );
|
|
exit(666);
|
|
}
|
|
else {
|
|
char dplStr1 [256];
|
|
char dplStr2 [256];
|
|
|
|
magicLeftVal =env2hex("LEFTMAGIC", 0x3201);
|
|
magicRightVal=env2hex("RIGHTMAGIC", 0x3201);
|
|
|
|
near_clip=25.6/2;
|
|
far_clip =52428.8/2;
|
|
|
|
size_from_magic ( magicLeftVal );
|
|
|
|
start_dView ( makedplName ( dplStr1, "pp5mon2.btl"),
|
|
NULL,
|
|
makedplName ( dplStr2, "pazpl5.mng"),
|
|
env2hex("TRANSPUTER", 0x150), 1, -1 );
|
|
|
|
nain ( argc, argv );
|
|
}
|
|
}
|
|
/*}}} */
|