/** * @file llspatialpartition.h * @brief LLSpatialGroup header file including definitions for supporting functions * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LL_LLSPATIALPARTITION_H #define LL_LLSPATIALPARTITION_H #define SG_MIN_DIST_RATIO 0.00001f #include "lldrawable.h" #include "lloctree.h" #include "llpointer.h" #include "llrefcount.h" #include "llvertexbuffer.h" #include "llgltypes.h" #include "llcubemap.h" #include "lldrawpool.h" #include "llface.h" #include "llviewercamera.h" #include "llvector4a.h" #include "llvoavatar.h" #include "llfetchedgltfmaterial.h" #include <queue> #include <unordered_map> #define SG_STATE_INHERIT_MASK (OCCLUDED) #define SG_INITIAL_STATE_MASK (static_cast<U32>(DIRTY) | static_cast<U32>(GEOM_DIRTY)) class LLViewerOctreePartition; class LLSpatialPartition; class LLSpatialBridge; class LLSpatialGroup; class LLViewerRegion; class LLReflectionMap; void pushVerts(LLFace* face); /* Class that represents a single Draw Call Make every effort to keep size minimal. Member ordering is important for cache coherency */ class LLDrawInfo final : public LLRefCount { LL_ALIGN_NEW; protected: ~LLDrawInfo(); public: LLDrawInfo(const LLDrawInfo& rhs) { *this = rhs; } const LLDrawInfo& operator=(const LLDrawInfo& rhs) { LL_ERRS() << "Illegal operation!" << LL_ENDL; return *this; } // return a hash of this LLDrawInfo as a debug color LLColor4U getDebugColor() const; LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, LLViewerTexture* image, LLVertexBuffer* buffer, bool fullbright = false, U8 bump = 0); void validate(); // return mSkinHash->mHash, or 0 if mSkinHash is null U64 getSkinHash(); LLPointer<LLVertexBuffer> mVertexBuffer; U16 mStart = 0; U16 mEnd = 0; U32 mCount = 0; U32 mOffset = 0; LLPointer<LLViewerTexture> mTexture; LLPointer<LLViewerTexture> mSpecularMap; LLPointer<LLViewerTexture> mNormalMap; const LLMatrix4* mSpecularMapMatrix = nullptr; const LLMatrix4* mNormalMapMatrix = nullptr; const LLMatrix4* mTextureMatrix = nullptr; const LLMatrix4* mModelMatrix = nullptr; LLPointer<LLVOAvatar> mAvatar = nullptr; LLMeshSkinInfo* mSkinInfo = nullptr; // Material pointer here is likely for debugging only and are immaterial (zing!) LLPointer<LLMaterial> mMaterial; // PBR material parameters LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial; LLVector4 mSpecColor = LLVector4(1.f, 1.f, 1.f, 0.5f); // XYZ = Specular RGB, W = Specular Exponent std::vector<LLPointer<LLViewerTexture> > mTextureList; LLUUID mMaterialID; // id of LLGLTFMaterial or LLMaterial applied to this draw info U32 mShaderMask = 0; F32 mEnvIntensity = 0.f; F32 mAlphaMaskCutoff = 0.5f; LLRender::eBlendFactor mBlendFuncSrc = LLRender::BF_SOURCE_ALPHA; LLRender::eBlendFactor mBlendFuncDst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; U8 mDiffuseAlphaMode = 0; U8 mBump = 0; U8 mShiny = 0; bool mFullbright = false; bool mHasGlow = false; struct CompareTexture { bool operator()(const LLDrawInfo& lhs, const LLDrawInfo& rhs) { return lhs.mTexture > rhs.mTexture; } }; struct CompareTexturePtr { //sort by texture bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) { // sort by pointer, sort NULL down to the end return lhs.get() != rhs.get() && (lhs.isNull() || (rhs.notNull() && lhs->mTexture.get() > rhs->mTexture.get())); } }; struct CompareVertexBuffer { //sort by texture bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) { // sort by pointer, sort NULL down to the end return lhs.get() != rhs.get() && (lhs.isNull() || (rhs.notNull() && lhs->mVertexBuffer.get() > rhs->mVertexBuffer.get())); } }; struct CompareTexturePtrMatrix { bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) { return lhs.get() != rhs.get() && (lhs.isNull() || (rhs.notNull() && (lhs->mTexture.get() > rhs->mTexture.get() || (lhs->mTexture.get() == rhs->mTexture.get() && lhs->mModelMatrix > rhs->mModelMatrix)))); } }; struct CompareMatrixTexturePtr { bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) { return lhs.get() != rhs.get() && (lhs.isNull() || (rhs.notNull() && (lhs->mModelMatrix > rhs->mModelMatrix || (lhs->mModelMatrix == rhs->mModelMatrix && lhs->mTexture.get() > rhs->mTexture.get())))); } }; struct CompareBump { bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) { // sort by mBump value, sort NULL down to the end return lhs.get() != rhs.get() && (lhs.isNull() || (rhs.notNull() && lhs->mBump > rhs->mBump)); } }; }; LL_ALIGN_PREFIX(16) class LLSpatialGroup : public LLOcclusionCullingGroup { using super = LLOcclusionCullingGroup; friend class LLSpatialPartition; friend class LLOctreeStateCheck; public: LLSpatialGroup(const LLSpatialGroup& rhs) : LLOcclusionCullingGroup(rhs) { *this = rhs; } const LLSpatialGroup& operator=(const LLSpatialGroup& rhs) { LL_ERRS() << "Illegal operation!" << LL_ENDL; return *this; } static U32 sNodeCount; static bool sNoDelete; //deletion of spatial groups and draw info not allowed if true typedef std::vector<LLPointer<LLSpatialGroup> > sg_vector_t; typedef std::vector<LLPointer<LLSpatialBridge> > bridge_list_t; typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t; typedef std::unordered_map<U32, drawmap_elem_t > draw_map_t; typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t; typedef std::unordered_map<LLFace*, buffer_list_t> buffer_texture_map_t; typedef std::unordered_map<U32, buffer_texture_map_t> buffer_map_t; struct CompareDistanceGreater { bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs) { return lhs->mDistance > rhs->mDistance; } }; struct CompareUpdateUrgency { bool operator()(const LLPointer<LLSpatialGroup> lhs, const LLPointer<LLSpatialGroup> rhs) { return lhs->getUpdateUrgency() > rhs->getUpdateUrgency(); } }; struct CompareDepthGreater { bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs) { return lhs->mDepth > rhs->mDepth; } }; struct CompareRenderOrder { bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs) { if (lhs->mAvatarp != rhs->mAvatarp) { return lhs->mAvatarp < rhs->mAvatarp; } return lhs->mRenderOrder > rhs->mRenderOrder; } }; typedef enum { GEOM_DIRTY = LLViewerOctreeGroup::INVALID_STATE, ALPHA_DIRTY = (GEOM_DIRTY << 1), IN_IMAGE_QUEUE = (ALPHA_DIRTY << 1), IMAGE_DIRTY = (IN_IMAGE_QUEUE << 1), MESH_DIRTY = (IMAGE_DIRTY << 1), NEW_DRAWINFO = (MESH_DIRTY << 1), IN_BUILD_Q1 = (NEW_DRAWINFO << 1), IN_BUILD_Q2 = (IN_BUILD_Q1 << 1), STATE_MASK = 0x0000FFFF, } eSpatialState; LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part); bool isHUDGroup() ; void clearDrawMap(); void validate(); void validateDrawMap(); void setState(U32 state, S32 mode); void clearState(U32 state, S32 mode); void clearState(U32 state) {mState &= ~state;} LLSpatialGroup* getParent(); bool addObject(LLDrawable *drawablep); bool removeObject(LLDrawable *drawablep, bool from_octree = false); bool updateInGroup(LLDrawable *drawablep, bool immediate = false); // Update position if it's in the group void expandExtents(const LLVector4a* addingExtents, const LLXformMatrix& currentTransform); void shift(const LLVector4a &offset); // TODO: this no longer appears to be called, figure out if it's important and if not remove it void destroyGLState(bool keep_occlusion = false); void updateDistance(LLCamera& camera); F32 getUpdateUrgency() const; bool changeLOD(); void rebuildGeom(); void rebuildMesh(); void setState(U32 state) {mState |= state;} void dirtyGeom() { setState(GEOM_DIRTY); } void dirtyMesh() { setState(MESH_DIRTY); } void drawObjectBox(LLColor4 col); LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, bool pick_transparent, bool pick_rigged, bool pick_unselectable, bool pick_reflection_probe, S32* face_hit, // return the face hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point LLVector4a* normal = NULL, // return the surface normal at the intersection point LLVector4a* tangent = NULL // return the surface tangent at the intersection point ); LLSpatialPartition* getSpatialPartition() {return (LLSpatialPartition*)mSpatialPartition;} //LISTENER FUNCTIONS virtual void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* face); virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face); virtual void handleDestruction(const TreeNode* node); virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); // LLViewerOctreeGroup virtual void rebound(); public: LL_ALIGN_16(LLVector4a mViewAngle); LL_ALIGN_16(LLVector4a mLastUpdateViewAngle); protected: virtual ~LLSpatialGroup(); public: LLPointer<LLVertexBuffer> mVertexBuffer; draw_map_t mDrawMap; bridge_list_t mBridgeList; buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3() U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node F32 mBuilt; F32 mDistance; F32 mDepth; F32 mLastUpdateDistance; F32 mLastUpdateTime; F32 mPixelArea; F32 mRadius; //used by LLVOAVatar to set render order in alpha draw pool to preserve legacy render order behavior LLVOAvatar* mAvatarp = nullptr; U32 mRenderOrder = 0; // Reflection Probe associated with this node (if any) LLPointer<LLReflectionMap> mReflectionProbe = nullptr; } LL_ALIGN_POSTFIX(16); class LLGeometryManager { public: std::vector<LLFace*> mFaceList; virtual ~LLGeometryManager() { } virtual void rebuildGeom(LLSpatialGroup* group) = 0; virtual void rebuildMesh(LLSpatialGroup* group) = 0; virtual void getGeometry(LLSpatialGroup* group) = 0; virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count); }; class LLSpatialPartition: public LLViewerOctreePartition, public LLGeometryManager { public: LLSpatialPartition(U32 data_mask, bool render_by_group, LLViewerRegion* regionp); virtual ~LLSpatialPartition(); LLSpatialGroup *put(LLDrawable *drawablep, bool was_visible = false); bool remove(LLDrawable *drawablep, LLSpatialGroup *curp); LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, bool pick_transparent, bool pick_rigged, bool pick_unselectable, bool pick_reflection_probe, S32* face_hit, // return the face hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point LLVector4a* normal = NULL, // return the surface normal at the intersection point LLVector4a* tangent = NULL // return the surface tangent at the intersection point ); // If the drawable moves, move it here. virtual void move(LLDrawable *drawablep, LLSpatialGroup *curp, bool immediate = false); virtual void shift(const LLVector4a &offset); virtual F32 calcDistance(LLSpatialGroup* group, LLCamera& camera); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); bool visibleObjectsInFrustum(LLCamera& camera); /*virtual*/ S32 cull(LLCamera &camera, bool do_occlusion=false); // Cull on arbitrary frustum S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results, bool for_select); // Cull on arbitrary frustum bool isVisible(const LLVector3& v); bool isHUDPartition() ; LLSpatialBridge* asBridge() { return mBridge; } bool isBridge() { return asBridge() != NULL; } void renderPhysicsShapes(bool depth_only); void renderDebug(); void renderIntersectingBBoxes(LLCamera* camera); void restoreGL(); bool getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax); public: LLSpatialBridge* mBridge; // NULL for non-LLSpatialBridge instances, otherwise, mBridge == this // use a pointer instead of making "isBridge" and "asBridge" virtual so it's safe // to call asBridge() from the destructor bool mInfiniteFarClip; // if true, frustum culling ignores far clip plane const bool mRenderByGroup; U32 mVertexDataMask; F32 mSlopRatio; //percentage distance must change before drawables receive LOD update (default is 0.25); bool mDepthMask; //if true, objects in this partition will be written to depth during alpha rendering }; // class for creating bridges between spatial partitions class LLSpatialBridge : public LLDrawable, public LLSpatialPartition { protected: ~LLSpatialBridge(); public: typedef std::vector<LLPointer<LLSpatialBridge> > bridge_vector_t; LLSpatialBridge(LLDrawable* root, bool render_by_group, U32 data_mask, LLViewerRegion* regionp); void destroyTree(); virtual bool isSpatialBridge() const { return true; } virtual void updateSpatialExtents(); virtual void updateBinRadius(); virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, bool for_select = false); virtual void updateDistance(LLCamera& camera_in, bool force_update); virtual void makeActive(); virtual void move(LLDrawable *drawablep, LLSpatialGroup *curp, bool immediate = false); virtual bool updateMove(); virtual void shiftPos(const LLVector4a& vec); virtual void cleanupReferences(); virtual LLSpatialPartition* asPartition() { return this; } //transform agent space camera into this Spatial Bridge's coordinate frame virtual LLCamera transformCamera(LLCamera& camera); //transform agent space bounding box into this Spatial Bridge's coordinate frame void transformExtents(const LLVector4a* src, LLVector4a* dst); LLDrawable* mDrawable; }; class LLCullResult { public: LLCullResult(); typedef std::vector<LLSpatialGroup*> sg_list_t; typedef std::vector<LLDrawable*> drawable_list_t; typedef std::vector<LLSpatialBridge*> bridge_list_t; typedef std::vector<LLDrawInfo*> drawinfo_list_t; typedef LLSpatialGroup** sg_iterator; typedef LLSpatialBridge** bridge_iterator; typedef LLDrawInfo** drawinfo_iterator; typedef LLDrawable** drawable_iterator; // Helper function for taking advantage of _mm_prefetch when iterating over cull results static inline void increment_iterator(LLCullResult::drawinfo_iterator& i, const LLCullResult::drawinfo_iterator& end) { ++i; if (i != end) { _mm_prefetch((char*)(*i)->mVertexBuffer.get(), _MM_HINT_NTA); auto* ni = i + 1; if (ni != end) { _mm_prefetch((char*)*ni, _MM_HINT_NTA); } } } void clear(); sg_iterator beginVisibleGroups(); sg_iterator endVisibleGroups(); sg_iterator beginAlphaGroups(); sg_iterator endAlphaGroups(); sg_iterator beginRiggedAlphaGroups(); sg_iterator endRiggedAlphaGroups(); bool hasOcclusionGroups() { return mOcclusionGroupsSize > 0; } sg_iterator beginOcclusionGroups(); sg_iterator endOcclusionGroups(); sg_iterator beginDrawableGroups(); sg_iterator endDrawableGroups(); drawable_iterator beginVisibleList(); drawable_iterator endVisibleList(); bridge_iterator beginVisibleBridge(); bridge_iterator endVisibleBridge(); drawinfo_iterator beginRenderMap(U32 type); drawinfo_iterator endRenderMap(U32 type); void pushVisibleGroup(LLSpatialGroup* group); void pushAlphaGroup(LLSpatialGroup* group); void pushRiggedAlphaGroup(LLSpatialGroup* group); void pushOcclusionGroup(LLSpatialGroup* group); void pushDrawableGroup(LLSpatialGroup* group); void pushDrawable(LLDrawable* drawable); void pushBridge(LLSpatialBridge* bridge); void pushDrawInfo(U32 type, LLDrawInfo* draw_info); U32 getVisibleGroupsSize() { return mVisibleGroupsSize; } U32 getAlphaGroupsSize() { return mAlphaGroupsSize; } U32 getRiggedAlphaGroupsSize() { return mRiggedAlphaGroupsSize; } U32 getDrawableGroupsSize() { return mDrawableGroupsSize; } U32 getVisibleListSize() { return mVisibleListSize; } U32 getVisibleBridgeSize() { return mVisibleBridgeSize; } U32 getRenderMapSize(U32 type) { return mRenderMapSize[type]; } void assertDrawMapsEmpty(); private: template <class T, class V> void pushBack(T &head, U32& count, V* val); U32 mVisibleGroupsSize; U32 mAlphaGroupsSize; U32 mRiggedAlphaGroupsSize; U32 mOcclusionGroupsSize; U32 mDrawableGroupsSize; U32 mVisibleListSize; U32 mVisibleBridgeSize; U32 mVisibleGroupsAllocated; U32 mAlphaGroupsAllocated; U32 mRiggedAlphaGroupsAllocated; U32 mOcclusionGroupsAllocated; U32 mDrawableGroupsAllocated; U32 mVisibleListAllocated; U32 mVisibleBridgeAllocated; U32 mRenderMapSize[LLRenderPass::NUM_RENDER_TYPES]; sg_list_t mVisibleGroups; sg_iterator mVisibleGroupsEnd; sg_list_t mAlphaGroups; sg_iterator mAlphaGroupsEnd; sg_list_t mRiggedAlphaGroups; sg_iterator mRiggedAlphaGroupsEnd; sg_list_t mOcclusionGroups; sg_iterator mOcclusionGroupsEnd; sg_list_t mDrawableGroups; sg_iterator mDrawableGroupsEnd; drawable_list_t mVisibleList; drawable_iterator mVisibleListEnd; bridge_list_t mVisibleBridge; bridge_iterator mVisibleBridgeEnd; drawinfo_list_t mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; U32 mRenderMapAllocated[LLRenderPass::NUM_RENDER_TYPES]; drawinfo_iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; }; //spatial partition for water (implemented in LLVOWater.cpp) class LLWaterPartition : public LLSpatialPartition { public: LLWaterPartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group) { } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } }; //spatial partition for hole and edge water (implemented in LLVOWater.cpp) class LLVoidWaterPartition : public LLWaterPartition { public: LLVoidWaterPartition(LLViewerRegion* regionp); }; //spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp) class LLTerrainPartition : public LLSpatialPartition { public: LLTerrainPartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group); }; //spatial partition for trees class LLTreePartition : public LLSpatialPartition { public: LLTreePartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group) { } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } }; //spatial partition for particles (implemented in LLVOPartGroup.cpp) class LLParticlePartition : public LLSpatialPartition { public: LLParticlePartition(LLViewerRegion* regionp); virtual void rebuildGeom(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); protected: U32 mRenderPass; }; class LLHUDParticlePartition : public LLParticlePartition { public: LLHUDParticlePartition(LLViewerRegion* regionp); }; //spatial partition for grass (implemented in LLVOGrass.cpp) class LLGrassPartition : public LLSpatialPartition { public: LLGrassPartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); protected: U32 mRenderPass; }; //class for wrangling geometry out of volumes (implemented in LLVOVolume.cpp) class LLVolumeGeometryManager: public LLGeometryManager { public: typedef enum { NONE = 0, BATCH_SORT, DISTANCE_SORT } eSortType; LLVolumeGeometryManager(); virtual ~LLVolumeGeometryManager(); virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count); U32 genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, bool distance_sort = false, bool batch_textures = false, bool rigged = false); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); private: void allocateFaces(U32 pMaxFaceCount); void freeFaces(); static int32_t sInstanceCount; static LLFace** sFullbrightFaces[2]; static LLFace** sBumpFaces[2]; static LLFace** sSimpleFaces[2]; static LLFace** sNormFaces[2]; static LLFace** sSpecFaces[2]; static LLFace** sNormSpecFaces[2]; static LLFace** sPbrFaces[2]; static LLFace** sAlphaFaces[2]; }; //spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp) class LLVolumePartition : public LLSpatialPartition, public LLVolumeGeometryManager { public: LLVolumePartition(LLViewerRegion* regionp); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); } }; //spatial bridge that uses volume geometry manager (implemented in LLVOVolume.cpp) class LLVolumeBridge : public LLSpatialBridge, public LLVolumeGeometryManager { public: LLVolumeBridge(LLDrawable* drawable, LLViewerRegion* regionp); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); } }; class LLAvatarBridge : public LLVolumeBridge { public: LLAvatarBridge(LLDrawable* drawablep, LLViewerRegion* regionp); }; class LLControlAVBridge : public LLVolumeBridge { using super = LLVolumeBridge; public: LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp); }; class LLHUDBridge : public LLVolumeBridge { public: LLHUDBridge(LLDrawable* drawablep, LLViewerRegion* regionp); virtual void shiftPos(const LLVector4a& vec); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); }; //spatial partition that holds nothing but spatial bridges class LLBridgePartition : public LLSpatialPartition { public: LLBridgePartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group) { } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } }; class LLAvatarPartition : public LLBridgePartition { public: LLAvatarPartition(LLViewerRegion* regionp); }; class LLControlAVPartition : public LLBridgePartition { public: LLControlAVPartition(LLViewerRegion* regionp); }; class LLHUDPartition : public LLBridgePartition { public: LLHUDPartition(LLViewerRegion* regionp); virtual void shift(const LLVector4a &offset); }; extern const F32 SG_BOX_SIDE; extern const F32 SG_BOX_OFFSET; extern const F32 SG_BOX_RAD; extern const F32 SG_OBJ_SIDE; extern const F32 SG_MAX_OBJ_RAD; #endif //LL_LLSPATIALPARTITION_H