#define COLORDEPTH 255 #define DEPTHEXTEN 32760 typedef double point[3]; typedef void (*BFunction)(); typedef double (*ZFunction)(double x, double y); typedef void (*SFunction)(point p, double x, double y); typedef void (*CFunction)(point p, double x); const double CONV_RAD=M_PI/180; int do_init = 1, orient = 1; int width, height; double x_1,x_2,y_1,y_2,z_1,z_2; double ratio_x, ratio_y, ratio_z; double light_x, light_y, light_z; double m_rot[12]={1,0,0,0,0,1,0,0,0,0,1,0}; short int *z_depth = NULL; short int *luminosity = NULL; double max(double x, double y) { if(x>=y) return x; else return y; } double min(double x, double y) { if(x>=y) return x; else return y; } void setcolor(char *pix, char *val) { memcpy(pix, val, 3); } void create_3d_buffer() { z_depth = (short int *)malloc(width*height*sizeof(short int)); luminosity = (short int *)malloc(width*height*sizeof(short int)); } void free_3d_buffer() { if (z_depth) free(z_depth); if (luminosity) free(luminosity); z_depth = NULL; luminosity = NULL; } void init_3d_buffer() { int i, j, k; double light; if (do_init) { for (j=0; j0) { light_x = light_x/light; light_y = light_y/light; light_z = light_z/light; } ratio_x = (x_2-x_1)/(double)width; ratio_y = (y_2-y_1)/(double)height; if(ratio_x==0 || ratio_y==0) exit(1); ratio_z = z_2-z_1; if (ratio_z<=0) exit(1); else ratio_z = ((double)DEPTHEXTEN)/ratio_z; do_init = 0; } } void translation(double a, double b, double c) { m_rot[3] = a; m_rot[7] = b; m_rot[11] = c; } void scale(double a) { int i; for (i=0; i<=11; i++) m_rot[i] *= a; } void rotation_angles(double theta, double phi, double psi) { double ca,cb,cc, sa,sb,sc; ca=theta*CONV_RAD; cb=phi*CONV_RAD; cc=psi*CONV_RAD; sa=sin(ca); ca=cos(ca); sb=sin(cb); cb=cos(cb); sc=sin(cc); cc=cos(cc); m_rot[0] = ca*cb; m_rot[1] = -sa*cc-ca*sb*sc; m_rot[2] = sa*sc-ca*sb*cc; m_rot[4] = sa*cb; m_rot[5] = ca*cc-sa*sb*sc; m_rot[6] = -ca*sc-sa*sb*cc; m_rot[8] = sb; m_rot[9] = cb*sc; m_rot[10]= cb*cc; } void rotate(point p, point q) { int i,j; for (i=0; i<=2; i++) { j=4*i; q[i] = m_rot[j]*p[0]+m_rot[j+1]*p[1]+m_rot[j+2]*p[2]+m_rot[j+3]; } } void setpoint(point p, point q) { int i; for(i=0; i<=2; i++) p[i] = q[i]; } void mesh(point *p, int h, int i, int j) { point a[3], b, c; double ca,cb,cc,cd, s,t, adds,addt, x, y, z, z0,z1,z2; double delta_x, delta_y, delta_z, delta; int u1, u2, v1, v2, col; int k,l,m,n; init_3d_buffer(); rotate(p[h],a[0]); rotate(p[i],a[1]); rotate(p[j],a[2]); u1=width; u2=-1; v1=height; v2=-1; for(k=0; k<=2; k++) { l=(int)((a[k][0]-x_1)/ratio_x); if(lu2) u2=l; l=(int)((y_2-a[k][1])/ratio_y); if(lv2) v2=l; } if(u1<0) u1=0; if(u2>=width) u2=width-1; if(v1<0) v1=0; if(v2>=height) v2=height-1; if(u1>u2 || v1>v2) return; z0 = a[0][2]; z1 = a[1][2]-z0; z2 = a[2][2]-z0; z0 = (z0-z_1)*ratio_z; z1 = z1*ratio_z; z2 = z2*ratio_z; for (k=0; k<=2; k++) { b[k] = a[1][k] - a[0][k]; c[k] = a[2][k] - a[0][k]; } delta_x = b[1]*c[2] - b[2]*c[1]; delta_y = -b[0]*c[2] + b[2]*c[0]; delta_z = b[0]*c[1] - b[1]*c[0]; if (fabs(delta_z)<1E-5) return; delta = 1/delta_z; ca = c[1] * delta; cb = -c[0] * delta; cc = -b[1] * delta; cd = b[0] * delta; adds = ca*ratio_x; addt = cc*ratio_x; delta = -1/(sqrt(delta_x*delta_x + delta_y*delta_y + delta_z*delta_z)); delta_x = delta_x * delta; delta_y = delta_y * delta; delta_z = delta_z * delta; if (orient<0) { /* for (k=0; k<=2; k++) c[k] = (a[0][k] + a[1][k] + a[2][k])/3.0 - m_rot[3+4*k]; delta = c[0] * delta_x + c[1] * delta_y + c[2] * delta_z; if (delta>0) printf("+"); else printf("-"); if (delta<0) { delta_x = -delta_x; delta_y = -delta_y; delta_z = -delta_z; } */ delta_x = -delta_x; delta_y = -delta_y; delta_z = -delta_z; } col = 32767 * (1.000001 + light_x * delta_x + light_y*delta_y + light_z * delta_z); for(l=v1; l<=v2; l++) { x = x_1 + u1*ratio_x - a[0][0]; y = y_2 - l*ratio_y - a[0][1]; s = ca*x + cb*y; t = cc*x + cd*y; for(k=u1; k<=u2; k++) { if (s>=-0.0001 && t>=-0.0001 && s+t<=1.0001) { m = (int) (z0 + s*z1 + t*z2); if (m<-DEPTHEXTEN) m=-DEPTHEXTEN; if (m>DEPTHEXTEN) m=DEPTHEXTEN; n = k+l*width; if (m>z_depth[n]) { z_depth[n] = m; luminosity[n] = col; } } s = s + adds; t = t + addt; } } } void build(BFunction bfunct) { init_3d_buffer(); bfunct(); } void light(ZFunction zfunct) { int i, j; int k, l; double x,y; init_3d_buffer(); for(j=0; jDEPTHEXTEN) k=DEPTHEXTEN; l = i+j*width; if (k>z_depth[l]) z_depth[l] = k; } } } void surface(SFunction sfunct, double xi, double xs, int nx, double yi, double ys, int ny) { int i, j, l; double hx,hy; point p[4]; if (nx<=0 || ny<=0) return; init_3d_buffer(); hx = (xs-xi)/nx; hy = (ys-yi)/ny; for (j=0; jny) { min = ny; max = nx; dx = dxp; dy = 0; } else { min = nx; max = ny; dx = 0; dy = dyp; } dz = dz/((double)max); delta = max/2 - max; for (i=0; i<=max; i++) { u = x0+width*y0; if (x0>=0 && x0=0 && y0z_depth[u]) { luminosity[u] = 1; z_depth[u] = z; } } delta += min; if (delta>=max/2) { delta -= max; x0 += dxp; y0 += dyp; } else { x0 += dx; y0 += dy; } } } void curve(CFunction cfunct, double ti, double ts, int n) { int i, l; double h; point p[2]; if (n<=0) return; init_3d_buffer(); h = (ts-ti)/n; for (i=0; i<=n; i++) { if (i>=1) setpoint(p[0], p[1]); cfunct(p[1], ti+i*h); if (i>=1) segment(p); } }