//////////////////////////////////////////////////////////////////////////// // // Crytek Engine Source File. // Copyright (C), Crytek Studios, 2002. // ------------------------------------------------------------------------- // File name: statobjman.cpp // Version: v1.00 // Created: 28/5/2001 by Vladimir Kajalin // Compilers: Visual Studio.NET // Description: objects container, streaming, common part for indoor and outdoor sectors // ------------------------------------------------------------------------- // History: // //////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "StatObj.h" #include "objman.h" #include "visareas.h" #include "terrain_sector.h" #include "cbuffer.h" #include "3DEngine.h" #include "meshidx.h" #include "watervolumes.h" #include "brush.h" #include "LMCompStructures.h" void CBasicArea::SerializeArea(bool bSave) { char szFileName[256]=""; sprintf(szFileName,"visarea_objects_%.1f_%.1f_%.1f_%.1f.cache", m_vBoxMin.x, m_vBoxMin.y, m_vBoxMax.x, m_vBoxMax.y); FILE * f = GetPak()->FOpen(Get3DEngine()->GetFilePath(szFileName), bSave ? "wb" : "rb"); if(!f) return; if(bSave) { for(int i=0; iGetEntityRenderType(); if(eType == eERType_Brush || eType == eERType_Vegetation) { GetPak()->FWrite(&eType,sizeof(eType),1,f); // if(m_lstEntities[STATIC_ENTITIES].GetAt(i)->GetEntityRS()) { m_lstEntities[STATIC_ENTITIES].GetAt(i)->m_pVisArea = 0; m_lstEntities[STATIC_ENTITIES].GetAt(i)->m_pSector = 0; } m_lstEntities[STATIC_ENTITIES].GetAt(i)->Dephysicalize(); m_lstEntities[STATIC_ENTITIES].GetAt(i)->Dematerialize(); m_lstEntities[STATIC_ENTITIES].GetAt(i)->Serialize(bSave,GetPak(),f); } } m_lstEntities[STATIC_ENTITIES].Reset(); } else { assert(m_lstEntities[STATIC_ENTITIES].Count()==0); m_lstEntities[STATIC_ENTITIES].Reset(); m_eSStatus = eSStatus_Ready; while(1) { EERType eType = eERType_Unknown; if(GetPak()->FRead(&eType,sizeof(eType),1,f)!=1) break; IEntityRender * pEntityRender = 0; if(eType == eERType_Brush) pEntityRender = new CBrush(); else if(eType == eERType_Vegetation) pEntityRender = new CStatObjInst(); if(pEntityRender) { pEntityRender->Serialize(bSave,GetPak(),f); pEntityRender->GetEntityRS() = new IEntityRenderState; pEntityRender->Physicalize(); Get3DEngine()->RegisterEntity(pEntityRender); } } } GetPak()->FClose(f); } void CBasicArea::UnmakeAreaBrush() { for( int i=0; im_dwRndFlags &= ~ERF_MERGED; assert(!(pEntityRender->m_dwRndFlags & ERF_MERGED)); } m_lstAreaBrush.Clear(); } void CBasicArea::DrawEntities( int nFogVolumeID, int nDLightMask, bool bLMapGeneration, const CCamera & EntViewCamera, Vec3d * pvAmbColor, Vec3d * pvDynAmbColor, VolumeInfo * pFogVolume, bool bNotAllInFrustum, float fSectorMinDist, CObjManager * pObjManager, bool bAllowBrushMerging, char*fake, uint nStatics) { FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled ); if(!GetCVars()->e_objects) return; if(GetCVars()->e_stream_areas && GetCVars()->e_stream_for_visuals && CStatObj::m_fStreamingTimePerFrameGetAsyncCurTime(); SerializeArea(false); CStatObj::m_fStreamingTimePerFrame += GetTimer()->GetAsyncCurTime(); } } // apply zoom factor fSectorMinDist *= pObjManager->m_fZoomFactor; // make lmask for vegetations int nDLightMaskNoSun = nDLightMask; list2 * pSources = ((C3DEngine*)m_p3DEngine)->GetDynamicLightSources(); for(int i=0; iCount(); i++) { CDLight * pDynLight = pSources->Get(i); assert(pDynLight->m_Id == i || pDynLight->m_Id == -1); if(pDynLight->m_Flags & DLF_SUN) { nDLightMaskNoSun &= ~(1<m_Id); break; } } if(nStatics && m_StaticEntitiesSorted && GetCVars()->e_optimized_render_object && !bLMapGeneration && pObjManager->m_fZoomFactor >= 0.99f) { // render statics compiled const Vec3d vCamPos = EntViewCamera.GetPos(); const Plane PlaneR = *EntViewCamera.GetFrustumPlane(FR_PLANE_RIGHT); const Plane PlaneL = *EntViewCamera.GetFrustumPlane(FR_PLANE_LEFT); static list2 TmpEntList; TmpEntList.Clear(); list2 & SrcEntList = m_lstEntities[STATIC_ENTITIES]; if(GetCVars()->e_vegetation) { // fill simple vegetations // FRAME_PROFILER( "*fill simple vegetations", GetSystem(), PROFILE_3DENGINE ); for( int i=0; i= inf.m_fWSMaxViewDist) break; // check max view distance sq const Vec3d vCamPos = EntViewCamera.GetPos(); const float dx = vCamPos.x-inf.m_vWSCenter.x; const float dy = vCamPos.y-inf.m_vWSCenter.y; const float fEntDistanceSQ = (dx*dx+dy*dy); // must be 2d for sprites if(fEntDistanceSQ > inf.m_fWSMaxViewDistSQ) continue; // early sphere test agains left and right camera planes if( bNotAllInFrustum && PlaneR.DistFromPlane(inf.m_vWSCenter) > inf.m_fWSRadius || PlaneR.DistFromPlane(inf.m_vWSCenter) > inf.m_fWSRadius ) continue; // get view distance inf.m_fEntDistance = cry_sqrtf(fEntDistanceSQ); assert(inf.m_fEntDistance>=0 && _finite(inf.m_fEntDistance)); assert(inf.m_fEntDistance <= inf.m_fWSMaxViewDist); TmpEntList.Add(&inf); } // render simple vegetations // FRAME_PROFILER( "*render simple vegetations", GetSystem(), PROFILE_3DENGINE ); for( int i=0; im_pEntityRender; if (i+1 < TmpEntList.Count()) { // prefech next element IEntityRender * pNext = TmpEntList.GetAt(i+1)->m_pEntityRender; cryPrefetchT0SSE(pNext); } assert(fSectorMinDist < pEntityRender->m_fWSMaxViewDist); pObjManager->RenderObjectVegetationNonCastersNoFogVolume( pEntityRender, nDLightMaskNoSun, EntViewCamera, bNotAllInFrustum, pEntityRender->m_fWSMaxViewDist, TmpEntList.GetAt(i)); } } TmpEntList.Clear(); if(GetCVars()->e_vegetation || GetCVars()->e_brushes) { // fill complex objects // FRAME_PROFILER( "*fill complex objects", GetSystem(), PROFILE_3DENGINE ); for( int i=0; i= inf.m_fWSMaxViewDist) break; // check max view distance sq const Vec3d vCamPos = EntViewCamera.GetPos(); const float dx = vCamPos.x-inf.m_vWSCenter.x; const float dy = vCamPos.y-inf.m_vWSCenter.y; const float fEntDistanceSQ = (dx*dx+dy*dy); // must be 2d for sprites if(fEntDistanceSQ > inf.m_fWSMaxViewDistSQ) continue; // early sphere test agains left and right camera planes if( bNotAllInFrustum && PlaneR.DistFromPlane(inf.m_vWSCenter) > inf.m_fWSRadius+TERRAIN_SECTORS_MAX_OVERLAPPING || PlaneR.DistFromPlane(inf.m_vWSCenter) > inf.m_fWSRadius+TERRAIN_SECTORS_MAX_OVERLAPPING ) continue; // get view distance inf.m_fEntDistance = cry_sqrtf(fEntDistanceSQ); assert(inf.m_fEntDistance>=0 && _finite(inf.m_fEntDistance)); assert(inf.m_fEntDistance <= inf.m_fWSMaxViewDist); TmpEntList.Add(&inf); } // render complex objects // FRAME_PROFILER( "*render complex objects", GetSystem(), PROFILE_3DENGINE ); for( int i=0; im_pEntityRender; if (i+1 < TmpEntList.Count()) { // prefech next element IEntityRender * pNext = TmpEntList.GetAt(i+1)->m_pEntityRender; cryPrefetchT0SSE(pNext); } assert(fSectorMinDist < pEntityRender->m_fWSMaxViewDist); pObjManager->RenderObject( pEntityRender, nFogVolumeID, nDLightMask, bLMapGeneration, EntViewCamera, pvAmbColor, pvDynAmbColor, pFogVolume, bNotAllInFrustum, pEntityRender->m_fWSMaxViewDist, TmpEntList.GetAt(i)); } } } else if(nStatics && m_StaticEntitiesSorted && !bLMapGeneration) { #ifdef VEGETATION_MEM_STATS static int64 t0=0,t1=0,t2=0; #endif // VEGETATION_MEM_STATS list2 & EntList = m_lstEntities[STATIC_ENTITIES]; for( int i=0; ipThis) { if(((int64)pNext-(int64)pThis)<=128) t0++; else t1++; } else t2++; } #endif // VEGETATION_MEM_STATS if(fSectorMinDist > pEntityRender->m_fWSMaxViewDist) break; pObjManager->RenderObject( pEntityRender, nFogVolumeID, nDLightMask, bLMapGeneration, EntViewCamera, pvAmbColor, pvDynAmbColor, pFogVolume, bNotAllInFrustum, pEntityRender->m_fWSMaxViewDist); } #ifdef VEGETATION_MEM_STATS static int fr=0; if((GetFrameID()&63)==0 && fr!=GetFrameID()) { fr=GetFrameID(); if(t0+t1+t2) GetLog()->Log( "<128 = %.1f, >128 = %.1f, NEG = %.1f", 0.1f*float((t0*1000/(t0+t1+t2))), 0.1f*float((t1*1000/(t0+t1+t2))), 0.1f*float((t2*1000/(t0+t1+t2)))); } #endif // VEGETATION_MEM_STATS } else if(nStatics || GetCVars()->e_entities) { // render dynamics or statics uncompiled assert(!m_StaticEntitiesSorted || !nStatics); list2 & EntList = m_lstEntities[nStatics]; for( int i=0; im_fWSMaxViewDist = pEntityRender->GetMaxViewDist(); if(fSectorMinDist > pEntityRender->m_fWSMaxViewDist) continue; pObjManager->RenderObject( pEntityRender, nFogVolumeID, nDLightMask, bLMapGeneration, EntViewCamera, pvAmbColor, pvDynAmbColor, pFogVolume, bNotAllInFrustum, pEntityRender->m_fWSMaxViewDist); } } } void CBasicArea::Unload(bool bUnloadOnlyVegetations, const Vec3d & vVegetPos) { if(bUnloadOnlyVegetations) { for(int i=0; iGetEntityRenderType(); if(eType == eERType_Vegetation) { Vec3d vEntPos = m_lstEntities[STATIC_ENTITIES].GetAt(i)->GetPos(); float fDist = (vVegetPos==Vec3d(0,0,0)) ? 0 : GetDist2D(vVegetPos.x,vVegetPos.y,vEntPos.x,vEntPos.y); if(fDist<0.01f) { int nCountBefore = m_lstEntities[STATIC_ENTITIES].Count(); delete m_lstEntities[STATIC_ENTITIES].GetAt(i); // will also remove it from this list assert(m_lstEntities[STATIC_ENTITIES].Count() == (nCountBefore-1)); i--; } } } } else { while(m_lstEntities[STATIC_ENTITIES].Count()) { EERType eType = m_lstEntities[STATIC_ENTITIES].GetAt(0)->GetEntityRenderType(); assert(eType == eERType_Brush || eType == eERType_Vegetation); int nCountBefore = m_lstEntities[STATIC_ENTITIES].Count(); if(eType != eERType_Vegetation) Get3DEngine()->ReleaseObject(m_lstEntities[STATIC_ENTITIES].GetAt(0)->GetEntityStatObj(0)); m_lstEntities[STATIC_ENTITIES].GetAt(0)->SetEntityStatObj(0,0); IEntityRender * pEntityRender = m_lstEntities[STATIC_ENTITIES].GetAt(0); // will also remove it from this list delete pEntityRender; // will also remove it from this list assert(m_lstEntities[STATIC_ENTITIES].Count() == (nCountBefore-1)); } assert(m_lstEntities[STATIC_ENTITIES].Count()==0); m_eSStatus = eSStatus_Unloaded; } UnmakeAreaBrush(); } bool CBasicArea::CheckUnload() { if(CStatObj::m_fStreamingTimePerFrame>=CGF_STREAMING_MAX_TIME_PER_FRAME) return (m_eSStatus == eSStatus_Ready); CStatObj::m_fStreamingTimePerFrame -= GetTimer()->GetAsyncCurTime(); if(m_nLastUsedFrameId < GetFrameID() - 100)// && m_lstEntities[STATIC_ENTITIES].Count()) { // unload Unload(); } CStatObj::m_fStreamingTimePerFrame += GetTimer()->GetAsyncCurTime(); return (m_eSStatus == eSStatus_Ready); } void CBasicArea::CheckPhysicalized() { if(m_eSStatus != eSStatus_Ready) SerializeArea(false); for(int i=0; iCheckPhysicalized(); m_nLastUsedFrameId = GetFrameID(); } void CBasicArea::PreloadResources(Vec3d vPrevPortalPos, float fPrevPortalDistance) { FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE ); int nFrameId = GetFrameID(); for(int nStatic=0; nStatic<2; nStatic++) for( int i=0; iPreloadInstanceResources(vPrevPortalPos, fPrevPortalDistance, 1.f); } } void CBasicArea::UnregisterDynamicEntities() { while(m_lstEntities[DYNAMIC_ENTITIES].Count()) { EERType eType = m_lstEntities[DYNAMIC_ENTITIES].GetAt(0)->GetEntityRenderType(); assert(eType != eERType_Brush && eType != eERType_Vegetation); int nCountBefore = m_lstEntities[DYNAMIC_ENTITIES].Count(); // delete m_lstEntities[DYNAMIC_ENTITIES].GetAt(0); // will also remove it from this list Get3DEngine()->UnRegisterEntity(m_lstEntities[DYNAMIC_ENTITIES].GetAt(0)); assert(m_lstEntities[DYNAMIC_ENTITIES].Count() == (nCountBefore-1)); } assert(m_lstEntities[DYNAMIC_ENTITIES].Count()==0); } int __cdecl CObjManager__Cmp_EntTmpDistance(const void* v1, const void* v2); void CBasicArea::SortStaticInstancesBySize(VolumeInfo * pFogVolume) { // sort lists instances in sector by size ( for rendering speed up ) for( int i=0; iGetEntityRS()->fTmpDistance = -m_lstEntities[STATIC_ENTITIES][i]->GetMaxViewDist(); m_lstEntities[STATIC_ENTITIES][i]->m_fWSMaxViewDist = m_lstEntities[STATIC_ENTITIES][i]->GetMaxViewDist(); } // sort if(m_lstEntities[STATIC_ENTITIES].Count()) qsort(m_lstEntities[STATIC_ENTITIES].GetElements(), m_lstEntities[STATIC_ENTITIES].Count(), sizeof(m_lstEntities[STATIC_ENTITIES][0]), CObjManager__Cmp_EntTmpDistance); m_lstStaticShadowMapCasters.Clear(); for( int i=0; iGetRndFlags()&ERF_CASTSHADOWMAPS) m_lstStaticShadowMapCasters.Add(pEntityRender); } m_lstStatEntInfoVegetNoCastersNoVolFog.Clear(); m_lstStatEntInfoOthers.Clear(); for( int i=0; im_pSector); pEntityRender->GetBBox(vBoxMin,vBoxMax); if(pFogVolume->IntersectBBox(vBoxMin,vBoxMax)) bInFogVolume = true; } if( !(pEntityRender->GetRndFlags() & (ERF_CASTSHADOWMAPS|ERF_CASTSHADOWVOLUME|ERF_RECVSHADOWMAPS|ERF_SELFSHADOW)) && pEntityRender->GetEntityRenderType() == eERType_Vegetation && !bInFogVolume) m_lstStatEntInfoVegetNoCastersNoVolFog.Add(inf); else m_lstStatEntInfoOthers.Add(inf); } m_StaticEntitiesSorted = true; // swap to disk if(GetCVars()->e_stream_areas) SerializeArea(true); } int __cdecl CBasicArea__Cmp_MatChunks(const void* v1, const void* v2) { CMatInfo * pMat1 = (CMatInfo*)v1; CMatInfo * pMat2 = (CMatInfo*)v2; // shader if(pMat1->shaderItem.m_pShader->GetTemplate(-1) > pMat2->shaderItem.m_pShader->GetTemplate(-1)) return 1; else if(pMat1->shaderItem.m_pShader->GetTemplate(-1) < pMat2->shaderItem.m_pShader->GetTemplate(-1)) return -1; // shader resources if(pMat1->shaderItem.m_pShaderResources > pMat2->shaderItem.m_pShaderResources) return 1; else if(pMat1->shaderItem.m_pShaderResources < pMat2->shaderItem.m_pShaderResources) return -1; // lm tex id if(pMat1->m_Id > pMat2->m_Id) return 1; else if(pMat1->m_Id < pMat2->m_Id) return -1; return 0; /* const char * pName1 = ((*(((*(pMat1)).shaderItem).m_pShaderResources)).m_Textures)[0] ? (*(((*(((*(pMat1)).shaderItem).m_pShaderResources)).m_Textures)[0])).m_Name.c_str() : ""; const char * pName2 = ((*(((*(pMat2)).shaderItem).m_pShaderResources)).m_Textures)[0] ? (*(((*(((*(pMat2)).shaderItem).m_pShaderResources)).m_Textures)[0])).m_Name.c_str() : ""; return strcmp(pName1,pName2);*/ } struct LMTexCoord { float s,t; }; void CBasicArea::MakeAreaBrush() { const Vec3d vCamPos = GetViewCamera().GetPos(); int nEntityId=0; int nNextStartId=-1; while(nEntityId=0) { static list2 lstVerts;lstVerts.Clear(); static list2 lstLMTexCoords; lstLMTexCoords.Clear(); static list2 lstIndices; lstIndices.Clear(); static list2 lstIndicesSorted; lstIndicesSorted.Clear(); static list2 lstChunks; lstChunks.Clear(); static list2 lstChunksMerged; lstChunksMerged.Clear(); static list2 lstTangBasises; lstTangBasises.Clear(); Vec3d vBoxMax(-10000,-10000,-10000); Vec3d vBoxMin( 10000, 10000, 10000); int nLMTexId=-1; int nHDRLMTexId=-1; int nLMDirTexId=-1; int nCurVertsNum=0; if(nNextStartId>=0) nEntityId = nNextStartId; nNextStartId=-1; for( ; nEntityIdm_dwRndFlags & ERF_MERGED || pEntityRender->m_dwRndFlags & ERF_CASTSHADOWVOLUME || pEntityRender->m_dwRndFlags & ERF_CASTSHADOWMAPS) continue; // Vec3d vCenter = (pEntityRender->m_vWSBoxMin+pEntityRender->m_vWSBoxMax)*0.5f; // float fEntDistance = GetDist2D( vCamPos.x, vCamPos.y, vCenter.x, vCenter.y ); // if(fEntDistance > pEntityRender->GetMaxViewDist()) // continue; // if(fEntDistance > GetCVars()->e_area_merging_distance) // continue; if(nLMTexId<0) { nLMTexId = pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetColorLerpTex() : 0; nHDRLMTexId = pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetHDRColorLerpTex() : 0; nLMDirTexId = pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetDomDirectionTex() : 0; } else { if(nLMTexId != (pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetColorLerpTex() : 0) || nLMDirTexId != (pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetDomDirectionTex() : 0) || nHDRLMTexId != (pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetHDRColorLerpTex() : 0)) { if(nNextStartId<0) nNextStartId = nEntityId; continue; } } Matrix44 mat; mat.SetIdentity(); mat*=0; IStatObj * pStatObj = pEntityRender->GetEntityStatObj(0,&mat); if(!pStatObj) continue; EERType eType = pEntityRender->GetEntityRenderType(); if(eType == eERType_Vegetation) { Matrix33diag diag = Vec3(pEntityRender->GetScale(),pEntityRender->GetScale(),pEntityRender->GetScale()); //use diag-matrix for scaling mathCalcMatrix(mat, pEntityRender->GetPos(), Vec3d(0,0,0), Vec3d(pEntityRender->GetScale(),pEntityRender->GetScale(),pEntityRender->GetScale()), Cry3DEngineBase::m_CpuFlags); } if(!CBrush::IsMatrixValid(mat)) continue; CLeafBuffer * pLMLB = pEntityRender->GetLightmapTexCoord(0); CLeafBuffer * pLB = pStatObj->GetLeafBuffer(); if(!pLB->m_SecVertCount) continue; if(nCurVertsNum + pLB->m_SecVertCount>65000) break; int nIndCount=0; pLB->GetIndices(&nIndCount); if(nIndCount > GetCVars()->e_area_merging_max_tris_in_input_brush*3) continue; int nInitVertCout = lstVerts.Count(); for(int m=0; mm_pMats->Count(); m++) { CMatInfo newMatInfo = *pLB->m_pMats->Get(m); if(GetCVars()->e_materials) { // Override default material CMatInfo * pCustMat = (CMatInfo *)pEntityRender->GetMaterial(); if (pCustMat) { int nMatId = newMatInfo.m_nCGFMaterialID; if(nMatId<0) continue; if (nMatId == 0) pCustMat = (CMatInfo*)pCustMat; else if (nMatId-1 < pCustMat->GetSubMtlCount()) pCustMat = (CMatInfo*)pCustMat->GetSubMtl(nMatId-1); newMatInfo.shaderItem = pCustMat->shaderItem; } } // copy indices for(int i=newMatInfo.nFirstIndexId; iGetIndices(0)[i]+nInitVertCout); newMatInfo.nFirstIndexId = lstIndices.Count() - newMatInfo.nNumIndices; // copy verts int nPosStride=0; const byte * pPos = pLB->GetPosPtr(nPosStride,0,true); int nTexStride=0; const byte * pTex = pLB->GetUVPtr(nTexStride,0,true); // get tengent basis int nTangStride=0; const byte * pTang = pLB->GetTangentPtr(nTangStride,0,true); int nTnormStride=0; const byte * pTNorm = pLB->GetTNormalPtr(nTnormStride,0,true); int nBNormStride=0; const byte * pBNorm = pLB->GetBinormalPtr(nBNormStride,0,true); int nColorStride=0; const byte * pColor = pLB->GetColorPtr(nColorStride,0,true); // get LM TexCoords int nLMStride=0; const byte * pLMTexCoords = pLMLB ? pLMLB->GetPosPtr(nLMStride,0,true) : 0; for(int v=newMatInfo.nFirstVertId; vGetLightmap(0) ? pEntityRender->GetLightmap(0)->GetColorLerpTex() : 0; if(newMatInfo.nNumIndices) { lstChunks.Add(newMatInfo); } else assert(!newMatInfo.nNumVerts); } nCurVertsNum += pLB->m_SecVertCount; pEntityRender->m_dwRndFlags |= ERF_MERGED; } CBrush * pAreaBrush = 0; if(!lstVerts.Count()) { // make empty brush - no geometry in sector pAreaBrush = new CBrush; m_lstAreaBrush.Add(pAreaBrush); return; } // sort if(lstChunks.Count()) qsort(lstChunks.GetElements(), lstChunks.Count(), sizeof(lstChunks[0]), CBasicArea__Cmp_MatChunks); // merge chunks for(int nChunk=0; nChunkCreateLeafBufferInitialized( lstVerts.GetElements(), lstVerts.Count(), VERTEX_FORMAT_P3F_COL4UB_TEX2F, lstIndices.GetElements(), lstIndices.Count(), R_PRIMV_TRIANGLES, "AreaLB", eBT_Static, lstChunks.Count()); pAreaLB->UpdateTangBuffer(lstTangBasises.GetElements()); for(int i=0; iSetChunk(lstChunks[i].GetShaderItem().m_pShader, lstChunks[i].nFirstVertId, lstChunks[i].nNumVerts, lstChunks[i].nFirstIndexId, lstChunks[i].nNumIndices, i, true); assert(lstChunks[i].GetShaderItem().m_pShaderResources); assert(lstChunks[i].GetShaderItem().m_pShader); pAreaLB->m_pMats->Get(i)->shaderItem = lstChunks[i].GetShaderItem(); pAreaLB->m_pMats->Get(i)->shaderItem.m_pShader->AddRef(); pAreaLB->m_pMats->Get(i)->shaderItem.m_pShaderResources->AddRef(); } // make statobj CStatObj * pAreaStatObj = new CStatObj(); pAreaStatObj->m_nLoadedTrisCount = lstIndices.Count()/3; pAreaStatObj->SetLeafBuffer(pAreaLB); pAreaStatObj->SetBBoxMin(vBoxMin); pAreaStatObj->SetBBoxMax(vBoxMax); pAreaStatObj->RegisterUser(); // make brush pAreaBrush = new CBrush(); // if(m_pAreaBrush == (CBrush*)0x0e968358) // int b=0; Matrix44 mat; mat.SetIdentity(); pAreaBrush->SetEntityStatObj(0,pAreaStatObj,&mat); pAreaBrush->m_vWSBoxMin = vBoxMin; pAreaBrush->m_vWSBoxMax = vBoxMax; pAreaBrush->m_fWSRadius = vBoxMin.GetDistance(vBoxMax)*0.5f; // Make leafbuffer and fill it with texture coordinates if(nLMTexId && (nLMDirTexId || (GetCVars()->e_light_maps_quality==0))) { RenderLMData * pLMData = new RenderLMData(GetRenderer(), nLMTexId, nHDRLMTexId, nLMDirTexId); pAreaBrush->SetLightmap(pLMData, (float*)lstLMTexCoords.GetElements(), lstLMTexCoords.Count(), 0); pLMData->AddRef(); pAreaBrush->SetRndFlags(ERF_USELIGHTMAPS,true); } Get3DEngine()->UnRegisterEntity(pAreaBrush); Get3DEngine()->RegisterEntity(pAreaBrush); // find distance to the camera const Vec3d vCamPos = GetViewCamera().GetPos(); Vec3d vCenter = (pAreaBrush->m_vWSBoxMin+pAreaBrush->m_vWSBoxMax)*0.5f; float fEntDistance = GetDist2D( vCamPos.x, vCamPos.y, vCenter.x, vCenter.y ); assert(fEntDistance>=0); assert(_finite(fEntDistance)); m_lstAreaBrush.Add(pAreaBrush); } } void CBasicArea::FreeAreaBrush(CBrush * pAreaBrush) { if(!pAreaBrush) return; Get3DEngine()->UnRegisterEntity(pAreaBrush); // if(m_pAreaBrush == (CBrush*)0x0e968358) // int b=0; CStatObj * pAreaStatObj = (CStatObj *)pAreaBrush->GetEntityStatObj(0); if(pAreaStatObj) { pAreaBrush->SetEntityStatObj(0,0); pAreaStatObj->UnregisterUser(); CLeafBuffer * pAreaLB = pAreaStatObj->GetLeafBuffer(); pAreaStatObj->SetLeafBuffer(0); GetRenderer()->DeleteLeafBuffer(pAreaLB); delete pAreaStatObj; } delete pAreaBrush; pAreaBrush=0; } CBasicArea::~CBasicArea() { for( int i=0; i>nJump); nJump++) { IEntityRender * pCaster = m_lstEntities[STATIC_ENTITIES][nCurrId]; if(pCaster->m_fWSMaxViewDist>nJump; else nCurrId += nCount>>nJump; } return min(nCurrId+2,m_lstEntities[STATIC_ENTITIES].Count()); }