Changeset View
Standalone View
source/simulation2/components/CCmpObstructionManager.cpp
Show All 27 Lines | |||||
#include "simulation2/helpers/Rasterize.h" | #include "simulation2/helpers/Rasterize.h" | ||||
#include "simulation2/helpers/Render.h" | #include "simulation2/helpers/Render.h" | ||||
#include "simulation2/helpers/Spatial.h" | #include "simulation2/helpers/Spatial.h" | ||||
#include "simulation2/serialization/SerializeTemplates.h" | #include "simulation2/serialization/SerializeTemplates.h" | ||||
#include "graphics/Overlay.h" | #include "graphics/Overlay.h" | ||||
#include "graphics/Terrain.h" | #include "graphics/Terrain.h" | ||||
#include "maths/MathUtil.h" | #include "maths/MathUtil.h" | ||||
#include "ps/CLogger.h" | |||||
#include "ps/MutexProtected.h" | |||||
#include "ps/Profile.h" | #include "ps/Profile.h" | ||||
#include "renderer/Scene.h" | #include "renderer/Scene.h" | ||||
#include "ps/CLogger.h" | |||||
#include <mutex> | |||||
// Externally, tags are opaque non-zero positive integers. | // Externally, tags are opaque non-zero positive integers. | ||||
// Internally, they are tagged (by shape) indexes into shape lists. | // Internally, they are tagged (by shape) indexes into shape lists. | ||||
wraitii: forgot to remove these. | |||||
// idx must be non-zero. | // idx must be non-zero. | ||||
#define TAG_IS_VALID(tag) ((tag).valid()) | #define TAG_IS_VALID(tag) ((tag).valid()) | ||||
#define TAG_IS_UNIT(tag) (((tag).n & 1) == 0) | #define TAG_IS_UNIT(tag) (((tag).n & 1) == 0) | ||||
#define TAG_IS_STATIC(tag) (((tag).n & 1) == 1) | #define TAG_IS_STATIC(tag) (((tag).n & 1) == 1) | ||||
#define UNIT_INDEX_TO_TAG(idx) tag_t(((idx) << 1) | 0) | #define UNIT_INDEX_TO_TAG(idx) tag_t(((idx) << 1) | 0) | ||||
#define STATIC_INDEX_TO_TAG(idx) tag_t(((idx) << 1) | 1) | #define STATIC_INDEX_TO_TAG(idx) tag_t(((idx) << 1) | 1) | ||||
#define TAG_TO_INDEX(tag) ((tag).n >> 1) | #define TAG_TO_INDEX(tag) ((tag).n >> 1) | ||||
Show All 23 Lines | struct StaticShape | ||||
entity_id_t group2; | entity_id_t group2; | ||||
}; | }; | ||||
/** | /** | ||||
* Serialization helper template for UnitShape | * Serialization helper template for UnitShape | ||||
*/ | */ | ||||
struct SerializeUnitShape | struct SerializeUnitShape | ||||
{ | { | ||||
template<typename S> | template<typename S, typename UnitShape> | ||||
void operator()(S& serialize, const char* UNUSED(name), UnitShape& value) const | void operator()(S& serialize, const char* UNUSED(name), UnitShape& value) const | ||||
{ | { | ||||
serialize.NumberU32_Unbounded("entity", value.entity); | serialize.NumberU32_Unbounded("entity", value.entity); | ||||
serialize.NumberFixed_Unbounded("x", value.x); | serialize.NumberFixed_Unbounded("x", value.x); | ||||
serialize.NumberFixed_Unbounded("z", value.z); | serialize.NumberFixed_Unbounded("z", value.z); | ||||
serialize.NumberFixed_Unbounded("clearance", value.clearance); | serialize.NumberFixed_Unbounded("clearance", value.clearance); | ||||
serialize.NumberU8_Unbounded("flags", value.flags); | serialize.NumberU8_Unbounded("flags", value.flags); | ||||
serialize.NumberU32_Unbounded("group", value.group); | serialize.NumberU32_Unbounded("group", value.group); | ||||
} | } | ||||
}; | }; | ||||
/** | /** | ||||
* Serialization helper template for StaticShape | * Serialization helper template for StaticShape | ||||
*/ | */ | ||||
struct SerializeStaticShape | struct SerializeStaticShape | ||||
{ | { | ||||
template<typename S> | template<typename S, typename StaticShape> | ||||
void operator()(S& serialize, const char* UNUSED(name), StaticShape& value) const | void operator()(S& serialize, const char* UNUSED(name), StaticShape& value) const | ||||
{ | { | ||||
serialize.NumberU32_Unbounded("entity", value.entity); | serialize.NumberU32_Unbounded("entity", value.entity); | ||||
serialize.NumberFixed_Unbounded("x", value.x); | serialize.NumberFixed_Unbounded("x", value.x); | ||||
serialize.NumberFixed_Unbounded("z", value.z); | serialize.NumberFixed_Unbounded("z", value.z); | ||||
serialize.NumberFixed_Unbounded("u.x", value.u.X); | serialize.NumberFixed_Unbounded("u.x", value.u.X); | ||||
serialize.NumberFixed_Unbounded("u.y", value.u.Y); | serialize.NumberFixed_Unbounded("u.y", value.u.Y); | ||||
serialize.NumberFixed_Unbounded("v.x", value.v.X); | serialize.NumberFixed_Unbounded("v.x", value.v.X); | ||||
Show All 15 Lines | public: | ||||
} | } | ||||
DEFAULT_COMPONENT_ALLOCATOR(ObstructionManager) | DEFAULT_COMPONENT_ALLOCATOR(ObstructionManager) | ||||
bool m_DebugOverlayEnabled; | bool m_DebugOverlayEnabled; | ||||
bool m_DebugOverlayDirty; | bool m_DebugOverlayDirty; | ||||
std::vector<SOverlayLine> m_DebugOverlayLines; | std::vector<SOverlayLine> m_DebugOverlayLines; | ||||
SpatialSubdivision m_UnitSubdivision; | #define PROTECTED_DATA_NAME MutexProtected | ||||
SpatialSubdivision m_StaticSubdivision; | |||||
using UnitShapeType = std::map<u32, UnitShape>; | |||||
using StaticShapeType = std::map<u32, StaticShape>; | |||||
BEGIN_PROTECTED_DATA() | |||||
PROTECTED_DATA(SpatialSubdivision, UnitSubdivision); | |||||
PROTECTED_DATA(SpatialSubdivision, StaticSubdivision); | |||||
// TODO: using std::map is a bit inefficient; is there a better way to store these? | // TODO: using std::map is a bit inefficient; is there a better way to store these? | ||||
Not Done Inline ActionsStill accurate? Stan: Still accurate? | |||||
Not Done Inline Actionsyes wraitii: yes | |||||
Not Done Inline ActionsShould be near to the std::map type usage and not the variable declaration. vladislavbelov: Should be near to the `std::map` type usage and not the variable declaration. | |||||
std::map<u32, UnitShape> m_UnitShapes; | PROTECTED_DATA(UnitShapeType, UnitShapes); | ||||
std::map<u32, StaticShape> m_StaticShapes; | PROTECTED_DATA(StaticShapeType, StaticShapes); | ||||
END_PROTECTED_DATA(); | |||||
PROTECTED_DATA_ACCESSOR(SpatialSubdivision, UnitSubdivision); | |||||
PROTECTED_DATA_ACCESSOR(SpatialSubdivision, StaticSubdivision); | |||||
PROTECTED_DATA_ACCESSOR(UnitShapeType, UnitShapes); | |||||
PROTECTED_DATA_ACCESSOR(StaticShapeType, StaticShapes); | |||||
#undef PROTECTED_DATA_NAME | |||||
Not Done Inline ActionsIf it's protected by the single guard, why you don't move it in a separate class with a proper protection? vladislavbelov: If it's protected by the single guard, why you don't move it in a separate class with a proper… | |||||
u32 m_UnitShapeNext; // next allocated id | u32 m_UnitShapeNext; // next allocated id | ||||
u32 m_StaticShapeNext; | u32 m_StaticShapeNext; | ||||
entity_pos_t m_MaxClearance; | entity_pos_t m_MaxClearance; | ||||
bool m_PassabilityCircular; | bool m_PassabilityCircular; | ||||
entity_pos_t m_WorldX0; | entity_pos_t m_WorldX0; | ||||
Show All 30 Lines | #undef PROTECTED_DATA_NAME | ||||
virtual void Deinit() | virtual void Deinit() | ||||
{ | { | ||||
} | } | ||||
template<typename S> | template<typename S> | ||||
void SerializeCommon(S& serialize) | void SerializeCommon(S& serialize) | ||||
{ | { | ||||
SerializeSpatialSubdivision()(serialize, "unit subdiv", m_UnitSubdivision); | |||||
SerializeSpatialSubdivision()(serialize, "static subdiv", m_StaticSubdivision); | |||||
serialize.NumberFixed_Unbounded("max clearance", m_MaxClearance); | serialize.NumberFixed_Unbounded("max clearance", m_MaxClearance); | ||||
SerializeMap<SerializeU32_Unbounded, SerializeUnitShape>()(serialize, "unit shapes", m_UnitShapes); | |||||
SerializeMap<SerializeU32_Unbounded, SerializeStaticShape>()(serialize, "static shapes", m_StaticShapes); | |||||
serialize.NumberU32_Unbounded("unit shape next", m_UnitShapeNext); | serialize.NumberU32_Unbounded("unit shape next", m_UnitShapeNext); | ||||
serialize.NumberU32_Unbounded("static shape next", m_StaticShapeNext); | serialize.NumberU32_Unbounded("static shape next", m_StaticShapeNext); | ||||
serialize.Bool("circular", m_PassabilityCircular); | serialize.Bool("circular", m_PassabilityCircular); | ||||
serialize.NumberFixed_Unbounded("world x0", m_WorldX0); | serialize.NumberFixed_Unbounded("world x0", m_WorldX0); | ||||
serialize.NumberFixed_Unbounded("world z0", m_WorldZ0); | serialize.NumberFixed_Unbounded("world z0", m_WorldZ0); | ||||
serialize.NumberFixed_Unbounded("world x1", m_WorldX1); | serialize.NumberFixed_Unbounded("world x1", m_WorldX1); | ||||
serialize.NumberFixed_Unbounded("world z1", m_WorldZ1); | serialize.NumberFixed_Unbounded("world z1", m_WorldZ1); | ||||
serialize.NumberU16_Unbounded("terrain tiles", m_TerrainTiles); | serialize.NumberU16_Unbounded("terrain tiles", m_TerrainTiles); | ||||
} | } | ||||
virtual void Serialize(ISerializer& serialize) | virtual void Serialize(ISerializer& serialize) | ||||
{ | { | ||||
// TODO: this could perhaps be optimised by not storing all the obstructions, | // TODO: this could perhaps be optimised by not storing all the obstructions, | ||||
// and instead regenerating them from the other entities on Deserialize | // and instead regenerating them from the other entities on Deserialize | ||||
SerializeSpatialSubdivision()(serialize, "unit subdiv", UnitSubdivision()); | |||||
SerializeSpatialSubdivision()(serialize, "static subdiv", StaticSubdivision()); | |||||
SerializeMap<SerializeU32_Unbounded, SerializeUnitShape>()(serialize, "unit shapes", UnitShapes()); | |||||
SerializeMap<SerializeU32_Unbounded, SerializeStaticShape>()(serialize, "static shapes", StaticShapes()); | |||||
SerializeCommon(serialize); | SerializeCommon(serialize); | ||||
} | } | ||||
virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) | virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) | ||||
{ | { | ||||
Init(paramNode); | Init(paramNode); | ||||
MutexProtected::Lock lock(m_MutexProtectedData); | |||||
SerializeSpatialSubdivision()(deserialize, "unit subdiv", UnitSubdivision(lock)); | |||||
SerializeSpatialSubdivision()(deserialize, "static subdiv", StaticSubdivision(lock)); | |||||
SerializeMap<SerializeU32_Unbounded, SerializeUnitShape>()(deserialize, "unit shapes", UnitShapes(lock)); | |||||
SerializeMap<SerializeU32_Unbounded, SerializeStaticShape>()(deserialize, "static shapes", StaticShapes(lock)); | |||||
SerializeCommon(deserialize); | SerializeCommon(deserialize); | ||||
m_UpdateInformations.dirtinessGrid = Grid<u8>(m_TerrainTiles*Pathfinding::NAVCELLS_PER_TILE, m_TerrainTiles*Pathfinding::NAVCELLS_PER_TILE); | m_UpdateInformations.dirtinessGrid = Grid<u8>(m_TerrainTiles*Pathfinding::NAVCELLS_PER_TILE, m_TerrainTiles*Pathfinding::NAVCELLS_PER_TILE); | ||||
} | } | ||||
virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) | virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) | ||||
{ | { | ||||
switch (msg.GetType()) | switch (msg.GetType()) | ||||
Show All 30 Lines | virtual void SetBounds(entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1) | ||||
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); | CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); | ||||
if (cmpPathfinder) | if (cmpPathfinder) | ||||
m_MaxClearance = cmpPathfinder->GetMaximumClearance(); | m_MaxClearance = cmpPathfinder->GetMaximumClearance(); | ||||
} | } | ||||
void ResetSubdivisions(entity_pos_t x1, entity_pos_t z1) | void ResetSubdivisions(entity_pos_t x1, entity_pos_t z1) | ||||
{ | { | ||||
MutexProtected::Lock lock(m_MutexProtectedData); | |||||
Not Done Inline ActionsIt seems that this method will be acquiring/releasing locks frequently, wouldn't it be more efficient to have one global lock during its execution ? kilobug: It seems that this method will be acquiring/releasing locks frequently, wouldn't it be more… | |||||
Not Done Inline Actions@Kuba386 can you run some profiling to see if it's better/worse? Stan: @Kuba386 can you run some profiling to see if it's better/worse? | |||||
Not Done Inline ActionsWe hardly ever reset the subdivisions, so it should be fine. wraitii: We hardly ever reset the subdivisions, so it should be fine. | |||||
// Use 8x8 tile subdivisions | // Use 8x8 tile subdivisions | ||||
// (TODO: find the optimal number instead of blindly guessing) | // (TODO: find the optimal number instead of blindly guessing) | ||||
m_UnitSubdivision.Reset(x1, z1, entity_pos_t::FromInt(8*TERRAIN_TILE_SIZE)); | UnitSubdivision(lock).Reset(x1, z1, entity_pos_t::FromInt(8*TERRAIN_TILE_SIZE)); | ||||
m_StaticSubdivision.Reset(x1, z1, entity_pos_t::FromInt(8*TERRAIN_TILE_SIZE)); | StaticSubdivision(lock).Reset(x1, z1, entity_pos_t::FromInt(8*TERRAIN_TILE_SIZE)); | ||||
Not Done Inline ActionsPassing (lock) to each variable seems odd. vladislavbelov: Passing `(lock)` to each variable seems odd. | |||||
for (std::map<u32, UnitShape>::iterator it = m_UnitShapes.begin(); it != m_UnitShapes.end(); ++it) | for (std::map<u32, UnitShape>::iterator it = UnitShapes(lock).begin(); it != UnitShapes(lock).end(); ++it) | ||||
StanUnsubmitted Not Done Inline ActionsCan the iterator be const? Stan: Can the iterator be const? | |||||
Kuba386Unsubmitted Done Inline ActionsIt could be I guess Kuba386: It could be I guess | |||||
{ | { | ||||
CFixedVector2D center(it->second.x, it->second.z); | CFixedVector2D center(it->second.x, it->second.z); | ||||
CFixedVector2D halfSize(it->second.clearance, it->second.clearance); | CFixedVector2D halfSize(it->second.clearance, it->second.clearance); | ||||
m_UnitSubdivision.Add(it->first, center - halfSize, center + halfSize); | UnitSubdivision(lock).Add(it->first, center - halfSize, center + halfSize); | ||||
} | } | ||||
for (std::map<u32, StaticShape>::iterator it = m_StaticShapes.begin(); it != m_StaticShapes.end(); ++it) | for (std::map<u32, StaticShape>::iterator it = StaticShapes(lock).begin(); it != StaticShapes(lock).end(); ++it) | ||||
StanUnsubmitted Not Done Inline ActionsSame here Stan: Same here | |||||
{ | { | ||||
CFixedVector2D center(it->second.x, it->second.z); | CFixedVector2D center(it->second.x, it->second.z); | ||||
CFixedVector2D bbHalfSize = Geometry::GetHalfBoundingBox(it->second.u, it->second.v, CFixedVector2D(it->second.hw, it->second.hh)); | CFixedVector2D bbHalfSize = Geometry::GetHalfBoundingBox(it->second.u, it->second.v, CFixedVector2D(it->second.hw, it->second.hh)); | ||||
m_StaticSubdivision.Add(it->first, center - bbHalfSize, center + bbHalfSize); | StaticSubdivision(lock).Add(it->first, center - bbHalfSize, center + bbHalfSize); | ||||
} | } | ||||
} | } | ||||
virtual tag_t AddUnitShape(entity_id_t ent, entity_pos_t x, entity_pos_t z, entity_pos_t clearance, flags_t flags, entity_id_t group) | virtual tag_t AddUnitShape(entity_id_t ent, entity_pos_t x, entity_pos_t z, entity_pos_t clearance, flags_t flags, entity_id_t group) | ||||
{ | { | ||||
MutexProtected::Lock lock(m_MutexProtectedData); | |||||
Not Done Inline ActionsLocking the mutex for each unit addition seems overhead, especially in case you know time bounds of the obstructions lock. vladislavbelov: Locking the mutex for each unit addition seems overhead, especially in case you know time… | |||||
UnitShape shape = { ent, x, z, clearance, flags, group }; | UnitShape shape = { ent, x, z, clearance, flags, group }; | ||||
u32 id = m_UnitShapeNext++; | u32 id = m_UnitShapeNext++; | ||||
m_UnitShapes[id] = shape; | UnitShapes(lock)[id] = shape; | ||||
m_UnitSubdivision.Add(id, CFixedVector2D(x - clearance, z - clearance), CFixedVector2D(x + clearance, z + clearance)); | UnitSubdivision(lock).Add(id, CFixedVector2D(x - clearance, z - clearance), CFixedVector2D(x + clearance, z + clearance)); | ||||
MakeDirtyUnit(flags, id, shape); | MakeDirtyUnit(flags, id, shape); | ||||
return UNIT_INDEX_TO_TAG(id); | return UNIT_INDEX_TO_TAG(id); | ||||
} | } | ||||
virtual tag_t AddStaticShape(entity_id_t ent, entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h, flags_t flags, entity_id_t group, entity_id_t group2 /* = INVALID_ENTITY */) | virtual tag_t AddStaticShape(entity_id_t ent, entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h, flags_t flags, entity_id_t group, entity_id_t group2 /* = INVALID_ENTITY */) | ||||
{ | { | ||||
MutexProtected::Lock lock(m_MutexProtectedData); | |||||
fixed s, c; | fixed s, c; | ||||
sincos_approx(a, s, c); | sincos_approx(a, s, c); | ||||
CFixedVector2D u(c, -s); | CFixedVector2D u(c, -s); | ||||
CFixedVector2D v(s, c); | CFixedVector2D v(s, c); | ||||
StaticShape shape = { ent, x, z, u, v, w/2, h/2, flags, group, group2 }; | StaticShape shape = { ent, x, z, u, v, w/2, h/2, flags, group, group2 }; | ||||
u32 id = m_StaticShapeNext++; | u32 id = m_StaticShapeNext++; | ||||
m_StaticShapes[id] = shape; | StaticShapes(lock)[id] = shape; | ||||
CFixedVector2D center(x, z); | CFixedVector2D center(x, z); | ||||
CFixedVector2D bbHalfSize = Geometry::GetHalfBoundingBox(u, v, CFixedVector2D(w/2, h/2)); | CFixedVector2D bbHalfSize = Geometry::GetHalfBoundingBox(u, v, CFixedVector2D(w/2, h/2)); | ||||
m_StaticSubdivision.Add(id, center - bbHalfSize, center + bbHalfSize); | StaticSubdivision(lock).Add(id, center - bbHalfSize, center + bbHalfSize); | ||||
MakeDirtyStatic(flags, id, shape); | MakeDirtyStatic(flags, id, shape); | ||||
return STATIC_INDEX_TO_TAG(id); | return STATIC_INDEX_TO_TAG(id); | ||||
} | } | ||||
virtual ObstructionSquare GetUnitShapeObstruction(entity_pos_t x, entity_pos_t z, entity_pos_t clearance) const | virtual ObstructionSquare GetUnitShapeObstruction(entity_pos_t x, entity_pos_t z, entity_pos_t clearance) const | ||||
{ | { | ||||
Show All 11 Lines | virtual ObstructionSquare GetStaticShapeObstruction(entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h) const | ||||
CFixedVector2D v(s, c); | CFixedVector2D v(s, c); | ||||
ObstructionSquare o = { x, z, u, v, w/2, h/2 }; | ObstructionSquare o = { x, z, u, v, w/2, h/2 }; | ||||
return o; | return o; | ||||
} | } | ||||
virtual void MoveShape(tag_t tag, entity_pos_t x, entity_pos_t z, entity_angle_t a) | virtual void MoveShape(tag_t tag, entity_pos_t x, entity_pos_t z, entity_angle_t a) | ||||
{ | { | ||||
MutexProtected::Lock lock(m_MutexProtectedData); | |||||
ENSURE(TAG_IS_VALID(tag)); | ENSURE(TAG_IS_VALID(tag)); | ||||
if (TAG_IS_UNIT(tag)) | if (TAG_IS_UNIT(tag)) | ||||
{ | { | ||||
UnitShape& shape = m_UnitShapes[TAG_TO_INDEX(tag)]; | UnitShape& shape = UnitShapes(lock)[TAG_TO_INDEX(tag)]; | ||||
MakeDirtyUnit(shape.flags, TAG_TO_INDEX(tag), shape); // dirty the old shape region | MakeDirtyUnit(shape.flags, TAG_TO_INDEX(tag), shape); // dirty the old shape region | ||||
m_UnitSubdivision.Move(TAG_TO_INDEX(tag), | UnitSubdivision(lock).Move(TAG_TO_INDEX(tag), | ||||
CFixedVector2D(shape.x - shape.clearance, shape.z - shape.clearance), | CFixedVector2D(shape.x - shape.clearance, shape.z - shape.clearance), | ||||
CFixedVector2D(shape.x + shape.clearance, shape.z + shape.clearance), | CFixedVector2D(shape.x + shape.clearance, shape.z + shape.clearance), | ||||
CFixedVector2D(x - shape.clearance, z - shape.clearance), | CFixedVector2D(x - shape.clearance, z - shape.clearance), | ||||
CFixedVector2D(x + shape.clearance, z + shape.clearance)); | CFixedVector2D(x + shape.clearance, z + shape.clearance)); | ||||
shape.x = x; | shape.x = x; | ||||
shape.z = z; | shape.z = z; | ||||
MakeDirtyUnit(shape.flags, TAG_TO_INDEX(tag), shape); // dirty the new shape region | MakeDirtyUnit(shape.flags, TAG_TO_INDEX(tag), shape); // dirty the new shape region | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
fixed s, c; | fixed s, c; | ||||
sincos_approx(a, s, c); | sincos_approx(a, s, c); | ||||
CFixedVector2D u(c, -s); | CFixedVector2D u(c, -s); | ||||
CFixedVector2D v(s, c); | CFixedVector2D v(s, c); | ||||
StaticShape& shape = m_StaticShapes[TAG_TO_INDEX(tag)]; | StaticShape& shape = StaticShapes(lock)[TAG_TO_INDEX(tag)]; | ||||
MakeDirtyStatic(shape.flags, TAG_TO_INDEX(tag), shape); // dirty the old shape region | MakeDirtyStatic(shape.flags, TAG_TO_INDEX(tag), shape); // dirty the old shape region | ||||
CFixedVector2D fromBbHalfSize = Geometry::GetHalfBoundingBox(shape.u, shape.v, CFixedVector2D(shape.hw, shape.hh)); | CFixedVector2D fromBbHalfSize = Geometry::GetHalfBoundingBox(shape.u, shape.v, CFixedVector2D(shape.hw, shape.hh)); | ||||
CFixedVector2D toBbHalfSize = Geometry::GetHalfBoundingBox(u, v, CFixedVector2D(shape.hw, shape.hh)); | CFixedVector2D toBbHalfSize = Geometry::GetHalfBoundingBox(u, v, CFixedVector2D(shape.hw, shape.hh)); | ||||
m_StaticSubdivision.Move(TAG_TO_INDEX(tag), | StaticSubdivision(lock).Move(TAG_TO_INDEX(tag), | ||||
CFixedVector2D(shape.x, shape.z) - fromBbHalfSize, | CFixedVector2D(shape.x, shape.z) - fromBbHalfSize, | ||||
CFixedVector2D(shape.x, shape.z) + fromBbHalfSize, | CFixedVector2D(shape.x, shape.z) + fromBbHalfSize, | ||||
CFixedVector2D(x, z) - toBbHalfSize, | CFixedVector2D(x, z) - toBbHalfSize, | ||||
CFixedVector2D(x, z) + toBbHalfSize); | CFixedVector2D(x, z) + toBbHalfSize); | ||||
shape.x = x; | shape.x = x; | ||||
shape.z = z; | shape.z = z; | ||||
shape.u = u; | shape.u = u; | ||||
shape.v = v; | shape.v = v; | ||||
MakeDirtyStatic(shape.flags, TAG_TO_INDEX(tag), shape); // dirty the new shape region | MakeDirtyStatic(shape.flags, TAG_TO_INDEX(tag), shape); // dirty the new shape region | ||||
} | } | ||||
} | } | ||||
virtual void SetUnitMovingFlag(tag_t tag, bool moving) | virtual void SetUnitMovingFlag(tag_t tag, bool moving) | ||||
{ | { | ||||
MutexProtected::Lock lock(m_MutexProtectedData); | |||||
ENSURE(TAG_IS_VALID(tag) && TAG_IS_UNIT(tag)); | ENSURE(TAG_IS_VALID(tag) && TAG_IS_UNIT(tag)); | ||||
if (TAG_IS_UNIT(tag)) | if (TAG_IS_UNIT(tag)) | ||||
{ | { | ||||
UnitShape& shape = m_UnitShapes[TAG_TO_INDEX(tag)]; | UnitShape& shape = UnitShapes(lock)[TAG_TO_INDEX(tag)]; | ||||
if (moving) | if (moving) | ||||
shape.flags |= FLAG_MOVING; | shape.flags |= FLAG_MOVING; | ||||
else | else | ||||
shape.flags &= (flags_t)~FLAG_MOVING; | shape.flags &= (flags_t)~FLAG_MOVING; | ||||
MakeDirtyDebug(); | MakeDirtyDebug(); | ||||
} | } | ||||
} | } | ||||
virtual void SetUnitControlGroup(tag_t tag, entity_id_t group) | virtual void SetUnitControlGroup(tag_t tag, entity_id_t group) | ||||
{ | { | ||||
MutexProtected::Lock lock(m_MutexProtectedData); | |||||
ENSURE(TAG_IS_VALID(tag) && TAG_IS_UNIT(tag)); | ENSURE(TAG_IS_VALID(tag) && TAG_IS_UNIT(tag)); | ||||
if (TAG_IS_UNIT(tag)) | if (TAG_IS_UNIT(tag)) | ||||
{ | { | ||||
UnitShape& shape = m_UnitShapes[TAG_TO_INDEX(tag)]; | UnitShape& shape = UnitShapes(lock)[TAG_TO_INDEX(tag)]; | ||||
shape.group = group; | shape.group = group; | ||||
} | } | ||||
} | } | ||||
virtual void SetStaticControlGroup(tag_t tag, entity_id_t group, entity_id_t group2) | virtual void SetStaticControlGroup(tag_t tag, entity_id_t group, entity_id_t group2) | ||||
{ | { | ||||
MutexProtected::Lock lock(m_MutexProtectedData); | |||||
ENSURE(TAG_IS_VALID(tag) && TAG_IS_STATIC(tag)); | ENSURE(TAG_IS_VALID(tag) && TAG_IS_STATIC(tag)); | ||||
if (TAG_IS_STATIC(tag)) | if (TAG_IS_STATIC(tag)) | ||||
{ | { | ||||
StaticShape& shape = m_StaticShapes[TAG_TO_INDEX(tag)]; | StaticShape& shape = StaticShapes(lock)[TAG_TO_INDEX(tag)]; | ||||
shape.group = group; | shape.group = group; | ||||
shape.group2 = group2; | shape.group2 = group2; | ||||
} | } | ||||
} | } | ||||
virtual void RemoveShape(tag_t tag) | virtual void RemoveShape(tag_t tag) | ||||
{ | { | ||||
MutexProtected::Lock lock(m_MutexProtectedData); | |||||
ENSURE(TAG_IS_VALID(tag)); | ENSURE(TAG_IS_VALID(tag)); | ||||
if (TAG_IS_UNIT(tag)) | if (TAG_IS_UNIT(tag)) | ||||
{ | { | ||||
UnitShape& shape = m_UnitShapes[TAG_TO_INDEX(tag)]; | UnitShape& shape = UnitShapes(lock)[TAG_TO_INDEX(tag)]; | ||||
m_UnitSubdivision.Remove(TAG_TO_INDEX(tag), | UnitSubdivision(lock).Remove(TAG_TO_INDEX(tag), | ||||
CFixedVector2D(shape.x - shape.clearance, shape.z - shape.clearance), | CFixedVector2D(shape.x - shape.clearance, shape.z - shape.clearance), | ||||
CFixedVector2D(shape.x + shape.clearance, shape.z + shape.clearance)); | CFixedVector2D(shape.x + shape.clearance, shape.z + shape.clearance)); | ||||
MakeDirtyUnit(shape.flags, TAG_TO_INDEX(tag), shape); | MakeDirtyUnit(shape.flags, TAG_TO_INDEX(tag), shape); | ||||
m_UnitShapes.erase(TAG_TO_INDEX(tag)); | UnitShapes(lock).erase(TAG_TO_INDEX(tag)); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
StaticShape& shape = m_StaticShapes[TAG_TO_INDEX(tag)]; | StaticShape& shape = StaticShapes(lock)[TAG_TO_INDEX(tag)]; | ||||
CFixedVector2D center(shape.x, shape.z); | CFixedVector2D center(shape.x, shape.z); | ||||
CFixedVector2D bbHalfSize = Geometry::GetHalfBoundingBox(shape.u, shape.v, CFixedVector2D(shape.hw, shape.hh)); | CFixedVector2D bbHalfSize = Geometry::GetHalfBoundingBox(shape.u, shape.v, CFixedVector2D(shape.hw, shape.hh)); | ||||
m_StaticSubdivision.Remove(TAG_TO_INDEX(tag), center - bbHalfSize, center + bbHalfSize); | StaticSubdivision(lock).Remove(TAG_TO_INDEX(tag), center - bbHalfSize, center + bbHalfSize); | ||||
MakeDirtyStatic(shape.flags, TAG_TO_INDEX(tag), shape); | MakeDirtyStatic(shape.flags, TAG_TO_INDEX(tag), shape); | ||||
m_StaticShapes.erase(TAG_TO_INDEX(tag)); | StaticShapes(lock).erase(TAG_TO_INDEX(tag)); | ||||
} | } | ||||
} | } | ||||
virtual ObstructionSquare GetObstruction(tag_t tag) const | virtual ObstructionSquare GetObstruction(tag_t tag) const | ||||
{ | { | ||||
ENSURE(TAG_IS_VALID(tag)); | ENSURE(TAG_IS_VALID(tag)); | ||||
if (TAG_IS_UNIT(tag)) | if (TAG_IS_UNIT(tag)) | ||||
{ | { | ||||
const UnitShape& shape = m_UnitShapes.at(TAG_TO_INDEX(tag)); | const UnitShape& shape = UnitShapes().at(TAG_TO_INDEX(tag)); | ||||
CFixedVector2D u(entity_pos_t::FromInt(1), entity_pos_t::Zero()); | CFixedVector2D u(entity_pos_t::FromInt(1), entity_pos_t::Zero()); | ||||
CFixedVector2D v(entity_pos_t::Zero(), entity_pos_t::FromInt(1)); | CFixedVector2D v(entity_pos_t::Zero(), entity_pos_t::FromInt(1)); | ||||
ObstructionSquare o = { shape.x, shape.z, u, v, shape.clearance, shape.clearance }; | ObstructionSquare o = { shape.x, shape.z, u, v, shape.clearance, shape.clearance }; | ||||
return o; | return o; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
const StaticShape& shape = m_StaticShapes.at(TAG_TO_INDEX(tag)); | const StaticShape& shape = 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 fixed MaxDistanceToPoint(entity_id_t ent, entity_pos_t px, entity_pos_t pz) const; | virtual fixed MaxDistanceToPoint(entity_id_t ent, entity_pos_t px, entity_pos_t pz) const; | ||||
virtual fixed DistanceToTarget(entity_id_t ent, entity_id_t target) const; | virtual fixed DistanceToTarget(entity_id_t ent, entity_id_t target) const; | ||||
Show All 12 Lines | #undef PROTECTED_DATA_NAME | ||||
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, bool strict = false) 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 LockObstructions() | |||||
{ | |||||
m_MutexProtectedData.m_LockShapesMutex.lock(); | |||||
} | |||||
virtual void UnlockObstructions() | |||||
{ | |||||
m_MutexProtectedData.m_LockShapesMutex.unlock(); | |||||
} | |||||
virtual void SetPassabilityCircular(bool enabled) | virtual void SetPassabilityCircular(bool enabled) | ||||
{ | { | ||||
m_PassabilityCircular = enabled; | m_PassabilityCircular = enabled; | ||||
MakeDirtyAll(); | MakeDirtyAll(); | ||||
CMessageObstructionMapShapeChanged msg; | CMessageObstructionMapShapeChanged msg; | ||||
GetSimContext().GetComponentManager().BroadcastMessage(msg); | GetSimContext().GetComponentManager().BroadcastMessage(msg); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | if (flags & (FLAG_BLOCK_PATHFINDING | FLAG_BLOCK_FOUNDATION)) | ||||
// and we need to get the shapes whose clearance can overlap this area. So we need to extend the search area | // and we need to get the shapes whose clearance can overlap this area. So we need to extend the search area | ||||
// by two times the maximum clearance. | // by two times the maximum clearance. | ||||
CFixedVector2D center(shape.x, shape.z); | CFixedVector2D center(shape.x, shape.z); | ||||
CFixedVector2D hbox = Geometry::GetHalfBoundingBox(shape.u, shape.v, CFixedVector2D(shape.hw, shape.hh)); | CFixedVector2D hbox = Geometry::GetHalfBoundingBox(shape.u, shape.v, CFixedVector2D(shape.hw, shape.hh)); | ||||
CFixedVector2D expand(m_MaxClearance, m_MaxClearance); | CFixedVector2D expand(m_MaxClearance, m_MaxClearance); | ||||
std::vector<u32> staticsNear; | std::vector<u32> staticsNear; | ||||
m_StaticSubdivision.GetInRange(staticsNear, center - hbox - expand*2, center + hbox + expand*2); | StaticSubdivision().GetInRange(staticsNear, center - hbox - expand*2, center + hbox + expand*2); | ||||
for (u32& staticId : staticsNear) | for (u32& staticId : staticsNear) | ||||
if (std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), staticId) == m_DirtyStaticShapes.end()) | if (std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), staticId) == m_DirtyStaticShapes.end()) | ||||
m_DirtyStaticShapes.push_back(staticId); | m_DirtyStaticShapes.push_back(staticId); | ||||
std::vector<u32> unitsNear; | std::vector<u32> unitsNear; | ||||
m_UnitSubdivision.GetInRange(unitsNear, center - hbox - expand*2, center + hbox + expand*2); | UnitSubdivision().GetInRange(unitsNear, center - hbox - expand*2, center + hbox + expand*2); | ||||
for (u32& unitId : unitsNear) | for (u32& unitId : unitsNear) | ||||
if (std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), unitId) == m_DirtyUnitShapes.end()) | if (std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), unitId) == m_DirtyUnitShapes.end()) | ||||
m_DirtyUnitShapes.push_back(unitId); | m_DirtyUnitShapes.push_back(unitId); | ||||
MarkDirtinessGrid(shape.x, shape.z, hbox + expand); | MarkDirtinessGrid(shape.x, shape.z, hbox + expand); | ||||
} | } | ||||
} | } | ||||
Show All 15 Lines | if (flags & (FLAG_BLOCK_PATHFINDING | FLAG_BLOCK_FOUNDATION)) | ||||
// All shapes overlapping the updated part of the grid should be dirtied too. | // All shapes overlapping the updated part of the grid should be dirtied too. | ||||
// We are going to invalidate the region of the grid corresponding to the modified shape plus its clearance, | // We are going to invalidate the region of the grid corresponding to the modified shape plus its clearance, | ||||
// and we need to get the shapes whose clearance can overlap this area. So we need to extend the search area | // and we need to get the shapes whose clearance can overlap this area. So we need to extend the search area | ||||
// by two times the maximum clearance. | // by two times the maximum clearance. | ||||
CFixedVector2D center(shape.x, shape.z); | CFixedVector2D center(shape.x, shape.z); | ||||
std::vector<u32> staticsNear; | std::vector<u32> staticsNear; | ||||
m_StaticSubdivision.GetNear(staticsNear, center, shape.clearance + m_MaxClearance*2); | StaticSubdivision().GetNear(staticsNear, center, shape.clearance + m_MaxClearance*2); | ||||
for (u32& staticId : staticsNear) | for (u32& staticId : staticsNear) | ||||
Not Done Inline Actions& useless ? Stan: & useless ? | |||||
if (std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), staticId) == m_DirtyStaticShapes.end()) | if (std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), staticId) == m_DirtyStaticShapes.end()) | ||||
m_DirtyStaticShapes.push_back(staticId); | m_DirtyStaticShapes.push_back(staticId); | ||||
std::vector<u32> unitsNear; | std::vector<u32> unitsNear; | ||||
m_UnitSubdivision.GetNear(unitsNear, center, shape.clearance + m_MaxClearance*2); | UnitSubdivision().GetNear(unitsNear, center, shape.clearance + m_MaxClearance*2); | ||||
for (u32& unitId : unitsNear) | for (u32& unitId : unitsNear) | ||||
Not Done Inline Actions& useless ? Stan: & useless ? | |||||
if (std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), unitId) == m_DirtyUnitShapes.end()) | if (std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), unitId) == m_DirtyUnitShapes.end()) | ||||
m_DirtyUnitShapes.push_back(unitId); | m_DirtyUnitShapes.push_back(unitId); | ||||
MarkDirtinessGrid(shape.x, shape.z, shape.clearance + m_MaxClearance); | MarkDirtinessGrid(shape.x, shape.z, shape.clearance + m_MaxClearance); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
▲ Show 20 Lines • Show All 215 Lines • ▼ Show 20 Lines | 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 | ||||
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. | // actual radius used for unit-unit collisions. If relaxClearanceForUnits, will be smaller to allow more overlap. | ||||
entity_pos_t unitUnitRadius = r; | entity_pos_t unitUnitRadius = r; | ||||
if (relaxClearanceForUnits) | if (relaxClearanceForUnits) | ||||
unitUnitRadius -= entity_pos_t::FromInt(1)/2; | 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); | UnitSubdivision().GetInRange(unitShapes, posMin, posMax); | ||||
for (const entity_id_t& shape : unitShapes) | for (const entity_id_t& shape : unitShapes) | ||||
Not Done Inline Actionsfor (entity_id_t shape : staticShapes) https://stackoverflow.com/questions/9637856/why-is-const-int-faster-than-const-int Stan: for (entity_id_t shape : staticShapes)
https://stackoverflow.com/questions/9637856/why-is… | |||||
Not Done Inline ActionsErr too much copy paste unitShapes for (entity_id_t shape : unitShapes) Stan: Err too much copy paste unitShapes
```
for (entity_id_t shape : unitShapes)
``` | |||||
{ | { | ||||
std::map<u32, UnitShape>::const_iterator it = m_UnitShapes.find(shape); | std::map<u32, UnitShape>::const_iterator it = UnitShapes().find(shape); | ||||
ENSURE(it != m_UnitShapes.end()); | ENSURE(it != 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; | std::vector<entity_id_t> staticShapes; | ||||
m_StaticSubdivision.GetInRange(staticShapes, posMin, posMax); | StaticSubdivision().GetInRange(staticShapes, posMin, posMax); | ||||
for (const entity_id_t& shape : staticShapes) | for (const entity_id_t& shape : staticShapes) | ||||
Not Done Inline Actionsfor (entity_id_t shape : staticShapes) https://stackoverflow.com/questions/9637856/why-is-const-int-faster-than-const-int Stan: ```
for (entity_id_t shape : staticShapes)
```
https://stackoverflow. | |||||
{ | { | ||||
std::map<u32, StaticShape>::const_iterator it = m_StaticShapes.find(shape); | std::map<u32, StaticShape>::const_iterator it = StaticShapes().find(shape); | ||||
ENSURE(it != m_StaticShapes.end()); | ENSURE(it != StaticShapes().end()); | ||||
if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) | if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) | ||||
continue; | continue; | ||||
CFixedVector2D center(it->second.x, it->second.z); | CFixedVector2D center(it->second.x, it->second.z); | ||||
CFixedVector2D halfSize(it->second.hw + r, it->second.hh + r); | 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)) | if (Geometry::TestRaySquare(CFixedVector2D(x0, z0) - center, CFixedVector2D(x1, z1) - center, it->second.u, it->second.v, halfSize)) | ||||
return true; | return true; | ||||
Show All 31 Lines | bool CCmpObstructionManager::TestStaticShape(const IObstructionTestFilter& filter, | ||||
} | } | ||||
fixed bbHalfWidth = std::max(corner1.X.Absolute(), corner2.X.Absolute()); | fixed bbHalfWidth = std::max(corner1.X.Absolute(), corner2.X.Absolute()); | ||||
fixed bbHalfHeight = std::max(corner1.Y.Absolute(), corner2.Y.Absolute()); | fixed bbHalfHeight = std::max(corner1.Y.Absolute(), corner2.Y.Absolute()); | ||||
CFixedVector2D posMin(x - bbHalfWidth, z - bbHalfHeight); | CFixedVector2D posMin(x - bbHalfWidth, z - bbHalfHeight); | ||||
CFixedVector2D posMax(x + bbHalfWidth, z + bbHalfHeight); | CFixedVector2D posMax(x + bbHalfWidth, z + bbHalfHeight); | ||||
std::vector<entity_id_t> unitShapes; | std::vector<entity_id_t> unitShapes; | ||||
m_UnitSubdivision.GetInRange(unitShapes, posMin, posMax); | UnitSubdivision().GetInRange(unitShapes, posMin, posMax); | ||||
for (entity_id_t& shape : unitShapes) | for (entity_id_t& shape : unitShapes) | ||||
Not Done Inline ActionsI guess the & is useless there Stan: I guess the & is useless there | |||||
{ | { | ||||
std::map<u32, UnitShape>::const_iterator it = m_UnitShapes.find(shape); | std::map<u32, UnitShape>::const_iterator it = UnitShapes().find(shape); | ||||
ENSURE(it != m_UnitShapes.end()); | ENSURE(it != 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 center1(it->second.x, it->second.z); | CFixedVector2D center1(it->second.x, it->second.z); | ||||
if (Geometry::PointIsInSquare(center1 - center, u, v, CFixedVector2D(halfSize.X + it->second.clearance, halfSize.Y + it->second.clearance))) | if (Geometry::PointIsInSquare(center1 - center, u, v, CFixedVector2D(halfSize.X + it->second.clearance, halfSize.Y + it->second.clearance))) | ||||
{ | { | ||||
if (out) | if (out) | ||||
out->push_back(it->second.entity); | out->push_back(it->second.entity); | ||||
else | else | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
std::vector<entity_id_t> staticShapes; | std::vector<entity_id_t> staticShapes; | ||||
m_StaticSubdivision.GetInRange(staticShapes, posMin, posMax); | StaticSubdivision().GetInRange(staticShapes, posMin, posMax); | ||||
for (entity_id_t& shape : staticShapes) | for (entity_id_t& shape : staticShapes) | ||||
{ | { | ||||
std::map<u32, StaticShape>::const_iterator it = m_StaticShapes.find(shape); | std::map<u32, StaticShape>::const_iterator it = StaticShapes().find(shape); | ||||
ENSURE(it != m_StaticShapes.end()); | ENSURE(it != StaticShapes().end()); | ||||
if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) | if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) | ||||
continue; | continue; | ||||
CFixedVector2D center1(it->second.x, it->second.z); | CFixedVector2D center1(it->second.x, it->second.z); | ||||
CFixedVector2D halfSize1(it->second.hw, it->second.hh); | CFixedVector2D halfSize1(it->second.hw, it->second.hh); | ||||
if (Geometry::TestSquareSquare(center, u, v, halfSize, center1, it->second.u, it->second.v, halfSize1)) | if (Geometry::TestSquareSquare(center, u, v, halfSize, center1, it->second.u, it->second.v, halfSize1)) | ||||
{ | { | ||||
Show All 25 Lines | else | ||||
return true; | return true; | ||||
} | } | ||||
CFixedVector2D center(x, z); | CFixedVector2D center(x, z); | ||||
CFixedVector2D posMin(x - clearance, z - clearance); | CFixedVector2D posMin(x - clearance, z - clearance); | ||||
CFixedVector2D posMax(x + clearance, z + clearance); | CFixedVector2D posMax(x + clearance, z + clearance); | ||||
std::vector<entity_id_t> unitShapes; | std::vector<entity_id_t> unitShapes; | ||||
m_UnitSubdivision.GetInRange(unitShapes, posMin, posMax); | UnitSubdivision().GetInRange(unitShapes, posMin, posMax); | ||||
for (const entity_id_t& shape : unitShapes) | for (const entity_id_t& shape : unitShapes) | ||||
StanUnsubmitted Not Done Inline ActionsStan: That's a int right? https://stackoverflow.com/questions/9637856/why-is-const-int-faster-than… | |||||
Kuba386Unsubmitted Done Inline ActionsWow, didn't know about that.. Kuba386: Wow, didn't know about that.. | |||||
{ | { | ||||
std::map<u32, UnitShape>::const_iterator it = m_UnitShapes.find(shape); | std::map<u32, UnitShape>::const_iterator it = UnitShapes().find(shape); | ||||
ENSURE(it != m_UnitShapes.end()); | ENSURE(it != 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; | ||||
entity_pos_t c1 = it->second.clearance; | entity_pos_t c1 = it->second.clearance; | ||||
if (!( | if (!( | ||||
it->second.x + c1 < x - clearance || | it->second.x + c1 < x - clearance || | ||||
it->second.x - c1 > x + clearance || | it->second.x - c1 > x + clearance || | ||||
it->second.z + c1 < z - clearance || | it->second.z + c1 < z - clearance || | ||||
it->second.z - c1 > z + clearance)) | it->second.z - c1 > z + clearance)) | ||||
{ | { | ||||
if (out) | if (out) | ||||
out->push_back(it->second.entity); | out->push_back(it->second.entity); | ||||
else | else | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
std::vector<entity_id_t> staticShapes; | std::vector<entity_id_t> staticShapes; | ||||
m_StaticSubdivision.GetInRange(staticShapes, posMin, posMax); | StaticSubdivision().GetInRange(staticShapes, posMin, posMax); | ||||
for (const entity_id_t& shape : staticShapes) | for (const entity_id_t& shape : staticShapes) | ||||
{ | { | ||||
std::map<u32, StaticShape>::const_iterator it = m_StaticShapes.find(shape); | std::map<u32, StaticShape>::const_iterator it = StaticShapes().find(shape); | ||||
ENSURE(it != m_StaticShapes.end()); | ENSURE(it != StaticShapes().end()); | ||||
if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) | if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) | ||||
continue; | continue; | ||||
CFixedVector2D center1(it->second.x, it->second.z); | CFixedVector2D center1(it->second.x, it->second.z); | ||||
if (Geometry::PointIsInSquare(center1 - center, it->second.u, it->second.v, CFixedVector2D(it->second.hw + clearance, it->second.hh + clearance))) | if (Geometry::PointIsInSquare(center1 - center, it->second.u, it->second.v, CFixedVector2D(it->second.hw + clearance, it->second.hh + clearance))) | ||||
{ | { | ||||
if (out) | if (out) | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | void CCmpObstructionManager::Rasterize(Grid<NavcellData>& grid, const std::vector<PathfinderPassability>& passClasses, bool fullUpdate) | ||||
RasterizeHelper(grid, FLAG_BLOCK_FOUNDATION, fullUpdate, foundationMask); | RasterizeHelper(grid, FLAG_BLOCK_FOUNDATION, fullUpdate, foundationMask); | ||||
m_DirtyStaticShapes.clear(); | m_DirtyStaticShapes.clear(); | ||||
m_DirtyUnitShapes.clear(); | m_DirtyUnitShapes.clear(); | ||||
} | } | ||||
void CCmpObstructionManager::RasterizeHelper(Grid<NavcellData>& grid, ICmpObstructionManager::flags_t requireMask, bool fullUpdate, pass_class_t appliedMask, entity_pos_t clearance) const | void CCmpObstructionManager::RasterizeHelper(Grid<NavcellData>& grid, ICmpObstructionManager::flags_t requireMask, bool fullUpdate, pass_class_t appliedMask, entity_pos_t clearance) const | ||||
{ | { | ||||
for (auto& pair : m_StaticShapes) | for (const auto& pair : StaticShapes()) | ||||
Not Done Inline ActionsWas any decision reached on the usage of auto ? Stan: Was any decision reached on the usage of auto ? | |||||
Not Done Inline Actionsauto should be replaced by the type. Stan: auto should be replaced by the type.
Shouldn't staticShapes be taken out of the loop in case… | |||||
Done Inline ActionsMaybe my knowledge of how c++ range loops are compiled is missing here, but I don't think that moving this out of the loop is necessary. Kuba386: Maybe my knowledge of how c++ range loops are compiled is missing here, but I don't think that… | |||||
{ | { | ||||
const StaticShape& shape = pair.second; | const StaticShape& shape = pair.second; | ||||
if (!(shape.flags & requireMask)) | if (!(shape.flags & requireMask)) | ||||
continue; | continue; | ||||
if (!fullUpdate && std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), pair.first) == m_DirtyStaticShapes.end()) | if (!fullUpdate && std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), pair.first) == m_DirtyStaticShapes.end()) | ||||
continue; | continue; | ||||
// TODO: it might be nice to rasterize with rounded corners for large 'expand' values. | // TODO: it might be nice to rasterize with rounded corners for large 'expand' values. | ||||
ObstructionSquare square = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh }; | ObstructionSquare square = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh }; | ||||
SimRasterize::Spans spans; | SimRasterize::Spans spans; | ||||
SimRasterize::RasterizeRectWithClearance(spans, square, clearance, Pathfinding::NAVCELL_SIZE); | SimRasterize::RasterizeRectWithClearance(spans, square, clearance, Pathfinding::NAVCELL_SIZE); | ||||
for (SimRasterize::Span& span : spans) | for (SimRasterize::Span& span : spans) | ||||
{ | { | ||||
i16 j = Clamp(span.j, (i16)0, (i16)(grid.m_H-1)); | i16 j = Clamp(span.j, (i16)0, (i16)(grid.m_H-1)); | ||||
i16 i0 = std::max(span.i0, (i16)0); | i16 i0 = std::max(span.i0, (i16)0); | ||||
i16 i1 = std::min(span.i1, (i16)grid.m_W); | i16 i1 = std::min(span.i1, (i16)grid.m_W); | ||||
for (i16 i = i0; i < i1; ++i) | for (i16 i = i0; i < i1; ++i) | ||||
grid.set(i, j, grid.get(i, j) | appliedMask); | grid.set(i, j, grid.get(i, j) | appliedMask); | ||||
} | } | ||||
} | } | ||||
for (auto& pair : m_UnitShapes) | for (const auto& pair : UnitShapes()) | ||||
Not Done Inline ActionsSame as above Stan: Same as above | |||||
Not Done Inline ActionsStill up to date. Stan: Still up to date. | |||||
{ | { | ||||
if (!(pair.second.flags & requireMask)) | if (!(pair.second.flags & requireMask)) | ||||
continue; | continue; | ||||
if (!fullUpdate && std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), pair.first) == m_DirtyUnitShapes.end()) | if (!fullUpdate && std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), pair.first) == m_DirtyUnitShapes.end()) | ||||
continue; | continue; | ||||
CFixedVector2D center(pair.second.x, pair.second.z); | CFixedVector2D center(pair.second.x, pair.second.z); | ||||
Show All 16 Lines | |||||
void CCmpObstructionManager::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 | void CCmpObstructionManager::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 | ||||
{ | { | ||||
PROFILE("GetObstructionsInRange"); | PROFILE("GetObstructionsInRange"); | ||||
ENSURE(x0 <= x1 && z0 <= z1); | ENSURE(x0 <= x1 && z0 <= z1); | ||||
std::vector<entity_id_t> unitShapes; | std::vector<entity_id_t> unitShapes; | ||||
m_UnitSubdivision.GetInRange(unitShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1)); | UnitSubdivision().GetInRange(unitShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1)); | ||||
for (entity_id_t& unitShape : unitShapes) | for (entity_id_t& unitShape : unitShapes) | ||||
StanUnsubmitted Not Done Inline ActionsStan: That's a int right? https://stackoverflow.com/questions/9637856/why-is-const-int-faster-than… | |||||
{ | { | ||||
std::map<u32, UnitShape>::const_iterator it = m_UnitShapes.find(unitShape); | std::map<u32, UnitShape>::const_iterator it = UnitShapes().find(unitShape); | ||||
ENSURE(it != m_UnitShapes.end()); | ENSURE(it != 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; | ||||
entity_pos_t c = it->second.clearance; | entity_pos_t c = it->second.clearance; | ||||
// Skip this object if it's completely outside the requested range | // Skip this object if it's completely outside the requested range | ||||
if (it->second.x + c < x0 || it->second.x - c > x1 || it->second.z + c < z0 || it->second.z - c > z1) | if (it->second.x + c < x0 || it->second.x - c > x1 || it->second.z + c < z0 || it->second.z - c > z1) | ||||
continue; | continue; | ||||
CFixedVector2D u(entity_pos_t::FromInt(1), entity_pos_t::Zero()); | CFixedVector2D u(entity_pos_t::FromInt(1), entity_pos_t::Zero()); | ||||
CFixedVector2D v(entity_pos_t::Zero(), entity_pos_t::FromInt(1)); | CFixedVector2D v(entity_pos_t::Zero(), entity_pos_t::FromInt(1)); | ||||
squares.emplace_back(ObstructionSquare{ it->second.x, it->second.z, u, v, c, c }); | squares.emplace_back(ObstructionSquare{ it->second.x, it->second.z, u, v, c, c }); | ||||
} | } | ||||
} | } | ||||
void CCmpObstructionManager::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 | void CCmpObstructionManager::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 | ||||
{ | { | ||||
PROFILE("GetObstructionsInRange"); | PROFILE("GetObstructionsInRange"); | ||||
ENSURE(x0 <= x1 && z0 <= z1); | ENSURE(x0 <= x1 && z0 <= z1); | ||||
std::vector<entity_id_t> staticShapes; | std::vector<entity_id_t> staticShapes; | ||||
m_StaticSubdivision.GetInRange(staticShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1)); | StaticSubdivision().GetInRange(staticShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1)); | ||||
for (entity_id_t& staticShape : staticShapes) | for (entity_id_t& staticShape : staticShapes) | ||||
StanUnsubmitted Not Done Inline ActionsStan: That's a int right? https://stackoverflow.com/questions/9637856/why-is-const-int-faster-than… | |||||
{ | { | ||||
std::map<u32, StaticShape>::const_iterator it = m_StaticShapes.find(staticShape); | std::map<u32, StaticShape>::const_iterator it = StaticShapes().find(staticShape); | ||||
ENSURE(it != m_StaticShapes.end()); | ENSURE(it != StaticShapes().end()); | ||||
if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) | if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) | ||||
continue; | continue; | ||||
entity_pos_t r = it->second.hw + it->second.hh; // overestimate the max dist of an edge from the center | entity_pos_t r = it->second.hw + it->second.hh; // overestimate the max dist of an edge from the center | ||||
// Skip this object if its overestimated bounding box is completely outside the requested range | // Skip this object if its overestimated bounding box is completely outside the requested range | ||||
if (it->second.x + r < x0 || it->second.x - r > x1 || it->second.z + r < z0 || it->second.z - r > z1) | if (it->second.x + r < x0 || it->second.x - r > x1 || it->second.z + r < z0 || it->second.z - r > z1) | ||||
Show All 13 Lines | void CCmpObstructionManager::GetUnitsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter, bool strict) const | ||||
// 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; | ||||
CFixedVector2D center(square.x, square.z); | CFixedVector2D center(square.x, square.z); | ||||
CFixedVector2D expandedBox = | CFixedVector2D expandedBox = | ||||
Geometry::GetHalfBoundingBox(square.u, square.v, CFixedVector2D(square.hw, square.hh)) + | Geometry::GetHalfBoundingBox(square.u, square.v, CFixedVector2D(square.hw, square.hh)) + | ||||
CFixedVector2D(m_MaxClearance, m_MaxClearance); | CFixedVector2D(m_MaxClearance, m_MaxClearance); | ||||
m_UnitSubdivision.GetInRange(unitShapes, center - expandedBox, center + expandedBox); | UnitSubdivision().GetInRange(unitShapes, center - expandedBox, center + expandedBox); | ||||
std::map<entity_pos_t, SimRasterize::Spans> rasterizedRects; | std::map<entity_pos_t, SimRasterize::Spans> rasterizedRects; | ||||
for (const u32& unitShape : unitShapes) | for (const u32& unitShape : unitShapes) | ||||
StanUnsubmitted Not Done Inline ActionsStan: https://stackoverflow.com/questions/9637856/why-is-const-int-faster-than-const-int | |||||
{ | { | ||||
std::map<u32, UnitShape>::const_iterator it = m_UnitShapes.find(unitShape); | std::map<u32, UnitShape>::const_iterator it = UnitShapes().find(unitShape); | ||||
ENSURE(it != m_UnitShapes.end()); | ENSURE(it != UnitShapes().end()); | ||||
const UnitShape& shape = it->second; | const UnitShape& shape = it->second; | ||||
if (!filter.TestShape(UNIT_INDEX_TO_TAG(unitShape), shape.flags, shape.group, INVALID_ENTITY)) | if (!filter.TestShape(UNIT_INDEX_TO_TAG(unitShape), shape.flags, shape.group, INVALID_ENTITY)) | ||||
continue; | continue; | ||||
if (rasterizedRects.find(shape.clearance) == rasterizedRects.end()) | if (rasterizedRects.find(shape.clearance) == rasterizedRects.end()) | ||||
{ | { | ||||
Show All 31 Lines | |||||
void CCmpObstructionManager::GetStaticObstructionsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter) const | void CCmpObstructionManager::GetStaticObstructionsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter) const | ||||
{ | { | ||||
PROFILE("GetStaticObstructionsOnObstruction"); | PROFILE("GetStaticObstructionsOnObstruction"); | ||||
std::vector<entity_id_t> staticShapes; | std::vector<entity_id_t> staticShapes; | ||||
CFixedVector2D center(square.x, square.z); | CFixedVector2D center(square.x, square.z); | ||||
CFixedVector2D expandedBox = Geometry::GetHalfBoundingBox(square.u, square.v, CFixedVector2D(square.hw, square.hh)); | CFixedVector2D expandedBox = Geometry::GetHalfBoundingBox(square.u, square.v, CFixedVector2D(square.hw, square.hh)); | ||||
m_StaticSubdivision.GetInRange(staticShapes, center - expandedBox, center + expandedBox); | StaticSubdivision().GetInRange(staticShapes, center - expandedBox, center + expandedBox); | ||||
for (const u32& staticShape : staticShapes) | for (const u32& staticShape : staticShapes) | ||||
StanUnsubmitted Not Done Inline ActionsHere as well Stan: Here as well | |||||
{ | { | ||||
std::map<u32, StaticShape>::const_iterator it = m_StaticShapes.find(staticShape); | std::map<u32, StaticShape>::const_iterator it = StaticShapes().find(staticShape); | ||||
ENSURE(it != m_StaticShapes.end()); | ENSURE(it != StaticShapes().end()); | ||||
const StaticShape& shape = it->second; | const StaticShape& shape = it->second; | ||||
if (!filter.TestShape(STATIC_INDEX_TO_TAG(staticShape), shape.flags, shape.group, shape.group2)) | if (!filter.TestShape(STATIC_INDEX_TO_TAG(staticShape), shape.flags, shape.group, shape.group2)) | ||||
continue; | continue; | ||||
if (Geometry::TestSquareSquare( | if (Geometry::TestSquareSquare( | ||||
center, | center, | ||||
Show All 25 Lines | if (m_DebugOverlayDirty) | ||||
m_DebugOverlayLines.clear(); | m_DebugOverlayLines.clear(); | ||||
m_DebugOverlayLines.push_back(SOverlayLine()); | m_DebugOverlayLines.push_back(SOverlayLine()); | ||||
m_DebugOverlayLines.back().m_Color = boundsColor; | m_DebugOverlayLines.back().m_Color = boundsColor; | ||||
SimRender::ConstructSquareOnGround(GetSimContext(), | SimRender::ConstructSquareOnGround(GetSimContext(), | ||||
(m_WorldX0+m_WorldX1).ToFloat()/2.f, (m_WorldZ0+m_WorldZ1).ToFloat()/2.f, | (m_WorldX0+m_WorldX1).ToFloat()/2.f, (m_WorldZ0+m_WorldZ1).ToFloat()/2.f, | ||||
(m_WorldX1-m_WorldX0).ToFloat(), (m_WorldZ1-m_WorldZ0).ToFloat(), | (m_WorldX1-m_WorldX0).ToFloat(), (m_WorldZ1-m_WorldZ0).ToFloat(), | ||||
0, m_DebugOverlayLines.back(), true); | 0, m_DebugOverlayLines.back(), true); | ||||
StanUnsubmitted Not Done Inline Actionsrange based loop? const iterator? Stan: range based loop? const iterator? | |||||
for (std::map<u32, UnitShape>::iterator it = m_UnitShapes.begin(); it != m_UnitShapes.end(); ++it) | for (std::map<u32, UnitShape>::const_iterator it = UnitShapes().begin(); it != UnitShapes().end(); ++it) | ||||
{ | { | ||||
m_DebugOverlayLines.push_back(SOverlayLine()); | m_DebugOverlayLines.push_back(SOverlayLine()); | ||||
m_DebugOverlayLines.back().m_Color = ((it->second.flags & FLAG_MOVING) ? movingColor : defaultColor); | m_DebugOverlayLines.back().m_Color = ((it->second.flags & FLAG_MOVING) ? movingColor : defaultColor); | ||||
SimRender::ConstructSquareOnGround(GetSimContext(), it->second.x.ToFloat(), it->second.z.ToFloat(), it->second.clearance.ToFloat(), it->second.clearance.ToFloat(), 0, m_DebugOverlayLines.back(), true); | SimRender::ConstructSquareOnGround(GetSimContext(), it->second.x.ToFloat(), it->second.z.ToFloat(), it->second.clearance.ToFloat(), it->second.clearance.ToFloat(), 0, m_DebugOverlayLines.back(), true); | ||||
} | } | ||||
for (std::map<u32, StaticShape>::iterator it = m_StaticShapes.begin(); it != m_StaticShapes.end(); ++it) | for (std::map<u32, StaticShape>::const_iterator it = StaticShapes().begin(); it != StaticShapes().end(); ++it) | ||||
StanUnsubmitted Not Done Inline Actionsrange based loop? const iterator? Stan: range based loop? const iterator? | |||||
{ | { | ||||
m_DebugOverlayLines.push_back(SOverlayLine()); | m_DebugOverlayLines.push_back(SOverlayLine()); | ||||
m_DebugOverlayLines.back().m_Color = defaultColor; | m_DebugOverlayLines.back().m_Color = defaultColor; | ||||
float a = atan2f(it->second.v.X.ToFloat(), it->second.v.Y.ToFloat()); | float a = atan2f(it->second.v.X.ToFloat(), it->second.v.Y.ToFloat()); | ||||
SimRender::ConstructSquareOnGround(GetSimContext(), it->second.x.ToFloat(), it->second.z.ToFloat(), it->second.hw.ToFloat()*2, it->second.hh.ToFloat()*2, a, m_DebugOverlayLines.back(), true); | SimRender::ConstructSquareOnGround(GetSimContext(), it->second.x.ToFloat(), it->second.z.ToFloat(), it->second.hw.ToFloat()*2, it->second.hh.ToFloat()*2, a, m_DebugOverlayLines.back(), true); | ||||
} | } | ||||
m_DebugOverlayDirty = false; | m_DebugOverlayDirty = false; | ||||
} | } | ||||
for (size_t i = 0; i < m_DebugOverlayLines.size(); ++i) | for (size_t i = 0; i < m_DebugOverlayLines.size(); ++i) | ||||
collector.Submit(&m_DebugOverlayLines[i]); | collector.Submit(&m_DebugOverlayLines[i]); | ||||
} | } |
forgot to remove these.