160 lines
5.8 KiB
C++
160 lines
5.8 KiB
C++
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
* OPCODE - Optimized Collision Detection
|
|
* Copyright (C) 2001 Pierre Terdiman
|
|
* Homepage: http://www.codercorner.com/Opcode.htm
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
* Contains an array-based version of the sweep-and-prune algorithm
|
|
* \file OPC_ArraySAP.h
|
|
* \author Pierre Terdiman
|
|
* \date December, 2, 2007
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Include Guard
|
|
#ifndef OPC_ARRAYSAP_H
|
|
#define OPC_ARRAYSAP_H
|
|
|
|
#pragma pack(1)
|
|
struct OPCODE_API ASAP_Pair
|
|
{
|
|
uword id0;
|
|
uword id1;
|
|
const void* object0;
|
|
const void* object1;
|
|
//#ifdef PAIR_USER_DATA
|
|
void* userData;
|
|
//#endif
|
|
inline_ const void* GetObject0() const { return (const void*)(size_t(object0) & ~3); }
|
|
inline_ const void* GetObject1() const { return (const void*)(size_t(object1) & ~3); }
|
|
inline_ size_t IsInArray() const { return size_t(object0) & 1; }
|
|
inline_ size_t IsRemoved() const { return size_t(object1) & 1; }
|
|
inline_ size_t IsNew() const { return size_t(object0) & 2; }
|
|
private:
|
|
inline_ void SetInArray() { object0 = (const void*)(size_t(object0) | 1); }
|
|
inline_ void SetRemoved() { object1 = (const void*)(size_t(object1) | 1); }
|
|
inline_ void SetNew() { object0 = (const void*)(size_t(object0) | 2); }
|
|
inline_ void ClearInArray() { object0 = (const void*)(size_t(object0) & ~1); }
|
|
inline_ void ClearRemoved() { object1 = (const void*)(size_t(object1) & ~1); }
|
|
inline_ void ClearNew() { object0 = (const void*)(size_t(object0) & ~2); }
|
|
|
|
friend class ArraySAP;
|
|
};
|
|
#pragma pack()
|
|
|
|
class OPCODE_API ASAP_PairManager
|
|
{
|
|
public:
|
|
ASAP_PairManager();
|
|
~ASAP_PairManager();
|
|
|
|
void Purge();
|
|
void ShrinkMemory();
|
|
|
|
const ASAP_Pair* AddPair (uword id0, uword id1, const void* object0, const void* object1);
|
|
bool RemovePair (uword id0, uword id1);
|
|
bool RemovePairs (const BitArray& array);
|
|
const ASAP_Pair* FindPair (uword id0, uword id1) const;
|
|
inline_ udword GetPairIndex(const ASAP_Pair* pair) const
|
|
{
|
|
return ((udword)((size_t(pair) - size_t(mActivePairs)))/sizeof(ASAP_Pair));
|
|
}
|
|
|
|
udword mHashSize;
|
|
udword mMask;
|
|
udword mNbActivePairs;
|
|
udword* mHashTable;
|
|
udword* mNext;
|
|
ASAP_Pair* mActivePairs;
|
|
inline_ ASAP_Pair* FindPair(uword id0, uword id1, udword hash_value) const;
|
|
void RemovePair(uword id0, uword id1, udword hash_value, udword pair_index);
|
|
void ReallocPairs();
|
|
};
|
|
|
|
typedef void* (*SAP_CreatePair)(const void* object0, const void* object1, void* user_data);
|
|
typedef void (*SAP_DeletePair)(const void* object0, const void* object1, void* user_data, void* pair_user_data);
|
|
|
|
// Forward declarations
|
|
class ASAP_EndPoint;
|
|
class ASAP_Box;
|
|
struct IAABB;
|
|
struct CreateData;
|
|
|
|
class OPCODE_API ArraySAP : public Allocateable
|
|
{
|
|
public:
|
|
ArraySAP();
|
|
~ArraySAP();
|
|
|
|
udword AddObject(void* object, uword guid, const AABB& box);
|
|
bool RemoveObject(udword handle);
|
|
bool UpdateObject(udword handle, const AABB& box);
|
|
|
|
udword DumpPairs(SAP_CreatePair create_cb, SAP_DeletePair delete_cb, void* cb_user_data, ASAP_Pair** pairs=null);
|
|
private:
|
|
Container mData;
|
|
ASAP_PairManager mPairs;
|
|
|
|
inline_ void AddPair(const void* object0, const void* object1, uword id0, uword id1)
|
|
{
|
|
ASSERT(object0);
|
|
ASAP_Pair* UP = (ASAP_Pair*)mPairs.AddPair(id0, id1, null, null);
|
|
ASSERT(UP);
|
|
|
|
if(UP->object0)
|
|
{
|
|
// Persistent pair
|
|
}
|
|
else
|
|
{
|
|
// New pair
|
|
ASSERT(!(int(object0)&1));
|
|
ASSERT(!(int(object1)&1));
|
|
UP->object0 = object0;
|
|
UP->object1 = object1;
|
|
UP->SetInArray();
|
|
mData.Add(mPairs.GetPairIndex(UP));
|
|
UP->SetNew();
|
|
}
|
|
UP->ClearRemoved();
|
|
}
|
|
|
|
inline_ void RemovePair(const void* object0, const void* object1, uword id0, uword id1)
|
|
{
|
|
ASAP_Pair* UP = (ASAP_Pair*)mPairs.FindPair(id0, id1);
|
|
if(UP)
|
|
{
|
|
if(!UP->IsInArray())
|
|
{
|
|
UP->SetInArray();
|
|
mData.Add(mPairs.GetPairIndex(UP));
|
|
}
|
|
UP->SetRemoved();
|
|
}
|
|
}
|
|
|
|
udword mNbBoxes;
|
|
udword mMaxNbBoxes;
|
|
ASAP_Box* mBoxes;
|
|
ASAP_EndPoint* mEndPoints[3];
|
|
udword mFirstFree;
|
|
|
|
void ResizeBoxArray();
|
|
// For batch creation
|
|
Container mCreated;
|
|
void BatchCreate();
|
|
void InsertEndPoints(udword axis, const ASAP_EndPoint* end_points, udword nb_endpoints);
|
|
bool CompleteBoxPruning2(udword nb, const IAABB* array, const Axes& axes, const CreateData* batched);
|
|
bool BipartiteBoxPruning2(udword nb0, const IAABB* array0, udword nb1, const IAABB* array1, const Axes& axes, const CreateData* batched, const udword* box_indices);
|
|
// For batch removal
|
|
Container mRemoved;
|
|
void BatchRemove();
|
|
};
|
|
|
|
#endif // OPC_ARRAYSAP_H
|