home *** CD-ROM | disk | FTP | other *** search
- /* 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);
- }
-
-