fix: some file didn't have the svn:eol-style native yet

This commit is contained in:
erwin.coumans
2010-03-06 15:23:36 +00:00
parent 4fd48ac691
commit 81f04a4d48
641 changed files with 301123 additions and 301123 deletions

View File

@@ -1,422 +1,422 @@
/*
* ICE OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains AABB-related code.
* \file IceAABB.cpp
* \author Pierre Terdiman
* \date January, 29, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* AABB class.
* \class AABB
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 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 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 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
}
/*
* ICE OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains AABB-related code.
* \file IceAABB.cpp
* \author Pierre Terdiman
* \date January, 29, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* AABB class.
* \class AABB
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 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 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 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 diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +1,52 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains an allocator base class.
* \file IceAllocator.h
* \author Pierre Terdiman
* \date December, 19, 2003
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEALLOCATOR_H
#define ICEALLOCATOR_H
enum MemoryType
{
MEMORY_PERSISTENT,
MEMORY_TEMP,
};
class ICECORE_API Allocator
{
public:
virtual void* malloc(size_t size, MemoryType type) = 0;
virtual void* mallocDebug(size_t size, const char* filename, udword line, const char* class_name, MemoryType type) = 0;
virtual void* realloc(void* memory, size_t size) = 0;
virtual void* shrink(void* memory, size_t size) = 0;
virtual void free(void* memory) = 0;
};
FUNCTION ICECORE_API Allocator* GetAllocator();
FUNCTION ICECORE_API bool SetAllocator(Allocator& allocator);
FUNCTION ICECORE_API void DumpMemory();
class ICECORE_API Allocateable
{
public:
#ifdef DONT_TRACK_MEMORY_LEAKS
inline_ void* operator new (size_t size, MemoryType type) { return GetAllocator()->malloc(size, type); }
inline_ void* operator new (size_t size, const char * filename, int line, const char* class_name, MemoryType type) { return GetAllocator()->mallocDebug(size, filename, line, class_name, type); }
inline_ void* operator new[] (size_t size, MemoryType type) { return GetAllocator()->malloc(size, type); }
inline_ void* operator new[] (size_t size, const char * filename, int line, const char* class_name, MemoryType type) { return GetAllocator()->mallocDebug(size, filename, line, class_name, type); }
inline_ void operator delete (void* p) { GetAllocator()->free(p); }
inline_ void operator delete (void* p, MemoryType) { GetAllocator()->free(p); }
inline_ void operator delete (void* p, const char*, int, const char*, MemoryType) { GetAllocator()->free(p); }
inline_ void operator delete[] (void* p) { GetAllocator()->free(p); }
inline_ void operator delete[] (void* p, MemoryType) { GetAllocator()->free(p); }
inline_ void operator delete[] (void* p, const char*, int, const char*, MemoryType) { GetAllocator()->free(p); }
#endif
};
#endif // ICEALLOCATOR_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains an allocator base class.
* \file IceAllocator.h
* \author Pierre Terdiman
* \date December, 19, 2003
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEALLOCATOR_H
#define ICEALLOCATOR_H
enum MemoryType
{
MEMORY_PERSISTENT,
MEMORY_TEMP,
};
class ICECORE_API Allocator
{
public:
virtual void* malloc(size_t size, MemoryType type) = 0;
virtual void* mallocDebug(size_t size, const char* filename, udword line, const char* class_name, MemoryType type) = 0;
virtual void* realloc(void* memory, size_t size) = 0;
virtual void* shrink(void* memory, size_t size) = 0;
virtual void free(void* memory) = 0;
};
FUNCTION ICECORE_API Allocator* GetAllocator();
FUNCTION ICECORE_API bool SetAllocator(Allocator& allocator);
FUNCTION ICECORE_API void DumpMemory();
class ICECORE_API Allocateable
{
public:
#ifdef DONT_TRACK_MEMORY_LEAKS
inline_ void* operator new (size_t size, MemoryType type) { return GetAllocator()->malloc(size, type); }
inline_ void* operator new (size_t size, const char * filename, int line, const char* class_name, MemoryType type) { return GetAllocator()->mallocDebug(size, filename, line, class_name, type); }
inline_ void* operator new[] (size_t size, MemoryType type) { return GetAllocator()->malloc(size, type); }
inline_ void* operator new[] (size_t size, const char * filename, int line, const char* class_name, MemoryType type) { return GetAllocator()->mallocDebug(size, filename, line, class_name, type); }
inline_ void operator delete (void* p) { GetAllocator()->free(p); }
inline_ void operator delete (void* p, MemoryType) { GetAllocator()->free(p); }
inline_ void operator delete (void* p, const char*, int, const char*, MemoryType) { GetAllocator()->free(p); }
inline_ void operator delete[] (void* p) { GetAllocator()->free(p); }
inline_ void operator delete[] (void* p, MemoryType) { GetAllocator()->free(p); }
inline_ void operator delete[] (void* p, const char*, int, const char*, MemoryType) { GetAllocator()->free(p); }
#endif
};
#endif // ICEALLOCATOR_H

View File

@@ -1,48 +1,48 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains custom assertion code.
* \file IceAssert.h
* \author Pierre Terdiman
* \date January, 14, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEASSERT_H
#define ICEASSERT_H
// Leave the {} so that you can write this kind of things safely in release mode:
// if(condition) ASSERT()
#ifndef ASSERT
#if defined( _DEBUG )
FUNCTION ICECORE_API bool CustomAssertFunction(int, char*, int, char*, bool&);
//! Custom ASSERT function. Various usages:
//! ASSERT(condition)
//! ASSERT(!"Not implemented")
//! ASSERT(condition && "error text")
#define ASSERT(exp) \
{ \
static bool IgnoreAlways = false; \
if(!IgnoreAlways) \
{ \
if(CustomAssertFunction((int)(exp), #exp, __LINE__, __FILE__, IgnoreAlways)) \
{ \
_asm { int 3 } \
} \
} \
}
#else
#define ASSERT(exp) {}
#endif
#endif
#ifndef assert
#define assert ASSERT
#endif
#define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ]
#endif // ICEASSERT_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains custom assertion code.
* \file IceAssert.h
* \author Pierre Terdiman
* \date January, 14, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEASSERT_H
#define ICEASSERT_H
// Leave the {} so that you can write this kind of things safely in release mode:
// if(condition) ASSERT()
#ifndef ASSERT
#if defined( _DEBUG )
FUNCTION ICECORE_API bool CustomAssertFunction(int, char*, int, char*, bool&);
//! Custom ASSERT function. Various usages:
//! ASSERT(condition)
//! ASSERT(!"Not implemented")
//! ASSERT(condition && "error text")
#define ASSERT(exp) \
{ \
static bool IgnoreAlways = false; \
if(!IgnoreAlways) \
{ \
if(CustomAssertFunction((int)(exp), #exp, __LINE__, __FILE__, IgnoreAlways)) \
{ \
_asm { int 3 } \
} \
} \
}
#else
#define ASSERT(exp) {}
#endif
#endif
#ifndef assert
#define assert ASSERT
#endif
#define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ]
#endif // ICEASSERT_H

View File

@@ -1,70 +1,70 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__

View File

@@ -1,73 +1,73 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for bit arrays.
* \file IceBitArray.cpp
* \author Pierre Terdiman
* \date February, 5, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* A simple array of bits stored as bytes.
*
* \class Container
* \author Pierre Terdiman
* \version 1.0
* \date February, 5, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "StdAfx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BitArray::BitArray() : mSize(0), mBits(null)
{
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BitArray::BitArray(udword nb_bits) : mSize(0), mBits(null)
{
Init(nb_bits);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Destructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BitArray::~BitArray()
{
ICE_FREE(mBits);
mSize = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Initializes the bit array for a given number of entries
* \param nb_bits [in] max number of entries in the array
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool BitArray::Init(udword nb_bits)
{
mSize = BitsToDwords(nb_bits);
// Get ram for n bits
ICE_FREE(mBits);
mBits = (udword*)ICE_ALLOC(sizeof(udword)*mSize);
// Set all bits to 0
ClearAll();
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for bit arrays.
* \file IceBitArray.cpp
* \author Pierre Terdiman
* \date February, 5, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* A simple array of bits stored as bytes.
*
* \class Container
* \author Pierre Terdiman
* \version 1.0
* \date February, 5, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "StdAfx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BitArray::BitArray() : mSize(0), mBits(null)
{
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BitArray::BitArray(udword nb_bits) : mSize(0), mBits(null)
{
Init(nb_bits);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Destructor.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BitArray::~BitArray()
{
ICE_FREE(mBits);
mSize = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Initializes the bit array for a given number of entries
* \param nb_bits [in] max number of entries in the array
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool BitArray::Init(udword nb_bits)
{
mSize = BitsToDwords(nb_bits);
// Get ram for n bits
ICE_FREE(mBits);
mBits = (udword*)ICE_ALLOC(sizeof(udword)*mSize);
// Set all bits to 0
ClearAll();
return true;
}

View File

@@ -1,82 +1,82 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for bit arrays.
* \file IceBitArray.h
* \author Pierre Terdiman
* \date February, 5, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEBITARRAY_H
#define ICEBITARRAY_H
inline_ udword BitsToBytes(udword nb_bits)
{
return (nb_bits>>3) + ((nb_bits&7) ? 1 : 0);
}
inline_ udword BitsToDwords(udword nb_bits)
{
return (nb_bits>>5) + ((nb_bits&31) ? 1 : 0);
}
// Use that one instead of an array of bools. Takes less ram, nearly as fast [no bounds checkings and so on].
class ICECORE_API BitArray
{
public:
//! Constructor
BitArray();
BitArray(udword nb_bits);
//! Destructor
~BitArray();
bool Init(udword nb_bits);
// Data management
inline_ void SetBit(udword bit_number) { mBits[bit_number>>5] |= 1<<(bit_number&31); }
inline_ void ClearBit(udword bit_number) { mBits[bit_number>>5] &= ~(1<<(bit_number&31)); }
inline_ void ToggleBit(udword bit_number) { mBits[bit_number>>5] ^= 1<<(bit_number&31); }
inline_ void ClearAll() { ZeroMemory(mBits, mSize*4); }
inline_ void SetAll() { FillMemory(mBits, mSize*4, 0xff); }
// Data access
inline_ BOOL IsSet(udword bit_number) const { return mBits[bit_number>>5] & (1<<(bit_number&31)); }
inline_ const udword* GetBits() const { return mBits; }
inline_ udword GetSize() const { return mSize; }
protected:
udword* mBits; //!< Array of bits
udword mSize; //!< Size of the array in dwords
};
// - We consider square symmetric N*N matrices
// - A N*N symmetric matrix has N(N+1)/2 elements
// - A boolean version needs N(N+1)/16 bytes
// N NbBits NbBytes
// 4 10 -
// 8 36 4.5
// 16 136 17 <= the one we select
// 32 528 66
static ubyte BitMasks[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
static ubyte NegBitMasks[] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
class ICECORE_API BoolSquareSymmetricMatrix16
{
public:
inline_ udword Index(udword x, udword y) const { if(x>y) Swap(x,y); return x + (y ? ((y-1)*y)>>1 : 0); }
inline_ void Set(udword x, udword y) { udword i = Index(x, y); mBits[i>>3] |= BitMasks[i&7]; }
inline_ void Clear(udword x, udword y) { udword i = Index(x, y); mBits[i>>3] &= NegBitMasks[i&7]; }
inline_ void Toggle(udword x, udword y) { udword i = Index(x, y); mBits[i>>3] ^= BitMasks[i&7]; }
inline_ bool IsSet(udword x, udword y) const { udword i = Index(x, y); return (mBits[i>>3] & BitMasks[i&7])!=0; }
inline_ void ClearAll() { ZeroMemory(mBits, 17); }
inline_ void SetAll() { FillMemory(mBits, 17, 0xff); }
ubyte mBits[17];
};
#endif // ICEBITARRAY_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for bit arrays.
* \file IceBitArray.h
* \author Pierre Terdiman
* \date February, 5, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEBITARRAY_H
#define ICEBITARRAY_H
inline_ udword BitsToBytes(udword nb_bits)
{
return (nb_bits>>3) + ((nb_bits&7) ? 1 : 0);
}
inline_ udword BitsToDwords(udword nb_bits)
{
return (nb_bits>>5) + ((nb_bits&31) ? 1 : 0);
}
// Use that one instead of an array of bools. Takes less ram, nearly as fast [no bounds checkings and so on].
class ICECORE_API BitArray
{
public:
//! Constructor
BitArray();
BitArray(udword nb_bits);
//! Destructor
~BitArray();
bool Init(udword nb_bits);
// Data management
inline_ void SetBit(udword bit_number) { mBits[bit_number>>5] |= 1<<(bit_number&31); }
inline_ void ClearBit(udword bit_number) { mBits[bit_number>>5] &= ~(1<<(bit_number&31)); }
inline_ void ToggleBit(udword bit_number) { mBits[bit_number>>5] ^= 1<<(bit_number&31); }
inline_ void ClearAll() { ZeroMemory(mBits, mSize*4); }
inline_ void SetAll() { FillMemory(mBits, mSize*4, 0xff); }
// Data access
inline_ BOOL IsSet(udword bit_number) const { return mBits[bit_number>>5] & (1<<(bit_number&31)); }
inline_ const udword* GetBits() const { return mBits; }
inline_ udword GetSize() const { return mSize; }
protected:
udword* mBits; //!< Array of bits
udword mSize; //!< Size of the array in dwords
};
// - We consider square symmetric N*N matrices
// - A N*N symmetric matrix has N(N+1)/2 elements
// - A boolean version needs N(N+1)/16 bytes
// N NbBits NbBytes
// 4 10 -
// 8 36 4.5
// 16 136 17 <= the one we select
// 32 528 66
static ubyte BitMasks[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
static ubyte NegBitMasks[] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
class ICECORE_API BoolSquareSymmetricMatrix16
{
public:
inline_ udword Index(udword x, udword y) const { if(x>y) Swap(x,y); return x + (y ? ((y-1)*y)>>1 : 0); }
inline_ void Set(udword x, udword y) { udword i = Index(x, y); mBits[i>>3] |= BitMasks[i&7]; }
inline_ void Clear(udword x, udword y) { udword i = Index(x, y); mBits[i>>3] &= NegBitMasks[i&7]; }
inline_ void Toggle(udword x, udword y) { udword i = Index(x, y); mBits[i>>3] ^= BitMasks[i&7]; }
inline_ bool IsSet(udword x, udword y) const { udword i = Index(x, y); return (mBits[i>>3] & BitMasks[i&7])!=0; }
inline_ void ClearAll() { ZeroMemory(mBits, 17); }
inline_ void SetAll() { FillMemory(mBits, 17, 0xff); }
ubyte mBits[17];
};
#endif // ICEBITARRAY_H

View File

@@ -1,158 +1,158 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__

View File

@@ -1,423 +1,423 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 Opcode;
// Static members
#ifdef CONTAINER_STATS
udword Container::mNbContainers = 0;
udword Container::mUsedRam = 0;
LinkedList Container::mContainers;
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor. No entries allocated there.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
{
#ifdef CONTAINER_STATS
mNbContainers++;
mUsedRam+=sizeof(Container);
mContainers.AddElem(this);
#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor. Also allocates a given number of entries.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null)
{
SetGrowthFactor(growth_factor);
#ifdef CONTAINER_STATS
mNbContainers++;
mUsedRam+=sizeof(Container);
mContainers.AddElem(this);
#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);
mContainers.AddElem(this);
#endif
*this = object;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Destructor. Frees everything and leaves.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Container::~Container()
{
Empty();
#ifdef CONTAINER_STATS
mNbContainers--;
mUsedRam-=GetUsedRam();
mContainers.RemElem(this);
#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Initializes the container so that it uses an external memory buffer. The container doesn't own the memory, resizing is disabled.
* \param max_entries [in] max number of entries in the container
* \param entries [in] external memory buffer
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Container::InitSharedBuffers(udword max_entries, udword* entries)
{
Empty(); // Make sure everything has been released
mMaxNbEntries = max_entries;
mEntries = entries;
mGrowthFactor = -1.0f; // Negative growth ==> resize is disabled
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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
if(mGrowthFactor>=0.0f) ICE_FREE(mEntries); // Release memory if we own it
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)
{
// Check growth is allowed
if(mGrowthFactor<=0.0f)
{
ASSERT(!"Invalid operation - trying to resize a static buffer!");
return false;
}
#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 = (udword*)ICE_ALLOC(sizeof(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
ICE_FREE(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 = (udword*)ICE_ALLOC(sizeof(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()
{
// Check refit is allowed
if(mGrowthFactor<=0.0f)
{
ASSERT(!"Invalid operation - trying to refit a static buffer!");
return false;
}
#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 = (udword*)ICE_ALLOC(sizeof(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
ICE_FREE(mEntries);
// Assign new pointer
mEntries = NewEntries;
return true;
}
// Same as Refit but more efficient
bool Container::Shrink()
{
if(!mEntries) return false;
if(!mCurNbEntries)
{
Empty();
return true;
}
// Try to shrink the pointer
if(!GetAllocator()->shrink(mEntries, sizeof(udword)*mCurNbEntries))
return false;
#ifdef CONTAINER_STATS
// Subtract previous amount of bytes
mUsedRam-=mMaxNbEntries*sizeof(udword);
#endif
// Get just enough entries
mMaxNbEntries = mCurNbEntries;
#ifdef CONTAINER_STATS
// Add current amount of bytes
mUsedRam+=mMaxNbEntries*sizeof(udword);
#endif
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);
}
float Container::GetGrowthFactor() const
{
return mGrowthFactor;
}
void Container::SetGrowthFactor(float growth)
{
// Negative growths are reserved for internal usages
if(growth<0.0f) growth = 0.0f;
mGrowthFactor = growth;
}
//! Operator for "Container A = Container B"
void Container::operator=(const Container& object)
{
SetSize(object.GetNbEntries());
CopyMemory(mEntries, object.GetEntries(), mMaxNbEntries*sizeof(udword));
mCurNbEntries = mMaxNbEntries;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 Opcode;
// Static members
#ifdef CONTAINER_STATS
udword Container::mNbContainers = 0;
udword Container::mUsedRam = 0;
LinkedList Container::mContainers;
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor. No entries allocated there.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
{
#ifdef CONTAINER_STATS
mNbContainers++;
mUsedRam+=sizeof(Container);
mContainers.AddElem(this);
#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor. Also allocates a given number of entries.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null)
{
SetGrowthFactor(growth_factor);
#ifdef CONTAINER_STATS
mNbContainers++;
mUsedRam+=sizeof(Container);
mContainers.AddElem(this);
#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);
mContainers.AddElem(this);
#endif
*this = object;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Destructor. Frees everything and leaves.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Container::~Container()
{
Empty();
#ifdef CONTAINER_STATS
mNbContainers--;
mUsedRam-=GetUsedRam();
mContainers.RemElem(this);
#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Initializes the container so that it uses an external memory buffer. The container doesn't own the memory, resizing is disabled.
* \param max_entries [in] max number of entries in the container
* \param entries [in] external memory buffer
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Container::InitSharedBuffers(udword max_entries, udword* entries)
{
Empty(); // Make sure everything has been released
mMaxNbEntries = max_entries;
mEntries = entries;
mGrowthFactor = -1.0f; // Negative growth ==> resize is disabled
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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
if(mGrowthFactor>=0.0f) ICE_FREE(mEntries); // Release memory if we own it
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)
{
// Check growth is allowed
if(mGrowthFactor<=0.0f)
{
ASSERT(!"Invalid operation - trying to resize a static buffer!");
return false;
}
#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 = (udword*)ICE_ALLOC(sizeof(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
ICE_FREE(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 = (udword*)ICE_ALLOC(sizeof(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()
{
// Check refit is allowed
if(mGrowthFactor<=0.0f)
{
ASSERT(!"Invalid operation - trying to refit a static buffer!");
return false;
}
#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 = (udword*)ICE_ALLOC(sizeof(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
ICE_FREE(mEntries);
// Assign new pointer
mEntries = NewEntries;
return true;
}
// Same as Refit but more efficient
bool Container::Shrink()
{
if(!mEntries) return false;
if(!mCurNbEntries)
{
Empty();
return true;
}
// Try to shrink the pointer
if(!GetAllocator()->shrink(mEntries, sizeof(udword)*mCurNbEntries))
return false;
#ifdef CONTAINER_STATS
// Subtract previous amount of bytes
mUsedRam-=mMaxNbEntries*sizeof(udword);
#endif
// Get just enough entries
mMaxNbEntries = mCurNbEntries;
#ifdef CONTAINER_STATS
// Add current amount of bytes
mUsedRam+=mMaxNbEntries*sizeof(udword);
#endif
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);
}
float Container::GetGrowthFactor() const
{
return mGrowthFactor;
}
void Container::SetGrowthFactor(float growth)
{
// Negative growths are reserved for internal usages
if(growth<0.0f) growth = 0.0f;
mGrowthFactor = growth;
}
//! Operator for "Container A = Container B"
void Container::operator=(const Container& object)
{
SetSize(object.GetNbEntries());
CopyMemory(mEntries, object.GetEntries(), mMaxNbEntries*sizeof(udword));
mCurNbEntries = mMaxNbEntries;
}

View File

@@ -1,254 +1,254 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 // #### doesn't work with micro-threads!
class LinkedList;
enum FindMode
{
FIND_CLAMP,
FIND_WRAP,
FIND_FORCE_DWORD = 0x7fffffff
};
class ICECORE_API Container : public Allocateable
#ifdef CONTAINER_STATS
, public ListElem
#endif
{
public:
// Constructor / Destructor
Container();
Container(const Container& object);
Container(udword size, float growth_factor);
~Container();
// Management
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Initializes the container so that it uses an external memory buffer. The container doesn't own the memory, resizing is disabled.
* \param max_entries [in] max number of entries in the container
* \param entries [in] external memory buffer
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void InitSharedBuffers(udword max_entries, udword* entries);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 udword* entries, udword nb)
{
if(entries && nb)
{
// Resize if needed
if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
// Add new entry
CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword));
mCurNbEntries += nb;
}
return *this;
}
inline_ Container& Add(const Container& container)
{
return Add(container.GetEntries(), container.GetNbEntries());
}
inline_ udword* Reserve(udword nb)
{
// Resize if needed
if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
// We expect the user to fill reserved memory with 'nb' udwords
udword* Reserved = &mEntries[mCurNbEntries];
// Meanwhile, we do as if it had been filled
mCurNbEntries += nb;
// This is mainly used to avoid the copy when possible
return Reserved;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 - I hope you know what you're doing
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();
bool Shrink();
// 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 GetMaxNbEntries() const { return mMaxNbEntries; } //!< Returns max number of entries before resizing.
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
float GetGrowthFactor() const; //!< Returns the growth factor
void SetGrowthFactor(float 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
static udword GetNbContainers() { return mNbContainers; }
static udword GetTotalBytes() { return mUsedRam; }
static LinkedList& GetContainers() { return mContainers; }
private:
static udword mNbContainers; //!< Number of containers around
static udword mUsedRam; //!< Amount of bytes used by containers in the system
static LinkedList mContainers;
#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
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 // #### doesn't work with micro-threads!
class LinkedList;
enum FindMode
{
FIND_CLAMP,
FIND_WRAP,
FIND_FORCE_DWORD = 0x7fffffff
};
class ICECORE_API Container : public Allocateable
#ifdef CONTAINER_STATS
, public ListElem
#endif
{
public:
// Constructor / Destructor
Container();
Container(const Container& object);
Container(udword size, float growth_factor);
~Container();
// Management
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Initializes the container so that it uses an external memory buffer. The container doesn't own the memory, resizing is disabled.
* \param max_entries [in] max number of entries in the container
* \param entries [in] external memory buffer
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void InitSharedBuffers(udword max_entries, udword* entries);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 udword* entries, udword nb)
{
if(entries && nb)
{
// Resize if needed
if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
// Add new entry
CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword));
mCurNbEntries += nb;
}
return *this;
}
inline_ Container& Add(const Container& container)
{
return Add(container.GetEntries(), container.GetNbEntries());
}
inline_ udword* Reserve(udword nb)
{
// Resize if needed
if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
// We expect the user to fill reserved memory with 'nb' udwords
udword* Reserved = &mEntries[mCurNbEntries];
// Meanwhile, we do as if it had been filled
mCurNbEntries += nb;
// This is mainly used to avoid the copy when possible
return Reserved;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 - I hope you know what you're doing
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();
bool Shrink();
// 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 GetMaxNbEntries() const { return mMaxNbEntries; } //!< Returns max number of entries before resizing.
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
float GetGrowthFactor() const; //!< Returns the growth factor
void SetGrowthFactor(float 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
static udword GetNbContainers() { return mNbContainers; }
static udword GetTotalBytes() { return mUsedRam; }
static LinkedList& GetContainers() { return mContainers; }
private:
static udword mNbContainers; //!< Number of containers around
static udword mUsedRam; //!< Amount of bytes used by containers in the system
static LinkedList mContainers;
#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

View File

@@ -1,403 +1,403 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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
//! Integer representation of a floating-point value.
#define IR(x) ((udword&)(x))
//! Signed integer representation of a floating-point value.
#define SIR(x) ((sdword&)(x))
//! 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))
//! 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)
//! Checks 2 values have different signs
inline_ BOOL DifferentSign(float f0, float f1)
{
return (IR(f0)^IR(f1))&SIGN_BITMASK;
}
//! 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)
{
float retval;
__asm {
mov eax, square
sub eax, 0x3F800000
sar eax, 1
add eax, 0x3F800000
mov [retval], eax
}
return retval;
}
//! Saturates positive to zero.
inline_ float fsat(float f)
{
udword y = (udword&)f & ~((sdword&)f >>31);
return (float&)y;
}
//! Computes 1.0f / sqrtf(x).
inline_ float frsqrt(float f)
{
float x = f * 0.5f;
udword y = 0x5f3759df - ((udword&)f >> 1);
// Iteration...
(float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) );
// Result
return (float&)y;
}
//! Computes 1.0f / sqrtf(x). Comes from NVIDIA.
inline_ float InvSqrt(const float& x)
{
udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1;
float y = *(float*)&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)
{
long i;
float x2, y;
const float threehalfs = 1.5f;
x2 = number * 0.5f;
y = number;
i = * (long *) &y;
i = 0x5f3759df - (i >> 1);
y = * (float *) &i;
y = y * (threehalfs - (x2 * y * y));
return y;
}
//! TO BE DOCUMENTED
inline_ float fsqrt(float f)
{
udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000;
// Iteration...?
// (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f;
// Result
return (float&)y;
}
//! Returns the float ranged espilon value.
inline_ float fepsilon(float f)
{
udword b = (udword&)f & 0xff800000;
udword a = b | 0x00000001;
(float&)a -= (float&)b;
// Result
return (float&)a;
}
//! 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
mov wTemp, ax
fldcw wTemp
}
}
}
}
*/
//! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON)
inline_ float ComputeFloatEpsilon()
{
float f = 1.0f;
((udword&)f)^=1;
return f - 1.0f; // You can check it's the same as FLT_EPSILON
}
inline_ bool IsFloatZero(float x, float epsilon=1e-6f)
{
return x*x < epsilon;
}
#define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0
#define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0
#define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0
#define FCMOVNB_ST0 _asm _emit 0xdb _asm _emit 0xc0
#define FCOMI_ST1 _asm _emit 0xdb _asm _emit 0xf1
#define FCOMIP_ST1 _asm _emit 0xdf _asm _emit 0xf1
#define FCMOVB_ST1 _asm _emit 0xda _asm _emit 0xc1
#define FCMOVNB_ST1 _asm _emit 0xdb _asm _emit 0xc1
#define FCOMI_ST2 _asm _emit 0xdb _asm _emit 0xf2
#define FCOMIP_ST2 _asm _emit 0xdf _asm _emit 0xf2
#define FCMOVB_ST2 _asm _emit 0xda _asm _emit 0xc2
#define FCMOVNB_ST2 _asm _emit 0xdb _asm _emit 0xc2
#define FCOMI_ST3 _asm _emit 0xdb _asm _emit 0xf3
#define FCOMIP_ST3 _asm _emit 0xdf _asm _emit 0xf3
#define FCMOVB_ST3 _asm _emit 0xda _asm _emit 0xc3
#define FCMOVNB_ST3 _asm _emit 0xdb _asm _emit 0xc3
#define FCOMI_ST4 _asm _emit 0xdb _asm _emit 0xf4
#define FCOMIP_ST4 _asm _emit 0xdf _asm _emit 0xf4
#define FCMOVB_ST4 _asm _emit 0xda _asm _emit 0xc4
#define FCMOVNB_ST4 _asm _emit 0xdb _asm _emit 0xc4
#define FCOMI_ST5 _asm _emit 0xdb _asm _emit 0xf5
#define FCOMIP_ST5 _asm _emit 0xdf _asm _emit 0xf5
#define FCMOVB_ST5 _asm _emit 0xda _asm _emit 0xc5
#define FCMOVNB_ST5 _asm _emit 0xdb _asm _emit 0xc5
#define FCOMI_ST6 _asm _emit 0xdb _asm _emit 0xf6
#define FCOMIP_ST6 _asm _emit 0xdf _asm _emit 0xf6
#define FCMOVB_ST6 _asm _emit 0xda _asm _emit 0xc6
#define FCMOVNB_ST6 _asm _emit 0xdb _asm _emit 0xc6
#define FCOMI_ST7 _asm _emit 0xdb _asm _emit 0xf7
#define FCOMIP_ST7 _asm _emit 0xdf _asm _emit 0xf7
#define FCMOVB_ST7 _asm _emit 0xda _asm _emit 0xc7
#define FCMOVNB_ST7 _asm _emit 0xdb _asm _emit 0xc7
//! A global function to find MAX(a,b) using FCOMI/FCMOV
inline_ float FCMax2(float a, float b)
{
float Res;
_asm fld [a]
_asm fld [b]
FCOMI_ST1
FCMOVB_ST1
_asm fstp [Res]
_asm fcomp
return Res;
}
//! A global function to find MIN(a,b) using FCOMI/FCMOV
inline_ float FCMin2(float a, float b)
{
float Res;
_asm fld [a]
_asm fld [b]
FCOMI_ST1
FCMOVNB_ST1
_asm fstp [Res]
_asm fcomp
return Res;
}
//! A global function to find MAX(a,b,c) using FCOMI/FCMOV
inline_ float FCMax3(float a, float b, float c)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
FCOMI_ST1
FCMOVB_ST1
FCOMI_ST2
FCMOVB_ST2
_asm fstp [Res]
_asm fcompp
return Res;
}
//! A global function to find MIN(a,b,c) using FCOMI/FCMOV
inline_ float FCMin3(float a, float b, float c)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
FCOMI_ST1
FCMOVNB_ST1
FCOMI_ST2
FCMOVNB_ST2
_asm fstp [Res]
_asm fcompp
return Res;
}
//! A global function to find MAX(a,b,c,d) using FCOMI/FCMOV
inline_ float FCMax4(float a, float b, float c, float d)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
_asm fld [d]
FCOMI_ST1
FCMOVB_ST1
FCOMI_ST2
FCMOVB_ST2
FCOMI_ST3
FCMOVB_ST3
_asm fstp [Res]
_asm fcompp
_asm fcomp
return Res;
}
//! A global function to find MIN(a,b,c,d) using FCOMI/FCMOV
inline_ float FCMin4(float a, float b, float c, float d)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
_asm fld [d]
FCOMI_ST1
FCMOVNB_ST1
FCOMI_ST2
FCMOVNB_ST2
FCOMI_ST3
FCMOVNB_ST3
_asm fstp [Res]
_asm fcompp
_asm fcomp
return Res;
}
inline_ int ConvertToSortable(float f)
{
int& Fi = (int&)f;
int Fmask = (Fi>>31);
Fi ^= Fmask;
Fmask &= ~(1<<31);
Fi -= Fmask;
return Fi;
}
inline_ udword EncodeFloat(const float val)
{
// We may need to check on -0 and 0
// But it should make no practical difference.
udword ir = IR(val);
if(ir & 0x80000000) //negative?
ir = ~ir;//reverse sequence of negative numbers
else
ir |= 0x80000000; // flip sign
return ir;
}
inline_ float DecodeFloat(udword ir)
{
udword rv;
if(ir & 0x80000000) //positive?
rv = ir & ~0x80000000; //flip sign
else
rv = ~ir; //undo reversal
return FR(rv);
}
enum FPUMode
{
FPU_FLOOR = 0,
FPU_CEIL = 1,
FPU_BEST = 2,
FPU_FORCE_DWORD = 0x7fffffff
};
FUNCTION ICECORE_API FPUMode GetFPUMode();
FUNCTION ICECORE_API void SaveFPU();
FUNCTION ICECORE_API void RestoreFPU();
FUNCTION ICECORE_API void SetFPUFloorMode();
FUNCTION ICECORE_API void SetFPUCeilMode();
FUNCTION ICECORE_API void SetFPUBestMode();
FUNCTION ICECORE_API void SetFPUPrecision24();
FUNCTION ICECORE_API void SetFPUPrecision53();
FUNCTION ICECORE_API void SetFPUPrecision64();
FUNCTION ICECORE_API void SetFPURoundingChop();
FUNCTION ICECORE_API void SetFPURoundingUp();
FUNCTION ICECORE_API void SetFPURoundingDown();
FUNCTION ICECORE_API void SetFPURoundingNear();
FUNCTION ICECORE_API int intChop(const float& f);
FUNCTION ICECORE_API int intFloor(const float& f);
FUNCTION ICECORE_API int intCeil(const float& f);
inline_ sdword MyFloor(float f)
{
return (sdword)f - (IR(f)>>31);
}
class ICECORE_API FPUGuard
{
public:
FPUGuard();
~FPUGuard();
private:
uword mControlWord;
};
#endif // ICEFPU_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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
//! Integer representation of a floating-point value.
#define IR(x) ((udword&)(x))
//! Signed integer representation of a floating-point value.
#define SIR(x) ((sdword&)(x))
//! 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))
//! 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)
//! Checks 2 values have different signs
inline_ BOOL DifferentSign(float f0, float f1)
{
return (IR(f0)^IR(f1))&SIGN_BITMASK;
}
//! 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)
{
float retval;
__asm {
mov eax, square
sub eax, 0x3F800000
sar eax, 1
add eax, 0x3F800000
mov [retval], eax
}
return retval;
}
//! Saturates positive to zero.
inline_ float fsat(float f)
{
udword y = (udword&)f & ~((sdword&)f >>31);
return (float&)y;
}
//! Computes 1.0f / sqrtf(x).
inline_ float frsqrt(float f)
{
float x = f * 0.5f;
udword y = 0x5f3759df - ((udword&)f >> 1);
// Iteration...
(float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) );
// Result
return (float&)y;
}
//! Computes 1.0f / sqrtf(x). Comes from NVIDIA.
inline_ float InvSqrt(const float& x)
{
udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1;
float y = *(float*)&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)
{
long i;
float x2, y;
const float threehalfs = 1.5f;
x2 = number * 0.5f;
y = number;
i = * (long *) &y;
i = 0x5f3759df - (i >> 1);
y = * (float *) &i;
y = y * (threehalfs - (x2 * y * y));
return y;
}
//! TO BE DOCUMENTED
inline_ float fsqrt(float f)
{
udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000;
// Iteration...?
// (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f;
// Result
return (float&)y;
}
//! Returns the float ranged espilon value.
inline_ float fepsilon(float f)
{
udword b = (udword&)f & 0xff800000;
udword a = b | 0x00000001;
(float&)a -= (float&)b;
// Result
return (float&)a;
}
//! 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
mov wTemp, ax
fldcw wTemp
}
}
}
}
*/
//! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON)
inline_ float ComputeFloatEpsilon()
{
float f = 1.0f;
((udword&)f)^=1;
return f - 1.0f; // You can check it's the same as FLT_EPSILON
}
inline_ bool IsFloatZero(float x, float epsilon=1e-6f)
{
return x*x < epsilon;
}
#define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0
#define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0
#define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0
#define FCMOVNB_ST0 _asm _emit 0xdb _asm _emit 0xc0
#define FCOMI_ST1 _asm _emit 0xdb _asm _emit 0xf1
#define FCOMIP_ST1 _asm _emit 0xdf _asm _emit 0xf1
#define FCMOVB_ST1 _asm _emit 0xda _asm _emit 0xc1
#define FCMOVNB_ST1 _asm _emit 0xdb _asm _emit 0xc1
#define FCOMI_ST2 _asm _emit 0xdb _asm _emit 0xf2
#define FCOMIP_ST2 _asm _emit 0xdf _asm _emit 0xf2
#define FCMOVB_ST2 _asm _emit 0xda _asm _emit 0xc2
#define FCMOVNB_ST2 _asm _emit 0xdb _asm _emit 0xc2
#define FCOMI_ST3 _asm _emit 0xdb _asm _emit 0xf3
#define FCOMIP_ST3 _asm _emit 0xdf _asm _emit 0xf3
#define FCMOVB_ST3 _asm _emit 0xda _asm _emit 0xc3
#define FCMOVNB_ST3 _asm _emit 0xdb _asm _emit 0xc3
#define FCOMI_ST4 _asm _emit 0xdb _asm _emit 0xf4
#define FCOMIP_ST4 _asm _emit 0xdf _asm _emit 0xf4
#define FCMOVB_ST4 _asm _emit 0xda _asm _emit 0xc4
#define FCMOVNB_ST4 _asm _emit 0xdb _asm _emit 0xc4
#define FCOMI_ST5 _asm _emit 0xdb _asm _emit 0xf5
#define FCOMIP_ST5 _asm _emit 0xdf _asm _emit 0xf5
#define FCMOVB_ST5 _asm _emit 0xda _asm _emit 0xc5
#define FCMOVNB_ST5 _asm _emit 0xdb _asm _emit 0xc5
#define FCOMI_ST6 _asm _emit 0xdb _asm _emit 0xf6
#define FCOMIP_ST6 _asm _emit 0xdf _asm _emit 0xf6
#define FCMOVB_ST6 _asm _emit 0xda _asm _emit 0xc6
#define FCMOVNB_ST6 _asm _emit 0xdb _asm _emit 0xc6
#define FCOMI_ST7 _asm _emit 0xdb _asm _emit 0xf7
#define FCOMIP_ST7 _asm _emit 0xdf _asm _emit 0xf7
#define FCMOVB_ST7 _asm _emit 0xda _asm _emit 0xc7
#define FCMOVNB_ST7 _asm _emit 0xdb _asm _emit 0xc7
//! A global function to find MAX(a,b) using FCOMI/FCMOV
inline_ float FCMax2(float a, float b)
{
float Res;
_asm fld [a]
_asm fld [b]
FCOMI_ST1
FCMOVB_ST1
_asm fstp [Res]
_asm fcomp
return Res;
}
//! A global function to find MIN(a,b) using FCOMI/FCMOV
inline_ float FCMin2(float a, float b)
{
float Res;
_asm fld [a]
_asm fld [b]
FCOMI_ST1
FCMOVNB_ST1
_asm fstp [Res]
_asm fcomp
return Res;
}
//! A global function to find MAX(a,b,c) using FCOMI/FCMOV
inline_ float FCMax3(float a, float b, float c)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
FCOMI_ST1
FCMOVB_ST1
FCOMI_ST2
FCMOVB_ST2
_asm fstp [Res]
_asm fcompp
return Res;
}
//! A global function to find MIN(a,b,c) using FCOMI/FCMOV
inline_ float FCMin3(float a, float b, float c)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
FCOMI_ST1
FCMOVNB_ST1
FCOMI_ST2
FCMOVNB_ST2
_asm fstp [Res]
_asm fcompp
return Res;
}
//! A global function to find MAX(a,b,c,d) using FCOMI/FCMOV
inline_ float FCMax4(float a, float b, float c, float d)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
_asm fld [d]
FCOMI_ST1
FCMOVB_ST1
FCOMI_ST2
FCMOVB_ST2
FCOMI_ST3
FCMOVB_ST3
_asm fstp [Res]
_asm fcompp
_asm fcomp
return Res;
}
//! A global function to find MIN(a,b,c,d) using FCOMI/FCMOV
inline_ float FCMin4(float a, float b, float c, float d)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
_asm fld [d]
FCOMI_ST1
FCMOVNB_ST1
FCOMI_ST2
FCMOVNB_ST2
FCOMI_ST3
FCMOVNB_ST3
_asm fstp [Res]
_asm fcompp
_asm fcomp
return Res;
}
inline_ int ConvertToSortable(float f)
{
int& Fi = (int&)f;
int Fmask = (Fi>>31);
Fi ^= Fmask;
Fmask &= ~(1<<31);
Fi -= Fmask;
return Fi;
}
inline_ udword EncodeFloat(const float val)
{
// We may need to check on -0 and 0
// But it should make no practical difference.
udword ir = IR(val);
if(ir & 0x80000000) //negative?
ir = ~ir;//reverse sequence of negative numbers
else
ir |= 0x80000000; // flip sign
return ir;
}
inline_ float DecodeFloat(udword ir)
{
udword rv;
if(ir & 0x80000000) //positive?
rv = ir & ~0x80000000; //flip sign
else
rv = ~ir; //undo reversal
return FR(rv);
}
enum FPUMode
{
FPU_FLOOR = 0,
FPU_CEIL = 1,
FPU_BEST = 2,
FPU_FORCE_DWORD = 0x7fffffff
};
FUNCTION ICECORE_API FPUMode GetFPUMode();
FUNCTION ICECORE_API void SaveFPU();
FUNCTION ICECORE_API void RestoreFPU();
FUNCTION ICECORE_API void SetFPUFloorMode();
FUNCTION ICECORE_API void SetFPUCeilMode();
FUNCTION ICECORE_API void SetFPUBestMode();
FUNCTION ICECORE_API void SetFPUPrecision24();
FUNCTION ICECORE_API void SetFPUPrecision53();
FUNCTION ICECORE_API void SetFPUPrecision64();
FUNCTION ICECORE_API void SetFPURoundingChop();
FUNCTION ICECORE_API void SetFPURoundingUp();
FUNCTION ICECORE_API void SetFPURoundingDown();
FUNCTION ICECORE_API void SetFPURoundingNear();
FUNCTION ICECORE_API int intChop(const float& f);
FUNCTION ICECORE_API int intFloor(const float& f);
FUNCTION ICECORE_API int intCeil(const float& f);
inline_ sdword MyFloor(float f)
{
return (sdword)f - (IR(f)>>31);
}
class ICECORE_API FPUGuard
{
public:
FPUGuard();
~FPUGuard();
private:
uword mControlWord;
};
#endif // ICEFPU_H

