home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
374b.lha
/
3DLibrary_v1.5
/
3d.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-02
|
8KB
|
274 lines
/* 3D library - By Steve Ludtke */
/* cre : 8/14/89 mod : 4/28/90 */
/* ver 1.5 (release) */
/* Copyright 1990 */
/*
The 3d library and all associated software in this distribution
is Copyright 1990 by Steven J. Ludtke. You have permission to
use and/or modify this code for any purpose commercial or non-
commercial with two conditions : I must be given credit in any
distributed product's documentation, and if any part of this
package is used in any commercial product (even Shareware) one
free copy of said software must be sent to me at the following
address : Steven Ludtke, 406 Yale Cir., Glenwood Springs, CO
81601; all other royalties are waived. This Copyright notice
must accompany any distributions of any part of this package,
and in general, the package should be distributed intact, with
no modifications. This notice must not be removed from the 3d.c,
test.c, and cube.c source code in this release. Modified versions
may not be distributed without permission. If the conditions
in the disclaimer are not valid in your home state, permission
to use this software is revoked.
*/
#define PI 3.141592
#define BET(a,b,c) (a<b && b<c)
#define sqr(a) ((a)*(a))
typedef struct { long *x,*y,*z; long *tx,*ty,*tz;} VECTOR;
/* this structure is used to sort surfaces for hidden line removal */
typedef struct { long n,may; } SORTS;
typedef struct { unsigned short l; unsigned nl :1;
unsigned nc :1; unsigned nco :1; } LINES;
long xfm[3][4]; /* transformation matrix */
VECTOR *V;
LINES *L;
short N;
long REGS[12]; /* register storage for assembly ver (not done) */
struct TmpRas TR; /* TmpRas and AreaInfo for filled polygons */
struct AreaInfo AI;
WORD LB[500]; /* Line buffer. Polygons limited to 100 lines */
/* comparison routine for sort */
int cmp(x,y)
SORTS *x,*y;
{
return (y->may-x->may);
}
/* set new x-form matrix x,y,z is position of viewer in 3-space */
/* tx,ty,tz is the viewing direction. The length of the tx,ty,tz */
/* vector changes nothing. n,d are for scaling. Use rotate(v)p */
setxfm2(x,y,z,tx,ty,tz,n,d)
long x,y,z;
long tx,ty,tz,n,d;
{
if (y!=0) setxfm(atan((double)x/y),atan((double)z/sqrt((double)sqr(x)+sqr(y))),0.0,-tx,-ty,-tz,n,d);
else if (x>0) setxfm(PI/2,atan((double) z/sqrt((double)sqr(x)+sqr(y))),0.0,-tx,-ty,-tz,n,d);
else if (x<0) setxfm(-PI/2,atan((double) z/sqrt((double)sqr(x)+sqr(y))),0.0,-tx,-ty,-tz,n,d);
else if (z>0) setxfm(0.0,-PI/2,0.0,tx,ty,tz,n,d);
else setxfm(0.0,PI/2,0.0,tx,ty,tz,n,d);
return(0);
}
/* set new x-form matrix a1=x/y a2=z/xy a3=z'/x'y' (see Goldstein 146) */
/* tx,ty,tz are translsations after rotation. n,d are for scaling. */
setxfm(a1,a2,a3,tx,ty,tz,n,d)
double a1,a2,a3;
long tx,ty,tz,n,d;
{
xfm[0][0]=(long) (( cos(a3)*cos(a1)-cos(a2)*sin(a1)*sin(a3))*REZ)*n/d;
xfm[1][0]=(long) ((-sin(a3)*cos(a1)-cos(a2)*sin(a1)*cos(a3))*REZ)*n/d;
xfm[2][0]=(long) ( sin(a2)*sin(a1)*REZ)*n/d;
xfm[0][1]=(long) (( cos(a3)*sin(a1)+cos(a2)*cos(a1)*sin(a3))*REZ)*n/d;
xfm[1][1]=(long) ((-sin(a3)*sin(a1)+cos(a2)*cos(a1)*cos(a3))*REZ)*n/d;
xfm[2][1]=(long) (-sin(a2)*cos(a1)*REZ)*n/d;
xfm[0][2]=(long) ( sin(a3)*sin(a2)*REZ)*n/d;
xfm[1][2]=(long) ( cos(a3)*sin(a2)*REZ)*n/d;
xfm[2][2]=(long) ( cos(a2)*REZ)*n/d;
xfm[0][3]=tx;
xfm[1][3]=ty;
xfm[2][3]=tz;
return(0);
}
/* rotate without perspective */
rotate(v,n)
VECTOR *v;
int n;
{
int i;
for (i=0; i<n; i++) {
v->ty[i]=(v->x[i]*xfm[1][0]+v->y[i]*xfm[1][1]+v->z[i]*xfm[1][2])/REZ+xfm[1][3];
v->tx[i]=((v->x[i]*xfm[0][0]+v->y[i]*xfm[0][1]+v->z[i]*xfm[0][2])/REZ+xfm[0][3])*ASPECT+XCEN;
v->tz[i]=((v->x[i]*xfm[2][0]+v->y[i]*xfm[2][1]+v->z[i]*xfm[2][2])/REZ+xfm[2][3])+YCEN;
}
return(0);
}
/* rotate pre-translate. Use with setxfm2 */
rotatep(v,n)
VECTOR *v;
int n;
{
long i,j,x,y;
for (i=0; i<n; i++) {
v->tx[i]=v->x[i]+xfm[0][3];
v->ty[i]=v->y[i]+xfm[1][3];
v->tz[i]=v->z[i]+xfm[2][3];
y=(v->tx[i]*xfm[1][0]+v->ty[i]*xfm[1][1]+v->tz[i]*xfm[1][2])/REZ;
x=((v->tx[i]*xfm[0][0]+v->ty[i]*xfm[0][1]+v->tz[i]*xfm[0][2])/REZ)*ASPECT+XCEN;
v->tz[i]=((v->tx[i]*xfm[2][0]+v->ty[i]*xfm[2][1]+v->tz[i]*xfm[2][2])/REZ)+YCEN;
v->ty[i]=y;
v->tx[i]=x;
}
return(0);
}
/* rotate with perspective, pre-translate. Use with setxfm2 */
rotatevp(v,n)
VECTOR *v;
int n;
{
long i,j,x,y;
for (i=0; i<n; i++) {
v->tx[i]=v->x[i]+xfm[0][3];
v->ty[i]=v->y[i]+xfm[1][3];
v->tz[i]=v->z[i]+xfm[2][3];
if (0==(y=(v->tx[i]*xfm[1][0]+v->ty[i]*xfm[1][1]+v->tz[i]*xfm[1][2])/REZ)) y= -1;
j=D3VDIST+ y;
if (j==0) j=1;
x=((v->tx[i]*xfm[0][0]+v->ty[i]*xfm[0][1]+v->tz[i]*xfm[0][2])/REZ*D3VDIST)/j*ASPECT+XCEN;
v->tz[i]=((v->tx[i]*xfm[2][0]+v->ty[i]*xfm[2][1]+v->tz[i]*xfm[2][2])/REZ*D3VDIST)/j+YCEN;
v->ty[i]=y;
v->tx[i]=x;
}
return(0);
}
/* rotate with perspective */
rotatev(v,n)
VECTOR *v;
int n;
{
long i,j;
for (i=0; i<n; i++) {
if (0==(v->ty[i]=(v->x[i]*xfm[1][0]+v->y[i]*xfm[1][1]+v->z[i]*xfm[1][2])/REZ+xfm[1][3])) v->ty[i]= -1;
j=D3VDIST+ v->ty[i];
if (j==0) j=1;
v->tx[i]=((v->x[i]*xfm[0][0]+v->y[i]*xfm[0][1]+v->z[i]*xfm[0][2])/REZ+xfm[0][3])*D3VDIST/j*ASPECT+XCEN;
v->tz[i]=((v->x[i]*xfm[2][0]+v->y[i]*xfm[2][1]+v->z[i]*xfm[2][2])/REZ+xfm[2][3])*D3VDIST/j+YCEN;
}
return(0);
}
/* set up 1 - 4 rastports for filled shape drawing */
Init3Ras(rp,rp2,rp3,rp4)
struct RastPort *rp,*rp2,*rp3,*rp4;
{
PLANEPTR buf;
InitArea(&AI,&LB,200);
rp->AreaInfo=&AI;
if (rp2!=NULL) rp2->AreaInfo=&AI;
if (rp3!=NULL) rp3->AreaInfo=&AI;
if (rp4!=NULL) rp4->AreaInfo=&AI;
buf=(PLANEPTR)AllocRaster(XHI,YHI);
InitTmpRas(&TR,buf,RASSIZE(XHI,YHI));
rp->TmpRas=&TR;
if (rp2!=NULL) rp2->TmpRas=&TR;
if (rp3!=NULL) rp3->TmpRas=&TR;
if (rp4!=NULL) rp4->TmpRas=&TR;
return(0);
}
/* free memory allocated by Init3Ras */
Exit3d(rp)
struct RastPort *rp;
{
FreeRaster(rp->TmpRas->RasPtr,XHI,YHI);
return(0);
}
/* draw outlines of 3d shapes */
d3lines(v,l,n,rp)
VECTOR *v;
int n;
LINES *l;
struct RastPort *rp;
{
int i,flag;
flag=0;
for (i=0; i<n; i++) {
while (l[i].nc || l[i].nco) { /* change colors if necc. */
if (l[i].nco) SetAPen(rp,l[i].l);
i++;
}
if (v->tx[l[i].l]>XLO && v->tx[l[i].l]<XHI && /* clip to defined region */
v->tz[l[i].l]>YLO && v->tz[l[i].l]<YHI ) {
if (l[i].nl) { Move(rp,v->tx[l[i].l],YHI-v->tz[l[i].l]+YLO); flag=0; }
else {
if (v->ty[l[i].l]<0) flag=1;
else if (flag==1) { Move(rp,v->tx[l[i].l],YHI-v->tz[l[i].l]+YLO); flag=0; }
else Draw(rp,v->tx[l[i].l],YHI-v->tz[l[i].l]+YLO);
}
}
else flag=1;
}
return(0);
}
/* draw filled 3d shapes with hidden line removal */
d3surf(v,l,n,rp)
VECTOR *v;
LINES *l;
int n;
struct RastPort *rp;
{
int i,j,flag,c;
int cmp();
SORTS s[100],m;
c= -1;
for (i=0; i<n; i++) { /* set up SORTS for */
if (l[i].nl) {
if (c>=0) s[c].may=s[c].may/(i-s[c].n);
c++;
s[c].n=i;
s[c].may=0;
}
if (!(l[i].nc || l[i].nco)) s[c].may+=v->ty[l[i].l];
}
s[c].may=s[c].may/(i-s[c].n);
L=l; V=v; N=n;
flag=0;
qsort(s,c+1,sizeof(SORTS),&cmp);
for (j=0; j<c+1; j++) { /* draw shapes in order */
flag=0;
i=s[j].n;
while(!l[i].nl && i!=n || i==s[j].n) {
while (l[i].nc || l[i].nco) {
if (l[i].nc) SetAPen(rp,l[i].l);
if (l[i].nco) SetOPen(rp,l[i].l);
i++;
}
if (v->tx[l[i].l]>XLO && v->tx[l[i].l]<XHI &&
v->tz[l[i].l]>YLO && v->tz[l[i].l]<YHI ) {
if (l[i].nl) { AreaMove(rp,v->tx[l[i].l],YHI-v->tz[l[i].l]+YLO); flag=0; }
else {
if (v->ty[l[i].l]<0) flag=1;
else if (flag==1) { AreaMove(rp,v->tx[l[i].l],YHI-v->tz[l[i].l]+YLO); flag=0; }
else AreaDraw(rp,v->tx[l[i].l],YHI-v->tz[l[i].l]+YLO);
}
}
else flag=1;
i++;
}
AreaEnd(rp);
}
return(0);
}