1. Daniel K. O.
  2. KODE

Commits

Daniel K. O.  committed 214ab91

started OPCODE integration

  • Participants
  • Parent commits 15d1ef8
  • Branches default

Comments (0)

Files changed (103)

File configure.ac

View file
                  docs/Makefile
                  externals/Makefile
                  externals/libccd/Makefile
+                 externals/OPCODE/Makefile
+                 externals/OPCODE/Ice/Makefile
                  include/Makefile
                  include/kode/Makefile
                  include/kode/collision/Makefile

File externals/Makefile.am

View file
-SUBDIRS = libccd
+SUBDIRS = libccd OPCODE

File externals/OPCODE/COPYING

View file
+The OPCODE library distributed as part of ODE is licensed under
+the same terms as ODE (LGPLv2.1+ and BSD).
+
+Quoting a public e-mail from the author:
+
+    Re: TriMesh support and OPCODE added to ODE core
+    Pierre Terdiman <p.terdiman <at> wanadoo.fr>
+    2003-07-01 21:18:44 GMT
+
+    > If he wants
+    > to explicitly make it clear that OpCode is good under ODE's
+    > license, that would be A-1 Super...
+
+    "Opcode is good under ODE's license"
+
+    I didn't put a license to prevent boring questions about licenses, but it
+    seems it's not enough - I still get as many questions, regarding missing
+    license.
+
+    The only thing that would NOT be good would be renaming it "TopCode",
+    changing the author's name, selling it at a very expensive price, and still
+    managing to make money out of it :)
+
+    ...I should add a license explicitely against this :)
+
+    Pierre
+
+Source:
+    http://permalink.gmane.org/gmane.comp.lib.ode/3237
+

File externals/OPCODE/Ice/IceAABB.cpp