View File

@@ -1,87 +1,87 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for homogeneous points.
* \file IceHPoint.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Homogeneous point.
*
* Use it:
* - for clipping in homogeneous space (standard way)
* - to differentiate between points (w=1) and vectors (w=0).
* - in some cases you can also use it instead of Point for padding reasons.
*
* \class HPoint
* \author Pierre Terdiman
* \version 1.0
* \warning No cross-product in 4D.
* \warning HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Point Mul = HPoint * Matrix3x3;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Point HPoint::operator*(const Matrix3x3& mat) const
{
return Point(
x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0],
x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1],
x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] );
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// HPoint Mul = HPoint * Matrix4x4;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HPoint HPoint::operator*(const Matrix4x4& mat) const
{
return HPoint(
x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0],
x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1],
x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2],
x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// HPoint *= Matrix4x4
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HPoint& HPoint::operator*=(const Matrix4x4& mat)
{
float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0];
float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1];
float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2];
float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3];
x = xp; y = yp; z = zp; w = wp;
return *this;
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for homogeneous points.
* \file IceHPoint.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Homogeneous point.
*
* Use it:
* - for clipping in homogeneous space (standard way)
* - to differentiate between points (w=1) and vectors (w=0).
* - in some cases you can also use it instead of Point for padding reasons.
*
* \class HPoint
* \author Pierre Terdiman
* \version 1.0
* \warning No cross-product in 4D.
* \warning HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Point Mul = HPoint * Matrix3x3;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Point HPoint::operator*(const Matrix3x3& mat) const
{
return Point(
x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0],
x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1],
x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] );
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// HPoint Mul = HPoint * Matrix4x4;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HPoint HPoint::operator*(const Matrix4x4& mat) const
{
return HPoint(
x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0],
x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1],
x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2],
x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// HPoint *= Matrix4x4
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HPoint& HPoint::operator*=(const Matrix4x4& mat)
{
float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0];
float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1];
float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2];
float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3];
x = xp; y = yp; z = zp; w = wp;
return *this;
}

View File

@@ -1,173 +1,173 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for homogeneous points.
* \file IceHPoint.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEHPOINT_H__
#define __ICEHPOINT_H__
class ICEMATHS_API HPoint : public Point
{
public:
//! Empty constructor
inline_ HPoint() {}
//! Constructor from floats
inline_ HPoint(float _x, float _y, float _z, float _w=0.0f) : Point(_x, _y, _z), w(_w) {}
//! Constructor from array
inline_ HPoint(const float f[4]) : Point(f), w(f[3]) {}
//! Constructor from a Point
inline_ HPoint(const Point& p, float _w=0.0f) : Point(p), w(_w) {}
//! Destructor
inline_ ~HPoint() {}
//! Clear the point
inline_ HPoint& Zero() { x = y = z = w = 0.0f; return *this; }
//! Assignment from values
inline_ HPoint& Set(float _x, float _y, float _z, float _w ) { x = _x; y = _y; z = _z; w = _w; return *this; }
//! Assignment from array
inline_ HPoint& Set(const float f[4]) { x = f[_X]; y = f[_Y]; z = f[_Z]; w = f[_W]; return *this; }
//! Assignment from another h-point
inline_ HPoint& Set(const HPoint& src) { x = src.x; y = src.y; z = src.z; w = src.w; return *this; }
//! Add a vector
inline_ HPoint& Add(float _x, float _y, float _z, float _w ) { x += _x; y += _y; z += _z; w += _w; return *this; }
//! Add a vector
inline_ HPoint& Add(const float f[4]) { x += f[_X]; y += f[_Y]; z += f[_Z]; w += f[_W]; return *this; }
//! Subtract a vector
inline_ HPoint& Sub(float _x, float _y, float _z, float _w ) { x -= _x; y -= _y; z -= _z; w -= _w; return *this; }
//! Subtract a vector
inline_ HPoint& Sub(const float f[4]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; w -= f[_W]; return *this; }
//! Multiplies by a scalar
inline_ HPoint& Mul(float s) { x *= s; y *= s; z *= s; w *= s; return *this; }
//! Returns MIN(x, y, z, w);
float Min() const { return MIN(x, MIN(y, MIN(z, w))); }
//! Returns MAX(x, y, z, w);
float Max() const { return MAX(x, MAX(y, MAX(z, w))); }
//! Sets each element to be componentwise minimum
HPoint& Min(const HPoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w); return *this; }
//! Sets each element to be componentwise maximum
HPoint& Max(const HPoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w); return *this; }
//! Computes square magnitude
inline_ float SquareMagnitude() const { return x*x + y*y + z*z + w*w; }
//! Computes magnitude
inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z + w*w); }
//! Normalize the vector
inline_ HPoint& Normalize()
{
float M = Magnitude();
if(M)
{
M = 1.0f / M;
x *= M;
y *= M;
z *= M;
w *= M;
}
return *this;
}
// Arithmetic operators
//! Operator for HPoint Negate = - HPoint;
inline_ HPoint operator-() const { return HPoint(-x, -y, -z, -w); }
//! Operator for HPoint Plus = HPoint + HPoint;
inline_ HPoint operator+(const HPoint& p) const { return HPoint(x + p.x, y + p.y, z + p.z, w + p.w); }
//! Operator for HPoint Minus = HPoint - HPoint;
inline_ HPoint operator-(const HPoint& p) const { return HPoint(x - p.x, y - p.y, z - p.z, w - p.w); }
//! Operator for HPoint Mul = HPoint * HPoint;
inline_ HPoint operator*(const HPoint& p) const { return HPoint(x * p.x, y * p.y, z * p.z, w * p.w); }
//! Operator for HPoint Scale = HPoint * float;
inline_ HPoint operator*(float s) const { return HPoint(x * s, y * s, z * s, w * s); }
//! Operator for HPoint Scale = float * HPoint;
inline_ friend HPoint operator*(float s, const HPoint& p) { return HPoint(s * p.x, s * p.y, s * p.z, s * p.w); }
//! Operator for HPoint Div = HPoint / HPoint;
inline_ HPoint operator/(const HPoint& p) const { return HPoint(x / p.x, y / p.y, z / p.z, w / p.w); }
//! Operator for HPoint Scale = HPoint / float;
inline_ HPoint operator/(float s) const { s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s); }
//! Operator for HPoint Scale = float / HPoint;
inline_ friend HPoint operator/(float s, const HPoint& p) { return HPoint(s / p.x, s / p.y, s / p.z, s / p.w); }
//! Operator for float DotProd = HPoint | HPoint;
inline_ float operator|(const HPoint& p) const { return x*p.x + y*p.y + z*p.z + w*p.w; }
// No cross-product in 4D
//! Operator for HPoint += HPoint;
inline_ HPoint& operator+=(const HPoint& p) { x += p.x; y += p.y; z += p.z; w += p.w; return *this; }
//! Operator for HPoint += float;
inline_ HPoint& operator+=(float s) { x += s; y += s; z += s; w += s; return *this; }
//! Operator for HPoint -= HPoint;
inline_ HPoint& operator-=(const HPoint& p) { x -= p.x; y -= p.y; z -= p.z; w -= p.w; return *this; }
//! Operator for HPoint -= float;
inline_ HPoint& operator-=(float s) { x -= s; y -= s; z -= s; w -= s; return *this; }
//! Operator for HPoint *= HPoint;
inline_ HPoint& operator*=(const HPoint& p) { x *= p.x; y *= p.y; z *= p.z; w *= p.w; return *this; }
//! Operator for HPoint *= float;
inline_ HPoint& operator*=(float s) { x*=s; y*=s; z*=s; w*=s; return *this; }
//! Operator for HPoint /= HPoint;
inline_ HPoint& operator/=(const HPoint& p) { x /= p.x; y /= p.y; z /= p.z; w /= p.w; return *this; }
//! Operator for HPoint /= float;
inline_ HPoint& operator/=(float s) { s = 1.0f / s; x*=s; y*=s; z*=s; w*=s; return *this; }
// Arithmetic operators
//! Operator for Point Mul = HPoint * Matrix3x3;
Point operator*(const Matrix3x3& mat) const;
//! Operator for HPoint Mul = HPoint * Matrix4x4;
HPoint operator*(const Matrix4x4& mat) const;
// HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4
//! Operator for HPoint *= Matrix4x4
HPoint& operator*=(const Matrix4x4& mat);
// Logical operators
//! Operator for "if(HPoint==HPoint)"
inline_ bool operator==(const HPoint& p) const { return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w)); }
//! Operator for "if(HPoint!=HPoint)"
inline_ bool operator!=(const HPoint& p) const { return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w)); }
// Cast operators
//! Cast a HPoint to a Point. w is discarded.
inline_ operator Point() const { return Point(x, y, z); }
public:
float w;
};
#endif // __ICEHPOINT_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for homogeneous points.
* \file IceHPoint.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEHPOINT_H__
#define __ICEHPOINT_H__
class ICEMATHS_API HPoint : public Point
{
public:
//! Empty constructor
inline_ HPoint() {}
//! Constructor from floats
inline_ HPoint(float _x, float _y, float _z, float _w=0.0f) : Point(_x, _y, _z), w(_w) {}
//! Constructor from array
inline_ HPoint(const float f[4]) : Point(f), w(f[3]) {}
//! Constructor from a Point
inline_ HPoint(const Point& p, float _w=0.0f) : Point(p), w(_w) {}
//! Destructor
inline_ ~HPoint() {}
//! Clear the point
inline_ HPoint& Zero() { x = y = z = w = 0.0f; return *this; }
//! Assignment from values
inline_ HPoint& Set(float _x, float _y, float _z, float _w ) { x = _x; y = _y; z = _z; w = _w; return *this; }
//! Assignment from array
inline_ HPoint& Set(const float f[4]) { x = f[_X]; y = f[_Y]; z = f[_Z]; w = f[_W]; return *this; }
//! Assignment from another h-point
inline_ HPoint& Set(const HPoint& src) { x = src.x; y = src.y; z = src.z; w = src.w; return *this; }
//! Add a vector
inline_ HPoint& Add(float _x, float _y, float _z, float _w ) { x += _x; y += _y; z += _z; w += _w; return *this; }
//! Add a vector
inline_ HPoint& Add(const float f[4]) { x += f[_X]; y += f[_Y]; z += f[_Z]; w += f[_W]; return *this; }
//! Subtract a vector
inline_ HPoint& Sub(float _x, float _y, float _z, float _w ) { x -= _x; y -= _y; z -= _z; w -= _w; return *this; }
//! Subtract a vector
inline_ HPoint& Sub(const float f[4]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; w -= f[_W]; return *this; }
//! Multiplies by a scalar
inline_ HPoint& Mul(float s) { x *= s; y *= s; z *= s; w *= s; return *this; }
//! Returns MIN(x, y, z, w);
float Min() const { return MIN(x, MIN(y, MIN(z, w))); }
//! Returns MAX(x, y, z, w);
float Max() const { return MAX(x, MAX(y, MAX(z, w))); }
//! Sets each element to be componentwise minimum
HPoint& Min(const HPoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w); return *this; }
//! Sets each element to be componentwise maximum
HPoint& Max(const HPoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w); return *this; }
//! Computes square magnitude
inline_ float SquareMagnitude() const { return x*x + y*y + z*z + w*w; }
//! Computes magnitude
inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z + w*w); }
//! Normalize the vector
inline_ HPoint& Normalize()
{
float M = Magnitude();
if(M)
{
M = 1.0f / M;
x *= M;
y *= M;
z *= M;
w *= M;
}
return *this;
}
// Arithmetic operators
//! Operator for HPoint Negate = - HPoint;
inline_ HPoint operator-() const { return HPoint(-x, -y, -z, -w); }
//! Operator for HPoint Plus = HPoint + HPoint;
inline_ HPoint operator+(const HPoint& p) const { return HPoint(x + p.x, y + p.y, z + p.z, w + p.w); }
//! Operator for HPoint Minus = HPoint - HPoint;
inline_ HPoint operator-(const HPoint& p) const { return HPoint(x - p.x, y - p.y, z - p.z, w - p.w); }
//! Operator for HPoint Mul = HPoint * HPoint;
inline_ HPoint operator*(const HPoint& p) const { return HPoint(x * p.x, y * p.y, z * p.z, w * p.w); }
//! Operator for HPoint Scale = HPoint * float;
inline_ HPoint operator*(float s) const { return HPoint(x * s, y * s, z * s, w * s); }
//! Operator for HPoint Scale = float * HPoint;
inline_ friend HPoint operator*(float s, const HPoint& p) { return HPoint(s * p.x, s * p.y, s * p.z, s * p.w); }
//! Operator for HPoint Div = HPoint / HPoint;
inline_ HPoint operator/(const HPoint& p) const { return HPoint(x / p.x, y / p.y, z / p.z, w / p.w); }
//! Operator for HPoint Scale = HPoint / float;
inline_ HPoint operator/(float s) const { s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s); }
//! Operator for HPoint Scale = float / HPoint;
inline_ friend HPoint operator/(float s, const HPoint& p) { return HPoint(s / p.x, s / p.y, s / p.z, s / p.w); }
//! Operator for float DotProd = HPoint | HPoint;
inline_ float operator|(const HPoint& p) const { return x*p.x + y*p.y + z*p.z + w*p.w; }
// No cross-product in 4D
//! Operator for HPoint += HPoint;
inline_ HPoint& operator+=(const HPoint& p) { x += p.x; y += p.y; z += p.z; w += p.w; return *this; }
//! Operator for HPoint += float;
inline_ HPoint& operator+=(float s) { x += s; y += s; z += s; w += s; return *this; }
//! Operator for HPoint -= HPoint;
inline_ HPoint& operator-=(const HPoint& p) { x -= p.x; y -= p.y; z -= p.z; w -= p.w; return *this; }
//! Operator for HPoint -= float;
inline_ HPoint& operator-=(float s) { x -= s; y -= s; z -= s; w -= s; return *this; }
//! Operator for HPoint *= HPoint;
inline_ HPoint& operator*=(const HPoint& p) { x *= p.x; y *= p.y; z *= p.z; w *= p.w; return *this; }
//! Operator for HPoint *= float;
inline_ HPoint& operator*=(float s) { x*=s; y*=s; z*=s; w*=s; return *this; }
//! Operator for HPoint /= HPoint;
inline_ HPoint& operator/=(const HPoint& p) { x /= p.x; y /= p.y; z /= p.z; w /= p.w; return *this; }
//! Operator for HPoint /= float;
inline_ HPoint& operator/=(float s) { s = 1.0f / s; x*=s; y*=s; z*=s; w*=s; return *this; }
// Arithmetic operators
//! Operator for Point Mul = HPoint * Matrix3x3;
Point operator*(const Matrix3x3& mat) const;
//! Operator for HPoint Mul = HPoint * Matrix4x4;
HPoint operator*(const Matrix4x4& mat) const;
// HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4
//! Operator for HPoint *= Matrix4x4
HPoint& operator*=(const Matrix4x4& mat);
// Logical operators
//! Operator for "if(HPoint==HPoint)"
inline_ bool operator==(const HPoint& p) const { return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w)); }
//! Operator for "if(HPoint!=HPoint)"
inline_ bool operator!=(const HPoint& p) const { return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w)); }
// Cast operators
//! Cast a HPoint to a Point. w is discarded.
inline_ operator Point() const { return Point(x, y, z); }
public:
float w;
};
#endif // __ICEHPOINT_H__

View File

@@ -1,78 +1,78 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains hashing code.
* \file IceHashing.h
* \author Pierre Terdiman
* \date May, 08, 1999
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEHASHING_H
#define ICEHASHING_H
#define HashSize(n) ((udword)1<<(n))
#define HashMask(n) (HashSize(n)-1)
ICECORE_API udword Hash(const char* str);
ICECORE_API udword Hash(ubyte* k, udword length, udword initval);
// Bob Jenkin's hash
inline_ unsigned int Hash32Bits_0(unsigned int key)
{
key += (key << 12);
key ^= (key >> 22);
key += (key << 4);
key ^= (key >> 9);
key += (key << 10);
key ^= (key >> 2);
key += (key << 7);
key ^= (key >> 12);
return key;
}
// Thomas Wang's hash
inline_ int Hash32Bits_1(int key)
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
}
// Thomas Wang's hash
inline_ __int64 Hash64Bits_0(__int64 key)
{
key += ~(key << 32);
key ^= (key >> 22);
key += ~(key << 13);
key ^= (key >> 8);
key += (key << 3);
key ^= (key >> 15);
key += ~(key << 27);
key ^= (key >> 31);
return key;
}
inline_ __int64 Hash64Bits_1(__int64 key)
{
__int64 c1 = 0x6e5ea73858134343L;
__int64 c2 = 0xb34e8f99a2ec9ef5L;
key ^= ((c1 ^ key) >> 32);
key *= c1;
key ^= ((c2 ^ key) >> 31);
key *= c2;
key ^= ((c1 ^ key) >> 32);
return key;
}
inline_ udword Hash(udword id0, udword id1)
{
return Hash32Bits_1( (id0&0xffff)|(id1<<16) );
}
#endif // ICEHASHING_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains hashing code.
* \file IceHashing.h
* \author Pierre Terdiman
* \date May, 08, 1999
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEHASHING_H
#define ICEHASHING_H
#define HashSize(n) ((udword)1<<(n))
#define HashMask(n) (HashSize(n)-1)
ICECORE_API udword Hash(const char* str);
ICECORE_API udword Hash(ubyte* k, udword length, udword initval);
// Bob Jenkin's hash
inline_ unsigned int Hash32Bits_0(unsigned int key)
{
key += (key << 12);
key ^= (key >> 22);
key += (key << 4);
key ^= (key >> 9);
key += (key << 10);
key ^= (key >> 2);
key += (key << 7);
key ^= (key >> 12);
return key;
}
// Thomas Wang's hash
inline_ int Hash32Bits_1(int key)
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
}
// Thomas Wang's hash
inline_ __int64 Hash64Bits_0(__int64 key)
{
key += ~(key << 32);
key ^= (key >> 22);
key += ~(key << 13);
key ^= (key >> 8);
key += (key << 3);
key ^= (key >> 15);
key += ~(key << 27);
key ^= (key >> 31);
return key;
}
inline_ __int64 Hash64Bits_1(__int64 key)
{
__int64 c1 = 0x6e5ea73858134343L;
__int64 c2 = 0xb34e8f99a2ec9ef5L;
key ^= ((c1 ^ key) >> 32);
key *= c1;
key ^= ((c2 ^ key) >> 31);
key *= c2;
key ^= ((c1 ^ key) >> 32);
return key;
}
inline_ udword Hash(udword id0, udword id1)
{
return Hash32Bits_1( (id0&0xffff)|(id1<<16) );
}
#endif // ICEHASHING_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,84 +1,84 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a handy indexed triangle class.
* \file IceIndexedTriangle.h
* \author Pierre Terdiman
* \date January, 17, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEINDEXEDTRIANGLE_H__
#define __ICEINDEXEDTRIANGLE_H__
// Forward declarations
enum CubeIndex;
// An indexed triangle class.
class ICEMATHS_API IndexedTriangle
{
public:
//! Constructor
inline_ IndexedTriangle() {}
//! Constructor
inline_ IndexedTriangle(udword r0, udword r1, udword r2) { mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; }
//! Copy constructor
inline_ IndexedTriangle(const IndexedTriangle& triangle)
{
mVRef[0] = triangle.mVRef[0];
mVRef[1] = triangle.mVRef[1];
mVRef[2] = triangle.mVRef[2];
}
//! Destructor
inline_ ~IndexedTriangle() {}
//! Vertex-references
udword mVRef[3];
// Methods
void Flip();
float Area(const Point* verts) const;
float Perimeter(const Point* verts) const;
float Compacity(const Point* verts) const;
void Normal(const Point* verts, Point& normal) const;
void DenormalizedNormal(const Point* verts, Point& normal) const;
void Center(const Point* verts, Point& center) const;
void CenteredNormal(const Point* verts, Point& normal) const;
void RandomPoint(const Point* verts, Point& random) const;
bool IsVisible(const Point* verts, const Point& source) const;
bool BackfaceCulling(const Point* verts, const Point& source) const;
float ComputeOcclusionPotential(const Point* verts, const Point& view) const;
bool ReplaceVertex(udword oldref, udword newref);
bool IsDegenerate() const;
bool HasVertex(udword ref) const;
bool HasVertex(udword ref, udword* index) const;
ubyte FindEdge(udword vref0, udword vref1) const;
udword OppositeVertex(udword vref0, udword vref1) const;
inline_ udword OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; }
void GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const;
float MinEdgeLength(const Point* verts) const;
float MaxEdgeLength(const Point* verts) const;
void ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx=null) const;
float Angle(const IndexedTriangle& tri, const Point* verts) const;
inline_ Plane PlaneEquation(const Point* verts) const { return Plane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); }
bool Equal(const IndexedTriangle& tri) const;
CubeIndex ComputeCubeIndex(const Point* verts) const;
};
#endif // __ICEINDEXEDTRIANGLE_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a handy indexed triangle class.
* \file IceIndexedTriangle.h
* \author Pierre Terdiman
* \date January, 17, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEINDEXEDTRIANGLE_H__
#define __ICEINDEXEDTRIANGLE_H__
// Forward declarations
enum CubeIndex;
// An indexed triangle class.
class ICEMATHS_API IndexedTriangle
{
public:
//! Constructor
inline_ IndexedTriangle() {}
//! Constructor
inline_ IndexedTriangle(udword r0, udword r1, udword r2) { mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; }
//! Copy constructor
inline_ IndexedTriangle(const IndexedTriangle& triangle)
{
mVRef[0] = triangle.mVRef[0];
mVRef[1] = triangle.mVRef[1];
mVRef[2] = triangle.mVRef[2];
}
//! Destructor
inline_ ~IndexedTriangle() {}
//! Vertex-references
udword mVRef[3];
// Methods
void Flip();
float Area(const Point* verts) const;
float Perimeter(const Point* verts) const;
float Compacity(const Point* verts) const;
void Normal(const Point* verts, Point& normal) const;
void DenormalizedNormal(const Point* verts, Point& normal) const;
void Center(const Point* verts, Point& center) const;
void CenteredNormal(const Point* verts, Point& normal) const;
void RandomPoint(const Point* verts, Point& random) const;
bool IsVisible(const Point* verts, const Point& source) const;
bool BackfaceCulling(const Point* verts, const Point& source) const;
float ComputeOcclusionPotential(const Point* verts, const Point& view) const;
bool ReplaceVertex(udword oldref, udword newref);
bool IsDegenerate() const;
bool HasVertex(udword ref) const;
bool HasVertex(udword ref, udword* index) const;
ubyte FindEdge(udword vref0, udword vref1) const;
udword OppositeVertex(udword vref0, udword vref1) const;
inline_ udword OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; }
void GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const;
float MinEdgeLength(const Point* verts) const;
float MaxEdgeLength(const Point* verts) const;
void ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx=null) const;
float Angle(const IndexedTriangle& tri, const Point* verts) const;
inline_ Plane PlaneEquation(const Point* verts) const { return Plane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); }
bool Equal(const IndexedTriangle& tri) const;
CubeIndex ComputeCubeIndex(const Point* verts) const;
};
#endif // __ICEINDEXEDTRIANGLE_H__

View File

@@ -1,91 +1,91 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for line-swept spheres.
* \file IceLSS.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICELSS_H__
#define __ICELSS_H__
class ICEMATHS_API LSS : public Segment
{
public:
//! Constructor
inline_ LSS() {}
//! Constructor
inline_ LSS(const Segment& seg, float radius) : Segment(seg), mRadius(radius) {}
//! Destructor
inline_ ~LSS() {}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes an OBB surrounding the LSS.
* \param box [out] the OBB
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ComputeOBB(OBB& box);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if a point is contained within the LSS.
* \param pt [in] the point to test
* \return true if inside the LSS
* \warning point and LSS must be in same space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ bool Contains(const Point& pt) const { return SquareDistance(pt) <= mRadius*mRadius; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if a sphere is contained within the LSS.
* \param sphere [in] the sphere to test
* \return true if inside the LSS
* \warning sphere and LSS must be in same space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ bool Contains(const Sphere& sphere)
{
float d = mRadius - sphere.mRadius;
if(d>=0.0f) return SquareDistance(sphere.mCenter) <= d*d;
else return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if an LSS is contained within the LSS.
* \param lss [in] the LSS to test
* \return true if inside the LSS
* \warning both LSS must be in same space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ bool Contains(const LSS& lss)
{
// We check the LSS contains the two spheres at the start and end of the sweep
return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius));
}
float mRadius; //!< Sphere radius
};
#endif // __ICELSS_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for line-swept spheres.
* \file IceLSS.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICELSS_H__
#define __ICELSS_H__
class ICEMATHS_API LSS : public Segment
{
public:
//! Constructor
inline_ LSS() {}
//! Constructor
inline_ LSS(const Segment& seg, float radius) : Segment(seg), mRadius(radius) {}
//! Destructor
inline_ ~LSS() {}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes an OBB surrounding the LSS.
* \param box [out] the OBB
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ComputeOBB(OBB& box);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if a point is contained within the LSS.
* \param pt [in] the point to test
* \return true if inside the LSS
* \warning point and LSS must be in same space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ bool Contains(const Point& pt) const { return SquareDistance(pt) <= mRadius*mRadius; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if a sphere is contained within the LSS.
* \param sphere [in] the sphere to test
* \return true if inside the LSS
* \warning sphere and LSS must be in same space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ bool Contains(const Sphere& sphere)
{
float d = mRadius - sphere.mRadius;
if(d>=0.0f) return SquareDistance(sphere.mCenter) <= d*d;
else return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if an LSS is contained within the LSS.
* \param lss [in] the LSS to test
* \return true if inside the LSS
* \warning both LSS must be in same space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ bool Contains(const LSS& lss)
{
// We check the LSS contains the two spheres at the start and end of the sweep
return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius));
}
float mRadius; //!< Sphere radius
};
#endif // __ICELSS_H__

View File

