mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-06 05:50:31 +00:00
Optimize container bin lookups
This commit is contained in:
parent
c6047b24eb
commit
596d13f9a4
12 changed files with 1100 additions and 708 deletions
|
|
@ -39,7 +39,6 @@
|
|||
#include "console/console.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "gfx/gfxTextureHandle.h"
|
||||
#include "scene/sceneContainer.h"
|
||||
|
||||
#include "math/mPolyhedron.impl.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "core/dataChunker.h"
|
||||
#include "collision/collision.h"
|
||||
#include "scene/sceneObject.h"
|
||||
#include "scene/sceneContainer.h"
|
||||
#include "collision/gjk.h"
|
||||
#include "collision/concretePolyList.h"
|
||||
#include "platform/profiler.h"
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "core/strings/stringUnit.h"
|
||||
#include "math/mRandomDeck.h"
|
||||
#include "math/mRandomSet.h"
|
||||
#include "scene/sceneContainer.h"
|
||||
|
||||
|
||||
bool ForestBrushTool::protectedSetSize( void *object, const char *index, const char *data )
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "windowManager/platformCursorController.h"
|
||||
#include "forest/editor/forestUndo.h"
|
||||
#include "gui/worldEditor/undoActions.h"
|
||||
#include "scene/sceneContainer.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT( ForestEditorCtrl );
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -48,6 +48,10 @@
|
|||
#include "console/simObject.h"
|
||||
#endif
|
||||
|
||||
#ifndef _SCENEOBJECT_H_
|
||||
#include "scene/sceneObject.h"
|
||||
#endif
|
||||
|
||||
|
||||
/// @file
|
||||
/// SceneObject database.
|
||||
|
|
@ -61,78 +65,307 @@ class Point3F;
|
|||
|
||||
struct RayInfo;
|
||||
|
||||
|
||||
template< typename T >
|
||||
class SceneObjectRefBase
|
||||
inline U32 dCalcBlocks(U32 value, U32 blockSize)
|
||||
{
|
||||
public:
|
||||
U32 curBlock = value / blockSize;
|
||||
U32 nextBlock = curBlock + 1;
|
||||
return nextBlock * blockSize;
|
||||
}
|
||||
|
||||
/// Object that is referenced in the link.
|
||||
SceneObject* object;
|
||||
|
||||
/// Next link in chain of container.
|
||||
T* nextInBin;
|
||||
|
||||
/// Previous link in chain of container.
|
||||
T* prevInBin;
|
||||
|
||||
/// Next link in chain that is associated with #object.
|
||||
T* nextInObj;
|
||||
};
|
||||
|
||||
|
||||
/// Reference to a scene object.
|
||||
class SceneObjectRef : public SceneObjectRefBase< SceneObjectRef > {};
|
||||
|
||||
|
||||
/// A contextual hint passed to the polylist methods which
|
||||
/// allows it to return the appropriate geometry.
|
||||
enum PolyListContext
|
||||
/// Allocates a list of T in blocks of mBlockSize, doesn't shrink unless forced
|
||||
template<typename T> class LazyItemAllocator
|
||||
{
|
||||
/// A hint that the polyist is intended
|
||||
/// for collision testing.
|
||||
PLC_Collision,
|
||||
|
||||
/// A hint that the polyist is for decal
|
||||
/// geometry generation.
|
||||
PLC_Decal,
|
||||
protected:
|
||||
T* mItems;
|
||||
U32 mSize;
|
||||
U32 mBlockSize;
|
||||
|
||||
/// A hint that the polyist is used for
|
||||
/// selection from an editor or other tool.
|
||||
PLC_Selection,
|
||||
public:
|
||||
LazyItemAllocator(U32 blockSize) : mItems(NULL), mSize(0), mBlockSize(blockSize)
|
||||
{
|
||||
}
|
||||
|
||||
/// A hint that the polylist is used for
|
||||
/// building a representation of the environment
|
||||
/// used for navigation.
|
||||
PLC_Navigation,
|
||||
~LazyItemAllocator()
|
||||
{
|
||||
if (mItems)
|
||||
delete mItems;
|
||||
}
|
||||
|
||||
/// A hint that the polyist will be used
|
||||
/// to export geometry and would like to have
|
||||
/// texture coords and materials.
|
||||
PLC_Export
|
||||
};
|
||||
inline bool isNull() const
|
||||
{
|
||||
return mItems == NULL;
|
||||
}
|
||||
|
||||
inline T* getPtr()
|
||||
{
|
||||
return mItems;
|
||||
}
|
||||
|
||||
/// For simple queries. Simply creates a vector of the objects
|
||||
class SimpleQueryList
|
||||
{
|
||||
public:
|
||||
inline bool canFit(U32 count) const
|
||||
{
|
||||
return count < mSize;
|
||||
}
|
||||
|
||||
Vector< SceneObject* > mList;
|
||||
|
||||
SimpleQueryList()
|
||||
void realloc(U32 requiredItems, bool force)
|
||||
{
|
||||
U32 requiredSize = dCalcBlocks(requiredItems, mBlockSize);
|
||||
if (mSize < requiredSize || (force && (mSize != requiredSize)))
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION( mList );
|
||||
if (mItems == NULL)
|
||||
mItems = (T*)dMalloc(sizeof(T) * requiredSize);
|
||||
else
|
||||
dRealloc(mItems, sizeof(T) * requiredSize);
|
||||
|
||||
mSize = requiredSize;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Maintains a set of bin lists for SceneObjects
|
||||
/// Use allocList to allocate a list. freeList frees the list,
|
||||
/// and reallocList handles reallocating an existing list handle.
|
||||
template<typename T> class SceneContainerBinRefList
|
||||
{
|
||||
public:
|
||||
|
||||
/// Index type for a bin reference
|
||||
typedef T BinValue;
|
||||
|
||||
/// Type for number of bins used by a reference list
|
||||
typedef T BinCount;
|
||||
|
||||
/// Handle used for bin lists
|
||||
typedef U32 ListHandle;
|
||||
|
||||
// Defaults
|
||||
enum
|
||||
{
|
||||
/// Chunk size of reference lists
|
||||
ReserveSize = 20000,
|
||||
|
||||
/// Chunk count of reference list entries
|
||||
DataReserveSize = 20000*4,
|
||||
|
||||
/// Number of unused references when compaction should occur
|
||||
CompactionThreshold = 4096
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
#pragma pack(2)
|
||||
struct BinList
|
||||
{
|
||||
// Start reference
|
||||
U32 startValue;
|
||||
|
||||
/// References allocated
|
||||
BinCount numValues;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
/// List of bin lists
|
||||
Vector<BinList> mBinLists;
|
||||
|
||||
/// Current bin values
|
||||
LazyItemAllocator<BinValue> mBinValues;
|
||||
|
||||
/// Temporary compaction list
|
||||
LazyItemAllocator<BinValue> mCompactData;
|
||||
|
||||
/// Offset (+1) of first free mBinLists
|
||||
U32 mFreeListStart;
|
||||
|
||||
/// Chunks of mRefList to allocate
|
||||
U32 mListChunkSize;
|
||||
|
||||
/// Current used ref count (in mBinValues)
|
||||
U32 mUsedValues;
|
||||
|
||||
/// Current reference index we are writing
|
||||
U32 mLastValueIdx;
|
||||
|
||||
public:
|
||||
|
||||
SceneContainerBinRefList() :
|
||||
mBinValues(DataReserveSize),
|
||||
mCompactData(DataReserveSize),
|
||||
mFreeListStart(0),
|
||||
mListChunkSize(ReserveSize),
|
||||
mUsedValues(0),
|
||||
mLastValueIdx(0)
|
||||
{
|
||||
}
|
||||
|
||||
~SceneContainerBinRefList()
|
||||
{
|
||||
}
|
||||
|
||||
/// Resets the SceneContainerBinRefList
|
||||
void clear()
|
||||
{
|
||||
mBinLists.clear();
|
||||
mBinValues.realloc(0, true);
|
||||
mCompactData.realloc(0, true);
|
||||
|
||||
mFreeListStart = 0;
|
||||
mUsedValues = 0;
|
||||
mLastValueIdx = 0;
|
||||
}
|
||||
|
||||
/// Gets a BinValue list based on a ListHandle.
|
||||
BinValue* getValues(ListHandle handle, U32& numValues)
|
||||
{
|
||||
if (handle == 0)
|
||||
{
|
||||
numValues = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void insertObject( SceneObject* obj ) { mList.push_back(obj); }
|
||||
static void insertionCallback( SceneObject* obj, void* key )
|
||||
{
|
||||
SimpleQueryList* pList = reinterpret_cast< SimpleQueryList* >( key );
|
||||
pList->insertObject( obj );
|
||||
}
|
||||
};
|
||||
U32 realIDX = handle - 1;
|
||||
BinList& list = mBinLists[realIDX];
|
||||
numValues = list.numValues;
|
||||
|
||||
return mBinValues.getPtr() + list.startValue;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/// Gets a free entry from the free entry list.
|
||||
bool getFreeEntry(ListHandle& outIDX)
|
||||
{
|
||||
if (mFreeListStart > 0)
|
||||
{
|
||||
outIDX = mFreeListStart - 1;
|
||||
mFreeListStart = mBinLists[outIDX].startValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// Allocates a new ListHandle with numValue values copied from values.
|
||||
ListHandle allocList(BinCount numValues, BinValue* values)
|
||||
{
|
||||
BinList list;
|
||||
ListHandle retHandle = 0;
|
||||
|
||||
list.numValues = numValues;
|
||||
list.startValue = mLastValueIdx;
|
||||
|
||||
mLastValueIdx += numValues;
|
||||
mUsedValues += numValues;
|
||||
|
||||
// Use free list or push new entry
|
||||
if (!getFreeEntry(retHandle))
|
||||
{
|
||||
mBinLists.push_back(list);
|
||||
retHandle = mBinLists.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
mBinLists[retHandle++] = list;
|
||||
}
|
||||
|
||||
// Manage lists
|
||||
mBinLists.reserve(dCalcBlocks(mBinLists.size(), mListChunkSize));
|
||||
mBinValues.realloc(mLastValueIdx, false);
|
||||
|
||||
// Copy data
|
||||
dCopyArray(mBinValues.getPtr() + list.startValue, values, numValues);
|
||||
return retHandle;
|
||||
}
|
||||
|
||||
/// Reallocates an existing ListHandle.
|
||||
/// Existing memory will be used if numValues is the same,
|
||||
/// otherwise new list memory will be allocated.
|
||||
void reallocList(ListHandle handle, BinCount numValues, BinValue* values)
|
||||
{
|
||||
if (handle == 0)
|
||||
return;
|
||||
|
||||
U32 realIDX = handle - 1;
|
||||
BinList& list = mBinLists[realIDX];
|
||||
|
||||
if (list.numValues != numValues)
|
||||
{
|
||||
// Allocate new entry
|
||||
mUsedValues -= list.numValues;
|
||||
mUsedValues += numValues;
|
||||
|
||||
list.numValues = numValues;
|
||||
list.startValue = mLastValueIdx;
|
||||
|
||||
mLastValueIdx += numValues;
|
||||
mBinValues.realloc(mLastValueIdx, false);
|
||||
}
|
||||
|
||||
dCopyArray(mBinValues.getPtr() + list.startValue, values, numValues);
|
||||
}
|
||||
|
||||
/// Frees an existing ListHandle
|
||||
void freeList(ListHandle handle)
|
||||
{
|
||||
if (handle == 0)
|
||||
return;
|
||||
|
||||
U32 realIDX = handle - 1;
|
||||
BinList& list = mBinLists[realIDX];
|
||||
|
||||
mUsedValues -= list.numValues;
|
||||
list.numValues = 0;
|
||||
|
||||
// Add to free list
|
||||
list.startValue = mFreeListStart;
|
||||
// Next
|
||||
mFreeListStart = handle;
|
||||
|
||||
AssertFatal(mLastValueIdx >= mUsedValues, "ref overflow");
|
||||
|
||||
// Automatically compact if we have enough free items
|
||||
if ((mLastValueIdx - mUsedValues) > CompactionThreshold)
|
||||
{
|
||||
compact();
|
||||
}
|
||||
}
|
||||
|
||||
/// Compacts the BinValue lists.
|
||||
/// This will automatically be called by freeList usually
|
||||
/// once CompactionThreshold list values have been freed.
|
||||
void compact()
|
||||
{
|
||||
if (mBinValues.isNull())
|
||||
return;
|
||||
|
||||
mCompactData.realloc(mUsedValues, false);
|
||||
BinValue* outPtr = mCompactData.getPtr();
|
||||
U32 newOutStart = 0;
|
||||
|
||||
// Copy list values to scratch list
|
||||
for (BinList& list : mBinLists)
|
||||
{
|
||||
if (list.numValues == 0)
|
||||
continue;
|
||||
|
||||
const BinValue* inPtr = mBinValues.getPtr() + list.startValue;
|
||||
dCopyArray(outPtr, inPtr, list.numValues);
|
||||
|
||||
// Update counters
|
||||
list.startValue = newOutStart;
|
||||
outPtr += list.numValues;
|
||||
newOutStart += list.numValues;
|
||||
}
|
||||
|
||||
AssertFatal(newOutStart == mUsedValues, "value count mismatch");
|
||||
|
||||
mLastValueIdx = mUsedValues;
|
||||
mBinValues.realloc(mLastValueIdx, true);
|
||||
|
||||
const U32 copySize = newOutStart * sizeof(BinValue);
|
||||
memcpy(mBinValues.getPtr(), mCompactData.getPtr(), copySize);
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -141,6 +374,7 @@ class SimpleQueryList
|
|||
/// ScenceContainer implements a grid-based spatial subdivision for the contents of a scene.
|
||||
class SceneContainer
|
||||
{
|
||||
public:
|
||||
enum CastRayType
|
||||
{
|
||||
CollisionGeometry,
|
||||
|
|
@ -149,14 +383,16 @@ class SceneContainer
|
|||
|
||||
public:
|
||||
|
||||
struct Link
|
||||
{
|
||||
Link* mNext;
|
||||
Link* mPrev;
|
||||
Link();
|
||||
void unlink();
|
||||
void linkAfter(Link* ptr);
|
||||
};
|
||||
typedef SceneContainerBinRefList<U16> BinValueList;
|
||||
|
||||
/// Base object list type, should conform to Vector
|
||||
typedef Vector<SceneObject*> ObjectList;
|
||||
|
||||
/// Type to reference a bin list
|
||||
typedef U32 BinListIndex;
|
||||
|
||||
/// Type to reference a bin. This should be changed if there are more than 65536 bins.
|
||||
typedef U16 BinRef;
|
||||
|
||||
struct CallbackInfo
|
||||
{
|
||||
|
|
@ -169,9 +405,6 @@ class SceneContainer
|
|||
|
||||
private:
|
||||
|
||||
Link mStart;
|
||||
Link mEnd;
|
||||
|
||||
/// Container queries based on #mCurrSeqKey are are not re-entrant;
|
||||
/// this is used to detect when it happens.
|
||||
bool mSearchInProgress;
|
||||
|
|
@ -179,23 +412,40 @@ class SceneContainer
|
|||
/// Current sequence key.
|
||||
U32 mCurrSeqKey;
|
||||
|
||||
SceneObjectRef* mFreeRefPool;
|
||||
Vector< SceneObjectRef* > mRefPoolBlocks;
|
||||
/// Binned object lists
|
||||
ObjectList* mBinArray;
|
||||
|
||||
SceneObjectRef* mBinArray;
|
||||
SceneObjectRef mOverflowBin;
|
||||
/// Large objects
|
||||
ObjectList mOverflowBin;
|
||||
|
||||
/// Every single object not categorized by bin
|
||||
ObjectList mGlobalList;
|
||||
|
||||
/// A vector that contains just the water and physical zone
|
||||
/// object types which is used to optimize searches.
|
||||
Vector< SceneObject* > mWaterAndZones;
|
||||
ObjectList mWaterAndZones;
|
||||
|
||||
/// Vector that contains just the terrain objects in the container.
|
||||
Vector< SceneObject* > mTerrains;
|
||||
ObjectList mTerrains;
|
||||
|
||||
static const U32 csmNumBins;
|
||||
/// Temporary list for value insert
|
||||
Vector<BinValueList::BinValue> mBinValueList;
|
||||
|
||||
/// Maintains a list of bin references
|
||||
BinValueList mBinRefLists;
|
||||
|
||||
public:
|
||||
/// World units of side of bin
|
||||
static const F32 csmBinSize;
|
||||
static const F32 csmTotalBinSize;
|
||||
static const U32 csmRefPoolBlockSize;
|
||||
/// World units of entire side of bin grid
|
||||
static const F32 csmTotalAxisBinSize;
|
||||
|
||||
/// Size of grid on any axis
|
||||
static const U32 csmNumAxisBins;
|
||||
/// Index used to store overflow entries
|
||||
static const U32 csmOverflowBinIdx;
|
||||
/// Total number of bin lists to allocate
|
||||
static const U32 csmTotalNumBins;
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -273,9 +523,6 @@ class SceneContainer
|
|||
/// @param object A SceneObject.
|
||||
bool removeObject( SceneObject* object );
|
||||
|
||||
void addRefPoolBlock();
|
||||
SceneObjectRef* allocateObjectRef();
|
||||
void freeObjectRef(SceneObjectRef*);
|
||||
void insertIntoBins( SceneObject* object );
|
||||
void removeFromBins( SceneObject* object );
|
||||
|
||||
|
|
@ -283,7 +530,7 @@ class SceneContainer
|
|||
/// where it came from. The overloaded insertInto is so we don't calculate
|
||||
/// the ranges twice.
|
||||
void checkBins( SceneObject* object );
|
||||
void insertIntoBins(SceneObject*, U32, U32, U32, U32);
|
||||
void insertIntoBins(SceneObject*, const SceneBinRange& range);
|
||||
|
||||
void initRadiusSearch(const Point3F& searchPoint,
|
||||
const F32 searchRadius,
|
||||
|
|
@ -308,40 +555,38 @@ class SceneContainer
|
|||
void _findSpecialObjects( const Vector< SceneObject* >& vector, U32 mask, FindCallback, void *key = NULL );
|
||||
void _findSpecialObjects( const Vector< SceneObject* >& vector, const Box3F &box, U32 mask, FindCallback callback, void *key = NULL );
|
||||
|
||||
|
||||
public:
|
||||
|
||||
static inline void getBinRange( const Point2F minExtents, const Point2F maxExtents, SceneBinRange& outRange )
|
||||
{
|
||||
U32 outMin, outMax;
|
||||
getBinRange(minExtents.x, maxExtents.x, outMin, outMax);
|
||||
outRange.minCoord[0] = outMin;
|
||||
outRange.maxCoord[0] = outMax;
|
||||
getBinRange(minExtents.y, maxExtents.y, outMin, outMax);
|
||||
outRange.minCoord[1] = outMin;
|
||||
outRange.maxCoord[1] = outMax;
|
||||
}
|
||||
|
||||
static void getBinRange( const F32 min, const F32 max, U32& minBin, U32& maxBin );
|
||||
public:
|
||||
Vector<SimObjectPtr<SceneObject>*>& getRadiusSearchList() { return mSearchList; }
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool SceneBinRange::shouldOverflow() const
|
||||
{
|
||||
return
|
||||
((getWidth() + 1) >= SceneContainer::csmNumAxisBins ||
|
||||
((getHeight() + 1) >= SceneContainer::csmNumAxisBins));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
extern SceneContainer gServerContainer;
|
||||
extern SceneContainer gClientContainer;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void SceneContainer::freeObjectRef(SceneObjectRef* trash)
|
||||
{
|
||||
trash->object = NULL;
|
||||
trash->nextInBin = NULL;
|
||||
trash->prevInBin = NULL;
|
||||
trash->nextInObj = mFreeRefPool;
|
||||
mFreeRefPool = trash;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline SceneObjectRef* SceneContainer::allocateObjectRef()
|
||||
{
|
||||
if( mFreeRefPool == NULL )
|
||||
addRefPoolBlock();
|
||||
AssertFatal( mFreeRefPool!=NULL, "Error, should always have a free reference here!" );
|
||||
|
||||
SceneObjectRef* ret = mFreeRefPool;
|
||||
mFreeRefPool = mFreeRefPool->nextInObj;
|
||||
|
||||
ret->nextInObj = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // !_SCENECONTAINER_H_
|
||||
#endif // !_SCENECONTAINER_H_
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@
|
|||
#include "core/util/tSignal.h"
|
||||
#endif
|
||||
|
||||
#ifndef _SCENECONTAINER_H_
|
||||
#include "scene/sceneContainer.h"
|
||||
#endif
|
||||
|
||||
|
||||
class LightManager;
|
||||
class SceneRootZone;
|
||||
|
|
|
|||
|
|
@ -126,18 +126,12 @@ SceneObject::SceneObject()
|
|||
|
||||
mContainerSeqKey = 0;
|
||||
|
||||
mBinRefHead = NULL;
|
||||
|
||||
mSceneManager = NULL;
|
||||
|
||||
mNumCurrZones = 0;
|
||||
mZoneRefHead = NULL;
|
||||
mZoneRefDirty = false;
|
||||
|
||||
mBinMinX = 0xFFFFFFFF;
|
||||
mBinMaxX = 0xFFFFFFFF;
|
||||
mBinMinY = 0xFFFFFFFF;
|
||||
mBinMaxY = 0xFFFFFFFF;
|
||||
mLightPlugin = NULL;
|
||||
|
||||
mMount.object = NULL;
|
||||
|
|
@ -172,13 +166,14 @@ SceneObject::SceneObject()
|
|||
|
||||
SceneObject::~SceneObject()
|
||||
{
|
||||
AssertFatal( mZoneRefHead == NULL && mBinRefHead == NULL,
|
||||
AssertFatal(mContainer == NULL,
|
||||
"SceneObject::~SceneObject - Object still in container!");
|
||||
AssertFatal( mZoneRefHead == NULL,
|
||||
"SceneObject::~SceneObject - Object still linked in reference lists!");
|
||||
AssertFatal( !mSceneObjectLinks,
|
||||
"SceneObject::~SceneObject() - object is still linked to SceneTrackers" );
|
||||
|
||||
mAccuTex = NULL;
|
||||
unlink();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -52,10 +52,6 @@
|
|||
#include "T3D/gameBase/processList.h"
|
||||
#endif
|
||||
|
||||
#ifndef _SCENECONTAINER_H_
|
||||
#include "scene/sceneContainer.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXDEVICE_H_
|
||||
#include "gfx/gfxDevice.h"
|
||||
#endif
|
||||
|
|
@ -74,6 +70,11 @@
|
|||
#include "T3D/assets/GameObjectAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _SCENEQUERY_UTIL_H_
|
||||
#include "scene/sceneQueryUtil.h"
|
||||
#endif
|
||||
|
||||
|
||||
class SceneManager;
|
||||
class SceneRenderState;
|
||||
class SceneTraversalState;
|
||||
|
|
@ -87,7 +88,7 @@ class SFXAmbience;
|
|||
|
||||
struct ObjectRenderInst;
|
||||
struct Move;
|
||||
|
||||
struct SceneRayHelper;
|
||||
|
||||
/// A 3D object.
|
||||
///
|
||||
|
|
@ -112,7 +113,7 @@ struct Move;
|
|||
///
|
||||
/// @see http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=3217
|
||||
/// for a copy of Melv's example.
|
||||
class SceneObject : public NetObject, private SceneContainer::Link, public ProcessObject
|
||||
class SceneObject : public NetObject, public ProcessObject
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
@ -123,6 +124,7 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
|
|||
friend class SceneZoneSpaceManager;
|
||||
friend class SceneCullingState; // _getZoneRefHead
|
||||
friend class SceneObjectLink; // mSceneObjectLinks
|
||||
friend struct SceneRayHelper;
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -223,10 +225,22 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
|
|||
/// @{
|
||||
|
||||
/// Bidirectional link between a zone manager and its objects.
|
||||
struct ZoneRef : public SceneObjectRefBase< ZoneRef >
|
||||
struct ZoneRef
|
||||
{
|
||||
/// ID of zone.
|
||||
U32 zone;
|
||||
|
||||
/// Object that is referenced in the link.
|
||||
SceneObject* object;
|
||||
|
||||
/// Next link in chain of container.
|
||||
ZoneRef* nextInBin;
|
||||
|
||||
/// Previous link in chain of container.
|
||||
ZoneRef* prevInBin;
|
||||
|
||||
/// Next link in chain that is associated with #object.
|
||||
ZoneRef* nextInObj;
|
||||
};
|
||||
|
||||
/// Iterator over the zones that the object is assigned to.
|
||||
|
|
@ -360,17 +374,15 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
|
|||
/// Container database that the object is assigned to.
|
||||
SceneContainer* mContainer;
|
||||
|
||||
/// Assigned container index
|
||||
U32 mContainerIndex;
|
||||
|
||||
/// Lookup Info
|
||||
SceneBinListLookup mContainerLookup;
|
||||
|
||||
/// SceneContainer sequence key.
|
||||
U32 mContainerSeqKey;
|
||||
|
||||
///
|
||||
SceneObjectRef* mBinRefHead;
|
||||
|
||||
U32 mBinMinX;
|
||||
U32 mBinMaxX;
|
||||
U32 mBinMinY;
|
||||
U32 mBinMaxY;
|
||||
|
||||
/// Returns the container sequence key.
|
||||
U32 getContainerSeqKey() const { return mContainerSeqKey; }
|
||||
|
||||
|
|
@ -464,7 +476,7 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
|
|||
virtual void enableCollision();
|
||||
|
||||
/// Returns true if collisions are enabled
|
||||
bool isCollisionEnabled() const { return mCollisionCount == 0; }
|
||||
inline bool isCollisionEnabled() const { return mCollisionCount == 0; }
|
||||
|
||||
/// This gets called when an object collides with this object.
|
||||
/// @param object Object colliding with this object
|
||||
|
|
|
|||
115
Engine/source/scene/sceneQueryUtil.h
Normal file
115
Engine/source/scene/sceneQueryUtil.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#ifndef _SCENEQUERY_UTIL_H_
|
||||
#define _SCENEQUERY_UTIL_H_
|
||||
|
||||
/// A contextual hint passed to the polylist methods which
|
||||
/// allows it to return the appropriate geometry.
|
||||
enum PolyListContext
|
||||
{
|
||||
/// A hint that the polyist is intended
|
||||
/// for collision testing.
|
||||
PLC_Collision,
|
||||
|
||||
/// A hint that the polyist is for decal
|
||||
/// geometry generation.
|
||||
PLC_Decal,
|
||||
|
||||
/// A hint that the polyist is used for
|
||||
/// selection from an editor or other tool.
|
||||
PLC_Selection,
|
||||
|
||||
/// A hint that the polylist is used for
|
||||
/// building a representation of the environment
|
||||
/// used for navigation.
|
||||
PLC_Navigation,
|
||||
|
||||
/// A hint that the polyist will be used
|
||||
/// to export geometry and would like to have
|
||||
/// texture coords and materials.
|
||||
PLC_Export
|
||||
};
|
||||
|
||||
struct SceneBinRange
|
||||
{
|
||||
U16 minCoord[2];
|
||||
U16 maxCoord[2];
|
||||
|
||||
inline U32 getWidth() const
|
||||
{
|
||||
return maxCoord[0] - minCoord[0];
|
||||
}
|
||||
|
||||
inline U32 getHeight() const
|
||||
{
|
||||
return maxCoord[1] - minCoord[1];
|
||||
}
|
||||
|
||||
inline void setGlobal()
|
||||
{
|
||||
minCoord[0] = 0;
|
||||
minCoord[1] = 0;
|
||||
maxCoord[0] = 0xFFFF;
|
||||
maxCoord[1] = 0xFFFF;
|
||||
}
|
||||
|
||||
static SceneBinRange makeFromBin(U32 minX, U32 maxX, U32 minY, U32 maxY)
|
||||
{
|
||||
SceneBinRange outRange;
|
||||
outRange.minCoord[0] = minX;
|
||||
outRange.minCoord[1] = minY;
|
||||
outRange.maxCoord[0] = maxX;
|
||||
outRange.maxCoord[1] = maxY;
|
||||
return outRange;
|
||||
}
|
||||
|
||||
static SceneBinRange makeGlobal()
|
||||
{
|
||||
SceneBinRange outRange;
|
||||
outRange.setGlobal();
|
||||
return outRange;
|
||||
}
|
||||
|
||||
inline bool isGlobal() const
|
||||
{
|
||||
return minCoord[0] == 0 &&
|
||||
minCoord[0] == 0 &&
|
||||
maxCoord[0] == 0xFFFF &&
|
||||
maxCoord[1] == 0xFFFF;
|
||||
}
|
||||
|
||||
inline bool shouldOverflow() const;
|
||||
|
||||
inline bool operator==(const SceneBinRange& other) const
|
||||
{
|
||||
return memcmp(minCoord, other.minCoord, sizeof(minCoord)) == 0 &&
|
||||
memcmp(maxCoord, other.maxCoord, sizeof(maxCoord)) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// Lookup for bins assigned to SceneObject
|
||||
struct SceneBinListLookup
|
||||
{
|
||||
SceneBinRange mRange; ///< Range object is placed in
|
||||
U32 mListHandle; ///< Handle for ref list
|
||||
};
|
||||
|
||||
/// For simple queries. Simply creates a vector of the objects
|
||||
class SimpleQueryList
|
||||
{
|
||||
public:
|
||||
|
||||
Vector< SceneObject* > mList;
|
||||
|
||||
SimpleQueryList()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mList);
|
||||
}
|
||||
|
||||
void insertObject(SceneObject* obj) { mList.push_back(obj); }
|
||||
static void insertionCallback(SceneObject* obj, void* key)
|
||||
{
|
||||
SimpleQueryList* pList = reinterpret_cast<SimpleQueryList*>(key);
|
||||
pList->insertObject(obj);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "scene/sceneTracker.h"
|
||||
#include "scene/sceneContainer.h"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@
|
|||
|
||||
#include "platform/profiler.h"
|
||||
#include "platform/platformMemory.h"
|
||||
#include "scene/sceneContainer.h"
|
||||
#include "scene/zones/sceneRootZone.h"
|
||||
#include "scene/zones/sceneZoneSpace.h"
|
||||
#include "scene/sceneContainer.h"
|
||||
|
||||
|
||||
// Uncomment to enable verification code for debugging. This slows the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue