Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/components/CCmpObstructionManager.cpp
Show First 20 Lines • Show All 461 Lines • ▼ Show 20 Lines | else | ||||
const StaticShape& shape = m_StaticShapes.at(TAG_TO_INDEX(tag)); | const StaticShape& shape = m_StaticShapes.at(TAG_TO_INDEX(tag)); | ||||
ObstructionSquare o = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh }; | ObstructionSquare o = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh }; | ||||
return o; | return o; | ||||
} | } | ||||
} | } | ||||
virtual fixed DistanceToPoint(entity_id_t ent, entity_pos_t px, entity_pos_t pz) const; | virtual fixed DistanceToPoint(entity_id_t ent, entity_pos_t px, entity_pos_t pz) const; | ||||
virtual bool TestLine(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, entity_pos_t r, bool relaxClearanceForUnits = false) const; | virtual bool TestLineAgainstUnitShapes(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, entity_pos_t r) const; | ||||
virtual bool TestStaticShape(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, std::vector<entity_id_t>* out) const; | virtual bool TestStaticShape(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, std::vector<entity_id_t>* out) const; | ||||
virtual bool TestUnitShape(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, std::vector<entity_id_t>* out) const; | virtual bool TestUnitShape(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, std::vector<entity_id_t>* out) const; | ||||
virtual void Rasterize(Grid<NavcellData>& grid, const std::vector<PathfinderPassability>& passClasses, bool fullUpdate); | virtual void Rasterize(Grid<NavcellData>& grid, const std::vector<PathfinderPassability>& passClasses, bool fullUpdate); | ||||
virtual void GetObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const; | virtual void GetObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const; | ||||
virtual void GetUnitObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const; | virtual void GetUnitObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const; | ||||
virtual void GetStaticObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const; | virtual void GetStaticObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const; | ||||
virtual void GetUnitsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter, bool strict = false) const; | virtual void GetUnitsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter) const; | ||||
virtual void GetStaticObstructionsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter) const; | virtual void GetStaticObstructionsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter) const; | ||||
virtual void SetPassabilityCircular(bool enabled) | virtual void SetPassabilityCircular(bool enabled) | ||||
{ | { | ||||
m_PassabilityCircular = enabled; | m_PassabilityCircular = enabled; | ||||
MakeDirtyAll(); | MakeDirtyAll(); | ||||
CMessageObstructionMapShapeChanged msg; | CMessageObstructionMapShapeChanged msg; | ||||
▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | fixed CCmpObstructionManager::DistanceToPoint(entity_id_t ent, entity_pos_t px, entity_pos_t pz) const | ||||
ObstructionSquare s; | ObstructionSquare s; | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), ent); | CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), ent); | ||||
if (!cmpObstruction || !cmpObstruction->GetObstructionSquare(s)) | if (!cmpObstruction || !cmpObstruction->GetObstructionSquare(s)) | ||||
return (CFixedVector2D(px, pz) - cmpPosition->GetPosition2D()).Length(); | return (CFixedVector2D(px, pz) - cmpPosition->GetPosition2D()).Length(); | ||||
return Geometry::DistanceToSquare(CFixedVector2D(px - s.x, pz - s.z), s.u, s.v, CFixedVector2D(s.hw, s.hh)); | return Geometry::DistanceToSquare(CFixedVector2D(px - s.x, pz - s.z), s.u, s.v, CFixedVector2D(s.hw, s.hh)); | ||||
} | } | ||||
bool CCmpObstructionManager::TestLine(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, entity_pos_t r, bool relaxClearanceForUnits) const | bool CCmpObstructionManager::TestLineAgainstUnitShapes(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, entity_pos_t r) const | ||||
{ | { | ||||
PROFILE("TestLine"); | PROFILE("TestLine"); | ||||
// Check that both end points are within the world (which means the whole line must be) | // Check that both end points are within the world (which means the whole line must be) | ||||
if (!IsInWorld(x0, z0, r) || !IsInWorld(x1, z1, r)) | if (!IsInWorld(x0, z0, r) || !IsInWorld(x1, z1, r)) | ||||
return true; | return true; | ||||
CFixedVector2D posMin (std::min(x0, x1) - r, std::min(z0, z1) - r); | CFixedVector2D posMin (std::min(x0, x1) - r, std::min(z0, z1) - r); | ||||
CFixedVector2D posMax (std::max(x0, x1) + r, std::max(z0, z1) + r); | CFixedVector2D posMax (std::max(x0, x1) + r, std::max(z0, z1) + r); | ||||
// actual radius used for unit-unit collisions. If relaxClearanceForUnits, will be smaller to allow more overlap. | // Be a bit more tolerant when checking units as that looks better and improves pathfinding behaviour overall. | ||||
entity_pos_t unitUnitRadius = r; | entity_pos_t unitUnitRadius = r - entity_pos_t::FromInt(1)/2; | ||||
if (relaxClearanceForUnits) | |||||
unitUnitRadius -= entity_pos_t::FromInt(1)/2; | |||||
std::vector<entity_id_t> unitShapes; | std::vector<entity_id_t> unitShapes; | ||||
m_UnitSubdivision.GetInRange(unitShapes, posMin, posMax); | m_UnitSubdivision.GetInRange(unitShapes, posMin, posMax); | ||||
for (const entity_id_t& shape : unitShapes) | for (const entity_id_t& shape : unitShapes) | ||||
{ | { | ||||
std::map<u32, UnitShape>::const_iterator it = m_UnitShapes.find(shape); | std::map<u32, UnitShape>::const_iterator it = m_UnitShapes.find(shape); | ||||
ENSURE(it != m_UnitShapes.end()); | ENSURE(it != m_UnitShapes.end()); | ||||
if (!filter.TestShape(UNIT_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, INVALID_ENTITY)) | if (!filter.TestShape(UNIT_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, INVALID_ENTITY)) | ||||
continue; | continue; | ||||
CFixedVector2D center(it->second.x, it->second.z); | CFixedVector2D center(it->second.x, it->second.z); | ||||
CFixedVector2D halfSize(it->second.clearance + unitUnitRadius, it->second.clearance + unitUnitRadius); | CFixedVector2D halfSize(it->second.clearance + unitUnitRadius, it->second.clearance + unitUnitRadius); | ||||
if (Geometry::TestRayAASquare(CFixedVector2D(x0, z0) - center, CFixedVector2D(x1, z1) - center, halfSize)) | if (Geometry::TestRayAASquare(CFixedVector2D(x0, z0) - center, CFixedVector2D(x1, z1) - center, halfSize)) | ||||
return true; | return true; | ||||
} | } | ||||
std::vector<entity_id_t> staticShapes; | |||||
m_StaticSubdivision.GetInRange(staticShapes, posMin, posMax); | |||||
for (const entity_id_t& shape : staticShapes) | |||||
{ | |||||
std::map<u32, StaticShape>::const_iterator it = m_StaticShapes.find(shape); | |||||
ENSURE(it != m_StaticShapes.end()); | |||||
if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) | |||||
continue; | |||||
CFixedVector2D center(it->second.x, it->second.z); | |||||
CFixedVector2D halfSize(it->second.hw + r, it->second.hh + r); | |||||
if (Geometry::TestRaySquare(CFixedVector2D(x0, z0) - center, CFixedVector2D(x1, z1) - center, it->second.u, it->second.v, halfSize)) | |||||
return true; | |||||
} | |||||
return false; | return false; | ||||
} | } | ||||
bool CCmpObstructionManager::TestStaticShape(const IObstructionTestFilter& filter, | bool CCmpObstructionManager::TestStaticShape(const IObstructionTestFilter& filter, | ||||
entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, | entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, | ||||
std::vector<entity_id_t>* out) const | std::vector<entity_id_t>* out) const | ||||
{ | { | ||||
PROFILE("TestStaticShape"); | PROFILE("TestStaticShape"); | ||||
▲ Show 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | if (it->second.x + r < x0 || it->second.x - r > x1 || it->second.z + r < z0 || it->second.z - r > z1) | ||||
continue; | continue; | ||||
// TODO: maybe we should use Geometry::GetHalfBoundingBox to be more precise? | // TODO: maybe we should use Geometry::GetHalfBoundingBox to be more precise? | ||||
squares.emplace_back(ObstructionSquare{ it->second.x, it->second.z, it->second.u, it->second.v, it->second.hw, it->second.hh }); | squares.emplace_back(ObstructionSquare{ it->second.x, it->second.z, it->second.u, it->second.v, it->second.hw, it->second.hh }); | ||||
} | } | ||||
} | } | ||||
void CCmpObstructionManager::GetUnitsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter, bool strict) const | void CCmpObstructionManager::GetUnitsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter) const | ||||
{ | { | ||||
PROFILE("GetUnitsOnObstruction"); | PROFILE("GetUnitsOnObstruction"); | ||||
// In order to avoid getting units on impassable cells, we want to find all | // In order to avoid getting units on impassable cells, we want to find all | ||||
// units subject to the RasterizeRectWithClearance of the building's shape with the | // units subject to the RasterizeRectWithClearance of the building's shape with the | ||||
// unit's clearance covers the navcell the unit is on. | // unit's clearance covers the navcell the unit is on. | ||||
std::vector<entity_id_t> unitShapes; | std::vector<entity_id_t> unitShapes; | ||||
Show All 19 Lines | for (const u32& unitShape : unitShapes) | ||||
{ | { | ||||
// The rasterization is an approximation of the real shapes. | // The rasterization is an approximation of the real shapes. | ||||
// Depending on your use, you may want to be more or less strict on the rasterization, | // Depending on your use, you may want to be more or less strict on the rasterization, | ||||
// ie this may either return some units that aren't actually on the shape (if strict is set) | // ie this may either return some units that aren't actually on the shape (if strict is set) | ||||
// or this may not return some units that are on the shape (if strict is not set). | // or this may not return some units that are on the shape (if strict is not set). | ||||
// Foundations need to be non-strict, as otherwise it sometimes detects the builder units | // Foundations need to be non-strict, as otherwise it sometimes detects the builder units | ||||
// as being on the shape, so it orders them away. | // as being on the shape, so it orders them away. | ||||
SimRasterize::Spans& newSpans = rasterizedRects[shape.clearance]; | SimRasterize::Spans& newSpans = rasterizedRects[shape.clearance]; | ||||
if (strict) | |||||
SimRasterize::RasterizeRectWithClearance(newSpans, square, shape.clearance, Pathfinding::NAVCELL_SIZE); | SimRasterize::RasterizeRectWithClearance(newSpans, square, shape.clearance, Pathfinding::NAVCELL_SIZE); | ||||
else | |||||
SimRasterize::RasterizeRectWithClearance(newSpans, square, shape.clearance-Pathfinding::CLEARANCE_EXTENSION_RADIUS, Pathfinding::NAVCELL_SIZE); | |||||
} | } | ||||
SimRasterize::Spans& spans = rasterizedRects[shape.clearance]; | SimRasterize::Spans& spans = rasterizedRects[shape.clearance]; | ||||
// Check whether the unit's center is on a navcell that's in | // Check whether the unit's center is on a navcell that's in | ||||
// any of the spans | // any of the spans | ||||
u16 i = (shape.x / Pathfinding::NAVCELL_SIZE).ToInt_RoundToNegInfinity(); | u16 i = (shape.x / Pathfinding::NAVCELL_SIZE).ToInt_RoundToNegInfinity(); | ||||
▲ Show 20 Lines • Show All 89 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator