std::vector<CFeature*> CQuadField::GetFeaturesExact(const float3& pos, float radius) { GML_RECMUTEX_LOCK(qnum); // GetFeaturesExact const std::vector<int>& quads = GetQuads(pos, radius); const int tempNum = gs->tempNum++; std::vector<CFeature*> features; std::vector<int>::const_iterator qi; std::list<CFeature*>::iterator fi; for (qi = quads.begin(); qi != quads.end(); ++qi) { for (fi = baseQuads[*qi].features.begin(); fi != baseQuads[*qi].features.end(); ++fi) { if ((*fi)->tempNum == tempNum) { continue; } if (pos.SqDistance((*fi)->midPos) >= Square(radius + (*fi)->radius)) { continue; } (*fi)->tempNum = tempNum; features.push_back(*fi); } } return features; }
// should only be used by air bool CTransportCAI::FindEmptyDropSpots(float3 startpos, float3 endpos, std::list<float3>& dropSpots) { const float gap = 25.5f; // TODO - set tag for this? const float3 dir = (endpos - startpos).Normalize(); float3 nextPos = startpos; dropSpots.push_front(nextPos); if (dynamic_cast<CHoverAirMoveType*>(owner->moveType) == NULL) return false; const auto& transportees = static_cast<CTransportUnit*>(owner)->GetTransportedUnits(); auto ti = transportees.begin(); // first spot if (ti != transportees.end()) { nextPos += (dir * (gap + ti->unit->radius)); ++ti; } // remaining spots while (ti != transportees.end() && startpos.SqDistance(nextPos) < startpos.SqDistance(endpos)) { nextPos += (dir * (ti->unit->radius)); nextPos.y = CGround::GetHeightAboveWater(nextPos.x, nextPos.z); // check landing spot is ok for landing on if (!SpotIsClear(nextPos, ti->unit)) continue; dropSpots.push_front(nextPos); nextPos += (dir * (gap + ti->unit->radius)); ++ti; } return true; }
bool CTransportCAI::FindEmptyDropSpots(float3 startpos, float3 endpos, std::list<float3>& dropSpots) { //should only be used by air CTransportUnit* transport = static_cast<CTransportUnit*>(owner); //dropSpots.clear(); float gap = 25.5; // TODO - set tag for this? float3 dir = endpos - startpos; dir.Normalize(); float3 nextPos = startpos; float3 pos; std::list<CTransportUnit::TransportedUnit>::const_iterator ti = transport->GetTransportedUnits().begin(); dropSpots.push_front(nextPos); // first spot if (ti != transport->GetTransportedUnits().end()) { nextPos += dir * (gap + ti->unit->radius); ++ti; } // remaining spots if (dynamic_cast<CHoverAirMoveType*>(owner->moveType)) { while (ti != transport->GetTransportedUnits().end() && startpos.SqDistance(nextPos) < startpos.SqDistance(endpos)) { nextPos += dir * (ti->unit->radius); nextPos.y = ground->GetHeightAboveWater(nextPos.x, nextPos.z); // check landing spot is ok for landing on if (!SpotIsClear(nextPos,ti->unit)) continue; dropSpots.push_front(nextPos); nextPos += dir * (gap + ti->unit->radius); ++ti; } return true; } return false; }
std::vector<CUnit*> CQuadField::GetUnitsExact(const float3& pos, float radius, bool spherical) { GML_RECMUTEX_LOCK(qnum); // GetUnitsExact const int tempNum = gs->tempNum++; int* begQuad = &tempQuads[0]; int* endQuad = &tempQuads[0]; GetQuads(pos, radius, begQuad, endQuad); std::vector<CUnit*> units; std::list<CUnit*>::iterator ui; for (int* a = begQuad; a != endQuad; ++a) { Quad& quad = baseQuads[*a]; for (ui = quad.units.begin(); ui != quad.units.end(); ++ui) { if ((*ui)->tempNum == tempNum) continue; const float totRad = radius + (*ui)->radius; const float totRadSq = totRad * totRad; const float posUnitDstSq = spherical? pos.SqDistance((*ui)->midPos): pos.SqDistance2D((*ui)->midPos); if (posUnitDstSq >= totRadSq) continue; (*ui)->tempNum = tempNum; units.push_back(*ui); } } return units; }
static inline bool equals_distance(const float3& f1, const float3& f2) { return ((f1.x == f2.x) && (f1.y == f2.y) && (f1.z == f2.z)) || epscmp2(f1.SqDistance(f2)); }
// optimization specifically for projectile collisions void CQuadField::GetUnitsAndFeaturesColVol( const float3& pos, const float radius, std::vector<CUnit*>& units, std::vector<CFeature*>& features, unsigned int* numUnitsPtr, unsigned int* numFeaturesPtr ) { GML_RECMUTEX_LOCK(qnum); // GetUnitsAndFeaturesColVol const int tempNum = gs->tempNum++; // start counting from the previous object-cache sizes unsigned int numUnits = (numUnitsPtr == NULL)? 0: (*numUnitsPtr); unsigned int numFeatures = (numFeaturesPtr == NULL)? 0: (*numFeaturesPtr); int* begQuad = &tempQuads[0]; int* endQuad = &tempQuads[0]; // bail early if caches are already full if (numUnits >= units.size()) return; if (numFeatures >= features.size()) return; assert(numUnits == 0 || units[numUnits] == NULL); assert(numFeatures == 0 || features[numFeatures] == NULL); GetQuads(pos, radius, begQuad, endQuad); std::list<CUnit*>::const_iterator ui; std::list<CFeature*>::const_iterator fi; for (int* a = begQuad; a != endQuad; ++a) { const Quad& quad = baseQuads[*a]; for (ui = quad.units.begin(); ui != quad.units.end(); ++ui) { CUnit* u = *ui; // prevent double adding if (u->tempNum == tempNum) continue; const auto* colvol = u->collisionVolume; const float totRad = radius + colvol->GetBoundingRadius(); if (pos.SqDistance(colvol->GetWorldSpacePos(u)) >= (totRad * totRad)) continue; assert(numUnits < units.size()); if (numUnits < units.size()) { u->tempNum = tempNum; units[numUnits++] = u; } } for (fi = quad.features.begin(); fi != quad.features.end(); ++fi) { CFeature* f = *fi; // prevent double adding if (f->tempNum == tempNum) continue; const auto* colvol = f->collisionVolume; const float totRad = radius + colvol->GetBoundingRadius(); if (pos.SqDistance(colvol->GetWorldSpacePos(f)) >= (totRad * totRad)) continue; assert(numFeatures < features.size()); if (numFeatures < features.size()) { f->tempNum = tempNum; features[numFeatures++] = f; } } } assert(numUnits < units.size()); assert(numFeatures < features.size()); // set end-of-list sentinels if (numUnits < units.size()) units[numUnits] = NULL; if (numFeatures < features.size()) features[numFeatures] = NULL; if (numUnitsPtr != NULL) { *numUnitsPtr = numUnits; } if (numFeaturesPtr != NULL) { *numFeaturesPtr = numFeatures; } }