home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************/
- /* display.c */
- /* */
- /* Routines for displaying the current scene. */
- /* */
- /* Copyright (C) 1992, Bernard Kwok */
- /* All rights reserved. */
- /* Revision 1.0 */
- /* May, 1992 */
- /**********************************************************************/
- #include <stdio.h>
- #include "geo.h"
- #include "struct.h"
- #include "rad.h"
- #include "io.h"
- #include "display.h"
-
- extern OptionType Option;
- extern RadParams ReadLog;
- extern Colour Pr_Add_Ambient();
- extern int test_vtxshade;
-
- extern Scene RadScene;
- extern void Create_Initial_ReceiverList();
-
- #ifndef DAMN_SMALL
- #define DAMN_SMALL 1e-10
- #endif
-
- /**********************************************************************/
- /* Convert Spectra into RGB triples */
- /**********************************************************************/
- ColourChar SpectraToRGB(spectra)
- Spectra *spectra;
- {
- ColourChar c;
- Spectra r;
- double max=1.0;
- int k;
-
- /* Scale the intensity */
- for(k=MAX_SPECTRA_SAMPLES;k--;) {
- if(spectra->samples[k] > max)
- max = spectra->samples[k];
- }
- r = *spectra;
- if (max > 1.0) {
- for (k=MAX_SPECTRA_SAMPLES; k--;)
- r.samples[k] /= max;
- }
-
- /* Convert to a 32-bit colour, assume first 3 samples of spectra are
- r,g,b. else do colour conversion here */
- c.a = 0;
- c.r = (char) (r.samples[0] * RGB_SCALE + RGB_ROUND);
- c.g = (char) (r.samples[1] * RGB_SCALE + RGB_ROUND);
- c.b = (char) (r.samples[2] * RGB_SCALE + RGB_ROUND);
-
- return c;
- }
-
- /**********************************************************************/
- /* Scale Spectra is the values overflow */
- /**********************************************************************/
- Spectra SpectraScale(spectra)
- Spectra spectra;
- {
- Spectra r;
- double max=1.0;
- int k;
-
- /* Scale the intensity */
- for(k=MAX_SPECTRA_SAMPLES;k--;) {
- if(spectra.samples[k] > max)
- max = spectra.samples[k];
- }
- r = spectra;
- if (max > 1.0)
- for (k=0; k<MAX_SPECTRA_SAMPLES; k++)
- r.samples[k] /= max;
-
- return r;
- }
-
- /**********************************************************************/
- /* Find maximum spectra value for each spectrum */
- /**********************************************************************/
- void MaxSpectra(spectra, maxS)
- Spectra spectra;
- double maxS[3];
- {
- int k;
-
- /* Scale the intensity */
- for(k=0;k<MAX_SPECTRA_SAMPLES;k++)
- if(spectra.samples[k] > maxS[k])
- maxS[k] = spectra.samples[k];
- }
-
- /**********************************************************************/
- /* Colour scaling */
- /**********************************************************************/
- void ColourScale(c)
- Colour c;
- {
- double max=1.0;
-
- /* Scale the colour */
- if(c.r > max) max = c.r;
- if(c.g > max) max = c.g;
- if(c.b > max) max = c.b;
-
- if (max > 1.0) {
- c.r /= max;
- c.g /= max;
- c.b /= max;
- }
- }
-
- /**********************************************************************/
- /* Test if two polygons have the same surface properties */
- /* Only test for same simple reflectance, and emittance currently */
- /**********************************************************************/
- int Poly_SameProperties(p1, p2)
- Polygon *p1, *p2;
- {
- int i;
- Spectra p_p1, p_p2;
- Spectra E_p1, E_p2;
- int p_same, E_same;
-
- p_p1 = poly_reflect(p1);
- p_p2 = poly_reflect(p2);
- E_p1 = poly_emit(p1);
- E_p2 = poly_emit(p2);
-
- i=0; p_same = 1; E_same = 1;
- while(p_same && E_same && (i<MAX_SPECTRA_SAMPLES)) {
- p_same = (p_p1.samples[i] == p_p2.samples[i]);
- E_same = (E_p1.samples[i] == E_p2.samples[i]);
- i++;
- }
- return (p_same && E_same);
- }
-
- /**********************************************************************/
- /* Test if 2 polygons are on the same plane (different from coplanar) */
- /* Check same normal vector and d value */
- /**********************************************************************/
- int Poly_SamePlane(p1, p2)
- Polygon *p1, *p2;
- {
- return (vsame(&p1->normal[0], &p2->normal[0], VTX_TOLERANCE) &&
- equal(p1->d, p2->d));
- }
-
- /**********************************************************************/
- /* Interpolate vertex radiosities from adjacent patch radiosities */
- /**********************************************************************/
- void Interpolate_FromPatches(ep, c)
- Polygon *ep;
- Colour c[MAX_PATCH_VTX]; /* Colour of four vertices */
- {
- int i,j;
- int num_samples;
- PolyList *adjpolys;
- int num_adjpolys;
- int tmpc[MAX_PATCH_CHILDREN];
- int same_norm, same_obj, angle_ok;
- Vector current_vtx_pos, current_vtx_nrm;
- Colour tmpcol;
- Spectra polyp;
-
- polyp = poly_reflect(ep);
- for (i=0;i<ep->numVert;i++) {
- c[i].a = 0;
-
- /* Find adjacent polygons to this vertex */
- adjpolys = ep->vert[i]->polylist;
- num_adjpolys = ep->vert[i]->polyhead.num_polys;
- current_vtx_pos = ep->vert[i]->pos;
- current_vtx_nrm = ep->normal[0];
-
- /* Take average radiosity of adjacent polygons as vertex radiosity */
- /* Use (vertex rad * intensity scale) as RGB colour */
- num_samples = 0;
- c[i].r = 0.0;
- c[i].g = 0.0;
- c[i].b = 0.0;
- for(j=0;j<num_adjpolys;j++, adjpolys=adjpolys->next) {
-
- /* Polygon has no children */
- if (IsLeaf(adjpolys->patch, tmpc)) {
-
- /* Check same normal and same object */
- same_norm = vsame(&adjpolys->patch->normal[0], ¤t_vtx_nrm,
- VTX_TOLERANCE);
- same_obj = (poly_object(adjpolys->patch) == poly_object(ep));
-
- /* Don't interpolate around corners ! */
- angle_ok = (dot(&adjpolys->patch->normal[0], ¤t_vtx_nrm)
- >= DAMN_SMALL);
-
- /* Must have same properties and be on the same object */
- if (Poly_SameProperties(adjpolys->patch, ep) && angle_ok &&
- ((same_norm && !same_obj) || same_obj)) {
- c[i].r = c[i].r + adjpolys->patch->B.samples[0];
- c[i].g = c[i].g + adjpolys->patch->B.samples[1];
- c[i].b = c[i].b + adjpolys->patch->B.samples[2];
- num_samples++;
- }
- }
- }
- if (num_samples == 0) {
- (void) fprintf(stderr,"Oh Oh. This vertex does not belong to a polygon ! \n");
- exit(1);
- }
- c[i].r = c[i].r / (double) num_samples;
- c[i].g = c[i].g / (double) num_samples;
- c[i].b = c[i].b / (double) num_samples;
-
- if (Option.ambient) {
- c[i] = Pr_Add_Ambient(c[i], polyp);
- ColourScale(c[i]);
- }
- }
- }
-
- /**********************************************************************/
- /* Vertex radiosities = radiosity at vertex. No interpolation */
- /**********************************************************************/
- void Interpolate_FromVertices2(ep, c)
- Polygon *ep;
- Colour c[MAX_PATCH_VTX]; /* Colour of four vertices */
- {
- int i;
- Colour tmpcol;
- Spectra polyp;
-
- polyp = poly_reflect(ep);
- for (i=0;i<ep->numVert;i++) {
- c[i].r = ep->vtx_B[i].samples[0];
- c[i].g = ep->vtx_B[i].samples[1];
- c[i].b = ep->vtx_B[i].samples[2];
- if (Option.ambient) {
- c[i] = Pr_Add_Ambient(c[i], polyp);
- ColourScale(c[i]);
- }
- }
- }
-
- /**********************************************************************/
- /* Vertex radiosities = average of all vertex B values */
- /**********************************************************************/
- void Interpolate_FromVertices(ep, c)
- Polygon *ep;
- Colour c[MAX_PATCH_VTX]; /* Colour of four vertices */
- {
- int i,j,k;
- double num_samples;
- PolyList *adjpolys;
- int num_adjpolys;
- Vector current_vtx_pos;
- Vector current_vtx_nrm;
- int tmpc[MAX_PATCH_CHILDREN];
- Colour tmpcol;
- int same_norm, same_obj, angle_ok;
- Spectra polyp;
-
- for (i=0;i<ep->numVert;i++) {
-
- /* Find adjacent polygons to this vertex */
- adjpolys = ep->vert[i]->polylist;
- num_adjpolys = ep->vert[i]->polyhead.num_polys;
- current_vtx_pos = ep->vert[i]->pos;
- current_vtx_nrm = ep->normal[0];
-
- /* Take average radiosity of all vertex radiosities for a given
- vertex position as vertex radiosity. */
- num_samples = 1.0;
- c[i].r = ep->vtx_B[i].samples[0];
- c[i].g = ep->vtx_B[i].samples[1];
- c[i].b = ep->vtx_B[i].samples[2];
-
- for(j=0;j<num_adjpolys;j++, adjpolys=adjpolys->next) {
-
- /* Must not have any sub-elements, and can't be current poly */
- if (adjpolys->patch != ep) {
- if (IsLeaf(adjpolys->patch, tmpc)) {
-
- /* Check for same normal and same object */
- same_norm = vsame(&adjpolys->patch->normal[0], ¤t_vtx_nrm,
- VTX_TOLERANCE);
- same_obj = (poly_object(adjpolys->patch) == poly_object(ep));
-
- /* Don't interpolate around corners ! */
- angle_ok = (dot(&adjpolys->patch->normal[0], ¤t_vtx_nrm)
- >= DAMN_SMALL);
-
- /* Must have the same properties */
- if (Poly_SameProperties(adjpolys->patch, ep) && angle_ok &&
- ((same_norm && !same_obj) || same_obj)) {
-
- /* Must have the same vertex position */
- for (k=0;k<adjpolys->patch->numVert;k++) {
- if (vsame(&adjpolys->patch->vert[k]->pos, ¤t_vtx_pos,
- VTX_TOLERANCE)) {
- c[i].r = c[i].r + adjpolys->patch->vtx_B[k].samples[0];
- c[i].g = c[i].g + adjpolys->patch->vtx_B[k].samples[1];
- c[i].b = c[i].b + adjpolys->patch->vtx_B[k].samples[2];
- num_samples = num_samples + 1.0;
- } /* Same vtx */
- }
- } /* Same prop */
- } /* Not first */
- } /* Is leaf */
- }
- tmpcol.r = c[i].r / num_samples;
- tmpcol.g = c[i].g / num_samples;
- tmpcol.b = c[i].b / num_samples;
-
- /* Return interpolated vertex radiosities with or w/o ambient term */
- if (Option.ambient) {
- polyp = poly_reflect(ep);
- c[i] = Pr_Add_Ambient(tmpcol, polyp);
- ColourScale(c[i]);
- } else {
- c[i].r = tmpcol.r; c[i].g = tmpcol.g; c[i].b = tmpcol.b;
- }
- }
- }
-
- /**********************************************************************/
- /* Prepare receiver list of scaling all values first (not used) */
- /**********************************************************************/
- void Prep_List()
- {
- long i,k;
- Elist *el;
- Elist *tmp;
- Polygon *epr;
- Colour c[MAX_PATCH_VTX]; /* Colour of four vertices */
- Spectra tmpS;
- double maxS[3];
-
- /* Find elements to draw, and find max intensity */
- tmp = ReadLog.elements;
- el = ReadLog.elements;
- maxS[0] = 1.; maxS[1] = 1.; maxS[2] = 1.;
- for (k=0;k<ReadLog.num_elements;k++) {
- epr = el->element;
- for (i=0;i<epr->numVert;i++) {
- /* tmpS = SpectraScale(epr->vtx_B[i]); */
- MaxSpectra(epr->vtx_B[i], maxS);
- }
- el = el->next;
- }
- ReadLog.elements = tmp;
-
- el = ReadLog.elements;
- for (k=0;k<ReadLog.num_elements;k++) {
- epr = el->element;
- for (i=0;i<epr->numVert;i++) { /* Scale all vertex spectras */
- epr->vtx_dB[i].samples[0] = epr->vtx_B[i].samples[0] /* / maxS[0] */;
- epr->vtx_dB[i].samples[1] = epr->vtx_B[i].samples[1] /* / maxS[1] */;
- epr->vtx_dB[i].samples[2] = epr->vtx_B[i].samples[2] /* / maxS[2] */;
- }
- el = el->next;
- }
- ReadLog.elements = tmp;
- }
-
- /**********************************************************************/
- /* Display current PR results */
- /**********************************************************************/
- void DisplayResults(view)
- Camera view;
- {
- long i,k;
- Elist *elptr;
- Polygon *ep;
- Colour c[MAX_PATCH_VTX]; /* Colour of four vertices */
- Spectra tmpS;
-
- /* Prep_List(); */
- /* Create_Initial_ReceiverList(&RadScene); */
-
- if (Option.debug)
- (void) printf("\n\t> Drawing %d elements\n", ReadLog.num_elements);
-
- if (Option.show_pr_steps) Begin_DrawDispl(view, 0);
-
- /* Draw all elements in RGB scale */
- elptr = ReadLog.elements;
- for (k=0;k<ReadLog.num_elements;k++) {
- ep = elptr->element;
-
- /* Interpolate colour of vertex from colour of adjacent polygons
- or from adjacent vertices */
- if (Option.rad_interp_type == INTERP_VTX_FROM_PATCH)
- Interpolate_FromPatches(ep, c);
- else if (Option.rad_interp_type == INTERP_VTX_FROM_VTX) {
- if (test_vtxshade)
- Interpolate_FromVertices2(ep, c);
- else
- Interpolate_FromVertices(ep, c);
- } else
- (void) fprintf(stderr,"Invalid radiosity interpolation type %d\n",
- Option.rad_interp_type);
-
- if (Option.show_pr_steps)
- Draw_ElementRGB(ep, c);
- elptr = elptr->next;
- }
-
- if (Option.show_pr_steps) End_DrawDispl();
- }
-
- /**********************************************************************/
- /* Get radiosity (B) for polygon vertices */
- /**********************************************************************/
- void Poly_VertexB(ep, c)
- Polygon *ep;
- Colour c[MAX_PATCH_VTX]; /* Colour of four vertices */
- {
- /* Quantasize color */
- /* c = SpectraToRGB(&s); */
-
- /* Interpolate colour of vertex from colour of adjacent polygons
- or from adjacent vertices */
- if (Option.rad_interp_type == INTERP_VTX_FROM_PATCH)
- Interpolate_FromPatches(ep, c);
- else if (Option.rad_interp_type == INTERP_VTX_FROM_VTX) {
- if (test_vtxshade)
- Interpolate_FromVertices2(ep, c);
- else
- Interpolate_FromVertices(ep, c);
- }
- else
- (void) fprintf(stderr,"Invalid radiosity interpolation type %d\n",
- Option.rad_interp_type);
- }
-
- /**********************************************************************/
- /* Draw an element in single colour */
- /**********************************************************************/
- void Draw_Element(ep, colour)
- Polygon *ep;
- unsigned long colour;
- {
- Vector pts[MAX_PATCH_VTX];
- int nPts = ep->numVert;
- int j;
-
- for (j=0;j<nPts;j++)
- pts[j] = ep->vert[j]->pos;
- Draw_Polygon(nPts, pts, &(ep->normal[0]), colour);
- }
-
- /**********************************************************************/
- /* Draw an element shaded from vertx colours */
- /**********************************************************************/
- void Draw_ElementRGB(ep, colour)
- Polygon *ep;
- Colour colour[4];
- {
- Vector pts[MAX_PATCH_VTX];
- int nPts = ep->numVert;
- int j;
-
- for (j=0;j<nPts;j++)
- pts[j] = ep->vert[j]->pos;
- Draw_PolygonRGB(nPts, pts, &(ep->normal[0]), colour);
- }
-