home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
RISC DISC 3
/
RISC_DISC_3.iso
/
resources
/
etexts
/
gems
/
gemsii
/
interphong.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-26
|
5KB
|
224 lines
/******************************************************
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
#define Trunc(v) ((int)floor(v))
/* normalize vector, return in pn */
#define unity(v,pn) { double len ; \
len = sqrt((v).x*(v).x+(v).y*(v).y+(v).z*(v).z) ; \
(pn)->x=(v).x/len; (pn)->y=(v).y/len; \
(pn)->z=(v).z/len; }
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 depthbuf_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);
}
/*===========================================================*/
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;
}
tripedtrie = tripedtrie->ptedsuiv;
}
}