18 #include "precompiled.h"
40 #define TAG_IS_VALID(tag) ((tag).valid())
41 #define TAG_IS_UNIT(tag) (((tag).n & 1) == 0)
42 #define TAG_IS_STATIC(tag) (((tag).n & 1) == 1)
43 #define UNIT_INDEX_TO_TAG(idx) tag_t(((idx) << 1) | 0)
44 #define STATIC_INDEX_TO_TAG(idx) tag_t(((idx) << 1) | 1)
45 #define TAG_TO_INDEX(tag) ((tag).n >> 1)
81 serialize.NumberU32_Unbounded(
"entity", value.
entity);
82 serialize.NumberFixed_Unbounded(
"x", value.
x);
83 serialize.NumberFixed_Unbounded(
"z", value.
z);
84 serialize.NumberFixed_Unbounded(
"r", value.
r);
85 serialize.NumberU8_Unbounded(
"flags", value.
flags);
86 serialize.NumberU32_Unbounded(
"group", value.
group);
98 serialize.NumberU32_Unbounded(
"entity", value.
entity);
99 serialize.NumberFixed_Unbounded(
"x", value.
x);
100 serialize.NumberFixed_Unbounded(
"z", value.
z);
101 serialize.NumberFixed_Unbounded(
"u.x", value.
u.
X);
102 serialize.NumberFixed_Unbounded(
"u.y", value.
u.
Y);
103 serialize.NumberFixed_Unbounded(
"v.x", value.
v.
X);
104 serialize.NumberFixed_Unbounded(
"v.y", value.
v.
Y);
105 serialize.NumberFixed_Unbounded(
"hw", value.
hw);
106 serialize.NumberFixed_Unbounded(
"hh", value.
hh);
107 serialize.NumberU8_Unbounded(
"flags", value.
flags);
108 serialize.NumberU32_Unbounded(
"group", value.
group);
109 serialize.NumberU32_Unbounded(
"group2", value.
group2);
145 return "<a:component type='system'/><empty/>";
184 serialize.NumberFixed_Unbounded(
"world x0",
m_WorldX0);
185 serialize.NumberFixed_Unbounded(
"world z0",
m_WorldZ0);
186 serialize.NumberFixed_Unbounded(
"world x1",
m_WorldX1);
187 serialize.NumberFixed_Unbounded(
"world z1",
m_WorldZ1);
255 UnitShape shape = { ent, x, z, r, flags, group };
272 StaticShape shape = { ent, x, z, u, v, w/2, h/2, flags, group, group2 };
541 if (!IsInWorld(x0, z0, r) || !IsInWorld(x1, z1, r))
544 CFixedVector2D posMin (std::min(x0, x1) - r, std::min(z0, z1) - r);
545 CFixedVector2D posMax (std::max(x0, x1) + r, std::max(z0, z1) + r);
548 m_UnitSubdivision.GetInRange(unitShapes, posMin, posMax);
549 for (
int i = 0; i < unitShapes.
size(); ++i)
551 std::map<u32, UnitShape>::iterator it = m_UnitShapes.find(unitShapes[i]);
552 ENSURE(it != m_UnitShapes.end());
564 m_StaticSubdivision.GetInRange(staticShapes, posMin, posMax);
565 for (
int i = 0; i < staticShapes.
size(); ++i)
567 std::map<u32, StaticShape>::iterator it = m_StaticShapes.find(staticShapes[i]);
568 ENSURE(it != m_StaticShapes.end());
570 if (!filter.TestShape(
STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2))
584 std::vector<entity_id_t>*
out)
622 out->push_back(it->second.entity);
638 out->push_back(it->second.entity);
645 return !out->empty();
652 std::vector<entity_id_t>*
out)
676 if (!(it->second.x + r1 < x - r || it->second.x - r1 > x + r || it->second.z + r1 < z - r || it->second.z - r1 > z + r))
679 out->push_back(it->second.entity);
694 out->push_back(it->second.entity);
702 return !out->empty();
761 CFixedVector2D halfSize(it->second.hw + expandPathfinding, it->second.hh + expandPathfinding);
767 for (
u16 j = j0; j <= j1; ++j)
769 for (
u16 i = i0; i <= i1; ++i)
781 CFixedVector2D halfSize(it->second.hw + expandFoundation, it->second.hh + expandFoundation);
787 for (
u16 j = j0; j <= j1; ++j)
789 for (
u16 i = i0; i <= i1; ++i)
811 for (
u16 j = j0; j <= j1; ++j)
812 for (
u16 i = i0; i <= i1; ++i)
823 for (
u16 j = j0; j <= j1; ++j)
824 for (
u16 i = i0; i <= i1; ++i)
832 const u16 edgeSize = 3;
838 for (
u16 j = 0; j < grid.
m_H; ++j)
840 for (
u16 i = 0; i < grid.
m_W; ++i)
849 + (j*2 + 1 - grid.
m_H)*(j*2 + 1 - grid.
m_H);
851 if (dist2 >= (grid.
m_W - 2*edgeSize) * (grid.
m_H - 2*edgeSize))
852 grid.
set(i, j, edgeFlags);
862 for (
u16 j = 0; j < grid.
m_H; ++j)
863 for (
u16 i = 0; i < i0+edgeSize; ++i)
864 grid.
set(i, j, edgeFlags);
865 for (
u16 j = 0; j < grid.
m_H; ++j)
866 for (
u16 i = (
u16)(i1-edgeSize+1); i < grid.
m_W; ++i)
867 grid.
set(i, j, edgeFlags);
868 for (
u16 j = 0; j < j0+edgeSize; ++j)
869 for (
u16 i = (
u16)(i0+edgeSize); i < i1-edgeSize+1; ++i)
870 grid.
set(i, j, edgeFlags);
871 for (
u16 j = (
u16)(j1-edgeSize+1); j < grid.
m_H; ++j)
872 for (
u16 i = (
u16)(i0+edgeSize); i < i1-edgeSize+1; ++i)
873 grid.
set(i, j, edgeFlags);
881 PROFILE(
"GetObstructionsInRange");
883 ENSURE(x0 <= x1 && z0 <= z1);
887 for (
int i = 0; i < unitShapes.
size(); ++i)
889 std::map<u32, UnitShape>::iterator it =
m_UnitShapes.find(unitShapes[i]);
898 if (it->second.x + r < x0 || it->second.x - r > x1 || it->second.z + r < z0 || it->second.z - r > z1)
904 squares.push_back(s);
909 for (
int i = 0; i < staticShapes.
size(); ++i)
911 std::map<u32, StaticShape>::iterator it =
m_StaticShapes.find(staticShapes[i]);
920 if (it->second.x + r < x0 || it->second.x - r > x1 || it->second.z + r < z0 || it->second.z - r > z1)
925 ObstructionSquare s = { it->second.
x, it->second.z, it->second.u, it->second.v, it->second.hw, it->second.hh };
926 squares.push_back(s);
932 std::vector<ObstructionSquare> squares;
939 for (std::vector<ObstructionSquare>::reverse_iterator it = squares.rbegin(); it != squares.rend(); ++it)
954 for (std::vector<ObstructionSquare>::reverse_iterator it = squares.rbegin(); it != squares.rend(); ++it)
972 CColor defaultColour(0, 0, 1, 1);
973 CColor movingColour(1, 0, 1, 1);
974 CColor boundsColour(1, 1, 0, 1);
999 float a = atan2f(it->second.v.X.ToFloat(), it->second.v.Y.ToFloat());
An entity initialisation parameter node.
void SubscribeToMessageType(MessageTypeId mtid)
Subscribe the current component type to the given message type.
A simple fixed-point number class.
virtual void SetDebugOverlay(bool enabled)
Toggle the rendering of debug info.
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)
Collision test a flat-ended thick line against the current set of shapes.
#define TAG_IS_VALID(tag)
Interface for ICmpObstructionManager Test functions to filter out unwanted shapes.
#define REGISTER_COMPONENT_TYPE(cname)
void GetInRange(SpatialQueryArray &out, CFixedVector2D posMin, CFixedVector2D posMax)
Returns a sorted list of unique items that includes all items within the given axis-aligned square ra...
void MakeDirtyUnit(flags_t flags)
Mark all previous Rasterise()d grids as dirty, if they depend on this shape.
Helper templates for serializing/deserializing common objects.
virtual tag_t AddUnitShape(entity_id_t ent, entity_pos_t x, entity_pos_t z, entity_pos_t r, flags_t flags, entity_id_t group)
Register a unit shape.
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
Line-based overlay, with world-space coordinates, rendered in the world potentially behind other obje...
static void ClassInit(CComponentManager &componentManager)
virtual void HandleMessage(const CMessage &msg, bool global)
const ssize_t TERRAIN_TILE_SIZE
metres [world space units] per tile in x and z
virtual void Serialize(ISerializer &serialize)
void Remove(uint32_t item, CFixedVector2D fromMin, CFixedVector2D fromMax)
Remove an item with the given 'from' size.
std::vector< SOverlayLine > m_DebugOverlayLines
void Reset(entity_pos_t maxX, entity_pos_t maxZ, entity_pos_t divisionSize)
virtual void SetBounds(entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1)
Set the bounds of the world.
Serialization interface; see serialization overview.
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)
Collision test a static square shape against the current set of shapes.
Add renderable objects to the scene collector.
static void out(const wchar_t *fmt,...)
void MakeDirtyDebug()
Mark the debug display as dirty.
bool m_PassabilityCircular
virtual void SetUnitControlGroup(tag_t tag, entity_id_t group)
Set the control group of a unit shape.
Serialization helper template for StaticShape.
This interface accepts renderable objects.
virtual void SetStaticControlGroup(tag_t tag, entity_id_t group, entity_id_t group2)
Sets the control group of a static shape.
bool IsInWorld(CFixedVector2D p)
Return whether the given point is within the world bounds.
virtual void SetUnitMovingFlag(tag_t tag, bool moving)
Set whether a unit shape is moving or stationary.
virtual bool TestShape(tag_t tag, flags_t flags, entity_id_t group, entity_id_t group2) const =0
Return true if the shape with the specified parameters should be tested for collisions.
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
virtual void RemoveShape(tag_t tag)
Remove an existing shape.
virtual int GetType() const =0
Serialization helper template for UnitShape.
Internal representation of axis-aligned sometimes-square sometimes-circle shapes for moving units...
std::map< u32, UnitShape > m_UnitShapes
u8 flags_t
Bitmask of EFlag values.
virtual ObstructionSquare GetStaticShapeObstruction(entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h)
void ResetSubdivisions(entity_pos_t x1, entity_pos_t z1)
#define TAG_TO_INDEX(tag)
void SerializeCommon(S &serialize)
void operator()(S &serialize, const char *name, StaticShape &value)
virtual void MoveShape(tag_t tag, entity_pos_t x, entity_pos_t z, entity_angle_t a)
Adjust the position and angle of an existing shape.
std::map< u32, StaticShape > m_StaticShapes
#define DEFAULT_COMPONENT_ALLOCATOR(cname)
static void TileCenter(u16 i, u16 j, entity_pos_t &x, entity_pos_t &z)
Returns the position of the center of the given tile.
SpatialSubdivision m_StaticSubdivision
const CSimContext & GetSimContext() 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)
Find all the obstructions that are inside (or partially inside) the given range.
bool TestRayAASquare(CFixedVector2D a, CFixedVector2D b, CFixedVector2D halfSize)
bool TestRaySquare(CFixedVector2D a, CFixedVector2D b, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize)
Internal representation of arbitrary-rotation static square shapes for buildings. ...
static CFixed FromInt(int n)
bool IsDirty(const Grid< T > &grid)
Test whether a Rasterise()d grid is dirty and needs updating.
Helper functions related to rendering.
SpatialSubdivision m_UnitSubdivision
CFixedVector2D Multiply(fixed n) const
Multiply by a CFixed.
A very basic subdivision scheme for finding items in ranges.
bool TestSquareSquare(CFixedVector2D c0, CFixedVector2D u0, CFixedVector2D v0, CFixedVector2D halfSize0, CFixedVector2D c1, CFixedVector2D u1, CFixedVector2D v1, CFixedVector2D halfSize1)
virtual void SetPassabilityCircular(bool enabled)
Set the passability to be restricted to a circular map.
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)
Register a static shape.
virtual ObstructionSquare GetUnitShapeObstruction(entity_pos_t x, entity_pos_t z, entity_pos_t r)
bool IsZero() const
Returns true if the number is precisely 0.
SceneCollector & collector
virtual ObstructionSquare GetObstruction(tag_t tag)
Get the obstruction square representing the given shape.
T & get(int i, int j) const
void RenderSubmit(SceneCollector &collector)
void ConstructSquareOnGround(const CSimContext &context, float x, float z, float w, float h, float a, SOverlayLine &overlay, bool floating, float heightOffset=0.25f)
Constructs overlay line as rectangle with given center and dimensions, conforming to terrain...
#define TAG_IS_STATIC(tag)
bool IsInWorld(entity_pos_t x, entity_pos_t z, entity_pos_t r)
Return whether the given point is within the world bounds by at least r.
ICmpObstructionManager::flags_t flags
void sincos_approx(CFixed_15_16 a, CFixed_15_16 &sin_out, CFixed_15_16 &cos_out)
Compute sin(a) and cos(a).
virtual bool TestUnitShape(const IObstructionTestFilter &filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, std::vector< entity_id_t > *out)
Collision test a unit shape against the current set of registered shapes, and optionally writes a lis...
A simple fixed-size array that works similar to an std::vector but is obviously limited in its max it...
void Move(uint32_t item, CFixedVector2D fromMin, CFixedVector2D fromMax, CFixedVector2D toMin, CFixedVector2D toMax)
Equivalent to Remove() then Add(), but potentially faster.
Serialization helper template for SpatialSubdivision.
virtual void Deserialize(const CParamNode ¶mNode, IDeserializer &deserialize)
virtual bool Rasterise(Grid< u8 > &grid)
Convert the current set of shapes onto a grid.
void Add(uint32_t item, CFixedVector2D toMin, CFixedVector2D toMax)
Add an item with the given 'to' size.
bool m_DebugOverlayEnabled
bool PointIsInSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize)
Checks if a point is inside the given rotated square or rectangle.
const entity_id_t INVALID_ENTITY
Invalid entity ID.
u32 entity_id_t
Entity ID type.
static std::string GetSchema()
virtual void Submit(CPatch *patch)=0
Submit a terrain patch that is part of the scene.
void operator()(S &serialize, const char *name, UnitShape &value)
void MakeDirtyAll()
Mark all previous Rasterise()d grids as dirty, and the debug display.
#define STATIC_INDEX_TO_TAG(idx)
T clamp(T value, T min, T max)
#define UNIT_INDEX_TO_TAG(idx)
Standard representation for all types of shapes, for use with geometry processing code...
Helper functions related to geometry algorithms.
void set(int i, int j, const T &value)
CFixedVector2D GetHalfBoundingBox(CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize)
Obstruction manager: provides efficient spatial queries over objects in the world.
static void NearestTile(entity_pos_t x, entity_pos_t z, u16 &i, u16 &j, u16 w, u16 h)
Compute the tile indexes on the grid nearest to a given point.
ICmpObstructionManager::flags_t flags
void MakeDirtyStatic(flags_t flags)
Mark all previous Rasterise()d grids as dirty, if they depend on this shape.
Deserialization interface; see serialization overview.
External identifiers for shapes.
virtual bool FindMostImportantObstruction(const IObstructionTestFilter &filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, ObstructionSquare &square)
Find a single obstruction that blocks a unit at the given point with the given radius.
virtual void Init(const CParamNode ¶mNode)