bool CAreaManager::QueryAreas(EntityId const nEntityID, Vec3 const& rPos, SAreaManagerResult *pResults, int nMaxResults, int& rNumResults) { rNumResults = 0; if (pResults) { // Make sure the area grid is recompiled, if needed, before accessing it UpdateDirtyAreas(); uint32 numAreas = 0; TAreaPointers const& rAreasAtPos(m_areaGrid.GetAreas(rPos)); TAreaPointers::const_iterator IterAreas(rAreasAtPos.begin()); TAreaPointers::const_iterator const IterAreasEnd(rAreasAtPos.end()); for (; IterAreas != IterAreasEnd; ++IterAreas) { CArea* const pArea = *IterAreas; #if defined(DEBUG_AREAMANAGER) CheckArea(pArea); #endif // DEBUG_AREAMANAGER // check if Area is hidden IEntity const* const pAreaEntity = m_pEntitySystem->GetEntity(pArea->GetEntityID()); if (pAreaEntity && !pAreaEntity->IsHidden()) { Vec3 Closest3d(ZERO); float const fGreatestFadeDistance = pArea->GetGreatestFadeDistance(); // This is optimized internally and might not recalculate but rather retrieve the cached data. float const fDistanceSq = pArea->CalcPointNearDistSq(nEntityID, rPos, Closest3d, false); bool const bIsPointWithin = (pArea->CalcPosType(nEntityID, rPos, false) == AREA_POS_TYPE_2DINSIDE_ZINSIDE); bool const isNear = ((fDistanceSq > 0.0f) && (fDistanceSq < fGreatestFadeDistance*fGreatestFadeDistance)); if (isNear || bIsPointWithin) { // still have room to put it in? if (rNumResults == nMaxResults) return false; // found area that should go into the results pResults[rNumResults].pArea = pArea; pResults[rNumResults].fDistanceSq = fDistanceSq; pResults[rNumResults].vPosOnHull = Closest3d; pResults[rNumResults].bInside = bIsPointWithin; pResults[rNumResults].bNear = isNear; ++rNumResults; } } } return true; } return false; }
void CAreaManager::Update() { FUNCTION_PROFILER(GetISystem(), PROFILE_ENTITY); // Update the area grid data structure. UpdateDirtyAreas(); if (!m_mapEntitiesToUpdate.empty()) { #if defined(INCLUDE_ENTITYSYSTEM_PRODUCTION_CODE) float const debugPosX = 650.0f; float debugPosY = 500.0f; float const fColor[4] = {0.0f, 1.0f, 0.0f, 0.7f}; bool const bDrawDebug = CVar::pDrawAreaDebug->GetIVal() != 0; if (bDrawDebug) { gEnv->pRenderer->Draw2dLabel(debugPosX, debugPosY, 1.35f, fColor, false, "Entities to update: %d\n", static_cast<int>(m_mapEntitiesToUpdate.size())); debugPosY += 12.0f; } #endif // INCLUDE_ENTITYSYSTEM_PRODUCTION_CODE TEntitiesToUpdateMap::iterator Iter(m_mapEntitiesToUpdate.begin()); TEntitiesToUpdateMap::const_iterator const IterEnd(m_mapEntitiesToUpdate.end()); for (; Iter != IterEnd; ++Iter) { assert(Iter->second > 0); --(Iter->second); IEntity const* const pEntity = g_pIEntitySystem->GetEntity(Iter->first); if (pEntity != NULL) { // Add a Z offset of at least 0.11 to be slightly above the offset of 0.1 set through "CShapeObject::GetShapeZOffset". Vec3 const oPos = pEntity->GetWorldPos() + Vec3(0.0f, 0.0f, 0.11f); UpdateEntity(oPos, pEntity); #if defined(INCLUDE_ENTITYSYSTEM_PRODUCTION_CODE) if (bDrawDebug) { gEnv->pRenderer->Draw2dLabel(debugPosX + 10.0f, debugPosY, 1.35f, fColor, false, "Entity: %d (%s) Pos: (%.2f, %.2f, %.2f)\n", Iter->first, pEntity ? pEntity->GetName() : "NULL", oPos.x, oPos.y, oPos.z); debugPosY += 12.0f; } #endif // INCLUDE_ENTITYSYSTEM_PRODUCTION_CODE } } m_mapEntitiesToUpdate.erase_if(IsDoneUpdating); } }
bool CAreaManager::QueryAudioAreas(Vec3 const& rPos, SAudioAreaInfo *pResults, size_t const nMaxResults, size_t& rNumResults) { rNumResults = 0; if (pResults != NULL) { // Make sure the area grid is recompiled, if needed, before accessing it UpdateDirtyAreas(); uint32 numAreas = 0; TAreaPointers const& rAreasAtPos(m_areaGrid.GetAreas(rPos)); TAreaPointers::const_iterator IterAreas(rAreasAtPos.begin()); TAreaPointers::const_iterator const IterAreasEnd(rAreasAtPos.end()); for (; IterAreas != IterAreasEnd; ++IterAreas) { CArea* const pArea = *IterAreas; #if defined(DEBUG_AREAMANAGER) if (!stl::find(m_apAreas, pArea)) { CryFatalError("<AreaManager>: area in entity-area-cache not found in overall areas list!"); } #endif // DEBUG_AREAMANAGER // check if Area is hidden IEntity const* const pAreaEntity = m_pEntitySystem->GetEntity(pArea->GetEntityID()); if (pAreaEntity && !pAreaEntity->IsHidden()) { size_t const nAttachedEntities = pArea->GetEntityAmount(); if (nAttachedEntities > 0) { for (size_t iEntity = 0; iEntity < nAttachedEntities; ++iEntity) { IEntity const* const pEntity = gEnv->pEntitySystem->GetEntity(pArea->GetEntityByIdx(iEntity)); if (pEntity != NULL) { IEntityAudioProxy const* const pAudioProxy = (IEntityAudioProxy*)pEntity->GetProxy(ENTITY_PROXY_AUDIO); if (pAudioProxy != NULL) { TAudioEnvironmentID const nEnvironmentID = pAudioProxy->GetEnvironmentID(); float const fEnvironmentFadeDistance = pAudioProxy->GetEnvironmentFadeDistance(); if (nEnvironmentID != INVALID_AUDIO_ENVIRONMENT_ID) { // This is optimized internally and might not recalculate but rather retrieve the cached data. bool const bIsPointWithin = (pArea->CalcPosType(INVALID_ENTITYID, rPos, false) == AREA_POS_TYPE_2DINSIDE_ZINSIDE); float fEnvironmentAmount = 0.0f; if (!bIsPointWithin && (fEnvironmentFadeDistance > 0.0f)) { Vec3 Closest3d(ZERO); float const fDistance = sqrt_tpl(pArea->CalcPointNearDistSq(INVALID_ENTITYID, rPos, Closest3d, false)); if (fDistance <= fEnvironmentFadeDistance) { fEnvironmentAmount = 1.0f - (fDistance/fEnvironmentFadeDistance); } } else { fEnvironmentAmount = 1.0f; } if (fEnvironmentAmount > 0.0f) { // still have room to put it in? if (rNumResults == nMaxResults) return false; // found area that should go into the results pResults[rNumResults].pArea = pArea; pResults[rNumResults].fEnvironmentAmount = fEnvironmentAmount; pResults[rNumResults].nEnvironmentID = nEnvironmentID; pResults[rNumResults].nEnvProvidingEntityID = pEntity->GetId(); ++rNumResults; } } } } } } } } return true; } return false; }