/* * OBJECT.C * */ #include "bubbles.h" extern long S_width, S_height, S_midwidth, S_dblheight; static uword maxpts, maxcon; static long X,Y,Z; static long CX,CY,CZ; static short Cost, Cosp, Sint, Sinp, CostCosp, CospSint, SintSinp, SinpCost; static long *Scrx, *Scry, *Scrz; static uword CTheta, CPhi; OBJECT * makeobject(pts, npts, con, ncon, x, y, z) long *pts; uword *con; { register OBJECT *obj = malloc(sizeof(OBJECT)); register short i; obj->points = pts; obj->connect= con; obj->npts = npts; obj->ncon = ncon; obj->x = x; obj->y = y; obj->z = z; obj->theta = obj->phi = obj->rot = 0; if (npts > maxpts) maxpts = npts; if (ncon > maxcon) maxcon = ncon; return(obj); } init_objectmodule() { Scrx = malloc(sizeof(long) * (maxpts+1)); Scry = malloc(sizeof(long) * (maxpts+1)); Scrz = malloc(sizeof(long) * (maxpts+1)); } setcamera(x,y,z,cx,cy,cz,rot) { X=x; Y=y; Z=z; CX=cx; CY=cy; CZ=cz; CTheta = ibearing(cx-x,cy-y); CPhi = ibearing(irange(cx-x,cy-y),cz-z); Cost = ICOS(CTheta); /* returns signed -32767 to 32767 */ Cosp = ICOS(CPhi); Sint = ISIN(CTheta); Sinp = ISIN(CPhi); CostCosp = (Cost * Cosp) >> 15; CospSint = (Cosp * Sint) >> 15; SintSinp = (Sint * Sinp) >> 15; SinpCost = (Sinp * Cost) >> 15; } setcamerad(x,y,z,cx,cy,cz,rot) { setcamera(X+x,Y+y,Z+z,CX+cx,CY+cy,CZ+cz,rot); } displayobj(rp,obj) RP *rp; OBJECT *obj; { register long x,y,z; register long *scrx,*scry,*scrz; short i; long *p; long dx,dy,dz; dx = obj->x - X; dy = obj->y - Y; dz = obj->z - Z; scrx = Scrx; scry = Scry; scrz = Scrz; for (p = obj->points, i = obj->npts; i; --i, p += 3,++scrx,++scry,++scrz) { /* * Transform to center */ x = p[0]+dx; y = p[1]+dy; z = p[2]+dz; /* * Align with Z access pointing ahead (Z>0 is visible). X heading * to the right, Y heading up */ scrz[0] = (((short)x * CostCosp)>>15) + (((short)y * CospSint)>>15) + (((short)z * Sinp)>>15); scrx[0] = -((((short)y * Cost)>>15) - (((short)x * Sint)>>15)); scry[0] = -(((short)x * SinpCost)>>15) - (((short)y * SintSinp)>>15) + (((short)z * Cosp)>>15); /* * Add Perspective approximation. */ if (scrz[0] > 0) { scrx[0] = (scrx[0] << 8) / (scrz[0] + 256); scry[0] = (scry[0] << 8) / (scrz[0] + 256); } else { scrx[0] = (scrx[0] * (-scrz[0] + 256)) >> 8; scry[0] = (scry[0] * (-scrz[0] + 256)) >> 8; } } connect(rp,obj->connect,obj->ncon); } connect(rp,connect,ncon) register uword *connect; { register long x1,y1,z1; register long x2,y2,z2; for (; ncon; --ncon, connect += 2) { x1 = S_midwidth+Scrx[connect[0]]; x2 = S_midwidth+Scrx[connect[1]]; y1 = S_height-Scry[connect[0]] ; y2 = S_height-Scry[connect[1]]; z1 = Scrz[connect[0]]; z2 = Scrz[connect[1]]; if (z1 < 0 && z2 < 0) continue; if (z1 < 0) { /* Calculate x & y intercept with window */ x1 -= z1 * (x2 - x1) / (z2 - z1); y1 -= z1 * (y2 - y1) / (z2 - z1); } if (z2 < 0) { x2 -= z2 * (x1 - x2) / (z1 - z2); y2 -= z2 * (y1 - y2) / (z1 - z2); } if (y1 < 0) { /* CLIP PT A */ if (y2 <= 0) continue; x1 += y1 * (x2 - x1) / (y1 - y2); y1 = 0; } else if (y1 >= S_dblheight) { if (y2 >= S_dblheight) continue; x1 += (y1 - S_dblheight) * (x2 - x1) / (y1 - y2); y1 = S_dblheight-1; } if (x1 < 0) { if (x2 <= 0) continue; y1 += x1 * (y2 - y1) / (x1 - x2); x1 = 0; } else if (x1 >= S_width) { if (x2 >= S_width) continue; y1 += (x1 - S_width) * (y2 - y1) / (x1 - x2); x1 = S_width-1; } if (y2 < 0) { /* CLIP PT B */ if (y1 <= 0) continue; x2 += y2 * (x1 - x2) / (y2 - y1); y2 = 0; } else if (y2 >= S_dblheight) { if (y1 >= S_dblheight) continue; x2 += (y2 - S_dblheight) * (x1 - x2) / (y2 - y1); y2 = S_dblheight-1; } if (x2 < 0) { if (x1 <= 0) continue; y2 += x2 * (y1 - y2) / (x2 - x1); x2 = 0; } else if (x2 >= S_width) { if (x1 >= S_width) continue; y2 += (x2 - S_width) * (y1 - y2) / (x2 - x1); x2 = S_width-1; } if (x1 < 0 || x1 >= S_width || y1 < 0 || y1 >= S_dblheight || x2 < 0 || x2 >= S_width || y1 < 0 || y2 >= S_dblheight) { printf("Softerror: %ld %ld %ld %ld\n", x1, y1>>1, x2, y2>>1); } else { static long lastx,lasty; if ((lastx != x1) || (lasty != y1)) Move(rp,x1,y1>>1); Draw(rp,x2,y2>>1); lastx = x2; lasty = y2; } } }