home *** CD-ROM | disk | FTP | other *** search
- /* Accurate Rendering Algorithm Based on the Z-Buffer Algorithm
- Developed by Raghu Karinthi
- West Virginia University
- Department of Computer Science
- P.O.Box 6330
- Morgantown WV 26506-6330
- raghu@cs.wvu.edu
- Version 3 01/20/95 */
-
- #include "ZRendv3.h"
-
- #define ZFABS(x) (((x) < 0.0) ? -(x) : (x))
-
- #define sub_vec(res,V1,V2) \
- { \
- (res)[0] = (V1)[0] - (V2)[0]; \
- (res)[1] = (V1)[1] - (V2)[1]; \
- (res)[2] = (V1)[2] - (V2)[2]; \
- }
-
-
- #define dot_product(V1,V2) \
- ((V1)[0] * (V2)[0] + (V1)[1] * (V2)[1] + (V1)[2] * (V2)[2])
-
-
- #define mathpointmult(x,y,z,w,vec,mat) \
- { \
- (x) = (vec)[0] * (mat)[0][0] + \
- (vec)[1] * (mat)[0][1] + \
- (vec)[2] * (mat)[0][2] + \
- (mat)[0][3]; \
- \
- (y) = (vec)[0] * (mat)[1][0] + \
- (vec)[1] * (mat)[1][1] + \
- (vec)[2] * (mat)[1][2] + \
- (mat)[1][3]; \
- \
- (z) = (vec)[0] * (mat)[2][0] + \
- (vec)[1] * (mat)[2][1] + \
- (vec)[2] * (mat)[2][2] + \
- (mat)[2][3]; \
- \
- (w) = (vec)[0] * (mat)[3][0] + \
- (vec)[1] * (mat)[3][1] + \
- (vec)[2] * (mat)[3][2] + \
- (mat)[3][3]; \
- } /* mathpointmult */
-
- #define TSWAP(_a_, _b_, _c_) \
- { \
- (_c_) = (_a_); (_a_) = (_b_); (_b_) = (_c_); \
- }
-
-
- #define min(_a_, _b_) (((_a_) < (_b_)) ? (_a_) : (_b_))
- #define max(_a_, _b_) (((_a_) > (_b_)) ? (_a_) : (_b_))
-
-
- #define fp_int(x) \
- (((x) < 0) ? \
- (!((x) & LOMASK)) ? ((x) >> LOBITS) : (((x) >> LOBITS)+1) : \
- ((x) >> LOBITS) \
- )
-
-
- /*
- * Works only if x +ve.
- */
-
- #define fp_int_flr(x) ((x) >> LOBITS)
-
-
- /*
- * We use the following approximation.
- */
-
- #define fp_div(x,y) \
- (((x) < 0) ? ((x) / (y) - 1) << LOBITS : ((x) / (y)) << LOBITS)
-
- /*
- * Works only if xlo = 0.
- */
-
- #define fp_mult1(x,y) \
- (((x)<0) ? \
- -(((-(x) & HIMASK)>> LOBITS)*(y)) : \
- ((x)>> LOBITS)*(y))
- /*
- * Works only if xhi = 0
- */
-
- #define fp_mult2(x,y) \
- (((y)<0)?(-((((-(y))&HIMASK)>>LOBITS)*(x)+((((-(y))&LOMASK)*x)>>LOBITS)))\
- : (((y) >> LOBITS) * (x) + ((((y)&LOMASK)*x)>>LOBITS)))
-
- /*
- * Fractional Part if x +ve
- */
-
- #define fp_fraction(x) ((x) & LOMASK)
-
- /* Turn a double into a fixpoint number int two's complement.
- Negative numbers become: ~a + 1
- */
- fixpoint fp_fix(double x)
- {
- int negative = (x < 0);
- double i; /* integer part */
- /* not used: double fraction; /* fraction part, positive only */
- fixpoint p; /* fixpoint version of abs(x) */
-
- x = fabs(x);
- i = floor(x);
- /* not used: fraction = x - i; */
-
- p = (((int) i) << LOBITS) | ((int) ((x-i)*(1<<LOBITS)));
-
- if (negative) return (-p);
- else return (p);
- }
-
-
-
- /*
- * The following : edge data structure, and functions EdgeScan,
- * EdgeSetup, and rasterize_sorted_triangle, are modified from the code
- * obtained in Graphics Gems III subdirectory accurate_scan due to Kurt
- * Fleischer. Also Refer Lathrop, Kirk, Voorhies, IEEE CG&A 10(5),
- * 1990 for a discussion
- */
-
- /*
- * Array has the fields called E, Imin, Astep, Bstep, DEA and DEB
- * in the paper by Lathrop, Kirk and Voorhies.
- */
-
- typedef int edge[6];
-
-
- #define EdgeScan(e) \
- if ((e)[0] < 0 ) \
- { \
- (e)[1] += (e)[2]; (e)[0] += (e)[4]; \
- } \
- else \
- { \
- (e)[1] += (e)[3]; (e)[0] += (e)[5]; \
- }
-
- #define EdgeSetup(e,x0,y0,x1,y1) \
- { \
- dx = (x1)-(x0); \
- dy = (y1)-(y0); \
- if (dy >= FIX1) \
- { \
- si = fp_div(dx, dy); \
- sf = dx - fp_mult1(si, dy); \
- xi = (x0) + fp_mult2((FIX1 - fp_fraction((y0))),si) ; \
- e[2] = fp_int(si); \
- e[3] = e[2]+1; \
- e[4]= sf; \
- e[5] = sf - dy; \
- e[0] = fp_mult2(fp_fraction(xi),dy) + e[5]; \
- e[1] = fp_int(xi); \
- } \
- else e[1] = fp_int(x0); \
- } /* EdgeSetup */
-
- /*
- * This function applies the view Transform to set of triangles.
- */
-
- void viewTrans_DivByW_DevTrans (InDataSet localSet, register int count,
- MAT3mat transform)
- {
- int i, j;
-
- double x,y,z,w;
-
- /* For every triangle do... */
-
- for( i = 0; i < count; i++)
- {
- for( j = 0; j < 3; j++)
- {
- mathpointmult (x,y,z,w,localSet[i].vertices[j].vertex,transform)
-
- x /= w;
- y /= w;
- z /= w;
-
- localSet[i].vertices[j].vertex[X] = x * (double) WINDOW_WIDTH/2
- + (double) WINDOW_WIDTH/2;
- localSet[i].vertices[j].vertex[Y] = y * (double) WINDOW_WIDTH/2
- + (double) WINDOW_HEIGHT/2;
- localSet[i].vertices[j].vertex[Z] = z * (double) WINDOW_WIDTH
- + (double) WINDOW_WIDTH;
- } /* for j */
-
- } /* for i */
-
- } /* viewTrans_DivByW_DevTrans */
-
-
- /*
- * This function does the actual rasterization.
- * Like integer version, but uses EdgeSetup.
- */
-
- void rasterize_sorted_triangle (int minv,
- int midv,
- int maxv,
- InDataSet tp,
- FrameBuffer localBuff)
- {
- edge left, right,
- zleft, zright, zspan,
- rleft, rright, rspan,
- gleft, gright, gspan,
- bleft, bright, bspan;
- int x, yi,
- xmin, xmax;
- int temp;
- int temp1;
- int cw;
- fixpoint sf, xi, si, dx, dy;
- fixpoint fxmin, fxmax,
- fzmin, fzmax, z,
- frmin, frmax, r,
- fgmin, fgmax, g,
- fbmin, fbmax, b;
- fixpoint x0, y0, z0, r0, g0, b0;
- fixpoint x1, y1, z1, r1, g1, b1;
- fixpoint x2, y2, z2, r2, g2, b2;
-
- /*
- * Convert the vertices of the triangle and their color value
- * to 'fixpoint' representation.
- */
-
- x0 = fp_fix ((tp->vertices[minv]).vertex[X]);
- y0 = fp_fix ((tp->vertices[minv]).vertex[Y]);
- z0 = fp_fix ((tp->vertices[minv]).vertex[Z]);
-
- x1 = fp_fix ((tp->vertices[midv]).vertex[X]);
- y1 = fp_fix ((tp->vertices[midv]).vertex[Y]);
- z1 = fp_fix ((tp->vertices[midv]).vertex[Z]);
-
- x2 = fp_fix ((tp->vertices[maxv]).vertex[X]);
- y2 = fp_fix ((tp->vertices[maxv]).vertex[Y]);
- z2 = fp_fix ((tp->vertices[maxv]).vertex[Z]);
-
- r0 = (tp->vertices[minv]).red;
- g0 = (tp->vertices[minv]).green;
- b0 = (tp->vertices[minv]).blue;
-
- r1 = (tp->vertices[midv]).red;
- g1 = (tp->vertices[midv]).green;
- b1 = (tp->vertices[midv]).blue;
-
- r2 = (tp->vertices[maxv]).red;
- g2 = (tp->vertices[maxv]).green;
- b2 = (tp->vertices[maxv]).blue;
-
- /*
- * Find out whether the triangle edges are oriented in clockwise
- * or anti-clockwise direction.
- *
- */
-
- cw = ( ((tp->vertices[midv]).vertex[1] -
- (tp->vertices[minv]).vertex[1]) *
-
- ((tp->vertices[maxv]).vertex[0] -
- (tp->vertices[minv]).vertex[0])
-
- < ((tp->vertices[midv]).vertex[0] -
- (tp->vertices[minv]).vertex[0]) *
-
- ((tp->vertices[maxv]).vertex[1] -
- (tp->vertices[minv]).vertex[1])
- );
-
- /*
- * Setup first pair of edges.
- */
-
- if (cw)
- {
- EdgeSetup (left, x0, y0, x2, y2);
- EdgeSetup (zleft, z0, y0, z2, y2);
- EdgeSetup (rleft, r0, y0, r2, y2);
- EdgeSetup (gleft, g0, y0, g2, y2);
- EdgeSetup (bleft, b0, y0, b2, y2);
-
- EdgeSetup (right, x0, y0, x1, y1);
- EdgeSetup (zright, z0, y0, z1, y1);
- EdgeSetup (rright, r0, y0, r1, y1);
- EdgeSetup (gright, g0, y0, g1, y1);
- EdgeSetup (bright, b0, y0, b1, y1);
-
- } /* if cw orientation of edges */
-
- else
- {
- EdgeSetup (left, x0, y0, x1, y1);
- EdgeSetup (zleft, z0, y0, z1, y1);
- EdgeSetup (rleft, r0, y0, r1, y1);
- EdgeSetup (gleft, g0, y0, g1, y1);
- EdgeSetup (bleft, b0, y0, b1, y1);
-
- EdgeSetup (right, x0, y0, x2, y2);
- EdgeSetup (zright, z0, y0, z2, y2);
- EdgeSetup (rright, r0, y0, r2, y2);
- EdgeSetup (gright, g0, y0, g2, y2);
- EdgeSetup (bright, b0, y0, b2, y2);
-
- } /* else anti-clockwise orientation of edges */
-
-
- temp = min (fp_int_flr ((cw) ? y2 : y1), fp_int_flr ((cw) ? y1 : y2));
- for (yi = fp_int_flr (y0) + 1; yi <= temp; yi ++)
- {
- fxmin = left[1]; EdgeScan (left)
- fxmax = right[1]; EdgeScan (right)
- fzmin = zleft[1]; EdgeScan (zleft)
- fzmax = zright[1]; EdgeScan (zright)
- frmin = rleft[1]; EdgeScan (rleft)
- frmax = rright[1]; EdgeScan (rright)
- fgmin = gleft[1]; EdgeScan (gleft)
- fgmax = gright[1]; EdgeScan (gright)
- fbmin = bleft[1]; EdgeScan (bleft)
- fbmax = bright[1]; EdgeScan (bright)
-
- xmin = fxmin;
- xmax = fxmax;
-
- fxmin = fxmin << LOBITS;
- fxmax = fxmax << LOBITS;
- fzmin = fzmin << LOBITS;
- fzmax = fzmax << LOBITS;
- frmin = frmin << LOBITS;
- frmax = frmax << LOBITS;
- fgmin = fgmin << LOBITS;
- fgmax = fgmax << LOBITS;
- fbmin = fbmin << LOBITS;
- fbmax = fbmax << LOBITS;
-
- EdgeSetup (zspan, fzmin, fxmin, fzmax, fxmax);
- EdgeSetup (rspan, frmin, fxmin, frmax, fxmax);
- EdgeSetup (gspan, fgmin, fxmin, fgmax, fxmax);
- EdgeSetup (bspan, fbmin, fxmin, fbmax, fxmax);
-
- for (x = xmin + 1; x <= xmax; x ++)
- {
- z = zspan[1]; EdgeScan (zspan)
- r = rspan[1]; EdgeScan (rspan)
- g = gspan[1]; EdgeScan (gspan)
- b = bspan[1]; EdgeScan (bspan)
-
- if (localBuff[yi][x].z < z)
- {
- localBuff[yi][x].z = z;
- localBuff[yi][x].red = r;
- localBuff[yi][x].green = g;
- localBuff[yi][x].blue = b;
- }
-
- } /* for all pixels on the scan line between the edges */
-
- } /* for every scan line upto the lower 'y' of the two edges */
-
- /*
- * Setup the third edge.
- */
-
- if (!cw)
- {
- EdgeSetup (left, x1, y1, x2, y2);
- EdgeSetup (zleft, z1, y1, z2, y2);
- EdgeSetup (rleft, r1, y1, r2, y2);
- EdgeSetup (gleft, g1, y1, g2, y2);
- EdgeSetup (bleft, b1, y1, b2, y2);
- }
- else
- {
- EdgeSetup (right, x1, y1, x2, y2);
- EdgeSetup (zright, z1, y1, z2, y2);
- EdgeSetup (rright, r1, y1, r2, y2);
- EdgeSetup (gright, g1, y1, g2, y2);
- EdgeSetup (bright, b1, y1, b2, y2);
- }
-
- /*
- * Now scan convert the rest of the triangle.
- */
-
- temp = max (fp_int_flr ((cw) ? y0 : y1), fp_int_flr ((cw) ? y1 : y0)) + 1;
- temp1 = fp_int_flr (y2);
- for (yi = temp; yi <= temp1; yi ++)
- {
- fxmin = left[1]; EdgeScan (left)
- fxmax = right[1]; EdgeScan (right)
- fzmin = zleft[1]; EdgeScan (zleft)
- fzmax = zright[1]; EdgeScan (zright)
- frmin = rleft[1]; EdgeScan (rleft)
- frmax = rright[1]; EdgeScan (rright)
- fgmin = gleft[1]; EdgeScan (gleft)
- fgmax = gright[1]; EdgeScan (gright)
- fbmin = bleft[1]; EdgeScan (bleft)
- fbmax = bright[1]; EdgeScan (bright)
-
- xmin = fxmin;
- xmax = fxmax;
-
- fxmin = fxmin << LOBITS;
- fxmax = fxmax << LOBITS;
- fzmin = fzmin << LOBITS;
- fzmax = fzmax << LOBITS;
- frmin = frmin << LOBITS;
- frmax = frmax << LOBITS;
- fgmin = fgmin << LOBITS;
- fgmax = fgmax << LOBITS;
- fbmin = fbmin << LOBITS;
- fbmax = fbmax << LOBITS;
-
- EdgeSetup (zspan, fzmin, fxmin, fzmax, fxmax);
- EdgeSetup (rspan, frmin, fxmin, frmax, fxmax);
- EdgeSetup (gspan, fgmin, fxmin, fgmax, fxmax);
- EdgeSetup (bspan, fbmin, fxmin, fbmax, fxmax);
-
- for (x = xmin + 1; x <= xmax; x ++)
- {
- z = zspan[1]; EdgeScan (zspan)
- r = rspan[1]; EdgeScan (rspan)
- g = gspan[1]; EdgeScan (gspan)
- b = bspan[1]; EdgeScan (bspan)
-
- if (localBuff[yi][x].z < z)
- {
- localBuff[yi][x].z = z;
- localBuff[yi][x].red = r;
- localBuff[yi][x].green = g;
- localBuff[yi][x].blue = b;
- }
-
- } /* for every pixel on scan line b/w the left and right edges */
-
- } /* for every scan line till the uppermost vertex of the triangle */
-
- } /* rasterize_sorted_triangle */
-
-
- /*
- * Rasterizes a triangle. It first orients the triangle edges so that
- * vertex 0 is lower that vertex 1 which in turn is lower than vertex 2.
- */
-
- void rasterizeTriangle (FrameBuffer localBuff, InDataSet tp)
- {
- int minv = 0, midv = 1, maxv = 2, tmp = 0;
-
-
- if ((tp->vertices[minv]).vertex[Y] >
- (tp->vertices[midv]).vertex[Y])
- {
- TSWAP (minv, midv, tmp);
- }
-
- if ((tp->vertices[minv]).vertex[Y] >
- (tp->vertices[maxv]).vertex[Y])
- {
- TSWAP (minv, maxv, tmp);
- }
-
- if ((tp->vertices[midv]).vertex[Y] >
- (tp->vertices[maxv]).vertex[Y])
- {
- TSWAP (midv, maxv, tmp);
- }
-
- rasterize_sorted_triangle (minv, midv, maxv, tp, localBuff);
-
- } /* rasterizeTriangle */
-
-
- /*
- * The function rasterizes a set of triangles one at a time.
- */
-
- void Rasterize (InDataSet localSet, int count, FrameBuffer localBuff)
- {
- int i;
-
-
- for (i = 0; i < count; i ++)
- {
- rasterizeTriangle (localBuff, &localSet[i]);
- }
-
- } /* Rasterize */
-
-
- /*
- * Function to Shade the Triangle Vertices.
- */
-
- void Lighting (InDataSet localSet,int *datasizep,
- double Iar, double Iag, double Iab,
- double Kar, double Kdr, double Kag,
- double Kdg, double Kab, double Kdb,
- double c1, double c2,
- int num_lights, Lights lights)
- {
- int i = 0, j = 0, k = 0;
- MAT3vec temp1;
- double dist, r = 0.0, g = 0.0, b = 0.0;
- double tmp2r, tmp2g, tmp2b ;
-
- tmp2r = Iar * Kar * MAX_INTENSITY / (num_lights + 1);
- tmp2g = Iag * Kag * MAX_INTENSITY / (num_lights + 1);
- tmp2b = Iab * Kab * MAX_INTENSITY / (num_lights + 1);
-
- for (k=0; k < num_lights; k++) {
- lights[k].red *= Kdr * MAX_INTENSITY / (num_lights+1);
- lights[k].green *= Kdg * MAX_INTENSITY / (num_lights+1);
- lights[k].blue *= Kdb * MAX_INTENSITY / (num_lights+1);
- }
- for(i = 0; i < (*datasizep); i++)
- {
- for (j = 0; j < 3; j++)
- {
- r = tmp2r; g = tmp2g; b = tmp2b;
- for (k = 0; k < num_lights; k++)
- {
- sub_vec (temp1, lights[k].location,
- localSet[i].vertices[j].vertex)
-
- dist = sqrt (temp1[X]*temp1[X] +
- temp1[Y]*temp1[Y] +
- temp1[Z]*temp1[Z]);
-
- dist = 1 / dist * (1 + c1*dist + c2*dist*dist);
-
- r += ZFABS (lights[k].red * dist *
- dot_product (temp1, localSet[i].vertices[j].normal));
-
- g += ZFABS (lights[k].green * dist *
- dot_product (temp1, localSet[i].vertices[j].normal));
-
- b += ZFABS (lights[k].blue * dist *
- dot_product (temp1, localSet[i].vertices[j].normal));
-
- } /* for k */
-
- localSet[i].vertices[j].red = fp_fix(r);
- localSet[i].vertices[j].green = fp_fix(g);
- localSet[i].vertices[j].blue = fp_fix(b);
-
- } /* for j */
-
- } /* for i */
-
- } /* Lighting */
-
-
-
- void main(int argc, char **argv)
- {
- int i, j, datasize, num_lights;
- InDataSet localSet;
- Point vrp, prp;
- MAT3vec vpn, vupv;
- double fplane, bplane,
- umin, umax, vmin, vmax;
- MAT3mat vo_matrix, vm_matrix, transform;
- MtlProp activeProp;
- FrameBuffer localBuff;
- Lights lights;
- BackGroundColor backgndcolor;
- clock_t tm1, tm2;
-
-
- localSet = (InDataSet) calloc (1, NUM_TRIANGLES * sizeof (Triangle));
- lights = (Lights) calloc (1, NUM_LIGHT_SOURCES * sizeof (LightPoint));
-
- readNFFFile (argv[1], localSet,
- vrp, vpn, vupv,
- prp, &fplane, &bplane,
- &umin, &umax, &vmin, &vmax,
- lights, &backgndcolor,
- &datasize, &activeProp, &num_lights);
-
- #ifdef PRINTVIEWINGVALS
-
- fprintf (stderr, "Number of triangles: %d\n", datasize);
- fprintf (stderr, "Vrp : %lf %lf %lf\n",
- vrp[0], vrp[1], vrp[2]);
- fprintf (stderr, "Vpn : %lf %lf %lf\n",
- vpn[0], vpn[1], vpn[2]);
- fprintf (stderr, "Vupv : %lf %lf %lf\n",
- vupv[0], vupv[1], vupv[2]);
- fprintf (stderr, "prp : %lf %lf %lf\n",
- prp[0], prp[1], prp[2]);
- fprintf (stderr, "fplane : %lf\n", fplane);
- fprintf (stderr, "bplane : %lf\n", bplane);
- fprintf (stderr, "umin, umax : %lf %lf\n",
- umin, umax);
- fprintf (stderr, "vmin, vmax : %lf %lf\n",
- vmin, vmax);
-
- #endif /* PRINTVIEWINGVALS */
-
-
- for (i=0; i < WINDOW_HEIGHT; i++)
- {
- for (j=0; j < WINDOW_WIDTH; j++)
- {
- localBuff[i][j].red = backgndcolor.red;
- localBuff[i][j].green = backgndcolor.green;
- localBuff[i][j].blue = backgndcolor.blue;
- }
- }
-
- evaluateViewOrientationMatrix (vrp, vpn, vupv, vo_matrix);
- evaluateViewMappingMatrix (umin, umax, vmin, vmax,
- prp, fplane, bplane, vm_matrix);
- MAT3mult (transform, vm_matrix, vo_matrix);
-
- tm1 = clock ();
- Lighting (localSet, &datasize,
- activeProp.red, activeProp.green, activeProp.blue,
- activeProp.ambientK, activeProp.diffuseK,
- activeProp.ambientK, activeProp.diffuseK,
- activeProp.ambientK, activeProp.diffuseK,
- activeProp.c1, activeProp.c2, num_lights, lights);
- tm2 = clock ();
- printf ("Lighting took %f secs.\n",
- (double) (tm2-tm1)/CLOCKS_PER_SEC);
-
- tm1 = clock ();
- viewTrans_DivByW_DevTrans (localSet, datasize, transform);
- tm2 = clock ();
- printf ("Transformation took %f secs.\n",
- (double)(tm2-tm1)/CLOCKS_PER_SEC);
-
- tm1 = clock ();
- Rasterize (localSet, datasize, localBuff);
- tm2 = clock ();
- printf ("Rasterize took %f secs\n",(double) (tm2-tm1)/CLOCKS_PER_SEC);
-
- write_tga_buffer (localBuff, (argc > 2) ? argv[2] : DEFAULTOUT);
-
- free ((char *) localSet);
- free ((char *) lights);
-
- } /* main */
-
-
-
-