summaryrefslogtreecommitdiffhomepage
path: root/Opcode/OPC_PlanesAABBOverlap.h
blob: 80b8bcef71a8b4253ca33537c9da7580efcc7455 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Planes-AABB overlap test.
 *	- original code by Ville Miettinen, from Umbra/dPVS (released on the GD-Algorithms mailing list)
 *	- almost used "as-is", I even left the comments (hence the frustum-related notes)
 *
 *	\param		center			[in] box center
 *	\param		extents			[in] box extents
 *	\param		out_clip_mask	[out] bitmask for active planes
 *	\param		in_clip_mask	[in] bitmask for active planes
 *	\return		TRUE if boxes overlap planes
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL PlanesCollider::PlanesAABBOverlap(const IcePoint& center, const IcePoint& extents, udword& out_clip_mask, udword in_clip_mask)
{
	// Stats
	mNbVolumeBVTests++;

	const Plane* p = mPlanes;

	// Evaluate through all active frustum planes. We determine the relation 
	// between the AABB and a plane by using the concept of "near" and "far"
	// vertices originally described by Zhang (and later by Möller). Our
	// variant here uses 3 fabs ops, 6 muls, 7 adds and two floating IcePoint
	// comparisons per plane. The routine early-exits if the AABB is found
	// to be outside any of the planes. The loop also constructs a new output
	// clip mask. Most FPUs have a native single-cycle fabsf() operation.

	udword Mask				= 1;			// current mask index (1,2,4,8,..)
	udword TmpOutClipMask	= 0;			// initialize output clip mask into empty. 

	while(Mask<=in_clip_mask)				// keep looping while we have active planes left...
	{
		if(in_clip_mask & Mask)				// if clip plane is active, process it..
		{               
			float NP = extents.x*fabsf(p->n.x) + extents.y*fabsf(p->n.y) + extents.z*fabsf(p->n.z);	// ### fabsf could be precomputed
			float MP = center.x*p->n.x + center.y*p->n.y + center.z*p->n.z + p->d;

			if(NP < MP)						// near vertex behind the clip plane... 
				return FALSE;				// .. so there is no intersection..
			if((-NP) < MP)					// near and far vertices on different sides of plane..
				TmpOutClipMask |= Mask;		// .. so update the clip mask...
		}
		Mask+=Mask;							// mk = (1<<plane)
		p++;								// advance to next plane
	}

	out_clip_mask = TmpOutClipMask;			// copy output value (temp used to resolve aliasing!)
	return TRUE;							// indicate that AABB intersects frustum
}