#pragma once #include #include #include "v8datamodel/PartInstance.h" #include "v8world/Primitive.h" #include "Util.h" namespace RBX { namespace Graphics { struct SpatialGridIndex { enum Flags { fLarge = 1 << 0, fFW = 1 << 1 }; Vector3int16 position; unsigned short flags; SpatialGridIndex(): position(0, 0, 0), flags(0) { } SpatialGridIndex(const Vector3int16& position, unsigned short flags): position(position), flags(flags) { } }; inline bool operator==(const SpatialGridIndex& lhs, const SpatialGridIndex& rhs) { return lhs.position == rhs.position && lhs.flags == rhs.flags; } inline bool operator!=(const SpatialGridIndex& lhs, const SpatialGridIndex& rhs) { return lhs.position != rhs.position || lhs.flags != rhs.flags; } inline size_t hash_value(const SpatialGridIndex& value) { size_t result = 0; boost::hash_combine(result, value.position.x); boost::hash_combine(result, value.position.y); boost::hash_combine(result, value.position.z); boost::hash_combine(result, value.flags); return result; } template class SpatialGrid { public: struct Cell { Cluster* cluster; }; SpatialGrid(const Vector3& cellExtents, float largeCoeff) : mInvCellExtents(Vector3::one() / cellExtents) , mCellExtentsLarge(cellExtents * largeCoeff) { } ~SpatialGrid() { for (typename SpatialMap::iterator it = mMap.begin(); it != mMap.end(); ++it) delete it->second.cluster; } Cell* requestCell(const SpatialGridIndex& index) { return &mMap[index]; } size_t removeCell(const SpatialGridIndex& index) { return mMap.erase(index); } const Cell* getCell(const SpatialGridIndex& index) const { typename SpatialMap::const_iterator it = mMap.find(index); return (it != mMap.end()) ? &it->second : NULL; } SpatialGridIndex getIndexUnsafe(RBX::PartInstance* part, unsigned short flags) const { Primitive* prim = part->getPartPrimitive(); const Vector3& center = prim->getCoordinateFrameUnsafe().translation; // This never was safe const Vector3& size = prim->getSize(); Vector3int16 gridPos = fastFloorInt(center * mInvCellExtents); bool large = size.x >= mCellExtentsLarge.x || size.y >= mCellExtentsLarge.y || size.z >= mCellExtentsLarge.z; return SpatialGridIndex(gridPos, flags | (large ? SpatialGridIndex::fLarge : 0)); } std::vector getClusters() const { std::vector result; for (typename SpatialMap::const_iterator it = mMap.begin(); it != mMap.end(); ++it) result.push_back(it->second.cluster); return result; } private: typedef boost::unordered_map, std::equal_to, boost::fast_pool_allocator > SpatialMap; SpatialMap mMap; Vector3 mInvCellExtents; Vector3 mCellExtentsLarge; }; } }