@@ -1,64 +1,64 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for 3x3 matrices.
* \file IceMatrix3x3.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 3x3 matrix.
* DirectX-compliant, ie row-column order, ie m[Row][Col].
* Same as:
* m11 m12 m13 first row.
* m21 m22 m23 second row.
* m31 m32 m33 third row.
* Stored in memory as m11 m12 m13 m21...
*
* Multiplication rules:
*
* [x'y'z'] = [xyz][M]
*
* x' = x*m11 + y*m21 + z*m31
* y' = x*m12 + y*m22 + z*m32
* z' = x*m13 + y*m23 + z*m33
*
* \class Matrix3x3
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
// Cast operator
Matrix3x3::operator Matrix4x4() const
{
return Matrix4x4(
m[0][0], m[0][1], m[0][2], 0.0f,
m[1][0], m[1][1], m[1][2], 0.0f,
m[2][0], m[2][1], m[2][2], 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for 3x3 matrices.
* \file IceMatrix3x3.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 3x3 matrix.
* DirectX-compliant, ie row-column order, ie m[Row][Col].
* Same as:
* m11 m12 m13 first row.
* m21 m22 m23 second row.
* m31 m32 m33 third row.
* Stored in memory as m11 m12 m13 m21...
*
* Multiplication rules:
*
* [x'y'z'] = [xyz][M]
*
* x' = x*m11 + y*m21 + z*m31
* y' = x*m12 + y*m22 + z*m32
* z' = x*m13 + y*m23 + z*m33
*
* \class Matrix3x3
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
// Cast operator
Matrix3x3::operator Matrix4x4() const
{
return Matrix4x4(
m[0][0], m[0][1], m[0][2], 0.0f,
m[1][0], m[1][1], m[1][2], 0.0f,
m[2][0], m[2][1], m[2][2], 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,152 +1,152 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for 4x4 matrices.
* \file IceMatrix4x4.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 4x4 matrix.
* DirectX-compliant, ie row-column order, ie m[Row][Col].
* Same as:
* m11 m12 m13 m14 first row.
* m21 m22 m23 m24 second row.
* m31 m32 m33 m34 third row.
* m41 m42 m43 m44 fourth row.
* Translation is (m41, m42, m43), (m14, m24, m34, m44) = (0, 0, 0, 1).
* Stored in memory as m11 m12 m13 m14 m21...
*
* Multiplication rules:
*
* [x'y'z'1] = [xyz1][M]
*
* x' = x*m11 + y*m21 + z*m31 + m41
* y' = x*m12 + y*m22 + z*m32 + m42
* z' = x*m13 + y*m23 + z*m33 + m43
* 1' = 0 + 0 + 0 + m44
*
* \class Matrix4x4
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Inverts a PR matrix. (which only contains a rotation and a translation)
* This is faster and less subject to FPU errors than the generic inversion code.
*
* \relates Matrix4x4
* \fn InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
* \param dest [out] destination matrix
* \param src [in] source matrix
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ICEMATHS_API void IceMaths::InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
{
dest.m[0][0] = src.m[0][0];
dest.m[1][0] = src.m[0][1];
dest.m[2][0] = src.m[0][2];
dest.m[3][0] = -(src.m[3][0]*src.m[0][0] + src.m[3][1]*src.m[0][1] + src.m[3][2]*src.m[0][2]);
dest.m[0][1] = src.m[1][0];
dest.m[1][1] = src.m[1][1];
dest.m[2][1] = src.m[1][2];
dest.m[3][1] = -(src.m[3][0]*src.m[1][0] + src.m[3][1]*src.m[1][1] + src.m[3][2]*src.m[1][2]);
dest.m[0][2] = src.m[2][0];
dest.m[1][2] = src.m[2][1];
dest.m[2][2] = src.m[2][2];
dest.m[3][2] = -(src.m[3][0]*src.m[2][0] + src.m[3][1]*src.m[2][1] + src.m[3][2]*src.m[2][2]);
dest.m[0][3] = 0.0f;
dest.m[1][3] = 0.0f;
dest.m[2][3] = 0.0f;
dest.m[3][3] = 1.0f;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Compute the cofactor of the Matrix at a specified location
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Matrix4x4::CoFactor(udword row, udword col) const
{
return (( m[(row+1)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+3)&3][(col+3)&3] +
m[(row+1)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+3)&3][(col+1)&3] +
m[(row+1)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+3)&3][(col+2)&3])
- (m[(row+3)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+1)&3][(col+3)&3] +
m[(row+3)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+1)&3][(col+1)&3] +
m[(row+3)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+1)&3][(col+2)&3])) * ((row + col) & 1 ? -1.0f : +1.0f);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Compute the determinant of the Matrix
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Matrix4x4::Determinant() const
{
return m[0][0] * CoFactor(0, 0) +
m[0][1] * CoFactor(0, 1) +
m[0][2] * CoFactor(0, 2) +
m[0][3] * CoFactor(0, 3);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Compute the inverse of the matrix
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Matrix4x4& Matrix4x4::Invert()
{
float Det = Determinant();
Matrix4x4 Temp;
if(fabsf(Det) < MATRIX4X4_EPSILON)
return *this; // The matrix is not invertible! Singular case!
float IDet = 1.0f / Det;
Temp.m[0][0] = CoFactor(0,0) * IDet;
Temp.m[1][0] = CoFactor(0,1) * IDet;
Temp.m[2][0] = CoFactor(0,2) * IDet;
Temp.m[3][0] = CoFactor(0,3) * IDet;
Temp.m[0][1] = CoFactor(1,0) * IDet;
Temp.m[1][1] = CoFactor(1,1) * IDet;
Temp.m[2][1] = CoFactor(1,2) * IDet;
Temp.m[3][1] = CoFactor(1,3) * IDet;
Temp.m[0][2] = CoFactor(2,0) * IDet;
Temp.m[1][2] = CoFactor(2,1) * IDet;
Temp.m[2][2] = CoFactor(2,2) * IDet;
Temp.m[3][2] = CoFactor(2,3) * IDet;
Temp.m[0][3] = CoFactor(3,0) * IDet;
Temp.m[1][3] = CoFactor(3,1) * IDet;
Temp.m[2][3] = CoFactor(3,2) * IDet;
Temp.m[3][3] = CoFactor(3,3) * IDet;
*this = Temp;
return *this;
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for 4x4 matrices.
* \file IceMatrix4x4.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 4x4 matrix.
* DirectX-compliant, ie row-column order, ie m[Row][Col].
* Same as:
* m11 m12 m13 m14 first row.
* m21 m22 m23 m24 second row.
* m31 m32 m33 m34 third row.
* m41 m42 m43 m44 fourth row.
* Translation is (m41, m42, m43), (m14, m24, m34, m44) = (0, 0, 0, 1).
* Stored in memory as m11 m12 m13 m14 m21...
*
* Multiplication rules:
*
* [x'y'z'1] = [xyz1][M]
*
* x' = x*m11 + y*m21 + z*m31 + m41
* y' = x*m12 + y*m22 + z*m32 + m42
* z' = x*m13 + y*m23 + z*m33 + m43
* 1' = 0 + 0 + 0 + m44
*
* \class Matrix4x4
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Inverts a PR matrix. (which only contains a rotation and a translation)
* This is faster and less subject to FPU errors than the generic inversion code.
*
* \relates Matrix4x4
* \fn InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
* \param dest [out] destination matrix
* \param src [in] source matrix
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ICEMATHS_API void IceMaths::InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
{
dest.m[0][0] = src.m[0][0];
dest.m[1][0] = src.m[0][1];
dest.m[2][0] = src.m[0][2];
dest.m[3][0] = -(src.m[3][0]*src.m[0][0] + src.m[3][1]*src.m[0][1] + src.m[3][2]*src.m[0][2]);
dest.m[0][1] = src.m[1][0];
dest.m[1][1] = src.m[1][1];
dest.m[2][1] = src.m[1][2];
dest.m[3][1] = -(src.m[3][0]*src.m[1][0] + src.m[3][1]*src.m[1][1] + src.m[3][2]*src.m[1][2]);
dest.m[0][2] = src.m[2][0];
dest.m[1][2] = src.m[2][1];
dest.m[2][2] = src.m[2][2];
dest.m[3][2] = -(src.m[3][0]*src.m[2][0] + src.m[3][1]*src.m[2][1] + src.m[3][2]*src.m[2][2]);
dest.m[0][3] = 0.0f;
dest.m[1][3] = 0.0f;
dest.m[2][3] = 0.0f;
dest.m[3][3] = 1.0f;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Compute the cofactor of the Matrix at a specified location
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Matrix4x4::CoFactor(udword row, udword col) const
{
return (( m[(row+1)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+3)&3][(col+3)&3] +
m[(row+1)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+3)&3][(col+1)&3] +
m[(row+1)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+3)&3][(col+2)&3])
- (m[(row+3)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+1)&3][(col+3)&3] +
m[(row+3)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+1)&3][(col+1)&3] +
m[(row+3)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+1)&3][(col+2)&3])) * ((row + col) & 1 ? -1.0f : +1.0f);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Compute the determinant of the Matrix
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Matrix4x4::Determinant() const
{
return m[0][0] * CoFactor(0, 0) +
m[0][1] * CoFactor(0, 1) +
m[0][2] * CoFactor(0, 2) +
m[0][3] * CoFactor(0, 3);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Compute the inverse of the matrix
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Matrix4x4& Matrix4x4::Invert()
{
float Det = Determinant();
Matrix4x4 Temp;
if(fabsf(Det) < MATRIX4X4_EPSILON)
return *this; // The matrix is not invertible! Singular case!
float IDet = 1.0f / Det;
Temp.m[0][0] = CoFactor(0,0) * IDet;
Temp.m[1][0] = CoFactor(0,1) * IDet;
Temp.m[2][0] = CoFactor(0,2) * IDet;
Temp.m[3][0] = CoFactor(0,3) * IDet;
Temp.m[0][1] = CoFactor(1,0) * IDet;
Temp.m[1][1] = CoFactor(1,1) * IDet;
Temp.m[2][1] = CoFactor(1,2) * IDet;
Temp.m[3][1] = CoFactor(1,3) * IDet;
Temp.m[0][2] = CoFactor(2,0) * IDet;
Temp.m[1][2] = CoFactor(2,1) * IDet;
Temp.m[2][2] = CoFactor(2,2) * IDet;
Temp.m[3][2] = CoFactor(2,3) * IDet;
Temp.m[0][3] = CoFactor(3,0) * IDet;
Temp.m[1][3] = CoFactor(3,1) * IDet;
Temp.m[2][3] = CoFactor(3,2) * IDet;
Temp.m[3][3] = CoFactor(3,3) * IDet;
*this = Temp;
return *this;
}

View File

@@ -1,471 +1,471 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for 4x4 matrices.
* \file IceMatrix4x4.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEMATRIX4X4_H__
#define __ICEMATRIX4X4_H__
// Forward declarations
class PRS;
class PR;
#define MATRIX4X4_EPSILON (1.0e-7f)
class ICEMATHS_API Matrix4x4
{
// void LUBackwardSubstitution( sdword *indx, float* b );
// void LUDecomposition( sdword* indx, float* d );
public:
//! Empty constructor.
inline_ Matrix4x4() {}
//! Constructor from 16 values
inline_ Matrix4x4( float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33)
{
m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
}
//! Copy constructor
inline_ Matrix4x4(const Matrix4x4& mat) { CopyMemory(m, &mat.m, 16*sizeof(float)); }
//! Destructor.
inline_ ~Matrix4x4() {}
//! Assign values (rotation only)
inline_ Matrix4x4& Set( float m00, float m01, float m02,
float m10, float m11, float m12,
float m20, float m21, float m22)
{
m[0][0] = m00; m[0][1] = m01; m[0][2] = m02;
m[1][0] = m10; m[1][1] = m11; m[1][2] = m12;
m[2][0] = m20; m[2][1] = m21; m[2][2] = m22;
return *this;
}
//! Assign values
inline_ Matrix4x4& Set( float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33)
{
m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
return *this;
}
//! Copy from a Matrix4x4
inline_ void Copy(const Matrix4x4& source) { CopyMemory(m, source.m, 16*sizeof(float)); }
// Row-column access
//! Returns a row.
inline_ void GetRow(const udword r, HPoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; p.w=m[r][3]; }
//! Returns a row.
inline_ void GetRow(const udword r, Point& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; }
//! Returns a row.
inline_ const HPoint& GetRow(const udword r) const { return *(const HPoint*)&m[r][0]; }
//! Returns a row.
inline_ HPoint& GetRow(const udword r) { return *(HPoint*)&m[r][0]; }
//! Sets a row.
inline_ void SetRow(const udword r, const HPoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]=p.w; }
//! Sets a row.
inline_ void SetRow(const udword r, const Point& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]= (r!=3) ? 0.0f : 1.0f; }
//! Returns a column.
inline_ void GetCol(const udword c, HPoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; p.w=m[3][c]; }
//! Returns a column.
inline_ void GetCol(const udword c, Point& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; }
//! Sets a column.
inline_ void SetCol(const udword c, const HPoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]=p.w; }
//! Sets a column.
inline_ void SetCol(const udword c, const Point& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]= (c!=3) ? 0.0f : 1.0f; }
// Translation
//! Returns the translation part of the matrix.
inline_ const HPoint& GetTrans() const { return GetRow(3); }
//! Gets the translation part of the matrix
inline_ void GetTrans(Point& p) const { p.x=m[3][0]; p.y=m[3][1]; p.z=m[3][2]; }
//! Sets the translation part of the matrix, from a Point.
inline_ void SetTrans(const Point& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; }
//! Sets the translation part of the matrix, from a HPoint.
inline_ void SetTrans(const HPoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; m[3][3]=p.w; }
//! Sets the translation part of the matrix, from floats.
inline_ void SetTrans(float tx, float ty, float tz) { m[3][0]=tx; m[3][1]=ty; m[3][2]=tz; }
// Scale
//! Sets the scale from a Point. The point is put on the diagonal.
inline_ void SetScale(const Point& p) { m[0][0]=p.x; m[1][1]=p.y; m[2][2]=p.z; }
//! Sets the scale from floats. Values are put on the diagonal.
inline_ void SetScale(float sx, float sy, float sz) { m[0][0]=sx; m[1][1]=sy; m[2][2]=sz; }
//! Scales from a Point. Each row is multiplied by a component.
void Scale(const Point& p)
{
m[0][0] *= p.x; m[1][0] *= p.y; m[2][0] *= p.z;
m[0][1] *= p.x; m[1][1] *= p.y; m[2][1] *= p.z;
m[0][2] *= p.x; m[1][2] *= p.y; m[2][2] *= p.z;
}
//! Scales from floats. Each row is multiplied by a value.
void Scale(float sx, float sy, float sz)
{
m[0][0] *= sx; m[1][0] *= sy; m[2][0] *= sz;
m[0][1] *= sx; m[1][1] *= sy; m[2][1] *= sz;
m[0][2] *= sx; m[1][2] *= sy; m[2][2] *= sz;
}
/*
//! Returns a row.
inline_ HPoint GetRow(const udword row) const { return mRow[row]; }
//! Sets a row.
inline_ Matrix4x4& SetRow(const udword row, const HPoint& p) { mRow[row] = p; return *this; }
//! Sets a row.
Matrix4x4& SetRow(const udword row, const Point& p)
{
m[row][0] = p.x;
m[row][1] = p.y;
m[row][2] = p.z;
m[row][3] = (row != 3) ? 0.0f : 1.0f;
return *this;
}
//! Returns a column.
HPoint GetCol(const udword col) const
{
HPoint Res;
Res.x = m[0][col];
Res.y = m[1][col];
Res.z = m[2][col];
Res.w = m[3][col];
return Res;
}
//! Sets a column.
Matrix4x4& SetCol(const udword col, const HPoint& p)
{
m[0][col] = p.x;
m[1][col] = p.y;
m[2][col] = p.z;
m[3][col] = p.w;
return *this;
}
//! Sets a column.
Matrix4x4& SetCol(const udword col, const Point& p)
{
m[0][col] = p.x;
m[1][col] = p.y;
m[2][col] = p.z;
m[3][col] = (col != 3) ? 0.0f : 1.0f;
return *this;
}
*/
//! Computes the trace. The trace is the sum of the 4 diagonal components.
inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2] + m[3][3]; }
//! Computes the trace of the upper 3x3 matrix.
inline_ float Trace3x3() const { return m[0][0] + m[1][1] + m[2][2]; }
//! Clears the matrix.
inline_ void Zero() { ZeroMemory(&m, sizeof(m)); }
//! Sets the identity matrix.
inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; }
//! Checks for identity
inline_ bool IsIdentity() const
{
if(IR(m[0][0])!=IEEE_1_0) return false;
if(IR(m[0][1])!=0) return false;
if(IR(m[0][2])!=0) return false;
if(IR(m[0][3])!=0) return false;
if(IR(m[1][0])!=0) return false;
if(IR(m[1][1])!=IEEE_1_0) return false;
if(IR(m[1][2])!=0) return false;
if(IR(m[1][3])!=0) return false;
if(IR(m[2][0])!=0) return false;
if(IR(m[2][1])!=0) return false;
if(IR(m[2][2])!=IEEE_1_0) return false;
if(IR(m[2][3])!=0) return false;
if(IR(m[3][0])!=0) return false;
if(IR(m[3][1])!=0) return false;
if(IR(m[3][2])!=0) return false;
if(IR(m[3][3])!=IEEE_1_0) return false;
return true;
}
//! Checks matrix validity
inline_ BOOL IsValid() const
{
for(udword j=0;j<4;j++)
{
for(udword i=0;i<4;i++)
{
if(!IsValidFloat(m[j][i])) return FALSE;
}
}
return TRUE;
}
//! Sets a rotation matrix around the X axis.
void RotX(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin; m[1][2] = Sin; }
//! Sets a rotation matrix around the Y axis.
void RotY(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin; m[0][2] = -Sin; }
//! Sets a rotation matrix around the Z axis.
void RotZ(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin; m[0][1] = Sin; }
//! Makes a rotation matrix about an arbitrary axis
Matrix4x4& Rot(float angle, Point& p1, Point& p2);
//! Transposes the matrix.
void Transpose()
{
IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]);
IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]);
IR(m[3][0]) ^= IR(m[0][3]); IR(m[0][3]) ^= IR(m[3][0]); IR(m[3][0]) ^= IR(m[0][3]);
IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]);
IR(m[1][3]) ^= IR(m[3][1]); IR(m[3][1]) ^= IR(m[1][3]); IR(m[1][3]) ^= IR(m[3][1]);
IR(m[2][3]) ^= IR(m[3][2]); IR(m[3][2]) ^= IR(m[2][3]); IR(m[2][3]) ^= IR(m[3][2]);
}
//! Computes a cofactor. Used for matrix inversion.
float CoFactor(udword row, udword col) const;
//! Computes the determinant of the matrix.
float Determinant() const;
//! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted.
Matrix4x4& Invert();
// Matrix& ComputeAxisMatrix(Point& axis, float angle);
// Cast operators
//! Casts a Matrix4x4 to a Matrix3x3.
inline_ operator Matrix3x3() const
{
return Matrix3x3(
m[0][0], m[0][1], m[0][2],
m[1][0], m[1][1], m[1][2],
m[2][0], m[2][1], m[2][2]);
}
//! Casts a Matrix4x4 to a Quat.
operator Quat() const;
//! Casts a Matrix4x4 to a PR.
operator PR() const;
// Arithmetic operators
//! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4;
inline_ Matrix4x4 operator+(const Matrix4x4& mat) const
{
return Matrix4x4(
m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3],
m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3],
m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3],
m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]);
}
//! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4;
inline_ Matrix4x4 operator-(const Matrix4x4& mat) const
{
return Matrix4x4(
m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3],
m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3],
m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3],
m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]);
}
//! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4;
inline_ Matrix4x4 operator*(const Matrix4x4& mat) const
{
return Matrix4x4(
m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0],
m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1],
m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2],
m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3],
m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0],
m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1],
m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2],
m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3],
m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0],
m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1],
m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2],
m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3],
m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0],
m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1],
m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2],
m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]);
}
//! Operator for HPoint Mul = Matrix4x4 * HPoint;
inline_ HPoint operator*(const HPoint& v) const { return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); }
//! Operator for Point Mul = Matrix4x4 * Point;
inline_ Point operator*(const Point& v) const
{
return Point( m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3],
m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3],
m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3] );
}
//! Operator for Matrix4x4 Scale = Matrix4x4 * float;
inline_ Matrix4x4 operator*(float s) const
{
return Matrix4x4(
m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s,
m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s,
m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s,
m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s);
}
//! Operator for Matrix4x4 Scale = float * Matrix4x4;
inline_ friend Matrix4x4 operator*(float s, const Matrix4x4& mat)
{
return Matrix4x4(
s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], s*mat.m[0][3],
s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], s*mat.m[1][3],
s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2], s*mat.m[2][3],
s*mat.m[3][0], s*mat.m[3][1], s*mat.m[3][2], s*mat.m[3][3]);
}
//! Operator for Matrix4x4 Div = Matrix4x4 / float;
inline_ Matrix4x4 operator/(float s) const
{
if(s) s = 1.0f / s;
return Matrix4x4(
m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s,
m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s,
m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s,
m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s);
}
//! Operator for Matrix4x4 Div = float / Matrix4x4;
inline_ friend Matrix4x4 operator/(float s, const Matrix4x4& mat)
{
return Matrix4x4(
s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], s/mat.m[0][3],
s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], s/mat.m[1][3],
s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2], s/mat.m[2][3],
s/mat.m[3][0], s/mat.m[3][1], s/mat.m[3][2], s/mat.m[3][3]);
}
//! Operator for Matrix4x4 += Matrix4x4;
inline_ Matrix4x4& operator+=(const Matrix4x4& mat)
{
m[0][0]+=mat.m[0][0]; m[0][1]+=mat.m[0][1]; m[0][2]+=mat.m[0][2]; m[0][3]+=mat.m[0][3];
m[1][0]+=mat.m[1][0]; m[1][1]+=mat.m[1][1]; m[1][2]+=mat.m[1][2]; m[1][3]+=mat.m[1][3];
m[2][0]+=mat.m[2][0]; m[2][1]+=mat.m[2][1]; m[2][2]+=mat.m[2][2]; m[2][3]+=mat.m[2][3];
m[3][0]+=mat.m[3][0]; m[3][1]+=mat.m[3][1]; m[3][2]+=mat.m[3][2]; m[3][3]+=mat.m[3][3];
return *this;
}
//! Operator for Matrix4x4 -= Matrix4x4;
inline_ Matrix4x4& operator-=(const Matrix4x4& mat)
{
m[0][0]-=mat.m[0][0]; m[0][1]-=mat.m[0][1]; m[0][2]-=mat.m[0][2]; m[0][3]-=mat.m[0][3];
m[1][0]-=mat.m[1][0]; m[1][1]-=mat.m[1][1]; m[1][2]-=mat.m[1][2]; m[1][3]-=mat.m[1][3];
m[2][0]-=mat.m[2][0]; m[2][1]-=mat.m[2][1]; m[2][2]-=mat.m[2][2]; m[2][3]-=mat.m[2][3];
m[3][0]-=mat.m[3][0]; m[3][1]-=mat.m[3][1]; m[3][2]-=mat.m[3][2]; m[3][3]-=mat.m[3][3];
return *this;
}
//! Operator for Matrix4x4 *= Matrix4x4;
Matrix4x4& operator*=(const Matrix4x4& mat)
{
HPoint TempRow;
GetRow(0, TempRow);
m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
GetRow(1, TempRow);
m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
GetRow(2, TempRow);
m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
GetRow(3, TempRow);
m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
return *this;
}
//! Operator for Matrix4x4 *= float;
inline_ Matrix4x4& operator*=(float s)
{
m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s;
m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s;
m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s;
m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s;
return *this;
}
//! Operator for Matrix4x4 /= float;
inline_ Matrix4x4& operator/=(float s)
{
if(s) s = 1.0f / s;
m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s;
m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s;
m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s;
m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s;
return *this;
}
inline_ const HPoint& operator[](int row) const { return *(const HPoint*)&m[row][0]; }
inline_ HPoint& operator[](int row) { return *(HPoint*)&m[row][0]; }
public:
float m[4][4];
};
//! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix
inline_ void TransformPoint4x3(Point& dest, const Point& source, const Matrix4x4& rot)
{
dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
}
//! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix
inline_ void TransformPoint3x3(Point& dest, const Point& source, const Matrix4x4& rot)
{
dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
}
ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src);
#endif // __ICEMATRIX4X4_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for 4x4 matrices.
* \file IceMatrix4x4.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEMATRIX4X4_H__
#define __ICEMATRIX4X4_H__
// Forward declarations
class PRS;
class PR;
#define MATRIX4X4_EPSILON (1.0e-7f)
class ICEMATHS_API Matrix4x4
{
// void LUBackwardSubstitution( sdword *indx, float* b );
// void LUDecomposition( sdword* indx, float* d );
public:
//! Empty constructor.
inline_ Matrix4x4() {}
//! Constructor from 16 values
inline_ Matrix4x4( float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33)
{
m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
}
//! Copy constructor
inline_ Matrix4x4(const Matrix4x4& mat) { CopyMemory(m, &mat.m, 16*sizeof(float)); }
//! Destructor.
inline_ ~Matrix4x4() {}
//! Assign values (rotation only)
inline_ Matrix4x4& Set( float m00, float m01, float m02,
float m10, float m11, float m12,
float m20, float m21, float m22)
{
m[0][0] = m00; m[0][1] = m01; m[0][2] = m02;
m[1][0] = m10; m[1][1] = m11; m[1][2] = m12;
m[2][0] = m20; m[2][1] = m21; m[2][2] = m22;
return *this;
}
//! Assign values
inline_ Matrix4x4& Set( float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33)
{
m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
return *this;
}
//! Copy from a Matrix4x4
inline_ void Copy(const Matrix4x4& source) { CopyMemory(m, source.m, 16*sizeof(float)); }
// Row-column access
//! Returns a row.
inline_ void GetRow(const udword r, HPoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; p.w=m[r][3]; }
//! Returns a row.
inline_ void GetRow(const udword r, Point& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; }
//! Returns a row.
inline_ const HPoint& GetRow(const udword r) const { return *(const HPoint*)&m[r][0]; }
//! Returns a row.
inline_ HPoint& GetRow(const udword r) { return *(HPoint*)&m[r][0]; }
//! Sets a row.
inline_ void SetRow(const udword r, const HPoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]=p.w; }
//! Sets a row.
inline_ void SetRow(const udword r, const Point& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]= (r!=3) ? 0.0f : 1.0f; }
//! Returns a column.
inline_ void GetCol(const udword c, HPoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; p.w=m[3][c]; }
//! Returns a column.
inline_ void GetCol(const udword c, Point& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; }
//! Sets a column.
inline_ void SetCol(const udword c, const HPoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]=p.w; }
//! Sets a column.
inline_ void SetCol(const udword c, const Point& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]= (c!=3) ? 0.0f : 1.0f; }
// Translation
//! Returns the translation part of the matrix.
inline_ const HPoint& GetTrans() const { return GetRow(3); }
//! Gets the translation part of the matrix
inline_ void GetTrans(Point& p) const { p.x=m[3][0]; p.y=m[3][1]; p.z=m[3][2]; }
//! Sets the translation part of the matrix, from a Point.
inline_ void SetTrans(const Point& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; }
//! Sets the translation part of the matrix, from a HPoint.
inline_ void SetTrans(const HPoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; m[3][3]=p.w; }
//! Sets the translation part of the matrix, from floats.
inline_ void SetTrans(float tx, float ty, float tz) { m[3][0]=tx; m[3][1]=ty; m[3][2]=tz; }
// Scale
//! Sets the scale from a Point. The point is put on the diagonal.
inline_ void SetScale(const Point& p) { m[0][0]=p.x; m[1][1]=p.y; m[2][2]=p.z; }
//! Sets the scale from floats. Values are put on the diagonal.
inline_ void SetScale(float sx, float sy, float sz) { m[0][0]=sx; m[1][1]=sy; m[2][2]=sz; }
//! Scales from a Point. Each row is multiplied by a component.
void Scale(const Point& p)
{
m[0][0] *= p.x; m[1][0] *= p.y; m[2][0] *= p.z;
m[0][1] *= p.x; m[1][1] *= p.y; m[2][1] *= p.z;
m[0][2] *= p.x; m[1][2] *= p.y; m[2][2] *= p.z;
}
//! Scales from floats. Each row is multiplied by a value.
void Scale(float sx, float sy, float sz)
{
m[0][0] *= sx; m[1][0] *= sy; m[2][0] *= sz;
m[0][1] *= sx; m[1][1] *= sy; m[2][1] *= sz;
m[0][2] *= sx; m[1][2] *= sy; m[2][2] *= sz;
}
/*
//! Returns a row.
inline_ HPoint GetRow(const udword row) const { return mRow[row]; }
//! Sets a row.
inline_ Matrix4x4& SetRow(const udword row, const HPoint& p) { mRow[row] = p; return *this; }
//! Sets a row.
Matrix4x4& SetRow(const udword row, const Point& p)
{
m[row][0] = p.x;
m[row][1] = p.y;
m[row][2] = p.z;
m[row][3] = (row != 3) ? 0.0f : 1.0f;
return *this;
}
//! Returns a column.
HPoint GetCol(const udword col) const
{
HPoint Res;
Res.x = m[0][col];
Res.y = m[1][col];
Res.z = m[2][col];
Res.w = m[3][col];
return Res;
}
//! Sets a column.
Matrix4x4& SetCol(const udword col, const HPoint& p)
{
m[0][col] = p.x;
m[1][col] = p.y;
m[2][col] = p.z;
m[3][col] = p.w;
return *this;
}
//! Sets a column.
Matrix4x4& SetCol(const udword col, const Point& p)
{
m[0][col] = p.x;
m[1][col] = p.y;
m[2][col] = p.z;
m[3][col] = (col != 3) ? 0.0f : 1.0f;
return *this;
}
*/
//! Computes the trace. The trace is the sum of the 4 diagonal components.
inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2] + m[3][3]; }
//! Computes the trace of the upper 3x3 matrix.
inline_ float Trace3x3() const { return m[0][0] + m[1][1] + m[2][2]; }
//! Clears the matrix.
inline_ void Zero() { ZeroMemory(&m, sizeof(m)); }
//! Sets the identity matrix.
inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; }
//! Checks for identity
inline_ bool IsIdentity() const
{
if(IR(m[0][0])!=IEEE_1_0) return false;
if(IR(m[0][1])!=0) return false;
if(IR(m[0][2])!=0) return false;
if(IR(m[0][3])!=0) return false;
if(IR(m[1][0])!=0) return false;
if(IR(m[1][1])!=IEEE_1_0) return false;
if(IR(m[1][2])!=0) return false;
if(IR(m[1][3])!=0) return false;
if(IR(m[2][0])!=0) return false;
if(IR(m[2][1])!=0) return false;
if(IR(m[2][2])!=IEEE_1_0) return false;
if(IR(m[2][3])!=0) return false;
if(IR(m[3][0])!=0) return false;
if(IR(m[3][1])!=0) return false;
if(IR(m[3][2])!=0) return false;
if(IR(m[3][3])!=IEEE_1_0) return false;
return true;
}
//! Checks matrix validity
inline_ BOOL IsValid() const
{
for(udword j=0;j<4;j++)
{
for(udword i=0;i<4;i++)
{
if(!IsValidFloat(m[j][i])) return FALSE;
}
}
return TRUE;
}
//! Sets a rotation matrix around the X axis.
void RotX(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin; m[1][2] = Sin; }
//! Sets a rotation matrix around the Y axis.
void RotY(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin; m[0][2] = -Sin; }
//! Sets a rotation matrix around the Z axis.
void RotZ(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin; m[0][1] = Sin; }
//! Makes a rotation matrix about an arbitrary axis
Matrix4x4& Rot(float angle, Point& p1, Point& p2);
//! Transposes the matrix.
void Transpose()
{
IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]);
IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]);
IR(m[3][0]) ^= IR(m[0][3]); IR(m[0][3]) ^= IR(m[3][0]); IR(m[3][0]) ^= IR(m[0][3]);
IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]);
IR(m[1][3]) ^= IR(m[3][1]); IR(m[3][1]) ^= IR(m[1][3]); IR(m[1][3]) ^= IR(m[3][1]);
IR(m[2][3]) ^= IR(m[3][2]); IR(m[3][2]) ^= IR(m[2][3]); IR(m[2][3]) ^= IR(m[3][2]);
}
//! Computes a cofactor. Used for matrix inversion.
float CoFactor(udword row, udword col) const;
//! Computes the determinant of the matrix.
float Determinant() const;
//! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted.
Matrix4x4& Invert();
// Matrix& ComputeAxisMatrix(Point& axis, float angle);
// Cast operators
//! Casts a Matrix4x4 to a Matrix3x3.
inline_ operator Matrix3x3() const
{
return Matrix3x3(
m[0][0], m[0][1], m[0][2],
m[1][0], m[1][1], m[1][2],
m[2][0], m[2][1], m[2][2]);
}
//! Casts a Matrix4x4 to a Quat.
operator Quat() const;
//! Casts a Matrix4x4 to a PR.
operator PR() const;
// Arithmetic operators
//! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4;
inline_ Matrix4x4 operator+(const Matrix4x4& mat) const
{
return Matrix4x4(
m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3],
m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3],
m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3],
m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]);
}
//! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4;
inline_ Matrix4x4 operator-(const Matrix4x4& mat) const
{
return Matrix4x4(
m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3],
m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3],
m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3],
m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]);
}
//! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4;
inline_ Matrix4x4 operator*(const Matrix4x4& mat) const
{
return Matrix4x4(
m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0],
m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1],
m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2],
m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3],
m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0],
m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1],
m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2],
m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3],
m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0],
m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1],
m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2],
m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3],
m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0],
m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1],
m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2],
m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]);
}
//! Operator for HPoint Mul = Matrix4x4 * HPoint;
inline_ HPoint operator*(const HPoint& v) const { return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); }
//! Operator for Point Mul = Matrix4x4 * Point;
inline_ Point operator*(const Point& v) const
{
return Point( m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3],
m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3],
m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3] );
}
//! Operator for Matrix4x4 Scale = Matrix4x4 * float;
inline_ Matrix4x4 operator*(float s) const
{
return Matrix4x4(
m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s,
m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s,
m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s,
m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s);
}
//! Operator for Matrix4x4 Scale = float * Matrix4x4;
inline_ friend Matrix4x4 operator*(float s, const Matrix4x4& mat)
{
return Matrix4x4(
s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], s*mat.m[0][3],
s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], s*mat.m[1][3],
s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2], s*mat.m[2][3],
s*mat.m[3][0], s*mat.m[3][1], s*mat.m[3][2], s*mat.m[3][3]);
}
//! Operator for Matrix4x4 Div = Matrix4x4 / float;
inline_ Matrix4x4 operator/(float s) const
{
if(s) s = 1.0f / s;
return Matrix4x4(
m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s,
m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s,
m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s,
m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s);
}
//! Operator for Matrix4x4 Div = float / Matrix4x4;
inline_ friend Matrix4x4 operator/(float s, const Matrix4x4& mat)
{
return Matrix4x4(
s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], s/mat.m[0][3],
s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], s/mat.m[1][3],
s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2], s/mat.m[2][3],
s/mat.m[3][0], s/mat.m[3][1], s/mat.m[3][2], s/mat.m[3][3]);
}
//! Operator for Matrix4x4 += Matrix4x4;
inline_ Matrix4x4& operator+=(const Matrix4x4& mat)
{
m[0][0]+=mat.m[0][0]; m[0][1]+=mat.m[0][1]; m[0][2]+=mat.m[0][2]; m[0][3]+=mat.m[0][3];
m[1][0]+=mat.m[1][0]; m[1][1]+=mat.m[1][1]; m[1][2]+=mat.m[1][2]; m[1][3]+=mat.m[1][3];
m[2][0]+=mat.m[2][0]; m[2][1]+=mat.m[2][1]; m[2][2]+=mat.m[2][2]; m[2][3]+=mat.m[2][3];
m[3][0]+=mat.m[3][0]; m[3][1]+=mat.m[3][1]; m[3][2]+=mat.m[3][2]; m[3][3]+=mat.m[3][3];
return *this;
}
//! Operator for Matrix4x4 -= Matrix4x4;
inline_ Matrix4x4& operator-=(const Matrix4x4& mat)
{
m[0][0]-=mat.m[0][0]; m[0][1]-=mat.m[0][1]; m[0][2]-=mat.m[0][2]; m[0][3]-=mat.m[0][3];
m[1][0]-=mat.m[1][0]; m[1][1]-=mat.m[1][1]; m[1][2]-=mat.m[1][2]; m[1][3]-=mat.m[1][3];
m[2][0]-=mat.m[2][0]; m[2][1]-=mat.m[2][1]; m[2][2]-=mat.m[2][2]; m[2][3]-=mat.m[2][3];
m[3][0]-=mat.m[3][0]; m[3][1]-=mat.m[3][1]; m[3][2]-=mat.m[3][2]; m[3][3]-=mat.m[3][3];
return *this;
}
//! Operator for Matrix4x4 *= Matrix4x4;
Matrix4x4& operator*=(const Matrix4x4& mat)
{
HPoint TempRow;
GetRow(0, TempRow);
m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
GetRow(1, TempRow);
m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
GetRow(2, TempRow);
m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
GetRow(3, TempRow);
m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
return *this;
}
//! Operator for Matrix4x4 *= float;
inline_ Matrix4x4& operator*=(float s)
{
m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s;
m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s;
m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s;
m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s;
return *this;
}
//! Operator for Matrix4x4 /= float;
inline_ Matrix4x4& operator/=(float s)
{
if(s) s = 1.0f / s;
m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s;
m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s;
m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s;
m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s;
return *this;
}
inline_ const HPoint& operator[](int row) const { return *(const HPoint*)&m[row][0]; }
inline_ HPoint& operator[](int row) { return *(HPoint*)&m[row][0]; }
public:
float m[4][4];
};
//! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix
inline_ void TransformPoint4x3(Point& dest, const Point& source, const Matrix4x4& rot)
{
dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
}
//! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix
inline_ void TransformPoint3x3(Point& dest, const Point& source, const Matrix4x4& rot)
{
dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
}
ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src);
#endif // __ICEMATRIX4X4_H__

View File

