/* ui_debug.c: debug submenu */ #include #include "ui.h" #include "uit.h" #include "scene.h" #include "geom.h" #include "select.h" #include "canvas.h" #include "patch.h" #include "error.h" #include "monitor.h" #include "time.h" #include "render.h" #include "file.h" #include "ui_pathdebug.h" #include "radiance.h" #include "GALERKIN/galerkin.h" /*************************** Debug menu ******************************************/ static void DumpMemoryBreakdownCallback(Widget w, XtPointer client_data, XtPointer call_data) { PrintPooledMemoryBreakdown(stderr); } static int more = FALSE; static Widget moreButton; static void MoreCallback(Widget w, XtPointer client_data, XtPointer call_data) { more = TRUE; } /* This routine manages the "More..." button in the main menu and * polls for events until the user pushes the button. */ void WaitForMore(void) { XtManageChild(moreButton); while (!more) ProcessWaitingEvents(); XtUnmanageChild(moreButton); ProcessWaitingEvents(); more = FALSE; } static void CreateMoreButton(Widget menuBar) { #ifdef MORE_BUTTON /* push buttons do not belong in the main menu ... some versions of Motif even * refuse to realize them. */ moreButton = CreatePushButton(menuBar, "moreButton", MoreCallback, (XtPointer)NULL); XtUnmanageChild(moreButton); #endif more = FALSE; } static void DoDumpPatchBounds(PATCH *P, VECTOR *hitp) { fprintf(stderr, "%f %f %f %f %f %f\n", P->bounds[MIN_X], P->bounds[MIN_Y], P->bounds[MIN_Z], P->bounds[MAX_X], P->bounds[MAX_Y], P->bounds[MAX_Z]); } void DumpPatchBounds(void) { SelectPatchSetCallback(DoDumpPatchBounds); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void DoDumpPatch(PATCH *P, VECTOR *hitp) { PatchPrint(stderr, P); } static void DumpPatchCallback(Widget w, XtPointer client_data, XtPointer call_data) { SelectPatchSetCallback(DoDumpPatch); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void LocatePatchCallback(Widget w, XtPointer client_data, XtPointer call_data) { int patchid = *(int *)client_data; int found = FALSE; ForAllPatches(P, Patches) { if (P->id == patchid) { RGBSET(P->color, 1., 0., 0.); found = TRUE; break; } } EndForAll; if (!found) { Error(NULL, "No patch with id %d found", patchid); } else { RenderNewDisplayList(); RenderScene(); } } static Widget CreateLocatePatchDialog(Widget parent, char *name) { static int patchid; Widget dialog = CreatePromptDialog(parent, name, FET_INTEGER, (XtPointer)&patchid, NULL, 0); XtAddCallback(dialog, XmNokCallback, LocatePatchCallback, (XtPointer)&patchid); return dialog; } static void DumpWorldCallback(Widget w, XtPointer client_data, XtPointer call_data) { GeomListIterate1B(World, GeomPrint, stdout); } static void DumpClustersCallback(Widget w, XtPointer client_data, XtPointer call_data) { GeomListIterate1B(ClusteredWorld, GeomPrint, stdout); } #ifdef TEST_SUBDIVISION #include "galerkinP.h" #include "render.h" static PATCH *rcv, *src; static INTERACTION *the_link; static void SelectInteraction(INTERACTION *link) { if (link->rcv->patch == rcv && link->src->patch == src) the_link = link; } static INTERACTION *FindInteraction(void) { fprintf(stderr, "Finding interactoin between rcv=patch id %d and src=patch id %d ...\n", rcv->id, src->id); the_link = (INTERACTION *)NULL; if (galstate.iteration_method == SOUTHWELL) { InteractionListIterate(TOPLEVEL_ELEMENT(src)->interactions, SelectInteraction); } else { InteractionListIterate(TOPLEVEL_ELEMENT(rcv)->interactions, SelectInteraction); } return the_link; } extern int RefineRecursive(INTERACTION *link); static void TestRegularElementSubdivision(PATCH *patch2, VECTOR *hitp) { ELEMENT *el = (ELEMENT *)patch2->radiance_data; INTERACTION *link; src = patch2; fprintf(stderr, "patch ID %d.\n", src->id); if (el && el->patch != patch2) { Error(NULL, "No Galerkin element for these patches!!\n"); return; } if (!(link=FindInteraction())) fprintf(stderr, "The patches don't interact\n"); else { fprintf(stderr, "The interaction:\n"); InteractionPrint(stderr, link); fprintf(stderr, "Now refining:\n"); if (RefineRecursive(link)) fprintf(stderr, "====> REPLACED\n"); else fprintf(stderr, "====> ACCURATE ENOUGH\n"); fprintf(stderr, "Now doing push-pull on the receiver:\n"); PushPullRadiance(link->rcv); RenderScene(); } /* fprintf(stderr, "Subdividing element ... "); fflush(stderr); RegularSubdivideElement(el); fprintf(stderr, "done. It now looks like:\n"); PrintElement(stderr, el); */ } static void TestRegularElementSubdivision1(PATCH *patch, VECTOR *hitp) { rcv = patch; fprintf(stderr, "patch ID %d\nNow select the source patch ... ", rcv->id); fflush(stderr); SelectPatchSetCallback(TestRegularElementSubdivision); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void TestRegularElementSubdivisionCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select receiver patch ... "); fflush(stderr); SelectPatchSetCallback(TestRegularElementSubdivision1); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif #ifdef TEST_UNIFORM_MAPPING #include "patch.h" static void TestUniformMapping(PATCH *patch, POINT *p) { double uniformu, uniformv, u, v; fprintf(stderr, "patch %d, point (%g,%g,%g)", patch->id, p->x, p->y, p->z); PatchUV(patch, p, &u, &v); fprintf(stderr, "bilinear or barycentric (u,v) = (%g,%g)\n", u, v); PatchUniformUV(patch, p, &uniformu, &uniformv); fprintf(stderr, "uniform (u,v) = (%g,%g)\n", uniformu, uniformv); PatchUniformPoint(patch, uniformu, uniformv, p); fprintf(stderr, "PatchUniformPoint -> (%g,%g,%g)\n", p->x, p->y, p->z); } static void TestUniformMappingCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a point on a patch ... "); fflush(stderr); SelectPatchSetCallback(TestUniformMapping); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /*TEST_UNIFORM_MAPPING*/ #define TEST_ID_RENDERING #ifdef TEST_ID_RENDERING #include "pools.h" #include "patch.h" #include "render.h" #include "potential.h" static void TestIdRenderingCallback(Widget w, XtPointer client_data, XtPointer call_data) { unsigned long *ids, *id; long x, y, i, nrpixels, lostpixels, maxpatchid; int *patchpixels; ids = RenderIds(&x, &y); nrpixels = x*y; lostpixels=0; maxpatchid = PatchGetNextID()-1; patchpixels = (int *)Alloc((maxpatchid+1) * sizeof(int)); for (i=0; i<=maxpatchid; i++) patchpixels[i] = 0; for (i=0, id=ids; i 0) fprintf(stderr, "patch %ld: %d pixels.\n", i, patchpixels[i]); } fprintf(stderr, "%ld lost pixels.\n", lostpixels); Free((char *)patchpixels, (maxpatchid+1)*sizeof(int)); UpdateDirectPotential(); RenderDirectPotential(); } #endif /* TEST_ID_RENDERING */ #ifdef TEST_POTENTIAL #include "potential.h" static void TestPotentialCallback(Widget w, XtPointer client_data, XtPointer call_data) { UpdateDirectPotential(); RenderDirectPotential(); } #endif /*TEST_POTENTIAL*/ /* #define TEST_SHAFTCULLING */ #ifdef TEST_SHAFTCULLING #include "shaftculling.h" #include "scene.h" #include "render.h" #include "camera.h" #include "geometry3d.h" extern int ShaftCullTestPatch(PATCH *, SHAFT *); extern void RenderShaft(SHAFT *shaft); static PATCH *rcv, *src; static SHAFT shaft; static POLYGON rcvpoly, srcpoly; static GEOMLIST *candlist = (GEOMLIST *)NULL; static enum {POLY_TO_POLY, BOX_TO_BOX} shaft_type; static int nrinside, nroverlap, nroutside; static POLYGON *PatchPolygon(PATCH *patch, POLYGON *poly) { poly->normal = patch->normal; poly->index = patch->index; BoundsCopy(patch->bounds, poly->bounds); poly->nrvertices = patch->nrvertices; poly->plane_constant = patch->plane_constant; poly->vertex[0] = *patch->vertex[0]->point; poly->vertex[1] = *patch->vertex[1]->point; poly->vertex[2] = *patch->vertex[2]->point; if (poly->nrvertices > 3) poly->vertex[3] = *patch->vertex[3]->point; return poly; } static void MakeShaftStats(PATCH *patch) { switch (ShaftCullTestPatch(patch, &shaft)) { case -1: nrinside++; break; case 0: nroverlap++; break; case 1: nroutside++; break; } } static void TestShaftCulling2(PATCH *patch, VECTOR *hitp) { PATCHLIST *patches = (PATCHLIST *)NULL; src = patch; fprintf(stderr, "patch ID %d\n", src->id); fflush(stderr); if (shaft_type == POLY_TO_POLY) { fprintf(stderr, "Constructing polygon-to-polygon shaft.\n"); if (!ConstructPolygonToPolygonShaft(PatchPolygon(rcv, &rcvpoly), PatchPolygon(src, &srcpoly), &shaft)) fprintf(stderr, "Couldn't construct shaft.\n"); } else { BOUNDINGBOX bounds; fprintf(stderr, "Constructing box-to-box shaft.\n"); if (!rcv->bounds) PatchBounds(rcv, bounds); if (!src->bounds) PatchBounds(src, bounds); if (!ConstructShaft(rcv->bounds, src->bounds, &shaft)) fprintf(stderr, "Couldn't construct shaft.\n"); } ShaftOmit(&shaft, (GEOM *)&rcv); ShaftOmit(&shaft, (GEOM *)&src); candlist = DoShaftCulling(ClusteredWorld, &shaft, GeomListCreate()); patches = BuildPatchList(candlist, PatchListCreate()); fprintf(stderr, "%d items in shaft, %s%d patches: ", GeomListCount(candlist), shaft.cut ? "shaft cut, " : "", PatchListCount(patches)); PatchListIterate1A(patches, PatchPrintID, stderr); nrinside = nroverlap = nroutside = 0; PatchListIterate(patches, MakeShaftStats); fprintf(stderr, "%d inside, %d overlapping, %d outside.\n", nrinside, nroverlap, nroutside); PatchListDestroy(patches); } static void TestShaftCulling1(PATCH *patch, VECTOR *hitp) { rcv = patch; fprintf(stderr, "patch ID %d\nNow select the source patch ... ", rcv->id); fflush(stderr); SelectPatchSetCallback(TestShaftCulling2); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void SelectPtPShaftCallback(Widget w, XtPointer client_data, XtPointer call_data) { shaft_type = POLY_TO_POLY; fprintf(stderr, "Select receiver patch ... "); fflush(stderr); SelectPatchSetCallback(TestShaftCulling1); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void SelectBtBShaftCallback(Widget w, XtPointer client_data, XtPointer call_data) { shaft_type = BOX_TO_BOX; fprintf(stderr, "Select receiver patch ... "); fflush(stderr); SelectPatchSetCallback(TestShaftCulling1); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void ShowShaftCallback(Widget w, XtPointer client_data, XtPointer call_data) { RenderShaft(&shaft); } static void ShowShaftPatch(PATCH *patch) { RenderSetColor(&Blue); RenderPatchOutline(patch); /* find intersection of patch with the shaft */ } static void ShowShaftContentsCallback(Widget w, XtPointer client_data, XtPointer call_data) { PATCHLIST *patches = (PATCHLIST *)NULL; patches = BuildPatchList(candlist, PatchListCreate()); PatchListIterate(patches, ShowShaftPatch); PatchListDestroy(patches); } static void TestShaftCullTestPatch(PATCH *patch, VECTOR *hitp) { int code = ShaftCullTestPatch(patch, &shaft); fprintf(stderr, "Patch %d is %s the shaft\n", patch->id, code == -1 ? "INSIDE" : (code == 0 ? "OVERLAPPING with" : (code == 1 ? "OUTSIDE" : "UNKNOWN w.r.t."))); } static void TestShaftCullTestPatchCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a patch ... "); fflush(stderr); SelectPatchSetCallback(TestShaftCullTestPatch); CanvasPushMode(CANVASMODE_SELECT_PATCH); } /* #define TESTSHAFTFORMFACTOR */ #ifdef TESTSHAFTFORMFACTOR #include "GALERKIN/galerkinP.h" #include "GALERKIN/basis.h" extern unsigned TestAreaToAreaFormFactor(INTERACTION *link, GEOMLIST *shadowlist); static void TestShaftFormFactorCallback(Widget w, XtPointer client_data, XtPointer call_data) { INTERACTION link; float ff[MAXBASISSIZE*MAXBASISSIZE]; link.K.p = ff; link.src = TOPLEVEL_ELEMENT(src); link.rcv = TOPLEVEL_ELEMENT(rcv); link.nsrc = link.src->basis_size; link.nrcv = link.rcv->basis_size; link.vis = TestAreaToAreaFormFactor(&link, candlist); InteractionPrint(stderr, &link); } #endif /*TESTSHAFTFORMFACTOR*/ #endif /*TEST_SHAFTCULLING*/ /*#define TESTFORMFACTOR*/ #ifdef TESTFORMFACTOR #include "radiance.h" #include "GALERKIN/galerkin.h" #include "GALERKIN/galerkinP.h" #include "GALERKIN/basis.h" extern unsigned TestAreaToAreaFormFactor(INTERACTION *link, GEOMLIST *shadowlist); PATCH *rcv, *src; static void TestFormFactor2(PATCH *p, POINT *hit) { INTERACTION link; float ff[MAXBASISSIZE*MAXBASISSIZE]; rcv = p; link.K.p = ff; link.src = TOPLEVEL_ELEMENT(src); link.rcv = TOPLEVEL_ELEMENT(rcv); link.nsrc = link.src->basis_size; link.nrcv = link.rcv->basis_size; link.vis = TestAreaToAreaFormFactor(&link, World); InteractionPrint(stderr, &link); } static void TestFormFactor1(PATCH *p, POINT *hit) { src = p; fprintf(stderr, "Select receiver patch ...\n"); SelectPatchSetCallback(TestFormFactor2); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void TestFormFactorCallback(Widget w, XtPointer client_data, XtPointer call_data) { if (!Radiance || Radiance != &GalerkinRadiosity) { Error(NULL, "First enable Galerkin radiosity ..."); return; } fprintf(stderr, "Select source patch ...\n"); SelectPatchSetCallback(TestFormFactor1); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /*TESTFORMFACTOR*/ static void StartMonitoringPatch(PATCH *patch, POINT *hitp) { fprintf(stderr, "patch id %d\n", patch->id); MonitorAdd(patch); } static void StartMonitoringPatchCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select the patch to be monitored ... "); fflush(stderr); SelectPatchSetCallback(StartMonitoringPatch); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void StartMonitorPatchIDCallback(Widget w, XtPointer client_data, XtPointer call_data) { int patchid = *(int *)client_data; ForAllPatches(P, Patches) { if (P->id == patchid) { MonitorAdd(P); return; } } EndForAll; Error(NULL, "No patch with id %d found", patchid); } static Widget CreateMonitorPatchDialog(Widget parent, char *name) { static int patchid; Widget dialog = CreatePromptDialog(parent, name, FET_INTEGER, (XtPointer)&patchid, NULL, 0); XtAddCallback(dialog, XmNokCallback, StartMonitorPatchIDCallback, (XtPointer)&patchid); return dialog; } static void StopMonitoringPatch(PATCH *patch, POINT *hitp) { fprintf(stderr, "patch id %d\n", patch->id); MonitorRemove(patch); } static void StopMonitoringPatchCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select the patch not to be monitored anymore ... "); fflush(stderr); SelectPatchSetCallback(StopMonitoringPatch); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #ifdef RECORD_MONITORED /* patch.h */ static void ClosePatchMonitorFilesCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr,"Closing all monitor-files\n"); PatchListIterate(Patches, PatchCloseAllRecordFiles); } #endif #ifdef TEST_BREP static void PrintNeighbourPatch(BREP_WING *wing) { BREP_WING *owing = BrepEdgeOtherWing(wing); if (!owing->contour) fprintf(stderr, "No neighbour.\n"); else fprintf(stderr, "Patch %d.\n", ((PATCH *)(owing->contour->face->client_data))->id); } static void TestPatchNeighbours(PATCH *patch, POINT *hitp) { fprintf(stderr, "patch id %d.\n", patch->id); if (!patch->brep_data) fprintf(stderr, "No BREP data for this patch!\n"); else if (!patch->brep_data->outer_contour) fprintf(stderr, "No contour defined for the BREP_FACE corresponding to the patch!\n"); else { fprintf(stderr, "iterating over the wings of the contour of the face corresponding to the patch ...\n"); BrepContourIterateWings(patch->brep_data->outer_contour, PrintNeighbourPatch); fprintf(stderr, "So ... that's it!\n"); } } static void TestNeighboursCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a patch ... "); fflush(stderr); SelectPatchSetCallback(TestPatchNeighbours); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /*TEST_BREP*/ /* #define DUMP_GALERKIN_MATRIX */ #ifdef DUMP_GALERKIN_MATRIX #include "GALERKIN/galerkinP.h" static void PatchDumpFormFactors(PATCH *patch, FILE *fp) { ELEMENT *top = TOPLEVEL_ELEMENT(patch); INTERACTIONLIST *ilist; for (ilist = top->interactions; ilist; ilist = ilist->next) { INTERACTION *link = ilist->interaction; double d; VECTORDIST(link->rcv->pog.patch->midpoint, link->src->pog.patch->midpoint, d); fprintf(fp, "%d %d %10f %f %f\n", link->rcv->id, link->src->id, REFLECTIVITY(link->rcv->pog.patch).r * ((link->nrcv == 1 && link->nsrc == 1) ? link->K.f : link->K.p[0]) / link->rcv->area, SELFEMITTED_RADIANCE(link->rcv->pog.patch).r, d); } } static void DumpMatrixCallback(Widget w, XtPointer client_data, XtPointer call_data) { FILE *fp; char *fname = "formfactor.matrix"; if (!Radiance || Radiance != &GalerkinRadiosity) { Error(NULL, "Can only dump the form factor matrix after doing Galerkin radiosity computations"); return; } if ((fp = fopen(fname, "w")) == (FILE *)NULL) { Error(NULL, "Can't open file '%s' for writing", fname); return; } fprintf(stderr, "Dumping form factor matrix to file '%s' ... \n", fname); PatchListIterate1A(Patches, (void (*)(PATCH *, void *))PatchDumpFormFactors, (void *)fp); fprintf(stderr, "Done.\n"); fclose(fp); } #endif /*DUMP_GALERKIN_MATRIX*/ /* #define EXAMINE_ELEMENT_HIERARCHY */ #ifdef EXAMINE_ELEMENT_HIERARCHY #include "radiance.h" #include "GALERKIN/galerkin.h" #include "GALERKIN/galerkinP.h" static ELEMENT *current_element = (ELEMENT *)NULL; static PATCH *current_patch = (PATCH *)NULL; static VECTOR current_hitp; static void DrawLink(INTERACTION *link) { POINT x, y; ELEMENT *drawel = link->src == current_element? link->rcv : link->src; RGB linkcol; linkcol.r = linkcol.g = linkcol.b = (float)link->vis / 255.; RenderSetColor(&linkcol); x = ElementMidpoint(link->rcv); y = ElementMidpoint(link->src); RenderLine(&x, &y); DrawElementOutline(drawel); } static void DrawLinks(ELEMENT *elem) { InteractionListIterate(elem->interactions, DrawLink); } static void DoStartExamineElementHierarchy(PATCH *P, VECTOR *hitp) { current_hitp = *hitp; fprintf(stderr, "at point "); VectorPrint(stderr, current_hitp); fprintf(stderr, "\n"); current_patch = P; current_element = TOPLEVEL_ELEMENT(P); RenderSetColor(&Green); DrawElementOutline(current_element); DrawLinks(current_element); PrintElement(stderr, current_element); } static void ExamineElementHierarchyUp(Widget w, XtPointer client_data, XtPointer call_darta) { if (!current_element) { Error(NULL, "First select a point at which to examine the element hierarchy"); return; } if (!current_element->parent) { fprintf(stderr, "At top of element hierarchy.\n"); return; } current_element = current_element->parent; RenderSetColor(&Green); DrawElementOutline(current_element); DrawLinks(current_element); PrintElement(stderr, current_element); } static int ClusterContainsPatch(ELEMENT *clus, PATCH *patch) { if (!IsCluster(clus)) return clus->pog.patch == patch; else { /* cluster contains the patch if any of it's subclusters contains the patch */ ELEMENTLIST *ellist; for (ellist=clus->irregular_subelements; ellist; ellist=ellist->next) { ELEMENT *subclus = ellist->element; if (ClusterContainsPatch(subclus, patch)) return TRUE; } } return FALSE; } static ELEMENT *SubclusterContainingPatch(ELEMENT *elem, PATCH *patch) { ELEMENTLIST *ellist; for (ellist=elem->irregular_subelements; ellist; ellist=ellist->next) { ELEMENT *subclus = ellist->element; if (ClusterContainsPatch(subclus, patch)) return subclus; } return (ELEMENT *)NULL; } static ELEMENT *RegularSubelementContainingPoint(ELEMENT *elem, POINT *point) { ELEMENT *subelem; double u, v; PatchUniformUV(current_patch, point, &u, &v); subelem = RegularLeafElementAtPoint(TOPLEVEL_ELEMENT(current_patch), &u, &v); while (subelem->parent) { if (subelem->parent == elem) return subelem; else subelem = subelem->parent; } return (ELEMENT *)NULL; } static void ExamineElementHierarchyDown(Widget w, XtPointer client_data, XtPointer call_darta) { if (!current_element) { Error(NULL, "First select a point at which to examine the element hierarchy"); return; } if (!current_element->regular_subelements && !current_element->irregular_subelements) { fprintf(stderr, "At bottom of element hierarchy.\n"); return; } if (IsCluster(current_element)) current_element = SubclusterContainingPatch(current_element, current_patch); else current_element = RegularSubelementContainingPoint(current_element, ¤t_hitp); if (!current_element) { Error(NULL, "Coulnd't find subelement at current location"); return; } RenderSetColor(&Green); DrawElementOutline(current_element); DrawLinks(current_element); PrintElement(stderr, current_element); } static void StartExamineElementHierarchy(Widget w, XtPointer client_data, XtPointer call_data) { if (Radiance != &GalerkinRadiosity) { Error(NULL, "This function only works for Galerkin radiosity."); return; } current_element = (ELEMENT *)NULL; fprintf(stderr, "Select a patch ... "); SelectPatchSetCallback(DoStartExamineElementHierarchy); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /*EXAMINE_ELEMENT_HIERARCHY*/ #define TEST_SGL #ifdef TEST_SGL #include "camera.h" #include "SGL/sgl.h" #include static void TestSGLRenderPatch(PATCH *patch) { VECTOR verts[4]; int i; /* back face culling */ if (VECTORDOTPRODUCT(patch->normal, Camera.eyep) + patch->plane_constant < EPSILON) return; sglSetColor((SGL_PIXEL) ((unsigned)(patch->color.b * 255.) << 16 | (unsigned)(patch->color.g * 255.) << 8 | (unsigned)(patch->color.r * 255.))); for (i=0; inrvertices; i++) verts[i] = *patch->vertex[i]->point; sglPolygon(patch->nrvertices, verts); } static void TestSGLDumpFrameBuffer(SGL_CONTEXT *sgl, char *fname) { SGL_PIXEL *pix; int i; FILE *fp = fopen(fname, "w"); if (!fp) { Error("TestSGLDumpFrameBuffer", "Can't open file '%s' for writing", fname); return; } fprintf(fp, "P6\n%d %d\n255\n", sgl->width, sgl->height); for (pix = sgl->fbuf, i=0; iwidth * sgl->height; pix++, i++) { fputc((*pix) & 0xff, fp); fputc((*pix >> 8) & 0xff, fp); fputc((*pix >> 16) & 0xff, fp); } fclose(fp); } static void TestSGLCallback(Widget w, XtPointer client_data, XtPointer call_data) { clock_t t; SGL_CONTEXT *sgl; sgl = sglOpen(Camera.hres, Camera.vres); sglDepthTesting(TRUE); sglClipping(TRUE); /* sglViewport(0, 0, Camera.hres-20, Camera.vres-20); */ sglClear(0, SGL_ZMAX); sglLoadMatrix(Perspective(Camera.fov*2.*M_PI/180., (float)Camera.hres/(float)Camera.vres, Camera.near, Camera.far)); sglMultMatrix(LookAt(Camera.eyep, Camera.lookp, Camera.updir)); /* { BOUNDINGBOX bbx; TRANSFORM lookat = LookAt(Camera.eyep, Camera.lookp, Camera.updir); BoundsTransform(ClusteredWorldGeom->bounds, &lookat, bbx); sglLoadMatrix(Ortho(bbx[MIN_X], bbx[MAX_X], bbx[MIN_Y], bbx[MAX_Y], -bbx[MAX_Z], -bbx[MIN_Z])); sglMultMatrix(lookat); } */ t = clock(); PatchListIterate(Patches, TestSGLRenderPatch); t = clock() - t; fprintf(stderr, "1x rendering took %g sec.\n", (double)t / (double)CLOCKS_PER_SEC); fprintf(stderr, "Dumping frame buffer to 'sgl.ppm'.\n"); TestSGLDumpFrameBuffer(sgl, "sgl.ppm"); fprintf(stderr, "Done.\n"); sglClose(sgl); } #endif /*TEST_SGL*/ #include "cie.h" static void MakeMgfColor(COLOR col, float *x, float *y, float *intensity) { float s, rgb[3], xyz[3]; #ifdef RGBCOLORS rgb[0] = col.spec[0]; rgb[1] = col.spec[1]; rgb[2] = col.spec[2]; rgb_xyz(rgb, xyz); #else xyz[0] = col.spec[0]; xyz[1] = col.spec[1]; xyz[2] = col.spec[2]; #endif *intensity = xyz[1]; s = xyz[0] + xyz[1] + xyz[2]; if (s > EPSILON) { *x = xyz[0] / s; *y = xyz[1] / s; } else { *x = *y = 0.3333333333; } } #ifdef DUMP_REFL /* doesn't work anymore!!!! */ static void DumpMaterial(MATERIAL *mat) { HITREC hit; VECTOR p = {0.,0.,0.}; VECTOR n = {0.,0.,1.}; InitHit(&hit, (PATCH*)1 /*cheating*/, (GEOM *)NULL, &p, &n, mat, 0); COLOR rho = BsdfDiffuseReflectance(mat->bsdf, &hit, &n); float x, y, rd; MakeMgfColor(rho, &x, &y, &rd); printf("m %s =\n\tc\n\t\tcxy %g %g\n\trd %g\n\n", mat->name, x, y, rd); } static void DumpReflectivities(Widget w, XtPointer client_data, XtPointer call_data) { ForAllInList(MATERIAL, mat, MaterialLib) { DumpMaterial(mat); } EndForAll; } #endif /*DUMP_REFL*/ /* #define TEST_RAYTRACING */ #ifdef TEST_RAYTRACING static void DrawVirtualScreen(Widget w, XtPointer client_data, XtPointer call_data) { VECTOR upperleft, s,e; double x,y,h,v; int i, num; RenderSetColor(&Red); h = 2. * tan(Camera.hfov * M_PI/180.) / (float)(Camera.hres-1); v = 2. * tan(Camera.vfov * M_PI/180.) / (float)(Camera.vres-1); x = -h * (float)(Camera.hres)/2.0 ; y = -v * (float)(Camera.vres)/2.0; VECTORSCALE(1.0, Camera.Z, upperleft); VECTORCOMB3(upperleft, x, Camera.X, y, Camera.Y, upperleft); VECTORADD(Camera.eyep, upperleft, upperleft); num = 10; for(i=0; i <= num; i++) { /* Horizontal */ VECTORCOMB2(1.0, upperleft, i*(Camera.vres*v)/(float)num, Camera.Y, s); VECTORCOMB2(1.0, s, (Camera.hres*h), Camera.X, e); RenderLine(&s,&e); RenderLine(&Camera.lookp,&s); RenderLine(&Camera.lookp,&e); VECTORCOMB2(1.0, upperleft, i*(Camera.hres*h)/(float)num, Camera.X, s); VECTORCOMB2(1.0, s, (Camera.vres*v), Camera.Y, e); RenderLine(&s,&e); RenderLine(&Camera.lookp,&s); RenderLine(&Camera.lookp,&e); } } #endif /* #define TEST_RAYINTERSECT */ #ifdef TEST_RAYINTERSECT static void DoTestRayIntersect(PATCH *patch, POINT *p) { fprintf(stderr, "hit patch %d ('%s' material)\n", patch->id, patch->surface->material->name); } static void TestRayIntersect(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a pixel ... "); fflush(stderr); SelectPatchSetCallback(DoTestRayIntersect); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /* TEST_RAYINTERSECT*/ #define TEST_LIGHTMETERING #ifdef TEST_LIGHTMETERING #include "lightmetering.h" #include "statistics.h" static void TestLightMetering(Widget w, XtPointer client_data, XtPointer call_data) { float avlum = DetermineAverageIncidentLuminance(); fprintf(stderr, "Average incident luminance = %g\n", avlum); reference_luminance = 5.42 *avlum; RenderNewDisplayList(); RenderScene(); } #endif /*TEST_LIGHTMETERING*/ #define TEST_GLOBAL_LINE #ifdef TEST_GLOBAL_LINE #include "globallines.h" static void ShowHit(HITREC *hit) { RenderSetColor(&Yellow); RenderPoint(&hit->point); /* RenderSetColor(&Blue); RenderPatchOutline(hit->patch); */ } static void PrintRenderSpan(HITREC *start, HITREC *end) { PrintSpan(start, end); /* show the line */ ShowHit(start); ShowHit(end); RenderSetColor(&Yellow); RenderLine(&start->point, &end->point); } static void PrintRenderSpans(HITLIST *hits) { if (ProcessSpans(hits, PrintRenderSpan) == 0) fprintf(stderr, "No spans.\n"); } /* generates, traces and processes a global line */ void TestGlobalLine(void) { int i; InitGlobalLines(NULL, DefCompareHits, PrintRenderSpans); for (i=0; i<100; i++) { fprintf(stderr, "Line %d\n", i); if (!DoGlobalLine(i)) fprintf(stderr, "No hits.\n"); } RenderFinish(); } static void TestGlobalLineCallback(Widget w, XtPointer client_data, XtPointer call_data) { TestGlobalLine(); } #endif /*TEST_GLOBAL_LINE*/ #define RAYTRACING_TEST #ifdef RAYTRACING_TEST #include "scene.h" #include "hitlist.h" /* Ray Tracing Confidence Test */ static int rtct_global_lines_per_patch = 10; static double *Random4D(int n) { static double xi[4]; srand48(n); xi[0] = drand48(); xi[1] = drand48(); xi[2] = drand48(); xi[3] = drand48(); return xi; } static void AccumulateHitCount(HITLIST *hits) { ForAllHits(hit, hits) { hit->patch->radiance_data = (void*)((int)(hit->patch->radiance_data) + 1); } EndForAll; } static void TestRayTracingCallback(Widget w, XtPointer client_data, XtPointer call_data) { int i, numpatches, nr_global_lines; float avlpp, avlpp2, lines_unit_area; if (Radiance) { Error("TestRayTracingCallback", "Switch off radiance computations before doing the ray tracing confidence test ..."); return; } /* count nr of patches and set nr of hits for each patch to zero. */ numpatches = 0; ForAllPatches(P, Patches) { P->radiance_data = (void*)0; /* store hit count in 'radiance_data' */ numpatches++; } EndForAll; /* initialise global line tracing */ InitGlobalLines(Random4D, NULL /* no sorting */, AccumulateHitCount); /* glin_Radius and glin_Center (unused here) are the radius and center of * a bounding sphere for the scene. They are computed as a side result * of InitGLobalLines */ nr_global_lines = rtct_global_lines_per_patch * numpatches; lines_unit_area = (2.0 * nr_global_lines) / (4. * M_PI * glin_Radius * glin_Radius); /* trace global lines anc count hits */ fprintf(stderr, "Tracing %d global lines ...\n", nr_global_lines); CanvasPushMode(CANVASMODE_WORKING); for (i=0; iradiance_data); /* observed nr of lines */ float expect = P->area * lines_unit_area; /* expected nr of lines */ float dev = (have - expect) / expect; /* relative deviation */ if (dev < -0.5) P->color = Red; else if (dev < -0.1) P->color = Yellow; else if (dev < 0.1) P->color = White; else if (dev < 0.5) P->color = Turquoise; else P->color = Blue; avlpp += have/expect; avlpp2 += have * have / (expect * expect); } EndForAll; avlpp /= numpatches; avlpp2 /= numpatches; fprintf(stderr, "Effective/predicted lines per patch ratio: %g (+/-%g)\n", avlpp, sqrt(avlpp2 - avlpp*avlpp)); if (renderopts.smooth_shading) { Warning(NULL, "Switch off smooth shading in order to see the result."); } RenderScene(); } static Widget CreateLinesPerPatchDialog(Widget parent, char *name) { return CreatePromptDialog(parent, name, FET_INTEGER, (XtPointer)&rtct_global_lines_per_patch, NULL, 0); } static void CreateRayTracingTestMenu(Widget parent) { Widget menu = CreateSubMenu(parent, "Ray Tracing Confidence Test Settings", "rtctMenu"); CreateCascadeDialog(menu, "Lines per Patch", CreateLinesPerPatchDialog, "linesPerPatchDialog", NULL, NULL); } #endif /* RAYTRACING_TEST */ #define SHOW_NORMALS #ifdef SHOW_NORMALS extern int do_render_normals; static void ShowNormalsCallback(Widget w, XtPointer client_data, XtPointer call_data) { do_render_normals = 1 - do_render_normals; RenderScene(); } #endif /*SHOW_NORMALS*/ #define TEST_BSDF_SAMPLING #ifdef TEST_BSDF_SAMPLING #include "camera.h" #include "ray.h" static POINT refpoint; int debug_mat = FALSE; static void DoTestBsdfSampling(PATCH *patch, POINT *p) { RAY ray; HITREC *hit, hitstore; VECTOR inDir, outDir; double pdf, pdfRR; float dist; COLOR bsdfval; int doRR = FALSE; HITREC phit; debug_mat = TRUE; fprintf(stderr, "hit patch %d ('%s' material)\n", patch->id, patch->surface->material->name); InitHit(&phit, patch, NULL, p, &patch->normal, patch->surface->material, 0.); VECTORSUBTRACT(Camera.eyep, *p, inDir); VECTORNORMALIZE(inDir); fprintf(stderr, "Camera.eyep = "); VectorPrint(stderr, Camera.eyep); fprintf(stderr, " - point = "); VectorPrint(stderr, *p); fprintf(stderr, " ===> inDir = "); VectorPrint(stderr, inDir); fprintf(stderr, "\n"); ray.pos = *p; ray.dir = BsdfSample(patch->surface->material->bsdf, &phit, (BSDF *)NULL, (BSDF *)NULL, &inDir, doRR, BSDF_ALL_COMPONENTS, drand48(), drand48(), &pdf); fprintf(stderr, "pdf = %f, ray.dir = ", pdf); VectorPrint(stderr, ray.dir); fprintf(stderr, "\n"); bsdfval = BsdfEval(patch->surface->material->bsdf, &phit, (BSDF *)NULL, (BSDF *)NULL, &inDir, &ray.dir, BSDF_ALL_COMPONENTS); fprintf(stderr, "bsdfval = "); ColorPrint(stderr, bsdfval); if (pdf > 0.) { COLORSCALE((VECTORDOTPRODUCT(ray.dir, patch->normal)/pdf), bsdfval, bsdfval); fprintf(stderr, ", times cos / pdf = "); ColorPrint(stderr, bsdfval); } fprintf(stderr, "\n"); BsdfEvalPdf(patch->surface->material->bsdf, &phit, (BSDF *)NULL, (BSDF *)NULL, &inDir, &ray.dir, BSDF_ALL_COMPONENTS, &pdf, &pdfRR); fprintf(stderr, "pdf = %f, pdfRR = %f\n", pdf, pdfRR); dist = HUGE; if (pdf > 0. && (hit = GridIntersect(WorldGrid, &ray, EPSILON, &dist, HIT_FRONT, &hitstore))) { fprintf(stderr, "ray.pos = "); VectorPrint(stderr, ray.pos); fprintf(stderr, ", hit->point = "); VectorPrint(stderr, hit->point); fprintf(stderr, "\n"); RenderSetColor(&Yellow); RenderLine(&ray.pos, &hit->point); RenderFinish(); } fprintf(stderr, "BSDF and PDF evaluation w.r.t refpoint:\n"); VECTORSUBTRACT(refpoint, *p, outDir); VECTORNORMALIZE(outDir); fprintf(stderr, "refpoint = "); VectorPrint(stderr, refpoint); fprintf(stderr, " - point = "); VectorPrint(stderr, *p); fprintf(stderr, " = outDir = "); VectorPrint(stderr, outDir); fprintf(stderr, "\n"); fprintf(stderr, "cos_in = %g, cos_out = %g\n", VECTORDOTPRODUCT(inDir, patch->normal), VECTORDOTPRODUCT(outDir, patch->normal)); bsdfval = BsdfEval(patch->surface->material->bsdf, &phit, (BSDF *)NULL, (BSDF *)NULL, &inDir, &outDir, BSDF_ALL_COMPONENTS); fprintf(stderr, "bsdfval = "); ColorPrint(stderr, bsdfval); fprintf(stderr, "\n"); BsdfEvalPdf(patch->surface->material->bsdf, &phit, (BSDF *)NULL, (BSDF *)NULL, &inDir, &outDir, BSDF_ALL_COMPONENTS, &pdf, &pdfRR); fprintf(stderr, "pdf = %f, pdfRR = %f\n", pdf, pdfRR); if (pdf > 0.) { COLORSCALE((VECTORDOTPRODUCT(inDir, patch->normal)/pdf), bsdfval, bsdfval); fprintf(stderr, "bsdf * times cos_in / pdf = "); ColorPrint(stderr, bsdfval); fprintf(stderr, "\n"); } fprintf(stderr, "And now if we switch inDir and outDir:\n"); bsdfval = BsdfEval(patch->surface->material->bsdf, &phit, (BSDF *)NULL, (BSDF *)NULL, &outDir, &inDir, BSDF_ALL_COMPONENTS); fprintf(stderr, "bsdfval = "); ColorPrint(stderr, bsdfval); fprintf(stderr, "\n"); BsdfEvalPdf(patch->surface->material->bsdf, &phit, (BSDF *)NULL, (BSDF *)NULL, &outDir, &inDir, BSDF_ALL_COMPONENTS, &pdf, &pdfRR); fprintf(stderr, "pdf = %f, pdfRR = %f\n", pdf, pdfRR); if (pdf > 0.) { COLORSCALE((VECTORDOTPRODUCT(outDir, patch->normal)/pdf), bsdfval, bsdfval); fprintf(stderr, "bsdf x times cos_out / pdf = "); ColorPrint(stderr, bsdfval); } fprintf(stderr, "\n"); debug_mat = FALSE; } static void DoTestBsdfSampling1(PATCH *patch, POINT *p) { refpoint = *p; fprintf(stderr, "\n"); fprintf(stderr, "Select a scattering point ... "); fflush(stderr); SelectPatchSetCallback(DoTestBsdfSampling); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void TestBsdfSampling(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a reference point ... "); fflush(stderr); SelectPatchSetCallback(DoTestBsdfSampling1); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void ShowShadingFrame(PATCH *patch, POINT *P) { HITREC hit; VECTOR X, Y, Z; fprintf(stderr, "hit patch %d ('%s' material)\n", patch->id, patch->surface->material->name); InitHit(&hit, patch, (GEOM*)NULL, P, &patch->normal, patch->surface->material, 0.); HitShadingFrame(&hit, &X, &Y, &Z); RenderCoordinateFrame(&hit.point, &X, &Y, &Z); fprintf(stderr, "point = "); VectorPrint(stderr, hit.point); fprintf(stderr, "\n"); fprintf(stderr, "normal= "); VectorPrint(stderr, hit.gnormal); fprintf(stderr, "\n"); fprintf(stderr, "X = "); VectorPrint(stderr, X); fprintf(stderr, ", norm = %f\n", VECTORNORM(X)); fprintf(stderr, "Y = "); VectorPrint(stderr, Y); fprintf(stderr, ", norm = %f\n", VECTORNORM(Y)); fprintf(stderr, "Z = "); VectorPrint(stderr, Z); fprintf(stderr, ", norm = %f\n", VECTORNORM(Z)); } static void ShowShadingFrameCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a point ... "); fflush(stderr); SelectPatchSetCallback(ShowShadingFrame); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void PrintAlbedoAtHit(HITREC *hit, VECTOR *eyedir, BSDFFLAGS mode, char *name) { COLOR albedo = BsdfScatteredPower(hit->material->bsdf, hit, eyedir, mode); fprintf(stderr, "%s = ", name); ColorPrint(stderr, albedo); fprintf(stderr, "\n"); } static void PrintReflectanceAtHit(HITREC *hit, VECTOR *eyedir, XXDFFLAGS mode, char *name) { COLOR albedo = BsdfReflectance(hit->material->bsdf, hit, eyedir, mode); fprintf(stderr, "%s = ", name); ColorPrint(stderr, albedo); fprintf(stderr, "\n"); } static void PrintTransmittanceAtHit(HITREC *hit, VECTOR *eyedir, XXDFFLAGS mode, char *name) { COLOR albedo = BsdfTransmittance(hit->material->bsdf, hit, eyedir, mode); fprintf(stderr, "%s = ", name); ColorPrint(stderr, albedo); fprintf(stderr, "\n"); } static void PrintAlbedoes(PATCH *patch, POINT *P) { HITREC hit; VECTOR eyedir; fprintf(stderr, "hit patch %d ('%s' material)\n", patch->id, patch->surface->material->name); InitHit(&hit, patch, (GEOM*)NULL, P, &patch->normal, patch->surface->material, 0.); VECTORSUBTRACT(Camera.eyep, *P, eyedir); VECTORNORMALISE(eyedir); if (hit.material->bsdf) { fprintf(stderr, "Testing BsdfScatetredPower():\n"); PrintAlbedoAtHit(&hit, &eyedir, BRDF_DIFFUSE_COMPONENT, "diffuse reflection"); PrintAlbedoAtHit(&hit, &eyedir, BRDF_GLOSSY_COMPONENT, "glossy reflection"); PrintAlbedoAtHit(&hit, &eyedir, BRDF_SPECULAR_COMPONENT, "specular reflection"); PrintAlbedoAtHit(&hit, &eyedir, BTDF_DIFFUSE_COMPONENT, "diffuse refraction"); PrintAlbedoAtHit(&hit, &eyedir, BTDF_GLOSSY_COMPONENT, "glossy refraction"); PrintAlbedoAtHit(&hit, &eyedir, BTDF_SPECULAR_COMPONENT, "specular refraction"); fprintf(stderr, "Testing BsdfReflectance():\n"); PrintReflectanceAtHit(&hit, &eyedir, DIFFUSE_COMPONENT, "diffuse reflection"); PrintReflectanceAtHit(&hit, &eyedir, GLOSSY_COMPONENT, "glossy reflection"); PrintReflectanceAtHit(&hit, &eyedir, SPECULAR_COMPONENT, "specular reflection"); fprintf(stderr, "Testing BsdfTransmittance():\n"); PrintTransmittanceAtHit(&hit, &eyedir, DIFFUSE_COMPONENT, "diffuse refraction"); PrintTransmittanceAtHit(&hit, &eyedir, GLOSSY_COMPONENT, "glossy refraction"); PrintTransmittanceAtHit(&hit, &eyedir, SPECULAR_COMPONENT, "specular refraction"); } else fprintf(stderr, "not a scattering material\n"); } static void PrintAlbedoesCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a point ... "); fflush(stderr); SelectPatchSetCallback(PrintAlbedoes); CanvasPushMode(CANVASMODE_SELECT_PATCH); } static void TestHackPath(PATCH *patch, POINT *P) { HITREC hit; VECTOR eyedir; RAY ray; } static void TestHackPathCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a point ... "); fflush(stderr); SelectPatchSetCallback(TestHackPath); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /* TEST_BSDF_SAMPLING */ /* #define TEST_PHOTONMAP */ #ifdef TEST_PHOTONMAP #include "PHOTONMAP/pmap.h" static POINT rc_point; static PATCH *rc_patch; static void DoTestPmapReconstruction(PATCH *patch, POINT *p) { VECTOR dir; VECTORSUBTRACT(*p, rc_point, dir); VECTORNORMALIZE(dir); PmapTestReconstruction(rc_point, rc_patch, dir); } static void DoTestPmapReconstruction1(PATCH *patch, POINT *p) { rc_point = *p; rc_patch = patch; fprintf(stderr, "\n"); fprintf(stderr, "Select a destination point ... \n"); fflush(stderr); SelectPatchSetCallback(DoTestPmapReconstruction); CanvasPushMode(CANVASMODE_SELECT_PATCH); } void TestPhotonmapReconstruction(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Photonmap reconstruction\n"); fprintf(stderr, "Select a reconstruction point ... "); fflush(stderr); SelectPatchSetCallback(DoTestPmapReconstruction1); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /* TEST_PHOTONMAP */ static void BuildIdToPatchTable(PATCH *patch, PATCH **id2patch) { id2patch[patch->id] = patch; } static void Raycast(FILE *fp, COLOR (*GetRadiance)(PATCH *P, double u, double v, VECTOR dir)) { PATCH **id2patch; unsigned long *ids, *id; long i, j, x, y, nrpixels, maxpatchid, lostpixels; RGB *pix; RAY ray; float v, h, xsample, ysample, dist; HITREC *hit, hitstore; CanvasPushMode(CANVASMODE_RENDER); /* get the patch IDs for each pixel. */ ids = RenderIds(&x, &y); if (!ids) return; nrpixels = x*y; lostpixels=0; /* build a table to convert a patch ID to the corresponding PATCH * */ maxpatchid = PatchGetNextID()-1; id2patch = (PATCH **)Alloc((maxpatchid+1) * sizeof(PATCH *)); for (i=0; i<=maxpatchid; i++) id2patch[i] = (PATCH *)NULL; PatchListIterate1A(Patches, BuildIdToPatchTable, (void *)id2patch); pix = (RGB *)Alloc(x * sizeof(RGB)); /* h and v are the horizontal resp. vertical distance between two * neighbooring pixels on the screen. */ h = 2. * tan(Camera.hfov * M_PI/180.) / (float)x; v = 2. * tan(Camera.vfov * M_PI/180.) / (float)y; /* the ray origin is the same for all eye-rays */ ray.pos = Camera.eyep; if (fp) fprintf(fp, "P6\n%ld %ld\n255\n", x, y); for (j=y-1, ysample=-v*(float)(y-1)/2.; j>=0; j--, ysample+=v) { id = ids + j*x; for (i=0, xsample=-h*(float)(x-1)/2.; ipatch, &pt, &u, &v); VECTORSCALE(-1, ray.dir, dir); rad = GetRadiance(hit->patch, u, v, dir); /* rad = GetDirectRadiance(hit->patch, u, v, dir); */ RadianceToRGB(rad, &pix[i]); /* if (hit->patch != the_patch) { pix[i] = Red; lostpixels++; } */ } else { pix[i] = Black; /* if (the_patch) { pix[i] = Red; lostpixels++; } */ } } if (fp) { for (i=0; i 0) Warning(NULL, "%d lost pixels", lostpixels); Free((char *)pix, x * sizeof(RGB)); Free((char *)id2patch, (maxpatchid+1) * sizeof(PATCH *)); Free((char *)ids, nrpixels * sizeof(unsigned long)); CanvasPullMode(); } #define TEST_EDF_SAMPLING #ifdef TEST_EDF_SAMPLING #include "camera.h" #include "ray.h" #ifndef TEST_BSDF_SAMPLING static POINT refpoint; #endif static PATCH *refpatch; static COLOR EvalDirectRadiance(PATCH *P, double u, double v, VECTOR eyedir) { POINT p; VECTOR dir; HITREC hit; PatchPoint(P, u, v, &p); InitHit(&hit, refpatch, NULL, &p, &refpatch->normal, refpatch->surface->material, 0.); VECTORSUBTRACT(p, refpoint, dir); VECTORNORMALIZE(dir); return EdfEval(refpatch->surface->material->edf, &hit, &dir, ALL_COMPONENTS, (double *)0); } static void DoTestEdfEval(PATCH *patch, POINT *p) { refpoint = *p; refpatch = patch; if (!patch->surface->material->edf) { fprintf(stderr, "Not a light source!! Try again.\n"); return; } Raycast((FILE *)NULL, EvalDirectRadiance); } static void TestEdfEval(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a point on a light source... "); fflush(stderr); SelectPatchSetCallback(DoTestEdfEval); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #include extern double drand48(void); static void DoTestEdfSampling(PATCH *patch, POINT *p) { VECTOR dir; COLOR val; RGB col; double pdf; EDF *edf = patch->surface->material->edf; int i; RAY ray; HITREC *hit, hitstore; float dist; if (!edf) { fprintf(stderr, "Not a light source!! Try again.\n"); return; } ray.pos = *p; fprintf(stderr, "%s %d: p = ", __FILE__, __LINE__); VectorPrint(stderr, *p); fprintf(stderr, "\n"); fprintf(stderr, "\n"); for (i=0; i<10; i++) { float cosa; HITREC phit; InitHit(&phit, patch, NULL, p, &patch->normal, patch->surface->material, 0.); dir = EdfSample(edf, &phit, ALL_COMPONENTS, drand48(), drand48(), &val, &pdf); fprintf(stderr, "==> dir = "); VectorPrint(stderr, dir); fprintf(stderr, "\nval = "); ColorPrint(stderr, val); fprintf(stderr, ", pdf = %f\n", pdf); cosa = VECTORDOTPRODUCT(dir, patch->normal); COLORSCALE(cosa / pdf, val, val); fprintf(stderr, "radiance = "); ColorPrint(stderr, val); fprintf(stderr, "\n"); ray.dir = dir; dist = HUGE; if ((hit = GridIntersect(WorldGrid, &ray, EPSILON, &dist, HIT_FRONT, &hitstore))) { RadianceToRGB(val, &col); RenderSetColor(&col); RenderLine(p, &hit->point); } else fprintf(stderr, "No hit.\n"); } RenderFinish(); } static void TestEdfSampling(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a point on a light source ... "); fflush(stderr); SelectPatchSetCallback(DoTestEdfSampling); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /* TEST_EDF_SAMPLING */ #define PRINT_MATERIAL #ifdef PRINT_MATERIAL static void DoPrintMaterial(PATCH *P, POINT *p) { MaterialPrint(stderr, P->surface->material); } static void PrintMaterialCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a patch ... "); fflush(stderr); SelectPatchSetCallback(DoPrintMaterial); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /*PRINT_MATERIAL*/ /*#define TEST_PATH*/ #ifdef TEST_PATH extern void TestTracePath(int i); /* MCRAD/rwrad.c */ static int patcnt = 1; #include "MCRAD/rwrad.h" static void TestPathCallback(Widget w, XtPointer client_data, XtPointer call_data) { if (Radiance!=&RandomWalkRadiosity) { fprintf(stderr, "This test requires Random Walk Radiosity!\n"); return; } TestTracePath(patcnt); patcnt++; } #endif /*TEST_PATH*/ #define TEST_RTSPIXEL #ifdef TEST_RTSPIXEL #include "RAYTRACING/rtstochastic.h" static void DoTraceDebugPixel(int pixx, int pixy) { RTStochastic_DebugPixel(pixx, pixy); } static void TraceDebugPixelCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a pixel ... "); fflush(stderr); SelectPixelSetCallback(DoTraceDebugPixel); CanvasPushMode(CANVASMODE_SELECT_PIXEL); } #endif #define PIXEL_RADIANCE #ifdef PIXEL_RADIANCE #include "color.h" #include "raytracing.h" #include "RAYTRACING/rtstochastic.h" #include "RAYTRACING/bidirpath.h" static void DoGetPixelRadiance(int pixx, int pixy) { COLOR rad; if(RayTracing) { if(RayTracing == &RT_StochasticMethod) rad = RTStochastic_GetPixel(pixx, pixy); if(RayTracing == &RT_BidirPathMethod) rad = Bidir_GetPixel(pixx, pixy); fprintf(stderr, "Radiance at (%d, %d) is ", pixx, pixy); ColorPrint(stderr, rad); fprintf(stderr, ".\n"); } } static void GetPixelRadianceCallback(Widget w, XtPointer clien_data, XtPointer call_data) { fprintf(stderr, "Select a pixel ..."); fflush(stderr); SelectPixelSetCallback(DoGetPixelRadiance); CanvasPushMode(CANVASMODE_SELECT_PIXEL); } #endif /* PIXEL_RADIANCE */ #define SAVEDEPTH #ifdef SAVEDEPTH extern void SaveDepth(char *fname, FILE *fp, int ispipe); static void SaveDepthCallback(Widget w, XtPointer client_data, XtPointer call_data) { FILE *fp = fopen("depth.ppm", "w"); fprintf(stderr, "Saving depth image in 'depth.ppm' ..."); fflush(stderr); SaveDepth("depth.ppm", fp, FALSE); fprintf(stderr, "done.\n"); fclose(fp); } #endif /*SAVEDEPTH*/ #define DUMPS #ifdef DUMPS #include "ui_dump.h" #endif /*DUMPS*/ #define MCR_DUMP_LEAF #ifdef MCR_DUMP_LEAF #include "MCRAD/mcrad.h" extern void McrDumpLeaf(PATCH *P, double u, double v); static void McrDumpLeafAtPoint(PATCH *P, POINT *p) { double u, v; PatchUV(P, p, &u, &v); McrDumpLeaf(P, u, v); } static void McrDumpLeafCallback(Widget w, XtPointer client_data, XtPointer call_data) { if (Radiance != &StochasticRelaxationRadiosity) { Error(NULL, "This test requires Stochastic Relaxation Radiosity"); return; } fprintf(stderr, "Select a point ... "); fflush(stderr); SelectPatchSetCallback(McrDumpLeafAtPoint); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif /*MCR_DUMP_LEAF*/ #define DUMP_MGF #ifdef DUMP_MGF #include "patch_flags.h" static MATERIAL *lastmat; static int vcount; static void GeomListDumpMGF(FILE *out, GEOMLIST *gl); static void DiffuseColorDumpMGF(FILE *out, COLOR col, char *id) { float x, y, intensity; MakeMgfColor(col, &x, &y, &intensity); fprintf(out, "c\ncxy %g %g\n%s %g\n", x, y, id, intensity); } #include "vertex.h" static PATCH *FakePatch(void) { VECTOR p[3] = { {0,0,0}, {1,0,0}, {0,1,0} }; VERTEX *v[3]; v[0] = VertexCreate(&p[0], NULL, NULL, NULL); v[1] = VertexCreate(&p[1], NULL, NULL, NULL); v[2] = VertexCreate(&p[2], NULL, NULL, NULL); return PatchCreate(3, v[0], v[1], v[2], NULL); } static void MaterialDumpMGF(FILE *out, MATERIAL *mat) { static PATCH *fakepatch = NULL; VECTOR p = {0.5, 0.5, 0.}; HITREC hit; if (!fakepatch) fakepatch = FakePatch(); InitHit(&hit, fakepatch, NULL, &p, &fakepatch->normal, mat, 0.); fprintf(out, "m %s =\n", mat->name); fprintf(out, "sides %d\n", mat->sided ? 1 : 2); if (mat->edf) DiffuseColorDumpMGF(out, EdfDiffuseEmittance(mat->edf, &hit), "ed"); if (mat->bsdf) DiffuseColorDumpMGF(out, BsdfDiffuseReflectance(mat->bsdf, &hit, &fakepatch->normal), "rd"); } static void VertexDumpMGF(FILE *out, VERTEX *v) { fprintf(out, "v v%d =\np %g %g %g\n", ++vcount, v->point->x, v->point->y, v->point->z); } static void PatchDumpMGF(FILE *out, PATCH *patch) { int vcbase = vcount; VertexDumpMGF(out, patch->vertex[0]); VertexDumpMGF(out, patch->vertex[1]); VertexDumpMGF(out, patch->vertex[2]); if (patch->nrvertices > 3) { VertexDumpMGF(out, patch->vertex[3]); fprintf(out, "f v%d v%d v%d v%d\n", vcbase+1, vcbase+2, vcbase+3, vcbase+4); } else fprintf(out, "f v%d v%d v%d\n", vcbase+1, vcbase+2, vcbase+3); } static void PrimitiveDumpMGF(FILE *out, PATCHLIST *patches) { if (patches) { MATERIAL *mat = patches->patch->surface->material; if (mat != lastmat) { /* write out material of first patch (subsequent patches have same material) */ MaterialDumpMGF(out, patches->patch->surface->material); lastmat = mat; } ForAllPatches(patch, patches) { if (!IGNORE_PATCH(patch)) PatchDumpMGF(out, patch); } EndForAll; } } static void GeomDumpMGF(FILE *out, GEOM *geom) { if (GeomIsAggregate(geom)) GeomListDumpMGF(out, GeomPrimList(geom)); else PrimitiveDumpMGF(out, GeomPatchList(geom)); } static void GeomListDumpMGF(FILE *out, GEOMLIST *gl) { ForAllGeoms(geom, gl) { GeomDumpMGF(out, geom); } EndForAll; } static void DumpMGF(char *fname) { int ispipe; FILE *fp = OpenFile(fname, "w", &ispipe); if (!fp) { Error("DumpMGF", "Can't open file %s for writing.", fname); return; } fprintf(stderr, "Dumping MGF model in '%s' ... ", fname); vcount=0; lastmat=(MATERIAL *)NULL; GeomListDumpMGF(fp, World); CloseFile(fp, ispipe); fprintf(stderr, "done.\n"); } static void DumpMGFCallback(Widget w, XtPointer client_data, XtPointer call_data) { CanvasPushMode(CANVASMODE_WORKING); DumpMGF("dumped.mgf.gz"); CanvasPullMode(); } #endif /*DUMP_MGF*/ #define CULL_DUPLICATE_PATCHES #ifdef CULL_DUPLICATE_PATCHES #define VECTORCOMPARE(v1, v2) \ ( (v1.x < v2.x - EPSILON) ? -1 : \ ( (v1.x > v2.x + EPSILON) ? +1 : \ ( (v1.y < v2.y - EPSILON) ? -1 : \ ( (v1.y > v2.y + EPSILON) ? +1 : \ ( (v1.z < v2.z - EPSILON) ? -1 : \ ( (v1.z > v2.z + EPSILON) ? +1 : 0 )))))) static int SpectrumCompare(SPECTRUM s1, SPECTRUM s2) { InitChannels2(s1, _s1, s2, _s2); if (*_s1 < *_s2 - EPSILON) return -1; if (*_s1 > *_s2 + EPSILON) return +1; _s1++; _s2++; if (*_s1 < *_s2 - EPSILON) return -1; if (*_s1 > *_s2 + EPSILON) return +1; _s1++; _s2++; if (*_s1 < *_s2 - EPSILON) return -1; if (*_s1 > *_s2 + EPSILON) return +1; _s1++; _s2++; return 0; } #define COLORCOMPARE(c1, c2) SpectrumCompare((c1).spec, (c2).spec) #define EPS2 1e-4 static int CompareHitsNormals(HITREC *hit1, HITREC *hit2) { int code=0; if (hit1->dist < hit2->dist-EPS2) code = -1; else if (hit1->dist > hit2->dist+EPS2) code = +1; else { /* coincident hitpoints, compare normals of hit patches */ code = VECTORCOMPARE(hit1->patch->normal, hit2->patch->normal); } return code; } static void PrintCoincidingHits(FILE *out, HITLIST *start, HITLIST *end) { HITLIST *h; for (h=start; h!=end; h=h->next) { HITREC *hit = h->hit; fprintf(stderr, "patch %d (area %g) (u,v) = (%f,%f), ", hit->patch->id, hit->patch->area, hit->uv.u, hit->uv.v); } } static void DoCullDuplicates(HITLIST *start, HITLIST *end) { /* find largest patch hit between 'start' and 'hit' in sorted hitlist */ HITLIST *h, *largest; float maxarea; if (end == start->next) { /* single hit -> no or no complete overlap with other patches */ PATCH_SET_HAS_NO_OVERLAP(start->hit->patch); return; } /* find patch with largest area at the considered hit point */ maxarea = 0.; largest = NULL; for (h=start; h!=end; h=h->next) { HITREC *hit = h->hit; if (Monitored(hit->patch)) { fprintf(stderr, "\nPatch %d hit: span = ", hit->patch->id); PrintCoincidingHits(stderr, start, end); } if (!(hit->flags & HIT_UV)) PatchUV(hit->patch, &hit->point, &hit->uv.u, &hit->uv.v); if (hit->uv.u < 0.01 || hit->uv.u > 0.99 || hit->uv.v < 0.01 || hit->uv.v > 0.99) return; /* hit too close to border */ if (hit->patch->area > maxarea*(1.+EPSILON) || /* also compare ids in order to always get same result * for patches of equal area */ (largest && hit->patch->area > maxarea*(1.-EPSILON) && hit->patch->area < maxarea*(1.+EPSILON) && hit->patch->id < largest->hit->patch->id)) { maxarea = hit->patch->area; largest = h; } } PATCH_SET_IS_LARGEST(largest->hit->patch); if (PATCH_HAS_OVERLAP(largest->hit->patch)) { /* largest has overlap with an even larger patch, so there is no * full overlap with a single other patch */ PATCH_SET_HAS_NO_OVERLAP(largest->hit->patch); } else { /* mark all except largest as having overlap with the largest */ for (h=start; h!=end; h=h->next) { if (h == largest) continue; if (PATCH_HAS_NO_OVERLAP(h->hit->patch)) { /* patch contains hits not on 'largest' */ } else if (PATCH_HAS_OVERLAP(h->hit->patch)) { /* check if there was overlap with an other patch than 'largest' * before. If so, the overlap is not completely with 'largest' * and we will prefer to keep this patch. */ PATCH *prevovlp = (PATCH *)(h->hit->patch->radiance_data); if (prevovlp != largest->hit->patch) { PATCH_SET_HAS_NO_OVERLAP(h->hit->patch); fprintf(stderr, "o"); RenderSetColor(&Yellow); RenderPoint(&h->hit->point); } } else if (PATCH_IS_LARGEST(h->hit->patch)) { /* patch was the largest one in a collection of coinciding hits * before, so that must have been without overlap with the * current hit. */ PATCH_SET_HAS_NO_OVERLAP(h->hit->patch); fprintf(stderr, "x"); RenderSetColor(&Red); RenderPoint(&h->hit->point); } else { /* new overlap found */ PATCH_SET_HAS_OVERLAP(h->hit->patch); h->hit->patch->radiance_data = largest->hit->patch; fprintf(stderr, "."); RenderSetColor(&Blue); RenderPoint(&h->hit->point); } } } } static void CullDuplicatePatches(HITLIST *hits) { HITLIST *start = NULL, *hit; for (hit=hits; hit; hit=hit->next) { if (hit->hit->patch->omit < 127) hit->hit->patch->omit ++; /* just to indicate we had a hit there */ if (!start) start=hit; else if (CompareHitsNormals(start->hit, hit->hit) != 0) { DoCullDuplicates(start, hit); start = hit; } } } static int interrupt_culling; static void InterruptCullDuplicatePatchesCallback(Widget w, XtPointer client_data, XtPointer call_data) { interrupt_culling = TRUE; } #include "globallines.h" static void CullDuplicatePatchesCallback(Widget w, XtPointer client_data, XtPointer call_data) { int n = 0, patches_left, nrpatches; patches_left = 0; ForAllPatches(P, Patches) { P->omit = 0; /* misuse of field!! */ patches_left ++; } EndForAll; nrpatches = patches_left; interrupt_culling = FALSE; InitGlobalLines(NULL, CompareHitsNormals, CullDuplicatePatches); CanvasPushMode(CANVASMODE_WORKING); while (/*patches_left > 0 &&*/ !interrupt_culling) { float area_left, totalarea; int i, nrlines = nrpatches * 10; for (i=0; iomit == 0) { patches_left++ ; area_left += P->area; } totalarea += P->area; if (PATCH_HAS_OVERLAP(P) && !PATCH_HAS_NO_OVERLAP(P) && P->omit > 2) { /* more than 2 rays decide !! */ PATCH_SET_IGNORE(P); } else { PATCH_SET_DONT_IGNORE(P); } } EndForAll; fprintf(stderr, "\n%d patches without hits out of %d (%g%% area)\n", patches_left, nrpatches, area_left/totalarea); DumpMGF("culled.mgf.gz"); } CanvasPullMode(); } #endif /*CULL_DUPLICATE_PATCHES*/ #define DUMP_PATCHES_AT_PIXEL #ifdef DUMP_PATCHES_AT_PIXEL #include "hitlist.h" static void DumpPatchesAtPixel(PATCH *P, POINT *p) { RAY ray; HITLIST *hits; HITREC *prev; ray.pos = Camera.eyep; VECTORSUBTRACT(*p, ray.pos, ray.dir); VECTORNORMALIZE(ray.dir); hits = AllGridIntersections((HITLIST*)NULL, WorldGrid, &ray, -EPSILON, HUGE, HIT_FRONT|HIT_BACK|HIT_PATCH|HIT_POINT); hits = HitListSort(hits, CompareHitsNormals); prev = NULL; ForAllHits(hit, hits) { if (prev && CompareHitsNormals(hit, prev) == 0) { fprintf(stderr, "Coinciding: "); RenderSetColor(hit->flags&HIT_BACK ? &Turquoise : &Red); RenderPatchOutline(prev->patch); } else RenderSetColor(hit->flags&HIT_BACK ? &Magenta : &Green); PrintHit(stderr, hit); RenderPatchOutline(hit->patch); prev = hit; } EndForAll; RenderFinish(); DestroyHitlist(hits); } static void DumpPatchesAtPixelCallback(Widget w, XtPointer client_data, XtPointer call_data) { fprintf(stderr, "Select a point ... "); fflush(stderr); SelectPatchSetCallback(DumpPatchesAtPixel); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif #define TEST_GET_RADIANCE #ifdef TEST_GET_RADIANCE static void TestGetRadianceAtPoint(PATCH *patch, POINT *point) { double u, v; VECTOR dir; COLOR rad; PatchUV(patch, point, &u, &v); VECTORSUBTRACT(Camera.eyep, *point, dir); VECTORNORMALIZE(dir); fprintf(stderr, "Querying radiance at Point "); VectorPrint(stderr, *point); fprintf(stderr, " into direction to eye "); VectorPrint(stderr, dir); fprintf(stderr, "\n"); rad = Radiance->GetRadiance(patch, u, v, dir); fprintf(stderr, "Result = "); ColorPrint(stderr, rad); fprintf(stderr, ", luminosity = %g\n", ColorLuminance(rad) * M_PI); } static void TestGetRadianceCallback(Widget w, XtPointer client_data, XtPointer call_data) { if (!Radiance || !Radiance->GetRadiance) { fprintf(stderr, "No radiance method active, or active radiance method does not have a GetRadiance query routine"); return; } fprintf(stderr, "Select a point ... "); fflush(stderr); SelectPatchSetCallback(TestGetRadianceAtPoint); CanvasPushMode(CANVASMODE_SELECT_PATCH); } #endif void CreateDebugMenu(Widget menuBar) { Widget debugMenu; debugMenu = CreateSubMenu(menuBar, "debugButton", "debugMenu"); CreateMoreButton(menuBar); CreatePushButton(debugMenu, "Path Debug Panel", ShowPathDebugPanel, (XtPointer)NULL); CreatePushButton(debugMenu, "Dump Pooled Memory Breakdown", DumpMemoryBreakdownCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Dump World", DumpWorldCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Dump Clusters", DumpClustersCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Dump Patch", DumpPatchCallback, (XtPointer)NULL); CreateCascadeDialog(debugMenu, "Locate Patch", CreateLocatePatchDialog, "locatePatchDialog", NULL, NULL); CreatePushButton(debugMenu, "Start monitoring patch", StartMonitoringPatchCallback, (XtPointer)NULL); CreateCascadeDialog(debugMenu, "Start Monitoring Patch w/ ID", CreateMonitorPatchDialog, "locatePatchDialog", NULL, NULL); CreatePushButton(debugMenu, "Stop monitoring patch", StopMonitoringPatchCallback, (XtPointer)NULL); #ifdef RECORD_MONITORED CreatePushButton(debugMenu, "Close patch monitor files", ClosePatchMonitorFilesCallback, (XtPointer)NULL); #endif #ifdef TEST_SUBDIVISION CreatePushButton(debugMenu, "Test Element Subdivision", TestRegularElementSubdivisionCallback, (XtPointer)NULL); #endif #ifdef TEST_UNIFORM_MAPPING CreatePushButton(debugMenu, "Test Uniform Mapping", TestUniformMappingCallback, (XtPointer)NULL); #endif /*TEST_UNIFORM_MAPPING*/ #ifdef TEST_ID_RENDERING CreatePushButton(debugMenu, "Test ID rendering", TestIdRenderingCallback, (XtPointer)NULL); #endif #ifdef TEST_POTENTIAL CreatePushButton(debugMenu, "Test Direct Potential", TestPotentialCallback, (XtPointer)NULL); #endif #ifdef TEST_SHAFTCULLING CreatePushButton(debugMenu, "Select Polygon-To-Polygon Shaft", SelectPtPShaftCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Select Box-To-Box Shaft", SelectBtBShaftCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Show Shaft", ShowShaftCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Show Shaft Contents", ShowShaftContentsCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Test Patch Against Shaft", TestShaftCullTestPatchCallback, (XtPointer)NULL); #ifdef TESTSHAFTFORMFACTOR CreatePushButton(debugMenu, "Test Shaft Form Factor", TestShaftFormFactorCallback, (XtPointer)NULL); #endif #endif #ifdef TESTFORMFACTOR CreatePushButton(debugMenu, "Test Form Factor", TestFormFactorCallback, (XtPointer)NULL); #endif #ifdef TEST_BREP CreatePushButton(debugMenu, "Test Patch Neighbours", TestNeighboursCallback, (XtPointer)NULL); #endif #ifdef DUMP_GALERKIN_MATRIX CreatePushButton(debugMenu, "Dump Form Factor Matrix", DumpMatrixCallback, (XtPointer)NULL); #endif /*DUMP_GALERKIN_MATRIX*/ #ifdef EXAMINE_ELEMENT_HIERARCHY CreatePushButton(debugMenu, "Start Examine Element Hierarchy", StartExamineElementHierarchy, (XtPointer)NULL); CreatePushButton(debugMenu, "Examine Element Hierarchy Up", ExamineElementHierarchyUp, (XtPointer)NULL); CreatePushButton(debugMenu, "Examine Element Hierarchy Down", ExamineElementHierarchyDown, (XtPointer)NULL); #endif /*EXAMINE_ELEMENT_HIERARCHY*/ #ifdef TEST_SGL CreatePushButton(debugMenu, "Test SGL", TestSGLCallback, (XtPointer)NULL); #endif /*TEST_SGL*/ #ifdef DUMP_REFL CreatePushButton(debugMenu, "Dump Diffuse Reflectivities", DumpReflectivities, (XtPointer)NULL); #endif /*DUMP_REFL*/ #ifdef TEST_RAYTRACING CreatePushButton(debugMenu, "Draw Virtual Screen", DrawVirtualScreen, (XtPointer)NULL); #endif #ifdef TEST_RAYINTERSECT CreatePushButton(debugMenu, "Test Ray-World Intersection", TestRayIntersect, (XtPointer)NULL); #endif /*TEST_RAYINTERSECT*/ #ifdef TEST_LIGHTMETERING CreatePushButton(debugMenu, "Test Light Metering", TestLightMetering, (XtPointer)NULL); #endif /*TEST_LIGHTMETERING*/ #ifdef TEST_GLOBAL_LINE CreatePushButton(debugMenu, "Test Global Line Tracing", TestGlobalLineCallback, (XtPointer)NULL); #endif /*TEST_GLOBAL_LINE*/ #ifdef RAYTRACING_TEST CreateRayTracingTestMenu(debugMenu); CreatePushButton(debugMenu, "Ray Tracing Confidence Test", TestRayTracingCallback, (XtPointer)NULL); #endif /*RAYTRACING_TEST*/ #ifdef SHOW_NORMALS CreatePushButton(debugMenu, "Show Vertex Normals", ShowNormalsCallback, (XtPointer)NULL); #endif /*SHOW_NORMALS*/ #ifdef TEST_BSDF_SAMPLING CreatePushButton(debugMenu, "Test BSDF sampling", TestBsdfSampling, (XtPointer)NULL); CreatePushButton(debugMenu, "Show Shading Frame At Point", ShowShadingFrameCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Print Albedoes at Point", PrintAlbedoesCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Test Path Tracing Hack at Point", TestHackPathCallback, (XtPointer)NULL); #endif /*TEST_BSDF_SAMPLING*/ #ifdef TEST_PHOTONMAP CreatePushButton(debugMenu, "Test Photonmap", TestPhotonmapReconstruction, (XtPointer)NULL); #endif #ifdef TEST_EDF_SAMPLING CreatePushButton(debugMenu, "Test EDF sampling", TestEdfSampling, (XtPointer)NULL); CreatePushButton(debugMenu, "Test EDF evaluation", TestEdfEval, (XtPointer)NULL); #endif /*TEST_EDF_SAMPLING*/ #ifdef PRINT_MATERIAL CreatePushButton(debugMenu, "Print Material", PrintMaterialCallback, (XtPointer)NULL); #endif /*PRINT_MATERIAL*/ #ifdef TEST_PATH CreatePushButton(debugMenu, "Test Random Walk", TestPathCallback, (XtPointer)NULL); #endif /*TEST_PATH*/ #ifdef TEST_RTSPIXEL CreatePushButton(debugMenu, "Debug RTS Trace Pixel", TraceDebugPixelCallback, (XtPointer)NULL); #endif /*TEST_RTSPIXEL*/ #ifdef SAVEDEPTH CreatePushButton(debugMenu, "Save Depth", SaveDepthCallback, (XtPointer)NULL); #endif /*SAVEDEPTH*/ #ifdef DUMPS CreateCascadeDialog(debugMenu, "Dump Configuration", CreateDumpConfigureDialog, "configDumpDialog", NULL, NULL); CreateCascadeDialog(debugMenu, "Read Radiance/False Color Dump", CreateReadDumpDialog, "readDumpDialog", NULL, NULL); #endif #ifdef MCR_DUMP_LEAF CreatePushButton(debugMenu, "Dump Leaf Element At Point", McrDumpLeafCallback, (XtPointer)NULL); #endif #ifdef DUMP_MGF CreatePushButton(debugMenu, "Dump MGF model", DumpMGFCallback, (XtPointer)NULL); #endif /*DUMP_MGF*/ #ifdef CULL_DUPLICATE_PATCHES CreatePushButton(debugMenu, "Cull duplicate patches", CullDuplicatePatchesCallback, (XtPointer)NULL); CreatePushButton(debugMenu, "Interrupt Culling", InterruptCullDuplicatePatchesCallback, (XtPointer)NULL); #endif /*CULL_DUPLICATE_PATCHES*/ #ifdef DUMP_PATCHES_AT_PIXEL CreatePushButton(debugMenu, "Dump Patches At Pixel", DumpPatchesAtPixelCallback, (XtPointer)NULL); #endif #ifdef TEST_GET_RADIANCE CreatePushButton(debugMenu, "Get Radiance At Point", TestGetRadianceCallback, (XtPointer)NULL); #endif #ifdef PIXEL_RADIANCE CreatePushButton(debugMenu, "Get Radiance At Pixel (RT)", GetPixelRadianceCallback, (XtPointer)NULL); #endif /* PIXEL_RADIANCE */ }