/* fix.c: routines to fix vertex orientation, ... */ #include "fix.h" #include "render.h" #include "camera.h" #include "scene.h" #include "canvas.h" #include "patch.h" #include "pools.h" #include "error.h" static void BuildIdToPatchTable(PATCH *patch, PATCH **id2patch) { id2patch[patch->id] = patch; } /* reverse vertex order, normal and plane constant */ static void PatchReverseVertexOrder(PATCH *patch) { VERTEX *vtmp = patch->vertex[2]; patch->vertex[2] = patch->vertex[0]; patch->vertex[0] = vtmp; VECTORSCALE(-1, patch->normal, patch->normal); patch->plane_constant = -patch->plane_constant; } /* Fixes the vertex order and normal direction for all patches visible in the * current view. */ void FixVertexOrderInView(void) { PATCH **id2patch, *lastpatch; unsigned long *ids, *id; long i, x, y, nrpixels, maxpatchid, lostpixels; int backface_culling; if (!Patches) return; /* switch off backface culling */ backface_culling = renderopts.backface_culling; renderopts.backface_culling = FALSE; CanvasPushMode(CANVASMODE_RENDER); /* get the patch IDs for each pixel. */ ids = RenderIds(&x, &y); CanvasPullMode(); CanvasPushMode(CANVASMODE_WORKING); /* switch backface culling back on if it was on */ renderopts.backface_culling = backface_culling; 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((int)(maxpatchid+1) * sizeof(PATCH *)); for (i=0; i<=maxpatchid; i++) id2patch[i] = (PATCH *)NULL; PatchListIterate1A(Patches, BuildIdToPatchTable, (void *)id2patch); lastpatch = (PATCH *)NULL; for (i=0, id=ids; i < nrpixels; i++, id++) { unsigned long the_id = (*id)&0xffffff; PATCH *patch = (the_id <= maxpatchid) ? id2patch[the_id] : (PATCH *)NULL; if (patch && patch != lastpatch) /* reverse vertex order, normal and plane constant if the eye point is behind the * plane of the patch (which is visible) */ if (VECTORDOTPRODUCT(patch->normal, Camera.eyep) + patch->plane_constant < EPSILON) PatchReverseVertexOrder(patch); lastpatch = patch; } if (lostpixels > 0) Warning(NULL, "%d lost pixels", lostpixels); Free((char *)id2patch, (int)(maxpatchid+1) * sizeof(PATCH *)); Free((char *)ids, (int)nrpixels * sizeof(unsigned long)); CanvasPullMode(); }