//////////////////////////////////////////////////////////////////////////// // // Crytek Engine Source File. // Copyright (C), Crytek Studios, 2002. // ------------------------------------------------------------------------- // File name: statobjmandraw.cpp // Version: v1.00 // Created: 18/12/2002 by Vladimir Kajalin // Compilers: Visual Studio.NET // Description: Visibility areas // ------------------------------------------------------------------------- // History: // //////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "StatObj.h" #include "objman.h" #include "visareas.h" #include "terrain_sector.h" #include "3dengine.h" #include "cbuffer.h" #include "3dengine.h" #include "IMarkers.h" CVisAreaManager::CVisAreaManager() { m_pCurPortal = m_pCurArea = 0; m_nLoadedSectors = 0; } CVisAreaManager::~CVisAreaManager() { for(int i=0; iGetEntityRS() || GetCVars()->e_portals==3) return true; if(!pEntityRS->GetEntityVisArea()) return IsOutdoorAreasVisible(); return true; } void CVisAreaManager::SetCurAreas(CObjManager * pObjManager) { m_pCurArea = 0; m_pCurPortal = 0; if(!GetCVars()->e_portals) return; // find camera portal id for(int v=0; vm_bActive && m_lstPortals[v]->IsPointInsideVisArea(GetViewCamera().GetOccPos())) { m_pCurPortal = m_lstPortals[v]; break; } // if not inside any portal - try to find area if( !m_pCurPortal ) { int nFoundAreasNum = 0; // find camera area for(int nVolumeId=0; nVolumeIdIsPointInsideVisArea(GetViewCamera().GetOccPos())) { nFoundAreasNum++; m_pCurArea = m_lstVisAreas[nVolumeId]; } } if(nFoundAreasNum>1) // if more than one area found - set cur area to undefined { // todo: try to set joining portal as current m_pCurArea = 0; } } // camera is in outdoors m_lstActiveEntransePortals.Clear(); if(!m_pCurArea && !m_pCurPortal) MakeActiveEntransePortalsList(GetViewCamera(), m_lstActiveEntransePortals, 0, pObjManager); /* if(m_pCurArea) { IVisArea * arrAreas[8]; int nres = m_pCurArea->GetVisAreaConnections(arrAreas, 8); nres=nres; } DefineTrees();*/ if(GetCVars()->e_portals == 4) { if(m_pCurPortal) { IVisArea * arrAreas[64]; int nConnections = m_pCurPortal->GetVisAreaConnections(arrAreas,64); GetLog()->Log("CurPortal = %s, nConnections = %d", m_pCurPortal->m_sName, nConnections); } if(m_pCurArea) { IVisArea * arrAreas[64]; int nConnections = m_pCurArea->GetVisAreaConnections(arrAreas,64); GetLog()->Log("CurArea = %s, nRes = %d", m_pCurArea->m_sName, nConnections); } } } bool CVisAreaManager::IsSkyVisible() { return m_bSkyVisible; } bool CVisAreaManager::IsOutdoorAreasVisible() { if(!m_pCurArea && !m_pCurPortal) return m_bOutdoorVisible=true; // camera not in the areas if(m_pCurPortal && m_pCurPortal->m_lstConnections.Count()==1) return m_bOutdoorVisible=true; // camera is in exit portal if(m_bOutdoorVisible) return true; // exit is visible // note: outdoor camera is no modified in this case return false; } void CVisAreaManager::LoadVisAreaBoxFromXML(XDOM::IXMLDOMDocumentPtr pDoc) { { { // reset only non shape volumes for(int i=0; im_bLoadedAsAreaBox) { delete m_lstVisAreas[i]; m_lstVisAreas.Delete(i); i--; } } for(int i=0; im_bLoadedAsAreaBox) { delete m_lstPortals[i]; m_lstPortals.Delete(i); i--; } } for(int i=0; im_bLoadedAsAreaBox) { delete m_lstOcclAreas[i]; m_lstOcclAreas.Delete(i); i--; } } } XDOM::IXMLDOMNodeListPtr pNodeTagList; XDOM::IXMLDOMNodePtr pNodeTag; pNodeTagList = pDoc->getElementsByTagName("Objects"); if (pNodeTagList) { pNodeTagList->reset(); pNodeTag = pNodeTagList->nextNode(); XDOM::IXMLDOMNodeListPtr pNodeList; pNodeList = pNodeTag->getElementsByTagName("Object"); if (pNodeList) { pNodeList->reset(); XDOM::IXMLDOMNodePtr pNode; while (pNode = pNodeList->nextNode()) { XDOM::IXMLDOMNodePtr pName = pNode->getAttribute("Type"); if (pName) { if (strstr(pName->getText(),"AreaBox")) { XDOM::IXMLDOMNodePtr pAttr0,pAttr1,pAttr2,pAttr3,pAttr4,pAttr5; pAttr0 = pNode->getAttribute("Pos"); pAttr1 = pNode->getAttribute("Width"); pAttr2 = pNode->getAttribute("Length"); pAttr3 = pNode->getAttribute("Height"); pAttr4 = pNode->getAttribute("Name"); if(pAttr0!=0 && pAttr1!=0 && pAttr2!=0 && pAttr3!=0 && pAttr4!=0) { CVisArea * pVolumeInfo = new CVisArea(true); Vec3d vPos = StringToVector(pAttr0->getText()); Vec3d vSize((float)atof(pAttr1->getText()), (float)atof(pAttr2->getText()), (float)atof(pAttr3->getText())); pVolumeInfo->m_vBoxMax = vPos + Vec3d(vSize.x*0.5f, vSize.y*0.5f, vSize.z); pVolumeInfo->m_vBoxMin = vPos - Vec3d(vSize.x*0.5f, vSize.y*0.5f, 0); const Vec3d & min = pVolumeInfo->m_vBoxMin; const Vec3d & max = pVolumeInfo->m_vBoxMax; pVolumeInfo->m_lstShapePoints.Add(Vec3d(min.x,min.y,min.z)); pVolumeInfo->m_lstShapePoints.Add(Vec3d(min.x,max.y,min.z)); pVolumeInfo->m_lstShapePoints.Add(Vec3d(max.x,max.y,min.z)); pVolumeInfo->m_lstShapePoints.Add(Vec3d(max.x,min.y,min.z)); pVolumeInfo->m_fHeight = max.z-min.z; pVolumeInfo->m_vAmbColor = ((C3DEngine*)Get3DEngine())->GetObjManager()->m_vOutdoorAmbientColor; pVolumeInfo->m_vDynAmbColor = Vec3d(0,0,0); strncpy(pVolumeInfo->m_sName, pAttr4->getText(), sizeof(pVolumeInfo->m_sName)); pVolumeInfo->UpdateGeometryBBox(); // add volume to list strlwr(pVolumeInfo->m_sName); if(strstr(pVolumeInfo->m_sName, "portal")) m_lstPortals.Add(pVolumeInfo); else if(strstr(pVolumeInfo->m_sName, "visarea")) m_lstVisAreas.Add(pVolumeInfo); else if(strstr(pVolumeInfo->m_sName, "occlarea")) m_lstOcclAreas.Add(pVolumeInfo); else delete pVolumeInfo; } } } } } } } UpdateConnections(); } void CVisAreaManager::SetAreaFogVolume(CTerrain * pTerrain, CVisArea * pVisArea) { pVisArea->m_nFogVolumeId=0; if(pTerrain) for(int f=0; fm_lstFogVolumes.Count(); f++) { const Vec3d & v1Min = pTerrain->m_lstFogVolumes[f].vBoxMin; const Vec3d & v1Max = pTerrain->m_lstFogVolumes[f].vBoxMax; const Vec3d & v2Min = pVisArea->m_vBoxMin; const Vec3d & v2Max = pVisArea->m_vBoxMax; if(v1Max.x>v2Min.x && v2Max.x>v1Min.x) if(v1Max.y>v2Min.y && v2Max.y>v1Min.y) if(v1Max.z>v2Min.z && v2Max.z>v1Min.z) if(!pTerrain->m_lstFogVolumes[f].bOcean) { Vec3d arrVerts3d[8] = { Vec3d(v1Min.x,v1Min.y,v1Min.z), Vec3d(v1Min.x,v1Max.y,v1Min.z), Vec3d(v1Max.x,v1Min.y,v1Min.z), Vec3d(v1Max.x,v1Max.y,v1Min.z), Vec3d(v1Min.x,v1Min.y,v1Max.z), Vec3d(v1Min.x,v1Max.y,v1Max.z), Vec3d(v1Max.x,v1Min.y,v1Max.z), Vec3d(v1Max.x,v1Max.y,v1Max.z) }; bool bIntersect = false; for(int i=0; i<8; i++) if(pVisArea->IsPointInsideVisArea(arrVerts3d[i])) { bIntersect = true; break; } if(!bIntersect) if(pVisArea->IsPointInsideVisArea((v1Min+v1Max)*0.5f)) bIntersect = true; if(!bIntersect) { for(int i=0; im_lstShapePoints.Count(); i++) if(pTerrain->m_lstFogVolumes[f].InsideBBox(pVisArea->m_lstShapePoints[i])) { bIntersect = true; break; } } if(!bIntersect) { Vec3d vCenter = (pVisArea->m_vBoxMin+pVisArea->m_vBoxMax)*0.5f; if(pTerrain->m_lstFogVolumes[f].InsideBBox(vCenter)) bIntersect = true; } if(bIntersect) { int nFogId = pVisArea->m_nFogVolumeId = pTerrain->m_lstFogVolumes[f].nRendererVolumeID; pTerrain->m_lstFogVolumes[f].bIndoorOnly = true; pTerrain->UnregisterFogVolumeFromOutdoor(&pTerrain->m_lstFogVolumes[f]); break; } } } } void CVisAreaManager::SetupFogVolumes(CTerrain * pTerrain) { if(pTerrain) for(int f=0; fm_lstFogVolumes.Count(); f++) pTerrain->m_lstFogVolumes[f].bIndoorOnly = false; // set fog volumes for(int p=0; pm_lstConnections.Count(); p++) { CVisArea * pPortal = m_pCurArea->m_lstConnections[p]; float fError = pPortal->IsPortalValid() ? 1.f : int(GetTimer()->GetCurrTime()*8)&1; GetRenderer()->SetMaterialColor(fError,fError*(pPortal->m_lstConnections.Count()<2),0,0.25f); GetRenderer()->Draw3dBBox(pPortal->m_vBoxMin, pPortal->m_vBoxMax, DPRIM_SOLID_BOX); GetRenderer()->DrawLabel((pPortal->m_vBoxMin+ pPortal->m_vBoxMax)*0.5f, 2,pPortal->m_sName); } } else*/ { // debug draw areas GetRenderer()->SetMaterialColor(0,1,0,0.25f); for(int v=0; vDraw3dBBox(m_lstVisAreas[v]->m_vBoxMin, m_lstVisAreas[v]->m_vBoxMax, DPRIM_SOLID_BOX); GetRenderer()->DrawLabelEx((m_lstVisAreas[v]->m_vBoxMin+ m_lstVisAreas[v]->m_vBoxMax)*0.5f, 1,(float*)&Vec3d(1,1,1),0,1,m_lstVisAreas[v]->m_sName); GetRenderer()->SetMaterialColor(0,1,0,0.25f); GetRenderer()->Draw3dBBox(m_lstVisAreas[v]->m_vGeomBoxMin, m_lstVisAreas[v]->m_vGeomBoxMax); } // debug draw portals for(int v=0; vIsPortalValid() ? 1.f : int(GetTimer()->GetCurrTime()*8)&1; GetRenderer()->SetMaterialColor(fError,fError*(m_lstPortals[v]->m_lstConnections.Count()<2),0,0.25f); GetRenderer()->Draw3dBBox(m_lstPortals[v]->m_vBoxMin, m_lstPortals[v]->m_vBoxMax, DPRIM_SOLID_BOX); GetRenderer()->DrawLabelEx((m_lstPortals[v]->m_vBoxMin+ m_lstPortals[v]->m_vBoxMax)*0.5f, 1,(float*)&Vec3d(1,1,1),0,1,m_lstPortals[v]->m_sName); CVisArea * pPortal = m_lstPortals[v]; Vec3d vCenter = (pPortal->m_vBoxMin+pPortal->m_vBoxMax)*0.5f; GetRenderer()->Draw3dBBox(vCenter-Vec3d(0.1f,0.1f,0.1f), vCenter+Vec3d(0.1f,0.1f,0.1f)); for(int i=0; im_lstConnections.Count() && i<2; i++) GetRenderer()->Draw3dBBox(vCenter, vCenter+pPortal->m_vConnNormals[i], DPRIM_LINE); GetRenderer()->SetMaterialColor(0,0,1,0.25f); GetRenderer()->Draw3dBBox(pPortal->m_vGeomBoxMin, pPortal->m_vGeomBoxMax); } /* // debug draw area shape GetRenderer()->SetMaterialColor(0,0,1,0.25f); for(int v=0; vm_lstShapePoints.Count(); p++) GetRenderer()->DrawLabel(m_lstVisAreas[v]->m_lstShapePoints[p], 2,"%d", p); for(int v=0; vm_lstShapePoints.Count(); p++) GetRenderer()->DrawLabel(m_lstPortals[v]->m_lstShapePoints[p], 2,"%d", p);*/ } } bool CVisAreaManager::SetEntityArea(IEntityRender* pEntityRS) { assert(pEntityRS); CVisArea ** pVisArea = &pEntityRS->m_pVisArea; Vec3d vEntBMin, vEntBMax; pEntityRS->GetBBox(vEntBMin, vEntBMax); Vec3d vEntCenter = (vEntBMin+vEntBMax)*0.5f; if(pEntityRS->m_dwRndFlags&ERF_DONOTCHECKVIS) { // if CS_FLAG_DRAW_NEAR is set (fps weapon) - use camera position because fps weapon bbox is not correct // temporary solution until weapon bbox will be fixed ICryCharInstance * pChar; if ((pChar = pEntityRS->GetEntityCharacter(1)) && (pChar->GetFlags() & CS_FLAG_DRAW_MODEL) && (pChar->GetFlags() & CS_FLAG_DRAW_NEAR)) vEntCenter = GetViewCamera().GetPos(); else if ((pChar = pEntityRS->GetEntityCharacter(0)) && (pChar->GetFlags() & CS_FLAG_DRAW_MODEL) && (pChar->GetFlags() & CS_FLAG_DRAW_NEAR)) vEntCenter = GetViewCamera().GetPos(); } if (*pVisArea) { // detect if we are still in the same area if ((*pVisArea)->IsPointInsideVisArea(vEntCenter)) return true; UnRegisterEntity(pEntityRS); } *pVisArea = 0; int nStatic = (pEntityRS->GetEntityRenderType() != eERType_Unknown); // find portal containing object center for(int v=0; vIsPointInsideVisArea(vEntCenter)) { *pVisArea = m_lstPortals[v]; if(m_lstPortals[v]->m_lstEntities[nStatic].Find(pEntityRS)<0) m_lstPortals[v]->m_lstEntities[nStatic].Add(pEntityRS); break; } } if(!(*pVisArea)) // if portal not found - find volume for(int v=0; vIsPointInsideVisArea(vEntCenter)) { *pVisArea = m_lstVisAreas[v]; if(m_lstVisAreas[v]->m_lstEntities[nStatic].Find(pEntityRS)<0) m_lstVisAreas[v]->m_lstEntities[nStatic].Add(pEntityRS); break; } } /*if(0&&!(*pVisArea)) { // if still not found - reduce requirements and detect box intersection for(int v=0; vm_vBoxMin; const Vec3d & v2Max = m_lstPortals[v]->m_vBoxMax; if(vEntBMax.x>v2Min.x && v2Max.x>vEntBMin.x) if(vEntBMax.y>v2Min.y && v2Max.y>vEntBMin.y) if(vEntBMax.z>v2Min.z && v2Max.z>vEntBMin.z) { *pVisArea = m_lstPortals[v]; if(m_lstPortals[v]->m_lstEntities[nStatic].Find(pEntityRS)<0) m_lstPortals[v]->m_lstEntities[nStatic].Add(pEntityRS); break; } } }*/ if(nStatic && *pVisArea) // update bbox of exit portal // if((*pVisArea)->m_lstConnections.Count()==1) if((*pVisArea)->IsPortal()) (*pVisArea)->UpdateGeometryBBox(); return (*pVisArea) != 0; } bool CVisAreaManager::UnRegisterEntity(IEntityRender* pEntityRS) { assert(pEntityRS); bool bFound = false; int nStatic = (pEntityRS->GetEntityRenderType() != eERType_Unknown); // unregister in volumes if(pEntityRS->m_pVisArea) bFound |= pEntityRS->m_pVisArea->m_lstEntities[nStatic].Delete(pEntityRS); pEntityRS->m_pVisArea = 0; /* #ifdef _DEBUG { // find lost registrations for(int i=0; im_lstEntities[nStatic].Find(pEntityRS)>=0) { m_lstVisAreas[i]->m_lstEntities[nStatic].Delete(pEntityRS); assert(0); } } for(int i=0; im_lstEntities[nStatic].Find(pEntityRS)>=0) { m_lstPortals[i]->m_lstEntities[nStatic].Delete(pEntityRS); assert(0); } } } #endif */ return bFound; } void CVisAreaManager::Render(CObjManager * pObjManager) { FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE ); if(!pObjManager->m_nRenderStackLevel) { m_bOutdoorVisible = false; m_bSkyVisible = false; } m_lstOutdoorPortalCameras.Clear(); SetCurAreas(pObjManager); CCamera camRoot = GetViewCamera(); camRoot.m_ScissorInfo.x1 = 0; camRoot.m_ScissorInfo.y1 = 0; camRoot.m_ScissorInfo.x2 = GetRenderer()->GetWidth(); // todo: use values from camera camRoot.m_ScissorInfo.y2 = GetRenderer()->GetHeight(); if(GetCVars()->e_portals==3) { // draw everything for debug for(int i=0; im_vBoxMin,m_lstVisAreas[i]->m_vBoxMax) )) m_lstVisAreas[i]->DrawVolume(pObjManager, 0, camRoot, 0, m_pCurPortal, &m_bOutdoorVisible, &m_lstOutdoorPortalCameras, &m_bSkyVisible); for(int i=0; im_vBoxMin,m_lstPortals[i]->m_vBoxMax) )) m_lstPortals[i]->DrawVolume(pObjManager, 0, camRoot, 0, m_pCurPortal, &m_bOutdoorVisible, &m_lstOutdoorPortalCameras, &m_bSkyVisible); } else { if(pObjManager->m_nRenderStackLevel) { // use another starting point for reflections CVisArea * pVisArea = (CVisArea *)GetVisAreaFromPos(camRoot.GetOccPos()); if(pVisArea) pVisArea->DrawVolume(pObjManager, 3, camRoot, 0, m_pCurPortal, &m_bOutdoorVisible, &m_lstOutdoorPortalCameras, &m_bSkyVisible); } else if(m_pCurArea) { // camera inside some sector m_pCurArea->DrawVolume(pObjManager, 6, camRoot, 0, m_pCurPortal, &m_bOutdoorVisible, &m_lstOutdoorPortalCameras, &m_bSkyVisible); for(int i=0; iDrawVolume(pObjManager, i==0 ? 5 : 1, m_lstOutdoorPortalCameras.Count() ? m_lstOutdoorPortalCameras[0] : camRoot, 0, m_pCurPortal, 0, 0, 0); } // make one final camera /* while(m_lstOutdoorPortalCameras.Count()>1) { MergeCameras(m_lstOutdoorPortalCameras[0], m_lstOutdoorPortalCameras[1]); m_lstOutdoorPortalCameras.Delete(1); }*/ if(m_lstOutdoorPortalCameras.Count()>1) m_lstOutdoorPortalCameras.Clear(); // use default camera if more than two exits found // reset scissor if skybox is visible also thru skyboxonly portal if(m_bSkyVisible && m_lstOutdoorPortalCameras.Count()==1) m_lstOutdoorPortalCameras[0].m_ScissorInfo.x1 = m_lstOutdoorPortalCameras[0].m_ScissorInfo.x2 = m_lstOutdoorPortalCameras[0].m_ScissorInfo.y1 = m_lstOutdoorPortalCameras[0].m_ScissorInfo.y2 = 0; } else if(m_pCurPortal) { // camera inside some portal m_pCurPortal->DrawVolume(pObjManager, 5, camRoot, 0, m_pCurPortal, &m_bOutdoorVisible, &m_lstOutdoorPortalCameras, &m_bSkyVisible); if(m_pCurPortal->m_lstConnections.Count()==1 || m_lstOutdoorPortalCameras.Count()) { // if camera is in exit portal or exit is visible MakeActiveEntransePortalsList(m_lstOutdoorPortalCameras.Count() ? m_lstOutdoorPortalCameras[0] : camRoot, m_lstActiveEntransePortals, m_lstOutdoorPortalCameras.Count() ? (CVisArea*)m_lstOutdoorPortalCameras[0].m_pPortal : m_pCurPortal, pObjManager); for(int i=0; iDrawVolume(pObjManager, i==0 ? 5 : 1, m_lstOutdoorPortalCameras.Count() ? m_lstOutdoorPortalCameras[0] : camRoot, 0, m_pCurPortal, 0, 0, 0); m_lstOutdoorPortalCameras.Clear(); } } else if(m_lstActiveEntransePortals.Count()) { // camera in outdoors - process visible entrance portals for(int i=0; iDrawVolume(pObjManager, 5, camRoot, 0, m_lstActiveEntransePortals[i], &m_bOutdoorVisible, &m_lstOutdoorPortalCameras, &m_bSkyVisible); m_lstActiveEntransePortals.Clear(); // do not recurse to another building since we already processed all potential entrances m_lstOutdoorPortalCameras.Clear(); // use default camera m_bOutdoorVisible=true; } } if(GetCVars()->e_portals==2) PortalsDrawDebug(); } void CVisAreaManager::ActivatePortal(const Vec3d &vPos, bool bActivate, IEntityRender *pEntity) { for(int v=0; vm_vBoxMin-Vec3d(1,1,1), m_lstPortals[v]->m_vBoxMax+Vec3d(1,1,1))) m_lstPortals[v]->m_bActive = bActivate; } /* bool CVisAreaManager::IsEntityInVisibleArea(IEntityRenderState * pRS) { if( pRS && pRS->plstVisAreaId && pRS->plstVisAreaId->Count() ) { list2 * pVisAreas = pRS->plstVisAreaId; for(int n=0; nCount(); n++) if( m_lstVisAreas[pVisAreas->GetAt(n)].m_nVisFrameId==GetFrameID() ) break; if(n==pVisAreas->Count()) return false; // no visible areas } else return false; // entity is not inside return true; } */ bool CVisAreaManager::IsValidVisAreaPointer(CVisArea * pVisArea) { if( m_lstVisAreas.Find(pVisArea)<0 && m_lstPortals.Find(pVisArea)<0 && m_lstOcclAreas.Find(pVisArea)<0 ) return false; return true; } bool CVisAreaManager::DeleteVisArea(CVisArea * pVisArea) { bool bFound = false; if(m_lstVisAreas.Delete(pVisArea) || m_lstPortals.Delete(pVisArea) || m_lstOcclAreas.Delete(pVisArea)) { delete pVisArea; bFound = true; } m_pCurArea = 0; m_pCurPortal = 0; UpdateConnections(); return bFound; } void CVisAreaManager::LoadVisAreaShapeFromXML(XDOM::IXMLDOMDocumentPtr pDoc) { { // reset only shape volumes for(int i=0; im_bLoadedAsAreaBox) { delete m_lstVisAreas[i]; m_lstVisAreas.Delete(i); i--; } } for(int i=0; im_bLoadedAsAreaBox) { delete m_lstPortals[i]; m_lstPortals.Delete(i); i--; } } } // fill list of volumes of shape points XDOM::IXMLDOMNodeListPtr pNodeTagList; XDOM::IXMLDOMNodePtr pNodeTag; pNodeTagList = pDoc->getElementsByTagName("Objects"); if (pNodeTagList) { pNodeTagList->reset(); pNodeTag = pNodeTagList->nextNode(); XDOM::IXMLDOMNodeListPtr pNodeList; pNodeList = pNodeTag->getElementsByTagName("Object"); if (pNodeList) { pNodeList->reset(); XDOM::IXMLDOMNodePtr pNode; while (pNode = pNodeList->nextNode()) { XDOM::IXMLDOMNodePtr pName = pNode->getAttribute("Type"); if (pName) { const char * pType = pName->getText(); if (strstr(pType,"OccluderArea") || strstr(pType,"VisArea") || strstr(pType,"Portal")) { CVisArea * pArea = new CVisArea(false); pArea->m_vBoxMax=SetMinBB(); pArea->m_vBoxMin=SetMaxBB(); // set shader XDOM::IXMLDOMNodePtr pAttr5 = pNode->getAttribute("Name"); if(pAttr5) strcpy(pArea->m_sName, pAttr5->getText()); // set height XDOM::IXMLDOMNodePtr pAttr6 = pNode->getAttribute("Height"); if(pAttr6) pArea->m_fHeight = (float)atof(pAttr6->getText()); // set ambient color XDOM::IXMLDOMNodePtr pAttr7 = pNode->getAttribute("AmbientColor"); if(pAttr7) pArea->m_vAmbColor = StringToVector(pAttr7->getText()); // set dyn ambient color XDOM::IXMLDOMNodePtr pDynAmbClr = pNode->getAttribute("DynAmbientColor"); if(pDynAmbClr) pArea->m_vDynAmbColor = StringToVector(pDynAmbClr->getText()); // set SkyOnly flag XDOM::IXMLDOMNodePtr pAttr8 = pNode->getAttribute("SkyOnly"); if(pAttr8) pArea->m_bSkyOnly = atol(pAttr8->getText())!=0; // set AfectedByOutLights flag XDOM::IXMLDOMNodePtr pAttr9 = pNode->getAttribute("AffectedBySun"); if(pAttr9) pArea->m_bAfectedByOutLights = atol(pAttr9->getText())!=0; // set ViewDistRatio XDOM::IXMLDOMNodePtr pAttr10 = pNode->getAttribute("ViewDistRatio"); if(pAttr10) pArea->m_fViewDistRatio = (float)atof(pAttr10->getText()); // set DoubleSide flag XDOM::IXMLDOMNodePtr pAttr11 = pNode->getAttribute("DoubleSide"); if(pAttr11) pArea->m_bDoubleSide = atol(pAttr11->getText())!=0; // set UseDeepness flag // XDOM::IXMLDOMNodePtr pAttr12 = pNode->getAttribute("UseDeepness"); // if(pAttr12) // pArea->m_bUseDeepness = atol(pAttr12->getText())!=0; // set UseInIndoors flag XDOM::IXMLDOMNodePtr pAttr13 = pNode->getAttribute("UseInIndoors"); if(pAttr13) pArea->m_bUseInIndoors = atol(pAttr13->getText())!=0; // load vertices if(pAttr5!=0 && pAttr6!=0) { strlwr(pArea->m_sName); if(strstr(pType, "OccluderArea")) m_lstOcclAreas.Add(pArea); else if(strstr(pArea->m_sName,"portal") || strstr(pType,"Portal")) m_lstPortals.Add(pArea); else m_lstVisAreas.Add(pArea); XDOM::IXMLDOMNodeListPtr pNodeTagList; XDOM::IXMLDOMNodePtr pNodeTag; pNodeTagList = pNode->getElementsByTagName("Points"); if (pNodeTagList) { pNodeTagList->reset(); pNodeTag = pNodeTagList->nextNode(); XDOM::IXMLDOMNodeListPtr pNodeList; pNodeList = pNodeTag->getElementsByTagName("Point"); if (pNodeList) { pNodeList->reset(); XDOM::IXMLDOMNodePtr pNode; while (pNode = pNodeList->nextNode()) { XDOM::IXMLDOMNodePtr pPos = pNode->getAttribute("Pos"); if (pPos) { Vec3d vPos = StringToVector(pPos->getText()); pArea->m_lstShapePoints.Add(vPos); pArea->m_vBoxMax.CheckMax(vPos); pArea->m_vBoxMin.CheckMin(vPos); pArea->m_vBoxMax.CheckMax(vPos+Vec3d(0,0,pArea->m_fHeight)); pArea->m_vBoxMin.CheckMin(vPos+Vec3d(0,0,pArea->m_fHeight)); } } } pArea->UpdateGeometryBBox(); } } } } } } } // load area boxes to support old way // LoadVisAreaBoxFromXML(pDoc); } void CVisAreaManager::UpdateVisArea(CVisArea * pArea, const Vec3d * pPoints, int nCount, const char * szName, float fHeight, const Vec3d & vAmbientColor, bool bAfectedByOutLights, bool bSkyOnly, CTerrain*pTerrain, const Vec3 & vDynAmbientColor, float fViewDistRatio, bool bDoubleSide, bool bUseDeepness, bool bUseInIndoors) { // on first update there will be nothing to delete, area will be added into list only in this function m_lstPortals.Delete(pArea); m_lstVisAreas.Delete(pArea); m_lstOcclAreas.Delete(pArea); pArea->Update(pPoints, nCount, szName, fHeight, vAmbientColor, bAfectedByOutLights, bSkyOnly, vDynAmbientColor, fViewDistRatio, bDoubleSide, bUseDeepness, bUseInIndoors); strlwr(pArea->m_sName); if(strstr(pArea->m_sName,"portal")) { if(pArea->m_lstConnections.Count()==1) pArea->UpdateGeometryBBox(); m_lstPortals.Add(pArea); } else if(strstr(pArea->m_sName,"visarea")) m_lstVisAreas.Add(pArea); else if(strstr(pArea->m_sName, "occlarea")) m_lstOcclAreas.Add(pArea); UpdateConnections(); SetAreaFogVolume(pTerrain, pArea); } void CVisAreaManager::UpdateConnections() { // Reset connectivity for(int p=0; pm_lstConnections.Clear(); for(int v=0; vm_lstConnections.Clear(); // Init connectivity - check intersection of all areas and portals for(int p=0; pm_sName,"l5")) // int y=0; for(int v=0; vIsPortalIntersectAreaInValidWay(m_lstPortals[p])) { // if bboxes intersect m_lstVisAreas[v]->m_lstConnections.Add(m_lstPortals[p]); m_lstPortals[p]->m_lstConnections.Add(m_lstVisAreas[v]); // set portal direction Vec3d vNormal = m_lstVisAreas[v]->GetConnectionNormal(m_lstPortals[p]); if(m_lstPortals[p]->m_lstConnections.Count()<=2) m_lstPortals[p]->m_vConnNormals[m_lstPortals[p]->m_lstConnections.Count()-1] = vNormal; } } } } void CVisAreaManager::MoveAllEntitiesIntoList(list2 * plstVisAreasEntities, const Vec3d & vBoxMin, const Vec3d & vBoxMax) { for(int p=0; pm_vBoxMin.x < vBoxMax.x && m_lstPortals[p]->m_vBoxMax.x > vBoxMin.x && m_lstPortals[p]->m_vBoxMin.y < vBoxMax.y && m_lstPortals[p]->m_vBoxMax.y > vBoxMin.y ) { plstVisAreasEntities->AddList(m_lstPortals[p]->m_lstEntities[DYNAMIC_ENTITIES]); plstVisAreasEntities->AddList(m_lstPortals[p]->m_lstEntities[STATIC_ENTITIES]); m_lstPortals[p]->m_lstEntities[DYNAMIC_ENTITIES].Clear(); m_lstPortals[p]->m_lstEntities[STATIC_ENTITIES].Clear(); } } for(int v=0; vm_vBoxMin.x < vBoxMax.x && m_lstVisAreas[v]->m_vBoxMax.x > vBoxMin.x && m_lstVisAreas[v]->m_vBoxMin.y < vBoxMax.y && m_lstVisAreas[v]->m_vBoxMax.y > vBoxMin.y ) { plstVisAreasEntities->AddList(m_lstVisAreas[v]->m_lstEntities[DYNAMIC_ENTITIES]); plstVisAreasEntities->AddList(m_lstVisAreas[v]->m_lstEntities[STATIC_ENTITIES]); m_lstVisAreas[v]->m_lstEntities[DYNAMIC_ENTITIES].Clear(); m_lstVisAreas[v]->m_lstEntities[STATIC_ENTITIES].Clear(); } } } IVisArea * CVisAreaManager::GetVisAreaFromPos(const Vec3d &vPos) { // check areas for(int v=0; vIsPointInsideVisArea(vPos)) return m_lstVisAreas[v]; // check portals for(int v=0; vIsPointInsideVisArea(vPos)) return m_lstPortals[v]; return 0; } CVisArea * CVisAreaManager::CreateVisArea() { CVisArea * p = new CVisArea(false); return p; } /* void CVisAreaManager::DefineTrees() { int nTreeId=0; for(int v=0; vm_nTreeId != nTreeId) { m_lstVisAreas[v]->SetTreeId(nTreeId); nTreeId++; } } } */ bool CVisAreaManager::IsEntityVisAreaVisible(IEntityRender * pEnt, bool nCheckNeighbors) { if(pEnt->GetEntityVisArea()) { if(pEnt->m_pVisArea)//->IsPortal()) { // check is lsource area was rendered in prev frame CVisArea * pVisArea = pEnt->m_pVisArea; int nRndFrameId = GetFrameID(); if(abs(pVisArea->m_nRndFrameId - nRndFrameId)>2) { if(!nCheckNeighbors) return false; // this area is not visible // try neibhour areas bool bFound = false; if(pEnt->m_pVisArea->IsPortal()) { CVisArea * pPort = pEnt->m_pVisArea; for(int n=0; nm_lstConnections.Count(); n++) { // loop other sectors CVisArea * pNeibArea = (CVisArea*)pPort->m_lstConnections[n]; if(abs(pNeibArea->m_nRndFrameId - GetFrameID())<=2) { bFound=true; break; } } } else { for(int t=0; !bFound && tm_lstConnections.Count(); t++) { // loop portals CVisArea * pPort = (CVisArea*)pVisArea->m_lstConnections[t]; if(abs(pPort->m_nRndFrameId - GetFrameID())<=2) { bFound=true; break; } for(int n=0; nm_lstConnections.Count(); n++) { // loop other sectors CVisArea * pNeibArea = (CVisArea*)pPort->m_lstConnections[n]; if(abs(pNeibArea->m_nRndFrameId - GetFrameID())<=2) { bFound=true; break; } } } } if(!bFound) return false; return true; } } else return false; // not visible } else if(!IsOutdoorAreasVisible()) return false; return true; } int __cdecl CVisAreaManager__CmpDistToPortal(const void* v1, const void* v2) { CVisArea * p1 = *((CVisArea **)v1); CVisArea * p2 = *((CVisArea **)v2); if(!p1 || !p2) return 0; if(p1->m_fDistance > p2->m_fDistance) return 1; else if(p1->m_fDistance < p2->m_fDistance) return -1; return 0; } void CVisAreaManager::MakeActiveEntransePortalsList(const CCamera & curCamera, list2 & lstActiveEntransePortals, CVisArea * pThisPortal, CObjManager * pObjManager) { lstActiveEntransePortals.Clear(); for(int nPortalId=0; nPortalIdm_lstConnections.Count()==1 && pPortal != pThisPortal && /*pPortal->IsActive() && */!pPortal->m_bSkyOnly) { if(curCamera.IsAABBVisibleFast( AABB(pPortal->m_vGeomBoxMin,pPortal->m_vGeomBoxMax) )) { Vec3d vNormal = pPortal->m_lstConnections[0]->GetConnectionNormal(pPortal); Vec3d vCenter = (pPortal->m_vBoxMin+pPortal->m_vBoxMax)*0.5f; if(vNormal.Dot(vCenter - curCamera.GetPos())<0) continue; /* if(pCurPortal) { vNormal = pCurPortal->m_vConnNormals[0]; if(vNormal.Dot(vCenter - curCamera.GetPos())<0) continue; } */ pPortal->m_fDistance = GetDistance( (pPortal->m_vBoxMin+pPortal->m_vBoxMax)*0.5f, curCamera.GetPos() ); float fZoomFactor = 0.2f+0.8f*(RAD2DEG(curCamera.GetFov())/90.f); float fRadius = (pPortal->m_vBoxMax-pPortal->m_vBoxMin).Length()*0.5f; if(pPortal->m_fDistance > fRadius*pPortal->m_fViewDistRatio/fZoomFactor) continue; // test occlusion by mountains if(pObjManager->IsBoxOccluded( pPortal->m_vGeomBoxMin, pPortal->m_vGeomBoxMax,pPortal->m_fDistance, &pPortal->m_OcclState)) continue; // test occlusion by antiportals if(GetVisAreaManager()->IsOccludedByOcclVolumes(pPortal->m_vGeomBoxMin,pPortal->m_vGeomBoxMax)) continue; lstActiveEntransePortals.Add(pPortal); // if(GetCVars()->e_portals==3) // GetRenderer()->Draw3dBBox(pPortal->m_vGeomBoxMin, pPortal->m_vGeomBoxMax); } } } // sort by distance if(lstActiveEntransePortals.Count()) { qsort(&lstActiveEntransePortals[0], lstActiveEntransePortals.Count(), sizeof(lstActiveEntransePortals[0]), CVisAreaManager__CmpDistToPortal); // m_pCurPortal = lstActiveEntransePortals[0]; } } void CVisAreaManager::MergeCameras(CCamera & cam1, const CCamera & cam2) { assert(0); // under development /* { float fDotLR1 = cam1.GetFrustumPlane(FR_PLANE_LEFT )->n.Dot(cam1.GetFrustumPlane(FR_PLANE_RIGHT)->n); float fDotRL2 = cam2.GetFrustumPlane(FR_PLANE_RIGHT)->n.Dot(cam2.GetFrustumPlane(FR_PLANE_LEFT)->n); int y=0; } */ // left-right float fDotLR = cam1.GetFrustumPlane(FR_PLANE_LEFT )->n.Dot(cam2.GetFrustumPlane(FR_PLANE_RIGHT)->n); float fDotRL = cam1.GetFrustumPlane(FR_PLANE_RIGHT)->n.Dot(cam2.GetFrustumPlane(FR_PLANE_LEFT)->n); if(fabs(fDotLR)n.Dot(cam1.GetFrustumPlane(FR_PLANE_RIGHT)->n); float fDotRL2 = cam2.GetFrustumPlane(FR_PLANE_RIGHT)->n.Dot(cam2.GetFrustumPlane(FR_PLANE_LEFT)->n); int y=0; }*/ /* // top-bottom float fDotTB = cam1.GetFrustumPlane(FR_PLANE_TOP )->n.Dot(cam2.GetFrustumPlane(FR_PLANE_BOTTOM)->n); float fDotBT = cam1.GetFrustumPlane(FR_PLANE_BOTTOM)->n.Dot(cam2.GetFrustumPlane(FR_PLANE_TOP )->n); if(fDotTB>fDotBT) cam1.SetFrustumPlane(FR_PLANE_BOTTOM, *cam2.GetFrustumPlane(FR_PLANE_BOTTOM)); else cam1.SetFrustumPlane(FR_PLANE_TOP, *cam2.GetFrustumPlane(FR_PLANE_TOP)); */ cam1.SetFrustumPlane(FR_PLANE_NEAR, *GetViewCamera().GetFrustumPlane(FR_PLANE_NEAR)); cam1.SetFrustumPlane(FR_PLANE_FAR, *GetViewCamera().GetFrustumPlane(FR_PLANE_FAR)); cam1.SetFrustumPlane(FR_PLANE_TOP, *GetViewCamera().GetFrustumPlane(FR_PLANE_TOP)); cam1.SetFrustumPlane(FR_PLANE_BOTTOM, *GetViewCamera().GetFrustumPlane(FR_PLANE_BOTTOM)); /* if(GetCVars()->e_portals==4) { GetRenderer()->SetMaterialColor(1,1,1,1); GetRenderer()->Draw3dBBox(pVerts[0],pVerts[1],DPRIM_LINE); GetRenderer()->DrawLabel(pVerts[0],2,"0"); GetRenderer()->Draw3dBBox(pVerts[1],pVerts[2],DPRIM_LINE); GetRenderer()->DrawLabel(pVerts[1],2,"1"); GetRenderer()->Draw3dBBox(pVerts[2],pVerts[3],DPRIM_LINE); GetRenderer()->DrawLabel(pVerts[2],2,"2"); GetRenderer()->Draw3dBBox(pVerts[3],pVerts[0],DPRIM_LINE); GetRenderer()->DrawLabel(pVerts[3],2,"3"); }*/ } void CVisAreaManager::DrawOcclusionAreasIntoCBuffer(CCoverageBuffer * pCBuffer) { FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE ); m_lstActiveOcclVolumes.Clear(); m_lstIndoorActiveOcclVolumes.Clear(); if(GetCVars()->e_occlusion_volumes) for(int i=0; im_vBoxMin,pArea->m_vBoxMax))) { Vec3d vPos = (pArea->m_vBoxMin+pArea->m_vBoxMax)*0.5f; float fRadius = (pArea->m_vBoxMin-pArea->m_vBoxMax).GetLength(); float fDist = GetViewCamera().GetPos().GetDistance(vPos); float fZoomFactor = 0.2f+0.8f*(RAD2DEG(GetViewCamera().GetFov())/90.f); if(fDistm_fViewDistRatio/fZoomFactor*0.125f && pArea->m_lstShapePoints.Count()>=2) { // pArea->DrawAreaBoundsIntoCBuffer(pCBuffer); if(!pArea->m_pOcclCamera) pArea->m_pOcclCamera = new CCamera; *pArea->m_pOcclCamera = GetViewCamera(); int nShift = pArea->m_lstShapePoints.Count()>2 && (GetSquaredDistance(pArea->m_lstShapePoints[0], pArea->m_lstShapePoints[1]) m_lstShapePoints[1], pArea->m_lstShapePoints[2])); pArea->m_arrvActiveVerts[0] = pArea->m_lstShapePoints[0+nShift]; pArea->m_arrvActiveVerts[1] = pArea->m_lstShapePoints[0+nShift]+Vec3d(0,0,pArea->m_fHeight); pArea->m_arrvActiveVerts[2] = pArea->m_lstShapePoints[1+nShift]+Vec3d(0,0,pArea->m_fHeight); pArea->m_arrvActiveVerts[3] = pArea->m_lstShapePoints[1+nShift]; Plane plane; plane.CalcPlane(pArea->m_arrvActiveVerts[0], pArea->m_arrvActiveVerts[1], pArea->m_arrvActiveVerts[2]); if(plane.DistFromPlane(GetViewCamera().GetPos())<0) { pArea->m_arrvActiveVerts[3] = pArea->m_lstShapePoints[0+nShift]; pArea->m_arrvActiveVerts[2] = pArea->m_lstShapePoints[0+nShift]+Vec3d(0,0,pArea->m_fHeight); pArea->m_arrvActiveVerts[1] = pArea->m_lstShapePoints[1+nShift]+Vec3d(0,0,pArea->m_fHeight); pArea->m_arrvActiveVerts[0] = pArea->m_lstShapePoints[1+nShift]; } else if(!pArea->m_bDoubleSide) continue; GetRenderer()->SetMaterialColor(1,0,0,1); pArea->UpdatePortalCameraPlanes(*pArea->m_pOcclCamera, pArea->m_arrvActiveVerts, false); // make far plane never clip anything Plane newFarPlane; newFarPlane.CalcPlane(Vec3d(0,1,-1024), Vec3d(0,0,-1024), Vec3d(1,0,-1024)); pArea->m_pOcclCamera->SetFrustumPlane(FR_PLANE_FAR, newFarPlane); m_lstActiveOcclVolumes.Add(pArea); pArea->m_fDistance = fDist; } } } if(m_lstActiveOcclVolumes.Count()) { // sort occluders by distance to the camera qsort(&m_lstActiveOcclVolumes[0], m_lstActiveOcclVolumes.Count(), sizeof(m_lstActiveOcclVolumes[0]), CVisAreaManager__CmpDistToPortal); // remove occluded occluders for(int i=m_lstActiveOcclVolumes.Count()-1; i; i--) { CVisArea * pArea = m_lstActiveOcclVolumes[i]; if(IsOccludedByOcclVolumes(pArea->m_vGeomBoxMin,pArea->m_vGeomBoxMax)) m_lstActiveOcclVolumes.Delete(i); } // put indoor occluders into separate list for(int i=m_lstActiveOcclVolumes.Count()-1; i; i--) { CVisArea * pArea = m_lstActiveOcclVolumes[i]; if(pArea->m_bUseInIndoors) m_lstIndoorActiveOcclVolumes.Add(pArea); } if(GetCVars()->e_portals==4) { // show really active occluders for(int i=0; iSetMaterialColor(0,1,0,1); GetRenderer()->Draw3dBBox(pArea->m_vGeomBoxMin,pArea->m_vGeomBoxMax); } } } } bool CVisAreaManager::IsOccludedByOcclVolumes(Vec3d vBoxMin, Vec3d vBoxMax, bool bCheckOnlyIndoorVolumes) { list2 & rList = bCheckOnlyIndoorVolumes ? m_lstIndoorActiveOcclVolumes : m_lstActiveOcclVolumes; for(int i=0; im_pOcclCamera->IsAABBVisible_hierarchical(AABB(vBoxMin, vBoxMax), &bAllIn) && bAllIn) return true; } return false; } void CVisAreaManager::SortStaticInstancesBySize() { // areas for(int v=0; vSortStaticInstancesBySize(); // portals for(int v=0; vSortStaticInstancesBySize(); } bool CVisAreaManager::PreloadResources() { FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE ); bool bPreloadOutdoor = false; CVisArea * pVisArea = m_pCurArea ? m_pCurArea : m_pCurPortal; if(pVisArea) pVisArea->PreloadVisArea(GetCVars()->e_stream_preload_textures*2, &bPreloadOutdoor, 0, GetViewCamera().GetPos(), 0); else bPreloadOutdoor |= true; // areas // for(int v=0; vPreloadResources(); // portals // for(int v=0; vPreloadResources(); /* CVisArea * pVisArea = m_pCurArea ? m_pCurArea : m_pCurPortal; if(pVisArea) { pVisArea->PreloadResources(); CVisArea * areaArray[8]={0,0,0,0,0,0,0,0}; int nCount = pVisArea->GetVisAreaConnections((IVisArea **)&areaArray,8); for(int n=0; nPreloadResources(); }*/ // GetLog()->Log("CVisAreaManager::PreloadResources: %d", (int)bPreloadOutdoor); return bPreloadOutdoor; } void CVisAreaManager::CheckUnload() { m_nLoadedSectors=0; // areas for(int v=0; vCheckUnload(); // portals for(int v=0; vCheckUnload(); } void CVisAreaManager::GetStreamingStatus(int & nLoadedSectors, int & nTotalSectors) { nLoadedSectors = m_nLoadedSectors; nTotalSectors = m_lstPortals.Count() + m_lstVisAreas.Count(); } void CVisAreaManager::GetMemoryUsage(ICrySizer*pSizer) { // areas for(int v=0; vGetMemoryUsage(pSizer); // portals for(int v=0; vGetMemoryUsage(pSizer); pSizer->AddObject(this,sizeof(*this)); } bool CVisAreaManager::UnRegisterInAllSectors(IEntityRender * pEntityRS) { bool bRes = 0; int nStatic = pEntityRS->IsStatic(); // areas for(int v=0; vm_lstEntities[nStatic].Delete(pEntityRS); // portals for(int v=0; vm_lstEntities[nStatic].Delete(pEntityRS); pEntityRS->m_pVisArea=0; return bRes; } Vec3 CamAngles[6] = { Vec3( 90, -90, 0), //posx Vec3( 90, 90, 0 ), //negx Vec3(180, 180, 0 ), //posy Vec3( 0, 180, 0 ), //negy Vec3( 90, 180, 0 ), //posz Vec3( 90, 0, 0 ) //negz }; void CVisAreaManager::Preceche(CObjManager * pObjManager) { if(!GetCVars()->e_precache_level) return; //-------------------------------------------------------------------------------------- //---- PRE-FETCHING OF RENDER-DATA IN INDOORS ---- //-------------------------------------------------------------------------------------- GetRenderer()->EnableSwapBuffers(false); //loop over all sectors and place a light in the middle of the sector for(int v=0; vEF_Query(EFQ_Pointer2FrameID); if(pPtr2FrameID) (*pPtr2FrameID)++; m_nRenderFrameID = GetRenderer()->GetFrameID(); CDLight DynLight; //place camera in the middle of a sector and render sector form //different directions for(int i=0; i<6; i++) { GetRenderer()->BeginFrame(); // Add sun lsource DynLight.m_Origin = (m_lstVisAreas[v]->m_vBoxMin + m_lstVisAreas[v]->m_vBoxMax)*0.5f; DynLight.m_fRadius = 100; DynLight.m_Flags |= DLF_LM; Get3DEngine()->AddDynamicLightSource(DynLight,(IEntityRender*)-1); CCamera cam = GetViewCamera(); cam.SetPos( DynLight.m_Origin ); cam.SetAngle( CamAngles[i] ); cam.SetFov(1.7f); //very wide-opend fov Get3DEngine()->SetCamera(cam); Get3DEngine()->Draw(); GetRenderer()->Update(); } } //-------------------------------------------------------------------------------------- //---- PRE-FETCHING OF RENDER-DATA IN OUTDOORS ---- //-------------------------------------------------------------------------------------- //we search all TagPoints with the label "Cam_PreFetch??" in the level //and store the positions in an array Vec3 CamOutdoorPositions[100]; //array for 100 cam-postionin outdoors () int ValidPosition=0; char TagName[80]; IGame *pGame = GetISystem()->GetIGame(); if (pGame) { for (int cp=0; cp<99; cp++ ) { sprintf(TagName, "Cam_PreFetch%02d", cp); ITagPoint *pTagPoint = pGame->GetTagPointManager()->GetTagPoint( TagName ); if (pTagPoint) { pTagPoint->GetPos( CamOutdoorPositions[ValidPosition] ); ValidPosition++; } } } //loop over all cam-position in the level and render this part of the level //from 6 different directions for(int p=0; pBeginFrame(); CCamera cam = GetViewCamera(); cam.SetPos( CamOutdoorPositions[p] ); cam.SetAngle( CamAngles[i] ); cam.SetFov(1.7f); //very wide-opend fov Get3DEngine()->SetCamera(cam); Get3DEngine()->Draw(); GetRenderer()->Update(); } } GetCVars()->e_sleep = 0; ((C3DEngine*)Get3DEngine())->GetDynamicLightSources()->Clear(); GetRenderer()->EF_ClearLightsList(); ((C3DEngine*)Get3DEngine())->UpdateLightSources(); ((C3DEngine*)Get3DEngine())->PrepareLightSourcesForRendering(); GetRenderer()->EnableSwapBuffers(true); } void CVisAreaManager::GetObjectsAround(Vec3d vExploPos, float fExploRadius, list2 * pEntList) { CVisArea * pVisArea = (CVisArea *)GetVisAreaFromPos(vExploPos); // find static objects around for(int i=0; pVisArea && im_lstEntities[STATIC_ENTITIES].Count(); i++) { IEntityRender * pEntityRender = pVisArea->m_lstEntities[STATIC_ENTITIES][i]; Vec3d vEntBoxMin, vEntBoxMax; pEntityRender->GetBBox(vEntBoxMin, vEntBoxMax); if(Overlap::Sphere_AABB(Sphere(vExploPos,fExploRadius), AABB(vEntBoxMin,vEntBoxMax))) if(pEntList->Find(pEntityRender)<0) pEntList->Add(pEntityRender); } }