home *** CD-ROM | disk | FTP | other *** search
- /* animballs.c -- code to handle actual rotating images */
- #include <exec/types.h>
- #include <stdio.h>
- #include <math.h>
- #include <intuition/intuition.h>
-
- #include "globals.h"
-
- #include <proto/exec.h>
- #include <proto/graphics.h>
- #include <proto/intuition.h>
-
- int woffset = WOFFSET;
- #define SETANDBOUND(ii,ff) {ii = 0.5 + ff * 15; \
- if (ii > 15) ii = 15; \
- else if (ii < 0) ii = 0;}
-
- float ka, kd, ks, lx, ly, lz, n, r; /* coloring parameters */
- long int ix,iy,iz, jx,jy,jz, kx,ky,kz;
- static char title[81];
- int bgcolor = 0;
-
- int scx = WIDTH / 2, scy = SMHEIGHT / 2;
- int xstart = -1; ystart = -1;
-
- #define ISIZE 14
- #define FTOI(x) ((long int) (x * (1 << ISIZE)))
- #define MULT(x,y) ((x * y) >> ISIZE)
- #define LSIZE 10
-
- #define MAKEL(x) ((long int) x * (1 << LSIZE))
-
- struct Ball {
- long int x,y,z;
- float r,g,b,rad;
- long int xp,yp,zp;
- int y1,y2,intr,size;
- int dup;
- };
-
- int nball;
- struct Ball **ballptr;
- struct Ball *balls;
- int maxsize = 0;
- int maskw = 0, maskh = 1;
- int maxextent = 0;
-
- long int intsin[360];
- long int intcos[360];
-
- void
- readballs(name)
- char *name;
- {
- int i, j, extent;
- int c;
- float x,y,z,rad,r,g,b;
- FILE *fp, *fopen();
- int ir,ig,ib;
-
- if ((fp = fopen(name,"r")) == NULL) {
- fprintf(stderr,"Can't open balls file - '%s'",name);
- panic("");
- }
- strcpy(title,"Drag Mouse to Rotate");
- if ((c = getc(fp)) != '"') ungetc(c,fp);
- else {
- i = 0;
- c = getc(fp);
- while ((c != '"') && (c != EOF)) {
- if (i < 80) title[i++] = c;
- c = getc(fp);
- }
- if (c == EOF) panic("Error - title lacks final \"");
- title[i] = 0;
- }
- if ((c = fscanf(fp,"%f %f %f",&r,&g,&b)) != 3) {
- fprintf(stderr,"Error reading background color %d",c+1);
- panic("");
- } else {
- SETANDBOUND(ir,r);
- SETANDBOUND(ig,g);
- SETANDBOUND(ib,b);
- bgcolor = match(ir,ig,ib);
- }
- if (fscanf(fp,"%d",&nball) != 1)
- panic("Error - Can't read number of balls");
- balls = (struct Ball *) malloc(sizeof(struct Ball)*nball);
- if (balls == 0) panic("Not enough memory for balls");
- ballptr = (struct Ball **) malloc(sizeof(long int)*nball);
- if (ballptr == 0) panic("Not enough memory for ballptr");
- for (i = 0; i < nball; i++) {
- if ((c=fscanf(fp,"%f %f %f %f %f %f %f",&x,&y,&z,&rad,&r,&g,&b))!=7)
- {fprintf(stderr,
- "Error in reading item %d in ball description %d",
- c+1,i+1);
- panic("");
- }
- balls[i].x = MAKEL(x);
- balls[i].y = MAKEL(y);
- balls[i].z = MAKEL(z);
- balls[i].rad = rad;
- balls[i].r = r;
- balls[i].g = g;
- balls[i].b = b;
- balls[i].intr = rad + 0.5;
- balls[i].size = 2 * balls[i].intr + 1;
- extent = 0.9 + sqrt(x*x + y*y +z*z) + balls[i].intr;
- if (extent > maxextent) maxextent = extent;
- if (balls[i].size > maxsize) maxsize = balls[i].size;
- balls[i].dup = -1;
-
- for (j = 0; j < i; j++) /* check for duplicate entries */
- if ((balls[j].rad == rad) && (balls[j].r == r) &&
- (balls[j].g == g) && (balls[j].b == b)) {
- balls[i].dup = j;
- break;
- }
- if (balls[i].dup != -1) {
- balls[i].y1 = balls[balls[i].dup].y1;
- balls[i].y2 = balls[balls[i].dup].y2;
- } else {
- balls[i].y1 = maskh;
- maskh += balls[i].size;
- if (!bw) {
- balls[i].y2 = maskh;
- maskh += balls[i].size;
- } else balls[i].y2 = 0;
- }
- }
- maskw = ((maxsize + 15) & ~15) + 16;
- fclose(fp);
- checkextent();
- }
-
- void
- checkextent()
- {
- int largest,i;
- long int scale;
- double fscale;
-
- largest = scy - 10;
- if (scx < largest) largest = scx;
- if (maxextent > largest) {
- fprintf(stderr,"Warning, balls are too far apart, I will re-scale.\n");
- Delay(250);
- fscale = (((double) largest) / ((double) maxextent));
- scale = FTOI(fscale);
- maxsize = 0;
- maskw = 0;
- maskh = 1;
- for (i=0; i < nball; i++) {
- balls[i].x = MULT(balls[i].x,scale);
- balls[i].y = MULT(balls[i].y,scale);
- balls[i].z = MULT(balls[i].z,scale);
- balls[i].rad *= fscale;
- balls[i].intr = balls[i].rad + 0.5;
- balls[i].size = 2 * balls[i].intr + 1;
- if (balls[i].size > maxsize) maxsize = balls[i].size;
- if (balls[i].dup != -1 ) {
- balls[i].y1 = balls[balls[i].dup].y1;
- balls[i].y2 = balls[balls[i].dup].y2;
- } else {
- balls[i].y1 = maskh;
- maskh += balls[i].size;
- if (!bw) {
- balls[i].y2 = maskh;
- maskh += balls[i].size;
- } else balls[i].y2 = 0;
- }
- }
- maskw = ((maxsize + 15) & ~15) + 16;
- }
- }
-
- void
- initsin()
- {
- int i;
- float r,s;
-
- for (i=0; i < 360; i++) {
- r = i * (3.14159/180.0);
- s = sin(r);
- intsin[i] = FTOI(s);
- s = cos(r);
- intcos[i] = FTOI(s);
- }
- }
-
- void
- isin(x,c,s)
- int x; /* x is degrees */
- long int *c,*s;
- {
- while (x >= 360) x -=360;
- while (x < 0) x += 360;
- *c = intcos[x];
- *s = intsin[x];
- }
-
- void
- initrender()
- {
- float m;
-
- initsin();
- ka = .2; kd = .5; ks = .65;
- lx = ly = lz = 1;
- m = sqrt(lx*lx + ly*ly + lz*lz);
- lx /= m;
- ly /= m;
- lz /= m;
- n = 10; r = 9.5;
-
- ix = FTOI(1); iy = iz = 0;
- jy = FTOI(1); jx = jz = 0;
- kz = FTOI(1); kx = ky = 0;
- }
-
- void
- render()
- {
- int i;
- int x, y;
- int cont, MouseMoved;
- struct IntuiMessage *message;
- ULONG class;
- USHORT code,qual;
-
- for (i = 0; i < nball; i++) renderball(i);
-
- SetWindowTitles(mywindow,title,((char *)(-1)));
- mylinecopy(sbitmap,0,10,WOFFSET);
-
- showballs();
-
- cont = 1;
- while(cont) {
- Wait(1 << (mywindow->UserPort->mp_SigBit));
- MouseMoved = FALSE;
- while(message = (struct IntuiMessage *)
- GetMsg(mywindow->UserPort)) {
- class = message->Class;
- code = message->Code;
- x = message->MouseX;
- y = message->MouseY;
- qual = message->Qualifier;
- ReplyMsg((struct Message *)message);
-
- if (class == MOUSEMOVE) MouseMoved = TRUE;
- else if (class == CLOSEWINDOW) {
- cont = 0;
- break;
- } else if (class == MOUSEBUTTONS)
- mbutton(code,x,y);
- }
- if (MouseMoved && cont) mmove(x,y,qual);
- }
- }
-
- void
- showballs()
- {
- int i,j,sx,sy;
- struct Ball *ball;
- long int x,y;
-
- for (i = 0; i < nball; i++) {
- ball = ballptr[i] = &(balls[i]);
- ball->xp = ((ball->x)*ix + (ball->y)*jx + (ball->z)*kx) >> ISIZE;
- ball->yp = ((ball->x)*iy + (ball->y)*jy + (ball->z)*ky) >> ISIZE;
- ball->zp = ((ball->x)*iz + (ball->y)*jz + (ball->z)*kz) >> ISIZE;
- }
- for (i = nball-1; i > 0; i--)
- for (j = 0; j < i; j++) {
- if (ballptr[i]->zp < ballptr[j]->zp) {
- ball = ballptr[i];
- ballptr[i]=ballptr[j];
- ballptr[j]=ball;
- }
- }
-
- myblankc(sbitmap,10+woffset,190+woffset,bgcolor);
- if (!bw) myblankc(&tbitmap,0,SMHEIGHT-1,bgcolor);
-
- for (i = 0; i < nball; i++) {
- ball = ballptr[i];
- x = (ball->xp + (1 << (LSIZE - 1))) >> LSIZE;
- y = (ball->yp + (1 << (LSIZE - 1))) >> LSIZE;
- sx = scx + x - ball->intr;
- sy = scy - y - ball->intr;
-
- BltBitMask(&ibitmap,0,ball->y1,
- sbitmap,sx,sy+woffset,
- &mbitmap,0,ball->y1,0,
- ball->size,ball->size);
- if (!bw) {
- BltBitMask(&ibitmap,0,ball->y2,
- &tbitmap,sx,sy,
- &mbitmap,0,ball->y1,0,
- ball->size,ball->size);
- BltBitMask(&tbitmap,sx+ball->intr+1,sy,
- sbitmap,sx+ball->intr+1,sy+woffset,
- &mbitmap,ball->intr,ball->y2,0,
- ball->intr+1,ball->size);
- }
- }
- flip();
- }
-
- void
- scrollx(d)
- int d;
- {
- long int c,s;
- long int t;
-
- isin(-d,&c,&s);
-
- t = (c * ix - s * iz) >> ISIZE;
- iz = (s * ix + c * iz) >> ISIZE;
- ix = t;
- t = (c * jx - s * jz) >> ISIZE;
- jz = (s * jx + c * jz) >> ISIZE;
- jx = t;
- t = (c * kx - s * kz) >> ISIZE;
- kz = (s * kx + c * kz) >> ISIZE;
- kx = t;
- }
- void
- scrolly(d)
- int d;
- {
- long int c,s;
- long int t;
-
- isin(d,&c,&s);
-
- t = (c * iy - s * iz) >> ISIZE;
- iz = (s * iy + c * iz) >> ISIZE;
- iy = t;
- t = (c * jy - s * jz) >> ISIZE;
- jz = (s * jy + c * jz) >> ISIZE;
- jy = t;
- t = (c * ky - s * kz) >> ISIZE;
- kz = (s * ky + c * kz) >> ISIZE;
- ky = t;
- }
- void
- scrollz(d)
- int d;
- {
- long int c,s;
- long int t;
-
- isin(d,&c,&s);
-
- t = (c * iy - s * ix) >> ISIZE;
- ix = (s * iy + c * ix) >> ISIZE;
- iy = t;
- t = (c * jy - s * jx) >> ISIZE;
- jx = (s * jy + c * jx) >> ISIZE;
- jy = t;
- t = (c * ky - s * kx) >> ISIZE;
- kx = (s * ky + c * kx) >> ISIZE;
- ky = t;
- }
-
- void
- mbutton(code,x,y)
- int code, x, y;
- {
- if (code == SELECTDOWN) {
- xstart = x;
- ystart = y;
- } else if (code == SELECTUP) {
- xstart = ystart = -1;
- }
- }
-
- void
- mmove(x,y,qual)
- int x,y;
- USHORT qual;
- {
- register int shift;
-
- if (qual & 0x30) shift = 2; /* L-ALT, R-ALT */
- else if (qual & 0x07) shift = 0; /* SHIFT */
- else shift = 1;
-
- if (xstart != -1) {
- if (qual & 0x08) /* CNTL */
- scrollz((x - xstart)<<shift);
- else {
- scrolly((y - ystart)<<shift);
- scrollx((x - xstart)<<shift);
- }
-
- xstart = x;
- ystart = y;
-
- showballs();
- }
- }
-
- void
- flip()
- {
- Forbid();
- WaitTOF();
- WaitBlit();
- Disable();
- if (woffset) {
- vp->RasInfo->RyOffset = WOFFSET;
- } else {
- vp->RasInfo->RyOffset = 0;
- }
- ScrollVPort(vp);
- Enable();
- Permit();
- if (woffset) {
- woffset = 0;
- } else {
- woffset = WOFFSET;
- }
- }
-
- void
- renderball(j)
- int j;
- {
- struct Ball *ball;
- int intr, size, y1, y2;
- int x, y, xp, yp, ired, igreen, iblue;
- int start;
- float nx, ny, nz, rz, id, is;
-
- ball = balls+j;
-
- if (ball->dup != -1) return;
-
- y1 = ball->y1;
- y2 = ball->y2;
- intr = ball->intr;
- size = ball->size;
-
- /* special mask is offset -1 in x */
-
- for (y = 0; y < size; y++) {
- start = 0;
- for (x = 0; x < size; x++) {
- xp = x - intr;
- yp = intr - y;
- nz = (ball->rad * ball->rad) - (xp * xp) - (yp * yp);
- if (nz >= 0.0) {
- mywritepixel1(&mbitmap,x,y+y1);
- nx = xp / ball->rad;
- ny = yp / ball->rad;
- nz = sqrt(nz) / ball->rad;
- id = lx*nx + ly*ny + lz*nz; /* diffuse intensity */
- rz = (nz + nz) * id - lz;
- if (rz < 0) rz = 0;
- is = ks * pow(rz,n);
- id = ka + kd * id;
- SETANDBOUND(ired, (id * ball->r + is));
- SETANDBOUND(igreen,(id * ball->g + is));
- SETANDBOUND(iblue, (id * ball->b + is));
- setcolor(x,y+y1,y+y2,ired,iblue,igreen,!start);
- if (start == 0) start = 1;
- } else if (start == 1) {
- dolast();
- if (!bw) mywritepixel1(&mbitmap,x-1,y+y2);
- start = 2;
- }
- }
- if (start == 1) {
- dolast();
- if (!bw) mywritepixel1(&mbitmap,x-1,y+y2);
- }
- }
- }
-