mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
226 lines
6.8 KiB
C
226 lines
6.8 KiB
C
|
|
//-----------------------------------------------------------------------------
|
||
|
|
// Copyright (c) 2012 GarageGames, LLC
|
||
|
|
//
|
||
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
|
// of this software and associated documentation files (the "Software"), to
|
||
|
|
// deal in the Software without restriction, including without limitation the
|
||
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||
|
|
// furnished to do so, subject to the following conditions:
|
||
|
|
//
|
||
|
|
// The above copyright notice and this permission notice shall be included in
|
||
|
|
// all copies or substantial portions of the Software.
|
||
|
|
//
|
||
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||
|
|
// IN THE SOFTWARE.
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
#ifndef _FORESTCELL_H_
|
||
|
|
#define _FORESTCELL_H_
|
||
|
|
|
||
|
|
#ifndef _FORESTITEM_H_
|
||
|
|
#include "forest/forestItem.h"
|
||
|
|
#endif
|
||
|
|
#ifndef _H_FOREST_
|
||
|
|
#include "forest/forest.h"
|
||
|
|
#endif
|
||
|
|
#ifndef _BITVECTOR_H_
|
||
|
|
#include "core/bitVector.h"
|
||
|
|
#endif
|
||
|
|
|
||
|
|
class ForestCellBatch;
|
||
|
|
class SceneRenderState;
|
||
|
|
class Frustum;
|
||
|
|
class IForestCellCollision;
|
||
|
|
class PhysicsBody;
|
||
|
|
//class ForestRayInfo;
|
||
|
|
|
||
|
|
|
||
|
|
///
|
||
|
|
class ForestCell
|
||
|
|
{
|
||
|
|
friend class Forest;
|
||
|
|
|
||
|
|
protected:
|
||
|
|
|
||
|
|
/// The area which this cell represents in the world.
|
||
|
|
RectF mRect;
|
||
|
|
|
||
|
|
/// If items have been added or removed the dirty flag
|
||
|
|
/// is set so that the bounds can be rebuilt on the next
|
||
|
|
/// request.
|
||
|
|
bool mIsDirty;
|
||
|
|
|
||
|
|
/// The combined bounding box of all the items
|
||
|
|
/// in or children of this cell.
|
||
|
|
Box3F mBounds;
|
||
|
|
|
||
|
|
/// All the items in this cell.
|
||
|
|
Vector<ForestItem> mItems;
|
||
|
|
|
||
|
|
/// A vector of the current batches
|
||
|
|
/// associated with this cell.
|
||
|
|
Vector<ForestCellBatch*> mBatches;
|
||
|
|
|
||
|
|
/// The largest item in this cell.
|
||
|
|
ForestItem mLargestItem;
|
||
|
|
|
||
|
|
/// PhysicsBody for client and server for all trees in this ForestCell,
|
||
|
|
/// if it is a leaf cell.
|
||
|
|
PhysicsBody *mPhysicsRep[2];
|
||
|
|
|
||
|
|
/// The quad tree cells below this one which
|
||
|
|
/// may contain sub elements.
|
||
|
|
ForestCell* mSubCells[4];
|
||
|
|
|
||
|
|
/// The zone overlap for this cell.
|
||
|
|
/// @note The bit for the outdoor zone is never set.
|
||
|
|
BitVector mZoneOverlap;
|
||
|
|
|
||
|
|
/// Whether this cell is fully contained inside interior zones.
|
||
|
|
bool mIsInteriorOnly;
|
||
|
|
|
||
|
|
///
|
||
|
|
inline U32 _getSubCell( F32 x, F32 y ) const
|
||
|
|
{
|
||
|
|
bool left = x < ( mRect.point.x + ( mRect.extent.x / 2.0f ) );
|
||
|
|
bool top = y < ( mRect.point.y + ( mRect.extent.y / 2.0f ) );
|
||
|
|
|
||
|
|
if ( left && top ) return 0;
|
||
|
|
if ( left && !top ) return 1;
|
||
|
|
if ( !left && top ) return 2;
|
||
|
|
|
||
|
|
return 3;
|
||
|
|
}
|
||
|
|
|
||
|
|
///
|
||
|
|
inline RectF _makeChildRect( U32 index ) const
|
||
|
|
{
|
||
|
|
RectF rect( mRect.point, mRect.extent / 2.0f );
|
||
|
|
|
||
|
|
if ( index == 1 || index == 3 )
|
||
|
|
rect.point.y += rect.extent.y;
|
||
|
|
|
||
|
|
if ( index > 1 )
|
||
|
|
rect.point.x += rect.extent.x;
|
||
|
|
|
||
|
|
return rect;
|
||
|
|
}
|
||
|
|
|
||
|
|
void _updateBounds();
|
||
|
|
|
||
|
|
///
|
||
|
|
void _updateZoning( const SceneZoneSpaceManager *zoneManager );
|
||
|
|
|
||
|
|
public:
|
||
|
|
|
||
|
|
/// The maximum amount of objects allowed in a
|
||
|
|
/// cell before we repartition it.
|
||
|
|
static const U32 MaxItems = 200;
|
||
|
|
|
||
|
|
ForestCell( const RectF &rect );
|
||
|
|
virtual ~ForestCell();
|
||
|
|
|
||
|
|
/// Returns the 2D rectangle of quad tree bounds for this
|
||
|
|
/// cell. It is fixed and does not change during runtime.
|
||
|
|
const RectF& getRect() const { return mRect; }
|
||
|
|
|
||
|
|
/// The bounds of the cell generated by combining the
|
||
|
|
/// bounds of all the contained items or child cells.
|
||
|
|
const Box3F& getBounds() const;
|
||
|
|
|
||
|
|
/// Set flag so this cells bounds will be recalculated the next call to getBounds.
|
||
|
|
void invalidateBounds() { mIsDirty = true; }
|
||
|
|
|
||
|
|
/// Returns true if this cell has no items and no child cells.
|
||
|
|
bool isEmpty() const { return isLeaf() && mItems.empty(); }
|
||
|
|
|
||
|
|
/// Returns true if this cell does not have child cells.
|
||
|
|
/// It should directly contain items.
|
||
|
|
bool isLeaf() const { return !mSubCells[0]; }
|
||
|
|
|
||
|
|
/// Returns true if this cell has child cells.
|
||
|
|
/// This is the same as !isLeaf() but exists for clarity.
|
||
|
|
bool isBranch() const { return mSubCells[0] != NULL; }
|
||
|
|
|
||
|
|
/// Returns a bit vector of what zones overlap this cell.
|
||
|
|
const BitVector& getZoneOverlap() const { return mZoneOverlap; }
|
||
|
|
|
||
|
|
///
|
||
|
|
bool castRay( const Point3F &start, const Point3F &end, RayInfo *outInfo, bool rendered ) const;
|
||
|
|
|
||
|
|
bool hasBatches() const { return !mBatches.empty(); }
|
||
|
|
|
||
|
|
void buildBatches();
|
||
|
|
|
||
|
|
void freeBatches();
|
||
|
|
|
||
|
|
S32 renderBatches( SceneRenderState *state, Frustum *culler );
|
||
|
|
|
||
|
|
|
||
|
|
S32 render( TSRenderState *rdata, const Frustum *culler );
|
||
|
|
|
||
|
|
|
||
|
|
/// The find function does a binary search thru the sorted
|
||
|
|
/// item list. If the key is found then the index is the
|
||
|
|
/// position of the item. If the key is not found the index
|
||
|
|
/// is the correct insertion position for adding the new item.
|
||
|
|
///
|
||
|
|
/// @param key The item key to search for.
|
||
|
|
///
|
||
|
|
/// @param outIndex The item index or insertion index if
|
||
|
|
/// the item was not found.
|
||
|
|
///
|
||
|
|
/// @return Returns true if the item index is found.
|
||
|
|
///
|
||
|
|
bool findIndexByKey( ForestItemKey key, U32 *outIndex ) const;
|
||
|
|
|
||
|
|
const ForestItem& getLargestItem() const { return mLargestItem; }
|
||
|
|
|
||
|
|
const ForestItem& insertItem( ForestItemKey key,
|
||
|
|
ForestItemData *data,
|
||
|
|
const MatrixF &xfm,
|
||
|
|
F32 scale );
|
||
|
|
|
||
|
|
bool removeItem( ForestItemKey key, const Point3F &keyPos, bool deleteIfEmpty = false );
|
||
|
|
|
||
|
|
/// Returns the child cell at the position. The position is
|
||
|
|
/// assumed to be within this cell.
|
||
|
|
ForestCell* getChildAt( const Point3F &pos ) const;
|
||
|
|
|
||
|
|
/// Returns the child cells.
|
||
|
|
void getChildren( Vector<ForestCell*> *outCells ) const { outCells->merge( mSubCells, 4 ); }
|
||
|
|
void getChildren( Vector<const ForestCell*> *outCells ) const { outCells->merge( mSubCells, 4 ); }
|
||
|
|
|
||
|
|
/// Returns the items from this one cell.
|
||
|
|
const Vector<ForestItem>& getItems() const { return mItems; }
|
||
|
|
|
||
|
|
/// Returns the items from this cell and all its sub-cells.
|
||
|
|
void getItems( Vector<ForestItem> *outItems ) const;
|
||
|
|
|
||
|
|
void clearPhysicsRep( Forest *forest );
|
||
|
|
void buildPhysicsRep( Forest *forest );
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
inline const Box3F& ForestCell::getBounds() const
|
||
|
|
{
|
||
|
|
if ( mIsDirty )
|
||
|
|
const_cast<ForestCell*>( this )->_updateBounds();
|
||
|
|
|
||
|
|
return mBounds;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline ForestCell* ForestCell::getChildAt( const Point3F &pos ) const
|
||
|
|
{
|
||
|
|
U32 index = _getSubCell( pos.x, pos.y );
|
||
|
|
return mSubCells[index];
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif // _FORESTCELL_H_
|