@@ -1,180 +1,180 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains all memory macros.
* \file IceMemoryMacros.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEMEMORYMACROS_H
#define ICEMEMORYMACROS_H
#undef ZeroMemory
#undef CopyMemory
#undef MoveMemory
#undef FillMemory
//! Clears a buffer.
//! \param addr [in] buffer address
//! \param size [in] buffer length
//! \see FillMemory
//! \see StoreDwords
//! \see CopyMemory
//! \see MoveMemory
inline_ void ZeroMemory(void* addr, regsize size) { memset(addr, 0, size); }
//! Fills a buffer with a given byte.
//! \param addr [in] buffer address
//! \param size [in] buffer length
//! \param val [in] the byte value
//! \see StoreDwords
//! \see ZeroMemory
//! \see CopyMemory
//! \see MoveMemory
inline_ void FillMemory(void* dest, regsize size, ubyte val) { memset(dest, val, size); }
//! Fills a buffer with a given dword.
//! \param addr [in] buffer address
//! \param nb [in] number of dwords to write
//! \param value [in] the dword value
//! \see FillMemory
//! \see ZeroMemory
//! \see CopyMemory
//! \see MoveMemory
//! \warning writes nb*4 bytes !
inline_ void StoreDwords(udword* dest, udword nb, udword value)
{
// The asm code below **SHOULD** be equivalent to one of those C versions
// or the other if your compiled is good: (checked on VC++ 6.0)
//
// 1) while(nb--) *dest++ = value;
//
// 2) for(udword i=0;i<nb;i++) dest[i] = value;
//
_asm push eax
_asm push ecx
_asm push edi
_asm mov edi, dest
_asm mov ecx, nb
_asm mov eax, value
_asm rep stosd
_asm pop edi
_asm pop ecx
_asm pop eax
}
//! Copies a buffer.
//! \param addr [in] destination buffer address
//! \param addr [in] source buffer address
//! \param size [in] buffer length
//! \see ZeroMemory
//! \see FillMemory
//! \see StoreDwords
//! \see MoveMemory
inline_ void CopyMemory(void* dest, const void* src, regsize size) { memcpy(dest, src, size); }
//! Moves a buffer.
//! \param addr [in] destination buffer address
//! \param addr [in] source buffer address
//! \param size [in] buffer length
//! \see ZeroMemory
//! \see FillMemory
//! \see StoreDwords
//! \see CopyMemory
inline_ void MoveMemory(void* dest, const void* src, regsize size) { memmove(dest, src, size); }
//! Flexible buffer copy
//! \param src [in] source buffer address
//! \param dst [in] destination buffer address
//! \param nb_elem [in] number of elements to copy
//! \param elem_size [in] size of an element
//! \param stride [in] stride in bytes, including size of element
inline_ void FlexiCopy(const void* src, void* dst, udword nb_elem, regsize elem_size, udword stride)
{
ubyte* d = (ubyte*)dst;
const ubyte* s = (const ubyte*)src;
const ubyte* Last = s + stride*nb_elem;
while(s!=Last)
{
CopyMemory(d, s, elem_size);
d += elem_size;
s += stride;
}
}
//! Gives the size of current object. This avoids some mistakes (e.g. "sizeof(this)").
#define SIZEOFOBJECT sizeof(*this)
//! Clears current object. Laziness is my business! HANDLE WITH CARE. ### Removed, too dangerous, cleared too many v-tables
//#define CLEAROBJECT { memset(this, 0, SIZEOFOBJECT); }
// The two macros below are here for several reasons:
// - sometimes we write "delete x" instead of "delete []x" just because we don't pay attention. Using the macro forces you
// to think about what you're deleting, just because you have to write the macro's name (SINGLE or ARRAY).
// - always clearing the pointer afterwards prevents some double-deletion in various situations.
// - deleting null is a valid operation according to the standard, yet some lame memory managers don't like it. In sake of
// robustness, we avoid trying.
//! Deletes an instance of a class.
#define DELETESINGLE(x) if (x) { delete x; x = null; }
//! Deletes an array.
#define DELETEARRAY(x) if (x) { delete []x; x = null; }
//! Safe D3D-style release
#define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = null; }
//! Safe ICE-style release
#define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; }
#ifdef ICEERROR_H
//! Standard alloc checking. HANDLE WITH CARE. Relies on strict coding rules. Probably shouldn't be used outside of ICE.
#define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY);
#else
#define CHECKALLOC(x) if(!x) return false;
#endif
//! Standard allocation cycle
#define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr);
#define SAFE_ICE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = ICE_NEW(type)[count]; CHECKALLOC(ptr);
//! Don't use inline for alloca !!!
#ifdef WIN32
#define StackAlloc(x) _alloca(x)
#elif LINUX
#define StackAlloc(x) alloca(x)
#elif defined(__APPLE__)
#define StackAlloc(x) alloca(x)
#elif defined(_XBOX)
#define StackAlloc(x) _alloca(x)
#endif
#ifdef _DEBUG
// #define ICE_ALLOC_TMP(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #x, MEMORY_TEMP)
// #define ICE_ALLOC(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #x, MEMORY_PERSISTENT)
#define ICE_ALLOC_TMP(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, "(undefined)", MEMORY_TEMP)
#define ICE_ALLOC(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, "(undefined)", MEMORY_PERSISTENT)
#define ICE_ALLOC_TMP2(x, y) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #y, MEMORY_TEMP)
#define ICE_ALLOC2(x, y) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #y, MEMORY_PERSISTENT)
#else
#define ICE_ALLOC_TMP(x) GetAllocator()->malloc(x, MEMORY_TEMP)
#define ICE_ALLOC(x) GetAllocator()->malloc(x, MEMORY_PERSISTENT)
#endif
#define ICE_FREE(x) if(x) { GetAllocator()->free(x); x = null; }
#ifdef DONT_TRACK_MEMORY_LEAKS
#ifdef _DEBUG
#define ICE_NEW_TMP(x) new(__FILE__, __LINE__, #x, MEMORY_TEMP) x
#define ICE_NEW(x) new(__FILE__, __LINE__, #x, MEMORY_PERSISTENT) x
#else
#define ICE_NEW_TMP(x) new(MEMORY_TEMP) x
#define ICE_NEW(x) new(MEMORY_PERSISTENT) x
#endif
#else
#define ICE_NEW_TMP(x) new x
#define ICE_NEW(x) new x
#endif
#endif // ICEMEMORYMACROS_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains all memory macros.
* \file IceMemoryMacros.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEMEMORYMACROS_H
#define ICEMEMORYMACROS_H
#undef ZeroMemory
#undef CopyMemory
#undef MoveMemory
#undef FillMemory
//! Clears a buffer.
//! \param addr [in] buffer address
//! \param size [in] buffer length
//! \see FillMemory
//! \see StoreDwords
//! \see CopyMemory
//! \see MoveMemory
inline_ void ZeroMemory(void* addr, regsize size) { memset(addr, 0, size); }
//! Fills a buffer with a given byte.
//! \param addr [in] buffer address
//! \param size [in] buffer length
//! \param val [in] the byte value
//! \see StoreDwords
//! \see ZeroMemory
//! \see CopyMemory
//! \see MoveMemory
inline_ void FillMemory(void* dest, regsize size, ubyte val) { memset(dest, val, size); }
//! Fills a buffer with a given dword.
//! \param addr [in] buffer address
//! \param nb [in] number of dwords to write
//! \param value [in] the dword value
//! \see FillMemory
//! \see ZeroMemory
//! \see CopyMemory
//! \see MoveMemory
//! \warning writes nb*4 bytes !
inline_ void StoreDwords(udword* dest, udword nb, udword value)
{
// The asm code below **SHOULD** be equivalent to one of those C versions
// or the other if your compiled is good: (checked on VC++ 6.0)
//
// 1) while(nb--) *dest++ = value;
//
// 2) for(udword i=0;i<nb;i++) dest[i] = value;
//
_asm push eax
_asm push ecx
_asm push edi
_asm mov edi, dest
_asm mov ecx, nb
_asm mov eax, value
_asm rep stosd
_asm pop edi
_asm pop ecx
_asm pop eax
}
//! Copies a buffer.
//! \param addr [in] destination buffer address
//! \param addr [in] source buffer address
//! \param size [in] buffer length
//! \see ZeroMemory
//! \see FillMemory
//! \see StoreDwords
//! \see MoveMemory
inline_ void CopyMemory(void* dest, const void* src, regsize size) { memcpy(dest, src, size); }
//! Moves a buffer.
//! \param addr [in] destination buffer address
//! \param addr [in] source buffer address
//! \param size [in] buffer length
//! \see ZeroMemory
//! \see FillMemory
//! \see StoreDwords
//! \see CopyMemory
inline_ void MoveMemory(void* dest, const void* src, regsize size) { memmove(dest, src, size); }
//! Flexible buffer copy
//! \param src [in] source buffer address
//! \param dst [in] destination buffer address
//! \param nb_elem [in] number of elements to copy
//! \param elem_size [in] size of an element
//! \param stride [in] stride in bytes, including size of element
inline_ void FlexiCopy(const void* src, void* dst, udword nb_elem, regsize elem_size, udword stride)
{
ubyte* d = (ubyte*)dst;
const ubyte* s = (const ubyte*)src;
const ubyte* Last = s + stride*nb_elem;
while(s!=Last)
{
CopyMemory(d, s, elem_size);
d += elem_size;
s += stride;
}
}
//! Gives the size of current object. This avoids some mistakes (e.g. "sizeof(this)").
#define SIZEOFOBJECT sizeof(*this)
//! Clears current object. Laziness is my business! HANDLE WITH CARE. ### Removed, too dangerous, cleared too many v-tables
//#define CLEAROBJECT { memset(this, 0, SIZEOFOBJECT); }
// The two macros below are here for several reasons:
// - sometimes we write "delete x" instead of "delete []x" just because we don't pay attention. Using the macro forces you
// to think about what you're deleting, just because you have to write the macro's name (SINGLE or ARRAY).
// - always clearing the pointer afterwards prevents some double-deletion in various situations.
// - deleting null is a valid operation according to the standard, yet some lame memory managers don't like it. In sake of
// robustness, we avoid trying.
//! Deletes an instance of a class.
#define DELETESINGLE(x) if (x) { delete x; x = null; }
//! Deletes an array.
#define DELETEARRAY(x) if (x) { delete []x; x = null; }
//! Safe D3D-style release
#define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = null; }
//! Safe ICE-style release
#define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; }
#ifdef ICEERROR_H
//! Standard alloc checking. HANDLE WITH CARE. Relies on strict coding rules. Probably shouldn't be used outside of ICE.
#define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY);
#else
#define CHECKALLOC(x) if(!x) return false;
#endif
//! Standard allocation cycle
#define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr);
#define SAFE_ICE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = ICE_NEW(type)[count]; CHECKALLOC(ptr);
//! Don't use inline for alloca !!!
#ifdef WIN32
#define StackAlloc(x) _alloca(x)
#elif LINUX
#define StackAlloc(x) alloca(x)
#elif defined(__APPLE__)
#define StackAlloc(x) alloca(x)
#elif defined(_XBOX)
#define StackAlloc(x) _alloca(x)
#endif
#ifdef _DEBUG
// #define ICE_ALLOC_TMP(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #x, MEMORY_TEMP)
// #define ICE_ALLOC(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #x, MEMORY_PERSISTENT)
#define ICE_ALLOC_TMP(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, "(undefined)", MEMORY_TEMP)
#define ICE_ALLOC(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, "(undefined)", MEMORY_PERSISTENT)
#define ICE_ALLOC_TMP2(x, y) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #y, MEMORY_TEMP)
#define ICE_ALLOC2(x, y) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #y, MEMORY_PERSISTENT)
#else
#define ICE_ALLOC_TMP(x) GetAllocator()->malloc(x, MEMORY_TEMP)
#define ICE_ALLOC(x) GetAllocator()->malloc(x, MEMORY_PERSISTENT)
#endif
#define ICE_FREE(x) if(x) { GetAllocator()->free(x); x = null; }
#ifdef DONT_TRACK_MEMORY_LEAKS
#ifdef _DEBUG
#define ICE_NEW_TMP(x) new(__FILE__, __LINE__, #x, MEMORY_TEMP) x
#define ICE_NEW(x) new(__FILE__, __LINE__, #x, MEMORY_PERSISTENT) x
#else
#define ICE_NEW_TMP(x) new(MEMORY_TEMP) x
#define ICE_NEW(x) new(MEMORY_PERSISTENT) x
#endif
#else
#define ICE_NEW_TMP(x) new x
#define ICE_NEW(x) new x
#endif
#endif // ICEMEMORYMACROS_H

View File

