Article View: rec.games.programmer
Article #11133D code to those who want it
From: Timothy Wilson
Date: Sun, 11 Oct 1992 22:58
Date: Sun, 11 Oct 1992 22:58
594 lines
12157 bytes
12157 bytes
/* originally developed for alt.3d, but i though some people here
also would like to see it */
#include <math.h>
#include <stdio.h>
/*
#include <graphics.h>
#include <osbind.h>
**** Atari ST only commands will be commented out */
/* This program was developed on a Atari ST, using Sozobon 1.44i */
/* The graphic commands from the public domain turbo C compatible lib*/
/* With help from George Kyriazis and Bob Pendelton */
/* thanks guys!! */
/* told you'd be in the credits!! */
/* To speed operations, this program makes its own sin table, converts
it to longs, and uses integer math instead of doubles or floats */
/* speed more than doubled after i did this. */
/* the bottom part of this text file has longmath.c cut it out, its
another module */
/* any questions should be directed to: wilsont@prism.cs.orst.edu */
/* NOT to wilsont@holonet.net !!! i'll be moving shortly (next week!)*/
/* this code is in no way copyrighted, go ahead and grab all you want */
/* this code is for beginners, by a beginner, in no way should it be
taken as a professional work. */
/* upgrades may or maynot be availible. I have a job to deal with, but
if time permits, and if any one asks, I should have the following:
* cheapo scripting for RT animations (games, simulations etc..)
* fast actual 3D clipping, (right now the computers polygon routine does
the clippin,and only in 2D )
* object creation (based on this program)
*/
/* I really don't understand matrix operations. my equations do the same
thing, and they aren't dogs. */
/* this program is set up to do bit shifts for the sintables ( <<14=16384)
but for some reason, i couln't get the left shift to work.. since it
destroys the sign bit if the number is negative, i left it to do a divide */
/* again, any questions at all, direct them to wilsont@prism.cs.orst.edu */
/* Enjoy this code! */
/* Timothy Wilson */
typedef struct {
long x,y,z;
} Point3;
typedef struct {
int x,y;
} Point2;
typedef struct {
int a,b,c,d;
int color;
int viz;
long midz;
int own;
} POLY;
POLY poly[60]; /* all polygons eventually go here for depth sorting */
/* 5 object limit, just to keep it quick */
/* just bump up this number for more objects */
Point3 docalc();
Point3 objc[5];
Point3 objv[5][100];
int NP[5]; /* # of points in object */
int NL[5]; /* # of polys in object */
int NO; /* # of objects */
int NPOLY; /* total number of polygons */
Point3 world[5][40]; /* world coordinates for objects */
Point2 pic[5][100]; /* pic coordinates of objects */
Point3 view[5][100]; /* view coordinates of objects */
long ox,oy,oz;
int theta,phi,zw; /* zw=bank */
int fill; /* flag for wireframe or filled polygons */
main()
{
int i,ch;
Point3 p;
Point2 cc;
/* int graphdriver,graphmode; */
char out[30];
Point3 chk;
long offx,offy,offz;
/* long block,altscreen,oldscreen,hscreen,orgscreen; */
long sx,sy;
int ob;
int step;
long dx,dy,dz;
fill=1;
/* reserve memory for other screen
block=Malloc(0x7E00L);
altscreen= (block+256) & 0x00FFFF00;
*/
offx=0;
offy=0;
offz=2;
step=2;
/*
graphdriver=SC1224;
graphmode=SC1224LO;
*/
ox=0;
oy=0;
oz=-50;
theta=0;
phi=0;
zw=0;
makesintab();
loaddat();
/* set up screen
oldscreen=(long)Physbase();
orgscreen=oldscreen;
set to lowres
Setscreen(altscreen,oldscreen,0);
initgraph(&graphdriver,&graphmode,"");
*/
while(1)
{
/* clear the hidden page */
/* cleardevice(); */
for (ob=0;ob<NO;ob++)
for (i=0;i<NP[ob];i++)
{
/* convert from object coord sys to world sys */
world[ob][i].x=objc[ob].x+objv[ob][i].x;
world[ob][i].y=objc[ob].y+objv[ob][i].y;
world[ob][i].z=objc[ob].z+objv[ob][i].z;
p.x=world[ob][i].x;
p.y=world[ob][i].y;
p.z=world[ob][i].z;
/* use world coords to generate view coords */
chk=docalc(p);
view[ob][i].x=chk.x;
view[ob][i].y=chk.y;
view[ob][i].z=chk.z;
/* convert to screen(picture) coordinates */
sx=((chk.x)*128 ) /chk.z;
sy=((chk.y)*128) /chk.z;
/* convert to computer coordinates */
pic[ob][i].x=160+(int) sx;
pic[ob][i].y=100+(int) sy;
}
vizit(); /* determines polygon visibility (all of them) */
sortply(); /* combine and sort all polys here */
drawall(); /* draw those polygons */
/* get a key from the keyboard
if (Bconstat(2))
ch=Bconin(2) & 255;
else ch=0;
*/
switch(ch)
{
case 0: break;
case '+':
oz+=step;
break;
case '-' :
oz-=step;
break;
case '6': theta+=5;
break;
case '8': phi+=5;
break;
case '2': phi-=5;
break;
case '1': zw-=5;
break;
case '3': zw+=5;
break;
case '4': theta-=5;
break;
case 'x':
/* exit routine, restores modes, colors and original page
Setscreen(orgscreen,orgscreen,1);
restorecrtmode();
Mfree(block);
closegraph();
*/
exit(0);
break;
case 'a': oy+=step;
break;
case 'z': oy-=step;
break;
case 'q': ox-=step;
break;
case 'w': ox+=step;
break;
case 'f': fill=1;
break;
case 'g': fill=0;
break;
}
/* checks for out of bounds for degrees */
if (theta<0) theta+=360;
if (phi<0) phi+=360;
if (theta>360) theta-=360;
if (phi>360) phi-=360;
if (zw<0) zw+=360;
if (zw>360) zw-=360;
/* number keys determine stepping for movement */
if ((ch>49) && (ch<58))
step=ch-48;
/* page flip to the new screen
hscreen=altscreen;
altscreen=oldscreen;
oldscreen=hscreen;
Setscreen(altscreen,oldscreen,-1L);
*/
} /* while */
} /* end of main */
/* finds points of polygon, and draws it( using a built-in polygon routine ) */
drawply(q)
int q;
{
int p1,p2,p3,p4;
int xyp[8];
int col;
int pat;
int ob;
p1=poly[q].a;
p2=poly[q].b;
p3=poly[q].c;
p4=poly[q].d; /* grabs point numbers */
ob=poly[q].own; /* which object owns this polygon */
xyp[0]=pic[ob][p1].x;
xyp[1]=pic[ob][p1].y;
xyp[2]=pic[ob][p2].x;
xyp[3]=pic[ob][p2].y;
xyp[4]=pic[ob][p3].x;
xyp[5]=pic[ob][p3].y;
xyp[6]=pic[ob][p4].x;
xyp[7]=pic[ob][p4].y; /* fills the polygon point coord array */
col=poly[q].color; /* get color */
/* draw the polygon with xyp[]
setcolor(col);
if (fill){
setfillstyle(1,col);
fillpoly(4,xyp); /* call system routine to draw poly */
}
else drawpoly(4,xyp);
*/
}
/* sort all polygons */
sortply()
{
int i,j;
long z1,z2,z3,z4,max;
POLY sav;
int ob;
for (i=0;i<NPOLY;i++)
{
ob=poly[i].own;
/* calculate the middle Z's for depth sorting */
z1=view[ob][ poly[i].a ].z;
z2=view[ob][ poly[i].b ].z;
z3=view[ob][ poly[i].c ].z;
z4=view[ob][ poly[i].d ].z;
poly[i].midz=(z1+z2+z3+z4) /4;
}
/* simple sort */
for (i=0;i<NPOLY-1;i++)
for(j=i+1;j<NPOLY;j++)
if (poly[i].midz<poly[j].midz)
{
sav=poly[i];
poly[i]=poly[j];
poly[j]=sav;
}
}
vizit()
{
int i;
for (i=0;i<NPOLY;i++)
poly[i].viz=visible(i);
}
drawall()
{
int i;
/* first poly is closest */
for (i=NPOLY-1;i>=0;i--)
if (poly[i].viz) /* if visible, draw that polygon */
drawply(i);
}
Point3 docalc(p) /* takes a point and converts it based on view angles */
Point3 p;
{
Point3 res;
Point3 t;
Point3 des;
/* set up system to rotate around observer */
t.x=(p.x)-ox;
t.y=(p.y)-oy;
t.z=(p.z)-oz;
res.x=t.x;
res.y=t.y;
res.z=t.z;
/* more like an airplane if bank goes first */
des.x=dc2(res.x,zw)-ds2(res.y,zw);
des.y=dc2(res.y,zw)+ds2(res.x,zw);
res.x=des.x;
res.y=des.y;
/*pitch */
des.y=dc2(res.y,phi)-ds2(res.z,phi);
des.z=dc2(res.z,phi)+ds2(res.y,phi);
res.y=des.y;
res.z=des.z;
/* heading */
des.x=dc2(res.x,theta)-ds2(res.z,theta);
des.z=dc2(res.z,theta)+ds2(res.x,theta);
res.x=des.x;
res.z=-des.z;
return (res);
}
visible(q)
int q;
{
Point3 P,Q,S,R;
long c;
char out[40];
int ob;
ob=poly[q].own;
/* find surface normal */
/* requires polygon points to be ordered clockwise */
/* while looking straight on to the visible side of the polygon */
P.x=view[ob] [ poly[q].b ].x - view[ob] [ poly[q].a].x;
P.y=view[ob][ poly[q].b ].y - view[ob][ poly[q].a].y;
P.z=view[ob][ poly[q].b ].z - view[ob][ poly[q].a].z;
Q.x=view[ob][ poly[q].c ].x - view[ob][ poly[q].a].x;
Q.y=view[ob][ poly[q].c ].y - view[ob][ poly[q].a].y;
Q.z=view[ob][ poly[q].c ].z - view[ob][ poly[q].a].z;
R.x=P.y*Q.z-P.z*Q.y;
R.y=P.z*Q.x-P.x*Q.z;
R.z=P.x*Q.y-P.y*Q.x;
/* find vector from eye to polygon */
S.x=-view[ob][ poly[q].a ].x;
S.y=-view[ob][ poly[q].a ].y;
S.z=-view[ob][ poly[q].a ].z;
/* calculate scalar product */
c= (long)S.x*(long)R.x+(long)S.y*(long)R.y+(long)S.z*(long)R.z;
/* if the result is greater than one, the two vectors face in the
general same direction */
if (c<0) return 1;
/* face turned away from viewer */
return 0;
}
/* load in the objects from file plot.dat */
loaddat()
{
FILE *fdata;
int i,j;
int ob;
int pc=0;
fdata=fopen("plot.dat","rb");
if (!fdata) exit(10);
fscanf(fdata,"%d",&NO); /* read in number of objects */
for (ob=0;ob<NO;ob++)
{
fscanf(fdata,"%d",&NP[ob]); /*read in #points for this object */
fscanf(fdata,"%ld %ld %ld",&objc[ob].x,&objc[ob].y,&objc[ob].z);
for (i=0;i<NP[ob];i++)
fscanf(fdata,"%ld %ld %ld",&objv[ob][i].x,&objv[ob][i].y,&objv[ob][i].z);
fscanf(fdata,"%d",&NL[ob]); /* number of polygons */
for(i=0;i<NL[ob];i++)
{
fscanf(fdata,"%d %d %d %d %d",&poly[pc].a,&poly[pc].b,&poly[pc].c,&poly[pc].d,&poly[pc].color);
poly[pc].own=ob; /* give this polygon an owner */
pc++;
}
} /* object loop */
NPOLY=pc; /* set global */
fclose(fdata);
}
/*************************** CUT HERE ************************/
/** the int math module, so you can change the math easier */
/** if you want to that is. */
/** cut out and name it longmath or something like that */
/*************************************************************/
#include <math.h>
long sintab[361];
long ds2();
long dc2();
long Sin2();
long Cos2();
long ds2(w,d)
long w;
int d;
{
long l;
l=w*Sin2(d);
return( l/16384);
}
long dc2(w,d)
long w;
int d;
{
long l;
l=w*Cos2(d);
return( l/16384);
}
long Sin2(deg)
int deg;
{
if (deg<0) deg+=360;
return( sintab[deg] );
}
long Cos2(deg)
int deg;
{
return( Sin2(90-deg) );
}
#define DTOR 0.017453
makesintab()
{
int i;
long t;
double d,d2;
for (i=0;i<=360;i++)
{
d=i;
d2=sin(DTOR*d)*16384;
t=(long)d2;
sintab[i]=t;
}
}
Technical Details
Message-ID:
<BvzBtr.InI@iat.holonet.net>Path:
arc1-ca.pugleaf.net!sparky!uunet!know!hri.com!noc.near.net!news.bbn.com!usc!news!iat.holonet.net!wilsontShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!know!hri.com!noc.near.net!news.bbn.com!usc!news!iat.holonet.net!wilsont From: wilsont@orac.holonet.net (Timothy Wilson) Newsgroups: rec.games.programmer Subject: 3D code to those who want it Message-ID: <BvzBtr.InI@iat.holonet.net> Date: 11 Oct 92 22:58:37 GMT Sender: usenet@iat.holonet.net (USENET News System) Organization: HoloNet (BBS: 510-704-1058) Lines: 594 Nntp-Posting-Host: holonet.holonet.net