home *** CD-ROM | disk | FTP | other *** search
- /*
- ------------------------------------------------------------------
-
- Black Nebula
-
- File : 3drout.c
- Programmer: Colin Adams
- Date: 4/3/91
- Last Modified : 10/6/91
-
- ------------------------------------------------------------------
-
- */
-
- #define D3ROUT
- #define AMIGA_INCLUDES
-
- #include "3d.h"
-
- extern object myship;
- extern short swapflag, U_rot;
- extern short num_active[];
-
- extern struct BitMap my_bit_map;
- extern struct BitMap back_bit_map;
-
- short store1 = 0, store2 = 0;
-
- /* ------------------------------------------------------------------
- Fast Sin/Cos Routines
- ------------------------------------------------------------------
- */
-
- double deg(int degrees)
- /* converts degrees to radians */
- {
- double test = degrees;
- double one8 = 180;
-
- return 3.141592654/(one8/test);
- }
-
- void TrigSetUp(void)
- {
- register int i;
- FILE *fp;
-
- if(!(fp=fopen("trig.pre","r")))
- {
- printf("Creating trig tables...\n");
-
- for(i=0; i<=90; i++)
- {
- sintable[i] = ((double) sin(deg(i)) * 65536);
- costable[i] = ((double) cos(deg(i)) * 65536);
- }
-
- /* precalculate sin/cos for all quadrants */
-
- for(i=91; i<=360; i++)
- {
- short six = 0, cix = 0, rot = i;
-
- if(rot>=271)
- {
- rot = 360 - rot;
- six = 1;
- }
- else if(rot>=181)
- {
- rot -= 180;
- six = cix = 1;
- }
- else if(rot>=91)
- {
- rot = 180 - rot;
- cix = 1;
- }
-
- cix = cix ? -1 : 1;
- six = six ? -1 : 1;
-
- sintable[i] = ((double) sin(deg(rot)) * 65536)*six;
- costable[i] = ((double) cos(deg(rot)) * 65536)*cix;
- }
-
- printf("Saving...\n");
-
- if(!(fp = fopen("trig.pre","w")))
- {
- printf("Failed to save trig data!!!\n");
- return;
- }
-
- fwrite((void *) &sintable[0], sizeof(int), 361, fp);
- fwrite((void *) &costable[0], sizeof(int), 361, fp);
- fclose(fp);
- }
- else
- {
- fread((void *) &sintable[0], sizeof(int), 361, fp);
- fread((void *) &costable[0], sizeof(int), 361, fp);
- fclose(fp);
- }
- }
-
- /* ------------------------------------------------------------------
- Random Number Functions
- ------------------------------------------------------------------
- */
-
- void SetRandom(void)
- {
- long t;
- time(&t);
- srand((int) t);
- }
-
- int getrandom(int a, int b)
- {
- return (rand() % (1+b-a)) + a;
- }
-
- /* ------------------------------------------------------------------
- Routines for Object Manipulation
- ------------------------------------------------------------------
- */
-
-
- void Rotate_Obj_Abs(object *obj, short x, short y, short z)
- {
- obj->rot_x = x;
- obj->rot_y = y;
- obj->rot_z = z;
- }
-
- void Rotate_Obj_Rel(object *obj, short x, short y, short z)
- {
- if((obj->rot_x += x)>=360)
- obj->rot_x -= 360;
- else if(obj->rot_x<0)
- obj->rot_x += 360;
-
- if((obj->rot_y += y)>=360)
- obj->rot_y -= 360;
- else if(obj->rot_y<0)
- obj->rot_y += 360;
-
- if((obj->rot_z += z)>=360)
- obj->rot_z -= 360;
- else if(obj->rot_z<0)
- obj->rot_z += 360;
- }
-
- void Translate_Obj_Abs(object *obj, short x, short y, short z)
- {
- obj->trans_x = x;
- obj->trans_y = y;
- obj->trans_z = z;
- }
-
- void Translate_Obj_Rel(object *obj, short x, short y, short z)
- {
- obj->trans_x += x;
- obj->trans_y += y;
- obj->trans_z += z;
- }
-
- void Destroy_Object(object *obj)
- /* pretty obvious what this does */
- {
- polygon *p, *nextp;
-
- p = obj->poly;
- while(p)
- {
- nextp = (polygon *) p->next;
- free(p);
- p = nextp;
- }
-
- free(obj);
- }
-
- void Save_Object(object *obj, char *filename)
- {
- FILE *fp;
- polygon *p;
- int zero = 0, one = 1;
-
- if(!(fp=fopen(filename,"w")))
- {
- printf("Disk Error : Couldn't open the file for output!\n");
- return;
- }
-
- fwrite((void *) &(obj->type), sizeof(char), 1, fp);
- fwrite((void *) &(obj->start_x), sizeof(short), 1, fp);
- fwrite((void *) &(obj->start_y), sizeof(short), 1, fp);
- fwrite((void *) &(obj->start_z), sizeof(short), 1, fp);
- fwrite((void *) &(obj->numpoints), sizeof(short), 1, fp);
- fwrite((void *) &(obj->radius), sizeof(short), 1, fp);
- fwrite((void *) &(obj->objpoints[0]), sizeof(point), MAX_OBJ_POINTS, fp);
-
- p = obj->poly;
-
- while(p)
- {
- fwrite((void *) &one, sizeof(int), 1, fp);
-
- fwrite((void *) &(p->numpoints), sizeof(char), 1, fp);
- fwrite((void *) &(p->colour), sizeof(short), 1, fp);
- fwrite((void *) &(p->centre), sizeof(point), 1, fp);
- fwrite((void *) &(p->p[0]), sizeof(short), MAX_POINTS, fp);
-
- p = (polygon *) p->next;
- }
-
- fwrite((void *) &zero, sizeof(int), 1, fp);
- fclose(fp);
- printf("Object saved to file.\n");
- }
-
- int Load_Object(object *obj, char *filename)
- {
- FILE *fp;
- polygon *p;
- int i;
-
- if(!(fp=fopen(filename,"r")))
- {
- printf("Disk Error : Couldn't open the file for input!\n");
- return 0;
- }
-
- fread((void *) &(obj->type), sizeof(char), 1, fp);
- fread((void *) &(obj->start_x), sizeof(short), 1, fp);
- fread((void *) &(obj->start_y), sizeof(short), 1, fp);
- fread((void *) &(obj->start_z), sizeof(short), 1, fp);
- fread((void *) &(obj->numpoints), sizeof(short), 1, fp);
- fread((void *) &(obj->radius), sizeof(short), 1, fp);
-
- fread((void *) &(obj->objpoints[0]), sizeof(point), MAX_OBJ_POINTS, fp);
-
- fread((void *) &i, sizeof(int), 1, fp);
-
- if(i)
- {
- obj->poly = (polygon *) malloc(sizeof(polygon));
- p = obj->poly;
-
- fread((void *) &(p->numpoints), sizeof(char), 1, fp);
- fread((void *) &(p->colour), sizeof(short), 1, fp);
- fread((void *) &(p->centre), sizeof(point), 1, fp);
- fread((void *) &(p->p[0]), sizeof(short), MAX_POINTS, fp);
-
- fread((void *) &i, sizeof(int), 1, fp);
- while(i)
- {
- p->last_num = p->clip_num = p->last_num2 = 0;
- p->next = (polygon *) malloc(sizeof(polygon));
- p = (polygon *) p->next;
-
- fread((void *) &(p->numpoints), sizeof(char), 1, fp);
- fread((void *) &(p->colour), sizeof(short), 1, fp);
- fread((void *) &(p->centre), sizeof(point), 1, fp);
- fread((void *) &(p->p[0]), sizeof(short), MAX_POINTS, fp);
-
- fread((void *) &i, sizeof(int), 1, fp);
- }
- p->next = NULL;
- }
-
- fclose(fp);
- return 1;
- }
-
- object *CreateObject(void)
- {
- object *obj;
-
- if(!(obj = (object *) malloc(sizeof(object))))
- {
- printf("Fatal Error : Not enough memory!\n");
- CleanUpandExit();
- }
-
- obj->poly = NULL;
- obj->start_x = obj->start_y = obj->start_z = 0;
- obj->type = obj->centre_x = obj->centre_y = obj->centre_z = 0;
- obj->trans_x = obj->trans_y = obj->trans_z = 500;
- obj->rot_x = obj->rot_y = obj->rot_z = 0;
- obj->velocity = 5;
- obj->heading = 0;
- return obj;
- }
-
- void AddPoly(object *obj, polygon *p)
- {
- polygon *point = obj->poly;
- if(point)
- {
- while(point->next)
- point = (polygon *) point->next;
-
- point->next = p;
- p->next = NULL;
- }
- else
- {
- obj->poly = p;
- p->next = NULL;
- }
- }
-
- void SpinThatObject(object *obj)
- /*
- Spins an object around the axies. Seems to be a bottleneck, so will
- have to be converted to 68k. Anyone with a faster algorithm please tell
- me, as this is the fastest one I know.
- */
- {
- register short i;
- register short xrot = obj->rot_x;
- register short yrot = obj->rot_y;
- register short zrot = obj->rot_z;
-
- for(i=1; i<=obj->numpoints; i++)
- {
- register int x,y,z;
-
- x = obj->objpoints[i].x;
- y = obj->objpoints[i].y;
- z = obj->objpoints[i].z;
-
- /* rotate a point around the z axis */
-
- if(zrot)
- {
- register int temp, temp2, temp3;
- temp = x;
- temp2 = costable[zrot];
- temp3 = sintable[zrot];
-
- x = ((temp2*temp)>>16) - ((temp3*y)>>16);
- y = ((temp3*temp)>>16) + ((temp2*y)>>16);
- }
-
- /* rotate a point around the x axis */
-
- if(xrot)
- {
- register int temp, temp2, temp3;
- temp = y;
- temp2 = costable[xrot];
- temp3 = sintable[xrot];
-
- y = ((temp2*temp)>>16) - ((temp3*z)>>16);
- z = ((temp3*temp)>>16) + ((temp2*z)>>16);
- }
-
- /* rotate a point around the y axis */
-
- if(yrot)
- {
- register int temp, temp2, temp3;
- temp = z;
- temp2 = costable[yrot];
- temp3 = sintable[yrot];
-
- z = ((temp2*temp)>>16) - ((temp3*x)>>16);
- x = ((temp3*temp)>>16) + ((temp2*x)>>16);
- }
-
- /* move back to points */
-
- manipulate_x[i] = x;
- manipulate_y[i] = y;
- manipulate_z[i] = z;
- }
- }
-
- void SpinObjCentres(void)
- /* another use of my rotate code */
- {
- register short i;
-
- for(i=0; i<no_objects; i++)
- {
- register object *obj = active_list[i];
- register int x,y,z;
-
- register short xrot = obj->rot_x;
- register short yrot = obj->rot_y;
- register short zrot = obj->rot_z;
-
- x = obj->start_x;
- y = obj->start_y;
- z = obj->start_z;
-
- /* rotate a point around the z axis */
-
- if(zrot)
- {
- register int temp, temp2, temp3;
- temp = x;
- temp2 = costable[zrot];
- temp3 = sintable[zrot];
-
- x = ((temp2*temp)>>16) - ((temp3*y)>>16);
- y = ((temp3*temp)>>16) + ((temp2*y)>>16);
- }
-
- /* rotate a point around the x axis */
-
- if(xrot)
- {
- register int temp, temp2, temp3;
- temp = y;
- temp2 = costable[xrot];
- temp3 = sintable[xrot];
-
- y = ((temp2*temp)>>16) - ((temp3*z)>>16);
- z = ((temp3*temp)>>16) + ((temp2*z)>>16);
- }
-
- /* rotate a point around the y axis */
-
- if(yrot)
- {
- register int temp, temp2, temp3;
- temp = z;
- temp2 = costable[yrot];
- temp3 = sintable[yrot];
-
- z = ((temp2*temp)>>16) - ((temp3*x)>>16);
- x = ((temp3*temp)>>16) + ((temp2*x)>>16);
- }
-
- /* move back to points */
-
- obj->centre_x = x;
- obj->centre_y = y;
- obj->centre_z = z;
- }
- }
-
- void PrepareObject(object *obj)
- {
- polygon *pg = obj->poly;
- register short i;
-
- if(!(obj->drawme))
- return;
-
- SpinThatObject(obj);
-
- for(i=1; i<=obj->numpoints; i++) /* do translation */
- {
- manipulate_x[i] += obj->trans_x;
- manipulate_y[i] += obj->trans_y;
- manipulate_z[i] += obj->trans_z;
- }
-
- DepthSort(obj); /* sort polygons by depth from eye */
-
- /* convert all points in object to 2d */
-
- for(i=1; i<=obj->numpoints; i++)
- {
- get2d(manipulate_x[i], manipulate_y[i], manipulate_z[i]);
- obj->pointx[i] = x;
- obj->pointy[i] = y;
- }
-
- /* work out what points are in each polygon, then clip them */
-
- while(pg)
- {
- for(i=0; i<pg->numpoints; i++)
- {
- pg->x[i] = obj->pointx[pg->p[i]];
- pg->y[i] = obj->pointy[pg->p[i]];
- }
- if(!pg->back_face)
- polygon_clip(pg); /* creates a new polygon clipped */
- pg = (polygon *) pg->next;
- }
- }
-
- void DrawObject(object *obj)
- /* can only be used on an object that has already been clipped and
- arranged in drawing order */
- {
- register int j = 0;
- register polygon *pg;
-
- pg = obj->draworder[j];
-
- obj->lastdraw2 = obj->lastdrawme;
- obj->lastdrawme = obj->drawme;
-
- if(!(obj->drawme))
- return;
-
- while(pg) /* list is only terminated with a NULL */
- {
- register int i;
-
- if(!pg->back_face)
- {
- SetAPen(rastport, pg->colour);
-
- MoveTo(pg->clip_x[0], pg->clip_y[0]);
-
- for(i=1; i<pg->clip_num; i++)
- DrawTo(pg->clip_x[i], pg->clip_y[i]);
-
- FillArea();
- }
-
- if(swapflag)
- {
- store1 = 1;
-
- pg->last_num = pg->clip_num;
-
- for(i=0; i<pg->clip_num; i++)
- {
- pg->last_x[i] = pg->clip_x[i];
- pg->last_y[i] = pg->clip_y[i];
- }
- }
- else
- {
- store2 = 1;
-
- pg->last_num2 = pg->clip_num;
-
- for(i=0; i<pg->clip_num; i++)
- {
- pg->last_x2[i] = pg->clip_x[i];
- pg->last_y2[i] = pg->clip_y[i];
- }
- }
-
- j++;
- pg = obj->draworder[j];
- }
- }
-
- void EraseObject(object *obj)
- /* can only be used on an object that has already been drawn */
- {
- polygon *pg;
-
- if(!(obj->lastdraw2))
- return;
-
- pg = obj->poly;
- SetAPen(rastport, 0);
-
- if(swapflag)
- {
- if(store1)
- {
- while(pg)
- {
- register int i;
-
- if(pg->last_num)
- {
- MoveTo(pg->last_x[0], pg->last_y[0]);
-
- for(i=1; i<pg->last_num; i++)
- DrawTo(pg->last_x[i], pg->last_y[i]);
-
- FillArea();
- }
- pg = (polygon *) pg->next;
- }
- }
- }
- else
- {
- if(store2)
- {
- while(pg)
- {
- register int i;
-
- if(pg->last_num2)
- {
- MoveTo(pg->last_x2[0], pg->last_y2[0]);
-
- for(i=1; i<pg->last_num2; i++)
- DrawTo(pg->last_x2[i], pg->last_y2[i]);
-
- FillArea();
-
- }
- pg = (polygon *) pg->next;
- }
- }
- }
- }
-
- void AddObject(char *filename, short type)
- {
- object *obj;
- int i;
-
- for(i=0; i<MAX_OBJECTS; i++)
- {
- obj = CreateObject();
- if(!(Load_Object(obj, filename)))
- {
- printf("Failed to load %s\n",filename);
- free(obj);
- return;
- }
- memcpy(&obj_types[type][i], obj, sizeof(object));
- free(obj);
- }
- }
-
- void SetUpExplosions(void)
- {
- int i;
-
- for(i=0; i<MAX_EXPLOSIONS; i++)
- {
- explosions[i].type = EXPLOSION;
- explosions[i].radius = 2500;
-
- if(!(explosions[i].poly = malloc(sizeof(polygon))))
- {
- printf("Error creating explosions!\n");
- CleanUpandExit();
- }
- explosions[i].poly->next = NULL;
- explosions[i].poly->last_num = explosions[i].poly->last_num2 = 0;
- }
- }
-
- void AddNewObject(short type, short x, short y, short z)
- {
- register int i;
- register object *obj;
-
- for(i=0; i<MAX_OBJECTS; i++)
- {
- if(!obj_free[type][i])
- {
- obj = &obj_types[type][i];
-
- Translate_Obj_Abs(obj, x, y, z);
-
- obj->i_am_dying = obj->lastdrawme = obj->lastdraw2 = 0;
- obj->timeinflight = 0;
-
- if(type==MYMISSILE || type==GUIDEDMISSILE)
- {
-
- obj->velocity = 30;
- obj->heading = View_Angle;
- obj->target = NULL;
- if(type==MYMISSILE)
- Rotate_Obj_Abs(obj, 0, View_Angle, 180);
- else
- Rotate_Obj_Abs(obj, 0, View_Angle, 0);
- }
-
- if(type==PLAYER || type==MAMBA)
- Rotate_Obj_Abs(obj, 90, 0, 0);
-
- obj->explode = 0;
- obj_free[type][i] = 1;
- active_list[no_objects] = obj;
- no_objects++;
- num_active[type]++;
- return;
- }
- }
- }
-
- void KillAllObjects(void)
- {
- unsigned char i, j;
-
- for(j=0; j<NO_OBJ_TYPES; j++)
- {
- for(i=0; i<MAX_OBJECTS; i++)
- obj_free[j][i] = 0;
-
- num_active[j] = 0;
- }
-
- for(i=0; i<MAX_EXPLOSIONS; i++)
- exp_free[i] = 0;
-
- no_objects = 0;
- am_i_dead = 0;
- }
-
- void CreateExplosion(object *obj)
- /*
- Cool routine to blow an object into it's polygons. Takes a while though,
- so I'll have to fix it up a bit. Looks damn nice though...
- */
- {
- register int i, j = 0;
- register polygon *pg = obj->poly;
-
- while(pg)
- {
- for(i=j; i<MAX_EXPLOSIONS; i++)
- {
- if(!exp_free[i]) /* is free ! */
- {
- register int n;
-
- explosions[i].lastdrawme = explosions[i].lastdraw2 = 0;
- explosions[i].drawme = 1;
- explosions[i].explode = 0;
- explosions[i].i_am_dying = 0;
- explosions[i].type = EXPLOSION;
- explosions[i].centre_x = pg->centre.x;
- explosions[i].centre_y = pg->centre.y;
- explosions[i].centre_z = pg->centre.z;
- explosions[i].timeinflight = getrandom(5,25); /* time will last */
-
- explosions[i].poly->numpoints = explosions[i].numpoints =
- pg->numpoints;
-
- explosions[i].poly->colour = pg->colour;
- explosions[i].poly->centre = pg->centre;
-
- for(n=0; n<pg->numpoints; n++)
- explosions[i].poly->p[n] = n + 1;
-
- for(n=1; n<=pg->numpoints; n++)
- explosions[i].objpoints[n] = obj->objpoints[pg->p[n-1]];
-
- Translate_Obj_Abs(&explosions[i], obj->trans_x,
- obj->trans_y, obj->trans_z);
-
- Rotate_Obj_Abs(&explosions[i], obj->rot_x,
- obj->rot_y, obj->rot_z);
-
- explosions[i].velocity = getrandom(0,10);
- explosions[i].heading = getrandom(0,360);
- explosions[i].up_or_down = getrandom(0,2);
-
- exp_free[i] = 1; /* not free */
- active_list[no_objects] = &explosions[i];
- no_objects++;
- break;
- }
- }
- j = i; /* by doing this, I can search in order n instead of n^2 */
- pg = (polygon *) pg->next;
- }
- StartSound(1);
- }
-
- /* end of module */
-