@@ -1,339 +1,339 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains OBB-related code.
* \file IceOBB.cpp
* \author Pierre Terdiman
* \date January, 29, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* An Oriented Bounding Box (OBB).
* \class OBB
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if a point is contained within the OBB.
* \param p [in] the world point to test
* \return true if inside the OBB
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OBB::ContainsPoint(const Point& p) const
{
// Point in OBB test using lazy evaluation and early exits
// Translate to box space
Point RelPoint = p - mCenter;
// Point * mRot maps from box space to world space
// mRot * Point maps from world space to box space (what we need here)
float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z;
if(f >= mExtents.x || f <= -mExtents.x) return false;
f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z;
if(f >= mExtents.y || f <= -mExtents.y) return false;
f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z;
if(f >= mExtents.z || f <= -mExtents.z) return false;
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Builds an OBB from an AABB and a world transform.
* \param aabb [in] the aabb
* \param mat [in] the world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void OBB::Create(const AABB& aabb, const Matrix4x4& mat)
{
// Note: must be coherent with Rotate()
aabb.GetCenter(mCenter);
aabb.GetExtents(mExtents);
// Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity).
// So following what's done in Rotate:
// - x-form the center
mCenter *= mat;
// - combine rotation with identity, i.e. just use given matrix
mRot = mat;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the obb planes.
* \param planes [out] 6 box planes
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OBB::ComputePlanes(Plane* planes) const
{
// Checkings
if(!planes) return false;
Point Axis0 = mRot[0];
Point Axis1 = mRot[1];
Point Axis2 = mRot[2];
// Writes normals
planes[0].n = Axis0;
planes[1].n = -Axis0;
planes[2].n = Axis1;
planes[3].n = -Axis1;
planes[4].n = Axis2;
planes[5].n = -Axis2;
// Compute a point on each plane
Point p0 = mCenter + Axis0 * mExtents.x;
Point p1 = mCenter - Axis0 * mExtents.x;
Point p2 = mCenter + Axis1 * mExtents.y;
Point p3 = mCenter - Axis1 * mExtents.y;
Point p4 = mCenter + Axis2 * mExtents.z;
Point p5 = mCenter - Axis2 * mExtents.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 obb points.
* \param pts [out] 8 box points
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OBB::ComputePoints(Point* pts) const
{
// Checkings
if(!pts) return false;
Point Axis0 = mRot[0];
Point Axis1 = mRot[1];
Point Axis2 = mRot[2];
Axis0 *= mExtents.x;
Axis1 *= mExtents.y;
Axis2 *= mExtents.z;
// 7+------+6 0 = ---
// /| /| 1 = +--
// / | / | 2 = ++-
// / 4+---/--+5 3 = -+-
// 3+------+2 / y z 4 = --+
// | / | / | / 5 = +-+
// |/ |/ |/ 6 = +++
// 0+------+1 *---x 7 = -++
pts[0] = mCenter - Axis0 - Axis1 - Axis2;
pts[1] = mCenter + Axis0 - Axis1 - Axis2;
pts[2] = mCenter + Axis0 + Axis1 - Axis2;
pts[3] = mCenter - Axis0 + Axis1 - Axis2;
pts[4] = mCenter - Axis0 - Axis1 + Axis2;
pts[5] = mCenter + Axis0 - Axis1 + Axis2;
pts[6] = mCenter + Axis0 + Axis1 + Axis2;
pts[7] = mCenter - Axis0 + Axis1 + Axis2;
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes vertex normals.
* \param pts [out] 8 box points
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OBB::ComputeVertexNormals(Point* pts) const
{
static 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
};
if(!pts) return false;
const Point* VN = (const Point*)VertexNormals;
for(udword i=0;i<8;i++)
{
pts[i] = VN[i] * mRot;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns edges.
* \return 24 indices (12 edges) indexing the list returned by ComputePoints()
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const udword* OBB::GetEdges() const
{
static 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 local edge normals.
* \return edge normals in local space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const Point* OBB::GetLocalEdgeNormals() const
{
static 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;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns world edge normal
* \param edge_index [in] 0 <= edge index < 12
* \param world_normal [out] edge normal in world space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void OBB::ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const
{
ASSERT(edge_index<12);
world_normal = GetLocalEdgeNormals()[edge_index] * mRot;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes an LSS surrounding the OBB.
* \param lss [out] the LSS
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void OBB::ComputeLSS(LSS& lss) const
{
Point Axis0 = mRot[0];
Point Axis1 = mRot[1];
Point Axis2 = mRot[2];
switch(mExtents.LargestAxis())
{
case 0:
lss.mRadius = (mExtents.y + mExtents.z)*0.5f;
lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius);
lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius);
break;
case 1:
lss.mRadius = (mExtents.x + mExtents.z)*0.5f;
lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius);
lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius);
break;
case 2:
lss.mRadius = (mExtents.x + mExtents.y)*0.5f;
lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius);
lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius);
break;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks the OBB is inside another OBB.
* \param box [in] the other OBB
* \return TRUE if we're inside the other box
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL OBB::IsInside(const OBB& box) const
{
// Make a 4x4 from the box & inverse it
Matrix4x4 M0Inv;
{
Matrix4x4 M0 = box.mRot;
M0.SetTrans(box.mCenter);
InvertPRMatrix(M0Inv, M0);
}
// With our inversed 4x4, create box1 in space of box0
OBB _1in0;
Rotate(M0Inv, _1in0);
// This should cancel out box0's rotation, i.e. it's now an AABB.
// => Center(0,0,0), Rot(identity)
// The two boxes are in the same space so now we can compare them.
// Create the AABB of (box1 in space of box0)
const Matrix3x3& mtx = _1in0.mRot;
float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x;
if(f > _1in0.mCenter.x) return FALSE;
if(-f < _1in0.mCenter.x) return FALSE;
f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y;
if(f > _1in0.mCenter.y) return FALSE;
if(-f < _1in0.mCenter.y) return FALSE;
f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z;
if(f > _1in0.mCenter.z) return FALSE;
if(-f < _1in0.mCenter.z) return FALSE;
return TRUE;
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains OBB-related code.
* \file IceOBB.cpp
* \author Pierre Terdiman
* \date January, 29, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* An Oriented Bounding Box (OBB).
* \class OBB
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if a point is contained within the OBB.
* \param p [in] the world point to test
* \return true if inside the OBB
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OBB::ContainsPoint(const Point& p) const
{
// Point in OBB test using lazy evaluation and early exits
// Translate to box space
Point RelPoint = p - mCenter;
// Point * mRot maps from box space to world space
// mRot * Point maps from world space to box space (what we need here)
float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z;
if(f >= mExtents.x || f <= -mExtents.x) return false;
f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z;
if(f >= mExtents.y || f <= -mExtents.y) return false;
f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z;
if(f >= mExtents.z || f <= -mExtents.z) return false;
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Builds an OBB from an AABB and a world transform.
* \param aabb [in] the aabb
* \param mat [in] the world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void OBB::Create(const AABB& aabb, const Matrix4x4& mat)
{
// Note: must be coherent with Rotate()
aabb.GetCenter(mCenter);
aabb.GetExtents(mExtents);
// Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity).
// So following what's done in Rotate:
// - x-form the center
mCenter *= mat;
// - combine rotation with identity, i.e. just use given matrix
mRot = mat;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the obb planes.
* \param planes [out] 6 box planes
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OBB::ComputePlanes(Plane* planes) const
{
// Checkings
if(!planes) return false;
Point Axis0 = mRot[0];
Point Axis1 = mRot[1];
Point Axis2 = mRot[2];
// Writes normals
planes[0].n = Axis0;
planes[1].n = -Axis0;
planes[2].n = Axis1;
planes[3].n = -Axis1;
planes[4].n = Axis2;
planes[5].n = -Axis2;
// Compute a point on each plane
Point p0 = mCenter + Axis0 * mExtents.x;
Point p1 = mCenter - Axis0 * mExtents.x;
Point p2 = mCenter + Axis1 * mExtents.y;
Point p3 = mCenter - Axis1 * mExtents.y;
Point p4 = mCenter + Axis2 * mExtents.z;
Point p5 = mCenter - Axis2 * mExtents.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 obb points.
* \param pts [out] 8 box points
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OBB::ComputePoints(Point* pts) const
{
// Checkings
if(!pts) return false;
Point Axis0 = mRot[0];
Point Axis1 = mRot[1];
Point Axis2 = mRot[2];
Axis0 *= mExtents.x;
Axis1 *= mExtents.y;
Axis2 *= mExtents.z;
// 7+------+6 0 = ---
// /| /| 1 = +--
// / | / | 2 = ++-
// / 4+---/--+5 3 = -+-
// 3+------+2 / y z 4 = --+
// | / | / | / 5 = +-+
// |/ |/ |/ 6 = +++
// 0+------+1 *---x 7 = -++
pts[0] = mCenter - Axis0 - Axis1 - Axis2;
pts[1] = mCenter + Axis0 - Axis1 - Axis2;
pts[2] = mCenter + Axis0 + Axis1 - Axis2;
pts[3] = mCenter - Axis0 + Axis1 - Axis2;
pts[4] = mCenter - Axis0 - Axis1 + Axis2;
pts[5] = mCenter + Axis0 - Axis1 + Axis2;
pts[6] = mCenter + Axis0 + Axis1 + Axis2;
pts[7] = mCenter - Axis0 + Axis1 + Axis2;
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes vertex normals.
* \param pts [out] 8 box points
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OBB::ComputeVertexNormals(Point* pts) const
{
static 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
};
if(!pts) return false;
const Point* VN = (const Point*)VertexNormals;
for(udword i=0;i<8;i++)
{
pts[i] = VN[i] * mRot;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns edges.
* \return 24 indices (12 edges) indexing the list returned by ComputePoints()
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const udword* OBB::GetEdges() const
{
static 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 local edge normals.
* \return edge normals in local space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const Point* OBB::GetLocalEdgeNormals() const
{
static 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;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns world edge normal
* \param edge_index [in] 0 <= edge index < 12
* \param world_normal [out] edge normal in world space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void OBB::ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const
{
ASSERT(edge_index<12);
world_normal = GetLocalEdgeNormals()[edge_index] * mRot;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes an LSS surrounding the OBB.
* \param lss [out] the LSS
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void OBB::ComputeLSS(LSS& lss) const
{
Point Axis0 = mRot[0];
Point Axis1 = mRot[1];
Point Axis2 = mRot[2];
switch(mExtents.LargestAxis())
{
case 0:
lss.mRadius = (mExtents.y + mExtents.z)*0.5f;
lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius);
lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius);
break;
case 1:
lss.mRadius = (mExtents.x + mExtents.z)*0.5f;
lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius);
lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius);
break;
case 2:
lss.mRadius = (mExtents.x + mExtents.y)*0.5f;
lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius);
lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius);
break;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks the OBB is inside another OBB.
* \param box [in] the other OBB
* \return TRUE if we're inside the other box
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL OBB::IsInside(const OBB& box) const
{
// Make a 4x4 from the box & inverse it
Matrix4x4 M0Inv;
{
Matrix4x4 M0 = box.mRot;
M0.SetTrans(box.mCenter);
InvertPRMatrix(M0Inv, M0);
}
// With our inversed 4x4, create box1 in space of box0
OBB _1in0;
Rotate(M0Inv, _1in0);
// This should cancel out box0's rotation, i.e. it's now an AABB.
// => Center(0,0,0), Rot(identity)
// The two boxes are in the same space so now we can compare them.
// Create the AABB of (box1 in space of box0)
const Matrix3x3& mtx = _1in0.mRot;
float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x;
if(f > _1in0.mCenter.x) return FALSE;
if(-f < _1in0.mCenter.x) return FALSE;
f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y;
if(f > _1in0.mCenter.y) return FALSE;
if(-f < _1in0.mCenter.y) return FALSE;
f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z;
if(f > _1in0.mCenter.z) return FALSE;
if(-f < _1in0.mCenter.z) return FALSE;
return TRUE;
}

View File

@@ -1,193 +1,193 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains OBB-related code. (oriented bounding box)
* \file IceOBB.h
* \author Pierre Terdiman
* \date January, 13, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEOBB_H__
#define __ICEOBB_H__
// Forward declarations
class LSS;
class ICEMATHS_API OBB
{
public:
//! Constructor
inline_ OBB() {}
//! Constructor
inline_ OBB(const Point& center, const Point& extents, const Matrix3x3& rot) : mCenter(center), mExtents(extents), mRot(rot) {}
//! Destructor
inline_ ~OBB() {}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Setups an empty OBB.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetEmpty()
{
mCenter.Zero();
mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
mRot.Identity();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if a point is contained within the OBB.
* \param p [in] the world point to test
* \return true if inside the OBB
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ContainsPoint(const Point& p) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Builds an OBB from an AABB and a world transform.
* \param aabb [in] the aabb
* \param mat [in] the world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Create(const AABB& aabb, const Matrix4x4& mat);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Recomputes the OBB after an arbitrary transform by a 4x4 matrix.
* \param mtx [in] the transform matrix
* \param obb [out] the transformed OBB
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void Rotate(const Matrix4x4& mtx, OBB& obb) const
{
// The extents remain constant
obb.mExtents = mExtents;
// The center gets x-formed
obb.mCenter = mCenter * mtx;
// Combine rotations
obb.mRot = mRot * Matrix3x3(mtx);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks the OBB is valid.
* \return true if the box is valid
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL IsValid() const
{
// Consistency condition for (Center, Extents) boxes: Extents >= 0.0f
if(mExtents.x < 0.0f) return FALSE;
if(mExtents.y < 0.0f) return FALSE;
if(mExtents.z < 0.0f) return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the obb planes.
* \param planes [out] 6 box planes
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ComputePlanes(Plane* planes) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the obb points.
* \param pts [out] 8 box points
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ComputePoints(Point* pts) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes vertex normals.
* \param pts [out] 8 box points
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ComputeVertexNormals(Point* pts) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns edges.
* \return 24 indices (12 edges) indexing the list returned by ComputePoints()
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const udword* GetEdges() const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns local edge normals.
* \return edge normals in local space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const Point* GetLocalEdgeNormals() const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns world edge normal
* \param edge_index [in] 0 <= edge index < 12
* \param world_normal [out] edge normal in world space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes an LSS surrounding the OBB.
* \param lss [out] the LSS
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ComputeLSS(LSS& lss) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks the OBB is inside another OBB.
* \param box [in] the other OBB
* \return TRUE if we're inside the other box
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL IsInside(const OBB& box) const;
inline_ const Point& GetCenter() const { return mCenter; }
inline_ const Point& GetExtents() const { return mExtents; }
inline_ const Matrix3x3& GetRot() const { return mRot; }
inline_ void GetRotatedExtents(Matrix3x3& extents) const
{
extents = mRot;
extents.Scale(mExtents);
}
Point mCenter; //!< B for Box
Point mExtents; //!< B for Bounding
Matrix3x3 mRot; //!< O for Oriented
// Orientation is stored in row-major format,
// i.e. rows = eigen vectors of the covariance matrix
};
#endif // __ICEOBB_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains OBB-related code. (oriented bounding box)
* \file IceOBB.h
* \author Pierre Terdiman
* \date January, 13, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEOBB_H__
#define __ICEOBB_H__
// Forward declarations
class LSS;
class ICEMATHS_API OBB
{
public:
//! Constructor
inline_ OBB() {}
//! Constructor
inline_ OBB(const Point& center, const Point& extents, const Matrix3x3& rot) : mCenter(center), mExtents(extents), mRot(rot) {}
//! Destructor
inline_ ~OBB() {}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Setups an empty OBB.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetEmpty()
{
mCenter.Zero();
mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
mRot.Identity();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Tests if a point is contained within the OBB.
* \param p [in] the world point to test
* \return true if inside the OBB
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ContainsPoint(const Point& p) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Builds an OBB from an AABB and a world transform.
* \param aabb [in] the aabb
* \param mat [in] the world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Create(const AABB& aabb, const Matrix4x4& mat);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Recomputes the OBB after an arbitrary transform by a 4x4 matrix.
* \param mtx [in] the transform matrix
* \param obb [out] the transformed OBB
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void Rotate(const Matrix4x4& mtx, OBB& obb) const
{
// The extents remain constant
obb.mExtents = mExtents;
// The center gets x-formed
obb.mCenter = mCenter * mtx;
// Combine rotations
obb.mRot = mRot * Matrix3x3(mtx);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks the OBB is valid.
* \return true if the box is valid
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL IsValid() const
{
// Consistency condition for (Center, Extents) boxes: Extents >= 0.0f
if(mExtents.x < 0.0f) return FALSE;
if(mExtents.y < 0.0f) return FALSE;
if(mExtents.z < 0.0f) return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the obb planes.
* \param planes [out] 6 box planes
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ComputePlanes(Plane* planes) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the obb points.
* \param pts [out] 8 box points
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ComputePoints(Point* pts) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes vertex normals.
* \param pts [out] 8 box points
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ComputeVertexNormals(Point* pts) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns edges.
* \return 24 indices (12 edges) indexing the list returned by ComputePoints()
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const udword* GetEdges() const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns local edge normals.
* \return edge normals in local space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const Point* GetLocalEdgeNormals() const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns world edge normal
* \param edge_index [in] 0 <= edge index < 12
* \param world_normal [out] edge normal in world space
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes an LSS surrounding the OBB.
* \param lss [out] the LSS
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ComputeLSS(LSS& lss) const;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks the OBB is inside another OBB.
* \param box [in] the other OBB
* \return TRUE if we're inside the other box
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL IsInside(const OBB& box) const;
inline_ const Point& GetCenter() const { return mCenter; }
inline_ const Point& GetExtents() const { return mExtents; }
inline_ const Matrix3x3& GetRot() const { return mRot; }
inline_ void GetRotatedExtents(Matrix3x3& extents) const
{
extents = mRot;
extents.Scale(mExtents);
}
Point mCenter; //!< B for Box
Point mExtents; //!< B for Bounding
Matrix3x3 mRot; //!< O for Oriented
// Orientation is stored in row-major format,
// i.e. rows = eigen vectors of the covariance matrix
};
#endif // __ICEOBB_H__

View File

@@ -1,61 +1,61 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a simple pair class.
* \file IcePairs.h
* \author Pierre Terdiman
* \date January, 13, 2003
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEPAIRS_H__
#define __ICEPAIRS_H__
//! A generic couple structure
struct ICECORE_API Pair
{
inline_ Pair() {}
inline_ Pair(udword i0, udword i1) : id0(i0), id1(i1) {}
udword id0; //!< First index of the pair
udword id1; //!< Second index of the pair
};
class ICECORE_API Pairs : private Container
{
public:
// Constructor / Destructor
Pairs() {}
~Pairs() {}
inline_ udword GetNbPairs() const { return GetNbEntries()>>1; }
inline_ const Pair* GetPairs() const { return (const Pair*)GetEntries(); }
inline_ const Pair* GetPair(udword i) const { return (const Pair*)&GetEntries()[i+i]; }
inline_ BOOL HasPairs() const { return IsNotEmpty(); }
inline_ void ResetPairs() { Reset(); }
inline_ void DeleteLastPair() { DeleteLastEntry(); DeleteLastEntry(); }
inline_ void AddPair(const Pair& p) { Add(p.id0).Add(p.id1); }
inline_ void AddPair(udword id0, udword id1) { Add(id0).Add(id1); }
};
#endif // __ICEPAIRS_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a simple pair class.
* \file IcePairs.h
* \author Pierre Terdiman
* \date January, 13, 2003
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEPAIRS_H__
#define __ICEPAIRS_H__
//! A generic couple structure
struct ICECORE_API Pair
{
inline_ Pair() {}
inline_ Pair(udword i0, udword i1) : id0(i0), id1(i1) {}
udword id0; //!< First index of the pair
udword id1; //!< Second index of the pair
};
class ICECORE_API Pairs : private Container
{
public:
// Constructor / Destructor
Pairs() {}
~Pairs() {}
inline_ udword GetNbPairs() const { return GetNbEntries()>>1; }
inline_ const Pair* GetPairs() const { return (const Pair*)GetEntries(); }
inline_ const Pair* GetPair(udword i) const { return (const Pair*)&GetEntries()[i+i]; }
inline_ BOOL HasPairs() const { return IsNotEmpty(); }
inline_ void ResetPairs() { Reset(); }
inline_ void DeleteLastPair() { DeleteLastEntry(); DeleteLastEntry(); }
inline_ void AddPair(const Pair& p) { Add(p.id0).Add(p.id1); }
inline_ void AddPair(udword id0, udword id1) { Add(id0).Add(id1); }
};
#endif // __ICEPAIRS_H__

View File

@@ -1,61 +1,61 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for planes.
* \file IcePlane.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Plane class.
* \class Plane
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the plane equation from 3 points.
* \param p0 [in] first point
* \param p1 [in] second point
* \param p2 [in] third point
* \return Self-reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Plane& Plane::Set(const Point& p0, const Point& p1, const Point& p2)
{
Point Edge0 = p1 - p0;
Point Edge1 = p2 - p0;
n = Edge0 ^ Edge1;
n.Normalize();
d = -(p0 | n);
return *this;
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for planes.
* \file IcePlane.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Plane class.
* \class Plane
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the plane equation from 3 points.
* \param p0 [in] first point
* \param p1 [in] second point
* \param p2 [in] third point
* \return Self-reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Plane& Plane::Set(const Point& p0, const Point& p1, const Point& p2)
{
Point Edge0 = p1 - p0;
Point Edge1 = p2 - p0;
n = Edge0 ^ Edge1;
n.Normalize();
d = -(p0 | n);
return *this;
}

View File

@@ -1,129 +1,129 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for planes.
* \file IcePlane.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEPLANE_H__
#define __ICEPLANE_H__
#define PLANE_EPSILON (1.0e-7f)
class ICEMATHS_API Plane
{
public:
//! Constructor
inline_ Plane() { }
//! Constructor from a normal and a distance
inline_ Plane(float nx, float ny, float nz, float d) { Set(nx, ny, nz, d); }
//! Constructor from a point on the plane and a normal
inline_ Plane(const Point& p, const Point& n) { Set(p, n); }
//! Constructor from three points
inline_ Plane(const Point& p0, const Point& p1, const Point& p2) { Set(p0, p1, p2); }
//! Constructor from a normal and a distance
inline_ Plane(const Point& _n, float _d) { n = _n; d = _d; }
//! Copy constructor
inline_ Plane(const Plane& plane) : n(plane.n), d(plane.d) { }
//! Destructor
inline_ ~Plane() { }
inline_ Plane& Zero() { n.Zero(); d = 0.0f; return *this; }
inline_ Plane& Set(float nx, float ny, float nz, float _d) { n.Set(nx, ny, nz); d = _d; return *this; }
inline_ Plane& Set(const Point& p, const Point& _n) { n = _n; d = - p | _n; return *this; }
Plane& Set(const Point& p0, const Point& p1, const Point& p2);
inline_ float Distance(const Point& p) const { return (p | n) + d; }
inline_ bool Belongs(const Point& p) const { return fabsf(Distance(p)) < PLANE_EPSILON; }
inline_ void Normalize()
{
float Denom = 1.0f / n.Magnitude();
n.x *= Denom;
n.y *= Denom;
n.z *= Denom;
d *= Denom;
}
public:
// Members
Point n; //!< The normal to the plane
float d; //!< The distance from the origin
// Cast operators
inline_ operator Point() const { return n; }
inline_ operator HPoint() const { return HPoint(n, d); }
// Arithmetic operators
inline_ Plane operator*(const Matrix4x4& m) const
{
// Old code from Irion. Kept for reference.
Plane Ret(*this);
return Ret *= m;
}
inline_ Plane& operator*=(const Matrix4x4& m)
{
// Old code from Irion. Kept for reference.
Point n2 = HPoint(n, 0.0f) * m;
d = -((Point) (HPoint( -d*n, 1.0f ) * m) | n2);
n = n2;
return *this;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster.
* \param transformed [out] transformed plane
* \param plane [in] source plane
* \param transform [in] transform matrix
* \warning the plane normal must be unit-length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void TransformPlane(Plane& transformed, const Plane& plane, const Matrix4x4& transform)
{
// Rotate the normal using the rotation part of the 4x4 matrix
transformed.n = plane.n * Matrix3x3(transform);
// Compute new d
transformed.d = plane.d - (Point(transform.GetTrans())|transformed.n);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster.
* \param plane [in/out] source plane (transformed on return)
* \param transform [in] transform matrix
* \warning the plane normal must be unit-length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void TransformPlane(Plane& plane, const Matrix4x4& transform)
{
// Rotate the normal using the rotation part of the 4x4 matrix
plane.n *= Matrix3x3(transform);
// Compute new d
plane.d -= Point(transform.GetTrans())|plane.n;
}
#endif // __ICEPLANE_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for planes.
* \file IcePlane.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEPLANE_H__
#define __ICEPLANE_H__
#define PLANE_EPSILON (1.0e-7f)
class ICEMATHS_API Plane
{
public:
//! Constructor
inline_ Plane() { }
//! Constructor from a normal and a distance
inline_ Plane(float nx, float ny, float nz, float d) { Set(nx, ny, nz, d); }
//! Constructor from a point on the plane and a normal
inline_ Plane(const Point& p, const Point& n) { Set(p, n); }
//! Constructor from three points
inline_ Plane(const Point& p0, const Point& p1, const Point& p2) { Set(p0, p1, p2); }
//! Constructor from a normal and a distance
inline_ Plane(const Point& _n, float _d) { n = _n; d = _d; }
//! Copy constructor
inline_ Plane(const Plane& plane) : n(plane.n), d(plane.d) { }
//! Destructor
inline_ ~Plane() { }
inline_ Plane& Zero() { n.Zero(); d = 0.0f; return *this; }
inline_ Plane& Set(float nx, float ny, float nz, float _d) { n.Set(nx, ny, nz); d = _d; return *this; }
inline_ Plane& Set(const Point& p, const Point& _n) { n = _n; d = - p | _n; return *this; }
Plane& Set(const Point& p0, const Point& p1, const Point& p2);
inline_ float Distance(const Point& p) const { return (p | n) + d; }
inline_ bool Belongs(const Point& p) const { return fabsf(Distance(p)) < PLANE_EPSILON; }
inline_ void Normalize()
{
float Denom = 1.0f / n.Magnitude();
n.x *= Denom;
n.y *= Denom;
n.z *= Denom;
d *= Denom;
}
public:
// Members
Point n; //!< The normal to the plane
float d; //!< The distance from the origin
// Cast operators
inline_ operator Point() const { return n; }
inline_ operator HPoint() const { return HPoint(n, d); }
// Arithmetic operators
inline_ Plane operator*(const Matrix4x4& m) const
{
// Old code from Irion. Kept for reference.
Plane Ret(*this);
return Ret *= m;
}
inline_ Plane& operator*=(const Matrix4x4& m)
{
// Old code from Irion. Kept for reference.
Point n2 = HPoint(n, 0.0f) * m;
d = -((Point) (HPoint( -d*n, 1.0f ) * m) | n2);
n = n2;
return *this;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster.
* \param transformed [out] transformed plane
* \param plane [in] source plane
* \param transform [in] transform matrix
* \warning the plane normal must be unit-length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void TransformPlane(Plane& transformed, const Plane& plane, const Matrix4x4& transform)
{
// Rotate the normal using the rotation part of the 4x4 matrix
transformed.n = plane.n * Matrix3x3(transform);
// Compute new d
transformed.d = plane.d - (Point(transform.GetTrans())|transformed.n);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster.
* \param plane [in/out] source plane (transformed on return)
* \param transform [in] transform matrix
* \warning the plane normal must be unit-length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void TransformPlane(Plane& plane, const Matrix4x4& transform)
{
// Rotate the normal using the rotation part of the 4x4 matrix
plane.n *= Matrix3x3(transform);
// Compute new d
plane.d -= Point(transform.GetTrans())|plane.n;
}
#endif // __ICEPLANE_H__

View File

@@ -1,209 +1,209 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for 3D vectors.
* \file IcePoint.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 3D point.
*
* The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3".
* So the choice was between "Point" and "Vector3", the first one looked better (IMHO).
*
* Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3;
* This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out:
*
* \code
* Point P0,P1 = some 3D points;
* Point Delta = P1 - P0;
* \endcode
*
* This compiles fine, although you should have written:
*
* \code
* Point P0,P1 = some 3D points;
* Vector3 Delta = P1 - P0;
* \endcode
*
* Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake
* from the author or something you don't get.
*
* One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors.
* But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work.
*
* Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store
* your model's vertices and in most cases, you really want to use Points to save ram.
*
* \class Point
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Creates a positive unit random vector.
* \return Self-reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Point& Point::PositiveUnitRandomVector()
{
x = UnitRandomFloat();
y = UnitRandomFloat();
z = UnitRandomFloat();
Normalize();
return *this;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Creates a unit random vector.
* \return Self-reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Point& Point::UnitRandomVector()
{
x = UnitRandomFloat() - 0.5f;
y = UnitRandomFloat() - 0.5f;
z = UnitRandomFloat() - 0.5f;
Normalize();
return *this;
}
// Cast operator
// WARNING: not inlined
Point::operator HPoint() const { return HPoint(x, y, z, 0.0f); }
Point& Point::Refract(const Point& eye, const Point& n, float refractindex, Point& refracted)
{
// Point EyePt = eye position
// Point p = current vertex
// Point n = vertex normal
// Point rv = refracted vector
// Eye vector - doesn't need to be normalized
Point Env;
Env.x = eye.x - x;
Env.y = eye.y - y;
Env.z = eye.z - z;
float NDotE = n|Env;
float NDotN = n|n;
NDotE /= refractindex;
// Refracted vector
refracted = n*NDotE - Env*NDotN;
return *this;
}
Point& Point::ProjectToPlane(const Plane& p)
{
*this-= (p.d + (*this|p.n))*p.n;
return *this;
}
void Point::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const
{
projected = HPoint(x, y, z, 1.0f) * mat;
projected.w = 1.0f / projected.w;
projected.x*=projected.w;
projected.y*=projected.w;
projected.z*=projected.w;
projected.x *= halfrenderwidth; projected.x += halfrenderwidth;
projected.y *= -halfrenderheight; projected.y += halfrenderheight;
}
void Point::SetNotUsed()
{
// We use a particular integer pattern : 0xffffffff everywhere. This is a NAN.
IR(x) = 0xffffffff;
IR(y) = 0xffffffff;
IR(z) = 0xffffffff;
}
BOOL Point::IsNotUsed() const
{
if(IR(x)!=0xffffffff) return FALSE;
if(IR(y)!=0xffffffff) return FALSE;
if(IR(z)!=0xffffffff) return FALSE;
return TRUE;
}
Point& Point::Mult(const Matrix3x3& mat, const Point& a)
{
x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
return *this;
}
Point& Point::Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2)
{
x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2];
y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2];
z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2];
return *this;
}
Point& Point::Mac(const Matrix3x3& mat, const Point& a)
{
x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
return *this;
}
Point& Point::TransMult(const Matrix3x3& mat, const Point& a)
{
x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0];
y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1];
z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2];
return *this;
}
Point& Point::Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
{
x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x;
y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y;
z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z;
return *this;
}
Point& Point::InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
{
float sx = r.x - linpos.x;
float sy = r.y - linpos.y;
float sz = r.z - linpos.z;
x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0];
y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1];
z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2];
return *this;
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for 3D vectors.
* \file IcePoint.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 3D point.
*
* The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3".
* So the choice was between "Point" and "Vector3", the first one looked better (IMHO).
*
* Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3;
* This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out:
*
* \code
* Point P0,P1 = some 3D points;
* Point Delta = P1 - P0;
* \endcode
*
* This compiles fine, although you should have written:
*
* \code
* Point P0,P1 = some 3D points;
* Vector3 Delta = P1 - P0;
* \endcode
*
* Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake
* from the author or something you don't get.
*
* One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors.
* But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work.
*
* Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store
* your model's vertices and in most cases, you really want to use Points to save ram.
*
* \class Point
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Creates a positive unit random vector.
* \return Self-reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Point& Point::PositiveUnitRandomVector()
{
x = UnitRandomFloat();
y = UnitRandomFloat();
z = UnitRandomFloat();
Normalize();
return *this;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Creates a unit random vector.
* \return Self-reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Point& Point::UnitRandomVector()
{
x = UnitRandomFloat() - 0.5f;
y = UnitRandomFloat() - 0.5f;
z = UnitRandomFloat() - 0.5f;
Normalize();
return *this;
}
// Cast operator
// WARNING: not inlined
Point::operator HPoint() const { return HPoint(x, y, z, 0.0f); }
Point& Point::Refract(const Point& eye, const Point& n, float refractindex, Point& refracted)
{
// Point EyePt = eye position
// Point p = current vertex
// Point n = vertex normal
// Point rv = refracted vector
// Eye vector - doesn't need to be normalized
Point Env;
Env.x = eye.x - x;
Env.y = eye.y - y;
Env.z = eye.z - z;
float NDotE = n|Env;
float NDotN = n|n;
NDotE /= refractindex;
// Refracted vector
refracted = n*NDotE - Env*NDotN;
return *this;
}
Point& Point::ProjectToPlane(const Plane& p)
{
*this-= (p.d + (*this|p.n))*p.n;
return *this;
}
void Point::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const
{
projected = HPoint(x, y, z, 1.0f) * mat;
projected.w = 1.0f / projected.w;
projected.x*=projected.w;
projected.y*=projected.w;
projected.z*=projected.w;
projected.x *= halfrenderwidth; projected.x += halfrenderwidth;
projected.y *= -halfrenderheight; projected.y += halfrenderheight;
}
void Point::SetNotUsed()
{
// We use a particular integer pattern : 0xffffffff everywhere. This is a NAN.
IR(x) = 0xffffffff;
IR(y) = 0xffffffff;
IR(z) = 0xffffffff;
}
BOOL Point::IsNotUsed() const
{
if(IR(x)!=0xffffffff) return FALSE;
if(IR(y)!=0xffffffff) return FALSE;
if(IR(z)!=0xffffffff) return FALSE;
return TRUE;
}
Point& Point::Mult(const Matrix3x3& mat, const Point& a)
{
x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
return *this;
}
Point& Point::Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2)
{
x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2];
y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2];
z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2];
return *this;
}
Point& Point::Mac(const Matrix3x3& mat, const Point& a)
{
x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
return *this;
}
Point& Point::TransMult(const Matrix3x3& mat, const Point& a)
{
x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0];
y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1];
z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2];
return *this;
}
Point& Point::Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
{
x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x;
y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y;
z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z;
return *this;
}
Point& Point::InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
{
float sx = r.x - linpos.x;
float sy = r.y - linpos.y;
float sz = r.z - linpos.z;
x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0];
y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1];
z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2];
return *this;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,158 +1,158 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains preprocessor stuff. This should be the first included header.
* \file IcePreprocessor.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEPREPROCESSOR_H
#define ICEPREPROCESSOR_H
// Check platform
#if defined( _WIN32 ) || defined( WIN32 )
#pragma message("Compiling on Windows...")
#define PLATFORM_WINDOWS
#else
#pragma message("Compiling on unknown platform...")
#endif
// Check compiler
#if defined(_MSC_VER)
#pragma message("Compiling with VC++...")
#define COMPILER_VISUAL_CPP
#if _MSC_VER > 1300
#pragma message("Compiling with VC7")
#define COMPILER_VC7
#else
#pragma message("Compiling with VC6")
#define COMPILER_VC6
#endif
#else
#pragma message("Compiling with unknown compiler...")
#endif
// Check compiler options. If this file is included in user-apps, this
// shouldn't be needed, so that they can use what they like best.
#ifndef ICE_DONT_CHECK_COMPILER_OPTIONS
#ifdef COMPILER_VISUAL_CPP
#if defined(_CHAR_UNSIGNED)
#endif
#if defined(_CPPRTTI)
#error Please disable RTTI...
#endif
#if defined(_CPPUNWIND)
#error Please disable exceptions...
#endif
#if defined(_MT)
// Multithreading
#endif
#endif
#endif
// Check debug mode
#ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it.
#ifndef _DEBUG
#define _DEBUG
#endif
#endif
#ifdef _DEBUG
// Here you may define items for debug builds
#endif
#ifndef THIS_FILE
#define THIS_FILE __FILE__
#endif
#ifndef ICE_NO_DLL
#ifdef ICECORE_EXPORTS
#define ICECORE_API __declspec(dllexport)
#else
#define ICECORE_API __declspec(dllimport)
#endif
#else
#define ICECORE_API
#endif
#define FUNCTION extern "C"
// Cosmetic stuff [mainly useful with multiple inheritance]
#define override(base_class) virtual
// Our own inline keyword, so that:
// - we can switch to __forceinline to check it's really better or not
// - we can remove __forceinline if the compiler doesn't support it
// #define inline_ __forceinline
// #define inline_ inline
// Contributed by Bruce Mitchener
#if defined(COMPILER_VISUAL_CPP)
#define inline_ __forceinline
// #define inline_ inline
#elif defined(__GNUC__) && __GNUC__ < 3
#define inline_ inline
#elif defined(__GNUC__)
#define inline_ inline __attribute__ ((always_inline))
#else
#define inline_ inline
#endif
// Down the hatch
#pragma inline_depth( 255 )
#ifdef COMPILER_VISUAL_CPP
#pragma intrinsic(memcmp)
#pragma intrinsic(memcpy)
#pragma intrinsic(memset)
#pragma intrinsic(strcat)
#pragma intrinsic(strcmp)
#pragma intrinsic(strcpy)
#pragma intrinsic(strlen)
#pragma intrinsic(abs)
#pragma intrinsic(labs)
#endif
// ANSI compliance
#ifdef _DEBUG
// Remove painful warning in debug
inline_ bool ReturnsFalse(){ return false; }
#define for if(ReturnsFalse()){} else for
#else
#define for if(0){} else for
#endif
// Don't override new/delete
#define DEFAULT_NEWDELETE
#define DONT_TRACK_MEMORY_LEAKS
//! Macro used to give me a clue when it crashes in release and only the assembly is available
#define INCLUDE_GUARDIANS
#ifdef INCLUDE_GUARDIANS
#define GUARD(x) \
{ \
static const char guard_text[] = x; \
_asm push eax \
_asm nop \
_asm nop \
_asm nop \
_asm nop \
_asm lea eax, guard_text \
_asm nop \
_asm nop \
_asm nop \
_asm nop \
_asm pop eax \
}
#else
#define GUARD(x)
#endif
#endif // ICEPREPROCESSOR_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains preprocessor stuff. This should be the first included header.
* \file IcePreprocessor.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEPREPROCESSOR_H
#define ICEPREPROCESSOR_H
// Check platform
#if defined( _WIN32 ) || defined( WIN32 )
#pragma message("Compiling on Windows...")
#define PLATFORM_WINDOWS
#else
#pragma message("Compiling on unknown platform...")
#endif
// Check compiler
#if defined(_MSC_VER)
#pragma message("Compiling with VC++...")
#define COMPILER_VISUAL_CPP
#if _MSC_VER > 1300
#pragma message("Compiling with VC7")
#define COMPILER_VC7
#else
#pragma message("Compiling with VC6")
#define COMPILER_VC6
#endif
#else
#pragma message("Compiling with unknown compiler...")
#endif
// Check compiler options. If this file is included in user-apps, this
// shouldn't be needed, so that they can use what they like best.
#ifndef ICE_DONT_CHECK_COMPILER_OPTIONS
#ifdef COMPILER_VISUAL_CPP
#if defined(_CHAR_UNSIGNED)
#endif
#if defined(_CPPRTTI)
#error Please disable RTTI...
#endif
#if defined(_CPPUNWIND)
#error Please disable exceptions...
#endif
#if defined(_MT)
// Multithreading
#endif
#endif
#endif
// Check debug mode
#ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it.
#ifndef _DEBUG
#define _DEBUG
#endif
#endif
#ifdef _DEBUG
// Here you may define items for debug builds
#endif
#ifndef THIS_FILE
#define THIS_FILE __FILE__
#endif
#ifndef ICE_NO_DLL
#ifdef ICECORE_EXPORTS
#define ICECORE_API __declspec(dllexport)
#else
#define ICECORE_API __declspec(dllimport)
#endif
#else
#define ICECORE_API
#endif
#define FUNCTION extern "C"
// Cosmetic stuff [mainly useful with multiple inheritance]
#define override(base_class) virtual
// Our own inline keyword, so that:
// - we can switch to __forceinline to check it's really better or not
// - we can remove __forceinline if the compiler doesn't support it
// #define inline_ __forceinline
// #define inline_ inline
// Contributed by Bruce Mitchener
#if defined(COMPILER_VISUAL_CPP)
#define inline_ __forceinline
// #define inline_ inline
#elif defined(__GNUC__) && __GNUC__ < 3
#define inline_ inline
#elif defined(__GNUC__)
#define inline_ inline __attribute__ ((always_inline))
#else
#define inline_ inline
#endif
// Down the hatch
#pragma inline_depth( 255 )
#ifdef COMPILER_VISUAL_CPP
#pragma intrinsic(memcmp)
#pragma intrinsic(memcpy)
#pragma intrinsic(memset)
#pragma intrinsic(strcat)
#pragma intrinsic(strcmp)
#pragma intrinsic(strcpy)
#pragma intrinsic(strlen)
#pragma intrinsic(abs)
#pragma intrinsic(labs)
#endif
// ANSI compliance
#ifdef _DEBUG
// Remove painful warning in debug
inline_ bool ReturnsFalse(){ return false; }
#define for if(ReturnsFalse()){} else for
#else
#define for if(0){} else for
#endif
// Don't override new/delete
#define DEFAULT_NEWDELETE
#define DONT_TRACK_MEMORY_LEAKS
//! Macro used to give me a clue when it crashes in release and only the assembly is available
#define INCLUDE_GUARDIANS
#ifdef INCLUDE_GUARDIANS
#define GUARD(x) \
{ \
static const char guard_text[] = x; \
_asm push eax \
_asm nop \
_asm nop \
_asm nop \
_asm nop \
_asm lea eax, guard_text \
_asm nop \
_asm nop \
_asm nop \
_asm nop \
_asm pop eax \
}
#else
#define GUARD(x)
#endif
#endif // ICEPREPROCESSOR_H

View File

@@ -1,52 +1,52 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for random generators.
* \file IceRandom.cpp
* \author Pierre Terdiman
* \date August, 9, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
void IceCore:: SRand(udword seed)
{
srand(seed);
}
udword IceCore::Rand()
{
return rand();
}
static BasicRandom gRandomGenerator(42);
udword IceCore::GetRandomIndex(udword max_index)
{
// We don't use rand() since it's limited to RAND_MAX
udword Index = gRandomGenerator.Randomize();
return Index % max_index;
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for random generators.
* \file IceRandom.cpp
* \author Pierre Terdiman
* \date August, 9, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
void IceCore:: SRand(udword seed)
{
srand(seed);
}
udword IceCore::Rand()
{
return rand();
}
static BasicRandom gRandomGenerator(42);
udword IceCore::GetRandomIndex(udword max_index)
{
// We don't use rand() since it's limited to RAND_MAX
udword Index = gRandomGenerator.Randomize();
return Index % max_index;
}

View File

@@ -1,58 +1,58 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for random generators.
* \file IceRandom.h
* \author Pierre Terdiman
* \date August, 9, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICERANDOM_H__
#define __ICERANDOM_H__
FUNCTION ICECORE_API void SRand(udword seed);
FUNCTION ICECORE_API udword Rand();
//! Returns a unit random floating-point value
inline_ float UnitRandomFloat() { return float(Rand()) * ONE_OVER_RAND_MAX; }
//! Returns a random index so that 0<= index < max_index
ICECORE_API udword GetRandomIndex(udword max_index);
class ICECORE_API BasicRandom
{
public:
//! Constructor
inline_ BasicRandom(udword seed=0) : mRnd(seed) {}
//! Destructor
inline_ ~BasicRandom() {}
inline_ void SetSeed(udword seed) { mRnd = seed; }
inline_ udword GetCurrentValue() const { return mRnd; }
inline_ udword Randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; }
private:
udword mRnd;
};
#endif // __ICERANDOM_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for random generators.
* \file IceRandom.h
* \author Pierre Terdiman
* \date August, 9, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICERANDOM_H__
#define __ICERANDOM_H__
FUNCTION ICECORE_API void SRand(udword seed);
FUNCTION ICECORE_API udword Rand();
//! Returns a unit random floating-point value
inline_ float UnitRandomFloat() { return float(Rand()) * ONE_OVER_RAND_MAX; }
//! Returns a random index so that 0<= index < max_index
ICECORE_API udword GetRandomIndex(udword max_index);
class ICECORE_API BasicRandom
{
public:
//! Constructor
inline_ BasicRandom(udword seed=0) : mRnd(seed) {}
//! Destructor
inline_ ~BasicRandom() {}
inline_ void SetSeed(udword seed) { mRnd = seed; }
inline_ udword GetCurrentValue() const { return mRnd; }
inline_ udword Randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; }
private:
udword mRnd;
};
#endif // __ICERANDOM_H__

View File

@@ -1,100 +1,100 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for rays.
* \file IceRay.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Ray class.
* A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity
* \class Ray
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
O = Origin = impact point
i = normalized vector along the x axis
j = normalized vector along the y axis = actually the normal vector in O
D = Direction vector, norm |D| = 1
N = Projection of D on y axis, norm |N| = normal reaction
T = Projection of D on x axis, norm |T| = tangential reaction
R = Reflexion vector
^y
|
|
|
_ _ _| _ _ _
* * *|
\ | /
\ |N / |
R\ | /D
\ | / |
\ | /
_________\|/______*_______>x
O T
Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized.
j|D = |j|*|D|*cos(theta) => |N| = j|D
Then we simply have:
D = N + T
To compute tangential reaction :
T = D - N
To compute reflexion vector :
R = N - T = N - (D-N) = 2*N - D
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
float Ray::SquareDistance(const Point& point, float* t) const
{
Point Diff = point - mOrig;
float fT = Diff | mDir;
if(fT<=0.0f)
{
fT = 0.0f;
}
else
{
fT /= mDir.SquareMagnitude();
Diff -= fT*mDir;
}
if(t) *t = fT;
return Diff.SquareMagnitude();
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for rays.
* \file IceRay.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Ray class.
* A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity
* \class Ray
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
O = Origin = impact point
i = normalized vector along the x axis
j = normalized vector along the y axis = actually the normal vector in O
D = Direction vector, norm |D| = 1
N = Projection of D on y axis, norm |N| = normal reaction
T = Projection of D on x axis, norm |T| = tangential reaction
R = Reflexion vector
^y
|
|
|
_ _ _| _ _ _
* * *|
\ | /
\ |N / |
R\ | /D
\ | / |
\ | /
_________\|/______*_______>x
O T
Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized.
j|D = |j|*|D|*cos(theta) => |N| = j|D
Then we simply have:
D = N + T
To compute tangential reaction :
T = D - N
To compute reflexion vector :
R = N - T = N - (D-N) = 2*N - D
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
float Ray::SquareDistance(const Point& point, float* t) const
{
Point Diff = point - mOrig;
float fT = Diff | mDir;
if(fT<=0.0f)
{
fT = 0.0f;
}
else
{
fT /= mDir.SquareMagnitude();
Diff -= fT*mDir;
}
if(t) *t = fT;
return Diff.SquareMagnitude();
}

View File

@@ -1,114 +1,114 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for rays.
* \file IceRay.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICERAY_H__
#define __ICERAY_H__
class ICEMATHS_API Ray
{
public:
//! Constructor
inline_ Ray() {}
//! Constructor
inline_ Ray(const Point& orig, const Point& dir) : mOrig(orig), mDir(dir) {}
//! Copy constructor
inline_ Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir) {}
//! Destructor
inline_ ~Ray() {}
float SquareDistance(const Point& point, float* t=null) const;
inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); }
Point mOrig; //!< Ray origin
Point mDir; //!< Normalized direction
};
inline_ void ComputeReflexionVector(Point& reflected, const Point& incoming_dir, const Point& outward_normal)
{
reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal);
}
inline_ void ComputeReflexionVector(Point& reflected, const Point& source, const Point& impact, const Point& normal)
{
Point V = impact - source;
reflected = V - normal * 2.0f * (V|normal);
}
inline_ void DecomposeVector(Point& normal_compo, Point& tangent_compo, const Point& outward_dir, const Point& outward_normal)
{
normal_compo = outward_normal * (outward_dir|outward_normal);
tangent_compo = outward_dir - normal_compo;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a direction vector from world space to local space
* \param local_dir [out] direction vector in local space
* \param world_dir [in] direction vector in world space
* \param world [in] world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void ComputeLocalDirection(Point& local_dir, const Point& world_dir, const Matrix4x4& world)
{
// Get world direction back in local space
// Matrix3x3 InvWorld = world;
// local_dir = InvWorld * world_dir;
local_dir = Matrix3x3(world) * world_dir;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a position vector from world space to local space
* \param local_pt [out] position vector in local space
* \param world_pt [in] position vector in world space
* \param world [in] world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void ComputeLocalPoint(Point& local_pt, const Point& world_pt, const Matrix4x4& world)
{
// Get world vertex back in local space
Matrix4x4 InvWorld = world;
InvWorld.Invert();
local_pt = world_pt * InvWorld;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a ray from world space to local space
* \param local_ray [out] ray in local space
* \param world_ray [in] ray in world space
* \param world [in] world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world)
{
// Get world ray back in local space
ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world);
ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world);
}
#endif // __ICERAY_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for rays.
* \file IceRay.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICERAY_H__
#define __ICERAY_H__
class ICEMATHS_API Ray
{
public:
//! Constructor
inline_ Ray() {}
//! Constructor
inline_ Ray(const Point& orig, const Point& dir) : mOrig(orig), mDir(dir) {}
//! Copy constructor
inline_ Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir) {}
//! Destructor
inline_ ~Ray() {}
float SquareDistance(const Point& point, float* t=null) const;
inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); }
Point mOrig; //!< Ray origin
Point mDir; //!< Normalized direction
};
inline_ void ComputeReflexionVector(Point& reflected, const Point& incoming_dir, const Point& outward_normal)
{
reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal);
}
inline_ void ComputeReflexionVector(Point& reflected, const Point& source, const Point& impact, const Point& normal)
{
Point V = impact - source;
reflected = V - normal * 2.0f * (V|normal);
}
inline_ void DecomposeVector(Point& normal_compo, Point& tangent_compo, const Point& outward_dir, const Point& outward_normal)
{
normal_compo = outward_normal * (outward_dir|outward_normal);
tangent_compo = outward_dir - normal_compo;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a direction vector from world space to local space
* \param local_dir [out] direction vector in local space
* \param world_dir [in] direction vector in world space
* \param world [in] world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void ComputeLocalDirection(Point& local_dir, const Point& world_dir, const Matrix4x4& world)
{
// Get world direction back in local space
// Matrix3x3 InvWorld = world;
// local_dir = InvWorld * world_dir;
local_dir = Matrix3x3(world) * world_dir;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a position vector from world space to local space
* \param local_pt [out] position vector in local space
* \param world_pt [in] position vector in world space
* \param world [in] world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void ComputeLocalPoint(Point& local_pt, const Point& world_pt, const Matrix4x4& world)
{
// Get world vertex back in local space
Matrix4x4 InvWorld = world;
InvWorld.Invert();
local_pt = world_pt * InvWorld;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Transforms a ray from world space to local space
* \param local_ray [out] ray in local space
* \param world_ray [in] ray in world space
* \param world [in] world transform
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world)
{
// Get world ray back in local space
ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world);
ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world);
}
#endif // __ICERAY_H__

File diff suppressed because it is too large Load Diff

View File

@@ -1,74 +1,74 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains source code from the article "Radix Sort Revisited".
* \file IceRevisitedRadix.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICERADIXSORT_H
#define ICERADIXSORT_H
//! Allocate histograms & offsets locally
#define RADIX_LOCAL_RAM
enum RadixHint
{
RADIX_SIGNED, //!< Input values are signed
RADIX_UNSIGNED, //!< Input values are unsigned
RADIX_FORCE_DWORD = 0x7fffffff
};
class ICECORE_API RadixSort : public Allocateable
{
public:
// Constructor/Destructor
RadixSort();
~RadixSort();
// Sorting methods
RadixSort& Sort(const udword* input, udword nb, RadixHint hint=RADIX_SIGNED);
RadixSort& Sort(const float* input, udword nb);
//! Access to results. mRanks is a list of indices in sorted order, i.e. in the order you may further process your data
inline_ const udword* GetRanks() const { return mRanks; }
//! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want.
inline_ udword* GetRecyclable() const { return mRanks2; }
// Stats
udword GetUsedRam() const;
//! Returns the total number of calls to the radix sorter.
inline_ udword GetNbTotalCalls() const { return mTotalCalls; }
//! Returns the number of eraly exits due to temporal coherence.
inline_ udword GetNbHits() const { return mNbHits; }
bool SetRankBuffers(udword* ranks0, udword* ranks1);
PREVENT_COPY(RadixSort)
private:
#ifndef RADIX_LOCAL_RAM
udword* mHistogram; //!< Counters for each byte
udword* mOffset; //!< Offsets (nearly a cumulative distribution function)
#endif
udword mCurrentSize; //!< Current size of the indices list
udword* mRanks; //!< Two lists, swapped each pass
udword* mRanks2;
// Stats
udword mTotalCalls; //!< Total number of calls to the sort routine
udword mNbHits; //!< Number of early exits due to coherence
// Stack-radix
bool mDeleteRanks; //!<
// Internal methods
void CheckResize(udword nb);
bool Resize(udword nb);
};
#define StackRadixSort(name, ranks0, ranks1) \
RadixSort name; \
name.SetRankBuffers(ranks0, ranks1);
#endif // ICERADIXSORT_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains source code from the article "Radix Sort Revisited".
* \file IceRevisitedRadix.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICERADIXSORT_H
#define ICERADIXSORT_H
//! Allocate histograms & offsets locally
#define RADIX_LOCAL_RAM
enum RadixHint
{
RADIX_SIGNED, //!< Input values are signed
RADIX_UNSIGNED, //!< Input values are unsigned
RADIX_FORCE_DWORD = 0x7fffffff
};
class ICECORE_API RadixSort : public Allocateable
{
public:
// Constructor/Destructor
RadixSort();
~RadixSort();
// Sorting methods
RadixSort& Sort(const udword* input, udword nb, RadixHint hint=RADIX_SIGNED);
RadixSort& Sort(const float* input, udword nb);
//! Access to results. mRanks is a list of indices in sorted order, i.e. in the order you may further process your data
inline_ const udword* GetRanks() const { return mRanks; }
//! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want.
inline_ udword* GetRecyclable() const { return mRanks2; }
// Stats
udword GetUsedRam() const;
//! Returns the total number of calls to the radix sorter.
inline_ udword GetNbTotalCalls() const { return mTotalCalls; }
//! Returns the number of eraly exits due to temporal coherence.
inline_ udword GetNbHits() const { return mNbHits; }
bool SetRankBuffers(udword* ranks0, udword* ranks1);
PREVENT_COPY(RadixSort)
private:
#ifndef RADIX_LOCAL_RAM
udword* mHistogram; //!< Counters for each byte
udword* mOffset; //!< Offsets (nearly a cumulative distribution function)
#endif
udword mCurrentSize; //!< Current size of the indices list
udword* mRanks; //!< Two lists, swapped each pass
udword* mRanks2;
// Stats
udword mTotalCalls; //!< Total number of calls to the sort routine
udword mNbHits; //!< Number of early exits due to coherence
// Stack-radix
bool mDeleteRanks; //!<
// Internal methods
void CheckResize(udword nb);
bool Resize(udword nb);
};
#define StackRadixSort(name, ranks0, ranks1) \
RadixSort name; \
name.SetRankBuffers(ranks0, ranks1);
#endif // ICERADIXSORT_H

View File

@@ -1,73 +1,73 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for segments.
* \file IceSegment.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Segment class.
* A segment is defined by S(t) = mP0 * (1 - t) + mP1 * t, with 0 <= t <= 1
* Alternatively, a segment is S(t) = Origin + t * Direction for 0 <= t <= 1.
* Direction is not necessarily unit length. The end points are Origin = mP0 and Origin + Direction = mP1.
*
* \class Segment
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
float Segment::SquareDistance(const Point& point, float* t) const
{
Point Diff = point - mP0;
Point Dir = mP1 - mP0;
float fT = Diff | Dir;
if(fT<=0.0f)
{
fT = 0.0f;
}
else
{
float SqrLen= Dir.SquareMagnitude();
if(fT>=SqrLen)
{
fT = 1.0f;
Diff -= Dir;
}
else
{
fT /= SqrLen;
Diff -= fT*Dir;
}
}
if(t) *t = fT;
return Diff.SquareMagnitude();
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for segments.
* \file IceSegment.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Segment class.
* A segment is defined by S(t) = mP0 * (1 - t) + mP1 * t, with 0 <= t <= 1
* Alternatively, a segment is S(t) = Origin + t * Direction for 0 <= t <= 1.
* Direction is not necessarily unit length. The end points are Origin = mP0 and Origin + Direction = mP1.
*
* \class Segment
* \author Pierre Terdiman
* \version 1.0
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
float Segment::SquareDistance(const Point& point, float* t) const
{
Point Diff = point - mP0;
Point Dir = mP1 - mP0;
float fT = Diff | Dir;
if(fT<=0.0f)
{
fT = 0.0f;
}
else
{
float SqrLen= Dir.SquareMagnitude();
if(fT>=SqrLen)
{
fT = 1.0f;
Diff -= Dir;
}
else
{
fT /= SqrLen;
Diff -= fT*Dir;
}
}
if(t) *t = fT;
return Diff.SquareMagnitude();
}

View File

@@ -1,71 +1,71 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for segments.
* \file IceSegment.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICESEGMENT_H__
#define __ICESEGMENT_H__
class ICEMATHS_API Segment
{
public:
//! Constructor
inline_ Segment() {}
//! Constructor
inline_ Segment(const Point& p0, const Point& p1) : mP0(p0), mP1(p1) {}
//! Copy constructor
inline_ Segment(const Segment& seg) : mP0(seg.mP0), mP1(seg.mP1) {}
//! Destructor
inline_ ~Segment() {}
inline_ const Point& GetOrigin() const { return mP0; }
inline_ Point ComputeDirection() const { return mP1 - mP0; }
inline_ void ComputeDirection(Point& dir) const { dir = mP1 - mP0; }
inline_ float ComputeLength() const { return mP1.Distance(mP0); }
inline_ float ComputeSquareLength() const { return mP1.SquareDistance(mP0); }
inline_ void SetOriginDirection(const Point& origin, const Point& direction)
{
mP0 = mP1 = origin;
mP1 += direction;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes a point on the segment
* \param pt [out] point on segment
* \param t [in] point's parameter [t=0 => pt = mP0, t=1 => pt = mP1]
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void ComputePoint(Point& pt, float t) const { pt = mP0 + t * (mP1 - mP0); }
float SquareDistance(const Point& point, float* t=null) const;
inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); }
Point mP0; //!< Start of segment
Point mP1; //!< End of segment
};
#endif // __ICESEGMENT_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for segments.
* \file IceSegment.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICESEGMENT_H__
#define __ICESEGMENT_H__
class ICEMATHS_API Segment
{
public:
//! Constructor
inline_ Segment() {}
//! Constructor
inline_ Segment(const Point& p0, const Point& p1) : mP0(p0), mP1(p1) {}
//! Copy constructor
inline_ Segment(const Segment& seg) : mP0(seg.mP0), mP1(seg.mP1) {}
//! Destructor
inline_ ~Segment() {}
inline_ const Point& GetOrigin() const { return mP0; }
inline_ Point ComputeDirection() const { return mP1 - mP0; }
inline_ void ComputeDirection(Point& dir) const { dir = mP1 - mP0; }
inline_ float ComputeLength() const { return mP1.Distance(mP0); }
inline_ float ComputeSquareLength() const { return mP1.SquareDistance(mP0); }
inline_ void SetOriginDirection(const Point& origin, const Point& direction)
{
mP0 = mP1 = origin;
mP1 += direction;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes a point on the segment
* \param pt [out] point on segment
* \param t [in] point's parameter [t=0 => pt = mP0, t=1 => pt = mP1]
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void ComputePoint(Point& pt, float t) const { pt = mP0 + t * (mP1 - mP0); }
float SquareDistance(const Point& point, float* t=null) const;
inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); }
Point mP0; //!< Start of segment
Point mP1; //!< End of segment
};
#endif // __ICESEGMENT_H__

View File

