/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRY3DENGINE_STATOBJ_H #define CRYINCLUDE_CRY3DENGINE_STATOBJ_H #pragma once #if !defined(CONSOLE) # define TRACE_CGF_LEAKS # define SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS #endif class CIndexedMesh; class CRenderObject; class CContentCGF; struct CNodeCGF; struct CMaterialCGF; struct phys_geometry; struct IIndexedMesh; struct IParticleEffect; #include "../Cry3DEngine/Cry3DEngineBase.h" #include "CryArray.h" #include #include #include "RenderMeshUtils.h" #include "GeomQuery.h" #include #define MAX_PHYS_GEOMS_TYPES 4 struct SDeformableMeshData { IGeometry* pInternalGeom; int* pVtxMap; unsigned int* pUsedVtx; int* pVtxTri; int* pVtxTriBuf; float* prVtxValency; Vec3* pPrevVtx; float kViscosity; }; struct SSpine { ~SSpine() { delete[] pVtx; delete[] pVtxCur; delete[] pSegDim; delete[] pStiffness; delete[] pDamping; delete[] pThickness; } SSpine() : bActive(false), pVtx(nullptr), pVtxCur(nullptr), pSegDim(nullptr), pStiffness(nullptr), pDamping(nullptr), pThickness(nullptr), nVtx(0), len(0.0f), navg(0.0f, 0.0f, 0.0f), idmat(0), iAttachSpine(0), iAttachSeg(0) {} bool bActive; Vec3* pVtx; Vec3* pVtxCur; Vec4* pSegDim; /// Per bone UDP for stiffness, damping and thickness for touch bending vegetation float* pStiffness; float* pDamping; float* pThickness; int nVtx; float len; Vec3 navg; int idmat; int iAttachSpine; int iAttachSeg; }; namespace Physics { struct TouchBendingSkeletonHandle; } class CStatObjFoliage : public IFoliage , public Cry3DEngineBase { public: CStatObjFoliage() : m_touchBendingSkeletonProxy(nullptr), m_worldAabb(AABB::type_reset::RESET) { m_next = 0; m_prev = 0; m_lifeTime = 0; m_ppThis = 0; m_pStatObj = 0; #if ENABLE_CRY_PHYSICS m_pRopes = 0; #endif m_pRopesActiveTime = 0; m_nRopes = 0; m_nRefCount = 1; m_timeIdle = 0; m_pVegInst = 0; m_pTrunk = 0; m_pSkinningTransformations[0] = 0; m_pSkinningTransformations[1] = 0; m_iActivationSource = 0; m_flags = 0; m_bGeomRemoved = 0; m_bEnabled = 1; m_timeInvisible = 0; m_bDelete = 0; m_pRenderObject = 0; arrSkinningRendererData[0].pSkinningData = NULL; arrSkinningRendererData[0].nFrameID = 0; arrSkinningRendererData[1].pSkinningData = NULL; arrSkinningRendererData[1].nFrameID = 0; arrSkinningRendererData[2].pSkinningData = NULL; arrSkinningRendererData[2].nFrameID = 0; } ~CStatObjFoliage(); virtual void AddRef() { m_nRefCount++; } virtual void Release() { if (--m_nRefCount <= 0) { m_bDelete = 2; } } virtual int Serialize(TSerialize ser); virtual void SetFlags(int flags); virtual int GetFlags() { return m_flags; } virtual IRenderNode* GetIRenderNode() { return m_pVegInst; } virtual int GetBranchCount() { return m_nRopes; } virtual IPhysicalEntity* GetBranchPhysics(int iBranch) { #if ENABLE_CRY_PHYSICS return (unsigned int)iBranch < (unsigned int)m_nRopes ? m_pRopes[iBranch] : 0; #else return nullptr; #endif } virtual SSkinningData* GetSkinningData(const Matrix34& RenderMat34, const SRenderingPassInfo& passInfo); uint32 ComputeSkinningTransformationsCount(); void ComputeSkinningTransformations(uint32 nList); void OnHit(struct EventPhysCollision* pHit); void Update(float dt, const CCamera& rCamera); void BreakBranch(int idx); CStatObjFoliage* m_next, *m_prev; int m_nRefCount; int m_flags; CStatObj* m_pStatObj; #if ENABLE_CRY_PHYSICS IPhysicalEntity** m_pRopes; #endif float* m_pRopesActiveTime; IPhysicalEntity* m_pTrunk; int16 m_nRopes; int16 m_bEnabled; float m_timeIdle, m_lifeTime; IFoliage** m_ppThis; QuatTS* m_pSkinningTransformations[2]; int m_iActivationSource; int m_bGeomRemoved; IRenderNode* m_pVegInst; CRenderObject* m_pRenderObject; float m_timeInvisible; int m_bDelete; //Used only by TouchBendingGem START (TouchBendingCVegetationAgent.cpp) /// Opaque pointer created by TouchBending Gem. Used by TouchBendingCVegetationAgent to /// talk to the Touch Bending Gem on behalf of each CStatObjFoliage object. Physics::TouchBendingSkeletonHandle* m_touchBendingSkeletonProxy; AABB m_worldAabb; //Used only by TouchBendingGem END // history for skinning data, needed for motion blur struct { SSkinningData* pSkinningData; int nFrameID; } arrSkinningRendererData[3]; // tripple buffered for motion blur }; struct SClothTangentVtx { int ivtxT; // for each vertex, specifies the iThisVtx->ivtxT edge, which is the closest to the vertex's tangent vector Vec3 edge; // that edge's projection on the vertex's normal basis int sgnNorm; // sign of phys normal * normal from the basis }; struct SSkinVtx { int bVolumetric; int idx[4]; float w[4]; Matrix33 M; }; struct SDelayedSkinParams { Matrix34 mtxSkelToMesh; IGeometry* pPhysSkel; float r; }; struct SPhysGeomThunk { phys_geometry* pgeom; int type; void GetMemoryUsage(ICrySizer* pSizer) const { // pSizer->AddObject(pgeom); } }; struct SPhysGeomArray { phys_geometry* operator[](int idx) const { if (idx < PHYS_GEOM_TYPE_DEFAULT) { return idx < (int)m_array.size() ? m_array[idx].pgeom : 0; } else { int i; for (i = m_array.size() - 1; i >= 0 && m_array[i].type != idx; i--) { ; } return i >= 0 ? m_array[i].pgeom : 0; } } void SetPhysGeom(phys_geometry* pgeom, int idx = PHYS_GEOM_TYPE_DEFAULT, int type = PHYS_GEOM_TYPE_DEFAULT) { int i; if (idx < PHYS_GEOM_TYPE_DEFAULT) { i = idx, idx = type; } else { for (i = 0; i < (int)m_array.size() && m_array[i].type != idx; i++) { ; } } if (pgeom) { if (i >= (int)m_array.size()) { m_array.resize(i + 1); } m_array[i].pgeom = pgeom; m_array[i].type = idx; } else if (i < (int)m_array.size()) { m_array.erase(m_array.begin() + i); } } int GetGeomCount() { return m_array.size(); } int GetGeomType(int idx) { return idx >= PHYS_GEOM_TYPE_DEFAULT ? idx : m_array[idx].type; } std::vector m_array; void GetMemoryUsage(ICrySizer* pSizer) const { pSizer->AddObject(m_array); } }; struct SSyncToRenderMeshContext { Vec3* vmin, *vmax; int iVtx0; int nVtx; strided_pointer pVtx; int* pVtxMap; int mask; float rscale; SClothTangentVtx* ctd; strided_pointer pMeshVtx; strided_pointer pTangents; strided_pointer pNormals; // TODO: change Vec3 to SPipNormal CStatObj* pObj; AZ::LegacyJobExecutor jobExecutor; void Set(Vec3* _vmin, Vec3* _vmax, int _iVtx0, int _nVtx, strided_pointer _pVtx, int* _pVtxMap , int _mask, float _rscale, SClothTangentVtx* _ctd, strided_pointer _pMeshVtx , strided_pointer _pTangents, strided_pointer _pNormals, CStatObj* _pObj) { vmin = _vmin; vmax = _vmax; iVtx0 = _iVtx0; nVtx = _nVtx; pVtx = _pVtx; pVtxMap = _pVtxMap; mask = _mask; rscale = _rscale; ctd = _ctd; pMeshVtx = _pMeshVtx; pTangents = _pTangents; pNormals = _pNormals; pObj = _pObj; } }; struct CStatObj : public IStatObj , public IStreamCallback , public stl::intrusive_linked_list_node , public Cry3DEngineBase { CStatObj(); ~CStatObj(); public: ////////////////////////////////////////////////////////////////////////// // Variables. ////////////////////////////////////////////////////////////////////////// volatile int m_nUsers; // reference counter uint32 m_nLastDrawMainFrameId; _smart_ptr m_pRenderMesh; #ifdef SERVER_CHECKS CMesh* m_pMesh; // Used by the dedicated server where the render mesh doesn't exist #endif CryCriticalSection m_streamingMeshLock; _smart_ptr m_pStreamedRenderMesh; _smart_ptr m_pMergedRenderMesh; // Used by hierarchical breaking to hide sub-objects that initially must be hidden. uint64 m_nInitialSubObjHideMask; CIndexedMesh* m_pIndexedMesh; volatile int m_lockIdxMesh; string m_szFileName; string m_szGeomName; string m_szProperties; string m_szStreamingDependencyFilePath; int m_nLoadedTrisCount; int m_nLoadedVertexCount; int m_nRenderTrisCount; int m_nRenderMatIds; float m_fGeometricMeanFaceArea; float m_fLodDistance; // Default material. _smart_ptr m_pMaterial; float m_fObjectRadius; float m_fRadiusHors; float m_fRadiusVert; Vec3 m_vBoxMin, m_vBoxMax, m_vVegCenter; SPhysGeomArray m_arrPhysGeomInfo; ITetrLattice* m_pLattice; IStatObj* m_pLastBooleanOp; float m_lastBooleanOpScale; _smart_ptr* m_pLODs; IStatObj* m_pLod0; // Level 0 stat object. (Pointer to the original object of the LOD) unsigned int m_nMinUsableLod0 : 8; // What is the minimal LOD that can be used as LOD0. unsigned int m_nMaxUsableLod0 : 8; // What is the maximal LOD that can be used as LOD0. unsigned int m_nMaxUsableLod : 8; // What is the maximal LOD that can be used. unsigned int m_nLoadedLodsNum : 8; // How many lods loaded. string m_cgfNodeName; ////////////////////////////////////////////////////////////////////////// // Externally set flags from enum EStaticObjectFlags. ////////////////////////////////////////////////////////////////////////// int m_nFlags; ////////////////////////////////////////////////////////////////////////// // Internal Flags. ////////////////////////////////////////////////////////////////////////// unsigned int m_bCheckGarbage : 1; unsigned int m_bCanUnload : 1; unsigned int m_bLodsLoaded : 1; unsigned int m_bDefaultObject : 1; unsigned int m_bOpenEdgesTested : 1; unsigned int m_bSubObject : 1; // This is sub object. unsigned int m_bVehicleOnlyPhysics : 1; // Object can be used for collisions with vehicles only unsigned int m_bBreakableByGame : 1; // material is marked as breakable by game unsigned int m_bSharesChildren : 1; // means its subobjects belong to another parent statobj unsigned int m_bHasDeformationMorphs : 1; unsigned int m_bTmpIndexedMesh : 1; // indexed mesh is temporary and can be deleted after MakeRenderMesh unsigned int m_bUnmergable : 1; // Set if sub objects cannot be merged together to the single render merge. unsigned int m_bMerged : 1; // Set if sub objects merged together to the single render merge. unsigned int m_bMergedLODs : 1; // Set if m_pLODs were created while merging LODs unsigned int m_bLowSpecLod0Set : 1; unsigned int m_bHaveOcclusionProxy : 1; // If this stat object or its childs have occlusion proxy. unsigned int m_bLodsAreLoadedFromSeparateFile : 1; unsigned int m_bNoHitRefinement : 1; // doesn't refine bullet hits against rendermesh unsigned int m_bDontOccludeExplosions : 1; // don't act as an explosion occluder in physics unsigned int m_hasClothTangentsData : 1; unsigned int m_hasSkinInfo : 1; unsigned int m_bMeshStrippedCGF : 1; // This CGF was loaded from the Mesh Stripped CGF, (in Level Cache) unsigned int m_isDeformable : 1; // This cgf is deformable in the sense that it has a special renderpath unsigned int m_isProxyTooBig : 1; unsigned int m_bHasStreamOnlyCGF : 1; int m_idmatBreakable; // breakable id for the physics ////////////////////////////////////////////////////////////////////////// // streaming int m_nRenderMeshMemoryUsage; int m_nMergedMemoryUsage; int m_arrRenderMeshesPotentialMemoryUsage[2]; IReadStreamPtr m_pReadStream; #if !defined (_RELEASE) || defined(ENABLE_STATOSCOPE_RELEASE) static float s_fStreamingTime; static int s_nBandwidth; float m_fStreamingStart; #endif #ifdef OBJMAN_STREAM_STATS int m_nStatoscopeState; #endif ////////////////////////////////////////////////////////////////////////// uint16* m_pMapFaceToFace0; union { SClothTangentVtx* m_pClothTangentsData; SSkinVtx* m_pSkinInfo; }; SDelayedSkinParams* m_pDelayedSkinParams; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // Bendable Foliage. ////////////////////////////////////////////////////////////////////////// SSpine* m_pSpines; int m_nSpines; struct SMeshBoneMapping_uint8* m_pBoneMapping; std::vector m_chunkBoneIds; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // for debug purposes ////////////////////////////////////////////////////////////////////////// #ifdef TRACE_CGF_LEAKS string m_sLoadingCallstack; #endif private: ////////////////////////////////////////////////////////////////////////// // Sub objects. ////////////////////////////////////////////////////////////////////////// std::vector m_subObjects; CStatObj* m_pParentObject; // Parent object (Must not be smart pointer). CStatObj* m_pClonedSourceObject; // If this is cloned object, pointer to original source object (Must not be smart pointer). int m_nSubObjectMeshCount; int m_nNodeCount; CGeomExtents m_Extents; // Cached extents for random pos generation. ////////////////////////////////////////////////////////////////////////// // Special AI/Physics parameters. ////////////////////////////////////////////////////////////////////////// float m_aiVegetationRadius; float m_phys_mass; float m_phys_density; ////////////////////////////////////////////////////////////////////////// // used only in the editor ////////////////////////////////////////////////////////////////////////// #ifdef SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS float* m_pHeightmap; int m_nHeightmapSize; float m_fOcclusionAmount; #endif SSyncToRenderMeshContext* m_pAsyncUpdateContext; ////////////////////////////////////////////////////////////////////////// // Cloth data ////////////////////////////////////////////////////////////////////////// AZStd::vector m_clothData; ////////////////////////////////////////////////////////////////////////// // METHODS. ////////////////////////////////////////////////////////////////////////// public: virtual void SetDefaultObject(bool state) override { m_bDefaultObject = state; } ////////////////////////////////////////////////////////////////////////// // Fast non virtual access functions. ILINE IStatObj::SSubObject& SubObject(int nIndex) { return m_subObjects[nIndex]; }; ILINE int SubObjectCount() const { return m_subObjects.size(); }; ////////////////////////////////////////////////////////////////////////// virtual void SetCanUnload(bool value) override { m_bCanUnload = value; } virtual bool IsUnloadable() const { return m_bCanUnload; } virtual bool IsUnmergable() const { return m_bUnmergable; } virtual void SetUnmergable(bool state) { m_bUnmergable = state; } void DisableStreaming(); virtual bool AreLodsLoaded() const override { return m_bLodsLoaded; } virtual SPhysGeomArray& GetArrPhysGeomInfo() override { return m_arrPhysGeomInfo; } IIndexedMesh* GetIndexedMesh(bool bCreatefNone = false); IIndexedMesh* CreateIndexedMesh(); void ReleaseIndexedMesh(bool bRenderMeshUpdated = false); ILINE const Vec3 GetVegCenter() { return m_vVegCenter; } ILINE float GetRadius() { return m_fObjectRadius; } virtual void SetFlags(int nFlags) override { m_nFlags = nFlags; }; virtual int GetFlags() const override { return m_nFlags; }; virtual bool IsLodsAreLoadedFromSeparateFile() override { return m_bLodsAreLoadedFromSeparateFile; } virtual int GetSubObjectMeshCount() const override { return m_nSubObjectMeshCount; } virtual void SetSubObjectMeshCount(int count) { m_nSubObjectMeshCount = count; } virtual unsigned int GetVehicleOnlyPhysics() { return m_bVehicleOnlyPhysics; }; virtual int GetIDMatBreakable() { return m_idmatBreakable; }; virtual unsigned int GetBreakableByGame() { return m_bBreakableByGame; }; //Note: This function checks both the children and root data //It should really be 'has any deformable objects' //Should eventually be refactored as part of an eventual statobj refactor. virtual bool IsDeformable() override; // Loader bool LoadCGF(const char* filename, bool bLod, unsigned long nLoadingFlags, const void* pData, const int nDataSize); bool LoadCGF_Int(const char* filename, bool bLod, unsigned long nLoadingFlags, const void* pData, const int nDataSize); ////////////////////////////////////////////////////////////////////////// void SetMaterial(_smart_ptr pMaterial); _smart_ptr GetMaterial() { return m_pMaterial; } const _smart_ptr GetMaterial() const { return m_pMaterial; } ////////////////////////////////////////////////////////////////////////// void RenderInternal(CRenderObject* pRenderObject, uint64 nSubObjectHideMask, const CLodValue& lodValue, const SRenderingPassInfo& passInfo, const SRendItemSorter& rendItemSorter, bool forceStaticDraw); void RenderObjectInternal(CRenderObject* pRenderObject, int nLod, uint8 uLodDissolveRef, bool dissolveOut, const SRenderingPassInfo& passInfo, const SRendItemSorter& rendItemSorter, bool forceStaticDraw); void RenderSubObject(CRenderObject* pRenderObject, int nLod, int nSubObjId, const Matrix34A& renderTM, const SRenderingPassInfo& passInfo, const SRendItemSorter& rendItemSorter, bool forceStaticDraw); void RenderSubObjectInternal(CRenderObject* pRenderObject, int nLod, const SRenderingPassInfo& passInfo, const SRendItemSorter& rendItemSorter, bool forceStaticDraw); virtual void Render(const SRendParams& rParams, const SRenderingPassInfo& passInfo); void RenderRenderMesh(CRenderObject* pObj, struct SInstancingInfo* pInstInfo, const SRenderingPassInfo& passInfo, const SRendItemSorter& rendItemSorter); phys_geometry* GetPhysGeom(int nGeomType = PHYS_GEOM_TYPE_DEFAULT) { return m_arrPhysGeomInfo[nGeomType]; } void SetPhysGeom(phys_geometry* pPhysGeom, int nGeomType = PHYS_GEOM_TYPE_DEFAULT) { #if ENABLE_CRY_PHYSICS if (m_arrPhysGeomInfo[nGeomType]) { GetPhysicalWorld()->GetGeomManager()->UnregisterGeometry(m_arrPhysGeomInfo[nGeomType]); } #endif m_arrPhysGeomInfo.SetPhysGeom(pPhysGeom, nGeomType); } ITetrLattice* GetTetrLattice() { return m_pLattice; } float GetAIVegetationRadius() const { return m_aiVegetationRadius; } void SetAIVegetationRadius(float radius) { m_aiVegetationRadius = radius; } //! Refresh object ( reload shaders or/and object geometry ) virtual void Refresh(int nFlags); IRenderMesh* GetRenderMesh() { return m_pRenderMesh; }; void SetRenderMesh(IRenderMesh* pRM); const char* GetFilePath() const { return (m_szFileName); } void SetFilePath(const char* szFileName) { m_szFileName = szFileName; } const char* GetGeoName() { return (m_szGeomName); } void SetGeoName(const char* szGeoName) { m_szGeomName = szGeoName; } bool IsSameObject(const char* szFileName, const char* szGeomName); //set object's min/max bbox void SetBBoxMin(const Vec3& vBBoxMin) { m_vBoxMin = vBBoxMin; } void SetBBoxMax(const Vec3& vBBoxMax) { m_vBoxMax = vBBoxMax; } Vec3 GetBoxMin() { return m_vBoxMin; } Vec3 GetBoxMax() { return m_vBoxMax; } AABB GetAABB() { return AABB(m_vBoxMin, m_vBoxMax); } AABB GetAABB() const { return AABB(m_vBoxMin, m_vBoxMax); } virtual float GetExtent(EGeomForm eForm); virtual void GetRandomPos(PosNorm& ran, EGeomForm eForm) const; virtual Vec3 GetHelperPos(const char* szHelperName); virtual const Matrix34& GetHelperTM(const char* szHelperName); virtual float& GetRadiusVert() override { return m_fRadiusVert; } virtual float& GetRadiusHors() override { return m_fRadiusHors; } virtual int AddRef(); virtual int Release(); int GetNumRefs() const { return m_nUsers; } virtual bool IsDefaultObject() { return (m_bDefaultObject); } int GetLoadedTrisCount() const override { return m_nLoadedTrisCount; } int GetRenderTrisCount() const override { return m_nRenderTrisCount; } int GetRenderMatIds() const override { return m_nRenderMatIds; } // Load LODs void SetLodObject(int nLod, IStatObj* pLod) override; bool LoadLowLODS_Prep(bool bUseStreaming, unsigned long nLoadingFlags); IStatObj* LoadLowLODS_Load(int nLodLevel, bool bUseStreaming, unsigned long nLoadingFlags, const void* pData, int nDataLen); void LoadLowLODS_Finalize(int nLoadedLods, IStatObj* loadedLods[MAX_STATOBJ_LODS_NUM]); void LoadLowLODs(bool bUseStreaming, unsigned long nLoadingFlags); // Free render resources for unused upper LODs. virtual void CleanUnusedLods() override; virtual void FreeIndexedMesh(); bool RenderDebugInfo(CRenderObject* pObj, const SRenderingPassInfo& passInfo); //! Release method. void GetMemoryUsage(class ICrySizer* pSizer) const; void ShutDown(); void Init(); // void CheckLoaded(); IStatObj* GetLodObject(int nLodLevel, bool bReturnNearest = false) override; IStatObj* GetLowestLod() override; _smart_ptr* GetLods() override { return m_pLODs; } int GetLoadedLodsNum() override { return m_nLoadedLodsNum; } void SetMerged(bool state) override { m_bMerged = state; } int GetRenderMeshMemoryUsage() const override { return m_nRenderMeshMemoryUsage; } int FindNearesLoadedLOD(int nLodIn, bool bSearchUp = false) override; int FindHighestLOD(int nBias) override; // interface IStreamCallback ----------------------------------------------------- void StreamAsyncOnComplete(IReadStream* pStream, unsigned nError) override; void StreamOnComplete(IReadStream* pStream, unsigned nError) override; // ------------------------------------------------------------------------------- void StartStreaming(bool bFinishNow, IReadStream_AutoPtr* ppStream) override; void UpdateStreamingPrioriryInternal(const Matrix34A& objMatrix, float fDistance, bool bFullUpdate); void MakeCompiledFileName(char* szCompiledFileName, int nMaxLen); bool IsPhysicsExist(); bool IsSphereOverlap(const Sphere& sSphere); void Invalidate(bool bPhysics = false, float tolerance = 0.05f); void AnalyzeFoliage(IRenderMesh* pRenderMesh, CContentCGF* pCGF); void FreeFoliageData(); void CopyFoliageData(IStatObj* pObjDst, bool bMove = false, IFoliage* pSrcFoliage = 0, int* pVtxMap = 0, primitives::box* pMoveBoxes = 0, int nMovedBoxes = -1); int PhysicalizeFoliage(IPhysicalEntity* pTrunk, const Matrix34& mtxWorld, IFoliage*& pRes, float lifeTime = 0.0f, int iSource = 0); int SerializeFoliage(TSerialize ser, IFoliage* pFoliage); IStatObj* UpdateVertices(strided_pointer pVtx, strided_pointer pNormals, int iVtx0, int nVtx, int* pVtxMap = 0, float rscale = 1.f); bool HasSkinInfo(float skinRadius = -1.0f) { return m_hasSkinInfo && m_pSkinInfo && (skinRadius < 0.0f || m_pSkinInfo[m_nLoadedVertexCount].w[0] == skinRadius); } void PrepareSkinData(const Matrix34& mtxSkelToMesh, IGeometry* pPhysSkel, float r = 0.0f); IStatObj* SkinVertices(strided_pointer pSkelVtx, const Matrix34& mtxSkelToMesh); ////////////////////////////////////////////////////////////////////////// // Sub objects. ////////////////////////////////////////////////////////////////////////// virtual int GetSubObjectCount() const { return m_subObjects.size(); } virtual void SetSubObjectCount(int nCount); virtual IStatObj::SSubObject* FindSubObject(const char* sNodeName); virtual IStatObj::SSubObject* FindSubObject_StrStr(const char* sNodeName); virtual IStatObj::SSubObject* FindSubObject_CGA(const char* sNodeName); virtual IStatObj::SSubObject* GetSubObject(int nIndex) { if (nIndex >= 0 && nIndex < (int)m_subObjects.size()) { return &m_subObjects[nIndex]; } else { return 0; } } virtual bool RemoveSubObject(int nIndex); virtual IStatObj* GetParentObject() const { return m_pParentObject; } virtual IStatObj* GetCloneSourceObject() const { return m_pClonedSourceObject; } virtual bool IsSubObject() const { return m_bSubObject; }; virtual bool CopySubObject(int nToIndex, IStatObj* pFromObj, int nFromIndex); virtual int PhysicalizeSubobjects(IPhysicalEntity* pent, const Matrix34* pMtx, float mass, float density = 0.0f, int id0 = 0, strided_pointer pJointsIdMap = 0, const char* szPropsOverride = 0); virtual IStatObj::SSubObject& AddSubObject(IStatObj* pStatObj); virtual int Physicalize(IPhysicalEntity* pent, pe_geomparams* pgp, int id = -1, const char* szPropsOverride = 0); ////////////////////////////////////////////////////////////////////////// virtual bool SaveToCGF(const char* sFilename, IChunkFile** pOutChunkFile = NULL, bool bHavePhiscalProxy = false); //virtual IStatObj* Clone(bool bCloneChildren=true, bool nDynamic=false); virtual IStatObj* Clone(bool bCloneGeometry, bool bCloneChildren, bool bMeshesOnly); virtual int SetDeformationMorphTarget(IStatObj* pDeformed); virtual int SubobjHasDeformMorph(int iSubObj); virtual IStatObj* DeformMorph(const Vec3& pt, float r, float strength, IRenderMesh* pWeights = 0); virtual IStatObj* HideFoliage(); virtual int Serialize(TSerialize ser); // Get object properties as loaded from CGF. virtual const char* GetProperties() { return m_szProperties.c_str(); }; virtual void SetProperties(const char* props) { m_szProperties = props; ParseProperties(); } virtual bool GetPhysicalProperties(float& mass, float& density); virtual IStatObj* GetLastBooleanOp(float& scale) { scale = m_lastBooleanOpScale; return m_pLastBooleanOp; } // Intersect ray with static object. // Ray must be in object local space. virtual bool RayIntersection(SRayHitInfo& hitInfo, _smart_ptr pCustomMtl = 0); virtual bool LineSegIntersection(const Lineseg& lineSeg, Vec3& hitPos, int& surfaceTypeId); virtual void DebugDraw(const SGeometryDebugDrawInfo& info, float fExtrdueScale = 0.01f); virtual void GetStatistics(SStatistics& stats); ////////////////////////////////////////////////////////////////////////// IParticleEffect* GetSurfaceBreakageEffect(const char* sType); virtual uint64 GetInitialHideMask() { return m_nInitialSubObjHideMask; } virtual uint64 UpdateInitialHideMask(uint64 maskAND = 0ul - 1ul, uint64 maskOR = 0) { return m_nInitialSubObjHideMask &= maskAND |= maskOR; } virtual void SetStreamingDependencyFilePath(const char* szFileName) { const bool streamingDependencyLoop = CheckForStreamingDependencyLoop(szFileName); if (streamingDependencyLoop) { CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_WARNING, "StatObj '%s' cannot set '%s' as a streaming dependency as it would result in a looping dependency.", GetFilePath(), szFileName); return; } m_szStreamingDependencyFilePath = szFileName; } #ifdef SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS float GetOcclusionAmount(); void CheckUpdateObjectHeightmap(); float GetObjectHeight(float x, float y); #endif virtual int GetMaxUsableLod() const override; virtual int GetMinUsableLod() const override; virtual SMeshBoneMapping_uint8* GetBoneMapping() const override { return m_pBoneMapping; } virtual int GetSpineCount() const override { return m_nSpines; } virtual SSpine* GetSpines() const override { return m_pSpines; } void RenderStreamingDebugInfo(CRenderObject* pRenderObject); void RenderCoverInfo(CRenderObject* pRenderObject); virtual int CountChildReferences() const override; void ReleaseStreamableContent(); int GetStreamableContentMemoryUsage(bool bJustForDebug = false); virtual void ComputeGeometricMean(SMeshLodInfo& lodInfo); virtual float GetLodDistance() const override { return m_fLodDistance; } virtual bool UpdateStreamableComponents(float fImportance, const Matrix34A& objMatrix, bool bFullUpdate, int nNewLod) override; void GetStreamableName(string& sName) { sName = m_szFileName; if (m_szGeomName.length()) { sName += " - "; sName += m_szGeomName; } }; void GetStreamFilePath(stack_string& strOut); void FillRenderObject(const SRendParams& rParams, IRenderNode* pRenderNode, _smart_ptr pMaterial, SInstancingInfo* pInstInfo, CRenderObject*& pObj, const SRenderingPassInfo& passInfo); virtual uint32 GetLastDrawMainFrameId() { return m_nLastDrawMainFrameId; } // Allow pooled allocs static void* operator new (size_t size); static void operator delete (void* pToFree); // Used in ObjMan. void TryMergeSubObjects(bool bFromStreaming) override; #if ENABLE_CRY_PHYSICS void SavePhysicalizeData(CNodeCGF* pNode); #endif bool IsMeshStrippedCGF() const { return m_bMeshStrippedCGF; } string& GetFileName() override { return m_szFileName; } const string& GetFileName() const override { return m_szFileName; } const string& GetCGFNodeName() const override { return m_cgfNodeName; } int GetUserCount() const override { return m_nUsers; } bool CheckGarbage() const override { return m_bCheckGarbage; } void SetCheckGarbage(bool val) override { m_bCheckGarbage = val; } IStatObj* GetLodLevel0() override { return m_pLod0; } void SetLodLevel0(IStatObj* lod) override { m_pLod0 = lod; } AZStd::vector& GetClothData() override { return m_clothData; } protected: // Called by async stream callback. bool LoadStreamRenderMeshes(const char* filename, const void* pData, const int nDataSize, bool bLod); // Called by sync stream complete callback. void CommitStreamRenderMeshes(); void MergeSubObjectsRenderMeshes(bool bFromStreaming, CStatObj* pLod0, int nLod); void UnMergeSubObjectsRenderMeshes(); bool CanMergeSubObjects(); bool IsMatIDReferencedByObj(uint16 matID); // bool LoadCGF_Info( const char *filename ); CStatObj* MakeStatObjFromCgfNode(CContentCGF* pCGF, CNodeCGF* pNode, bool bLod, int nLoadingFlags, AABB& commonBBox); void ParseProperties(); void CalcRadiuses(); void GetStatisticsNonRecursive(SStatistics& stats); #if ENABLE_CRY_PHYSICS void PhysicalizeCompiled(CNodeCGF* pNode, int bAppend = 0); bool PhysicalizeGeomType(int nGeomType, CMesh& mesh, float tolerance = 0.05f, int bAppend = 0); bool RegisterPhysicGeom(int nGeomType, phys_geometry* pPhysGeom); void AssignPhysGeom(int nGeomType, phys_geometry* pPhysGeom, int bAppend = 0, int bLoading = 0); #endif // ENABLE_CRY_PHYSICS // Creates static object contents from mesh. // Return true if successful. _smart_ptr MakeRenderMesh(CMesh* pMesh, bool bDoRenderMesh); void MakeRenderMesh(); const char* stristr(const char* szString, const char* szSubstring) { int nSuperstringLength = (int)strlen(szString); int nSubstringLength = (int)strlen(szSubstring); for (int nSubstringPos = 0; nSubstringPos <= nSuperstringLength - nSubstringLength; ++nSubstringPos) { if (_strnicmp(szString + nSubstringPos, szSubstring, nSubstringLength) == 0) { return szString + nSubstringPos; } } return NULL; } bool CheckForStreamingDependencyLoop(const char* szFilenameDependancy) const; /// LOD support for touch bending vegetation void InitializeSkinnedChunk(); void FillClothData(CMesh& mesh); } _ALIGN(8); ////////////////////////////////////////////////////////////////////////// // Wrapper around CStatObj that allow rendering of static object with specified parameters. ////////////////////////////////////////////////////////////////////////// class CStatObjWrapper : public CStatObj { virtual void Render(const SRendParams& rParams, const SRenderingPassInfo& passInfo); private: // Reference Static Object this wrapper was created for. CStatObj* m_pReference; }; ////////////////////////////////////////////////////////////////////////// inline void InitializeSubObject(IStatObj::SSubObject& so) { so.localTM.SetIdentity(); so.name = ""; so.properties = ""; so.nType = STATIC_SUB_OBJECT_MESH; so.pWeights = 0; so.pFoliage = 0; so.nParent = -1; so.tm.SetIdentity(); so.bIdentityMatrix = true; so.bHidden = false; so.helperSize = Vec3(0, 0, 0); so.pStatObj = 0; so.bShadowProxy = 0; } #endif // CRYINCLUDE_CRY3DENGINE_STATOBJ_H