home *** CD-ROM | disk | FTP | other *** search
- /******************************************************
- InterPhong shading for Scan-line rendering algorithms
-
- InterPhong shading has been used for rendering the
- synthetic actors Marilyn
- Monroe and Humphrey Bogart in the film "Rendez-vous
- a Montreal" directed by Nadia Magnenat Thalmann and
- Daniel Thalmann, 1987
-
- *******************************************************/
-
- #include <math.h>
- #include "GraphicsGems.h"
-
- #define RESANTI 3839
- #define NBMAXSOURCES 10
- #define SQRT3_2 3.464101615
- #define NIL 0
-
- typedef struct {
- double r, g, b;
- } Colors;
-
- typedef struct {
- Colors coul;
- double w, n;
- } RecCoul;
-
- /* Declaration of types used for the datastructures that
- represent the information of a figure for the treatment by
- scanline ( software rendering )
- */
-
- typedef struct blocedge {
- struct blocedge *edsuiv; /* next edge in the list */
- struct blocpoly *ptpoly1, *ptpoly2; /*
- polygons sharing this edge */
- double x, dx; /* Xmin and Xdelta */
- double z, dz; /* Zmin and Zdelta */
- double ymax; /* maximum Y of edge */
- double nx, dnx, ny, dny, nz, dnz;
- double px, dpx, py, dpy, pz, dpz;
- } BlockEdge;
-
- typedef struct blocpoly {
- struct blocpoly *polsuiv; /* next polygon in the list */
- struct T_ptedge *ptlisttrie;
- RecCoul refl; /* polygon characteristics color, spec.
- coeff., ... */
- Colors coulpoly; /* polygon shading */
- Vector3 normalctri;
- double bias, tension;
- } BlockPoly;
-
- typedef struct T_ptedge {
- BlockEdge *ptedtrie;
- struct T_ptedge *ptedsuiv;
- } PtEdge;
-
- /*
- * Declaration of types concerning the calculated image for the
- * current scanline ( Z-buffer )
- */
-
- typedef struct scanbuf_el {
- Colors c, /* final color of this pixel */
- polycolor; /* initial color of
- visible polygon */
- } ScanBufType [RESANTI + 1];
-
- typedef struct epthbuf_el {
- double depth; /* depth of opaque
- pixel */
- } DepthBufType [RESANTI + 1];
-
- typedef struct {
- int xmin, xmax;
- } PosBufType;
-
- /*
- * Declaration of data structure types to store light source information
- */
-
- static PosBufType posbuffer;
-
- ScanBufType _scanbuffer; /* Z-buffer */
- DepthBufType _depthbuffer;
-
- static
- void intphong(nestime, noriginal, bias, tension)
- Vector3 *nestime, *noriginal;
- double bias, tension;
-
- /*
- Purpose: interphong interpolation
- Arguments
- nestime : estimated normal
- noriginal : original normal
- bias, tension : bias and tension
- */
-
- {
- double fact;
- Vector3 vtemp;
-
- V3Sub (noriginal, nestime, &vtemp);
- fact = fabs(vtemp.x) + fabs(vtemp.y) + fabs(vtemp.z);
- fact = (fact + bias * (SQRT3_2 - fact)) * tension;
- V3Scale (vtemp,fact*V3Length (vtemp));
- V3Add (nestime, &vtemp,nestime);
- V3Normalize (nestime);
- }
-
- /*===========================================================*/
-
- static
- void shadepoly(ptpoly)
- BlockPoly *ptpoly;
-
- /*
- Purpose: shades a polygon on the current scanline
- Arguments
- ptpoly : polygon to render
- noscline : current scanline
- */
-
- {
- BlockEdge *edge1, *edge2;
- PtEdge *tripedtrie;
- int xx;
- double dxx;
- double zz, dzz;
- double diffx;
- double dnnx, dnny, dnnz;
- Vector3 normal, unitn;
- double dppx, dppy, dppz;
- Vector3 point;
- Colors cc;
- RecCoul ptrefl;
- register struct scanbuf_el *scanel ;
- register struct depthbuf_el *depthel ;
-
- tripedtrie = ptpoly->ptlisttrie;
- ptrefl = ptpoly->refl;
- while (tripedtrie != (PtEdge *)NIL)
- {
- edge1 = tripedtrie->ptedtrie;
- if (tripedtrie->ptedsuiv != (PtEdge *)NIL)
- {
- tripedtrie = tripedtrie->ptedsuiv;
- edge2 = tripedtrie->ptedtrie;
- }
- else
- abort(" Odd number of edges on scanline");
-
- dxx = edge2->x - edge1->x; /* distance between edges
- on current scanline */
- if (dxx < 1.0) /* crossing edges ? */
- dxx = 1.0;
- dxx = 1.0 / dxx; /* increment per pixel */
- xx = Trunc(edge1->x) + 1; /* first pixel to be
- colored */
- diffx = xx - edge1->x;
-
- dzz = (edge2->z - edge1->z) * dxx;
- zz = edge1->z + dzz * diffx;
-
- if (xx < posbuffer.xmin)
- posbuffer.xmin = xx;
- if (edge2->x > posbuffer.xmax)
- posbuffer.xmax = Trunc(edge2->x);
-
- dnnx = (edge2->nx - edge1->nx) * dxx;
- dnny = (edge2->ny - edge1->ny) * dxx;
- dnnz = (edge2->nz - edge1->nz) * dxx;
- normal.x = (edge1->nx + dnnx * diffx) + dnnx;
- normal.y = (edge1->ny + dnny * diffx) + dnny;
- normal.z = (edge1->nz + dnnz * diffx) + dnnz;
- dppx = (edge2->px - edge1->px) * dxx;
- dppy = (edge2->py - edge1->py) * dxx;
- dppz = (edge2->pz - edge1->pz) * dxx;
- point.x = (edge1->px + dppx * diffx) + dppx;
- point.y = (edge1->py + dppy * diffx) + dppy;
- point.z = (edge1->pz + dppz * diffx) + dppz;
-
- while (xx <= edge2->x)
- {
- scanel = &_scanbuffer[xx];
- depthel = &_depthbuffer[xx];
-
- if (zz < depthel->depth)
- {
- unity(normal, &unitn);
- intphong(&unitn, &ptpoly->normalctri,
- ptpoly->bias, ptpoly->tension);
- cc = ptpoly->coulpoly;
- depthel->depth = zz;
- scanel->polycolor = ptrefl.coul;
- scanel->c = cc;
- }
- xx = xx + 1;
- zz = zz + dzz;
- normal.x = normal.x + dnnx;
- normal.y = normal.y + dnny;
- normal.z = normal.z + dnnz;
- point.x = point.x + dppx;
- point.y = point.y + dppy;
- point.z = point.z + dppz;
- }
- break ;
- tripedtrie = tripedtrie->ptedsuiv;
- }
- }
-
-
-
-
-