@@ -1,302 +1,302 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a handy triangle class.
* \file IceTriangle.cpp
* \author Pierre Terdiman
* \date January, 17, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a triangle class.
*
* \class Tri
* \author Pierre Terdiman
* \version 1.0
* \date 08.15.98
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static sdword VPlaneSideEps(const Point& v, const Plane& plane, float epsilon)
{
// Compute distance from current vertex to the plane
float Dist = plane.Distance(v);
// Compute side:
// 1 = the vertex is on the positive side of the plane
// -1 = the vertex is on the negative side of the plane
// 0 = the vertex is on the plane (within epsilon)
return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Flips the winding order.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::Flip()
{
Point Tmp = mVerts[1];
mVerts[1] = mVerts[2];
mVerts[2] = Tmp;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle area.
* \return the area
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::Area() const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle perimeter.
* \return the perimeter
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::Perimeter() const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
return p0.Distance(p1)
+ p0.Distance(p2)
+ p1.Distance(p2);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle compacity.
* \return the compacity
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::Compacity() const
{
float P = Perimeter();
if(P==0.0f) return 0.0f;
return (4.0f*PI*Area()/(P*P));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle normal.
* \param normal [out] the computed normal
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::Normal(Point& normal) const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
normal = ((p0 - p1)^(p0 - p2)).Normalize();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle denormalized normal.
* \param normal [out] the computed normal
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::DenormalizedNormal(Point& normal) const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
normal = ((p0 - p1)^(p0 - p2));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle center.
* \param center [out] the computed center
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::Center(Point& center) const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
center = (p0 + p1 + p2)*INV3;
}
PartVal Triangle::TestAgainstPlane(const Plane& plane, float epsilon) const
{
bool Pos = false, Neg = false;
// Loop through all vertices
for(udword i=0;i<3;i++)
{
// Compute side:
sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon);
if (Side < 0) Neg = true;
else if (Side > 0) Pos = true;
}
if (!Pos && !Neg) return TRI_ON_PLANE;
else if (Pos && Neg) return TRI_INTERSECT;
else if (Pos && !Neg) return TRI_PLUS_SPACE;
else if (!Pos && Neg) return TRI_MINUS_SPACE;
// What?!
return TRI_FORCEDWORD;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle moment.
* \param m [out] the moment
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
void Triangle::ComputeMoment(Moment& m)
{
// Compute the area of the triangle
m.mArea = Area();
// Compute the centroid
Center(m.mCentroid);
// Second-order components. Handle zero-area faces.
Point& p = mVerts[0];
Point& q = mVerts[1];
Point& r = mVerts[2];
if(m.mArea==0.0f)
{
// This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the
// sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices.
m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x);
m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y);
m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z);
m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y);
m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z);
m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z);
m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
}
else
{
const float OneOverTwelve = 1.0f / 12.0f;
m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve;
m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve;
m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve;
m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve;
m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve;
m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve;
m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
}
}
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle's smallest edge length.
* \return the smallest edge length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::MinEdgeLength() const
{
float Min = MAX_FLOAT;
float Length01 = mVerts[0].Distance(mVerts[1]);
float Length02 = mVerts[0].Distance(mVerts[2]);
float Length12 = mVerts[1].Distance(mVerts[2]);
if(Length01 < Min) Min = Length01;
if(Length02 < Min) Min = Length02;
if(Length12 < Min) Min = Length12;
return Min;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle's largest edge length.
* \return the largest edge length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::MaxEdgeLength() const
{
float Max = MIN_FLOAT;
float Length01 = mVerts[0].Distance(mVerts[1]);
float Length02 = mVerts[0].Distance(mVerts[2]);
float Length12 = mVerts[1].Distance(mVerts[2]);
if(Length01 > Max) Max = Length01;
if(Length02 > Max) Max = Length02;
if(Length12 > Max) Max = Length12;
return Max;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes a point on the triangle according to the stabbing information.
* \param u,v [in] point's barycentric coordinates
* \param pt [out] point on triangle
* \param nearvtx [out] index of nearest vertex
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::ComputePoint(float u, float v, Point& pt, udword* nearvtx) const
{
// Compute point coordinates
pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2];
// Compute nearest vertex if needed
if(nearvtx)
{
// Compute distance vector
Point d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to point on the face
mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to point on the face
mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face
// Get smallest distance
*nearvtx = d.SmallestAxis();
}
}
void Triangle::Inflate(float fat_coeff, bool constant_border)
{
// Compute triangle center
Point TriangleCenter;
Center(TriangleCenter);
// Don't normalize?
// Normalize => add a constant border, regardless of triangle size
// Don't => add more to big triangles
for(udword i=0;i<3;i++)
{
Point v = mVerts[i] - TriangleCenter;
if(constant_border) v.Normalize();
mVerts[i] += v * fat_coeff;
}
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a handy triangle class.
* \file IceTriangle.cpp
* \author Pierre Terdiman
* \date January, 17, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a triangle class.
*
* \class Tri
* \author Pierre Terdiman
* \version 1.0
* \date 08.15.98
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static sdword VPlaneSideEps(const Point& v, const Plane& plane, float epsilon)
{
// Compute distance from current vertex to the plane
float Dist = plane.Distance(v);
// Compute side:
// 1 = the vertex is on the positive side of the plane
// -1 = the vertex is on the negative side of the plane
// 0 = the vertex is on the plane (within epsilon)
return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Flips the winding order.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::Flip()
{
Point Tmp = mVerts[1];
mVerts[1] = mVerts[2];
mVerts[2] = Tmp;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle area.
* \return the area
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::Area() const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle perimeter.
* \return the perimeter
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::Perimeter() const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
return p0.Distance(p1)
+ p0.Distance(p2)
+ p1.Distance(p2);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle compacity.
* \return the compacity
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::Compacity() const
{
float P = Perimeter();
if(P==0.0f) return 0.0f;
return (4.0f*PI*Area()/(P*P));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle normal.
* \param normal [out] the computed normal
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::Normal(Point& normal) const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
normal = ((p0 - p1)^(p0 - p2)).Normalize();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle denormalized normal.
* \param normal [out] the computed normal
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::DenormalizedNormal(Point& normal) const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
normal = ((p0 - p1)^(p0 - p2));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle center.
* \param center [out] the computed center
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::Center(Point& center) const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
center = (p0 + p1 + p2)*INV3;
}
PartVal Triangle::TestAgainstPlane(const Plane& plane, float epsilon) const
{
bool Pos = false, Neg = false;
// Loop through all vertices
for(udword i=0;i<3;i++)
{
// Compute side:
sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon);
if (Side < 0) Neg = true;
else if (Side > 0) Pos = true;
}
if (!Pos && !Neg) return TRI_ON_PLANE;
else if (Pos && Neg) return TRI_INTERSECT;
else if (Pos && !Neg) return TRI_PLUS_SPACE;
else if (!Pos && Neg) return TRI_MINUS_SPACE;
// What?!
return TRI_FORCEDWORD;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle moment.
* \param m [out] the moment
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
void Triangle::ComputeMoment(Moment& m)
{
// Compute the area of the triangle
m.mArea = Area();
// Compute the centroid
Center(m.mCentroid);
// Second-order components. Handle zero-area faces.
Point& p = mVerts[0];
Point& q = mVerts[1];
Point& r = mVerts[2];
if(m.mArea==0.0f)
{
// This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the
// sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices.
m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x);
m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y);
m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z);
m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y);
m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z);
m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z);
m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
}
else
{
const float OneOverTwelve = 1.0f / 12.0f;
m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve;
m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve;
m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve;
m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve;
m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve;
m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve;
m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
}
}
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle's smallest edge length.
* \return the smallest edge length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::MinEdgeLength() const
{
float Min = MAX_FLOAT;
float Length01 = mVerts[0].Distance(mVerts[1]);
float Length02 = mVerts[0].Distance(mVerts[2]);
float Length12 = mVerts[1].Distance(mVerts[2]);
if(Length01 < Min) Min = Length01;
if(Length02 < Min) Min = Length02;
if(Length12 < Min) Min = Length12;
return Min;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle's largest edge length.
* \return the largest edge length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::MaxEdgeLength() const
{
float Max = MIN_FLOAT;
float Length01 = mVerts[0].Distance(mVerts[1]);
float Length02 = mVerts[0].Distance(mVerts[2]);
float Length12 = mVerts[1].Distance(mVerts[2]);
if(Length01 > Max) Max = Length01;
if(Length02 > Max) Max = Length02;
if(Length12 > Max) Max = Length12;
return Max;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes a point on the triangle according to the stabbing information.
* \param u,v [in] point's barycentric coordinates
* \param pt [out] point on triangle
* \param nearvtx [out] index of nearest vertex
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::ComputePoint(float u, float v, Point& pt, udword* nearvtx) const
{
// Compute point coordinates
pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2];
// Compute nearest vertex if needed
if(nearvtx)
{
// Compute distance vector
Point d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to point on the face
mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to point on the face
mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face
// Get smallest distance
*nearvtx = d.SmallestAxis();
}
}
void Triangle::Inflate(float fat_coeff, bool constant_border)
{
// Compute triangle center
Point TriangleCenter;
Center(TriangleCenter);
// Don't normalize?
// Normalize => add a constant border, regardless of triangle size
// Don't => add more to big triangles
for(udword i=0;i<3;i++)
{
Point v = mVerts[i] - TriangleCenter;
if(constant_border) v.Normalize();
mVerts[i] += v * fat_coeff;
}
}

View File

@@ -1,84 +1,84 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a handy triangle class.
* \file IceTriangle.h
* \author Pierre Terdiman
* \date January, 17, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICETRIANGLE_H__
#define __ICETRIANGLE_H__
// Forward declarations
class Moment;
// Partitioning values
enum PartVal
{
TRI_MINUS_SPACE = 0, //!< Triangle is in the negative space
TRI_PLUS_SPACE = 1, //!< Triangle is in the positive space
TRI_INTERSECT = 2, //!< Triangle intersects plane
TRI_ON_PLANE = 3, //!< Triangle and plane are coplanar
TRI_FORCEDWORD = 0x7fffffff
};
// A triangle class.
class ICEMATHS_API Triangle
{
public:
//! Constructor
inline_ Triangle() {}
//! Constructor
inline_ Triangle(const Point& p0, const Point& p1, const Point& p2) { mVerts[0]=p0; mVerts[1]=p1; mVerts[2]=p2; }
//! Copy constructor
inline_ Triangle(const Triangle& triangle)
{
mVerts[0] = triangle.mVerts[0];
mVerts[1] = triangle.mVerts[1];
mVerts[2] = triangle.mVerts[2];
}
//! Destructor
inline_ ~Triangle() {}
//! Vertices
Point mVerts[3];
// Methods
void Flip();
float Area() const;
float Perimeter() const;
float Compacity() const;
void Normal(Point& normal) const;
void DenormalizedNormal(Point& normal) const;
void Center(Point& center) const;
inline_ Plane PlaneEquation() const { return Plane(mVerts[0], mVerts[1], mVerts[2]); }
PartVal TestAgainstPlane(const Plane& plane, float epsilon) const;
// float Distance(Point& cp, Point& cq, Tri& tri);
void ComputeMoment(Moment& m);
float MinEdgeLength() const;
float MaxEdgeLength() const;
void ComputePoint(float u, float v, Point& pt, udword* nearvtx=null) const;
void Inflate(float fat_coeff, bool constant_border);
};
#endif // __ICETRIANGLE_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a handy triangle class.
* \file IceTriangle.h
* \author Pierre Terdiman
* \date January, 17, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICETRIANGLE_H__
#define __ICETRIANGLE_H__
// Forward declarations
class Moment;
// Partitioning values
enum PartVal
{
TRI_MINUS_SPACE = 0, //!< Triangle is in the negative space
TRI_PLUS_SPACE = 1, //!< Triangle is in the positive space
TRI_INTERSECT = 2, //!< Triangle intersects plane
TRI_ON_PLANE = 3, //!< Triangle and plane are coplanar
TRI_FORCEDWORD = 0x7fffffff
};
// A triangle class.
class ICEMATHS_API Triangle
{
public:
//! Constructor
inline_ Triangle() {}
//! Constructor
inline_ Triangle(const Point& p0, const Point& p1, const Point& p2) { mVerts[0]=p0; mVerts[1]=p1; mVerts[2]=p2; }
//! Copy constructor
inline_ Triangle(const Triangle& triangle)
{
mVerts[0] = triangle.mVerts[0];
mVerts[1] = triangle.mVerts[1];
mVerts[2] = triangle.mVerts[2];
}
//! Destructor
inline_ ~Triangle() {}
//! Vertices
Point mVerts[3];
// Methods
void Flip();
float Area() const;
float Perimeter() const;
float Compacity() const;
void Normal(Point& normal) const;
void DenormalizedNormal(Point& normal) const;
void Center(Point& center) const;
inline_ Plane PlaneEquation() const { return Plane(mVerts[0], mVerts[1], mVerts[2]); }
PartVal TestAgainstPlane(const Plane& plane, float epsilon) const;
// float Distance(Point& cp, Point& cq, Tri& tri);
void ComputeMoment(Moment& m);
float MinEdgeLength() const;
float MaxEdgeLength() const;
void ComputePoint(float u, float v, Point& pt, udword* nearvtx=null) const;
void Inflate(float fat_coeff, bool constant_border);
};
#endif // __ICETRIANGLE_H__

View File

@@ -1,77 +1,77 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for a triangle container.
* \file IceTrilist.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICETRILIST_H__
#define __ICETRILIST_H__
class ICEMATHS_API TriList : public Container
{
public:
// Constructor / Destructor
TriList() {}
~TriList() {}
inline_ udword GetNbTriangles() const { return GetNbEntries()/9; }
inline_ Triangle* GetTriangles() const { return (Triangle*)GetEntries(); }
void AddTri(const Triangle& tri)
{
Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z);
Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z);
Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z);
}
void AddTri(const Point& p0, const Point& p1, const Point& p2)
{
Add(p0.x).Add(p0.y).Add(p0.z);
Add(p1.x).Add(p1.y).Add(p1.z);
Add(p2.x).Add(p2.y).Add(p2.z);
}
};
class ICEMATHS_API TriangleList : public Container
{
public:
// Constructor / Destructor
TriangleList() {}
~TriangleList() {}
inline_ udword GetNbTriangles() const { return GetNbEntries()/3; }
inline_ IndexedTriangle* GetTriangles() const { return (IndexedTriangle*)GetEntries();}
void AddTriangle(const IndexedTriangle& tri)
{
Add(tri.mVRef[0]).Add(tri.mVRef[1]).Add(tri.mVRef[2]);
}
void AddTriangle(udword vref0, udword vref1, udword vref2)
{
Add(vref0).Add(vref1).Add(vref2);
}
};
#endif //__ICETRILIST_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for a triangle container.
* \file IceTrilist.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICETRILIST_H__
#define __ICETRILIST_H__
class ICEMATHS_API TriList : public Container
{
public:
// Constructor / Destructor
TriList() {}
~TriList() {}
inline_ udword GetNbTriangles() const { return GetNbEntries()/9; }
inline_ Triangle* GetTriangles() const { return (Triangle*)GetEntries(); }
void AddTri(const Triangle& tri)
{
Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z);
Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z);
Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z);
}
void AddTri(const Point& p0, const Point& p1, const Point& p2)
{
Add(p0.x).Add(p0.y).Add(p0.z);
Add(p1.x).Add(p1.y).Add(p1.z);
Add(p2.x).Add(p2.y).Add(p2.z);
}
};
class ICEMATHS_API TriangleList : public Container
{
public:
// Constructor / Destructor
TriangleList() {}
~TriangleList() {}
inline_ udword GetNbTriangles() const { return GetNbEntries()/3; }
inline_ IndexedTriangle* GetTriangles() const { return (IndexedTriangle*)GetEntries();}
void AddTriangle(const IndexedTriangle& tri)
{
Add(tri.mVRef[0]).Add(tri.mVRef[1]).Add(tri.mVRef[2]);
}
void AddTriangle(udword vref0, udword vref1, udword vref2)
{
Add(vref0).Add(vref1).Add(vref2);
}
};
#endif //__ICETRILIST_H__

View File

@@ -1,181 +1,181 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains custom types.
* \file IceTypes.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICETYPES_H
#define ICETYPES_H
#define USE_HANDLE_MANAGER
// Constants
#ifndef PI
#define PI 3.1415926535897932384626433832795028841971693993751f //!< PI
#endif
#define HALFPI 1.57079632679489661923f //!< 0.5 * PI
#define TWOPI 6.28318530717958647692f //!< 2.0 * PI
#define INVPI 0.31830988618379067154f //!< 1.0 / PI
#define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees
#define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians
#define EXP 2.71828182845904523536f //!< e
#define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2)
#define LN2 0.693147180559945f //!< ln(2)
#define INVLN2 1.44269504089f //!< 1.0f / ln(2)
#define INV3 0.33333333333333333333f //!< 1/3
#define INV6 0.16666666666666666666f //!< 1/6
#define INV7 0.14285714285714285714f //!< 1/7
#define INV9 0.11111111111111111111f //!< 1/9
#define INV255 0.00392156862745098039f //!< 1/255
#define SQRT2 1.41421356237f //!< sqrt(2)
#define INVSQRT2 0.707106781188f //!< 1 / sqrt(2)
#define SQRT3 1.73205080757f //!< sqrt(3)
#define INVSQRT3 0.577350269189f //!< 1 / sqrt(3)
#define null 0 //!< our own NULL pointer
// Custom types used in ICE
typedef signed char sbyte; //!< sizeof(sbyte) must be 1
typedef unsigned char ubyte; //!< sizeof(ubyte) must be 1
typedef signed short sword; //!< sizeof(sword) must be 2
typedef unsigned short uword; //!< sizeof(uword) must be 2
typedef signed int sdword; //!< sizeof(sdword) must be 4
typedef unsigned int udword; //!< sizeof(udword) must be 4
#ifdef WIN32
typedef signed __int64 sqword; //!< sizeof(sqword) must be 8
typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8
#elif LINUX
typedef signed long long sqword; //!< sizeof(sqword) must be 8
typedef unsigned long long uqword; //!< sizeof(uqword) must be 8
#elif defined(__APPLE__)
typedef signed long long sqword; //!< sizeof(sqword) must be 8
typedef unsigned long long uqword; //!< sizeof(uqword) must be 8
#elif defined(_XBOX)
typedef signed __int64 sqword; //!< sizeof(sqword) must be 8
typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8
#endif
typedef float float32; //!< sizeof(float32) must be 4
typedef double float64; //!< sizeof(float64) must be 8
typedef size_t regsize; //!< sizeof(regsize) must be sizeof(void*)
// For test purpose you can force one of those:
// typedef udword regsize;
// typedef uqword regsize;
ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1); // ...otherwise things might fail with VC++ 4.2 !
ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1);
ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1);
ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2);
ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2);
ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8);
ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8);
ICE_COMPILE_TIME_ASSERT(sizeof(float32)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(float64)==8);
ICE_COMPILE_TIME_ASSERT(sizeof(regsize)==sizeof(void*));
//! TO BE DOCUMENTED
#define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
typedef udword DynID; //!< Dynamic identifier
#ifdef USE_HANDLE_MANAGER
typedef udword KID; //!< Kernel ID
// DECLARE_ICE_HANDLE(KID);
#else
typedef uword KID; //!< Kernel ID
#endif
#define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers)
#ifdef USE_HANDLE_MANAGER
#define INVALID_KID 0xffffffff //!< Invalid Kernel ID
#else
#define INVALID_KID 0xffff //!< Invalid Kernel ID
#endif
#define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value
// Define BOOL if needed
#ifndef BOOL
typedef int BOOL; //!< Another boolean type.
#endif
//! Union of a float and a sdword
typedef union {
float f; //!< The float
sdword d; //!< The integer
}scell;
//! Union of a float and a udword
typedef union {
float f; //!< The float
udword d; //!< The integer
}ucell;
// Type ranges
#define MAX_SBYTE 0x7f //!< max possible sbyte value
#define MIN_SBYTE 0x80 //!< min possible sbyte value
#define MAX_UBYTE 0xff //!< max possible ubyte value
#define MIN_UBYTE 0x00 //!< min possible ubyte value
#define MAX_SWORD 0x7fff //!< max possible sword value
#define MIN_SWORD 0x8000 //!< min possible sword value
#define MAX_UWORD 0xffff //!< max possible uword value
#define MIN_UWORD 0x0000 //!< min possible uword value
#define MAX_SDWORD 0x7fffffff //!< max possible sdword value
#define MIN_SDWORD 0x80000000 //!< min possible sdword value
#define MAX_UDWORD 0xffffffff //!< max possible udword value
#define MIN_UDWORD 0x00000000 //!< min possible udword value
#define MAX_FLOAT FLT_MAX //!< max possible float value
#define MIN_FLOAT (-FLT_MAX) //!< min possible loat value
#define IEEE_1_0 0x3f800000 //!< integer representation of 1.0
#define IEEE_255_0 0x437f0000 //!< integer representation of 255.0
#define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT
#define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT
#define IEEE_UNDERFLOW_LIMIT 0x1a000000
#define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand()
typedef void** VTABLE; //!< A V-Table.
#undef MIN
#undef MAX
#define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b
#define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b
#define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c
template<class T> inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; }
template<class T> inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; }
template<class T> inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; }
template<class T> inline_ void TSetMax (T& a, const T& b) { if(a<b) a = b; }
/* Obsolete stuff - if needed, move to dedicated header and include in few files using this.
#define SQR(x) ((x)*(x)) //!< Returns x square
#define CUBE(x) ((x)*(x)*(x)) //!< Returns x cube
#define AND & //!< ...
#define OR | //!< ...
#define XOR ^ //!< ...
#define QUADRAT(x) ((x)*(x)) //!< Returns x square
typedef int (__stdcall* PROC)(); //!< A standard procedure call.
typedef bool (*ENUMERATION)(udword value, udword param, udword context); //!< ICE standard enumeration call
#ifdef _WIN32
// Used to compile legacy code
__forceinline void srand48(udword x) { srand(x); }
__forceinline void srandom(udword x) { srand(x); }
__forceinline double random() { return (double)rand(); }
__forceinline double drand48() { return (double) ( ((double)rand()) / ((double)RAND_MAX) ); }
#endif
*/
#endif // ICETYPES_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains custom types.
* \file IceTypes.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICETYPES_H
#define ICETYPES_H
#define USE_HANDLE_MANAGER
// Constants
#ifndef PI
#define PI 3.1415926535897932384626433832795028841971693993751f //!< PI
#endif
#define HALFPI 1.57079632679489661923f //!< 0.5 * PI
#define TWOPI 6.28318530717958647692f //!< 2.0 * PI
#define INVPI 0.31830988618379067154f //!< 1.0 / PI
#define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees
#define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians
#define EXP 2.71828182845904523536f //!< e
#define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2)
#define LN2 0.693147180559945f //!< ln(2)
#define INVLN2 1.44269504089f //!< 1.0f / ln(2)
#define INV3 0.33333333333333333333f //!< 1/3
#define INV6 0.16666666666666666666f //!< 1/6
#define INV7 0.14285714285714285714f //!< 1/7
#define INV9 0.11111111111111111111f //!< 1/9
#define INV255 0.00392156862745098039f //!< 1/255
#define SQRT2 1.41421356237f //!< sqrt(2)
#define INVSQRT2 0.707106781188f //!< 1 / sqrt(2)
#define SQRT3 1.73205080757f //!< sqrt(3)
#define INVSQRT3 0.577350269189f //!< 1 / sqrt(3)
#define null 0 //!< our own NULL pointer
// Custom types used in ICE
typedef signed char sbyte; //!< sizeof(sbyte) must be 1
typedef unsigned char ubyte; //!< sizeof(ubyte) must be 1
typedef signed short sword; //!< sizeof(sword) must be 2
typedef unsigned short uword; //!< sizeof(uword) must be 2
typedef signed int sdword; //!< sizeof(sdword) must be 4
typedef unsigned int udword; //!< sizeof(udword) must be 4
#ifdef WIN32
typedef signed __int64 sqword; //!< sizeof(sqword) must be 8
typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8
#elif LINUX
typedef signed long long sqword; //!< sizeof(sqword) must be 8
typedef unsigned long long uqword; //!< sizeof(uqword) must be 8
#elif defined(__APPLE__)
typedef signed long long sqword; //!< sizeof(sqword) must be 8
typedef unsigned long long uqword; //!< sizeof(uqword) must be 8
#elif defined(_XBOX)
typedef signed __int64 sqword; //!< sizeof(sqword) must be 8
typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8
#endif
typedef float float32; //!< sizeof(float32) must be 4
typedef double float64; //!< sizeof(float64) must be 8
typedef size_t regsize; //!< sizeof(regsize) must be sizeof(void*)
// For test purpose you can force one of those:
// typedef udword regsize;
// typedef uqword regsize;
ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1); // ...otherwise things might fail with VC++ 4.2 !
ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1);
ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1);
ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2);
ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2);
ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8);
ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8);
ICE_COMPILE_TIME_ASSERT(sizeof(float32)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(float64)==8);
ICE_COMPILE_TIME_ASSERT(sizeof(regsize)==sizeof(void*));
//! TO BE DOCUMENTED
#define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
typedef udword DynID; //!< Dynamic identifier
#ifdef USE_HANDLE_MANAGER
typedef udword KID; //!< Kernel ID
// DECLARE_ICE_HANDLE(KID);
#else
typedef uword KID; //!< Kernel ID
#endif
#define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers)
#ifdef USE_HANDLE_MANAGER
#define INVALID_KID 0xffffffff //!< Invalid Kernel ID
#else
#define INVALID_KID 0xffff //!< Invalid Kernel ID
#endif
#define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value
// Define BOOL if needed
#ifndef BOOL
typedef int BOOL; //!< Another boolean type.
#endif
//! Union of a float and a sdword
typedef union {
float f; //!< The float
sdword d; //!< The integer
}scell;
//! Union of a float and a udword
typedef union {
float f; //!< The float
udword d; //!< The integer
}ucell;
// Type ranges
#define MAX_SBYTE 0x7f //!< max possible sbyte value
#define MIN_SBYTE 0x80 //!< min possible sbyte value
#define MAX_UBYTE 0xff //!< max possible ubyte value
#define MIN_UBYTE 0x00 //!< min possible ubyte value
#define MAX_SWORD 0x7fff //!< max possible sword value
#define MIN_SWORD 0x8000 //!< min possible sword value
#define MAX_UWORD 0xffff //!< max possible uword value
#define MIN_UWORD 0x0000 //!< min possible uword value
#define MAX_SDWORD 0x7fffffff //!< max possible sdword value
#define MIN_SDWORD 0x80000000 //!< min possible sdword value
#define MAX_UDWORD 0xffffffff //!< max possible udword value
#define MIN_UDWORD 0x00000000 //!< min possible udword value
#define MAX_FLOAT FLT_MAX //!< max possible float value
#define MIN_FLOAT (-FLT_MAX) //!< min possible loat value
#define IEEE_1_0 0x3f800000 //!< integer representation of 1.0
#define IEEE_255_0 0x437f0000 //!< integer representation of 255.0
#define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT
#define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT
#define IEEE_UNDERFLOW_LIMIT 0x1a000000
#define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand()
typedef void** VTABLE; //!< A V-Table.
#undef MIN
#undef MAX
#define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b
#define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b
#define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c
template<class T> inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; }
template<class T> inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; }
template<class T> inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; }
template<class T> inline_ void TSetMax (T& a, const T& b) { if(a<b) a = b; }
/* Obsolete stuff - if needed, move to dedicated header and include in few files using this.
#define SQR(x) ((x)*(x)) //!< Returns x square
#define CUBE(x) ((x)*(x)*(x)) //!< Returns x cube
#define AND & //!< ...
#define OR | //!< ...
#define XOR ^ //!< ...
#define QUADRAT(x) ((x)*(x)) //!< Returns x square
typedef int (__stdcall* PROC)(); //!< A standard procedure call.
typedef bool (*ENUMERATION)(udword value, udword param, udword context); //!< ICE standard enumeration call
#ifdef _WIN32
// Used to compile legacy code
__forceinline void srand48(udword x) { srand(x); }
__forceinline void srandom(udword x) { srand(x); }
__forceinline double random() { return (double)rand(); }
__forceinline double drand48() { return (double) ( ((double)rand()) / ((double)RAND_MAX) ); }
#endif
*/
#endif // ICETYPES_H

View File