View file
+/**
+ *	Contains AABB-related code.
+ *	\file		IceAABB.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+
+/**
+ *	AABB class.
+ *	\class		AABB
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ */
+#include "Opcode.h"
+
+using namespace IceMaths;
+
+/**
+ * Computes the sum of two AABBs.
+ * \param aabb	[in] the other AABB
+ * \return Self-Reference
+ */
+AABB&
+AABB::Add(const AABB& aabb)
+{
+    // Compute new min & max values
+    Point Min;	GetMin(Min);
+    Point Tmp;	aabb.GetMin(Tmp);
+    Min.Min(Tmp);
+
+    Point Max;	GetMax(Max);
+    aabb.GetMax(Tmp);
+    Max.Max(Tmp);
+
+    // Update this
+    SetMinMax(Min, Max);
+    return *this;
+}
+
+/**
+ * Makes a cube from the AABB.
+ * \param cube [out] the cube AABB
+ * \return cube edge length
+ */
+float
+AABB::MakeCube(AABB& cube) const
+{
+    Point Ext;	GetExtents(Ext);
+    float Max = Ext.Max();
+
+    Point Cnt;
+    GetCenter(Cnt);
+    cube.SetCenterExtents(Cnt, Point(Max, Max, Max));
+    return Max;
+}
+
+/**
+ * Makes a sphere from the AABB.
+ * \param sphere [out] sphere containing the AABB
+ */
+void
+AABB::MakeSphere(Sphere& sphere) const
+{
+    GetExtents(sphere.mCenter);
+    sphere.mRadius = sphere.mCenter.Magnitude() * 1.00001f; // To make sure sphere::Contains(*this) succeeds
+    GetCenter(sphere.mCenter);
+}
+
+/**
+ * Checks a box is inside another box.
+ * \param box [in] the other AABB
+ * \return true if current box is inside input box
+ */
+bool
+AABB::IsInside(const AABB& box) const
+{
+    if (box.GetMin(0)>GetMin(0)) return false;
+    if (box.GetMin(1)>GetMin(1)) return false;
+    if (box.GetMin(2)>GetMin(2)) return false;
+    if (box.GetMax(0)<GetMax(0)) return false;
+    if (box.GetMax(1)<GetMax(1)) return false;
+    if (box.GetMax(2)<GetMax(2)) return false;
+    return true;
+}
+
+/**
+ * Computes the AABB planes.
+ * \param planes [out] 6 planes surrounding the box
+ * \return true if success
+ */
+bool
+AABB::ComputePlanes(Plane* planes)	const
+{
+    // Checkings
+    if (!planes)
+	return false;
+
+    Point Center, Extents;
+    GetCenter(Center);
+    GetExtents(Extents);
+
+    // Writes normals
+    planes[0].n = Point(1.0f, 0.0f, 0.0f);
+    planes[1].n = Point(-1.0f, 0.0f, 0.0f);
+    planes[2].n = Point(0.0f, 1.0f, 0.0f);
+    planes[3].n = Point(0.0f, -1.0f, 0.0f);
+    planes[4].n = Point(0.0f, 0.0f, 1.0f);
+    planes[5].n = Point(0.0f, 0.0f, -1.0f);
+
+    // Compute a point on each plane
+    Point p0 = Point(Center.x+Extents.x, Center.y, Center.z);
+    Point p1 = Point(Center.x-Extents.x, Center.y, Center.z);
+    Point p2 = Point(Center.x, Center.y+Extents.y, Center.z);
+    Point p3 = Point(Center.x, Center.y-Extents.y, Center.z);
+    Point p4 = Point(Center.x, Center.y, Center.z+Extents.z);
+    Point p5 = Point(Center.x, Center.y, Center.z-Extents.z);
+
+    // Compute d
+    planes[0].d = -(planes[0].n|p0);
+    planes[1].d = -(planes[1].n|p1);
+    planes[2].d = -(planes[2].n|p2);
+    planes[3].d = -(planes[3].n|p3);
+    planes[4].d = -(planes[4].n|p4);
+    planes[5].d = -(planes[5].n|p5);
+
+    return true;
+}
+
+/**
+ *	Computes the aabb points.
+ *	\param		pts	[out] 8 box points
+ *	\return		true if success
+ */
+bool
+AABB::ComputePoints(Point* pts)	const
+{
+    // Checkings
+    if(!pts)
+	return false;
+
+    // Get box corners
+    Point min;
+    GetMin(min);
+    Point max;
+    GetMax(max);
+
+    //     7+------+6			0 = ---
+    //     /|     /|			1 = +--
+    //    / |    / |			2 = ++-
+    //   / 4+---/--+5			3 = -+-
+    // 3+------+2 /    y   z	4 = --+
+    //  | /    | /     |  /		5 = +-+
+    //  |/     |/      |/		6 = +++
+    // 0+------+1      *---x	7 = -++
+
+    // Generate 8 corners of the bbox
+    pts[0] = Point(min.x, min.y, min.z);
+    pts[1] = Point(max.x, min.y, min.z);
+    pts[2] = Point(max.x, max.y, min.z);
+    pts[3] = Point(min.x, max.y, min.z);
+    pts[4] = Point(min.x, min.y, max.z);
+    pts[5] = Point(max.x, min.y, max.z);
+    pts[6] = Point(max.x, max.y, max.z);
+    pts[7] = Point(min.x, max.y, max.z);
+
+    return true;
+}
+
+/**
+ *	Gets vertex normals.
+ *	\param		pts	[out] 8 box points
+ *	\return		true if success
+ */
+const
+Point* AABB::GetVertexNormals()	const
+{
+	static const float VertexNormals[] = 
+	{
+		-INVSQRT3,	-INVSQRT3,	-INVSQRT3,
+		INVSQRT3,	-INVSQRT3,	-INVSQRT3,
+		INVSQRT3,	INVSQRT3,	-INVSQRT3,
+		-INVSQRT3,	INVSQRT3,	-INVSQRT3,
+		-INVSQRT3,	-INVSQRT3,	INVSQRT3,
+		INVSQRT3,	-INVSQRT3,	INVSQRT3,
+		INVSQRT3,	INVSQRT3,	INVSQRT3,
+		-INVSQRT3,	INVSQRT3,	INVSQRT3
+	};
+	return (const Point*)VertexNormals;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Returns edges.
+ *	\return		24 indices (12 edges) indexing the list returned by ComputePoints()
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const udword* AABB::GetEdges() const
+{
+	static const udword Indices[] = {
+	0, 1,	1, 2,	2, 3,	3, 0,
+	7, 6,	6, 5,	5, 4,	4, 7,
+	1, 5,	6, 2,
+	3, 7,	4, 0
+	};
+	return Indices;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Returns edge normals.
+ *	\return		edge normals in local space
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const Point* AABB::GetEdgeNormals() const
+{
+	static const float EdgeNormals[] = 
+	{
+		0,			-INVSQRT2,	-INVSQRT2,	// 0-1
+		INVSQRT2,	0,			-INVSQRT2,	// 1-2
+		0,			INVSQRT2,	-INVSQRT2,	// 2-3
+		-INVSQRT2,	0,			-INVSQRT2,	// 3-0
+
+		0,			INVSQRT2,	INVSQRT2,	// 7-6
+		INVSQRT2,	0,			INVSQRT2,	// 6-5
+		0,			-INVSQRT2,	INVSQRT2,	// 5-4
+		-INVSQRT2,	0,			INVSQRT2,	// 4-7
+
+		INVSQRT2,	-INVSQRT2,	0,			// 1-5
+		INVSQRT2,	INVSQRT2,	0,			// 6-2
+		-INVSQRT2,	INVSQRT2,	0,			// 3-7
+		-INVSQRT2,	-INVSQRT2,	0			// 4-0
+	};
+	return (const Point*)EdgeNormals;
+}
+
+// ===========================================================================
+//  (C) 1996-98 Vienna University of Technology
+// ===========================================================================
+//  NAME:       bboxarea
+//  TYPE:       c++ code
+//  PROJECT:    Bounding Box Area
+//  CONTENT:    Computes area of 2D projection of 3D oriented bounding box
+//  VERSION:    1.0
+// ===========================================================================
+//  AUTHORS:    ds      Dieter Schmalstieg
+//              ep      Erik Pojar
+// ===========================================================================
+//  HISTORY:
+//
+//  19-sep-99 15:23:03  ds      last modification
+//  01-dec-98 15:23:03  ep      created
+// ===========================================================================
+
+//----------------------------------------------------------------------------
+// SAMPLE CODE STARTS HERE
+//----------------------------------------------------------------------------
+
+// NOTE: This sample program requires OPEN INVENTOR!
+
+//indexlist: this table stores the 64 possible cases of classification of
+//the eyepoint with respect to the 6 defining planes of the bbox (2^6=64)
+//only 26 (3^3-1, where 1 is "inside" cube) of these cases are valid.
+//the first 6 numbers in each row are the indices of the bbox vertices that
+//form the outline of which we want to compute the area (counterclockwise
+//ordering), the 7th entry means the number of vertices in the outline.
+//there are 6 cases with a single face and and a 4-vertex outline, and
+//20 cases with 2 or 3 faces and a 6-vertex outline. a value of 0 indicates
+//an invalid case.
+
+
+// Original list was made of 7 items, I added an 8th element:
+// - to padd on a cache line
+// - to repeat the first entry to avoid modulos
+//
+// I also replaced original ints with sbytes.
+
+static const sbyte gIndexList[64][8] =
+{
+    {-1,-1,-1,-1,-1,-1,-1,   0}, // 0 inside
+    { 0, 4, 7, 3, 0,-1,-1,   4}, // 1 left
+    { 1, 2, 6, 5, 1,-1,-1,   4}, // 2 right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, // 3 -
+    { 0, 1, 5, 4, 0,-1,-1,   4}, // 4 bottom
+    { 0, 1, 5, 4, 7, 3, 0,   6}, // 5 bottom, left
+    { 0, 1, 2, 6, 5, 4, 0,   6}, // 6 bottom, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, // 7 -
+    { 2, 3, 7, 6, 2,-1,-1,   4}, // 8 top
+    { 0, 4, 7, 6, 2, 3, 0,   6}, // 9 top, left
+    { 1, 2, 3, 7, 6, 5, 1,   6}, //10 top, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //11 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //12 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //13 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //14 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //15 -
+    { 0, 3, 2, 1, 0,-1,-1,   4}, //16 front
+    { 0, 4, 7, 3, 2, 1, 0,   6}, //17 front, left
+    { 0, 3, 2, 6, 5, 1, 0,   6}, //18 front, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //19 -
+    { 0, 3, 2, 1, 5, 4, 0,   6}, //20 front, bottom
+    { 1, 5, 4, 7, 3, 2, 1,   6}, //21 front, bottom, left
+    { 0, 3, 2, 6, 5, 4, 0,   6}, //22 front, bottom, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //23 -
+    { 0, 3, 7, 6, 2, 1, 0,   6}, //24 front, top
+    { 0, 4, 7, 6, 2, 1, 0,   6}, //25 front, top, left
+    { 0, 3, 7, 6, 5, 1, 0,   6}, //26 front, top, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //27 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //28 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //29 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //30 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //31 -
+    { 4, 5, 6, 7, 4,-1,-1,   4}, //32 back
+    { 0, 4, 5, 6, 7, 3, 0,   6}, //33 back, left
+    { 1, 2, 6, 7, 4, 5, 1,   6}, //34 back, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //35 -
+    { 0, 1, 5, 6, 7, 4, 0,   6}, //36 back, bottom
+    { 0, 1, 5, 6, 7, 3, 0,   6}, //37 back, bottom, left
+    { 0, 1, 2, 6, 7, 4, 0,   6}, //38 back, bottom, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //39 -
+    { 2, 3, 7, 4, 5, 6, 2,   6}, //40 back, top
+    { 0, 4, 5, 6, 2, 3, 0,   6}, //41 back, top, left
+    { 1, 2, 3, 7, 4, 5, 1,   6}, //42 back, top, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //43 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //44 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //45 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //46 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //47 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //48 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //49 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //50 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //51 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //52 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //53 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //54 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //55 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //56 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //57 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //58 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //59 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //60 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //61 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //62 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}  //63 invalid
+};
+
+const sbyte* AABB::ComputeOutline(const Point& local_eye, sdword& num)	const
+{
+	// Get box corners
+	Point min;	GetMin(min);
+	Point max;	GetMax(max);
+
+	// Compute 6-bit code to classify eye with respect to the 6 defining planes of the bbox
+	int pos = ((local_eye.x < min.x) ?  1 : 0)	// 1 = left
+			+ ((local_eye.x > max.x) ?  2 : 0)	// 2 = right
+			+ ((local_eye.y < min.y) ?  4 : 0)	// 4 = bottom
+			+ ((local_eye.y > max.y) ?  8 : 0)	// 8 = top
+			+ ((local_eye.z < min.z) ? 16 : 0)	// 16 = front
+			+ ((local_eye.z > max.z) ? 32 : 0);	// 32 = back
+
+	// Look up number of vertices in outline
+	num = (sdword)gIndexList[pos][7];
+	// Zero indicates invalid case
+	if(!num) return null;
+
+	return &gIndexList[pos][0];
+}
+
+// calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box
+
+//const Point&		eye,		//eye point (in bbox object coordinates)
+//const AABB&			box,		//3d bbox
+//const Matrix4x4&	mat,		//free transformation for bbox
+//float width, float height, int& num)
+float AABB::ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num)	const
+{
+	const sbyte* Outline = ComputeOutline(eye, num);
+	if(!Outline)	return -1.0f;
+
+	// Compute box vertices
+	Point vertexBox[8], dst[8];
+	ComputePoints(vertexBox);
+
+	// Transform all outline corners into 2D screen space
+	for(sdword i=0;i<num;i++)
+	{
+		HPoint Projected;
+		vertexBox[Outline[i]].ProjectToScreen(width, height, mat, Projected);
+		dst[i] = Projected;
+	}
+
+	float Sum = (dst[num-1][0] - dst[0][0]) * (dst[num-1][1] + dst[0][1]);
+
+	for(int i=0; i<num-1; i++)
+		Sum += (dst[i][0] - dst[i+1][0]) * (dst[i][1] + dst[i+1][1]);
+
+	return Sum * 0.5f;	//return computed value corrected by 0.5
+}

File externals/OPCODE/Ice/IceAABB.h

View file
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains AABB-related code. (axis-aligned bounding box)
+ *	\file		IceAABB.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 13, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEAABB_H__
+#define __ICEAABB_H__
+
+	// Forward declarations
+	class Sphere;
+
+//! Declarations of type-independent methods (most of them implemented in the .cpp)
+#define AABB_COMMON_METHODS																											\
+			AABB&			Add(const AABB& aabb);																					\
+			float			MakeCube(AABB& cube)																			const;	\
+			void			MakeSphere(Sphere& sphere)																		const;	\
+			const sbyte*	ComputeOutline(const Point& local_eye, sdword& num)												const;	\
+			float			ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num)	const;	\
+			bool			IsInside(const AABB& box)																		const;	\
+			bool			ComputePlanes(Plane* planes)																	const;	\
+			bool			ComputePoints(Point* pts)																		const;	\
+			const Point*	GetVertexNormals()																				const;	\
+			const udword*	GetEdges()																						const;	\
+			const Point*	GetEdgeNormals()																				const;	\
+	inline_	BOOL			ContainsPoint(const Point& p)																	const	\
+							{																										\
+								if(p.x > GetMax(0) || p.x < GetMin(0)) return FALSE;												\
+								if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE;												\
+								if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE;												\
+								return TRUE;																						\
+							}
+
+	enum AABBType
+	{
+		AABB_RENDER			= 0,	//!< AABB used for rendering. Not visible == not rendered.
+		AABB_UPDATE			= 1,	//!< AABB used for dynamic updates. Not visible == not updated.
+
+		AABB_FORCE_DWORD	= 0x7fffffff,
+	};
+
+#ifdef USE_MINMAX
+
+	struct ICEMATHS_API ShadowAABB
+	{
+		Point	mMin;
+		Point	mMax;
+	};
+
+	class ICEMATHS_API AABB
+	{
+		public:
+		//! Constructor
+		inline_						AABB()	{}
+		//! Destructor
+		inline_						~AABB()	{}
+
+		//! Type-independent methods
+									AABB_COMMON_METHODS;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an AABB from min & max vectors.
+		 *	\param		min			[in] the min point
+		 *	\param		max			[in] the max point
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetMinMax(const Point& min, const Point& max)		{ mMin = min;		mMax = max;									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an AABB from center & extents vectors.
+		 *	\param		c			[in] the center point
+		 *	\param		e			[in] the extents vector
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetCenterExtents(const Point& c, const Point& e)	{ mMin = c - e;		mMax = c + e;								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an empty AABB.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetEmpty()											{ Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);	mMin = -p; mMax = p;}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups a point AABB.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetPoint(const Point& pt)							{ mMin = mMax = pt;												}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the size of the AABB. The size is defined as the longest extent.
+		 *	\return		the size of the AABB
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						float		GetSize()								const		{ Point e; GetExtents(e);	return e.Max();	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Extends the AABB.
+		 *	\param		p	[in] the next point
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		Extend(const Point& p)
+									{
+										if(p.x > mMax.x)	mMax.x = p.x;
+										if(p.x < mMin.x)	mMin.x = p.x;
+
+										if(p.y > mMax.y)	mMax.y = p.y;
+										if(p.y < mMin.y)	mMin.y = p.y;
+
+										if(p.z > mMax.z)	mMax.z = p.z;
+										if(p.z < mMin.z)	mMin.z = p.z;
+									}
+		// Data access
+
+		//! Get min point of the box
+		inline_			void		GetMin(Point& min)						const		{ min = mMin;								}
+		//! Get max point of the box
+		inline_			void		GetMax(Point& max)						const		{ max = mMax;								}
+
+		//! Get component of the box's min point along a given axis
+		inline_			float		GetMin(udword axis)						const		{ return mMin[axis];						}
+		//! Get component of the box's max point along a given axis
+		inline_			float		GetMax(udword axis)						const		{ return mMax[axis];						}
+
+		//! Get box center
+		inline_			void		GetCenter(Point& center)				const		{ center = (mMax + mMin)*0.5f;				}
+		//! Get box extents
+		inline_			void		GetExtents(Point& extents)				const		{ extents = (mMax - mMin)*0.5f;				}
+
+		//! Get component of the box's center along a given axis
+		inline_			float		GetCenter(udword axis)					const		{ return (mMax[axis] + mMin[axis])*0.5f;	}
+		//! Get component of the box's extents along a given axis
+		inline_			float		GetExtents(udword axis)					const		{ return (mMax[axis] - mMin[axis])*0.5f;	}
+
+		//! Get box diagonal
+		inline_			void		GetDiagonal(Point& diagonal)			const		{ diagonal = mMax - mMin;					}
+		inline_			float		GetWidth()								const		{ return mMax.x - mMin.x;					}
+		inline_			float		GetHeight()								const		{ return mMax.y - mMin.y;					}
+		inline_			float		GetDepth()								const		{ return mMax.z - mMin.z;					}
+
+		//! Volume
+		inline_			float		GetVolume()								const		{ return GetWidth() * GetHeight() * GetDepth();		}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the intersection between two AABBs.
+		 *	\param		a		[in] the other AABB
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		Intersect(const AABB& a)				const
+									{
+										if(mMax.x < a.mMin.x
+										|| a.mMax.x < mMin.x
+										|| mMax.y < a.mMin.y
+										|| a.mMax.y < mMin.y
+										|| mMax.z < a.mMin.z
+										|| a.mMax.z < mMin.z)	return FALSE;
+
+										return TRUE;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the 1D-intersection between two AABBs, on a given axis.
+		 *	\param		a		[in] the other AABB
+		 *	\param		axis	[in] the axis (0, 1, 2)
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		Intersect(const AABB& a, udword axis)	const
+									{
+										if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis])	return FALSE;
+										return TRUE;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Recomputes the AABB after an arbitrary transform by a 4x4 matrix.
+		 *	Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it)
+		 *	\param		mtx			[in] the transform matrix
+		 *	\param		aabb		[out] the transformed AABB [can be *this]
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			void		Rotate(const Matrix4x4& mtx, AABB& aabb)	const
+									{
+										// The three edges transformed: you can efficiently transform an X-only vector
+										// by just getting the "X" column of the matrix
+										Point vx,vy,vz;
+										mtx.GetRow(0, vx);	vx *= (mMax.x - mMin.x);
+										mtx.GetRow(1, vy);	vy *= (mMax.y - mMin.y);
+										mtx.GetRow(2, vz);	vz *= (mMax.z - mMin.z);
+
+										// Transform the min point
+										aabb.mMin = aabb.mMax = mMin * mtx;
+
+										// Take the transformed min & axes and find new extents
+										// Using CPU code in the right place is faster...
+										if(IS_NEGATIVE_FLOAT(vx.x))	aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x;
+										if(IS_NEGATIVE_FLOAT(vx.y))	aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y;
+										if(IS_NEGATIVE_FLOAT(vx.z))	aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z;
+										if(IS_NEGATIVE_FLOAT(vy.x))	aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x;
+										if(IS_NEGATIVE_FLOAT(vy.y))	aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y;
+										if(IS_NEGATIVE_FLOAT(vy.z))	aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z;
+										if(IS_NEGATIVE_FLOAT(vz.x))	aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x;
+										if(IS_NEGATIVE_FLOAT(vz.y))	aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y;
+										if(IS_NEGATIVE_FLOAT(vz.z))	aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the AABB is valid.
+		 *	\return		true if the box is valid
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		IsValid()	const
+									{
+										// Consistency condition for (Min, Max) boxes: min < max
+										if(mMin.x > mMax.x)	return FALSE;
+										if(mMin.y > mMax.y)	return FALSE;
+										if(mMin.z > mMax.z)	return FALSE;
+										return TRUE;
+									}
+
+		//! Operator for AABB *= float. Scales the extents, keeps same center.
+		inline_			AABB&		operator*=(float s)
+									{
+										Point Center;	GetCenter(Center);
+										Point Extents;	GetExtents(Extents);
+										SetCenterExtents(Center, Extents * s);
+										return *this;
+									}
+
+		//! Operator for AABB /= float. Scales the extents, keeps same center.
+		inline_			AABB&		operator/=(float s)
+									{
+										Point Center;	GetCenter(Center);
+										Point Extents;	GetExtents(Extents);
+										SetCenterExtents(Center, Extents / s);
+										return *this;
+									}
+
+		//! Operator for AABB += Point. Translates the box.
+		inline_			AABB&		operator+=(const Point& trans)
+									{
+										mMin+=trans;
+										mMax+=trans;
+										return *this;
+									}
+		private:
+						Point		mMin;			//!< Min point
+						Point		mMax;			//!< Max point
+	};
+
+#else
+
+	class ICEMATHS_API AABB
+	{
+		public:
+		//! Constructor
+		inline_						AABB()	{}
+		//! Destructor
+		inline_						~AABB()	{}
+
+		//! Type-independent methods
+									AABB_COMMON_METHODS;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an AABB from min & max vectors.
+		 *	\param		min			[in] the min point
+		 *	\param		max			[in] the max point
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetMinMax(const Point& min, const Point& max)		{ mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f;		}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an AABB from center & extents vectors.
+		 *	\param		c			[in] the center point
+		 *	\param		e			[in] the extents vector
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetCenterExtents(const Point& c, const Point& e)	{ mCenter = c;	 mExtents = e;									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an empty AABB.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetEmpty()											{ mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups a point AABB.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetPoint(const Point& pt)							{ mCenter = pt; mExtents.Zero();								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the size of the AABB. The size is defined as the longest extent.
+		 *	\return		the size of the AABB
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						float		GetSize()								const		{ return mExtents.Max();					}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Extends the AABB.
+		 *	\param		p	[in] the next point
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		Extend(const Point& p)
+									{
+										Point Max = mCenter + mExtents;
+										Point Min = mCenter - mExtents;
+
+										if(p.x > Max.x)	Max.x = p.x;
+										if(p.x < Min.x)	Min.x = p.x;
+
+										if(p.y > Max.y)	Max.y = p.y;
+										if(p.y < Min.y)	Min.y = p.y;
+
+										if(p.z > Max.z)	Max.z = p.z;
+										if(p.z < Min.z)	Min.z = p.z;
+
+										SetMinMax(Min, Max);
+									}
+		// Data access
+
+		//! Get min point of the box
+		inline_			void		GetMin(Point& min)						const		{ min = mCenter - mExtents;					}
+		//! Get max point of the box
+		inline_			void		GetMax(Point& max)						const		{ max = mCenter + mExtents;					}
+
+		//! Get component of the box's min point along a given axis
+		inline_			float		GetMin(udword axis)						const		{ return mCenter[axis] - mExtents[axis];	}
+		//! Get component of the box's max point along a given axis
+		inline_			float		GetMax(udword axis)						const		{ return mCenter[axis] + mExtents[axis];	}
+
+		//! Get box center
+		inline_			void		GetCenter(Point& center)				const		{ center = mCenter;							}
+		//! Get box extents
+		inline_			void		GetExtents(Point& extents)				const		{ extents = mExtents;						}
+
+		//! Get component of the box's center along a given axis
+		inline_			float		GetCenter(udword axis)					const		{ return mCenter[axis];						}
+		//! Get component of the box's extents along a given axis
+		inline_			float		GetExtents(udword axis)					const		{ return mExtents[axis];					}
+
+		//! Get box diagonal
+		inline_			void		GetDiagonal(Point& diagonal)			const		{ diagonal = mExtents * 2.0f;				}
+		inline_			float		GetWidth()								const		{ return mExtents.x * 2.0f;					}
+		inline_			float		GetHeight()								const		{ return mExtents.y * 2.0f;					}
+		inline_			float		GetDepth()								const		{ return mExtents.z * 2.0f;					}
+
+		//! Volume
+		inline_			float		GetVolume()								const		{ return mExtents.x * mExtents.y * mExtents.z * 8.0f;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the intersection between two AABBs.
+		 *	\param		a		[in] the other AABB
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		Intersect(const AABB& a)				const
+									{
+										float tx = mCenter.x - a.mCenter.x;	float ex = a.mExtents.x + mExtents.x;	if(AIR(tx) > IR(ex))	return FALSE;
+										float ty = mCenter.y - a.mCenter.y;	float ey = a.mExtents.y + mExtents.y;	if(AIR(ty) > IR(ey))	return FALSE;
+										float tz = mCenter.z - a.mCenter.z;	float ez = a.mExtents.z + mExtents.z;	if(AIR(tz) > IR(ez))	return FALSE;
+										return TRUE;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	The standard intersection method from Gamasutra. Just here to check its speed against the one above.
+		 *	\param		a		[in] the other AABB
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			bool		GomezIntersect(const AABB& a)
+									{
+										Point	T = mCenter - a.mCenter;	// Vector from A to B
+										return	((fabsf(T.x) <= (a.mExtents.x + mExtents.x))
+												&& (fabsf(T.y) <= (a.mExtents.y + mExtents.y))
+												&& (fabsf(T.z) <= (a.mExtents.z + mExtents.z)));
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the 1D-intersection between two AABBs, on a given axis.
+		 *	\param		a		[in] the other AABB
+		 *	\param		axis	[in] the axis (0, 1, 2)
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		Intersect(const AABB& a, udword axis)	const
+									{
+										float t = mCenter[axis] - a.mCenter[axis];
+										float e = a.mExtents[axis] + mExtents[axis];
+										if(AIR(t) > IR(e))	return FALSE;
+										return TRUE;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Recomputes the AABB after an arbitrary transform by a 4x4 matrix.
+		 *	\param		mtx			[in] the transform matrix
+		 *	\param		aabb		[out] the transformed AABB [can be *this]
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			void		Rotate(const Matrix4x4& mtx, AABB& aabb)	const
+									{
+										// Compute new center
+										aabb.mCenter = mCenter * mtx;
+
+										// Compute new extents. FPU code & CPU code have been interleaved for improved performance.
+										Point Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x);
+										//IR(Ex.x)&=0x7fffffff;	IR(Ex.y)&=0x7fffffff;	IR(Ex.z)&=0x7fffffff;
+										Ex.x = FR( AIR(Ex.x) );
+										Ex.y = FR( AIR(Ex.y) );
+										Ex.z = FR( AIR(Ex.z) );
+
+										Point Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y);
+										//IR(Ey.x)&=0x7fffffff;	IR(Ey.y)&=0x7fffffff;	IR(Ey.z)&=0x7fffffff;
+										Ey.x = FR( AIR(Ey.x) );
+										Ey.y = FR( AIR(Ey.y) );
+										Ey.z = FR( AIR(Ey.z) );
+
+										Point Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z);
+										//IR(Ez.x)&=0x7fffffff;	IR(Ez.y)&=0x7fffffff;	IR(Ez.z)&=0x7fffffff;
+										Ez.x = FR( AIR(Ez.x) );
+										Ez.y = FR( AIR(Ez.y) );
+										Ez.z = FR( AIR(Ez.z) );
+
+										aabb.mExtents.x = Ex.x + Ey.x + Ez.x;
+										aabb.mExtents.y = Ex.y + Ey.y + Ez.y;
+										aabb.mExtents.z = Ex.z + Ey.z + Ez.z;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the AABB is valid.
+		 *	\return		true if the box is valid
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		IsValid()	const
+									{
+										// Consistency condition for (Center, Extents) boxes: Extents >= 0
+										if(IS_NEGATIVE_FLOAT(mExtents.x))	return FALSE;
+										if(IS_NEGATIVE_FLOAT(mExtents.y))	return FALSE;
+										if(IS_NEGATIVE_FLOAT(mExtents.z))	return FALSE;
+										return TRUE;
+									}
+
+		//! Operator for AABB *= float. Scales the extents, keeps same center.
+		inline_			AABB&		operator*=(float s)		{ mExtents*=s;	return *this;	}
+
+		//! Operator for AABB /= float. Scales the extents, keeps same center.
+		inline_			AABB&		operator/=(float s)		{ mExtents/=s;	return *this;	}
+
+		//! Operator for AABB += Point. Translates the box.
+		inline_			AABB&		operator+=(const Point& trans)
+									{
+										mCenter+=trans;
+										return *this;
+									}
+		private:
+						Point		mCenter;			//!< AABB Center
+						Point		mExtents;			//!< x, y and z extents
+	};
+
+#endif
+
+	inline_ void ComputeMinMax(const Point& p, Point& min, Point& max)
+	{
+		if(p.x > max.x)	max.x = p.x;
+		if(p.x < min.x)	min.x = p.x;
+
+		if(p.y > max.y)	max.y = p.y;
+		if(p.y < min.y)	min.y = p.y;
+
+		if(p.z > max.z)	max.z = p.z;
+		if(p.z < min.z)	min.z = p.z;
+	}
+
+	inline_ void ComputeAABB(AABB& aabb, const Point* list, udword nb_pts)
+	{
+		if(list)
+		{
+			Point Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
+			Point Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT);
+			while(nb_pts--)
+			{
+//				_prefetch(list+1);	// off by one ?
+				ComputeMinMax(*list++, Mini, Maxi);
+			}
+			aabb.SetMinMax(Mini, Maxi);
+		}
+	}
+
+#endif	// __ICEAABB_H__

File externals/OPCODE/Ice/IceAxes.h

View file
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains axes definition.
+ *	\file		IceAxes.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEAXES_H__
+#define __ICEAXES_H__
+
+	enum PointComponent
+	{
+		X					= 0,
+		Y					= 1,
+		Z					= 2,
+		W					= 3,
+
+		FORCE_DWORD		= 0x7fffffff
+	};
+
+	enum AxisOrder
+	{
+		AXES_XYZ			= (X)|(Y<<2)|(Z<<4),
+		AXES_XZY			= (X)|(Z<<2)|(Y<<4),
+		AXES_YXZ			= (Y)|(X<<2)|(Z<<4),
+		AXES_YZX			= (Y)|(Z<<2)|(X<<4),
+		AXES_ZXY			= (Z)|(X<<2)|(Y<<4),
+		AXES_ZYX			= (Z)|(Y<<2)|(X<<4),
+
+		AXES_FORCE_DWORD	= 0x7fffffff
+	};
+
+	class ICEMATHS_API Axes
+	{
+		public:
+
+		inline_			Axes(AxisOrder order)
+						{
+							mAxis0 = (order   ) & 3;
+							mAxis1 = (order>>2) & 3;
+							mAxis2 = (order>>4) & 3;
+						}
+		inline_			~Axes()		{}
+
+				udword	mAxis0;
+				udword	mAxis1;
+				udword	mAxis2;
+	};
+
+#endif // __ICEAXES_H__

File externals/OPCODE/Ice/IceBoundingSphere.h

View file
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code to compute the minimal bounding sphere.
+ *	\file		IceBoundingSphere.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEBOUNDINGSPHERE_H__
+#define __ICEBOUNDINGSPHERE_H__
+
+	enum BSphereMethod
+	{
+		BS_NONE,
+		BS_GEMS,
+		BS_MINIBALL,
+
+		BS_FORCE_DWORD	= 0x7fffffff
+	};
+
+	class ICEMATHS_API Sphere
+	{
+		public:
+		//! Constructor
+		inline_					Sphere()																		{}
+		//! Constructor
+		inline_					Sphere(const Point& center, float radius) : mCenter(center), mRadius(radius)	{}
+		//! Constructor
+								Sphere(udword nb_verts, const Point* verts);
+		//! Copy constructor
+		inline_					Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius)	{}
+		//! Destructor
+		inline_					~Sphere()																		{}
+
+				BSphereMethod	Compute(udword nb_verts, const Point* verts);
+				bool			FastCompute(udword nb_verts, const Point* verts);
+
+		// Access methods
+		inline_	const Point&	GetCenter()						const		{ return mCenter; }
+		inline_	float			GetRadius()						const		{ return mRadius; }
+
+		inline_	const Point&	Center()						const		{ return mCenter; }
+		inline_	float			Radius()						const		{ return mRadius; }
+
+		inline_	Sphere&			Set(const Point& center, float radius)		{ mCenter = center; mRadius = radius; return *this; }
+		inline_	Sphere&			SetCenter(const Point& center)				{ mCenter = center; return *this; }
+		inline_	Sphere&			SetRadius(float radius)						{ mRadius = radius; return *this; }
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if a point is contained within the sphere.
+		 *	\param		p	[in] the point to test
+		 *	\return		true if inside the sphere
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	bool			Contains(const Point& p)		const
+								{
+									return mCenter.SquareDistance(p) <= mRadius*mRadius;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if a sphere is contained within the sphere.
+		 *	\param		sphere	[in] the sphere to test
+		 *	\return		true if inside the sphere
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	bool			Contains(const Sphere& sphere)	const
+								{
+									// If our radius is the smallest, we can't possibly contain the other sphere
+									if(mRadius < sphere.mRadius)	return false;
+									// So r is always positive or null now
+									float r = mRadius - sphere.mRadius;
+									return mCenter.SquareDistance(sphere.mCenter) <= r*r;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if a box is contained within the sphere.
+		 *	\param		aabb	[in] the box to test
+		 *	\return		true if inside the sphere
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_ BOOL			Contains(const AABB& aabb)	const
+								{
+									// I assume if all 8 box vertices are inside the sphere, so does the whole box.
+									// Sounds ok but maybe there's a better way?
+									float R2 = mRadius * mRadius;
+#ifdef USE_MIN_MAX
+									const Point& Max = ((ShadowAABB&)&aabb).mMax;
+									const Point& Min = ((ShadowAABB&)&aabb).mMin;
+#else
+									Point Max; aabb.GetMax(Max);
+									Point Min; aabb.GetMin(Min);
+#endif
+									Point p;
+									p.x=Max.x; p.y=Max.y; p.z=Max.z;	if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Max.x; p.y=Min.y;				if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Max.x; p.y=Max.y; p.z=Min.z;	if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Max.x; p.y=Min.y;				if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+
+									return TRUE;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if the sphere intersects another sphere
+		 *	\param		sphere	[in] the other sphere
+		 *	\return		true if spheres overlap
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	bool			Intersect(const Sphere& sphere)	const
+								{
+									float r = mRadius + sphere.mRadius;
+									return mCenter.SquareDistance(sphere.mCenter) <= r*r;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the sphere is valid.
+		 *	\return		true if the box is valid
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	BOOL			IsValid()	const
+								{
+									// Consistency condition for spheres: Radius >= 0.0f
+									if(mRadius < 0.0f)	return FALSE;
+									return TRUE;
+								}
+		public:
+				Point			mCenter;		//!< Sphere center
+				float			mRadius;		//!< Sphere radius
+	};
+
+#endif // __ICEBOUNDINGSPHERE_H__

File externals/OPCODE/Ice/IceContainer.cpp

View file
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a simple container class.
+ *	\file		IceContainer.cpp
+ *	\author		Pierre Terdiman
+ *	\date		February, 5, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a list of 32-bits values.
+ *	Use this class when you need to store an unknown number of values. The list is automatically
+ *	resized and can contains 32-bits entities (dwords or floats)
+ *
+ *	\class		Container
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ *	\date		08.15.98
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceCore;
+
+// Static members
+#ifdef CONTAINER_STATS
+udword Container::mNbContainers = 0;
+udword Container::mUsedRam = 0;
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor. No entries allocated there.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
+{
+#ifdef CONTAINER_STATS
+	mNbContainers++;
+	mUsedRam+=sizeof(Container);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor. Also allocates a given number of entries.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor)
+{
+#ifdef CONTAINER_STATS
+	mNbContainers++;
+	mUsedRam+=sizeof(Container);
+#endif
+	SetSize(size);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Copy constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
+{
+#ifdef CONTAINER_STATS
+	mNbContainers++;
+	mUsedRam+=sizeof(Container);
+#endif
+	*this = object;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.	Frees everything and leaves.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container::~Container()
+{
+	Empty();
+#ifdef CONTAINER_STATS
+	mNbContainers--;
+	mUsedRam-=GetUsedRam();
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Clears the container. All stored values are deleted, and it frees used ram.
+ *	\see		Reset()
+ *	\return		Self-Reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container& Container::Empty()
+{
+#ifdef CONTAINER_STATS
+	mUsedRam-=mMaxNbEntries*sizeof(udword);
+#endif
+	DELETEARRAY(mEntries);
+	mCurNbEntries = mMaxNbEntries = 0;
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Resizes the container.
+ *	\param		needed	[in] assume the container can be added at least "needed" values
+ *	\return		true if success.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::Resize(udword needed)
+{
+#ifdef CONTAINER_STATS
+	// Subtract previous amount of bytes
+	mUsedRam-=mMaxNbEntries*sizeof(udword);
+#endif
+
+	// Get more entries
+	mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2;	// Default nb Entries = 2
+	if(mMaxNbEntries<mCurNbEntries + needed)	mMaxNbEntries = mCurNbEntries + needed;
+
+	// Get some bytes for new entries
+	udword*	NewEntries = new udword[mMaxNbEntries];
+	CHECKALLOC(NewEntries);
+
+#ifdef CONTAINER_STATS
+	// Add current amount of bytes
+	mUsedRam+=mMaxNbEntries*sizeof(udword);
+#endif
+
+	// Copy old data if needed
+	if(mCurNbEntries)	CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
+
+	// Delete old data
+	DELETEARRAY(mEntries);
+
+	// Assign new pointer
+	mEntries = NewEntries;
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Sets the initial size of the container. If it already contains something, it's discarded.
+ *	\param		nb		[in] Number of entries
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::SetSize(udword nb)
+{
+	// Make sure it's empty
+	Empty();
+
+	// Checkings
+	if(!nb)	return false;
+
+	// Initialize for nb entries
+	mMaxNbEntries = nb;
+
+	// Get some bytes for new entries
+	mEntries = new udword[mMaxNbEntries];
+	CHECKALLOC(mEntries);
+
+#ifdef CONTAINER_STATS
+	// Add current amount of bytes
+	mUsedRam+=mMaxNbEntries*sizeof(udword);
+#endif
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the container and get rid of unused bytes.
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::Refit()
+{
+#ifdef CONTAINER_STATS
+	// Subtract previous amount of bytes
+	mUsedRam-=mMaxNbEntries*sizeof(udword);
+#endif
+
+	// Get just enough entries
+	mMaxNbEntries = mCurNbEntries;
+	if(!mMaxNbEntries)	return false;
+
+	// Get just enough bytes
+	udword*	NewEntries = new udword[mMaxNbEntries];
+	CHECKALLOC(NewEntries);
+
+#ifdef CONTAINER_STATS
+	// Add current amount of bytes
+	mUsedRam+=mMaxNbEntries*sizeof(udword);
+#endif
+
+	// Copy old data
+	CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
+
+	// Delete old data
+	DELETEARRAY(mEntries);
+
+	// Assign new pointer
+	mEntries = NewEntries;
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks whether the container already contains a given value.
+ *	\param		entry			[in] the value to look for in the container
+ *	\param		location		[out] a possible pointer to store the entry location
+ *	\see		Add(udword entry)
+ *	\see		Add(float entry)
+ *	\see		Empty()
+ *	\return		true if the value has been found in the container, else false.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::Contains(udword entry, udword* location) const
+{
+	// Look for the entry
+	for(udword i=0;i<mCurNbEntries;i++)
+	{
+		if(mEntries[i]==entry)
+		{
+			if(location)	*location = i;
+			return true;
+		}
+	}
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Deletes an entry. If the container contains such an entry, it's removed.
+ *	\param		entry		[in] the value to delete.
+ *	\return		true if the value has been found in the container, else false.
+ *	\warning	This method is arbitrary slow (O(n)) and should be used carefully. Insertion order is not preserved.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::Delete(udword entry)
+{
+	// Look for the entry
+	for(udword i=0;i<mCurNbEntries;i++)
+	{
+		if(mEntries[i]==entry)
+		{
+			// Entry has been found at index i. The strategy is to copy the last current entry at index i, and decrement the current number of entries.
+			DeleteIndex(i);
+			return true;
+		}
+	}
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Deletes an entry, preserving the insertion order. If the container contains such an entry, it's removed.
+ *	\param		entry		[in] the value to delete.
+ *	\return		true if the value has been found in the container, else false.
+ *	\warning	This method is arbitrary slow (O(n)) and should be used carefully.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::DeleteKeepingOrder(udword entry)
+{
+	// Look for the entry
+	for(udword i=0;i<mCurNbEntries;i++)
+	{
+		if(mEntries[i]==entry)
+		{
+			// Entry has been found at index i.
+			// Shift entries to preserve order. You really should use a linked list instead.
+			mCurNbEntries--;
+			for(udword j=i;j<mCurNbEntries;j++)
+			{
+				mEntries[j] = mEntries[j+1];
+			}
+			return true;
+		}
+	}
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the next entry, starting from input one.
+ *	\param		entry		[in/out] On input, the entry to look for. On output, the next entry
+ *	\param		find_mode	[in] wrap/clamp
+ *	\return		Self-Reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container& Container::FindNext(udword& entry, FindMode find_mode)
+{
+	udword Location;
+	if(Contains(entry, &Location))
+	{
+		Location++;
+		if(Location==mCurNbEntries)	Location = find_mode==FIND_WRAP ? 0 : mCurNbEntries-1;
+		entry = mEntries[Location];
+	}
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the previous entry, starting from input one.
+ *	\param		entry		[in/out] On input, the entry to look for. On output, the previous entry
+ *	\param		find_mode	[in] wrap/clamp
+ *	\return		Self-Reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container& Container::FindPrev(udword& entry, FindMode find_mode)
+{
+	udword Location;
+	if(Contains(entry, &Location))
+	{
+		Location--;
+		if(Location==0xffffffff)	Location = find_mode==FIND_WRAP ? mCurNbEntries-1 : 0;
+		entry = mEntries[Location];
+	}
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the ram used by the container.
+ *	\return		the ram used in bytes.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword Container::GetUsedRam() const
+{
+	return sizeof(Container) + mMaxNbEntries * sizeof(udword);
+}
+
+/*void Container::operator=(const Container& object)
+{
+	SetSize(object.GetNbEntries());
+	CopyMemory(mEntries, object.GetEntries(), mMaxNbEntries*sizeof(udword));
+	mCurNbEntries = mMaxNbEntries;
+}*/

File externals/OPCODE/Ice/IceContainer.h

View file
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a simple container class.
+ *	\file		IceContainer.h
+ *	\author		Pierre Terdiman
+ *	\date		February, 5, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICECONTAINER_H__
+#define __ICECONTAINER_H__
+
+	#define CONTAINER_STATS
+
+	enum FindMode
+	{
+		FIND_CLAMP,
+		FIND_WRAP,
+
+		FIND_FORCE_DWORD = 0x7fffffff
+	};
+
+	class ICECORE_API Container
+	{
+		public:
+		// Constructor / Destructor
+								Container();
+								Container(const Container& object);
+								Container(udword size, float growth_factor);
+								~Container();
+		// Management
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	A O(1) method to add a value in the container. The container is automatically resized if needed.
+		 *	The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
+		 *	costs a lot more than the call overhead...
+		 *
+		 *	\param		entry		[in] a udword to store in the container
+		 *	\see		Add(float entry)
+		 *	\see		Empty()
+		 *	\see		Contains(udword entry)
+		 *	\return		Self-Reference
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	Container&		Add(udword entry)
+								{
+									// Resize if needed
+									if(mCurNbEntries==mMaxNbEntries)	Resize();
+
+									// Add new entry
+									mEntries[mCurNbEntries++]	= entry;
+									return *this;
+								}
+
+		inline_	Container&		Add(const uword* entries, udword nb)
+								{
+									// Resize if needed
+									if(mCurNbEntries+nb>mMaxNbEntries)	Resize(nb);
+
+									// Add new entry
+									CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(uword));
+									mCurNbEntries+=nb;
+									return *this;
+								}
+
+		inline_	Container&		Add(const udword* entries, udword nb)
+								{
+									// Resize if needed
+									if(mCurNbEntries+nb>mMaxNbEntries)	Resize(nb);
+
+									// Add new entry
+									CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword));
+									mCurNbEntries+=nb;
+									return *this;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	A O(1) method to add a value in the container. The container is automatically resized if needed.
+		 *	The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
+		 *	costs a lot more than the call overhead...
+		 *
+		 *	\param		entry		[in] a float to store in the container
+		 *	\see		Add(udword entry)
+		 *	\see		Empty()
+		 *	\see		Contains(udword entry)
+		 *	\return		Self-Reference
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	Container&		Add(float entry)
+								{
+									// Resize if needed
+									if(mCurNbEntries==mMaxNbEntries)	Resize();
+
+									// Add new entry
+									mEntries[mCurNbEntries++]	= IR(entry);
+									return *this;
+								}
+
+		inline_	Container&		Add(const float* entries, udword nb)
+								{
+									// Resize if needed
+									if(mCurNbEntries+nb>mMaxNbEntries)	Resize(nb);
+
+									// Add new entry
+									CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float));
+									mCurNbEntries+=nb;
+									return *this;
+								}
+
+		//! Add unique [slow]
+		inline_	Container&		AddUnique(udword entry)
+								{
+									if(!Contains(entry))	Add(entry);
+									return *this;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Clears the container. All stored values are deleted, and it frees used ram.
+		 *	\see		Reset()
+		 *	\return		Self-Reference
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				Container&		Empty();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again.
+		 *	That's a kind of temporal coherence.
+		 *	\see		Empty()
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	void			Reset()
+								{
+									// Avoid the write if possible
+									// ### CMOV
+									if(mCurNbEntries)	mCurNbEntries = 0;
+								}
+
+		// HANDLE WITH CARE
+		inline_	void			ForceSize(udword size)
+								{
+									mCurNbEntries = size;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Sets the initial size of the container. If it already contains something, it's discarded.
+		 *	\param		nb		[in] Number of entries
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				bool			SetSize(udword nb);
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Refits the container and get rid of unused bytes.
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				bool			Refit();
+
+		// Checks whether the container already contains a given value.
+				bool			Contains(udword entry, udword* location=null) const;
+		// Deletes an entry - doesn't preserve insertion order.
+				bool			Delete(udword entry);
+		// Deletes an entry - does preserve insertion order.
+				bool			DeleteKeepingOrder(udword entry);
+		//! Deletes the very last entry.
+		inline_	void			DeleteLastEntry()						{ if(mCurNbEntries)	mCurNbEntries--;			}
+		//! Deletes the entry whose index is given
+		inline_	void			DeleteIndex(udword index)				{ mEntries[index] = mEntries[--mCurNbEntries];	}
+
+		// Helpers
+				Container&		FindNext(udword& entry, FindMode find_mode=FIND_CLAMP);
+				Container&		FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP);
+		// Data access.
+		inline_	udword			GetNbEntries()					const	{ return mCurNbEntries;					}	//!< Returns the current number of entries.
+		inline_	udword			GetEntry(udword i)				const	{ return mEntries[i];					}	//!< Returns ith entry
+		inline_	udword*			GetEntries()					const	{ return mEntries;						}	//!< Returns the list of entries.
+
+		inline_	udword			GetFirst()						const	{ return mEntries[0];					}
+		inline_	udword			GetLast()						const	{ return mEntries[mCurNbEntries-1];		}
+
+		// Growth control
+		inline_	float			GetGrowthFactor()				const	{ return mGrowthFactor;					}	//!< Returns the growth factor
+		inline_	void			SetGrowthFactor(float growth)			{ mGrowthFactor = growth;				}	//!< Sets the growth factor
+		inline_	bool			IsFull()						const	{ return mCurNbEntries==mMaxNbEntries;	}	//!< Checks the container is full
+		inline_	BOOL			IsNotEmpty()					const	{ return mCurNbEntries;					}	//!< Checks the container is empty
+
+		//! Read-access as an array
+		inline_	udword			operator[](udword i)			const	{ ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i];	}
+		//! Write-access as an array
+		inline_	udword&			operator[](udword i)					{ ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i];	}
+
+		// Stats
+				udword			GetUsedRam()					const;
+
+		//! Operator for "Container A = Container B"
+				//void			operator = (const Container& object);
+
+#ifdef CONTAINER_STATS
+		inline_	udword			GetNbContainers()				const	{ return mNbContainers;		}
+		inline_	udword			GetTotalBytes()					const	{ return mUsedRam;			}
+		private:
+
+		static	udword			mNbContainers;		//!< Number of containers around
+		static	udword			mUsedRam;			//!< Amount of bytes used by containers in the system
+#endif
+		private:
+		// Resizing
+				bool			Resize(udword needed=1);
+		// Data
+				udword			mMaxNbEntries;		//!< Maximum possible number of entries
+				udword			mCurNbEntries;		//!< Current number of entries
+				udword*			mEntries;			//!< List of entries
+				float			mGrowthFactor;		//!< Resize: new number of entries = old number * mGrowthFactor
+	};
+
+#endif // __ICECONTAINER_H__

File externals/OPCODE/Ice/IceFPU.h

View file
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains FPU related code.
+ *	\file		IceFPU.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEFPU_H__
+#define __ICEFPU_H__
+
+	#define	SIGN_BITMASK			0x80000000
+
+	namespace {
+		union float_udword { float f; udword u; };
+		union float_sdword { float f; sdword s; };
+	}
+
+
+	//! Integer representation of a floating-point value.
+	//#define IR(x)					((udword&)(x))
+	static inline udword IR(float x) { float_udword fu; fu.f = x; return fu.u; }
+
+	//! Signed integer representation of a floating-point value.
+	//#define SIR(x)					((sdword&)(x))
+	static inline sdword SIR(float x) { float_sdword fs; fs.f = x; return fs.s; }
+
+	//! Absolute integer representation of a floating-point value
+	#define AIR(x)					(IR(x)&0x7fffffff)
+
+	//! Floating-point representation of an integer value.
+	//#define FR(x)					((float&)(x))
+	static inline float FR(unsigned x) { float_udword fu; fu.u = x; return fu.f; }
+
+	//! Integer-based comparison of a floating point value.
+	//! Don't use it blindly, it can be faster or slower than the FPU comparison, depends on the context.
+	#define IS_NEGATIVE_FLOAT(x)	(IR(x)&0x80000000)
+
+	//! Fast fabs for floating-point values. It just clears the sign bit.
+	//! Don't use it blindy, it can be faster or slower than the FPU comparison, depends on the context.
+	inline_ float FastFabs(float x)
+	{
+		udword FloatBits = IR(x)&0x7fffffff;
+		return FR(FloatBits);
+	}
+
+	//! Fast square root for floating-point values.
+	inline_ float FastSqrt(float square)
+	{
+		return sqrt(square);
+	}
+
+	//! Saturates positive to zero.
+	inline_ float fsat(float f)
+	{
+		udword y = IR(f) & ~(SIR(f) >>31);
+		return FR(y);
+	}
+
+	//! Computes 1.0f / sqrtf(x).
+	inline_ float frsqrt(float f)
+	{
+		float x = f * 0.5f;
+		udword y = 0x5f3759df - (IR(f) >> 1);
+		// Iteration...
+		const float fy = FR(y);
+		const float result = fy * ( 1.5f - ( x * fy * fy ) );
+		// Result
+		return result;
+	}
+
+	//! Computes 1.0f / sqrtf(x). Comes from NVIDIA.
+	inline_ float InvSqrt(const float& x)
+	{
+		const udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - IR(x)) >> 1;      
+		const float y = FR(tmp);
+		return y * (1.47f - 0.47f * x * y * y);
+	}
+
+	//! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above.
+	//! See http://www.magic-software.com/3DGEDInvSqrt.html
+	inline_ float RSqrt(float number)
+	{
+		int i;
+		float x2, y;
+		const float threehalfs = 1.5f;
+
+		x2 = number * 0.5f;
+		y  = number;
+		i  = IR(y);
+		i  = 0x5f3759df - (i >> 1);
+		y  = FR(i);
+		y  = y * (threehalfs - (x2 * y * y));
+
+		return y;
+	}
+
+	//! TO BE DOCUMENTED
+	inline_ float fsqrt(float f)
+	{
+		udword y = ( ( SIR(f) - 0x3f800000 ) >> 1 ) + 0x3f800000;
+		// Iteration...?
+		// (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f;
+		// Result
+		return FR(y);
+	}
+
+	//! Returns the float ranged espilon value.
+	inline_ float fepsilon(float f)
+	{
+		udword b = IR(f) & 0xff800000;
+		udword a = b | 0x00000001;
+		// Result
+		return FR(a) - FR(b);
+	}
+
+	//! Is the float valid ?
+	inline_ bool IsNAN(float value)				{ return (IR(value)&0x7f800000) == 0x7f800000;	}
+	inline_ bool IsIndeterminate(float value)	{ return IR(value) == 0xffc00000;				}
+	inline_ bool IsPlusInf(float value)			{ return IR(value) == 0x7f800000;				}
+	inline_ bool IsMinusInf(float value)		{ return IR(value) == 0xff800000;				}
+
+	inline_	bool IsValidFloat(float value)
+	{
+		if(IsNAN(value))			return false;
+		if(IsIndeterminate(value))	return false;
+		if(IsPlusInf(value))		return false;
+		if(IsMinusInf(value))		return false;
+		return true;
+	}
+
+	#define CHECK_VALID_FLOAT(x)	ASSERT(IsValidFloat(x));
+
+/*
+	//! FPU precision setting function.
+	inline_ void SetFPU()
+	{
+		// This function evaluates whether the floating-point
+		// control word is set to single precision/round to nearest/
+		// exceptions disabled. If these conditions don't hold, the
+		// function changes the control word to set them and returns
+		// TRUE, putting the old control word value in the passback
+		// location pointed to by pwOldCW.
+		{
+			uword wTemp, wSave;
+ 
+			__asm fstcw wSave
+			if (wSave & 0x300 ||            // Not single mode
+				0x3f != (wSave & 0x3f) ||   // Exceptions enabled
+				wSave & 0xC00)              // Not round to nearest mode
+			{
+				__asm
+				{
+					mov ax, wSave
+					and ax, not 300h    ;; single mode
+					or  ax, 3fh         ;; disable all exceptions
+					and ax, not 0xC00   ;; round to nearest mode