home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
120.lha
/
AnimBalls
/
animballs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-11-20
|
10KB
|
485 lines
/* 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);
}
}
}