@@ -1,55 +1,55 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains misc. useful macros & defines.
* \file IceUtils.cpp
* \author Pierre Terdiman (collected from various sources)
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns the alignment of the input address.
* \fn Alignment()
* \param address [in] address to check
* \return the best alignment (e.g. 1 for odd addresses, etc)
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
udword IceCore::Alignment(udword address)
{
// Returns 0 for null addresses
if(!address) return 0;
// Test all bits
udword Align = 1;
for(udword i=1;i<32;i++)
{
// Returns as soon as the alignment is broken
if(address&Align) return Align;
Align<<=1;
}
// Here all bits are null, except the highest one (else the address would be null)
return Align;
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains misc. useful macros & defines.
* \file IceUtils.cpp
* \author Pierre Terdiman (collected from various sources)
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns the alignment of the input address.
* \fn Alignment()
* \param address [in] address to check
* \return the best alignment (e.g. 1 for odd addresses, etc)
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
udword IceCore::Alignment(udword address)
{
// Returns 0 for null addresses
if(!address) return 0;
// Test all bits
udword Align = 1;
for(udword i=1;i<32;i++)
{
// Returns as soon as the alignment is broken
if(address&Align) return Align;
Align<<=1;
}
// Here all bits are null, except the highest one (else the address would be null)
return Align;
}

View File

@@ -1,377 +1,377 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains misc. useful macros & defines.
* \file IceUtils.h
* \author Pierre Terdiman (personal code + collected from various sources)
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEUTILS_H
#define ICEUTILS_H
#define START_RUNONCE { static bool __RunOnce__ = false; if(!__RunOnce__){
#define END_RUNONCE __RunOnce__ = true;}}
//! Reverse all the bits in a 32 bit word (from Steve Baker's Cute Code Collection)
//! (each line can be done in any order.
inline_ void ReverseBits(udword& n)
{
n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
// Etc for larger integers (64 bits in Java)
// NOTE: the >> operation must be unsigned! (>>> in java)
}
//! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection)
inline_ udword CountBits(udword n)
{
// This relies of the fact that the count of n bits can NOT overflow
// an n bit integer. EG: 1 bit count takes a 1 bit integer, 2 bit counts
// 2 bit integer, 3 bit count requires only a 2 bit integer.
// So we add all bit pairs, then each nible, then each byte etc...
n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1);
n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2);
n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4);
n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8);
n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16);
// Etc for larger integers (64 bits in Java)
// NOTE: the >> operation must be unsigned! (>>> in java)
return n;
}
//! Even faster?
inline_ udword CountBits2(udword bits)
{
bits = bits - ((bits >> 1) & 0x55555555);
bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333);
bits = ((bits >> 4) + bits) & 0x0F0F0F0F;
return (bits * 0x01010101) >> 24;
}
// "Population Count (Ones Count)
// The population count of a binary integer value x is the number of one bits in the value. Although many machines have
// single instructions for this, the single instructions are usually microcoded loops that test a bit per cycle; a log-time
// algorithm coded in C is often faster. The following code uses a variable-precision SWAR algorithm to perform a tree
// reduction adding the bits in a 32-bit value:"
inline_ udword ones32(udword x)
{
/* 32-bit recursive reduction using SWAR...
but first step is mapping 2-bit values
into sum of 2 1-bit values in sneaky way
*/
x -= ((x >> 1) & 0x55555555);
x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
x = (((x >> 4) + x) & 0x0f0f0f0f);
x += (x >> 8);
x += (x >> 16);
return (x & 0x0000003f);
// "It is worthwhile noting that the SWAR population count algorithm given above can be improved upon for the case of
// counting the population of multi-word bit sets. How? The last few steps in the reduction are using only a portion
// of the SWAR width to produce their results; thus, it would be possible to combine these steps across multiple words
// being reduced. One additional note: the AMD Athlon optimization guidelines suggest a very similar algorithm that
// replaces the last three lines with return((x * 0x01010101) >> 24);. For the Athlon (which has a very fast integer
// multiply), I would have expected AMD's code to be faster... but it is actually 6% slower according to my benchmarks
// using a 1.2GHz Athlon (a Thunderbird). Why? Well, it so happens that GCC doesn't use a multiply instruction - it
// writes out the equivalent shift and add sequence!"
}
// "Trailing Zero Count
// Given the Least Significant 1 Bit and Population Count (Ones Count) algorithms, it is trivial to combine them to
// construct a trailing zero count (as pointed-out by Joe Bowbeer):"
inline_ udword tzc(sdword x)
{
return(ones32((x & -x) - 1));
}
//! Spread out bits. EG 00001111 -> 0101010101
//! 00001010 -> 0100010000
//! This is used to interleave two integers to produce a `Morton Key'
//! used in Space Filling Curves (See DrDobbs Journal, July 1999)
//! Order is important.
inline_ void SpreadBits(udword& n)
{
n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16);
n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8);
n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4);
n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2);
n = ( n & 0x11111111) | (( n & 0x22222222) << 1);
}
// "Next Largest Power of 2
// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
// largest power of 2. For a 32-bit value:"
inline_ udword NextPowerOfTwo(udword x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x+1;
}
//! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection)
inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); }
//! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection)
inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); }
//! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection)
inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<<n); }
//! Classic XOR swap (from Steve Baker's Cute Code Collection)
//! x ^= y; /* x' = (x^y) */
//! y ^= x; /* y' = (y^(x^y)) = x */
//! x ^= y; /* x' = (x^y)^x = y */
inline_ void Swap(udword& x, udword& y) { x ^= y; y ^= x; x ^= y; }
//! Little/Big endian (from Steve Baker's Cute Code Collection)
//!
//! Extra comments by Kenny Hoff:
//! Determines the byte-ordering of the current machine (little or big endian)
//! by setting an integer value to 1 (so least significant bit is now 1); take
//! the address of the int and cast to a byte pointer (treat integer as an
//! array of four bytes); check the value of the first byte (must be 0 or 1).
//! If the value is 1, then the first byte least significant byte and this
//! implies LITTLE endian. If the value is 0, the first byte is the most
//! significant byte, BIG endian. Examples:
//! integer 1 on BIG endian: 00000000 00000000 00000000 00000001
//! integer 1 on LITTLE endian: 00000001 00000000 00000000 00000000
//!---------------------------------------------------------------------------
//! int IsLittleEndian() { int x=1; return ( ((char*)(&x))[0] ); }
inline_ char LittleEndian() { int i = 1; return *((char*)&i); }
//!< Alternative abs function
inline_ udword abs_(sdword x) { sdword y= x >> 31; return (x^y)-y; }
// "Integer Minimum or Maximum
// Given 2's complement integer values x and y, the minimum can be computed without any branches as
// x+(((y-x)>>(WORDBITS-1))&(y-x)).
// Logically, this works because the shift by (WORDBITS-1) replicates the sign bit to create a mask
// -- be aware, however, that the C language does not require that shifts are signed even if their
// operands are signed, so there is a potential portability problem. Additionally, one might think
// that a shift by any number greater than or equal to WORDBITS would have the same effect, but many
// instruction sets have shifts that behave strangely when such shift distances are specified.
// Of course, maximum can be computed using the same trick:
// x-(((x-y)>>(WORDBITS-1))&(x-y))."
//!< Alternative min function
inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); }
//!< Alternative max function
inline_ sdword max_(sdword a, sdword b) { sdword delta = a-b; return a - (delta&(delta>>31)); }
// "Integer Selection
// A branchless, lookup-free, alternative to code like if (a<b) x=c; else x=d; is ((((a-b) >> (WORDBITS-1)) & (c^d)) ^ d).
// This code assumes that the shift is signed, which, of course, C does not promise."
inline_ sdword IntegerSelection(sdword a, sdword b, sdword c, sdword d)
{
return ((((a-b)>>31) & (c^d)) ^ d);
}
// Determine if one of the bytes in a 4 byte word is zero
inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); }
// To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0
inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); }
// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); }
// "Most Significant 1 Bit
// Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set)
// can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits.
// This process yields a bit vector with the same most significant 1 as x, but all 1's below it.
// Bitwise AND of the original value with the complement of the "folded" value shifted down by one
// yields the most significant bit. For a 32-bit value:"
inline_ udword msb32(udword x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return (x & ~(x >> 1));
}
// "Gray Code Conversion
// A Gray code is any binary coding sequence in which only a single bit position changes as we move from one value to the next.
// There are many such codes, but the traditional one is computed such that the Kth Gray code is K^(K>>1).
//
// The well-known algorithm for conversion from Gray to binary is a linear sequence of XORs that makes it seem each bit must be
// dealt with separately. Fortunately, that is equivalent to a parallel prefix XOR that can be computed using SWAR techniques
// in log time. For 32-bit Gray code values produced as described above, the conversion from Gray code back to unsigned binary is:"
inline_ udword g2b(udword gray)
{
gray ^= (gray >> 16);
gray ^= (gray >> 8);
gray ^= (gray >> 4);
gray ^= (gray >> 2);
gray ^= (gray >> 1);
return gray;
}
/*
"Just call it repeatedly with various input values and always with the same variable as "memory".
The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1
does no filtering at all.
I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed
to the more typical FIR (Finite Impulse Response).
Also, I'd say that you can make more intelligent and interesting filters than this, for example filters
that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter
to be applied before this one, of course."
(JCAB on Flipcode)
*/
inline_ float FeedbackFilter(float val, float& memory, float sharpness)
{
ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter");
if(sharpness<0.0f) sharpness = 0.0f;
else if(sharpness>1.0f) sharpness = 1.0f;
return memory = val * sharpness + memory * (1.0f - sharpness);
}
//! "If you can guarantee that your input domain (i.e. value of x) is slightly
//! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the
//! following code to clamp the resulting value into [-32768,+32767] range:"
inline_ int ClampToInt16(int x)
{
// ASSERT(abs(x) < (int)((1<<31u)-32767));
int delta = 32767 - x;
x += (delta>>31) & delta;
delta = x + 32768;
x -= (delta>>31) & delta;
return x;
}
// Generic functions
template<class Type> inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; }
template<class Type> inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((x<lo) ? lo : (x>hi) ? hi : x); }
template<class Type> inline_ void TSort(Type& a, Type& b)
{
if(a>b) TSwap(a, b);
}
template<class Type> inline_ void TSort(Type& a, Type& b, Type& c)
{
if(a>b) TSwap(a, b);
if(b>c) TSwap(b, c);
if(a>b) TSwap(a, b);
if(b>c) TSwap(b, c);
}
// Prevent nasty user-manipulations (strategy borrowed from Charles Bloom)
// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); }
// ... actually this is better !
#define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object);
//! TO BE DOCUMENTED
#define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member)
//! TO BE DOCUMENTED
#if !defined(_XBOX)
// Already defined on Xbox.
#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns the alignment of the input address.
* \fn Alignment()
* \param address [in] address to check
* \return the best alignment (e.g. 1 for odd addresses, etc)
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FUNCTION ICECORE_API udword Alignment(udword address);
#define IS_ALIGNED_2(x) ((x&1)==0)
#define IS_ALIGNED_4(x) ((x&3)==0)
#define IS_ALIGNED_8(x) ((x&7)==0)
// Updates a pointer with "stride" bytes
inline_ void UpdatePtr(void*& ptr, udword stride) { ptr = ((ubyte*)ptr) + stride; }
// From Jon Watte IIRC
inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; }
// Compute implicit coords from an index:
// The idea is to get back 2D coords from a 1D index.
// For example:
//
// 0 1 2 ... nbu-1
// nbu nbu+1 i ...
//
// We have i, we're looking for the equivalent (u=2, v=1) location.
// i = u + v*nbu
// <=> i/nbu = u/nbu + v
// Since 0 <= u < nbu, u/nbu = 0 (integer)
// Hence: v = i/nbu
// Then we simply put it back in the original equation to compute u = i - v*nbu
inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu)
{
v = i / nbu;
u = i - (v * nbu);
}
// In 3D: i = u + v*nbu + w*nbu*nbv
// <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w
// u/(nbu*nbv) is null since u/nbu was null already.
// v/nbv is null as well for the same reason.
// Hence w = i/(nbu*nbv)
// Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu
inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv)
{
w = i / (nbu_nbv);
Compute2DCoords(u, v, i - (w * nbu_nbv), nbu);
}
// Calling fsincos instead of fsin+fcos. Twice faster.
inline_ void FSinCos(float& c, float& s, float f)
{
float LocalCos, LocalSin;
float Local = f;
#ifdef WIN32
_asm fld Local
_asm fsincos
_asm fstp LocalCos
_asm fstp LocalSin
#elif LINUX
asm("fld Local\n\t"
"fsincos\n\t"
"fstp LocalCos\n\t"
"fstp LocalSin\n\t"
);
#endif
c = LocalCos;
s = LocalSin;
}
// Modulo3 macros. See http://www.codercorner.com/Modulo3.htm
#define GET_NEXT_INDICES(i, j, k) \
k = 0x01000201; \
k>>=(i<<3); \
j = k & 0xff; \
k>>=8; \
k&=0xff;
#define GET_NEXT_INDICES2(i, j, k) \
j = ( 9 >> (i<<1)) & 3; \
k = (18 >> (i<<1)) & 3;
// 0=>1, 1=>2, 2=>0
inline_ udword Modulo3(udword i)
{
ASSERT(i==0 || i==1 || i==2);
return (9 >> (i << 1)) & 3;
}
#endif // ICEUTILS_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains misc. useful macros & defines.
* \file IceUtils.h
* \author Pierre Terdiman (personal code + collected from various sources)
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef ICEUTILS_H
#define ICEUTILS_H
#define START_RUNONCE { static bool __RunOnce__ = false; if(!__RunOnce__){
#define END_RUNONCE __RunOnce__ = true;}}
//! Reverse all the bits in a 32 bit word (from Steve Baker's Cute Code Collection)
//! (each line can be done in any order.
inline_ void ReverseBits(udword& n)
{
n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
// Etc for larger integers (64 bits in Java)
// NOTE: the >> operation must be unsigned! (>>> in java)
}
//! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection)
inline_ udword CountBits(udword n)
{
// This relies of the fact that the count of n bits can NOT overflow
// an n bit integer. EG: 1 bit count takes a 1 bit integer, 2 bit counts
// 2 bit integer, 3 bit count requires only a 2 bit integer.
// So we add all bit pairs, then each nible, then each byte etc...
n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1);
n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2);
n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4);
n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8);
n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16);
// Etc for larger integers (64 bits in Java)
// NOTE: the >> operation must be unsigned! (>>> in java)
return n;
}
//! Even faster?
inline_ udword CountBits2(udword bits)
{
bits = bits - ((bits >> 1) & 0x55555555);
bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333);
bits = ((bits >> 4) + bits) & 0x0F0F0F0F;
return (bits * 0x01010101) >> 24;
}
// "Population Count (Ones Count)
// The population count of a binary integer value x is the number of one bits in the value. Although many machines have
// single instructions for this, the single instructions are usually microcoded loops that test a bit per cycle; a log-time
// algorithm coded in C is often faster. The following code uses a variable-precision SWAR algorithm to perform a tree
// reduction adding the bits in a 32-bit value:"
inline_ udword ones32(udword x)
{
/* 32-bit recursive reduction using SWAR...
but first step is mapping 2-bit values
into sum of 2 1-bit values in sneaky way
*/
x -= ((x >> 1) & 0x55555555);
x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
x = (((x >> 4) + x) & 0x0f0f0f0f);
x += (x >> 8);
x += (x >> 16);
return (x & 0x0000003f);
// "It is worthwhile noting that the SWAR population count algorithm given above can be improved upon for the case of
// counting the population of multi-word bit sets. How? The last few steps in the reduction are using only a portion
// of the SWAR width to produce their results; thus, it would be possible to combine these steps across multiple words
// being reduced. One additional note: the AMD Athlon optimization guidelines suggest a very similar algorithm that
// replaces the last three lines with return((x * 0x01010101) >> 24);. For the Athlon (which has a very fast integer
// multiply), I would have expected AMD's code to be faster... but it is actually 6% slower according to my benchmarks
// using a 1.2GHz Athlon (a Thunderbird). Why? Well, it so happens that GCC doesn't use a multiply instruction - it
// writes out the equivalent shift and add sequence!"
}
// "Trailing Zero Count
// Given the Least Significant 1 Bit and Population Count (Ones Count) algorithms, it is trivial to combine them to
// construct a trailing zero count (as pointed-out by Joe Bowbeer):"
inline_ udword tzc(sdword x)
{
return(ones32((x & -x) - 1));
}
//! Spread out bits. EG 00001111 -> 0101010101
//! 00001010 -> 0100010000
//! This is used to interleave two integers to produce a `Morton Key'
//! used in Space Filling Curves (See DrDobbs Journal, July 1999)
//! Order is important.
inline_ void SpreadBits(udword& n)
{
n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16);
n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8);
n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4);
n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2);
n = ( n & 0x11111111) | (( n & 0x22222222) << 1);
}
// "Next Largest Power of 2
// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
// largest power of 2. For a 32-bit value:"
inline_ udword NextPowerOfTwo(udword x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x+1;
}
//! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection)
inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); }
//! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection)
inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); }
//! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection)
inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<<n); }
//! Classic XOR swap (from Steve Baker's Cute Code Collection)
//! x ^= y; /* x' = (x^y) */
//! y ^= x; /* y' = (y^(x^y)) = x */
//! x ^= y; /* x' = (x^y)^x = y */
inline_ void Swap(udword& x, udword& y) { x ^= y; y ^= x; x ^= y; }
//! Little/Big endian (from Steve Baker's Cute Code Collection)
//!
//! Extra comments by Kenny Hoff:
//! Determines the byte-ordering of the current machine (little or big endian)
//! by setting an integer value to 1 (so least significant bit is now 1); take
//! the address of the int and cast to a byte pointer (treat integer as an
//! array of four bytes); check the value of the first byte (must be 0 or 1).
//! If the value is 1, then the first byte least significant byte and this
//! implies LITTLE endian. If the value is 0, the first byte is the most
//! significant byte, BIG endian. Examples:
//! integer 1 on BIG endian: 00000000 00000000 00000000 00000001
//! integer 1 on LITTLE endian: 00000001 00000000 00000000 00000000
//!---------------------------------------------------------------------------
//! int IsLittleEndian() { int x=1; return ( ((char*)(&x))[0] ); }
inline_ char LittleEndian() { int i = 1; return *((char*)&i); }
//!< Alternative abs function
inline_ udword abs_(sdword x) { sdword y= x >> 31; return (x^y)-y; }
// "Integer Minimum or Maximum
// Given 2's complement integer values x and y, the minimum can be computed without any branches as
// x+(((y-x)>>(WORDBITS-1))&(y-x)).
// Logically, this works because the shift by (WORDBITS-1) replicates the sign bit to create a mask
// -- be aware, however, that the C language does not require that shifts are signed even if their
// operands are signed, so there is a potential portability problem. Additionally, one might think
// that a shift by any number greater than or equal to WORDBITS would have the same effect, but many
// instruction sets have shifts that behave strangely when such shift distances are specified.
// Of course, maximum can be computed using the same trick:
// x-(((x-y)>>(WORDBITS-1))&(x-y))."
//!< Alternative min function
inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); }
//!< Alternative max function
inline_ sdword max_(sdword a, sdword b) { sdword delta = a-b; return a - (delta&(delta>>31)); }
// "Integer Selection
// A branchless, lookup-free, alternative to code like if (a<b) x=c; else x=d; is ((((a-b) >> (WORDBITS-1)) & (c^d)) ^ d).
// This code assumes that the shift is signed, which, of course, C does not promise."
inline_ sdword IntegerSelection(sdword a, sdword b, sdword c, sdword d)
{
return ((((a-b)>>31) & (c^d)) ^ d);
}
// Determine if one of the bytes in a 4 byte word is zero
inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); }
// To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0
inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); }
// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); }
// "Most Significant 1 Bit
// Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set)
// can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits.
// This process yields a bit vector with the same most significant 1 as x, but all 1's below it.
// Bitwise AND of the original value with the complement of the "folded" value shifted down by one
// yields the most significant bit. For a 32-bit value:"
inline_ udword msb32(udword x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return (x & ~(x >> 1));
}
// "Gray Code Conversion
// A Gray code is any binary coding sequence in which only a single bit position changes as we move from one value to the next.
// There are many such codes, but the traditional one is computed such that the Kth Gray code is K^(K>>1).
//
// The well-known algorithm for conversion from Gray to binary is a linear sequence of XORs that makes it seem each bit must be
// dealt with separately. Fortunately, that is equivalent to a parallel prefix XOR that can be computed using SWAR techniques
// in log time. For 32-bit Gray code values produced as described above, the conversion from Gray code back to unsigned binary is:"
inline_ udword g2b(udword gray)
{
gray ^= (gray >> 16);
gray ^= (gray >> 8);
gray ^= (gray >> 4);
gray ^= (gray >> 2);
gray ^= (gray >> 1);
return gray;
}
/*
"Just call it repeatedly with various input values and always with the same variable as "memory".
The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1
does no filtering at all.
I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed
to the more typical FIR (Finite Impulse Response).
Also, I'd say that you can make more intelligent and interesting filters than this, for example filters
that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter
to be applied before this one, of course."
(JCAB on Flipcode)
*/
inline_ float FeedbackFilter(float val, float& memory, float sharpness)
{
ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter");
if(sharpness<0.0f) sharpness = 0.0f;
else if(sharpness>1.0f) sharpness = 1.0f;
return memory = val * sharpness + memory * (1.0f - sharpness);
}
//! "If you can guarantee that your input domain (i.e. value of x) is slightly
//! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the
//! following code to clamp the resulting value into [-32768,+32767] range:"
inline_ int ClampToInt16(int x)
{
// ASSERT(abs(x) < (int)((1<<31u)-32767));
int delta = 32767 - x;
x += (delta>>31) & delta;
delta = x + 32768;
x -= (delta>>31) & delta;
return x;
}
// Generic functions
template<class Type> inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; }
template<class Type> inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((x<lo) ? lo : (x>hi) ? hi : x); }
template<class Type> inline_ void TSort(Type& a, Type& b)
{
if(a>b) TSwap(a, b);
}
template<class Type> inline_ void TSort(Type& a, Type& b, Type& c)
{
if(a>b) TSwap(a, b);
if(b>c) TSwap(b, c);
if(a>b) TSwap(a, b);
if(b>c) TSwap(b, c);
}
// Prevent nasty user-manipulations (strategy borrowed from Charles Bloom)
// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); }
// ... actually this is better !
#define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object);
//! TO BE DOCUMENTED
#define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member)
//! TO BE DOCUMENTED
#if !defined(_XBOX)
// Already defined on Xbox.
#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns the alignment of the input address.
* \fn Alignment()
* \param address [in] address to check
* \return the best alignment (e.g. 1 for odd addresses, etc)
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FUNCTION ICECORE_API udword Alignment(udword address);
#define IS_ALIGNED_2(x) ((x&1)==0)
#define IS_ALIGNED_4(x) ((x&3)==0)
#define IS_ALIGNED_8(x) ((x&7)==0)
// Updates a pointer with "stride" bytes
inline_ void UpdatePtr(void*& ptr, udword stride) { ptr = ((ubyte*)ptr) + stride; }
// From Jon Watte IIRC
inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; }
// Compute implicit coords from an index:
// The idea is to get back 2D coords from a 1D index.
// For example:
//
// 0 1 2 ... nbu-1
// nbu nbu+1 i ...
//
// We have i, we're looking for the equivalent (u=2, v=1) location.
// i = u + v*nbu
// <=> i/nbu = u/nbu + v
// Since 0 <= u < nbu, u/nbu = 0 (integer)
// Hence: v = i/nbu
// Then we simply put it back in the original equation to compute u = i - v*nbu
inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu)
{
v = i / nbu;
u = i - (v * nbu);
}
// In 3D: i = u + v*nbu + w*nbu*nbv
// <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w
// u/(nbu*nbv) is null since u/nbu was null already.
// v/nbv is null as well for the same reason.
// Hence w = i/(nbu*nbv)
// Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu
inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv)
{
w = i / (nbu_nbv);
Compute2DCoords(u, v, i - (w * nbu_nbv), nbu);
}
// Calling fsincos instead of fsin+fcos. Twice faster.
inline_ void FSinCos(float& c, float& s, float f)
{
float LocalCos, LocalSin;
float Local = f;
#ifdef WIN32
_asm fld Local
_asm fsincos
_asm fstp LocalCos
_asm fstp LocalSin
#elif LINUX
asm("fld Local\n\t"
"fsincos\n\t"
"fstp LocalCos\n\t"
"fstp LocalSin\n\t"
);
#endif
c = LocalCos;
s = LocalSin;
}
// Modulo3 macros. See http://www.codercorner.com/Modulo3.htm
#define GET_NEXT_INDICES(i, j, k) \
k = 0x01000201; \
k>>=(i<<3); \
j = k & 0xff; \
k>>=8; \
k&=0xff;
#define GET_NEXT_INDICES2(i, j, k) \
j = ( 9 >> (i<<1)) & 3; \
k = (18 >> (i<<1)) & 3;
// 0=>1, 1=>2, 2=>0
inline_ udword Modulo3(udword i)
{
ASSERT(i==0 || i==1 || i==2);
return (9 >> (i << 1)) & 3;
}
#endif // ICEUTILS_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,361 +1,361 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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;
}
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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;
}

View File

@@ -1,228 +1,228 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 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__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 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__

View File

@@ -1,333 +1,333 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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
//! Integer representation of a floating-point value.
#define IR(x) ((udword&)(x))
//! Signed integer representation of a floating-point value.
#define SIR(x) ((sdword&)(x))
//! 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))
//! 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)
{
float retval;
__asm {
mov eax, square
sub eax, 0x3F800000
sar eax, 1
add eax, 0x3F800000
mov [retval], eax
}
return retval;
}
//! Saturates positive to zero.
inline_ float fsat(float f)
{
udword y = (udword&)f & ~((sdword&)f >>31);
return (float&)y;
}
//! Computes 1.0f / sqrtf(x).
inline_ float frsqrt(float f)
{
float x = f * 0.5f;
udword y = 0x5f3759df - ((udword&)f >> 1);
// Iteration...
(float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) );
// Result
return (float&)y;
}
//! Computes 1.0f / sqrtf(x). Comes from NVIDIA.
inline_ float InvSqrt(const float& x)
{
udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1;
float y = *(float*)&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)
{
long i;
float x2, y;
const float threehalfs = 1.5f;
x2 = number * 0.5f;
y = number;
i = * (long *) &y;
i = 0x5f3759df - (i >> 1);
y = * (float *) &i;
y = y * (threehalfs - (x2 * y * y));
return y;
}
//! TO BE DOCUMENTED
inline_ float fsqrt(float f)
{
udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000;
// Iteration...?
// (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f;
// Result
return (float&)y;
}
//! Returns the float ranged espilon value.
inline_ float fepsilon(float f)
{
udword b = (udword&)f & 0xff800000;
udword a = b | 0x00000001;
(float&)a -= (float&)b;
// Result
return (float&)a;
}
//! 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
mov wTemp, ax
fldcw wTemp
}
}
}
}
*/
//! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON)
inline_ float ComputeFloatEpsilon()
{
float f = 1.0f;
((udword&)f)^=1;
return f - 1.0f; // You can check it's the same as FLT_EPSILON
}
inline_ bool IsFloatZero(float x, float epsilon=1e-6f)
{
return x*x < epsilon;
}
#define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0
#define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0
#define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0
#define FCMOVNB_ST0 _asm _emit 0xdb _asm _emit 0xc0
#define FCOMI_ST1 _asm _emit 0xdb _asm _emit 0xf1
#define FCOMIP_ST1 _asm _emit 0xdf _asm _emit 0xf1
#define FCMOVB_ST1 _asm _emit 0xda _asm _emit 0xc1
#define FCMOVNB_ST1 _asm _emit 0xdb _asm _emit 0xc1
#define FCOMI_ST2 _asm _emit 0xdb _asm _emit 0xf2
#define FCOMIP_ST2 _asm _emit 0xdf _asm _emit 0xf2
#define FCMOVB_ST2 _asm _emit 0xda _asm _emit 0xc2
#define FCMOVNB_ST2 _asm _emit 0xdb _asm _emit 0xc2
#define FCOMI_ST3 _asm _emit 0xdb _asm _emit 0xf3
#define FCOMIP_ST3 _asm _emit 0xdf _asm _emit 0xf3
#define FCMOVB_ST3 _asm _emit 0xda _asm _emit 0xc3
#define FCMOVNB_ST3 _asm _emit 0xdb _asm _emit 0xc3
#define FCOMI_ST4 _asm _emit 0xdb _asm _emit 0xf4
#define FCOMIP_ST4 _asm _emit 0xdf _asm _emit 0xf4
#define FCMOVB_ST4 _asm _emit 0xda _asm _emit 0xc4
#define FCMOVNB_ST4 _asm _emit 0xdb _asm _emit 0xc4
#define FCOMI_ST5 _asm _emit 0xdb _asm _emit 0xf5
#define FCOMIP_ST5 _asm _emit 0xdf _asm _emit 0xf5
#define FCMOVB_ST5 _asm _emit 0xda _asm _emit 0xc5
#define FCMOVNB_ST5 _asm _emit 0xdb _asm _emit 0xc5
#define FCOMI_ST6 _asm _emit 0xdb _asm _emit 0xf6
#define FCOMIP_ST6 _asm _emit 0xdf _asm _emit 0xf6
#define FCMOVB_ST6 _asm _emit 0xda _asm _emit 0xc6
#define FCMOVNB_ST6 _asm _emit 0xdb _asm _emit 0xc6
#define FCOMI_ST7 _asm _emit 0xdb _asm _emit 0xf7
#define FCOMIP_ST7 _asm _emit 0xdf _asm _emit 0xf7
#define FCMOVB_ST7 _asm _emit 0xda _asm _emit 0xc7
#define FCMOVNB_ST7 _asm _emit 0xdb _asm _emit 0xc7
//! A global function to find MAX(a,b) using FCOMI/FCMOV
inline_ float FCMax2(float a, float b)
{
float Res;
_asm fld [a]
_asm fld [b]
FCOMI_ST1
FCMOVB_ST1
_asm fstp [Res]
_asm fcomp
return Res;
}
//! A global function to find MIN(a,b) using FCOMI/FCMOV
inline_ float FCMin2(float a, float b)
{
float Res;
_asm fld [a]
_asm fld [b]
FCOMI_ST1
FCMOVNB_ST1
_asm fstp [Res]
_asm fcomp
return Res;
}
//! A global function to find MAX(a,b,c) using FCOMI/FCMOV
inline_ float FCMax3(float a, float b, float c)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
FCOMI_ST1
FCMOVB_ST1
FCOMI_ST2
FCMOVB_ST2
_asm fstp [Res]
_asm fcompp
return Res;
}
//! A global function to find MIN(a,b,c) using FCOMI/FCMOV
inline_ float FCMin3(float a, float b, float c)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
FCOMI_ST1
FCMOVNB_ST1
FCOMI_ST2
FCMOVNB_ST2
_asm fstp [Res]
_asm fcompp
return Res;
}
inline_ int ConvertToSortable(float f)
{
int& Fi = (int&)f;
int Fmask = (Fi>>31);
Fi ^= Fmask;
Fmask &= ~(1<<31);
Fi -= Fmask;
return Fi;
}
enum FPUMode
{
FPU_FLOOR = 0,
FPU_CEIL = 1,
FPU_BEST = 2,
FPU_FORCE_DWORD = 0x7fffffff
};
FUNCTION ICECORE_API FPUMode GetFPUMode();
FUNCTION ICECORE_API void SaveFPU();
FUNCTION ICECORE_API void RestoreFPU();
FUNCTION ICECORE_API void SetFPUFloorMode();
FUNCTION ICECORE_API void SetFPUCeilMode();
FUNCTION ICECORE_API void SetFPUBestMode();
FUNCTION ICECORE_API void SetFPUPrecision24();
FUNCTION ICECORE_API void SetFPUPrecision53();
FUNCTION ICECORE_API void SetFPUPrecision64();
FUNCTION ICECORE_API void SetFPURoundingChop();
FUNCTION ICECORE_API void SetFPURoundingUp();
FUNCTION ICECORE_API void SetFPURoundingDown();
FUNCTION ICECORE_API void SetFPURoundingNear();
FUNCTION ICECORE_API int intChop(const float& f);
FUNCTION ICECORE_API int intFloor(const float& f);
FUNCTION ICECORE_API int intCeil(const float& f);
#endif // __ICEFPU_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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
//! Integer representation of a floating-point value.
#define IR(x) ((udword&)(x))
//! Signed integer representation of a floating-point value.
#define SIR(x) ((sdword&)(x))
//! 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))
//! 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)
{
float retval;
__asm {
mov eax, square
sub eax, 0x3F800000
sar eax, 1
add eax, 0x3F800000
mov [retval], eax
}
return retval;
}
//! Saturates positive to zero.
inline_ float fsat(float f)
{
udword y = (udword&)f & ~((sdword&)f >>31);
return (float&)y;
}
//! Computes 1.0f / sqrtf(x).
inline_ float frsqrt(float f)
{
float x = f * 0.5f;
udword y = 0x5f3759df - ((udword&)f >> 1);
// Iteration...
(float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) );
// Result
return (float&)y;
}
//! Computes 1.0f / sqrtf(x). Comes from NVIDIA.
inline_ float InvSqrt(const float& x)
{
udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1;
float y = *(float*)&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)
{
long i;
float x2, y;
const float threehalfs = 1.5f;
x2 = number * 0.5f;
y = number;
i = * (long *) &y;
i = 0x5f3759df - (i >> 1);
y = * (float *) &i;
y = y * (threehalfs - (x2 * y * y));
return y;
}
//! TO BE DOCUMENTED
inline_ float fsqrt(float f)
{
udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000;
// Iteration...?
// (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f;
// Result
return (float&)y;
}
//! Returns the float ranged espilon value.
inline_ float fepsilon(float f)
{
udword b = (udword&)f & 0xff800000;
udword a = b | 0x00000001;
(float&)a -= (float&)b;
// Result
return (float&)a;
}
//! 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
mov wTemp, ax
fldcw wTemp
}
}
}
}
*/
//! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON)
inline_ float ComputeFloatEpsilon()
{
float f = 1.0f;
((udword&)f)^=1;
return f - 1.0f; // You can check it's the same as FLT_EPSILON
}
inline_ bool IsFloatZero(float x, float epsilon=1e-6f)
{
return x*x < epsilon;
}
#define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0
#define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0
#define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0
#define FCMOVNB_ST0 _asm _emit 0xdb _asm _emit 0xc0
#define FCOMI_ST1 _asm _emit 0xdb _asm _emit 0xf1
#define FCOMIP_ST1 _asm _emit 0xdf _asm _emit 0xf1
#define FCMOVB_ST1 _asm _emit 0xda _asm _emit 0xc1
#define FCMOVNB_ST1 _asm _emit 0xdb _asm _emit 0xc1
#define FCOMI_ST2 _asm _emit 0xdb _asm _emit 0xf2
#define FCOMIP_ST2 _asm _emit 0xdf _asm _emit 0xf2
#define FCMOVB_ST2 _asm _emit 0xda _asm _emit 0xc2
#define FCMOVNB_ST2 _asm _emit 0xdb _asm _emit 0xc2
#define FCOMI_ST3 _asm _emit 0xdb _asm _emit 0xf3
#define FCOMIP_ST3 _asm _emit 0xdf _asm _emit 0xf3
#define FCMOVB_ST3 _asm _emit 0xda _asm _emit 0xc3
#define FCMOVNB_ST3 _asm _emit 0xdb _asm _emit 0xc3
#define FCOMI_ST4 _asm _emit 0xdb _asm _emit 0xf4
#define FCOMIP_ST4 _asm _emit 0xdf _asm _emit 0xf4
#define FCMOVB_ST4 _asm _emit 0xda _asm _emit 0xc4
#define FCMOVNB_ST4 _asm _emit 0xdb _asm _emit 0xc4
#define FCOMI_ST5 _asm _emit 0xdb _asm _emit 0xf5
#define FCOMIP_ST5 _asm _emit 0xdf _asm _emit 0xf5
#define FCMOVB_ST5 _asm _emit 0xda _asm _emit 0xc5
#define FCMOVNB_ST5 _asm _emit 0xdb _asm _emit 0xc5
#define FCOMI_ST6 _asm _emit 0xdb _asm _emit 0xf6
#define FCOMIP_ST6 _asm _emit 0xdf _asm _emit 0xf6
#define FCMOVB_ST6 _asm _emit 0xda _asm _emit 0xc6
#define FCMOVNB_ST6 _asm _emit 0xdb _asm _emit 0xc6
#define FCOMI_ST7 _asm _emit 0xdb _asm _emit 0xf7
#define FCOMIP_ST7 _asm _emit 0xdf _asm _emit 0xf7
#define FCMOVB_ST7 _asm _emit 0xda _asm _emit 0xc7
#define FCMOVNB_ST7 _asm _emit 0xdb _asm _emit 0xc7
//! A global function to find MAX(a,b) using FCOMI/FCMOV
inline_ float FCMax2(float a, float b)
{
float Res;
_asm fld [a]
_asm fld [b]
FCOMI_ST1
FCMOVB_ST1
_asm fstp [Res]
_asm fcomp
return Res;
}
//! A global function to find MIN(a,b) using FCOMI/FCMOV
inline_ float FCMin2(float a, float b)
{
float Res;
_asm fld [a]
_asm fld [b]
FCOMI_ST1
FCMOVNB_ST1
_asm fstp [Res]
_asm fcomp
return Res;
}
//! A global function to find MAX(a,b,c) using FCOMI/FCMOV
inline_ float FCMax3(float a, float b, float c)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
FCOMI_ST1
FCMOVB_ST1
FCOMI_ST2
FCMOVB_ST2
_asm fstp [Res]
_asm fcompp
return Res;
}
//! A global function to find MIN(a,b,c) using FCOMI/FCMOV
inline_ float FCMin3(float a, float b, float c)
{
float Res;
_asm fld [a]
_asm fld [b]
_asm fld [c]
FCOMI_ST1
FCMOVNB_ST1
FCOMI_ST2
FCMOVNB_ST2
_asm fstp [Res]
_asm fcompp
return Res;
}
inline_ int ConvertToSortable(float f)
{
int& Fi = (int&)f;
int Fmask = (Fi>>31);
Fi ^= Fmask;
Fmask &= ~(1<<31);
Fi -= Fmask;
return Fi;
}
enum FPUMode
{
FPU_FLOOR = 0,
FPU_CEIL = 1,
FPU_BEST = 2,
FPU_FORCE_DWORD = 0x7fffffff
};
FUNCTION ICECORE_API FPUMode GetFPUMode();
FUNCTION ICECORE_API void SaveFPU();
FUNCTION ICECORE_API void RestoreFPU();
FUNCTION ICECORE_API void SetFPUFloorMode();
FUNCTION ICECORE_API void SetFPUCeilMode();
FUNCTION ICECORE_API void SetFPUBestMode();
FUNCTION ICECORE_API void SetFPUPrecision24();
FUNCTION ICECORE_API void SetFPUPrecision53();
FUNCTION ICECORE_API void SetFPUPrecision64();
FUNCTION ICECORE_API void SetFPURoundingChop();
FUNCTION ICECORE_API void SetFPURoundingUp();
FUNCTION ICECORE_API void SetFPURoundingDown();
FUNCTION ICECORE_API void SetFPURoundingNear();
FUNCTION ICECORE_API int intChop(const float& f);
FUNCTION ICECORE_API int intFloor(const float& f);
FUNCTION ICECORE_API int intCeil(const float& f);
#endif // __ICEFPU_H__

View File

@@ -1,121 +1,121 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains all memory macros.
* \file IceMemoryMacros.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEMEMORYMACROS_H__
#define __ICEMEMORYMACROS_H__
#undef ZeroMemory
#undef CopyMemory
#undef MoveMemory
#undef FillMemory
//! Clears a buffer.
//! \param addr [in] buffer address
//! \param size [in] buffer length
//! \see FillMemory
//! \see StoreDwords
//! \see CopyMemory
//! \see MoveMemory
inline_ void ZeroMemory(void* addr, udword size) { memset(addr, 0, size); }
//! Fills a buffer with a given byte.
//! \param addr [in] buffer address
//! \param size [in] buffer length
//! \param val [in] the byte value
//! \see StoreDwords
//! \see ZeroMemory
//! \see CopyMemory
//! \see MoveMemory
inline_ void FillMemory(void* dest, udword size, ubyte val) { memset(dest, val, size); }
//! Fills a buffer with a given dword.
//! \param addr [in] buffer address
//! \param nb [in] number of dwords to write
//! \param value [in] the dword value
//! \see FillMemory
//! \see ZeroMemory
//! \see CopyMemory
//! \see MoveMemory
//! \warning writes nb*4 bytes !
inline_ void StoreDwords(udword* dest, udword nb, udword value)
{
// The asm code below **SHOULD** be equivalent to one of those C versions
// or the other if your compiled is good: (checked on VC++ 6.0)
//
// 1) while(nb--) *dest++ = value;
//
// 2) for(udword i=0;i<nb;i++) dest[i] = value;
//
_asm push eax
_asm push ecx
_asm push edi
_asm mov edi, dest
_asm mov ecx, nb
_asm mov eax, value
_asm rep stosd
_asm pop edi
_asm pop ecx
_asm pop eax
}
//! Copies a buffer.
//! \param addr [in] destination buffer address
//! \param addr [in] source buffer address
//! \param size [in] buffer length
//! \see ZeroMemory
//! \see FillMemory
//! \see StoreDwords
//! \see MoveMemory
inline_ void CopyMemory(void* dest, const void* src, udword size) { memcpy(dest, src, size); }
//! Moves a buffer.
//! \param addr [in] destination buffer address
//! \param addr [in] source buffer address
//! \param size [in] buffer length
//! \see ZeroMemory
//! \see FillMemory
//! \see StoreDwords
//! \see CopyMemory
inline_ void MoveMemory(void* dest, const void* src, udword size) { memmove(dest, src, size); }
#define SIZEOFOBJECT sizeof(*this) //!< Gives the size of current object. Avoid some mistakes (e.g. "sizeof(this)").
//#define CLEAROBJECT { memset(this, 0, SIZEOFOBJECT); } //!< Clears current object. Laziness is my business. HANDLE WITH CARE.
#define DELETESINGLE(x) if (x) { delete x; x = null; } //!< Deletes an instance of a class.
#define DELETEARRAY(x) if (x) { delete []x; x = null; } //!< Deletes an array.
#define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = null; } //!< Safe D3D-style release
#define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } //!< Safe ICE-style release
#ifdef __ICEERROR_H__
#define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY); //!< Standard alloc checking. HANDLE WITH CARE.
#else
#define CHECKALLOC(x) if(!x) return false;
#endif
//! Standard allocation cycle
#define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr);
#endif // __ICEMEMORYMACROS_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains all memory macros.
* \file IceMemoryMacros.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEMEMORYMACROS_H__
#define __ICEMEMORYMACROS_H__
#undef ZeroMemory
#undef CopyMemory
#undef MoveMemory
#undef FillMemory
//! Clears a buffer.
//! \param addr [in] buffer address
//! \param size [in] buffer length
//! \see FillMemory
//! \see StoreDwords
//! \see CopyMemory
//! \see MoveMemory
inline_ void ZeroMemory(void* addr, udword size) { memset(addr, 0, size); }
//! Fills a buffer with a given byte.
//! \param addr [in] buffer address
//! \param size [in] buffer length
//! \param val [in] the byte value
//! \see StoreDwords
//! \see ZeroMemory
//! \see CopyMemory
//! \see MoveMemory
inline_ void FillMemory(void* dest, udword size, ubyte val) { memset(dest, val, size); }
//! Fills a buffer with a given dword.
//! \param addr [in] buffer address
//! \param nb [in] number of dwords to write
//! \param value [in] the dword value
//! \see FillMemory
//! \see ZeroMemory
//! \see CopyMemory
//! \see MoveMemory
//! \warning writes nb*4 bytes !
inline_ void StoreDwords(udword* dest, udword nb, udword value)
{
// The asm code below **SHOULD** be equivalent to one of those C versions
// or the other if your compiled is good: (checked on VC++ 6.0)
//
// 1) while(nb--) *dest++ = value;
//
// 2) for(udword i=0;i<nb;i++) dest[i] = value;
//
_asm push eax
_asm push ecx
_asm push edi
_asm mov edi, dest
_asm mov ecx, nb
_asm mov eax, value
_asm rep stosd
_asm pop edi
_asm pop ecx
_asm pop eax
}
//! Copies a buffer.
//! \param addr [in] destination buffer address
//! \param addr [in] source buffer address
//! \param size [in] buffer length
//! \see ZeroMemory
//! \see FillMemory
//! \see StoreDwords
//! \see MoveMemory
inline_ void CopyMemory(void* dest, const void* src, udword size) { memcpy(dest, src, size); }
//! Moves a buffer.
//! \param addr [in] destination buffer address
//! \param addr [in] source buffer address
//! \param size [in] buffer length
//! \see ZeroMemory
//! \see FillMemory
//! \see StoreDwords
//! \see CopyMemory
inline_ void MoveMemory(void* dest, const void* src, udword size) { memmove(dest, src, size); }
#define SIZEOFOBJECT sizeof(*this) //!< Gives the size of current object. Avoid some mistakes (e.g. "sizeof(this)").
//#define CLEAROBJECT { memset(this, 0, SIZEOFOBJECT); } //!< Clears current object. Laziness is my business. HANDLE WITH CARE.
#define DELETESINGLE(x) if (x) { delete x; x = null; } //!< Deletes an instance of a class.
#define DELETEARRAY(x) if (x) { delete []x; x = null; } //!< Deletes an array.
#define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = null; } //!< Safe D3D-style release
#define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } //!< Safe ICE-style release
#ifdef __ICEERROR_H__
#define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY); //!< Standard alloc checking. HANDLE WITH CARE.
#else
#define CHECKALLOC(x) if(!x) return false;
#endif
//! Standard allocation cycle
#define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr);
#endif // __ICEMEMORYMACROS_H__

