diff --git a/rts/ExternalAI/AICallback.cpp b/rts/ExternalAI/AICallback.cpp index 542f55a8dec..9c39400ae5e 100644 --- a/rts/ExternalAI/AICallback.cpp +++ b/rts/ExternalAI/AICallback.cpp @@ -897,9 +897,10 @@ int CAICallback::GetEnemyUnits(int* unitIds, const float3& pos, float radius, int unitIds_max) { verify(); - const std::vector& units = quadField->GetUnitsExact(pos, radius); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius); myAllyTeamId = teamHandler->AllyTeam(team); - return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsEnemyAndInLos); + return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsEnemyAndInLos); } @@ -914,9 +915,10 @@ int CAICallback::GetFriendlyUnits(int* unitIds, const float3& pos, float radius, int unitIds_max) { verify(); - const std::vector& units = quadField->GetUnitsExact(pos, radius); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius); myAllyTeamId = teamHandler->AllyTeam(team); - return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsFriendly); + return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsFriendly); } @@ -930,9 +932,10 @@ int CAICallback::GetNeutralUnits(int* unitIds, int unitIds_max) int CAICallback::GetNeutralUnits(int* unitIds, const float3& pos, float radius, int unitIds_max) { verify(); - const std::vector& units = quadField->GetUnitsExact(pos, radius); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius); myAllyTeamId = teamHandler->AllyTeam(team); - return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsNeutralAndInLosOrRadar); + return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsNeutralAndInLosOrRadar); } @@ -1252,14 +1255,12 @@ int CAICallback::GetFeatures(int* featureIds, int featureIds_sizeMax, const floa int featureIds_size = 0; verify(); - const std::vector& ft = quadField->GetFeaturesExact(pos, radius); + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, pos, radius); const int allyteam = teamHandler->AllyTeam(team); std::vector::const_iterator it; - for (it = ft.begin(); (it != ft.end()) && (featureIds_size < featureIds_sizeMax); ++it) { - const CFeature* f = *it; - assert(f); - + for (const CFeature* f: *qfQuery.features) { if (f->IsInLosForAllyTeam(allyteam)) { // if it is NULL, the caller only wants to know // the number of features diff --git a/rts/ExternalAI/AICheats.cpp b/rts/ExternalAI/AICheats.cpp index fcf325428ce..315e7edae3e 100644 --- a/rts/ExternalAI/AICheats.cpp +++ b/rts/ExternalAI/AICheats.cpp @@ -179,9 +179,10 @@ int CAICheats::GetEnemyUnits(int* unitIds, int unitIds_max) int CAICheats::GetEnemyUnits(int* unitIds, const float3& pos, float radius, int unitIds_max) { - const std::vector& units = quadField->GetUnitsExact(pos, radius); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius); myAllyTeamId = teamHandler->AllyTeam(ai->GetTeamId()); - return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsEnemy); + return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsEnemy); } int CAICheats::GetNeutralUnits(int* unitIds, int unitIds_max) @@ -191,8 +192,9 @@ int CAICheats::GetNeutralUnits(int* unitIds, int unitIds_max) int CAICheats::GetNeutralUnits(int* unitIds, const float3& pos, float radius, int unitIds_max) { - const std::vector& units = quadField->GetUnitsExact(pos, radius); - return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsNeutral); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius); + return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsNeutral); } int CAICheats::GetFeatures(int* features, int max) const { diff --git a/rts/ExternalAI/SSkirmishAICallbackImpl.cpp b/rts/ExternalAI/SSkirmishAICallbackImpl.cpp index 95a90f4d758..4c29611b531 100644 --- a/rts/ExternalAI/SSkirmishAICallbackImpl.cpp +++ b/rts/ExternalAI/SSkirmishAICallbackImpl.cpp @@ -4363,8 +4363,9 @@ EXPORT(int) skirmishAiCallback_getFeatures(int skirmishAIId, int* featureIds, in EXPORT(int) skirmishAiCallback_getFeaturesIn(int skirmishAIId, float* pos_posF3, float radius, int* featureIds, int featureIdsMaxSize) { if (skirmishAiCallback_Cheats_isEnabled(skirmishAIId)) { // cheating - const std::vector& fset = quadField->GetFeaturesExact(pos_posF3, radius); - const int featureIdsRealSize = fset.size(); + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, pos_posF3, radius); + const int featureIdsRealSize = qfQuery.features->size(); int featureIdsSize = featureIdsRealSize; @@ -4373,8 +4374,7 @@ EXPORT(int) skirmishAiCallback_getFeaturesIn(int skirmishAIId, float* pos_posF3, size_t f = 0; - for (auto it = fset.cbegin(); it != fset.cend() && f < featureIdsSize; ++it) { - const CFeature* feature = *it; + for (const CFeature* feature: *qfQuery.features) { assert(feature != nullptr); featureIds[f++] = feature->id; diff --git a/rts/Game/GameHelper.cpp b/rts/Game/GameHelper.cpp index cf36dcf3b19..24f865c77cb 100644 --- a/rts/Game/GameHelper.cpp +++ b/rts/Game/GameHelper.cpp @@ -351,14 +351,15 @@ void CGameHelper::Explosion(const CExplosionParams& params) { template static inline void QueryUnits(TFilter filter, TQuery& query) { - const auto& quads = quadField->GetQuads(query.pos, query.radius); + QuadFieldQuery qfQuery; + quadField->GetQuads(qfQuery, query.pos, query.radius); const int tempNum = gs->GetTempNum(); for (int t = 0; t < teamHandler->ActiveAllyTeams(); ++t) { //FIXME if (!filter.Team(t)) continue; - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { const auto& allyTeamUnits = quadField->GetQuad(qi).teamUnits[t]; for (CUnit* u: allyTeamUnits) { @@ -645,14 +646,15 @@ void CGameHelper::GenerateWeaponTargets(const CWeapon* weapon, const CUnit* avoi const bool paralyzer = (weapon->damages->paralyzeDamageTime != 0); // copy on purpose since the below calls lua - const std::vector quads = quadField->GetQuads(pos, radius + (aHeight - std::max(0.0f, readMap->GetInitMinHeight())) * heightMod); + QuadFieldQuery qfQuery; + quadField->GetQuads(qfQuery, pos, radius + (aHeight - std::max(0.0f, readMap->GetInitMinHeight())) * heightMod); const int tempNum = gs->GetTempNum(); for (int t = 0; t < teamHandler->ActiveAllyTeams(); ++t) { if (teamHandler->Ally(owner->allyteam, t)) continue; - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { const std::vector& allyTeamUnits = quadField->GetQuad(qi).teamUnits[t]; for (CUnit* targetUnit: allyTeamUnits) { @@ -820,10 +822,11 @@ void CGameHelper::GetEnemyUnitsNoLosTest(const float3& pos, float searchRadius, void CGameHelper::BuggerOff(float3 pos, float radius, bool spherical, bool forced, int teamId, CUnit* excludeUnit) { // copy on purpose since BuggerOff can call risky stuff - const std::vector units = quadField->GetUnitsExact(pos, radius + SQUARE_SIZE, spherical); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius + SQUARE_SIZE, spherical); const int allyTeamId = teamHandler->AllyTeam(teamId); - for (CUnit* u: units) { + for (CUnit* u: *qfQuery.units) { if (u == excludeUnit) continue; // don't send BuggerOff commands to enemy units @@ -1074,18 +1077,19 @@ CGameHelper::BuildSquareStatus CGameHelper::TestUnitBuildSquare( if (buildInfo.def->needGeo) { canBuild = BUILDSQUARE_BLOCKED; - const std::vector& features = quadField->GetFeaturesExact(pos, std::max(xsize, zsize) * 6); + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, pos, std::max(xsize, zsize) * 6); const int mindx = xsize * (SQUARE_SIZE >> 1) - (SQUARE_SIZE >> 1); const int mindz = zsize * (SQUARE_SIZE >> 1) - (SQUARE_SIZE >> 1); // look for a nearby geothermal feature if we need one - for (std::vector::const_iterator fi = features.begin(); fi != features.end(); ++fi) { - if (!(*fi)->def->geoThermal) + for (const CFeature* f: *qfQuery.features) { + if (!f->def->geoThermal) continue; - const float dx = math::fabs((*fi)->pos.x - pos.x); - const float dz = math::fabs((*fi)->pos.z - pos.z); + const float dx = math::fabs(f->pos.x - pos.x); + const float dz = math::fabs(f->pos.z - pos.z); if (dx < mindx && dz < mindz) { canBuild = BUILDSQUARE_OPEN; diff --git a/rts/Game/SelectedUnitsAI.cpp b/rts/Game/SelectedUnitsAI.cpp index 82b2458e354..9e8b0cf3c0a 100644 --- a/rts/Game/SelectedUnitsAI.cpp +++ b/rts/Game/SelectedUnitsAI.cpp @@ -602,16 +602,17 @@ void CSelectedUnitsHandlerAI::SelectCircleUnits( if (p == NULL) return; - const std::vector& tmpUnits = quadField->GetUnitsExact(pos, radius, false); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius, false); const float radiusSqr = radius * radius; - const unsigned int count = tmpUnits.size(); + const unsigned int count = qfQuery.units->size(); const int allyTeam = teamHandler->AllyTeam(p->team); units.reserve(count); for (unsigned int i = 0; i < count; i++) { - CUnit* unit = tmpUnits[i]; + CUnit* unit = (*qfQuery.units)[i]; if (unit == NULL) continue; @@ -650,15 +651,16 @@ void CSelectedUnitsHandlerAI::SelectRectangleUnits( const float3 mins(std::min(pos0.x, pos1.x), 0.0f, std::min(pos0.z, pos1.z)); const float3 maxs(std::max(pos0.x, pos1.x), 0.0f, std::max(pos0.z, pos1.z)); - const std::vector& tmpUnits = quadField->GetUnitsExact(mins, maxs); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, mins, maxs); - const unsigned int count = tmpUnits.size(); + const unsigned int count = qfQuery.units->size(); const int allyTeam = teamHandler->AllyTeam(p->team); units.reserve(count); for (unsigned int i = 0; i < count; i++) { - const CUnit* unit = tmpUnits[i]; + const CUnit* unit = (*qfQuery.units)[i]; if (unit == NULL) continue; diff --git a/rts/Game/TraceRay.cpp b/rts/Game/TraceRay.cpp index 337c5fb4c21..d7908f4a901 100644 --- a/rts/Game/TraceRay.cpp +++ b/rts/Game/TraceRay.cpp @@ -202,7 +202,8 @@ float TraceRay( if (scanForFeatures || scanForAnyUnits) { CollisionQuery cq; - const auto& quads = quadField->GetQuadsOnRay(pos, dir, traceLength); + QuadFieldQuery qfQuery; + quadField->GetQuadsOnRay(qfQuery, pos, dir, traceLength); // locally point somewhere non-NULL; we cannot pass hitColQuery // to DetectHit directly because each call resets it internally @@ -211,7 +212,7 @@ float TraceRay( // feature intersection if (scanForFeatures) { - for (const int quadIdx: quads) { + for (const int quadIdx: *qfQuery.quads) { const CQuadField::Quad& quad = quadField->GetQuad(quadIdx); for (CFeature* f: quad.features) { @@ -239,7 +240,7 @@ float TraceRay( // unit intersection if (scanForAnyUnits) { - for (const int quadIdx: quads) { + for (const int quadIdx: *qfQuery.quads) { const CQuadField::Quad& quad = quadField->GetQuad(quadIdx); for (CUnit* u: quad.units) { @@ -307,9 +308,10 @@ void TraceRayShields( ) { CollisionQuery cq; - const auto& quads = quadField->GetQuadsOnRay(start, dir, length); + QuadFieldQuery qfQuery; + quadField->GetQuadsOnRay(qfQuery, start, dir, length); - for (const int quadIdx: quads) { + for (const int quadIdx: *qfQuery.quads) { const CQuadField::Quad& quad = quadField->GetQuad(quadIdx); for (CPlasmaRepulser* r: quad.repulsers) { @@ -372,9 +374,10 @@ float GuiTraceRay( CollisionQuery cq; - const auto& quads = quadField->GetQuadsOnRay(start, dir, length); + QuadFieldQuery qfQuery; + quadField->GetQuadsOnRay(qfQuery, start, dir, length); - for (const int quadIdx: quads) { + for (const int quadIdx: *qfQuery.quads) { const CQuadField::Quad& quad = quadField->GetQuad(quadIdx); // Unit Intersection @@ -475,16 +478,17 @@ bool TestCone( int traceFlags, CUnit* owner ) { - const auto& quads = quadField->GetQuadsOnRay(from, dir, length); + QuadFieldQuery qfQuery; + quadField->GetQuadsOnRay(qfQuery, from, dir, length); - if (quads.empty()) + if (qfQuery.quads->empty()) return true; const bool scanForAllies = ((traceFlags & Collision::NOFRIENDLIES) == 0); const bool scanForNeutrals = ((traceFlags & Collision::NONEUTRALS ) == 0); const bool scanForFeatures = ((traceFlags & Collision::NOFEATURES ) == 0); - for (const int quadIdx: quads) { + for (const int quadIdx: *qfQuery.quads) { const CQuadField::Quad& quad = quadField->GetQuad(quadIdx); if (scanForAllies) { @@ -540,16 +544,17 @@ bool TestTrajectoryCone( int traceFlags, CUnit* owner ) { - const auto& quads = quadField->GetQuadsOnRay(from, dir, length); + QuadFieldQuery qfQuery; + quadField->GetQuadsOnRay(qfQuery, from, dir, length); - if (quads.empty()) + if (qfQuery.quads->empty()) return true; const bool scanForAllies = ((traceFlags & Collision::NOFRIENDLIES) == 0); const bool scanForNeutrals = ((traceFlags & Collision::NONEUTRALS ) == 0); const bool scanForFeatures = ((traceFlags & Collision::NOFEATURES ) == 0); - for (const int quadIdx: quads) { + for (const int quadIdx: *qfQuery.quads) { const CQuadField::Quad& quad = quadField->GetQuad(quadIdx); // friendly units in this quad diff --git a/rts/Game/WaitCommandsAI.cpp b/rts/Game/WaitCommandsAI.cpp index 0d9d36ff3cf..727486eed0d 100644 --- a/rts/Game/WaitCommandsAI.cpp +++ b/rts/Game/WaitCommandsAI.cpp @@ -828,11 +828,10 @@ void CWaitCommandsAI::DeathWait::SelectAreaUnits( const float3 mins(std::min(pos0.x, pos1.x), 0.0f, std::min(pos0.z, pos1.z)); const float3 maxs(std::max(pos0.x, pos1.x), 0.0f, std::max(pos0.z, pos1.z)); - const std::vector& tmpUnits = quadField->GetUnitsExact(mins, maxs); - - for (unsigned int i = 0; i < tmpUnits.size(); i++) { - const CUnit* unit = tmpUnits[i]; + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, mins, maxs); + for (const CUnit* unit: *qfQuery.units) { if (enemies && teamHandler->Ally(unit->allyteam, gu->myAllyTeam)) continue; diff --git a/rts/Lua/LuaSyncedRead.cpp b/rts/Lua/LuaSyncedRead.cpp index 3dbb566fe99..1ded529bf41 100644 --- a/rts/Lua/LuaSyncedRead.cpp +++ b/rts/Lua/LuaSyncedRead.cpp @@ -2013,8 +2013,7 @@ int LuaSyncedRead::GetTeamUnitCount(lua_State* L) lua_createtable(L, units.size(), 0); \ } \ \ - for (auto it = units.cbegin(); it != units.cend(); ++it) { \ - const CUnit* unit = *it; \ + for (const CUnit* unit: units) { \ \ ALLEGIANCE_TEST; \ CUSTOM_TEST; \ @@ -2085,7 +2084,9 @@ int LuaSyncedRead::GetUnitsInRectangle(lua_State* L) #define RECTANGLE_TEST ; // no test, GetUnitsExact is sufficient - const vector& units = quadField->GetUnitsExact(mins, maxs); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, mins, maxs); + const auto& units = (*qfQuery.units); if (allegiance >= 0) { if (IsAlliedTeam(L, allegiance)) { @@ -2132,7 +2133,9 @@ int LuaSyncedRead::GetUnitsInBox(lua_State* L) continue; \ } - const vector& units = quadField->GetUnitsExact(mins, maxs); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, mins, maxs); + const auto& units = (*qfQuery.units); if (allegiance >= 0) { if (IsAlliedTeam(L, allegiance)) { @@ -2180,7 +2183,9 @@ int LuaSyncedRead::GetUnitsInCylinder(lua_State* L) continue; \ } \ - const vector& units = quadField->GetUnitsExact(mins, maxs); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, mins, maxs); + const auto& units = (*qfQuery.units); if (allegiance >= 0) { if (IsAlliedTeam(L, allegiance)) { @@ -2232,7 +2237,9 @@ int LuaSyncedRead::GetUnitsInSphere(lua_State* L) continue; \ } \ - const vector& units = quadField->GetUnitsExact(mins, maxs); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, mins, maxs); + const auto& units = (*qfQuery.units); if (allegiance >= 0) { if (IsAlliedTeam(L, allegiance)) { @@ -2450,8 +2457,9 @@ int LuaSyncedRead::GetFeaturesInRectangle(lua_State* L) const float3 mins(xmin, 0.0f, zmin); const float3 maxs(xmax, 0.0f, zmax); - const vector& rectFeatures = quadField->GetFeaturesExact(mins, maxs); - ProcessFeatures(L, rectFeatures); + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, mins, maxs); + ProcessFeatures(L, *qfQuery.features); return 1; } @@ -2464,8 +2472,9 @@ int LuaSyncedRead::GetFeaturesInSphere(lua_State* L) const float3 pos(x, y, z); - const vector& sphFeatures = quadField->GetFeaturesExact(pos, rad, true); - ProcessFeatures(L, sphFeatures); + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, pos, rad, true); + ProcessFeatures(L, *qfQuery.features); return 1; } @@ -2477,8 +2486,9 @@ int LuaSyncedRead::GetFeaturesInCylinder(lua_State* L) const float3 pos(x, 0, z); - const vector& cylFeatures = quadField->GetFeaturesExact(pos, rad, false); - ProcessFeatures(L, cylFeatures); + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, pos, rad, false); + ProcessFeatures(L, *qfQuery.features); return 1; } @@ -2495,8 +2505,9 @@ int LuaSyncedRead::GetProjectilesInRectangle(lua_State* L) const float3 mins(xmin, 0.0f, zmin); const float3 maxs(xmax, 0.0f, zmax); - const vector& rectProjectiles = quadField->GetProjectilesExact(mins, maxs); - const unsigned int rectProjectileCount = rectProjectiles.size(); + QuadFieldQuery qfQuery; + quadField->GetProjectilesExact(qfQuery, mins, maxs); + const unsigned int rectProjectileCount = qfQuery.projectiles->size(); unsigned int arrayIndex = 1; lua_createtable(L, rectProjectileCount, 0); @@ -2504,7 +2515,7 @@ int LuaSyncedRead::GetProjectilesInRectangle(lua_State* L) if (CLuaHandle::GetHandleReadAllyTeam(L) < 0) { if (CLuaHandle::GetHandleFullRead(L)) { for (unsigned int i = 0; i < rectProjectileCount; i++) { - const CProjectile* pro = rectProjectiles[i]; + const CProjectile* pro = (*qfQuery.projectiles)[i]; // filter out unsynced projectiles, the SyncedRead // projecile Get* functions accept only synced ID's @@ -2523,7 +2534,7 @@ int LuaSyncedRead::GetProjectilesInRectangle(lua_State* L) } } else { for (unsigned int i = 0; i < rectProjectileCount; i++) { - const CProjectile* pro = rectProjectiles[i]; + const CProjectile* pro = (*qfQuery.projectiles)[i]; // see above if (!pro->synced) diff --git a/rts/Map/BasicMapDamage.cpp b/rts/Map/BasicMapDamage.cpp index c2a400dba2d..cbf7a6e72dd 100644 --- a/rts/Map/BasicMapDamage.cpp +++ b/rts/Map/BasicMapDamage.cpp @@ -128,11 +128,12 @@ void CBasicMapDamage::Explosion(const float3& pos, float strength, float radius) } } - const std::vector& units = quadField->GetUnitsExact(pos, radius); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius); // calculate how much to raise or lower buildings in the explosion radius // (while still keeping the ground below them flat) - for (const CUnit* unit: units) { + for (const CUnit* unit: *qfQuery.units) { if (!unit->blockHeightChanges) continue; if (!unit->IsBlocking()) diff --git a/rts/Sim/Features/Feature.cpp b/rts/Sim/Features/Feature.cpp index a5281621af8..0158595104c 100644 --- a/rts/Sim/Features/Feature.cpp +++ b/rts/Sim/Features/Feature.cpp @@ -656,12 +656,13 @@ void CFeature::EmitGeoSmoke() { if ((gs->frameNum + id % 5) % 5 == 0) { // Find the unit closest to the geothermal - const vector& objs = quadField->GetSolidsExact(pos, 0.0f, 0xFFFFFFFF, CSolidObject::CSTATE_BIT_SOLIDOBJECTS); + QuadFieldQuery qfQuery; + quadField->GetSolidsExact(qfQuery, pos, 0.0f, 0xFFFFFFFF, CSolidObject::CSTATE_BIT_SOLIDOBJECTS); float bestDist = std::numeric_limits::max(); CSolidObject* so = nullptr; - for (CSolidObject* obj: objs) { + for (CSolidObject* obj: *qfQuery.solids) { const float dist = (obj->pos - pos).SqLength(); if (dist > bestDist) diff --git a/rts/Sim/Features/FeatureHandler.cpp b/rts/Sim/Features/FeatureHandler.cpp index 5e2a7986b6f..22e5d275a47 100644 --- a/rts/Sim/Features/FeatureHandler.cpp +++ b/rts/Sim/Features/FeatureHandler.cpp @@ -251,9 +251,10 @@ void CFeatureHandler::TerrainChanged(int x1, int y1, int x2, int y2) const float3 mins(x1 * SQUARE_SIZE, 0, y1 * SQUARE_SIZE); const float3 maxs(x2 * SQUARE_SIZE, 0, y2 * SQUARE_SIZE); - const auto& quads = quadField->GetQuadsRectangle(mins, maxs); + QuadFieldQuery qfQuery; + quadField->GetQuadsRectangle(qfQuery, mins, maxs); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CFeature* f: quadField->GetQuad(qi).features) { // put this feature back in the update-queue SetFeatureUpdateable(f); diff --git a/rts/Sim/Misc/QuadField.cpp b/rts/Sim/Misc/QuadField.cpp index d0752b18f0c..79077f1dc95 100644 --- a/rts/Sim/Misc/QuadField.cpp +++ b/rts/Sim/Misc/QuadField.cpp @@ -149,17 +149,17 @@ int CQuadField::WorldPosToQuadFieldIdx(const float3 p) const #ifndef UNIT_TEST -const std::vector& CQuadField::GetQuads(float3 pos, float radius) +void CQuadField::GetQuads(QuadFieldQuery& qfq, float3 pos, float radius) { pos.AssertNaNs(); pos.ClampInBounds(); - tempQuads.clear(); + qfq.quads = tempQuads.GetVector(); const int2 min = WorldPosToQuadField(pos - radius); const int2 max = WorldPosToQuadField(pos + radius); if (max.y < min.y || max.x < min.x) - return tempQuads; + return; // qsx and qsz are always equal const float maxSqLength = (radius + quadSizeX * 0.72f) * (radius + quadSizeZ * 0.72f); @@ -170,46 +170,46 @@ const std::vector& CQuadField::GetQuads(float3 pos, float radius) assert(z < numQuadsZ); const float3 quadPos = float3(x * quadSizeX + quadSizeX * 0.5f, 0, z * quadSizeZ + quadSizeZ * 0.5f); if (pos.SqDistance2D(quadPos) < maxSqLength) { - tempQuads.push_back(z * numQuadsX + x); + qfq.quads->push_back(z * numQuadsX + x); } } } - return tempQuads; + return; } -const std::vector& CQuadField::GetQuadsRectangle(const float3& mins, const float3& maxs) +void CQuadField::GetQuadsRectangle(QuadFieldQuery& qfq, const float3& mins, const float3& maxs) { mins.AssertNaNs(); maxs.AssertNaNs(); - tempQuads.clear(); + qfq.quads = tempQuads.GetVector(); const int2 min = WorldPosToQuadField(mins); const int2 max = WorldPosToQuadField(maxs); if (max.y < min.y || max.x < min.x) - return tempQuads; + return; for (int z = min.y; z <= max.y; ++z) { for (int x = min.x; x <= max.x; ++x) { assert(x < numQuadsX); assert(z < numQuadsZ); - tempQuads.push_back(z * numQuadsX + x); + qfq.quads->push_back(z * numQuadsX + x); } } - return tempQuads; + return; } #endif // UNIT_TEST /// note: this function got an UnitTest, check the tests/ folder! -const std::vector& CQuadField::GetQuadsOnRay(const float3& start, const float3& dir, float length) +void CQuadField::GetQuadsOnRay(QuadFieldQuery& qfq, const float3& start, const float3& dir, float length) { dir.AssertNaNs(); start.AssertNaNs(); - tempQuads.clear(); + qfq.quads = tempQuads.GetVector(); const float3 to = start + (dir * length); const float3 invQuadSize = float3(1.0f / quadSizeX, 1.0f, 1.0f / quadSizeZ); @@ -219,9 +219,9 @@ const std::vector& CQuadField::GetQuadsOnRay(const float3& start, const flo // often happened special case if (noXdir && noZdir) { - tempQuads.push_back(WorldPosToQuadFieldIdx(start)); - assert(unsigned(tempQuads.back()) < baseQuads.size()); - return tempQuads; + qfq.quads->push_back(WorldPosToQuadFieldIdx(start)); + assert(unsigned(qfq.quads->back()) < baseQuads.size()); + return; } // to prevent Div0 @@ -234,11 +234,11 @@ const std::vector& CQuadField::GetQuadsOnRay(const float3& start, const flo const int row = Clamp(start.z * invQuadSize.z, 0, numQuadsZ - 1) * numQuadsX; for (unsigned x = startX; x <= finalX; x++) { - tempQuads.push_back(row + x); - assert(unsigned(tempQuads.back()) < baseQuads.size()); + qfq.quads->push_back(row + x); + assert(unsigned(qfq.quads->back()) < baseQuads.size()); } - return tempQuads; + return; } // all other @@ -271,23 +271,24 @@ const std::vector& CQuadField::GetQuadsOnRay(const float3& start, const flo const int row = Clamp(z, 0, numQuadsZ - 1) * numQuadsX; for (unsigned x = startX; x <= finalX; x++) { - tempQuads.push_back(row + x); - assert(unsigned(tempQuads.back()) < baseQuads.size()); + qfq.quads->push_back(row + x); + assert(unsigned(qfq.quads->back()) < baseQuads.size()); } } - return tempQuads; + return; } #ifndef UNIT_TEST void CQuadField::MovedUnit(CUnit* unit) { - auto newQuads = std::move(GetQuads(unit->pos, unit->radius)); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, unit->pos, unit->radius); // compare if the quads have changed, if not stop here - if (newQuads.size() == unit->quads.size()) { - if (std::equal(newQuads.begin(), newQuads.end(), unit->quads.begin())) { + if (qfQuery.quads->size() == unit->quads.size()) { + if (std::equal(qfQuery.quads->begin(), qfQuery.quads->end(), unit->quads.begin())) { return; } } @@ -297,12 +298,12 @@ void CQuadField::MovedUnit(CUnit* unit) spring::VectorErase(baseQuads[qi].teamUnits[unit->allyteam], unit); } - for (const int qi: newQuads) { + for (const int qi: *qfQuery.quads) { spring::VectorInsertUnique(baseQuads[qi].units, unit, false); spring::VectorInsertUnique(baseQuads[qi].teamUnits[unit->allyteam], unit, false); } - unit->quads = std::move(newQuads); + unit->quads = std::move(*qfQuery.quads); } void CQuadField::RemoveUnit(CUnit* unit) @@ -328,11 +329,12 @@ void CQuadField::RemoveUnit(CUnit* unit) void CQuadField::MovedRepulser(CPlasmaRepulser* repulser) { - auto newQuads = std::move(GetQuads(repulser->weaponMuzzlePos, repulser->GetRadius())); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, repulser->weaponMuzzlePos, repulser->GetRadius()); // compare if the quads have changed, if not stop here - if (newQuads.size() == repulser->quads.size()) { - if (std::equal(newQuads.begin(), newQuads.end(), repulser->quads.begin())) { + if (qfQuery.quads->size() == repulser->quads.size()) { + if (std::equal(qfQuery.quads->begin(), qfQuery.quads->end(), repulser->quads.begin())) { return; } } @@ -341,11 +343,11 @@ void CQuadField::MovedRepulser(CPlasmaRepulser* repulser) spring::VectorErase(baseQuads[qi].repulsers, repulser); } - for (const int qi: newQuads) { + for (const int qi: *qfQuery.quads) { spring::VectorInsertUnique(baseQuads[qi].repulsers, repulser, false); } - repulser->quads = std::move(newQuads); + repulser->quads = std::move(*qfQuery.quads); } void CQuadField::RemoveRepulser(CPlasmaRepulser* repulser) @@ -368,18 +370,20 @@ void CQuadField::RemoveRepulser(CPlasmaRepulser* repulser) void CQuadField::AddFeature(CFeature* feature) { - const auto& newQuads = GetQuads(feature->pos, feature->radius); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, feature->pos, feature->radius); - for (const int qi: newQuads) { + for (const int qi: *qfQuery.quads) { spring::VectorInsertUnique(baseQuads[qi].features, feature, false); } } void CQuadField::RemoveFeature(CFeature* feature) { - const auto& quads = GetQuads(feature->pos, feature->radius); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, feature->pos, feature->radius); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { spring::VectorErase(baseQuads[qi].features, feature); } @@ -414,13 +418,14 @@ void CQuadField::AddProjectile(CProjectile* p) assert(p->synced); if (p->hitscan) { - auto newQuads = std::move(GetQuadsOnRay(p->pos, p->dir, p->speed.w)); + QuadFieldQuery qfQuery; + GetQuadsOnRay(qfQuery, p->pos, p->dir, p->speed.w); - for (const int qi: newQuads) { + for (const int qi: *qfQuery.quads) { spring::VectorInsertUnique(baseQuads[qi].projectiles, p, false); } - p->quads = std::move(newQuads); + p->quads = std::move(*qfQuery.quads); } else { int newQuad = WorldPosToQuadFieldIdx(p->pos); spring::VectorInsertUnique(baseQuads[newQuad].projectiles, p, false); @@ -444,32 +449,34 @@ void CQuadField::RemoveProjectile(CProjectile* p) -const std::vector& CQuadField::GetUnits(const float3& pos, float radius) +void CQuadField::GetUnits(QuadFieldQuery& qfq, const float3& pos, float radius) { - const auto& quads = GetQuads(pos, radius); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, pos, radius); const int tempNum = gs->GetTempNum(); - tempUnits.clear(); + qfq.units = tempUnits.GetVector(); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CUnit* u: baseQuads[qi].units) { if (u->tempNum == tempNum) continue; u->tempNum = tempNum; - tempUnits.push_back(u); + qfq.units->push_back(u); } } - return tempUnits; + return; } -const std::vector& CQuadField::GetUnitsExact(const float3& pos, float radius, bool spherical) +void CQuadField::GetUnitsExact(QuadFieldQuery& qfq, const float3& pos, float radius, bool spherical) { - const auto& quads = GetQuads(pos, radius); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, pos, radius); const int tempNum = gs->GetTempNum(); - tempUnits.clear(); + qfq.units = tempUnits.GetVector(); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CUnit* u: baseQuads[qi].units) { if (u->tempNum == tempNum) continue; @@ -485,20 +492,21 @@ const std::vector& CQuadField::GetUnitsExact(const float3& pos, float ra if (posUnitDstSq >= totRadSq) continue; - tempUnits.push_back(u); + qfq.units->push_back(u); } } - return tempUnits; + return; } -const std::vector& CQuadField::GetUnitsExact(const float3& mins, const float3& maxs) +void CQuadField::GetUnitsExact(QuadFieldQuery& qfq, const float3& mins, const float3& maxs) { - const auto& quads = GetQuadsRectangle(mins, maxs); + QuadFieldQuery qfQuery; + GetQuadsRectangle(qfQuery, mins, maxs); const int tempNum = gs->GetTempNum(); - tempUnits.clear(); + qfq.units = tempUnits.GetVector(); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CUnit* unit: baseQuads[qi].units) { if (unit->tempNum == tempNum) @@ -512,21 +520,22 @@ const std::vector& CQuadField::GetUnitsExact(const float3& mins, const f if (pos.z < mins.z || pos.z > maxs.z) continue; - tempUnits.push_back(unit); + qfq.units->push_back(unit); } } - return tempUnits; + return; } -const std::vector& CQuadField::GetFeaturesExact(const float3& pos, float radius, bool spherical) +void CQuadField::GetFeaturesExact(QuadFieldQuery& qfq, const float3& pos, float radius, bool spherical) { - const auto& quads = GetQuads(pos, radius); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, pos, radius); const int tempNum = gs->GetTempNum(); - tempFeatures.clear(); + qfq.features = tempFeatures.GetVector(); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CFeature* f: baseQuads[qi].features) { if (f->tempNum == tempNum) continue; @@ -542,20 +551,21 @@ const std::vector& CQuadField::GetFeaturesExact(const float3& pos, fl if (posDstSq >= totRadSq) continue; - tempFeatures.push_back(f); + qfq.features->push_back(f); } } - return tempFeatures; + return; } -const std::vector& CQuadField::GetFeaturesExact(const float3& mins, const float3& maxs) +void CQuadField::GetFeaturesExact(QuadFieldQuery& qfq, const float3& mins, const float3& maxs) { - const auto& quads = GetQuadsRectangle(mins, maxs); + QuadFieldQuery qfQuery; + GetQuadsRectangle(qfQuery, mins, maxs); const int tempNum = gs->GetTempNum(); - tempFeatures.clear(); + qfq.features = tempFeatures.GetVector(); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CFeature* feature: baseQuads[qi].features) { if (feature->tempNum == tempNum) continue; @@ -568,22 +578,23 @@ const std::vector& CQuadField::GetFeaturesExact(const float3& mins, c if (pos.z < mins.z || pos.z > maxs.z) continue; - tempFeatures.push_back(feature); + qfq.features->push_back(feature); } } - return tempFeatures; + return; } -const std::vector& CQuadField::GetProjectilesExact(const float3& pos, float radius) +void CQuadField::GetProjectilesExact(QuadFieldQuery& qfq, const float3& pos, float radius) { - const auto& quads = GetQuads(pos, radius); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, pos, radius); const int tempNum = gs->GetTempNum(); - tempProjectiles.clear(); + qfq.projectiles = tempProjectiles.GetVector(); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CProjectile* p: baseQuads[qi].projectiles) { if (p->tempNum == tempNum) continue; @@ -593,20 +604,21 @@ const std::vector& CQuadField::GetProjectilesExact(const float3& p if (pos.SqDistance(p->pos) >= Square(radius + p->radius)) continue; - tempProjectiles.push_back(p); + qfq.projectiles->push_back(p); } } - return tempProjectiles; + return; } -const std::vector& CQuadField::GetProjectilesExact(const float3& mins, const float3& maxs) +void CQuadField::GetProjectilesExact(QuadFieldQuery& qfq, const float3& mins, const float3& maxs) { - const auto& quads = GetQuadsRectangle(mins, maxs); + QuadFieldQuery qfQuery; + GetQuadsRectangle(qfQuery, mins, maxs); const int tempNum = gs->GetTempNum(); - tempProjectiles.clear(); + qfq.projectiles = tempProjectiles.GetVector(); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CProjectile* p: baseQuads[qi].projectiles) { if (p->tempNum == tempNum) continue; @@ -619,26 +631,28 @@ const std::vector& CQuadField::GetProjectilesExact(const float3& m if (pos.z < mins.z || pos.z > maxs.z) continue; - tempProjectiles.push_back(p); + qfq.projectiles->push_back(p); } } - return tempProjectiles; + return; } -const std::vector& CQuadField::GetSolidsExact( +void CQuadField::GetSolidsExact( + QuadFieldQuery& qfq, const float3& pos, const float radius, const unsigned int physicalStateBits, const unsigned int collisionStateBits ) { - const auto& quads = GetQuads(pos, radius); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, pos, radius); const int tempNum = gs->GetTempNum(); - tempSolids.clear(); + qfq.solids = tempSolids.GetVector(); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CUnit* u: baseQuads[qi].units) { if (u->tempNum == tempNum) continue; @@ -652,7 +666,7 @@ const std::vector& CQuadField::GetSolidsExact( if ((pos - u->pos).SqLength() >= Square(radius + u->radius)) continue; - tempSolids.push_back(u); + qfq.solids->push_back(u); } for (CFeature* f: baseQuads[qi].features) { @@ -668,11 +682,11 @@ const std::vector& CQuadField::GetSolidsExact( if ((pos - f->pos).SqLength() >= Square(radius + f->radius)) continue; - tempSolids.push_back(f); + qfq.solids->push_back(f); } } - return tempSolids; + return; } @@ -682,10 +696,11 @@ bool CQuadField::NoSolidsExact( const unsigned int physicalStateBits, const unsigned int collisionStateBits ) { - const auto& quads = GetQuads(pos, radius); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, pos, radius); const int tempNum = gs->GetTempNum(); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { for (CUnit* u: baseQuads[qi].units) { if (u->tempNum == tempNum) continue; @@ -733,10 +748,11 @@ void CQuadField::GetUnitsAndFeaturesColVol( ) { const int tempNum = gs->GetTempNum(); + QuadFieldQuery qfQuery; + GetQuads(qfQuery, pos, radius); // start counting from the previous object-cache sizes - const auto& quads = GetQuads(pos, radius); - for (const int qi: quads) { + for (const int qi: *qfQuery.quads) { const Quad& quad = baseQuads[qi]; for (CUnit* u: quad.units) { diff --git a/rts/Sim/Misc/QuadField.h b/rts/Sim/Misc/QuadField.h index 5e8c78b4f31..e227692bb84 100644 --- a/rts/Sim/Misc/QuadField.h +++ b/rts/Sim/Misc/QuadField.h @@ -3,6 +3,7 @@ #ifndef QUAD_FIELD_H #define QUAD_FIELD_H +#include #include #include "System/Misc/NonCopyable.h" @@ -15,6 +16,45 @@ class CFeature; class CProjectile; class CSolidObject; class CPlasmaRepulser; +struct QuadFieldQuery; + +template +class ExclusiveVectors { +public: + std::vector* GetVector() { + for (auto& v: vectors){ + if (v.first) + continue; + + v.first = true; + v.second.clear(); + return &v.second; + } + vectors.emplace_back(); + // There shouldn't be too many concurrent users of each vector type + assert(vectors.size() < 4); + auto &v = vectors.back(); + v.first = true; + return &v.second; + } + + void ReleaseVector(std::vector* released) { + if (released == nullptr) + return; + + for (auto& v: vectors){ + if (&v.second != released) + continue; + + v.first = false; + return; + } + assert(false); + } + + std::deque>> vectors; +}; + class CQuadField : spring::noncopyable @@ -35,9 +75,9 @@ needed to support dynamic resizing (not used yet) CQuadField(int2 mapDims, int quad_size); ~CQuadField(); - const std::vector& GetQuads(float3 pos, float radius); - const std::vector& GetQuadsRectangle(const float3& mins, const float3& maxs); - const std::vector& GetQuadsOnRay(const float3& start, const float3& dir, float length); + void GetQuads(QuadFieldQuery& qfq, float3 pos, float radius); + void GetQuadsRectangle(QuadFieldQuery& qfq, const float3& mins, const float3& maxs); + void GetQuadsOnRay(QuadFieldQuery& qfq, const float3& start, const float3& dir, float length); void GetUnitsAndFeaturesColVol( const float3& pos, @@ -51,34 +91,35 @@ needed to support dynamic resizing (not used yet) * Returns all units within @c radius of @c pos, * and treats each unit as a 3D point object */ - const std::vector& GetUnits(const float3& pos, float radius); + void GetUnits(QuadFieldQuery& qfq, const float3& pos, float radius); /** * Returns all units within @c radius of @c pos, * takes the 3D model radius of each unit into account, * and performs the search within a sphere or cylinder depending on @c spherical */ - const std::vector& GetUnitsExact(const float3& pos, float radius, bool spherical = true); + void GetUnitsExact(QuadFieldQuery& qfq, const float3& pos, float radius, bool spherical = true); /** * Returns all units within the rectangle defined by * mins and maxs, which extends infinitely along the y-axis */ - const std::vector& GetUnitsExact(const float3& mins, const float3& maxs); + void GetUnitsExact(QuadFieldQuery& qfq, const float3& mins, const float3& maxs); /** * Returns all features within @c radius of @c pos, * takes the 3D model radius of each feature into account, * and performs the search within a sphere or cylinder depending on @c spherical */ - const std::vector& GetFeaturesExact(const float3& pos, float radius, bool spherical = true); + void GetFeaturesExact(QuadFieldQuery& qfq, const float3& pos, float radius, bool spherical = true); /** * Returns all features within the rectangle defined by * mins and maxs, which extends infinitely along the y-axis */ - const std::vector& GetFeaturesExact(const float3& mins, const float3& maxs); + void GetFeaturesExact(QuadFieldQuery& qfq, const float3& mins, const float3& maxs); - const std::vector& GetProjectilesExact(const float3& pos, float radius); - const std::vector& GetProjectilesExact(const float3& mins, const float3& maxs); + void GetProjectilesExact(QuadFieldQuery& qfq, const float3& pos, float radius); + void GetProjectilesExact(QuadFieldQuery& qfq, const float3& mins, const float3& maxs); - const std::vector& GetSolidsExact( + void GetSolidsExact( + QuadFieldQuery& qfq, const float3& pos, const float radius, const unsigned int physicalStateBits = 0xFFFFFFFF, @@ -105,6 +146,12 @@ needed to support dynamic resizing (not used yet) void MovedRepulser(CPlasmaRepulser* repulser); void RemoveRepulser(CPlasmaRepulser* repulser); + void ReleaseVector(std::vector* v ) { tempUnits.ReleaseVector(v); } + void ReleaseVector(std::vector* v ) { tempFeatures.ReleaseVector(v); } + void ReleaseVector(std::vector* v ) { tempProjectiles.ReleaseVector(v); } + void ReleaseVector(std::vector* v) { tempSolids.ReleaseVector(v); } + void ReleaseVector(std::vector* v ) { tempQuads.ReleaseVector(v); } + struct Quad { CR_DECLARE_STRUCT(Quad) Quad(); @@ -151,11 +198,11 @@ needed to support dynamic resizing (not used yet) std::vector baseQuads; // preallocated vectors for Get*Exact functions - std::vector tempUnits; - std::vector tempFeatures; - std::vector tempProjectiles; - std::vector tempSolids; - std::vector tempQuads; + ExclusiveVectors tempUnits; + ExclusiveVectors tempFeatures; + ExclusiveVectors tempProjectiles; + ExclusiveVectors tempSolids; + ExclusiveVectors tempQuads; int numQuadsX; int numQuadsZ; @@ -166,4 +213,19 @@ needed to support dynamic resizing (not used yet) extern CQuadField* quadField; +struct QuadFieldQuery { + ~QuadFieldQuery() { + quadField->ReleaseVector(units); + quadField->ReleaseVector(features); + quadField->ReleaseVector(projectiles); + quadField->ReleaseVector(solids); + quadField->ReleaseVector(quads); + } + std::vector* units = nullptr; + std::vector* features = nullptr; + std::vector* projectiles = nullptr; + std::vector* solids = nullptr; + std::vector* quads = nullptr; +}; + #endif /* QUAD_FIELD_H */ diff --git a/rts/Sim/MoveTypes/AAirMoveType.cpp b/rts/Sim/MoveTypes/AAirMoveType.cpp index e963d59930d..0d9312ba8e4 100644 --- a/rts/Sim/MoveTypes/AAirMoveType.cpp +++ b/rts/Sim/MoveTypes/AAirMoveType.cpp @@ -214,7 +214,8 @@ void AAirMoveType::CheckForCollision() const SyncedFloat3& forward = owner->frontdir; const float3 midTestPos = pos + forward * 121.0f; - const std::vector& others = quadField->GetUnitsExact(midTestPos, 115.0f); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, midTestPos, 115.0f); float dist = 200.0f; @@ -224,7 +225,7 @@ void AAirMoveType::CheckForCollision() lastColWarningType = 0; } - for (CUnit* unit: others) { + for (CUnit* unit: *qfQuery.units) { if (unit == owner || !unit->unitDef->canfly) { continue; } @@ -254,7 +255,7 @@ void AAirMoveType::CheckForCollision() return; } - for (CUnit* u: others) { + for (CUnit* u: *qfQuery.units) { if (u == owner) continue; if ((u->midPos - pos).SqLength() < (dist * dist)) { diff --git a/rts/Sim/MoveTypes/GroundMoveType.cpp b/rts/Sim/MoveTypes/GroundMoveType.cpp index 415a49412b3..5b526b471e1 100644 --- a/rts/Sim/MoveTypes/GroundMoveType.cpp +++ b/rts/Sim/MoveTypes/GroundMoveType.cpp @@ -931,15 +931,14 @@ void CGroundMoveType::CheckCollisionSkid() const UnitDef* colliderUD = collider->unitDef; // copy on purpose, since the below can call Lua - const vector nearUnits = quadField->GetUnitsExact(pos, collider->radius); - const vector nearFeatures = quadField->GetFeaturesExact(pos, collider->radius); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, collider->radius); + quadField->GetFeaturesExact(qfQuery, pos, collider->radius); vector::const_iterator ui; vector::const_iterator fi; - for (ui = nearUnits.begin(); ui != nearUnits.end(); ++ui) { - CUnit* collidee = *ui; - + for (CUnit* collidee: *qfQuery.units) { if (!collidee->HasCollidableStateBit(CSolidObject::CSTATE_BIT_SOLIDOBJECTS)) continue; @@ -1009,9 +1008,7 @@ void CGroundMoveType::CheckCollisionSkid() } } - for (fi = nearFeatures.begin(); fi != nearFeatures.end(); ++fi) { - CFeature* collidee = *fi; - + for (CFeature* collidee: *qfQuery.features) { if (!collidee->HasCollidableStateBit(CSolidObject::CSTATE_BIT_SOLIDOBJECTS)) continue; @@ -1125,9 +1122,10 @@ float3 CGroundMoveType::GetObstacleAvoidanceDir(const float3& desiredDir) { const float avoidanceRadius = std::max(currentSpeed, 1.0f) * (avoider->radius * 2.0f); const float avoiderRadius = FOOTPRINT_RADIUS(avoiderMD->xsize, avoiderMD->zsize, 1.0f); - const vector& objects = quadField->GetSolidsExact(avoider->pos, avoidanceRadius, 0xFFFFFFFF, CSolidObject::CSTATE_BIT_SOLIDOBJECTS); + QuadFieldQuery qfQuery; + quadField->GetSolidsExact(qfQuery, avoider->pos, avoidanceRadius, 0xFFFFFFFF, CSolidObject::CSTATE_BIT_SOLIDOBJECTS); - for (const CSolidObject* avoidee: objects) { + for (const CSolidObject* avoidee: *qfQuery.solids) { const MoveDef* avoideeMD = avoidee->moveDef; const UnitDef* avoideeUD = dynamic_cast(avoidee->GetDef()); @@ -1804,13 +1802,14 @@ void CGroundMoveType::HandleUnitCollisions( const float searchRadius = colliderSpeed + (colliderRadius * 2.0f); // copy on purpose, since the below can call Lua - const std::vector nearUnits = quadField->GetUnitsExact(collider->pos, searchRadius); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, collider->pos, searchRadius); // NOTE: probably too large for most units (eg. causes tree falling animations to be skipped) const int dirSign = Sign(int(!reversing)); const float3 crushImpulse = collider->speed * collider->mass * dirSign; - for (CUnit* collidee: nearUnits) { + for (CUnit* collidee: *qfQuery.units) { if (collidee == collider) continue; if (collidee->IsSkidding()) continue; if (collidee->IsFlying()) continue; @@ -2022,14 +2021,13 @@ void CGroundMoveType::HandleFeatureCollisions( const float searchRadius = colliderSpeed + (colliderRadius * 2.0f); // copy on purpose, since DoDamage below can call Lua - const std::vector nearFeatures = quadField->GetFeaturesExact(collider->pos, searchRadius); - std::vector::const_iterator fit; + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, collider->pos, searchRadius); const int dirSign = Sign(int(!reversing)); const float3 crushImpulse = collider->speed * collider->mass * dirSign; - for (fit = nearFeatures.begin(); fit != nearFeatures.end(); ++fit) { - CFeature* collidee = const_cast(*fit); + for (CFeature* collidee: *qfQuery.features) { // const FeatureDef* collideeFD = collidee->def; // use the collidee's Feature (not FeatureDef) footprint as radius diff --git a/rts/Sim/MoveTypes/HoverAirMoveType.cpp b/rts/Sim/MoveTypes/HoverAirMoveType.cpp index bbe7f60ef19..c388e5850e1 100644 --- a/rts/Sim/MoveTypes/HoverAirMoveType.cpp +++ b/rts/Sim/MoveTypes/HoverAirMoveType.cpp @@ -1056,9 +1056,10 @@ bool CHoverAirMoveType::HandleCollisions(bool checkCollisions) // check for collisions if not being built or not taking off // includes an extra condition for transports, which are exempt while loading if (!forceHeading && checkCollisions) { - const std::vector& nearUnits = quadField->GetUnitsExact(pos, owner->radius + 6); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, owner->radius + 6); - for (CUnit* unit: nearUnits) { + for (CUnit* unit: *qfQuery.units) { const bool unloadingUnit = (unit->unloadingTransportId == owner->id); const bool unloadingOwner = (owner->unloadingTransportId == unit->id); diff --git a/rts/Sim/MoveTypes/StrafeAirMoveType.cpp b/rts/Sim/MoveTypes/StrafeAirMoveType.cpp index c0cc2fdf74a..9003d990960 100644 --- a/rts/Sim/MoveTypes/StrafeAirMoveType.cpp +++ b/rts/Sim/MoveTypes/StrafeAirMoveType.cpp @@ -564,9 +564,10 @@ bool CStrafeAirMoveType::HandleCollisions(bool checkCollisions) { // check for collisions if not being built or not taking off if (checkCollisions) { // copy on purpose, since the below can call Lua - const std::vector nearUnits = quadField->GetUnitsExact(pos, owner->radius + 6); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, owner->radius + 6); - for (CUnit* unit: nearUnits) { + for (CUnit* unit: *qfQuery.units) { const bool unloadingUnit = (unit->unloadingTransportId == owner->id); const bool unloadingOwner = (owner->unloadingTransportId == unit->id); diff --git a/rts/Sim/Projectiles/FireProjectile.cpp b/rts/Sim/Projectiles/FireProjectile.cpp index 33f72648cfa..445204e8a81 100644 --- a/rts/Sim/Projectiles/FireProjectile.cpp +++ b/rts/Sim/Projectiles/FireProjectile.cpp @@ -97,17 +97,18 @@ void CFireProjectile::Update() } if (!(ttl & 31)) { // copy on purpose, since the below can call Lua - const std::vector features = quadField->GetFeaturesExact(emitPos + wind.GetCurrentWind() * 0.7f, emitRadius * 2); - const std::vector units = quadField->GetUnitsExact(emitPos + wind.GetCurrentWind() * 0.7f, emitRadius * 2); + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, emitPos + wind.GetCurrentWind() * 0.7f, emitRadius * 2); + quadField->GetUnitsExact(qfQuery, emitPos + wind.GetCurrentWind() * 0.7f, emitRadius * 2); - for (CFeature* f: features) { + for (CFeature* f: *qfQuery.features) { if (gsRNG.NextFloat() > 0.8f) { f->StartFire(); } } const DamageArray fireDmg(30); - for (CUnit* u: units) { + for (CUnit* u: *qfQuery.units) { u->DoDamage(fireDmg, ZeroVector, NULL, -CSolidObject::DAMAGE_EXTSOURCE_FIRE, -1); } } diff --git a/rts/Sim/Units/CommandAI/BuilderCAI.cpp b/rts/Sim/Units/CommandAI/BuilderCAI.cpp index e0226b0c026..b946fe8c17b 100644 --- a/rts/Sim/Units/CommandAI/BuilderCAI.cpp +++ b/rts/Sim/Units/CommandAI/BuilderCAI.cpp @@ -1477,9 +1477,9 @@ int CBuilderCAI::FindReclaimTarget(const float3& pos, float radius, unsigned cha int rid = -1; if (recUnits || recEnemy || recEnemyOnly) { - const std::vector& units = quadField->GetUnitsExact(pos, radius, false); - for (std::vector::const_iterator ui = units.begin(); ui != units.end(); ++ui) { - const CUnit* u = *ui; + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius, false); + for (const CUnit* u: *qfQuery.units) { if (u == owner) continue; @@ -1517,10 +1517,10 @@ int CBuilderCAI::FindReclaimTarget(const float3& pos, float radius, unsigned cha if ((!best || !stationary) && !recEnemyOnly) { best = NULL; const CTeam* team = teamHandler->Team(owner->team); - const std::vector& features = quadField->GetFeaturesExact(pos, radius, false); + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, pos, radius, false); bool metal = false; - for (std::vector::const_iterator fi = features.begin(); fi != features.end(); ++fi) { - const CFeature* f = *fi; + for (const CFeature* f: *qfQuery.features) { if (f->def->reclaimable && (recSpecial || f->def->autoreclaim) && (!recNonRez || !(f->def->destructable && f->udef != NULL)) ) { @@ -1588,13 +1588,13 @@ bool CBuilderCAI::FindResurrectableFeatureAndResurrect(const float3& pos, unsigned char options, bool freshOnly) { - const std::vector &features = quadField->GetFeaturesExact(pos, radius, false); + QuadFieldQuery qfQuery; + quadField->GetFeaturesExact(qfQuery, pos, radius, false); const CFeature* best = NULL; float bestDist = 1.0e30f; - for (std::vector::const_iterator fi = features.begin(); fi != features.end(); ++fi) { - const CFeature* f = *fi; + for (const CFeature* f: *qfQuery.features) { if (f->def->destructable && f->udef != NULL) { if (!f->IsInLosForAllyTeam(owner->allyteam)) { continue; @@ -1631,16 +1631,15 @@ bool CBuilderCAI::FindCaptureTargetAndCapture(const float3& pos, float radius, unsigned char options, bool healthyOnly) { - const std::vector &cu = quadField->GetUnitsExact(pos, radius, false); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius, false); std::vector::const_iterator ui; const CUnit* best = NULL; float bestDist = 1.0e30f; bool stationary = false; - for (ui = cu.begin(); ui != cu.end(); ++ui) { - CUnit* unit = *ui; - + for (const CUnit* unit: *qfQuery.units) { if ((((options & CONTROL_KEY) && owner->team != unit->team) || !teamHandler->Ally(owner->allyteam, unit->allyteam)) && (unit != owner) && (unit->losStatus[owner->allyteam] & (LOS_INRADAR|LOS_INLOS)) && @@ -1680,7 +1679,8 @@ bool CBuilderCAI::FindRepairTargetAndRepair(const float3& pos, float radius, bool attackEnemy, bool builtOnly) { - const std::vector& cu = quadField->GetUnitsExact(pos, radius, false); + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, pos, radius, false); const CUnit* bestUnit = NULL; const float maxSpeed = owner->moveType->GetMaxSpeed(); @@ -1691,9 +1691,7 @@ bool CBuilderCAI::FindRepairTargetAndRepair(const float3& pos, float radius, bool trySelfRepair = false; bool stationary = false; - for (std::vector::const_iterator ui = cu.begin(); ui != cu.end(); ++ui) { - const CUnit* unit = *ui; - + for (const CUnit* unit: *qfQuery.units) { if (teamHandler->Ally(owner->allyteam, unit->allyteam)) { if (!haveEnemy && (unit->health < unit->maxHealth)) { // don't help allies build unless set on roam diff --git a/rts/Sim/Units/CommandAI/MobileCAI.cpp b/rts/Sim/Units/CommandAI/MobileCAI.cpp index f1e62f0755e..1e8f3065018 100644 --- a/rts/Sim/Units/CommandAI/MobileCAI.cpp +++ b/rts/Sim/Units/CommandAI/MobileCAI.cpp @@ -1503,12 +1503,13 @@ bool CMobileCAI::FindEmptySpot(const CUnit* unloadee, const float3& center, floa // passing spread as query-radius ensures units are spaced at least // this far apart, since will be non-empty if pos is closer // to a previous unloadee than elmos - const std::vector& units = quadField->GetSolidsExact(pos, spread, 0xFFFFFFFF, CSolidObject::CSTATE_BIT_SOLIDOBJECTS); + QuadFieldQuery qfQuery; + quadField->GetSolidsExact(qfQuery, pos, spread, 0xFFFFFFFF, CSolidObject::CSTATE_BIT_SOLIDOBJECTS); - if (unitDef->IsAirUnit() && (units.size() > 1 || (units.size() == 1 && units[0] != owner))) + if (unitDef->IsAirUnit() && (qfQuery.solids->size() > 1 || (qfQuery.solids->size() == 1 && (*qfQuery.solids)[0] != owner))) continue; // ground-transports want the sampled position to be entirely free - if (!unitDef->IsAirUnit() && !units.empty()) + if (!unitDef->IsAirUnit() && !qfQuery.solids->empty()) continue; found = pos; @@ -1523,8 +1524,10 @@ CUnit* CMobileCAI::FindUnitToTransport(float3 center, float radius) { CUnit* bestUnit = nullptr; float bestDist = std::numeric_limits::max(); - - for (CUnit* unit: quadField->GetUnitsExact(center, radius)) { + + QuadFieldQuery qfQuery; + quadField->GetUnitsExact(qfQuery, center, radius); + for (CUnit* unit: *qfQuery.units) { const float dist = unit->pos.SqDistance2D(owner->pos); if (unit->loadingTransportId != -1 && unit->loadingTransportId != owner->id) { @@ -1597,9 +1600,10 @@ bool CMobileCAI::SpotIsClearIgnoreSelf(float3 pos, CUnit* unloadee) const float radius = std::max(1.0f, math::ceil(unloadee->radius / SQUARE_SIZE)) * SQUARE_SIZE; - const std::vector& units = quadField->GetSolidsExact(pos, radius, 0xFFFFFFFF, CSolidObject::CSTATE_BIT_SOLIDOBJECTS); + QuadFieldQuery qfQuery; + quadField->GetSolidsExact(qfQuery, pos, radius, 0xFFFFFFFF, CSolidObject::CSTATE_BIT_SOLIDOBJECTS); - for (auto objectsIt = units.begin(); objectsIt != units.end(); ++objectsIt) { + for (auto objectsIt = qfQuery.solids->begin(); objectsIt != qfQuery.solids->end(); ++objectsIt) { // check if the units are in the transport bool found = false; diff --git a/rts/Sim/Units/UnitTypes/ExtractorBuilding.cpp b/rts/Sim/Units/UnitTypes/ExtractorBuilding.cpp index ea8946bb4f4..305c5d8e07c 100644 --- a/rts/Sim/Units/UnitTypes/ExtractorBuilding.cpp +++ b/rts/Sim/Units/UnitTypes/ExtractorBuilding.cpp @@ -78,15 +78,16 @@ void CExtractorBuilding::SetExtractionRangeAndDepth(float range, float depth) maxExtractionRange = std::max(extractionRange, maxExtractionRange); // find any neighbouring extractors - const std::vector& cu = quadField->GetUnits(pos, extractionRange + maxExtractionRange); + QuadFieldQuery qfQuery; + quadField->GetUnits(qfQuery, pos, extractionRange + maxExtractionRange); - for (auto ui = cu.begin(); ui != cu.end(); ++ui) { - if (*ui == this) + for (CUnit* u: *qfQuery.units) { + if (u == this) continue; - if (typeid(**ui) != typeid(CExtractorBuilding)) + if (typeid(*u) != typeid(CExtractorBuilding)) continue; - CExtractorBuilding* eb = static_cast(*ui); + CExtractorBuilding* eb = static_cast(u); if (!IsNeighbour(eb)) continue;