ode-0.16.2/ 0000775 0001752 0001752 00000000000 13710545443 007364 5 0000000 0000000 ode-0.16.2/test-driver 0000755 0001752 0001752 00000011040 13710545412 011470 0000000 0000000 #! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2013-07-13.22; # UTC
# Copyright (C) 2011-2014 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to or send patches to
# .
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
usage_error ()
{
echo "$0: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <$log_file 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
tweaked_estatus=1
else
tweaked_estatus=$estatus
fi
case $tweaked_estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report the test outcome and exit status in the logs, so that one can
# know whether the test passed or failed simply by looking at the '.log'
# file, without the need of also peaking into the corresponding '.trs'
# file (automake bug#11814).
echo "$res $test_name (exit status: $estatus)" >>$log_file
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
# Register the test result, and other relevant metadata.
echo ":test-result: $res" > $trs_file
echo ":global-test-result: $res" >> $trs_file
echo ":recheck: $recheck" >> $trs_file
echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
ode-0.16.2/OPCODE/ 0000775 0001752 0001752 00000000000 13710545442 010334 5 0000000 0000000 ode-0.16.2/OPCODE/OPC_BaseModel.h 0000664 0001752 0001752 00000026014 13710545230 012757 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* OPCODE - Optimized Collision Detection
* Copyright (C) 2001 Pierre Terdiman
* Homepage: http://www.codercorner.com/Opcode.htm
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains base model interface.
* \file OPC_BaseModel.h
* \author Pierre Terdiman
* \date May, 18, 2003
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __OPC_BASEMODEL_H__
#define __OPC_BASEMODEL_H__
//! Model creation structure
struct OPCODE_API OPCODECREATE
{
//! Constructor
inline_ OPCODECREATE():
mIMesh(null),
mSettings(SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER),
mNoLeaf(true),
mQuantized(true),
#ifdef __MESHMERIZER_H__
mCollisionHull(false),
#endif // __MESHMERIZER_H__
mKeepOriginal(false),
mCanRemap(false)
{
}
inline_ OPCODECREATE(MeshInterface *IMesh, const BuildSettings &Settings, bool NoLeaf, bool Quantized):
mIMesh(IMesh),
mSettings(Settings),
mNoLeaf(NoLeaf),
mQuantized(Quantized),
#ifdef __MESHMERIZER_H__
mCollisionHull(false),
#endif // __MESHMERIZER_H__
mKeepOriginal(false),
mCanRemap(false)
{
}
MeshInterface* mIMesh; //!< Mesh interface (access to triangles & vertices) (*)
BuildSettings mSettings; //!< Builder's settings
bool mNoLeaf; //!< true => discard leaf nodes (else use a normal tree)
bool mQuantized; //!< true => quantize the tree (else use a normal tree)
#ifdef __MESHMERIZER_H__
bool mCollisionHull; //!< true => use convex hull + GJK
#endif // __MESHMERIZER_H__
bool mKeepOriginal; //!< true => keep a copy of the original tree (debug purpose)
bool mCanRemap; //!< true => allows OPCODE to reorganize client arrays
// (*) This pointer is saved internally and used by OPCODE until collision structures are released,
// so beware of the object's lifetime.
};
enum ModelFlag
{
OPC_QUANTIZED = (1<<0), //!< Compressed/uncompressed tree
OPC_NO_LEAF = (1<<1), //!< Leaf/NoLeaf tree
OPC_SINGLE_NODE = (1<<2) //!< Special case for 1-node models
};
class OPCODE_API BaseModel
{
public:
// Constructor/Destructor
BaseModel();
virtual ~BaseModel();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Builds a collision model.
* \param create [in] model creation structure
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual bool Build(const OPCODECREATE& create) = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the number of bytes used by the tree.
* \return amount of bytes used
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual udword GetUsedBytes() const = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Refits the collision model. This can be used to handle dynamic meshes. Usage is:
* 1. modify your mesh vertices (keep the topology constant!)
* 2. refit the tree (call this method)
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual bool Refit();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the source tree.
* \return generic tree
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ const AABBTree* GetSourceTree() const { return mSource; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the tree.
* \return the collision tree
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ const AABBOptimizedTree* GetTree() const { return mTree; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the tree.
* \return the collision tree
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ AABBOptimizedTree* GetTree() { return mTree; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the number of nodes in the tree.
* Should be 2*N-1 for normal trees and N-1 for optimized ones.
* \return number of nodes
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ udword GetNbNodes() const { return mTree->GetNbNodes(); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks whether the tree has leaf nodes or not.
* \return true if the tree has leaf nodes (normal tree), else false (optimized tree)
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL HasLeafNodes() const { return !(mModelCode & OPC_NO_LEAF); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks whether the tree is quantized or not.
* \return true if the tree is quantized
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL IsQuantized() const { return mModelCode & OPC_QUANTIZED; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks whether the model has a single node or not. This special case must be handled separately.
* \return true if the model has only 1 node
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL HasSingleNode() const { return mModelCode & OPC_SINGLE_NODE; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the model's code.
* \return model's code
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ udword GetModelCode() const { return mModelCode; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the mesh interface.
* \return mesh interface
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ const MeshInterface* GetMeshInterface() const { return mIMesh; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Sets the mesh interface.
* \param imesh [in] mesh interface
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void SetMeshInterface(const MeshInterface* imesh) { mIMesh = imesh; }
protected:
const MeshInterface* mIMesh; //!< User-defined mesh interface
udword mModelCode; //!< Model code = combination of ModelFlag(s)
AABBTree* mSource; //!< Original source tree
AABBOptimizedTree* mTree; //!< Optimized tree owned by the model
// Internal methods
void ReleaseBase();
bool CreateTree(bool no_leaf, bool quantized);
};
#endif //__OPC_BASEMODEL_H__
ode-0.16.2/OPCODE/OPC_Picking.cpp 0000664 0001752 0001752 00000012310 13710545230 013035 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* OPCODE - Optimized Collision Detection
* Copyright (C) 2001 Pierre Terdiman
* Homepage: http://www.codercorner.com/Opcode.htm
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code to perform "picking".
* \file OPC_Picking.cpp
* \author Pierre Terdiman
* \date March, 20, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace Opcode;
#ifdef OPC_RAYHIT_CALLBACK
/*
Possible RayCollider usages:
- boolean query (shadow feeler)
- closest hit
- all hits
- number of intersection (boolean)
*/
bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts)
{
struct Local
{
static void AllContacts(const CollisionFace& hit, void* user_data)
{
CollisionFaces* CF = (CollisionFaces*)user_data;
CF->AddFace(hit);
}
};
collider.SetFirstContact(false);
collider.SetHitCallback(Local::AllContacts);
collider.SetUserData(&contacts);
return true;
}
bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact)
{
struct Local
{
static void ClosestContact(const CollisionFace& hit, void* user_data)
{
CollisionFace* CF = (CollisionFace*)user_data;
if(hit.mDistancemDistance) *CF = hit;
}
};
collider.SetFirstContact(false);
collider.SetHitCallback(Local::ClosestContact);
collider.SetUserData(&closest_contact);
closest_contact.mDistance = MAX_FLOAT;
return true;
}
bool Opcode::SetupShadowFeeler(RayCollider& collider)
{
collider.SetFirstContact(true);
collider.SetHitCallback(null);
return true;
}
bool Opcode::SetupInOutTest(RayCollider& collider)
{
collider.SetFirstContact(false);
collider.SetHitCallback(null);
// Results with collider.GetNbIntersections()
return true;
}
bool Opcode::Picking(
CollisionFace& picked_face,
const Ray& world_ray, const Model& model, const Matrix4x4* world,
float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data)
{
struct Local
{
struct CullData
{
CollisionFace* Closest;
float MinLimit;
CullModeCallback Callback;
void* UserData;
Point ViewPoint;
const MeshInterface* IMesh;
};
// Called for each stabbed face
static void RenderCullingCallback(const CollisionFace& hit, void* user_data)
{
CullData* Data = (CullData*)user_data;
// Discard face if we already have a closer hit
if(hit.mDistance>=Data->Closest->mDistance) return;
// Discard face if hit point is smaller than min limit. This mainly happens when the face is in front
// of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an
// object that he may not even be able to see, which is very annoying.
if(hit.mDistance<=Data->MinLimit) return;
// This is the index of currently stabbed triangle.
udword StabbedFaceIndex = hit.mFaceID;
// We may keep it or not, depending on backface culling
bool KeepIt = true;
// Catch *render* cull mode for this face
CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData);
if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles
{
// Compute backface culling for current face
VertexPointers VP;
ConversionArea VC;
Data->IMesh->GetTriangle(VP, StabbedFaceIndex, VC);
if(VP.BackfaceCulling(Data->ViewPoint))
{
if(CM==CULLMODE_CW) KeepIt = false;
}
else
{
if(CM==CULLMODE_CCW) KeepIt = false;
}
}
if(KeepIt) *Data->Closest = hit;
}
};
RayCollider RC;
RC.SetMaxDist(max_dist);
RC.SetTemporalCoherence(false);
RC.SetCulling(false); // We need all faces since some of them can be double-sided
RC.SetFirstContact(false);
RC.SetHitCallback(Local::RenderCullingCallback);
picked_face.mFaceID = INVALID_ID;
picked_face.mDistance = MAX_FLOAT;
picked_face.mU = 0.0f;
picked_face.mV = 0.0f;
Local::CullData Data;
Data.Closest = &picked_face;
Data.MinLimit = min_dist;
Data.Callback = callback;
Data.UserData = user_data;
Data.ViewPoint = view_point;
Data.IMesh = model.GetMeshInterface();
if(world)
{
// Get matrices
Matrix4x4 InvWorld;
InvertPRMatrix(InvWorld, *world);
// Compute camera position in mesh space
Data.ViewPoint *= InvWorld;
}
RC.SetUserData(&Data);
if(RC.Collide(world_ray, model, world))
{
return picked_face.mFaceID!=INVALID_ID;
}
return false;
}
#endif
ode-0.16.2/OPCODE/OPC_SphereTriOverlap.h 0000664 0001752 0001752 00000010535 13710545230 014363 0000000 0000000
// This is collision detection. If you do another distance test for collision *response*,
// if might be useful to simply *skip* the test below completely, and report a collision.
// - if sphere-triangle overlap, result is ok
// - if they don't, we'll discard them during collision response with a similar test anyway
// Overall this approach should run faster.
// Original code by David Eberly in Magic.
BOOL SphereCollider::SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2)
{
// Stats
mNbVolumePrimTests++;
// Early exit if one of the vertices is inside the sphere
Point kDiff = vert2 - mCenter;
float fC = kDiff.SquareMagnitude();
if(fC <= mRadius2) return TRUE;
kDiff = vert1 - mCenter;
fC = kDiff.SquareMagnitude();
if(fC <= mRadius2) return TRUE;
kDiff = vert0 - mCenter;
fC = kDiff.SquareMagnitude();
if(fC <= mRadius2) return TRUE;
// Else do the full distance test
Point TriEdge0 = vert1 - vert0;
Point TriEdge1 = vert2 - vert0;
//Point kDiff = vert0 - mCenter;
float fA00 = TriEdge0.SquareMagnitude();
float fA01 = TriEdge0 | TriEdge1;
float fA11 = TriEdge1.SquareMagnitude();
float fB0 = kDiff | TriEdge0;
float fB1 = kDiff | TriEdge1;
//float fC = kDiff.SquareMagnitude();
float fDet = fabsf(fA00*fA11 - fA01*fA01);
float u = fA01*fB1-fA11*fB0;
float v = fA01*fB0-fA00*fB1;
float SqrDist;
if(u + v <= fDet)
{
if(u < 0.0f)
{
if(v < 0.0f) // region 4
{
if(fB0 < 0.0f)
{
// v = 0.0f;
if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; }
else { u = -fB0/fA00; SqrDist = fB0*u+fC; }
}
else
{
// u = 0.0f;
if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; }
else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; }
else { v = -fB1/fA11; SqrDist = fB1*v+fC; }
}
}
else // region 3
{
// u = 0.0f;
if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; }
else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; }
else { v = -fB1/fA11; SqrDist = fB1*v+fC; }
}
}
else if(v < 0.0f) // region 5
{
// v = 0.0f;
if(fB0>=0.0f) { /*u = 0.0f;*/ SqrDist = fC; }
else if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; }
else { u = -fB0/fA00; SqrDist = fB0*u+fC; }
}
else // region 0
{
// minimum at interior point
if(fDet==0.0f)
{
// u = 0.0f;
// v = 0.0f;
SqrDist = MAX_FLOAT;
}
else
{
float fInvDet = 1.0f/fDet;
u *= fInvDet;
v *= fInvDet;
SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
}
}
}
else
{
float fTmp0, fTmp1, fNumer, fDenom;
if(u < 0.0f) // region 2
{
fTmp0 = fA01 + fB0;
fTmp1 = fA11 + fB1;
if(fTmp1 > fTmp0)
{
fNumer = fTmp1 - fTmp0;
fDenom = fA00-2.0f*fA01+fA11;
if(fNumer >= fDenom)
{
// u = 1.0f;
// v = 0.0f;
SqrDist = fA00+2.0f*fB0+fC;
}
else
{
u = fNumer/fDenom;
v = 1.0f - u;
SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
}
}
else
{
// u = 0.0f;
if(fTmp1 <= 0.0f) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; }
else if(fB1 >= 0.0f) { /*v = 0.0f;*/ SqrDist = fC; }
else { v = -fB1/fA11; SqrDist = fB1*v+fC; }
}
}
else if(v < 0.0f) // region 6
{
fTmp0 = fA01 + fB1;
fTmp1 = fA00 + fB0;
if(fTmp1 > fTmp0)
{
fNumer = fTmp1 - fTmp0;
fDenom = fA00-2.0f*fA01+fA11;
if(fNumer >= fDenom)
{
// v = 1.0f;
// u = 0.0f;
SqrDist = fA11+2.0f*fB1+fC;
}
else
{
v = fNumer/fDenom;
u = 1.0f - v;
SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
}
}
else
{
// v = 0.0f;
if(fTmp1 <= 0.0f) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; }
else if(fB0 >= 0.0f) { /*u = 0.0f;*/ SqrDist = fC; }
else { u = -fB0/fA00; SqrDist = fB0*u+fC; }
}
}
else // region 1
{
fNumer = fA11 + fB1 - fA01 - fB0;
if(fNumer <= 0.0f)
{
// u = 0.0f;
// v = 1.0f;
SqrDist = fA11+2.0f*fB1+fC;
}
else
{
fDenom = fA00-2.0f*fA01+fA11;
if(fNumer >= fDenom)
{
// u = 1.0f;
// v = 0.0f;
SqrDist = fA00+2.0f*fB0+fC;
}
else
{
u = fNumer/fDenom;
v = 1.0f - u;
SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
}
}
}
}
return fabsf(SqrDist) < mRadius2;
}
ode-0.16.2/OPCODE/Ice/ 0000775 0001752 0001752 00000000000 13710545442 011034 5 0000000 0000000 ode-0.16.2/OPCODE/Ice/IcePairs.h 0000664 0001752 0001752 00000003373 13710545230 012625 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__
ode-0.16.2/OPCODE/Ice/IceUtils.h 0000664 0001752 0001752 00000025504 13710545230 012647 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__){ -- not thread safe
// #define END_RUNONCE __RunOnce__ = true;}} -- not thread safe
//! 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<> 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 inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; }
template inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((xhi) ? hi : x); }
template inline_ void TSort(Type& a, Type& b)
{
if(a>b) TSwap(a, b);
}
template 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
#ifndef ARRAYSIZE
#define ARRAYSIZE(p) (sizeof(p)/sizeof((p)[0]))
#endif // #ifndef ARRAYSIZE
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__
ode-0.16.2/OPCODE/Ice/IceRay.cpp 0000664 0001752 0001752 00000004700 13710545230 012630 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 IceMaths;
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();
}
ode-0.16.2/OPCODE/Ice/IceIndexedTriangle.h 0000664 0001752 0001752 00000006666 13710545230 014625 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a handy indexed triangle class.
* \file IceIndexedTriangle.h
* \author Pierre Terdiman
* \date January, 17, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "ode/common.h"
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __ICEINDEXEDTRIANGLE_H__
#define __ICEINDEXEDTRIANGLE_H__
// Forward declarations
#ifdef _MSC_VER
enum CubeIndex;
#else
typedef int CubeIndex;
#endif
// An indexed triangle class.
class ICEMATHS_API IndexedTriangle
{
public:
//! Constructor
inline_ IndexedTriangle() {}
//! Constructor
inline_ IndexedTriangle(dTriIndex r0, dTriIndex r1, dTriIndex 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
dTriIndex 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(dTriIndex oldref, dTriIndex newref);
bool IsDegenerate() const;
bool HasVertex(dTriIndex ref) const;
bool HasVertex(dTriIndex ref, dTriIndex* index) const;
ubyte FindEdge(dTriIndex vref0, dTriIndex vref1) const;
dTriIndex OppositeVertex(dTriIndex vref0, dTriIndex vref1) const;
inline_ dTriIndex OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; }
void GetVRefs(ubyte edgenb, dTriIndex& vref0, dTriIndex& vref1, dTriIndex& 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, dTriIndex* 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__
ode-0.16.2/OPCODE/Ice/IceRevisitedRadix.h 0000664 0001752 0001752 00000005032 13710545230 014467 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__
ode-0.16.2/OPCODE/Ice/IceRandom.h 0000664 0001752 0001752 00000003051 13710545230 012760 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__
ode-0.16.2/OPCODE/Ice/IceTriList.h 0000664 0001752 0001752 00000004273 13710545230 013141 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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((udword)tri.mVRef[0]).Add((udword)tri.mVRef[1]).Add((udword)tri.mVRef[2]);
}
void AddTriangle(udword vref0, udword vref1, udword vref2)
{
Add(vref0).Add(vref1).Add(vref2);
}
};
#endif //__ICETRILIST_H__
ode-0.16.2/OPCODE/Ice/IceLSS.h 0000664 0001752 0001752 00000007561 13710545230 012213 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__
ode-0.16.2/OPCODE/Ice/IceIndexedTriangle.cpp 0000664 0001752 0001752 00000057302 13710545230 015151 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains a handy indexed triangle class.
* \file IceIndexedTriangle.cpp
* \author Pierre Terdiman
* \date January, 17, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace IceMaths;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains an indexed triangle class.
*
* \class Triangle
* \author Pierre Terdiman
* \version 1.0
* \date 08.15.98
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Flips the winding order.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void IndexedTriangle::Flip()
{
Swap(mVRef[1], mVRef[2]);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle area.
* \param verts [in] the list of indexed vertices
* \return the area
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float IndexedTriangle::Area(const Point* verts) const
{
if(!verts) return 0.0f;
const Point& p0 = verts[0];
const Point& p1 = verts[1];
const Point& p2 = verts[2];
return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle perimeter.
* \param verts [in] the list of indexed vertices
* \return the perimeter
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float IndexedTriangle::Perimeter(const Point* verts) const
{
if(!verts) return 0.0f;
const Point& p0 = verts[0];
const Point& p1 = verts[1];
const Point& p2 = verts[2];
return p0.Distance(p1)
+ p0.Distance(p2)
+ p1.Distance(p2);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle compacity.
* \param verts [in] the list of indexed vertices
* \return the compacity
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float IndexedTriangle::Compacity(const Point* verts) const
{
if(!verts) return 0.0f;
float P = Perimeter(verts);
if(P==0.0f) return 0.0f;
return (4.0f*PI*Area(verts)/(P*P));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle normal.
* \param verts [in] the list of indexed vertices
* \param normal [out] the computed normal
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void IndexedTriangle::Normal(const Point* verts, Point& normal) const
{
if(!verts) return;
const Point& p0 = verts[mVRef[0]];
const Point& p1 = verts[mVRef[1]];
const Point& p2 = verts[mVRef[2]];
normal = ((p2-p1)^(p0-p1)).Normalize();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle denormalized normal.
* \param verts [in] the list of indexed vertices
* \param normal [out] the computed normal
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void IndexedTriangle::DenormalizedNormal(const Point* verts, Point& normal) const
{
if(!verts) return;
const Point& p0 = verts[mVRef[0]];
const Point& p1 = verts[mVRef[1]];
const Point& p2 = verts[mVRef[2]];
normal = ((p2-p1)^(p0-p1));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle center.
* \param verts [in] the list of indexed vertices
* \param center [out] the computed center
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void IndexedTriangle::Center(const Point* verts, Point& center) const
{
if(!verts) return;
const Point& p0 = verts[mVRef[0]];
const Point& p1 = verts[mVRef[1]];
const Point& p2 = verts[mVRef[2]];
center = (p0+p1+p2)*INV3;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the centered normal
* \param verts [in] the list of indexed vertices
* \param normal [out] the computed centered normal
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void IndexedTriangle::CenteredNormal(const Point* verts, Point& normal) const
{
if(!verts) return;
const Point& p0 = verts[mVRef[0]];
const Point& p1 = verts[mVRef[1]];
const Point& p2 = verts[mVRef[2]];
Point Center = (p0+p1+p2)*INV3;
normal = Center + ((p2-p1)^(p0-p1)).Normalize();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes a random point within the triangle.
* \param verts [in] the list of indexed vertices
* \param normal [out] the computed centered normal
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void IndexedTriangle::RandomPoint(const Point* verts, Point& random) const
{
if(!verts) return;
// Random barycentric coords
float Alpha = UnitRandomFloat();
float Beta = UnitRandomFloat();
float Gamma = UnitRandomFloat();
float OneOverTotal = 1.0f / (Alpha + Beta + Gamma);
Alpha *= OneOverTotal;
Beta *= OneOverTotal;
Gamma *= OneOverTotal;
const Point& p0 = verts[mVRef[0]];
const Point& p1 = verts[mVRef[1]];
const Point& p2 = verts[mVRef[2]];
random = Alpha*p0 + Beta*p1 + Gamma*p2;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes backface culling.
* \param verts [in] the list of indexed vertices
* \param source [in] source point (in local space) from which culling must be computed
* \return true if the triangle is visible from the source point
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool IndexedTriangle::IsVisible(const Point* verts, const Point& source) const
{
// Checkings
if(!verts) return false;
const Point& p0 = verts[mVRef[0]];
const Point& p1 = verts[mVRef[1]];
const Point& p2 = verts[mVRef[2]];
// Compute denormalized normal
Point Normal = (p2 - p1)^(p0 - p1);
// Backface culling
return (Normal | source) >= 0.0f;
// Same as:
// Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
// return PL.Distance(source) > PL.d;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes backface culling.
* \param verts [in] the list of indexed vertices
* \param source [in] source point (in local space) from which culling must be computed
* \return true if the triangle is visible from the source point
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool IndexedTriangle::BackfaceCulling(const Point* verts, const Point& source) const
{
// Checkings
if(!verts) return false;
const Point& p0 = verts[mVRef[0]];
const Point& p1 = verts[mVRef[1]];
const Point& p2 = verts[mVRef[2]];
// Compute base
// Point Base = (p0 + p1 + p2)*INV3;
// Compute denormalized normal
Point Normal = (p2 - p1)^(p0 - p1);
// Backface culling
// return (Normal | (source - Base)) >= 0.0f;
return (Normal | (source - p0)) >= 0.0f;
// Same as: (but a bit faster)
// Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
// return PL.Distance(source)>0.0f;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the occlusion potential of the triangle.
* \param verts [in] the list of indexed vertices
* \param source [in] source point (in local space) from which occlusion potential must be computed
* \return the occlusion potential
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float IndexedTriangle::ComputeOcclusionPotential(const Point* verts, const Point& view) const
{
if(!verts) return 0.0f;
// Occlusion potential: -(A * (N|V) / d^2)
// A = polygon area
// N = polygon normal
// V = view vector
// d = distance viewpoint-center of polygon
float A = Area(verts);
Point N; Normal(verts, N);
Point C; Center(verts, C);
float d = view.Distance(C);
return -(A*(N|view))/(d*d);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Replaces a vertex reference with another one.
* \param oldref [in] the vertex reference to replace
* \param newref [in] the new vertex reference
* \return true if success, else false if the input vertex reference doesn't belong to the triangle
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool IndexedTriangle::ReplaceVertex(dTriIndex oldref, dTriIndex newref)
{
if(mVRef[0]==oldref) { mVRef[0] = newref; return true; }
else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; }
else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; }
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks whether the triangle is degenerate or not. A degenerate triangle has two common vertex references. This is a zero-area triangle.
* \return true if the triangle is degenerate
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool IndexedTriangle::IsDegenerate() const
{
if(mVRef[0]==mVRef[1]) return true;
if(mVRef[1]==mVRef[2]) return true;
if(mVRef[2]==mVRef[0]) return true;
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks whether the input vertex reference belongs to the triangle or not.
* \param ref [in] the vertex reference to look for
* \return true if the triangle contains the vertex reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool IndexedTriangle::HasVertex(dTriIndex ref) const
{
if(mVRef[0]==ref) return true;
if(mVRef[1]==ref) return true;
if(mVRef[2]==ref) return true;
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks whether the input vertex reference belongs to the triangle or not.
* \param ref [in] the vertex reference to look for
* \param index [out] the corresponding index in the triangle
* \return true if the triangle contains the vertex reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool IndexedTriangle::HasVertex(dTriIndex ref, dTriIndex* index) const
{
if(mVRef[0]==ref) { *index = 0; return true; }
if(mVRef[1]==ref) { *index = 1; return true; }
if(mVRef[2]==ref) { *index = 2; return true; }
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Finds an edge in a tri, given two vertex references.
* \param vref0 [in] the edge's first vertex reference
* \param vref1 [in] the edge's second vertex reference
* \return the edge number between 0 and 2, or 0xff if input refs are wrong.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ubyte IndexedTriangle::FindEdge(dTriIndex vref0, dTriIndex vref1) const
{
if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0;
else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0;
else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1;
else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1;
else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2;
else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2;
return 0xff;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the last reference given the first two.
* \param vref0 [in] the first vertex reference
* \param vref1 [in] the second vertex reference
* \return the last reference, or INVALID_ID if input refs are wrong.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
dTriIndex IndexedTriangle::OppositeVertex(dTriIndex vref0, dTriIndex vref1) const
{
if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2];
else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2];
else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1];
else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1];
else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0];
else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0];
return (dTriIndex)INVALID_ID;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the three sorted vertex references according to an edge number.
* edgenb = 0 => edge 0-1, returns references 0, 1, 2
* edgenb = 1 => edge 0-2, returns references 0, 2, 1
* edgenb = 2 => edge 1-2, returns references 1, 2, 0
*
* \param edgenb [in] the edge number, 0, 1 or 2
* \param vref0 [out] the returned first vertex reference
* \param vref1 [out] the returned second vertex reference
* \param vref2 [out] the returned third vertex reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void IndexedTriangle::GetVRefs(ubyte edgenb, dTriIndex& vref0, dTriIndex& vref1, dTriIndex& vref2) const
{
if(edgenb==0)
{
vref0 = mVRef[0];
vref1 = mVRef[1];
vref2 = mVRef[2];
}
else if(edgenb==1)
{
vref0 = mVRef[0];
vref1 = mVRef[2];
vref2 = mVRef[1];
}
else if(edgenb==2)
{
vref0 = mVRef[1];
vref1 = mVRef[2];
vref2 = mVRef[0];
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle's smallest edge length.
* \param verts [in] the list of indexed vertices
* \return the smallest edge length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float IndexedTriangle::MinEdgeLength(const Point* verts) const
{
if(!verts) return 0.0f;
float Min = MAX_FLOAT;
float Length01 = verts[0].Distance(verts[1]);
float Length02 = verts[0].Distance(verts[2]);
float Length12 = verts[1].Distance(verts[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.
* \param verts [in] the list of indexed vertices
* \return the largest edge length
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float IndexedTriangle::MaxEdgeLength(const Point* verts) const
{
if(!verts) return 0.0f;
float Max = MIN_FLOAT;
float Length01 = verts[0].Distance(verts[1]);
float Length02 = verts[0].Distance(verts[2]);
float Length12 = verts[1].Distance(verts[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 verts [in] the list of indexed vertices
* \param u,v [in] point's barycentric coordinates
* \param pt [out] point on triangle
* \param nearvtx [out] index of nearest vertex
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void IndexedTriangle::ComputePoint(const Point* verts, float u, float v, Point& pt, dTriIndex* nearvtx) const
{
// Checkings
if(!verts) return;
// Get face in local or global space
const Point& p0 = verts[mVRef[0]];
const Point& p1 = verts[mVRef[1]];
const Point& p2 = verts[mVRef[2]];
// Compute point coordinates
pt = (1.0f - u - v)*p0 + u*p1 + v*p2;
// Compute nearest vertex if needed
if(nearvtx)
{
// Compute distance vector
Point d(p0.SquareDistance(pt), // Distance^2 from vertex 0 to point on the face
p1.SquareDistance(pt), // Distance^2 from vertex 1 to point on the face
p2.SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face
// Get smallest distance
*nearvtx = mVRef[d.SmallestAxis()];
}
}
//**************************************
// Angle between two vectors (in radians)
// we use this formula
// uv = |u||v| cos(u,v)
// u ^ v = w
// |w| = |u||v| |sin(u,v)|
//**************************************
float Angle(const Point& u, const Point& v)
{
float NormU = u.Magnitude(); // |u|
float NormV = v.Magnitude(); // |v|
float Product = NormU*NormV; // |u||v|
if(Product==0.0f) return 0.0f;
float OneOverProduct = 1.0f / Product;
// Cosinus
float Cosinus = (u|v) * OneOverProduct;
// Sinus
Point w = u^v;
float NormW = w.Magnitude();
float AbsSinus = NormW * OneOverProduct;
// Remove degeneracy
if(AbsSinus > 1.0f) AbsSinus = 1.0f;
if(AbsSinus < -1.0f) AbsSinus = -1.0f;
if(Cosinus>=0.0f) return asinf(AbsSinus);
else return (PI-asinf(AbsSinus));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the angle between two triangles.
* \param tri [in] the other triangle
* \param verts [in] the list of indexed vertices
* \return the angle in radians
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float IndexedTriangle::Angle(const IndexedTriangle& tri, const Point* verts) const
{
// Checkings
if(!verts) return 0.0f;
// Compute face normals
Point n0, n1;
Normal(verts, n0);
tri.Normal(verts, n1);
// Compute angle
float dp = n0|n1;
if(dp>1.0f) return 0.0f;
if(dp<-1.0f) return PI;
return acosf(dp);
// return ::Angle(n0,n1);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks a triangle is the same as another one.
* \param tri [in] the other triangle
* \return true if same triangle
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool IndexedTriangle::Equal(const IndexedTriangle& tri) const
{
// Test all vertex references
return (HasVertex(tri.mVRef[0]) &&
HasVertex(tri.mVRef[1]) &&
HasVertex(tri.mVRef[2]));
}
ode-0.16.2/OPCODE/Ice/Makefile.am 0000664 0001752 0001752 00000002055 13710545230 013005 0000000 0000000 AM_CPPFLAGS = -I$(top_srcdir)/OPCODE \
-I$(top_srcdir)/include \
-I$(top_builddir)/include
noinst_LTLIBRARIES = libIce.la
libIce_la_SOURCES = \
IceAABB.cpp IceAABB.h IceAxes.h \
IceBoundingSphere.h IceContainer.cpp IceContainer.h \
IceFPU.h IceHPoint.cpp IceHPoint.h \
IceIndexedTriangle.cpp IceIndexedTriangle.h IceLSS.h \
IceMatrix3x3.cpp IceMatrix3x3.h IceMatrix4x4.cpp \
IceMatrix4x4.h IceMemoryMacros.h IceOBB.cpp \
IceOBB.h IcePairs.h IcePlane.cpp \
IcePlane.h IcePoint.cpp IcePoint.h \
IcePreprocessor.h IceRandom.cpp IceRandom.h \
IceRay.cpp IceRay.h IceRevisitedRadix.cpp \
IceRevisitedRadix.h IceSegment.cpp IceSegment.h \
IceTriangle.cpp IceTriangle.h IceTriList.h \
IceTypes.h IceUtils.cpp IceUtils.h
ode-0.16.2/OPCODE/Ice/IceSegment.cpp 0000664 0001752 0001752 00000003610 13710545230 013476 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 IceMaths;
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();
}
ode-0.16.2/OPCODE/Ice/IcePreprocessor.h 0000664 0001752 0001752 00000007124 13710545230 014233 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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
// don't issue pragmas on unknown platforms
// #pragma message("Compiling on unknown platform...")
#endif
// Check compiler
#if defined(_MSC_VER)
// #pragma message("Compiling with VC++...")
#define COMPILER_VISUAL_CPP
#else
// don't issue pragmas on unknown platforms
// #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
#ifdef _MSC_VER
#pragma inline_depth( 255 )
#endif
#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__
ode-0.16.2/OPCODE/Ice/IceHPoint.cpp 0000664 0001752 0001752 00000007554 13710545230 013310 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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 IceMaths;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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;
}
ode-0.16.2/OPCODE/Ice/IceSegment.h 0000664 0001752 0001752 00000005102 13710545230 013141 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__
ode-0.16.2/OPCODE/Ice/IceRay.h 0000664 0001752 0001752 00000011120 13710545230 012267 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* 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__
ode-0.16.2/OPCODE/Ice/IceRevisitedRadix.cpp 0000664 0001752 0001752 00000053002 13710545230 015022 0000000 0000000 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains source code from the article "Radix Sort Revisited".
* \file IceRevisitedRadix.cpp
* \author Pierre Terdiman
* \date April, 4, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Revisited Radix Sort.
* This is my new radix routine:
* - it uses indices and doesn't recopy the values anymore, hence wasting less ram
* - it creates all the histograms in one run instead of four
* - it sorts words faster than dwords and bytes faster than words
* - it correctly sorts negative floating-point values by patching the offsets
* - it automatically takes advantage of temporal coherence
* - multiple keys support is a side effect of temporal coherence
* - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway]
*
* History:
* - 08.15.98: very first version
* - 04.04.00: recoded for the radix article
* - 12.xx.00: code lifting
* - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here)
* - 10.11.01: added local ram support
* - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting......
* - 01.02.02: - "mIndices" renamed => "mRanks". That's a rank sorter after all.
* - ranks are not "reset" anymore, but implicit on first calls
* - 07.05.02: - offsets rewritten with one less indirection.
* - 11.03.02: - "bool" replaced with RadixHint enum
*
* \class RadixSort
* \author Pierre Terdiman
* \version 1.4
* \date August, 15, 1998
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
To do:
- add an offset parameter between two input values (avoid some data recopy sometimes)
- unroll ? asm ?
- 11 bits trick & 3 passes as Michael did
- prefetch stuff the day I have a P3
- make a version with 16-bits indices ?
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "Stdafx.h"
using namespace IceCore;
#define INVALIDATE_RANKS mCurrentSize|=0x80000000
#define VALIDATE_RANKS mCurrentSize&=0x7fffffff
#define CURRENT_SIZE (mCurrentSize&0x7fffffff)
#define INVALID_RANKS (mCurrentSize&0x80000000)
#define CHECK_RESIZE(n) \
if(n!=mPreviousSize) \
{ \
if(n>mCurrentSize) Resize(n); \
else ResetRanks(); \
mPreviousSize = n; \
}
#define CREATE_HISTOGRAMS(type, buffer) \
/* Clear counters/histograms */ \
ZeroMemory(mHistogram, 256*4*sizeof(udword)); \
\
/* Prepare to count */ \
ubyte* p = (ubyte*)input; \
ubyte* pe = &p[nb*4]; \
udword* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \
udword* h1= &mHistogram[256]; /* Histogram for second pass */ \
udword* h2= &mHistogram[512]; /* Histogram for third pass */ \
udword* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \
\
bool AlreadySorted = true; /* Optimism... */ \
\
if(INVALID_RANKS) \
{ \
/* Prepare for temporal coherence */ \
type* Running = (type*)buffer; \
type PrevVal = *Running; \
\
while(p!=pe) \
{ \
/* Read input buffer in previous sorted order */ \
type Val = *Running++; \
/* Check whether already sorted or not */ \
if(ValCurSize) Resize(nb);
mCurrentSize = nb;
INVALIDATE_RANKS;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Main sort routine.
* This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data.
* \param input [in] a list of integer values to sort
* \param nb [in] number of values to sort, must be < 2^31
* \param hint [in] RADIX_SIGNED to handle negative values, RADIX_UNSIGNED if you know your input buffer only contains positive values
* \return Self-Reference
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RadixSort& RadixSort::Sort(const udword* input, udword nb, RadixHint hint)
{
// Checkings
if(!input || !nb || nb&0x80000000) return *this;
// Stats
mTotalCalls++;
// Resize lists if needed
CheckResize(nb);
#ifdef RADIX_LOCAL_RAM
// Allocate histograms & offsets on the stack
udword mHistogram[256*4];
// udword mOffset[256];
udword* mLink[256];
#endif
// Create histograms (counters). Counters for all passes are created in one run.
// Pros: read input buffer once instead of four times
// Cons: mHistogram is 4Kb instead of 1Kb
// We must take care of signed/unsigned values for temporal coherence.... I just
// have 2 code paths even if just a single opcode changes. Self-modifying code, someone?
if(hint==RADIX_UNSIGNED) { CREATE_HISTOGRAMS(udword, input); }
else { CREATE_HISTOGRAMS(sdword, input); }
// Compute #negative values involved if needed
udword NbNegativeValues = 0;
if(hint==RADIX_SIGNED)
{
// An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128
// last values of the last histogram. Last histogram because that's the one for the Most Significant Byte,
// responsible for the sign. 128 last values because the 128 first ones are related to positive numbers.
udword* h3= &mHistogram[768];
for(udword i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part
}
// Radix sort, j is the pass number (0=LSB, 3=MSB)
for(udword j=0;j<4;j++)
{
CHECK_PASS_VALIDITY(j);
// Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is
// not a problem, numbers are correctly sorted anyway.
if(PerformPass)
{
// Should we care about negative values?
if(j!=3 || hint==RADIX_UNSIGNED)
{
// Here we deal with positive values only
// Create offsets
// mOffset[0] = 0;
// for(udword i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
mLink[0] = mRanks2;
for(udword i=1;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1];
}
else
{
// This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place.
// Create biased offsets, in order for negative numbers to be sorted as well
// mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones
mLink[0] = &mRanks2[NbNegativeValues]; // First positive number takes place after the negative ones
// for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
// Fixing the wrong place for negative values
// mOffset[128] = 0;
mLink[128] = mRanks2;
// for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
for(udword i=129;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1];
}
// Perform Radix Sort
ubyte* InputBytes = (ubyte*)input;
InputBytes += j;
if(INVALID_RANKS)
{
// for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword).
// ### cmp to be killed. Not good. Later.
// if(Radix<128) mRanks2[mOffset[Radix]++] = i; // Number is positive, same as above
// else mRanks2[--mOffset[Radix]] = i; // Number is negative, flip the sorting order
if(Radix<128) *mLink[Radix]++ = i; // Number is positive, same as above
else *(--mLink[Radix]) = i; // Number is negative, flip the sorting order
}
VALIDATE_RANKS;
}
else
{
for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword).
// ### cmp to be killed. Not good. Later.
// if(Radix<128) mRanks2[mOffset[Radix]++] = mRanks[i]; // Number is positive, same as above
// else mRanks2[--mOffset[Radix]] = mRanks[i]; // Number is negative, flip the sorting order
if(Radix<128) *mLink[Radix]++ = mRanks[i]; // Number is positive, same as above
else *(--mLink[Radix]) = mRanks[i]; // Number is negative, flip the sorting order
}
}
// Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap.
udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp;
}
else
{
// The pass is useless, yet we still have to reverse the order of current list if all values are negative.
if(UniqueVal>=128)
{
if(INVALID_RANKS)
{
// ###Possible?
for(udword i=0;i