View File

@@ -1,144 +1,144 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains preprocessor stuff. This should be the first included header.
* \file IcePreprocessor.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEPREPROCESSOR_H__
#define __ICEPREPROCESSOR_H__
// Check platform
#if defined( _WIN32 ) || defined( WIN32 )
#pragma message("Compiling on Windows...")
#define PLATFORM_WINDOWS
#else
#pragma message("Compiling on unknown platform...")
#endif
// Check compiler
#if defined(_MSC_VER)
#pragma message("Compiling with VC++...")
#define COMPILER_VISUAL_CPP
#else
#pragma message("Compiling with unknown compiler...")
#endif
// Check compiler options. If this file is included in user-apps, this
// shouldn't be needed, so that they can use what they like best.
#ifndef ICE_DONT_CHECK_COMPILER_OPTIONS
#ifdef COMPILER_VISUAL_CPP
#if defined(_CHAR_UNSIGNED)
#endif
#if defined(_CPPRTTI)
#error Please disable RTTI...
#endif
#if defined(_CPPUNWIND)
#error Please disable exceptions...
#endif
#if defined(_MT)
// Multithreading
#endif
#endif
#endif
// Check debug mode
#ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it.
#ifndef _DEBUG
#define _DEBUG
#endif
#endif
#ifdef _DEBUG
// Here you may define items for debug builds
#endif
#ifndef THIS_FILE
#define THIS_FILE __FILE__
#endif
#ifndef ICE_NO_DLL
#ifdef ICECORE_EXPORTS
#define ICECORE_API __declspec(dllexport)
#else
#define ICECORE_API __declspec(dllimport)
#endif
#else
#define ICECORE_API
#endif
// Don't override new/delete
// #define DEFAULT_NEWDELETE
#define DONT_TRACK_MEMORY_LEAKS
#define FUNCTION extern "C"
// Cosmetic stuff [mainly useful with multiple inheritance]
#define override(base_class) virtual
// Our own inline keyword, so that:
// - we can switch to __forceinline to check it's really better or not
// - we can remove __forceinline if the compiler doesn't support it
// #define inline_ __forceinline
// #define inline_ inline
// Contributed by Bruce Mitchener
#if defined(COMPILER_VISUAL_CPP)
#define inline_ __forceinline
// #define inline_ inline
#elif defined(__GNUC__) && __GNUC__ < 3
#define inline_ inline
#elif defined(__GNUC__)
#define inline_ inline __attribute__ ((always_inline))
#else
#define inline_ inline
#endif
// Down the hatch
#pragma inline_depth( 255 )
#ifdef COMPILER_VISUAL_CPP
#pragma intrinsic(memcmp)
#pragma intrinsic(memcpy)
#pragma intrinsic(memset)
#pragma intrinsic(strcat)
#pragma intrinsic(strcmp)
#pragma intrinsic(strcpy)
#pragma intrinsic(strlen)
#pragma intrinsic(abs)
#pragma intrinsic(labs)
#endif
// ANSI compliance
#ifdef _DEBUG
// Remove painful warning in debug
inline_ bool __False__(){ return false; }
#define for if(__False__()){} else for
#else
#define for if(0){} else for
#endif
#endif // __ICEPREPROCESSOR_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains preprocessor stuff. This should be the first included header.
* \file IcePreprocessor.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEPREPROCESSOR_H__
#define __ICEPREPROCESSOR_H__
// Check platform
#if defined( _WIN32 ) || defined( WIN32 )
#pragma message("Compiling on Windows...")
#define PLATFORM_WINDOWS
#else
#pragma message("Compiling on unknown platform...")
#endif
// Check compiler
#if defined(_MSC_VER)
#pragma message("Compiling with VC++...")
#define COMPILER_VISUAL_CPP
#else
#pragma message("Compiling with unknown compiler...")
#endif
// Check compiler options. If this file is included in user-apps, this
// shouldn't be needed, so that they can use what they like best.
#ifndef ICE_DONT_CHECK_COMPILER_OPTIONS
#ifdef COMPILER_VISUAL_CPP
#if defined(_CHAR_UNSIGNED)
#endif
#if defined(_CPPRTTI)
#error Please disable RTTI...
#endif
#if defined(_CPPUNWIND)
#error Please disable exceptions...
#endif
#if defined(_MT)
// Multithreading
#endif
#endif
#endif
// Check debug mode
#ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it.
#ifndef _DEBUG
#define _DEBUG
#endif
#endif
#ifdef _DEBUG
// Here you may define items for debug builds
#endif
#ifndef THIS_FILE
#define THIS_FILE __FILE__
#endif
#ifndef ICE_NO_DLL
#ifdef ICECORE_EXPORTS
#define ICECORE_API __declspec(dllexport)
#else
#define ICECORE_API __declspec(dllimport)
#endif
#else
#define ICECORE_API
#endif
// Don't override new/delete
// #define DEFAULT_NEWDELETE
#define DONT_TRACK_MEMORY_LEAKS
#define FUNCTION extern "C"
// Cosmetic stuff [mainly useful with multiple inheritance]
#define override(base_class) virtual
// Our own inline keyword, so that:
// - we can switch to __forceinline to check it's really better or not
// - we can remove __forceinline if the compiler doesn't support it
// #define inline_ __forceinline
// #define inline_ inline
// Contributed by Bruce Mitchener
#if defined(COMPILER_VISUAL_CPP)
#define inline_ __forceinline
// #define inline_ inline
#elif defined(__GNUC__) && __GNUC__ < 3
#define inline_ inline
#elif defined(__GNUC__)
#define inline_ inline __attribute__ ((always_inline))
#else
#define inline_ inline
#endif
// Down the hatch
#pragma inline_depth( 255 )
#ifdef COMPILER_VISUAL_CPP
#pragma intrinsic(memcmp)
#pragma intrinsic(memcpy)
#pragma intrinsic(memset)
#pragma intrinsic(strcat)
#pragma intrinsic(strcmp)
#pragma intrinsic(strcpy)
#pragma intrinsic(strlen)
#pragma intrinsic(abs)
#pragma intrinsic(labs)
#endif
// ANSI compliance
#ifdef _DEBUG
// Remove painful warning in debug
inline_ bool __False__(){ return false; }
#define for if(__False__()){} else for
#else
#define for if(0){} else for
#endif
#endif // __ICEPREPROCESSOR_H__

File diff suppressed because it is too large Load Diff

View File

@@ -1,81 +1,81 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains source code from the article "Radix Sort Revisited".
* \file IceRevisitedRadix.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICERADIXSORT_H__
#define __ICERADIXSORT_H__
//! Allocate histograms & offsets locally
#define RADIX_LOCAL_RAM
enum RadixHint
{
RADIX_SIGNED, //!< Input values are signed
RADIX_UNSIGNED, //!< Input values are unsigned
RADIX_FORCE_DWORD = 0x7fffffff
};
class ICECORE_API RadixSort
{
public:
// Constructor/Destructor
RadixSort();
~RadixSort();
// Sorting methods
RadixSort& Sort(const udword* input, udword nb, RadixHint hint=RADIX_SIGNED);
RadixSort& Sort(const float* input, udword nb);
//! Access to results. mRanks is a list of indices in sorted order, i.e. in the order you may further process your data
inline_ const udword* GetRanks() const { return mRanks; }
//! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want.
inline_ udword* GetRecyclable() const { return mRanks2; }
// Stats
udword GetUsedRam() const;
//! Returns the total number of calls to the radix sorter.
inline_ udword GetNbTotalCalls() const { return mTotalCalls; }
//! Returns the number of eraly exits due to temporal coherence.
inline_ udword GetNbHits() const { return mNbHits; }
private:
#ifndef RADIX_LOCAL_RAM
udword* mHistogram; //!< Counters for each byte
udword* mOffset; //!< Offsets (nearly a cumulative distribution function)
#endif
udword mCurrentSize; //!< Current size of the indices list
udword* mRanks; //!< Two lists, swapped each pass
udword* mRanks2;
// Stats
udword mTotalCalls; //!< Total number of calls to the sort routine
udword mNbHits; //!< Number of early exits due to coherence
// Internal methods
void CheckResize(udword nb);
bool Resize(udword nb);
};
#endif // __ICERADIXSORT_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains source code from the article "Radix Sort Revisited".
* \file IceRevisitedRadix.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICERADIXSORT_H__
#define __ICERADIXSORT_H__
//! Allocate histograms & offsets locally
#define RADIX_LOCAL_RAM
enum RadixHint
{
RADIX_SIGNED, //!< Input values are signed
RADIX_UNSIGNED, //!< Input values are unsigned
RADIX_FORCE_DWORD = 0x7fffffff
};
class ICECORE_API RadixSort
{
public:
// Constructor/Destructor
RadixSort();
~RadixSort();
// Sorting methods
RadixSort& Sort(const udword* input, udword nb, RadixHint hint=RADIX_SIGNED);
RadixSort& Sort(const float* input, udword nb);
//! Access to results. mRanks is a list of indices in sorted order, i.e. in the order you may further process your data
inline_ const udword* GetRanks() const { return mRanks; }
//! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want.
inline_ udword* GetRecyclable() const { return mRanks2; }
// Stats
udword GetUsedRam() const;
//! Returns the total number of calls to the radix sorter.
inline_ udword GetNbTotalCalls() const { return mTotalCalls; }
//! Returns the number of eraly exits due to temporal coherence.
inline_ udword GetNbHits() const { return mNbHits; }
private:
#ifndef RADIX_LOCAL_RAM
udword* mHistogram; //!< Counters for each byte
udword* mOffset; //!< Offsets (nearly a cumulative distribution function)
#endif
udword mCurrentSize; //!< Current size of the indices list
udword* mRanks; //!< Two lists, swapped each pass
udword* mRanks2;
// Stats
udword mTotalCalls; //!< Total number of calls to the sort routine
udword mNbHits; //!< Number of early exits due to coherence
// Internal methods
void CheckResize(udword nb);
bool Resize(udword nb);
};
#endif // __ICERADIXSORT_H__

View File

@@ -1,173 +1,173 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains custom types.
* \file IceTypes.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICETYPES_H__
#define __ICETYPES_H__
#define USE_HANDLE_MANAGER
// Constants
#define PI 3.1415926535897932384626433832795028841971693993751f //!< PI
#define HALFPI 1.57079632679489661923f //!< 0.5 * PI
#define TWOPI 6.28318530717958647692f //!< 2.0 * PI
#define INVPI 0.31830988618379067154f //!< 1.0 / PI
#define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees
#define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians
#define EXP 2.71828182845904523536f //!< e
#define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2)
#define LN2 0.693147180559945f //!< ln(2)
#define INVLN2 1.44269504089f //!< 1.0f / ln(2)
#define INV3 0.33333333333333333333f //!< 1/3
#define INV6 0.16666666666666666666f //!< 1/6
#define INV7 0.14285714285714285714f //!< 1/7
#define INV9 0.11111111111111111111f //!< 1/9
#define INV255 0.00392156862745098039f //!< 1/255
#define SQRT2 1.41421356237f //!< sqrt(2)
#define INVSQRT2 0.707106781188f //!< 1 / sqrt(2)
#define SQRT3 1.73205080757f //!< sqrt(3)
#define INVSQRT3 0.577350269189f //!< 1 / sqrt(3)
#define null 0 //!< our own NULL pointer
// Custom types used in ICE
typedef signed char sbyte; //!< sizeof(sbyte) must be 1
typedef unsigned char ubyte; //!< sizeof(ubyte) must be 1
typedef signed short sword; //!< sizeof(sword) must be 2
typedef unsigned short uword; //!< sizeof(uword) must be 2
typedef signed int sdword; //!< sizeof(sdword) must be 4
typedef unsigned int udword; //!< sizeof(udword) must be 4
typedef signed __int64 sqword; //!< sizeof(sqword) must be 8
typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8
typedef float float32; //!< sizeof(float32) must be 4
typedef double float64; //!< sizeof(float64) must be 4
ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1); // ...otherwise things might fail with VC++ 4.2 !
ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1);
ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1);
ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2);
ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2);
ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8);
ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8);
//! TO BE DOCUMENTED
#define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
typedef udword DynID; //!< Dynamic identifier
#ifdef USE_HANDLE_MANAGER
typedef udword KID; //!< Kernel ID
// DECLARE_ICE_HANDLE(KID);
#else
typedef uword KID; //!< Kernel ID
#endif
typedef udword RTYPE; //!< Relationship-type (!) between owners and references
#define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers)
#ifdef USE_HANDLE_MANAGER
#define INVALID_KID 0xffffffff //!< Invalid Kernel ID
#else
#define INVALID_KID 0xffff //!< Invalid Kernel ID
#endif
#define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value
// Define BOOL if needed
#ifndef BOOL
typedef int BOOL; //!< Another boolean type.
#endif
//! Union of a float and a sdword
typedef union {
float f; //!< The float
sdword d; //!< The integer
}scell;
//! Union of a float and a udword
typedef union {
float f; //!< The float
udword d; //!< The integer
}ucell;
// Type ranges
#define MAX_SBYTE 0x7f //!< max possible sbyte value
#define MIN_SBYTE 0x80 //!< min possible sbyte value
#define MAX_UBYTE 0xff //!< max possible ubyte value
#define MIN_UBYTE 0x00 //!< min possible ubyte value
#define MAX_SWORD 0x7fff //!< max possible sword value
#define MIN_SWORD 0x8000 //!< min possible sword value
#define MAX_UWORD 0xffff //!< max possible uword value
#define MIN_UWORD 0x0000 //!< min possible uword value
#define MAX_SDWORD 0x7fffffff //!< max possible sdword value
#define MIN_SDWORD 0x80000000 //!< min possible sdword value
#define MAX_UDWORD 0xffffffff //!< max possible udword value
#define MIN_UDWORD 0x00000000 //!< min possible udword value
#define MAX_FLOAT FLT_MAX //!< max possible float value
#define MIN_FLOAT (-FLT_MAX) //!< min possible loat value
#define IEEE_1_0 0x3f800000 //!< integer representation of 1.0
#define IEEE_255_0 0x437f0000 //!< integer representation of 255.0
#define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT
#define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT
#define IEEE_UNDERFLOW_LIMIT 0x1a000000
#define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand()
typedef int (__stdcall* PROC)(); //!< A standard procedure call.
typedef bool (*ENUMERATION)(udword value, udword param, udword context); //!< ICE standard enumeration call
typedef void** VTABLE; //!< A V-Table.
#undef MIN
#undef MAX
#define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b
#define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b
#define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c
template<class T> inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; }
template<class T> inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; }
template<class T> inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; }
template<class T> inline_ void TSetMax (T& a, const T& b) { if(a<b) a = b; }
#define SQR(x) ((x)*(x)) //!< Returns x square
#define CUBE(x) ((x)*(x)*(x)) //!< Returns x cube
#define AND & //!< ...
#define OR | //!< ...
#define XOR ^ //!< ...
#define QUADRAT(x) ((x)*(x)) //!< Returns x square
#ifdef _WIN32
# define srand48(x) srand((unsigned int) (x))
# define srandom(x) srand((unsigned int) (x))
# define random() ((double) rand())
# define drand48() ((double) (((double) rand()) / ((double) RAND_MAX)))
#endif
#endif // __ICETYPES_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains custom types.
* \file IceTypes.h
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICETYPES_H__
#define __ICETYPES_H__
#define USE_HANDLE_MANAGER
// Constants
#define PI 3.1415926535897932384626433832795028841971693993751f //!< PI
#define HALFPI 1.57079632679489661923f //!< 0.5 * PI
#define TWOPI 6.28318530717958647692f //!< 2.0 * PI
#define INVPI 0.31830988618379067154f //!< 1.0 / PI
#define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees
#define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians
#define EXP 2.71828182845904523536f //!< e
#define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2)
#define LN2 0.693147180559945f //!< ln(2)
#define INVLN2 1.44269504089f //!< 1.0f / ln(2)
#define INV3 0.33333333333333333333f //!< 1/3
#define INV6 0.16666666666666666666f //!< 1/6
#define INV7 0.14285714285714285714f //!< 1/7
#define INV9 0.11111111111111111111f //!< 1/9
#define INV255 0.00392156862745098039f //!< 1/255
#define SQRT2 1.41421356237f //!< sqrt(2)
#define INVSQRT2 0.707106781188f //!< 1 / sqrt(2)
#define SQRT3 1.73205080757f //!< sqrt(3)
#define INVSQRT3 0.577350269189f //!< 1 / sqrt(3)
#define null 0 //!< our own NULL pointer
// Custom types used in ICE
typedef signed char sbyte; //!< sizeof(sbyte) must be 1
typedef unsigned char ubyte; //!< sizeof(ubyte) must be 1
typedef signed short sword; //!< sizeof(sword) must be 2
typedef unsigned short uword; //!< sizeof(uword) must be 2
typedef signed int sdword; //!< sizeof(sdword) must be 4
typedef unsigned int udword; //!< sizeof(udword) must be 4
typedef signed __int64 sqword; //!< sizeof(sqword) must be 8
typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8
typedef float float32; //!< sizeof(float32) must be 4
typedef double float64; //!< sizeof(float64) must be 4
ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1); // ...otherwise things might fail with VC++ 4.2 !
ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1);
ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1);
ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2);
ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2);
ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4);
ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8);
ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8);
//! TO BE DOCUMENTED
#define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
typedef udword DynID; //!< Dynamic identifier
#ifdef USE_HANDLE_MANAGER
typedef udword KID; //!< Kernel ID
// DECLARE_ICE_HANDLE(KID);
#else
typedef uword KID; //!< Kernel ID
#endif
typedef udword RTYPE; //!< Relationship-type (!) between owners and references
#define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers)
#ifdef USE_HANDLE_MANAGER
#define INVALID_KID 0xffffffff //!< Invalid Kernel ID
#else
#define INVALID_KID 0xffff //!< Invalid Kernel ID
#endif
#define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value
// Define BOOL if needed
#ifndef BOOL
typedef int BOOL; //!< Another boolean type.
#endif
//! Union of a float and a sdword
typedef union {
float f; //!< The float
sdword d; //!< The integer
}scell;
//! Union of a float and a udword
typedef union {
float f; //!< The float
udword d; //!< The integer
}ucell;
// Type ranges
#define MAX_SBYTE 0x7f //!< max possible sbyte value
#define MIN_SBYTE 0x80 //!< min possible sbyte value
#define MAX_UBYTE 0xff //!< max possible ubyte value
#define MIN_UBYTE 0x00 //!< min possible ubyte value
#define MAX_SWORD 0x7fff //!< max possible sword value
#define MIN_SWORD 0x8000 //!< min possible sword value
#define MAX_UWORD 0xffff //!< max possible uword value
#define MIN_UWORD 0x0000 //!< min possible uword value
#define MAX_SDWORD 0x7fffffff //!< max possible sdword value
#define MIN_SDWORD 0x80000000 //!< min possible sdword value
#define MAX_UDWORD 0xffffffff //!< max possible udword value
#define MIN_UDWORD 0x00000000 //!< min possible udword value
#define MAX_FLOAT FLT_MAX //!< max possible float value
#define MIN_FLOAT (-FLT_MAX) //!< min possible loat value
#define IEEE_1_0 0x3f800000 //!< integer representation of 1.0
#define IEEE_255_0 0x437f0000 //!< integer representation of 255.0
#define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT
#define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT
#define IEEE_UNDERFLOW_LIMIT 0x1a000000
#define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand()
typedef int (__stdcall* PROC)(); //!< A standard procedure call.
typedef bool (*ENUMERATION)(udword value, udword param, udword context); //!< ICE standard enumeration call
typedef void** VTABLE; //!< A V-Table.
#undef MIN
#undef MAX
#define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b
#define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b
#define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c
template<class T> inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; }
template<class T> inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; }
template<class T> inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; }
template<class T> inline_ void TSetMax (T& a, const T& b) { if(a<b) a = b; }
#define SQR(x) ((x)*(x)) //!< Returns x square
#define CUBE(x) ((x)*(x)*(x)) //!< Returns x cube
#define AND & //!< ...
#define OR | //!< ...
#define XOR ^ //!< ...
#define QUADRAT(x) ((x)*(x)) //!< Returns x square
#ifdef _WIN32
# define srand48(x) srand((unsigned int) (x))
# define srandom(x) srand((unsigned int) (x))
# define random() ((double) rand())
# define drand48() ((double) (((double) rand()) / ((double) RAND_MAX)))
#endif
#endif // __ICETYPES_H__

View File

@@ -1,272 +1,272 @@
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains misc. useful macros & defines.
* \file IceUtils.h
* \author Pierre Terdiman (collected from various sources)
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEUTILS_H__
#define __ICEUTILS_H__
#define START_RUNONCE { static bool __RunOnce__ = false; if(!__RunOnce__){
#define END_RUNONCE __RunOnce__ = true;}}
//! Reverse all the bits in a 32 bit word (from Steve Baker's Cute Code Collection)
//! (each line can be done in any order.
inline_ void ReverseBits(udword& n)
{
n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
// Etc for larger intergers (64 bits in Java)
// NOTE: the >> operation must be unsigned! (>>> in java)
}
//! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection)
inline_ udword CountBits(udword n)
{
// This relies of the fact that the count of n bits can NOT overflow
// an n bit interger. EG: 1 bit count takes a 1 bit interger, 2 bit counts
// 2 bit interger, 3 bit count requires only a 2 bit interger.
// So we add all bit pairs, then each nible, then each byte etc...
n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1);
n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2);
n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4);
n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8);
n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16);
// Etc for larger intergers (64 bits in Java)
// NOTE: the >> operation must be unsigned! (>>> in java)
return n;
}
//! Even faster?
inline_ udword CountBits2(udword bits)
{
bits = bits - ((bits >> 1) & 0x55555555);
bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333);
bits = ((bits >> 4) + bits) & 0x0F0F0F0F;
return (bits * 0x01010101) >> 24;
}
//! Spread out bits. EG 00001111 -> 0101010101
//! 00001010 -> 0100010000
//! This is used to interleve to intergers to produce a `Morten Key'
//! used in Space Filling Curves (See DrDobbs Journal, July 1999)
//! Order is important.
inline_ void SpreadBits(udword& n)
{
n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16);
n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8);
n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4);
n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2);
n = ( n & 0x11111111) | (( n & 0x22222222) << 1);
}
// Next Largest Power of 2
// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
// largest power of 2. For a 32-bit value:
inline_ udword nlpo2(udword x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x+1;
}
//! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection)
inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); }
//! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection)
inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); }
//! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection)
inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<<n); }
//! Classic XOR swap (from Steve Baker's Cute Code Collection)
//! x ^= y; /* x' = (x^y) */
//! y ^= x; /* y' = (y^(x^y)) = x */
//! x ^= y; /* x' = (x^y)^x = y */
inline_ void Swap(udword& x, udword& y) { x ^= y; y ^= x; x ^= y; }
//! Little/Big endian (from Steve Baker's Cute Code Collection)
//!
//! Extra comments by Kenny Hoff:
//! Determines the byte-ordering of the current machine (little or big endian)
//! by setting an integer value to 1 (so least significant bit is now 1); take
//! the address of the int and cast to a byte pointer (treat integer as an
//! array of four bytes); check the value of the first byte (must be 0 or 1).
//! If the value is 1, then the first byte least significant byte and this
//! implies LITTLE endian. If the value is 0, the first byte is the most
//! significant byte, BIG endian. Examples:
//! integer 1 on BIG endian: 00000000 00000000 00000000 00000001
//! integer 1 on LITTLE endian: 00000001 00000000 00000000 00000000
//!---------------------------------------------------------------------------
//! int IsLittleEndian() { int x=1; return ( ((char*)(&x))[0] ); }
inline_ char LittleEndian() { int i = 1; return *((char*)&i); }
//!< Alternative abs function
inline_ udword abs_(sdword x) { sdword y= x >> 31; return (x^y)-y; }
//!< Alternative min function
inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); }
// Determine if one of the bytes in a 4 byte word is zero
inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); }
// To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0
inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); }
// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); }
// Most Significant 1 Bit
// Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set)
// can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits.
// This process yields a bit vector with the same most significant 1 as x, but all 1's below it.
// Bitwise AND of the original value with the complement of the "folded" value shifted down by one
// yields the most significant bit. For a 32-bit value:
inline_ udword msb32(udword x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return (x & ~(x >> 1));
}
/*
"Just call it repeatedly with various input values and always with the same variable as "memory".
The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1
does no filtering at all.
I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed
to the more typical FIR (Finite Impulse Response).
Also, I'd say that you can make more intelligent and interesting filters than this, for example filters
that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter
to be applied before this one, of course."
(JCAB on Flipcode)
*/
inline_ float FeedbackFilter(float val, float& memory, float sharpness)
{
ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter");
if(sharpness<0.0f) sharpness = 0.0f;
else if(sharpness>1.0f) sharpness = 1.0f;
return memory = val * sharpness + memory * (1.0f - sharpness);
}
//! If you can guarantee that your input domain (i.e. value of x) is slightly
//! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the
//! following code to clamp the resulting value into [-32768,+32767] range:
inline_ int ClampToInt16(int x)
{
// ASSERT(abs(x) < (int)((1<<31u)-32767));
int delta = 32767 - x;
x += (delta>>31) & delta;
delta = x + 32768;
x -= (delta>>31) & delta;
return x;
}
// Generic functions
template<class Type> inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; }
template<class Type> inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((x<lo) ? lo : (x>hi) ? hi : x); }
template<class Type> inline_ void TSort(Type& a, Type& b)
{
if(a>b) TSwap(a, b);
}
template<class Type> inline_ void TSort(Type& a, Type& b, Type& c)
{
if(a>b) TSwap(a, b);
if(b>c) TSwap(b, c);
if(a>b) TSwap(a, b);
if(b>c) TSwap(b, c);
}
// Prevent nasty user-manipulations (strategy borrowed from Charles Bloom)
// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); }
// ... actually this is better !
#define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object);
//! TO BE DOCUMENTED
#define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member)
//! TO BE DOCUMENTED
#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns the alignment of the input address.
* \fn Alignment()
* \param address [in] address to check
* \return the best alignment (e.g. 1 for odd addresses, etc)
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FUNCTION ICECORE_API udword Alignment(udword address);
#define IS_ALIGNED_2(x) ((x&1)==0)
#define IS_ALIGNED_4(x) ((x&3)==0)
#define IS_ALIGNED_8(x) ((x&7)==0)
inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; }
// Compute implicit coords from an index:
// The idea is to get back 2D coords from a 1D index.
// For example:
//
// 0 1 2 ... nbu-1
// nbu nbu+1 i ...
//
// We have i, we're looking for the equivalent (u=2, v=1) location.
// i = u + v*nbu
// <=> i/nbu = u/nbu + v
// Since 0 <= u < nbu, u/nbu = 0 (integer)
// Hence: v = i/nbu
// Then we simply put it back in the original equation to compute u = i - v*nbu
inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu)
{
v = i / nbu;
u = i - (v * nbu);
}
// In 3D: i = u + v*nbu + w*nbu*nbv
// <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w
// u/(nbu*nbv) is null since u/nbu was null already.
// v/nbv is null as well for the same reason.
// Hence w = i/(nbu*nbv)
// Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu
inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv)
{
w = i / (nbu_nbv);
Compute2DCoords(u, v, i - (w * nbu_nbv), nbu);
}
#endif // __ICEUTILS_H__
/*
* ICE / OPCODE - Optimized Collision Detection
* http://www.codercorner.com/Opcode.htm
*
* Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains misc. useful macros & defines.
* \file IceUtils.h
* \author Pierre Terdiman (collected from various sources)
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEUTILS_H__
#define __ICEUTILS_H__
#define START_RUNONCE { static bool __RunOnce__ = false; if(!__RunOnce__){
#define END_RUNONCE __RunOnce__ = true;}}
//! Reverse all the bits in a 32 bit word (from Steve Baker's Cute Code Collection)
//! (each line can be done in any order.
inline_ void ReverseBits(udword& n)
{
n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
// Etc for larger intergers (64 bits in Java)
// NOTE: the >> operation must be unsigned! (>>> in java)
}
//! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection)
inline_ udword CountBits(udword n)
{
// This relies of the fact that the count of n bits can NOT overflow
// an n bit interger. EG: 1 bit count takes a 1 bit interger, 2 bit counts
// 2 bit interger, 3 bit count requires only a 2 bit interger.
// So we add all bit pairs, then each nible, then each byte etc...
n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1);
n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2);
n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4);
n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8);
n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16);
// Etc for larger intergers (64 bits in Java)
// NOTE: the >> operation must be unsigned! (>>> in java)
return n;
}
//! Even faster?
inline_ udword CountBits2(udword bits)
{
bits = bits - ((bits >> 1) & 0x55555555);
bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333);
bits = ((bits >> 4) + bits) & 0x0F0F0F0F;
return (bits * 0x01010101) >> 24;
}
//! Spread out bits. EG 00001111 -> 0101010101
//! 00001010 -> 0100010000
//! This is used to interleve to intergers to produce a `Morten Key'
//! used in Space Filling Curves (See DrDobbs Journal, July 1999)
//! Order is important.
inline_ void SpreadBits(udword& n)
{
n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16);
n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8);
n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4);
n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2);
n = ( n & 0x11111111) | (( n & 0x22222222) << 1);
}
// Next Largest Power of 2
// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
// largest power of 2. For a 32-bit value:
inline_ udword nlpo2(udword x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x+1;
}
//! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection)
inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); }
//! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection)
inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); }
//! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection)
inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<<n); }
//! Classic XOR swap (from Steve Baker's Cute Code Collection)
//! x ^= y; /* x' = (x^y) */
//! y ^= x; /* y' = (y^(x^y)) = x */
//! x ^= y; /* x' = (x^y)^x = y */
inline_ void Swap(udword& x, udword& y) { x ^= y; y ^= x; x ^= y; }
//! Little/Big endian (from Steve Baker's Cute Code Collection)
//!
//! Extra comments by Kenny Hoff:
//! Determines the byte-ordering of the current machine (little or big endian)
//! by setting an integer value to 1 (so least significant bit is now 1); take
//! the address of the int and cast to a byte pointer (treat integer as an
//! array of four bytes); check the value of the first byte (must be 0 or 1).
//! If the value is 1, then the first byte least significant byte and this
//! implies LITTLE endian. If the value is 0, the first byte is the most
//! significant byte, BIG endian. Examples:
//! integer 1 on BIG endian: 00000000 00000000 00000000 00000001
//! integer 1 on LITTLE endian: 00000001 00000000 00000000 00000000
//!---------------------------------------------------------------------------
//! int IsLittleEndian() { int x=1; return ( ((char*)(&x))[0] ); }
inline_ char LittleEndian() { int i = 1; return *((char*)&i); }
//!< Alternative abs function
inline_ udword abs_(sdword x) { sdword y= x >> 31; return (x^y)-y; }
//!< Alternative min function
inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); }
// Determine if one of the bytes in a 4 byte word is zero
inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); }
// To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0
inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); }
// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); }
// Most Significant 1 Bit
// Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set)
// can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits.
// This process yields a bit vector with the same most significant 1 as x, but all 1's below it.
// Bitwise AND of the original value with the complement of the "folded" value shifted down by one
// yields the most significant bit. For a 32-bit value:
inline_ udword msb32(udword x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return (x & ~(x >> 1));
}
/*
"Just call it repeatedly with various input values and always with the same variable as "memory".
The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1
does no filtering at all.
I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed
to the more typical FIR (Finite Impulse Response).
Also, I'd say that you can make more intelligent and interesting filters than this, for example filters
that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter
to be applied before this one, of course."
(JCAB on Flipcode)
*/
inline_ float FeedbackFilter(float val, float& memory, float sharpness)
{
ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter");
if(sharpness<0.0f) sharpness = 0.0f;
else if(sharpness>1.0f) sharpness = 1.0f;
return memory = val * sharpness + memory * (1.0f - sharpness);
}
//! If you can guarantee that your input domain (i.e. value of x) is slightly
//! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the
//! following code to clamp the resulting value into [-32768,+32767] range:
inline_ int ClampToInt16(int x)
{
// ASSERT(abs(x) < (int)((1<<31u)-32767));
int delta = 32767 - x;
x += (delta>>31) & delta;
delta = x + 32768;
x -= (delta>>31) & delta;
return x;
}
// Generic functions
template<class Type> inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; }
template<class Type> inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((x<lo) ? lo : (x>hi) ? hi : x); }
template<class Type> inline_ void TSort(Type& a, Type& b)
{
if(a>b) TSwap(a, b);
}
template<class Type> inline_ void TSort(Type& a, Type& b, Type& c)
{
if(a>b) TSwap(a, b);
if(b>c) TSwap(b, c);
if(a>b) TSwap(a, b);
if(b>c) TSwap(b, c);
}
// Prevent nasty user-manipulations (strategy borrowed from Charles Bloom)
// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); }
// ... actually this is better !
#define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object);
//! TO BE DOCUMENTED
#define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member)
//! TO BE DOCUMENTED
#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns the alignment of the input address.
* \fn Alignment()
* \param address [in] address to check
* \return the best alignment (e.g. 1 for odd addresses, etc)
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FUNCTION ICECORE_API udword Alignment(udword address);
#define IS_ALIGNED_2(x) ((x&1)==0)
#define IS_ALIGNED_4(x) ((x&3)==0)
#define IS_ALIGNED_8(x) ((x&7)==0)
inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; }
// Compute implicit coords from an index:
// The idea is to get back 2D coords from a 1D index.
// For example:
//
// 0 1 2 ... nbu-1
// nbu nbu+1 i ...
//
// We have i, we're looking for the equivalent (u=2, v=1) location.
// i = u + v*nbu
// <=> i/nbu = u/nbu + v
// Since 0 <= u < nbu, u/nbu = 0 (integer)
// Hence: v = i/nbu
// Then we simply put it back in the original equation to compute u = i - v*nbu
inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu)
{
v = i / nbu;
u = i - (v * nbu);
}
// In 3D: i = u + v*nbu + w*nbu*nbv
// <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w
// u/(nbu*nbv) is null since u/nbu was null already.
// v/nbv is null as well for the same reason.
// Hence w = i/(nbu*nbv)
// Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu
inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv)
{
w = i / (nbu_nbv);
Compute2DCoords(u, v, i - (w * nbu_nbv), nbu);
}
#endif // __ICEUTILS_H__