⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpcube.c

📁 [Game.Programming].Academic - Graphics Gems (6 books source code)
💻 C
字号:
/* *                  FAST POLYGON-CUBE INTERSECTION TESTS *                  by Daniel Green *                  January 1994 * * * The original inspiration for this routine comes from the triangle-cube * intersection algorithm in Graphics Gems III by Douglas Voorhies. * Aside from the fact that the original code was special-cased for triangles * only, it suffered from some bugs.  Don Hatch re-wrote the non-trivial tests * using the same basic ideas, fixed the bugs and also made it more * general and efficient.  Don's implementation performs just the * intersection calculations without any trivial accept or reject tests, * and is embodied in the routine polygon_intersects_cube(). * * The function implemented here is simply a wrapper that begins with a * slightly more efficient version of Voorhies' original trivial reject tests * and only calls polygon_intersects_cube() when those tests fail. * The result is a fast and robust polygon-cube tester. * * Also included here is trivial_vertex_tests() which is used by * fast_polygon_intersects_cube().  It can be used to quickly test an entire * set of vertices for trivial reject or accept.  This is useful for testing * polyhedra or polygon meshes. * * WARNING: When used to test intersection of a polyhedron with the unit cube, * remember that these routines only test *surfaces* and not volumes. * If polygon_intersects_cube() reports no intersection with any of the faces * of the polyhedron, the caller should be aware that the polyhedron * could still contain the whole unit cube which would then need to be checked * with a point-within-polyhedron test.  The origin would be a natural point * to check in such a test. */#include "pcube.h"#ifndef __cplusplus#define inline#endif#define TEST_AGAINST_PARALLEL_PLANES(posbit, negbit, value, limit)	\	if (mask & (posbit|negbit)) {					\		register real temp = value;				\		if ((mask & posbit) && temp > limit)			\			outcode |= posbit;				\		else if ((mask & negbit) && temp < -limit)		\			outcode |= negbit;				\	}								\/* * Tells which of the six face-planes the given point is outside of. * Only tests faces not represented in "mask". */static inline unsigned longface_plane(const real p[3], unsigned long mask){	register unsigned long outcode = 0L;	TEST_AGAINST_PARALLEL_PLANES(0x001, 0x002, p[0], 0.5)	TEST_AGAINST_PARALLEL_PLANES(0x004, 0x008, p[1], 0.5)	TEST_AGAINST_PARALLEL_PLANES(0x010, 0x020, p[2], 0.5)	return(outcode);}/* * Tells which of the twelve edge planes the given point is outside of. * Only tests faces not represented in "mask". */static inline unsigned longbevel_2d(const real p[3], unsigned long mask){	register unsigned long outcode = 0L;	TEST_AGAINST_PARALLEL_PLANES(0x001, 0x002, p[0] + p[1], 1.0)	TEST_AGAINST_PARALLEL_PLANES(0x004, 0x008, p[0] - p[1], 1.0)	TEST_AGAINST_PARALLEL_PLANES(0x010, 0x020, p[0] + p[2], 1.0)	TEST_AGAINST_PARALLEL_PLANES(0x040, 0x080, p[0] - p[2], 1.0)	TEST_AGAINST_PARALLEL_PLANES(0x100, 0x200, p[1] + p[2], 1.0)	TEST_AGAINST_PARALLEL_PLANES(0x400, 0x800, p[1] - p[2], 1.0)	return(outcode);}/* * Tells which of the eight corner planes the given point is outside of. * Only tests faces not represented in "mask". */static inline unsigned longbevel_3d(const real p[3], unsigned long mask){	register unsigned long outcode = 0L;	TEST_AGAINST_PARALLEL_PLANES(0x001, 0x002, p[0] + p[1] + p[2], 1.5)	TEST_AGAINST_PARALLEL_PLANES(0x004, 0x008, p[0] + p[1] - p[2], 1.5)	TEST_AGAINST_PARALLEL_PLANES(0x010, 0x020, p[0] - p[1] + p[2], 1.5)	TEST_AGAINST_PARALLEL_PLANES(0x040, 0x080, p[0] - p[1] - p[2], 1.5)	return(outcode);}/* * Returns 1 if any of the vertices are inside the cube of edge length 1 * centered at the origin (trivial accept), 0 if all vertices are outside * of any testing plane (trivial reject), -1 otherwise (couldn't help). */extern inttrivial_vertex_tests(int nverts, const real verts[][3],			int already_know_verts_are_outside_cube){	register unsigned long cum_and;  /* cumulative logical ANDs */	register int i;	/*	 * Compare the vertices with all six face-planes.	 * If it's known that no vertices are inside the unit cube	 * we can exit the loop early if we run out of bounding	 * planes that all vertices might be outside of.  That simply means	 * that this test failed and we can go on to the next one.	 * If we must test for vertices within the cube, the loop is slightly	 * different in that we can trivially accept if we ever do find a	 * vertex within the cube, but we can't break the loop early if we run	 * out of planes to reject against because subsequent vertices might	 * still be within the cube.	 */	cum_and = ~0L;  /* Set to all "1" bits */	if(already_know_verts_are_outside_cube) {		for(i=0; i<nverts; i++)			if(0L == (cum_and = face_plane(verts[i], cum_and)))				break; /* No planes left to trivially reject */	}	else {		for(i=0; i<nverts; i++) {			/* Note the ~0L mask below to always test all planes */			unsigned long face_bits = face_plane(verts[i], ~0L);			if(0L == face_bits)  /* vertex is inside the cube */				return 1; /* trivial accept */			cum_and &= face_bits;		}	}	if(cum_and != 0L)  /* All vertices outside some face plane. */		return 0;  /* Trivial reject */	/*	 * Now do the just the trivial reject test against the 12 edge planes.	 */	cum_and = ~0L;  /* Set to all "1" bits */	for(i=0; i<nverts; i++)		if(0L == (cum_and = bevel_2d(verts[i], cum_and)))			break; /* No planes left that might trivially reject */	if(cum_and != 0L)  /* All vertices outside some edge plane. */		return 0;  /* Trivial reject */	/*	 * Now do the trivial reject test against the 8 corner planes.	 */	cum_and = ~0L;  /* Set to all "1" bits */	for(i=0; i<nverts; i++)		if(0L == (cum_and = bevel_3d(verts[i], cum_and)))			break; /* No planes left that might trivially reject */	if(cum_and != 0L)  /* All vertices outside some corner plane. */		return 0;  /* Trivial reject */	/*	 * By now we know that the polygon is not to the outside of any of the	 * test planes and can't be trivially accepted *or* rejected.	 */	return -1;}/* * This is a version of the same polygon-cube intersection that first calls * trivial_vertex_tests() to hopefully skip the more expensive definitive test. * It simply calls polygon_intersects_cube() when that fails. * Note that after the trivial tests we at least know that all vertices are * outside the cube and can therefore pass a true flag to * polygon_intersects_cube(). */extern intfast_polygon_intersects_cube(int nverts, const real verts[][3],                        const real polynormal[3],			int already_know_verts_are_outside_cube,			int already_know_edges_are_outside_cube){	int quick_test = trivial_vertex_tests(nverts, verts,				already_know_verts_are_outside_cube);	if(-1 == quick_test)		return polygon_intersects_cube(nverts, verts, polynormal, 1,				already_know_edges_are_outside_cube);	else		return quick_test;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -