2020-11-26 14:28:50 -08:00
/* Copyright (C) 2020 Wildfire Games.
2010-03-17 16:01:12 -07:00
* This file is part of 0 A . D .
*
* 0 A . D . is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 2 of the License , or
* ( at your option ) any later version .
*
* 0 A . D . is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with 0 A . D . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "precompiled.h"
# include "simulation2/system/Component.h"
# include "ICmpObstructionManager.h"
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
# include "ICmpTerrain.h"
2018-01-21 13:21:21 -08:00
# include "ICmpPosition.h"
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
2010-03-17 16:01:12 -07:00
# include "simulation2/MessageTypes.h"
2010-04-29 16:36:05 -07:00
# include "simulation2/helpers/Geometry.h"
2020-06-14 13:39:03 -07:00
# include "simulation2/helpers/Grid.h"
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
# include "simulation2/helpers/Rasterize.h"
2010-03-20 12:18:01 -07:00
# include "simulation2/helpers/Render.h"
2010-09-19 11:08:56 -07:00
# include "simulation2/helpers/Spatial.h"
2010-10-23 12:59:40 -07:00
# include "simulation2/serialization/SerializeTemplates.h"
2010-03-17 16:01:12 -07:00
2010-03-20 12:18:01 -07:00
# include "graphics/Overlay.h"
2010-03-17 16:01:12 -07:00
# include "graphics/Terrain.h"
# include "maths/MathUtil.h"
# include "ps/Profile.h"
2010-03-20 12:18:01 -07:00
# include "renderer/Scene.h"
2012-05-05 12:22:22 -07:00
# include "ps/CLogger.h"
2010-03-17 16:01:12 -07:00
// Externally, tags are opaque non-zero positive integers.
// Internally, they are tagged (by shape) indexes into shape lists.
// idx must be non-zero.
2010-07-04 10:19:38 -07:00
# define TAG_IS_VALID(tag) ((tag).valid())
# define TAG_IS_UNIT(tag) (((tag).n & 1) == 0)
# define TAG_IS_STATIC(tag) (((tag).n & 1) == 1)
# define UNIT_INDEX_TO_TAG(idx) tag_t(((idx) << 1) | 0)
# define STATIC_INDEX_TO_TAG(idx) tag_t(((idx) << 1) | 1)
# define TAG_TO_INDEX(tag) ((tag).n >> 1)
2010-03-17 16:01:12 -07:00
/**
2015-07-18 01:37:49 -07:00
* Internal representation of axis - aligned circular shapes for moving units
2010-03-17 16:01:12 -07:00
*/
2010-04-29 16:36:05 -07:00
struct UnitShape
2010-03-17 16:01:12 -07:00
{
2011-02-10 08:06:28 -08:00
entity_id_t entity ;
2010-04-29 16:36:05 -07:00
entity_pos_t x , z ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
entity_pos_t clearance ;
2011-08-16 04:18:32 -07:00
ICmpObstructionManager : : flags_t flags ;
2010-09-03 02:55:14 -07:00
entity_id_t group ; // control group (typically the owner entity, or a formation controller entity) (units ignore collisions with others in the same group)
2010-03-17 16:01:12 -07:00
} ;
/**
2010-04-29 16:36:05 -07:00
* Internal representation of arbitrary - rotation static square shapes for buildings
2010-03-17 16:01:12 -07:00
*/
2010-04-29 16:36:05 -07:00
struct StaticShape
2010-03-17 16:01:12 -07:00
{
2011-02-10 08:06:28 -08:00
entity_id_t entity ;
2010-04-29 16:36:05 -07:00
entity_pos_t x , z ; // world-space coordinates
CFixedVector2D u , v ; // orthogonal unit vectors - axes of local coordinate space
entity_pos_t hw , hh ; // half width/height in local coordinate space
2011-08-16 04:18:32 -07:00
ICmpObstructionManager : : flags_t flags ;
2012-05-05 12:22:22 -07:00
entity_id_t group ;
entity_id_t group2 ;
2010-03-17 16:01:12 -07:00
} ;
2010-10-23 12:59:40 -07:00
/**
* Serialization helper template for UnitShape
*/
struct SerializeUnitShape
{
template < typename S >
2017-01-19 18:25:19 -08:00
void operator ( ) ( S & serialize , const char * UNUSED ( name ) , UnitShape & value ) const
2010-10-23 12:59:40 -07:00
{
2011-02-10 08:06:28 -08:00
serialize . NumberU32_Unbounded ( " entity " , value . entity ) ;
2010-10-23 12:59:40 -07:00
serialize . NumberFixed_Unbounded ( " x " , value . x ) ;
serialize . NumberFixed_Unbounded ( " z " , value . z ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
serialize . NumberFixed_Unbounded ( " clearance " , value . clearance ) ;
2011-02-10 08:06:28 -08:00
serialize . NumberU8_Unbounded ( " flags " , value . flags ) ;
2010-10-23 12:59:40 -07:00
serialize . NumberU32_Unbounded ( " group " , value . group ) ;
}
} ;
/**
* Serialization helper template for StaticShape
*/
struct SerializeStaticShape
{
template < typename S >
2017-01-19 18:25:19 -08:00
void operator ( ) ( S & serialize , const char * UNUSED ( name ) , StaticShape & value ) const
2010-10-23 12:59:40 -07:00
{
2011-02-10 08:06:28 -08:00
serialize . NumberU32_Unbounded ( " entity " , value . entity ) ;
2010-10-23 12:59:40 -07:00
serialize . NumberFixed_Unbounded ( " x " , value . x ) ;
serialize . NumberFixed_Unbounded ( " z " , value . z ) ;
serialize . NumberFixed_Unbounded ( " u.x " , value . u . X ) ;
serialize . NumberFixed_Unbounded ( " u.y " , value . u . Y ) ;
serialize . NumberFixed_Unbounded ( " v.x " , value . v . X ) ;
serialize . NumberFixed_Unbounded ( " v.y " , value . v . Y ) ;
serialize . NumberFixed_Unbounded ( " hw " , value . hw ) ;
serialize . NumberFixed_Unbounded ( " hh " , value . hh ) ;
2011-02-10 08:06:28 -08:00
serialize . NumberU8_Unbounded ( " flags " , value . flags ) ;
2012-05-05 12:22:22 -07:00
serialize . NumberU32_Unbounded ( " group " , value . group ) ;
serialize . NumberU32_Unbounded ( " group2 " , value . group2 ) ;
2010-10-23 12:59:40 -07:00
}
} ;
2010-03-17 16:01:12 -07:00
class CCmpObstructionManager : public ICmpObstructionManager
{
public :
2010-03-20 12:18:01 -07:00
static void ClassInit ( CComponentManager & componentManager )
2010-03-17 16:01:12 -07:00
{
2010-03-20 12:18:01 -07:00
componentManager . SubscribeToMessageType ( MT_RenderSubmit ) ; // for debug overlays
2010-03-17 16:01:12 -07:00
}
DEFAULT_COMPONENT_ALLOCATOR ( ObstructionManager )
2010-03-20 12:18:01 -07:00
bool m_DebugOverlayEnabled ;
bool m_DebugOverlayDirty ;
std : : vector < SOverlayLine > m_DebugOverlayLines ;
2013-09-15 07:03:53 -07:00
SpatialSubdivision m_UnitSubdivision ;
SpatialSubdivision m_StaticSubdivision ;
2010-09-19 11:08:56 -07:00
2010-03-17 16:01:12 -07:00
// TODO: using std::map is a bit inefficient; is there a better way to store these?
2010-04-29 16:36:05 -07:00
std : : map < u32 , UnitShape > m_UnitShapes ;
std : : map < u32 , StaticShape > m_StaticShapes ;
u32 m_UnitShapeNext ; // next allocated id
u32 m_StaticShapeNext ;
2010-03-17 16:01:12 -07:00
2015-06-14 12:22:07 -07:00
entity_pos_t m_MaxClearance ;
2010-10-30 11:25:34 -07:00
bool m_PassabilityCircular ;
2010-07-25 07:11:21 -07:00
entity_pos_t m_WorldX0 ;
entity_pos_t m_WorldZ0 ;
entity_pos_t m_WorldX1 ;
entity_pos_t m_WorldZ1 ;
2015-06-23 13:39:11 -07:00
u16 m_TerrainTiles ;
2010-07-25 07:11:21 -07:00
2010-04-23 09:09:03 -07:00
static std : : string GetSchema ( )
{
return " <a:component type='system'/><empty/> " ;
}
2011-01-16 06:08:38 -08:00
virtual void Init ( const CParamNode & UNUSED ( paramNode ) )
2010-03-17 16:01:12 -07:00
{
2010-03-20 12:18:01 -07:00
m_DebugOverlayEnabled = false ;
m_DebugOverlayDirty = true ;
2010-04-29 16:36:05 -07:00
m_UnitShapeNext = 1 ;
m_StaticShapeNext = 1 ;
2010-03-17 16:01:12 -07:00
2015-06-14 12:22:07 -07:00
m_UpdateInformations . dirty = true ;
m_UpdateInformations . globallyDirty = true ;
2010-07-25 07:11:21 -07:00
2010-10-30 11:25:34 -07:00
m_PassabilityCircular = false ;
2010-07-25 07:11:21 -07:00
m_WorldX0 = m_WorldZ0 = m_WorldX1 = m_WorldZ1 = entity_pos_t : : Zero ( ) ;
2015-06-23 13:39:11 -07:00
m_TerrainTiles = 0 ;
2010-09-19 11:08:56 -07:00
// Initialise with bogus values (these will get replaced when
// SetBounds is called)
2013-09-15 07:03:53 -07:00
ResetSubdivisions ( entity_pos_t : : FromInt ( 1024 ) , entity_pos_t : : FromInt ( 1024 ) ) ;
2010-03-17 16:01:12 -07:00
}
2011-01-16 06:08:38 -08:00
virtual void Deinit ( )
2010-03-17 16:01:12 -07:00
{
}
2010-10-23 12:59:40 -07:00
template < typename S >
void SerializeCommon ( S & serialize )
{
2013-09-15 07:03:53 -07:00
SerializeSpatialSubdivision ( ) ( serialize , " unit subdiv " , m_UnitSubdivision ) ;
SerializeSpatialSubdivision ( ) ( serialize , " static subdiv " , m_StaticSubdivision ) ;
2010-10-23 12:59:40 -07:00
2015-11-04 10:51:47 -08:00
serialize . NumberFixed_Unbounded ( " max clearance " , m_MaxClearance ) ;
2016-11-23 06:09:58 -08:00
2010-10-23 12:59:40 -07:00
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 ( " static shape next " , m_StaticShapeNext ) ;
2010-10-30 11:25:34 -07:00
serialize . Bool ( " circular " , m_PassabilityCircular ) ;
2010-10-23 12:59:40 -07:00
serialize . NumberFixed_Unbounded ( " world x0 " , m_WorldX0 ) ;
serialize . NumberFixed_Unbounded ( " world z0 " , m_WorldZ0 ) ;
serialize . NumberFixed_Unbounded ( " world x1 " , m_WorldX1 ) ;
serialize . NumberFixed_Unbounded ( " world z1 " , m_WorldZ1 ) ;
2015-06-23 13:39:11 -07:00
serialize . NumberU16_Unbounded ( " terrain tiles " , m_TerrainTiles ) ;
2010-10-23 12:59:40 -07:00
}
2010-03-17 16:01:12 -07:00
virtual void Serialize ( ISerializer & serialize )
{
2010-10-23 12:59:40 -07:00
// TODO: this could perhaps be optimised by not storing all the obstructions,
// and instead regenerating them from the other entities on Deserialize
SerializeCommon ( serialize ) ;
2010-03-17 16:01:12 -07:00
}
2011-01-16 06:08:38 -08:00
virtual void Deserialize ( const CParamNode & paramNode , IDeserializer & deserialize )
2010-03-17 16:01:12 -07:00
{
2011-01-16 06:08:38 -08:00
Init ( paramNode ) ;
2010-03-17 16:01:12 -07:00
2010-10-23 12:59:40 -07:00
SerializeCommon ( deserialize ) ;
2015-06-23 13:39:11 -07:00
m_UpdateInformations . dirtinessGrid = Grid < u8 > ( m_TerrainTiles * Pathfinding : : NAVCELLS_PER_TILE , m_TerrainTiles * Pathfinding : : NAVCELLS_PER_TILE ) ;
2010-03-17 16:01:12 -07:00
}
2011-01-16 06:08:38 -08:00
virtual void HandleMessage ( const CMessage & msg , bool UNUSED ( global ) )
2010-03-20 12:18:01 -07:00
{
switch ( msg . GetType ( ) )
{
case MT_RenderSubmit :
{
const CMessageRenderSubmit & msgData = static_cast < const CMessageRenderSubmit & > ( msg ) ;
2011-01-16 06:08:38 -08:00
RenderSubmit ( msgData . collector ) ;
2010-03-20 12:18:01 -07:00
break ;
}
}
}
2015-11-04 10:51:47 -08:00
// NB: on deserialization, this function is not called after the component is reset.
// So anything that happens here should be safely serialized.
2010-07-25 07:11:21 -07:00
virtual void SetBounds ( entity_pos_t x0 , entity_pos_t z0 , entity_pos_t x1 , entity_pos_t z1 )
{
m_WorldX0 = x0 ;
m_WorldZ0 = z0 ;
m_WorldX1 = x1 ;
m_WorldZ1 = z1 ;
2011-02-27 17:24:12 -08:00
MakeDirtyAll ( ) ;
2010-09-19 11:08:56 -07:00
// Subdivision system bounds:
2011-04-30 06:01:45 -07:00
ENSURE ( x0 . IsZero ( ) & & z0 . IsZero ( ) ) ; // don't bother implementing non-zero offsets yet
2010-09-19 11:08:56 -07:00
ResetSubdivisions ( x1 , z1 ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
CmpPtr < ICmpTerrain > cmpTerrain ( GetSystemEntity ( ) ) ;
if ( ! cmpTerrain )
return ;
2015-06-23 13:39:11 -07:00
m_TerrainTiles = cmpTerrain - > GetTilesPerSide ( ) ;
m_UpdateInformations . dirtinessGrid = Grid < u8 > ( m_TerrainTiles * Pathfinding : : NAVCELLS_PER_TILE , m_TerrainTiles * Pathfinding : : NAVCELLS_PER_TILE ) ;
2015-06-14 12:22:07 -07:00
CmpPtr < ICmpPathfinder > cmpPathfinder ( GetSystemEntity ( ) ) ;
if ( cmpPathfinder )
m_MaxClearance = cmpPathfinder - > GetMaximumClearance ( ) ;
2010-09-19 11:08:56 -07:00
}
void ResetSubdivisions ( entity_pos_t x1 , entity_pos_t z1 )
{
// Use 8x8 tile subdivisions
// (TODO: find the optimal number instead of blindly guessing)
2012-01-12 04:51:10 -08:00
m_UnitSubdivision . Reset ( x1 , z1 , entity_pos_t : : FromInt ( 8 * TERRAIN_TILE_SIZE ) ) ;
m_StaticSubdivision . Reset ( x1 , z1 , entity_pos_t : : FromInt ( 8 * TERRAIN_TILE_SIZE ) ) ;
2010-09-19 11:08:56 -07:00
for ( std : : map < u32 , UnitShape > : : iterator it = m_UnitShapes . begin ( ) ; it ! = m_UnitShapes . end ( ) ; + + it )
{
CFixedVector2D center ( it - > second . x , it - > second . z ) ;
2015-07-18 01:37:49 -07:00
CFixedVector2D halfSize ( it - > second . clearance , it - > second . clearance ) ;
2010-09-19 11:08:56 -07:00
m_UnitSubdivision . Add ( it - > first , center - halfSize , center + halfSize ) ;
}
for ( std : : map < u32 , StaticShape > : : iterator it = m_StaticShapes . begin ( ) ; it ! = m_StaticShapes . end ( ) ; + + it )
{
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 ) ) ;
m_StaticSubdivision . Add ( it - > first , center - bbHalfSize , center + bbHalfSize ) ;
}
2010-07-25 07:11:21 -07:00
}
2015-07-18 01:37:49 -07:00
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 )
2010-03-17 16:01:12 -07:00
{
2015-07-18 01:37:49 -07:00
UnitShape shape = { ent , x , z , clearance , flags , group } ;
2011-08-16 04:18:32 -07:00
u32 id = m_UnitShapeNext + + ;
2010-04-29 16:36:05 -07:00
m_UnitShapes [ id ] = shape ;
2010-09-19 11:08:56 -07:00
2015-07-18 01:37:49 -07:00
m_UnitSubdivision . Add ( id , CFixedVector2D ( x - clearance , z - clearance ) , CFixedVector2D ( x + clearance , z + clearance ) ) ;
2010-09-19 11:08:56 -07:00
2015-06-14 12:22:07 -07:00
MakeDirtyUnit ( flags , id , shape ) ;
2010-04-29 16:36:05 -07:00
return UNIT_INDEX_TO_TAG ( id ) ;
2010-03-17 16:01:12 -07:00
}
2012-05-05 12:22:22 -07:00
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 */ )
2010-03-17 16:01:12 -07:00
{
2010-05-02 13:32:37 -07:00
fixed s , c ;
2010-04-29 16:36:05 -07:00
sincos_approx ( a , s , c ) ;
CFixedVector2D u ( c , - s ) ;
CFixedVector2D v ( s , c ) ;
2012-05-05 12:22:22 -07:00
StaticShape shape = { ent , x , z , u , v , w / 2 , h / 2 , flags , group , group2 } ;
2011-08-16 04:18:32 -07:00
u32 id = m_StaticShapeNext + + ;
2010-04-29 16:36:05 -07:00
m_StaticShapes [ id ] = shape ;
2010-09-19 11:08:56 -07:00
CFixedVector2D center ( x , z ) ;
CFixedVector2D bbHalfSize = Geometry : : GetHalfBoundingBox ( u , v , CFixedVector2D ( w / 2 , h / 2 ) ) ;
m_StaticSubdivision . Add ( id , center - bbHalfSize , center + bbHalfSize ) ;
2015-06-14 12:22:07 -07:00
MakeDirtyStatic ( flags , id , shape ) ;
2010-04-29 16:36:05 -07:00
return STATIC_INDEX_TO_TAG ( id ) ;
2010-03-17 16:01:12 -07:00
}
2017-01-19 18:25:19 -08:00
virtual ObstructionSquare GetUnitShapeObstruction ( entity_pos_t x , entity_pos_t z , entity_pos_t clearance ) const
2011-02-10 08:06:28 -08:00
{
CFixedVector2D u ( entity_pos_t : : FromInt ( 1 ) , entity_pos_t : : Zero ( ) ) ;
CFixedVector2D v ( entity_pos_t : : Zero ( ) , entity_pos_t : : FromInt ( 1 ) ) ;
2015-07-18 01:37:49 -07:00
ObstructionSquare o = { x , z , u , v , clearance , clearance } ;
2011-02-10 08:06:28 -08:00
return o ;
}
2017-01-19 18:25:19 -08:00
virtual ObstructionSquare GetStaticShapeObstruction ( entity_pos_t x , entity_pos_t z , entity_angle_t a , entity_pos_t w , entity_pos_t h ) const
2011-02-10 08:06:28 -08:00
{
fixed s , c ;
sincos_approx ( a , s , c ) ;
CFixedVector2D u ( c , - s ) ;
CFixedVector2D v ( s , c ) ;
ObstructionSquare o = { x , z , u , v , w / 2 , h / 2 } ;
return o ;
}
2010-03-17 16:01:12 -07:00
virtual void MoveShape ( tag_t tag , entity_pos_t x , entity_pos_t z , entity_angle_t a )
{
2011-04-30 06:01:45 -07:00
ENSURE ( TAG_IS_VALID ( tag ) ) ;
2010-03-17 16:01:12 -07:00
2010-04-29 16:36:05 -07:00
if ( TAG_IS_UNIT ( tag ) )
2010-03-17 16:01:12 -07:00
{
2010-04-29 16:36:05 -07:00
UnitShape & shape = m_UnitShapes [ TAG_TO_INDEX ( tag ) ] ;
2010-09-19 11:08:56 -07:00
2015-06-14 12:22:07 -07:00
MakeDirtyUnit ( shape . flags , TAG_TO_INDEX ( tag ) , shape ) ; // dirty the old shape region
2010-09-19 11:08:56 -07:00
m_UnitSubdivision . Move ( TAG_TO_INDEX ( tag ) ,
2015-07-18 01:37:49 -07:00
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 ) ) ;
2010-09-19 11:08:56 -07:00
2010-04-29 16:36:05 -07:00
shape . x = x ;
shape . z = z ;
2010-07-25 07:11:21 -07:00
2015-06-14 12:22:07 -07:00
MakeDirtyUnit ( shape . flags , TAG_TO_INDEX ( tag ) , shape ) ; // dirty the new shape region
2010-03-17 16:01:12 -07:00
}
else
{
2010-05-02 13:32:37 -07:00
fixed s , c ;
2010-04-29 16:36:05 -07:00
sincos_approx ( a , s , c ) ;
CFixedVector2D u ( c , - s ) ;
CFixedVector2D v ( s , c ) ;
StaticShape & shape = m_StaticShapes [ TAG_TO_INDEX ( tag ) ] ;
2010-09-19 11:08:56 -07:00
2015-06-14 12:22:07 -07:00
MakeDirtyStatic ( shape . flags , TAG_TO_INDEX ( tag ) , shape ) ; // dirty the old shape region
2010-09-19 11:08:56 -07:00
CFixedVector2D fromBbHalfSize = Geometry : : GetHalfBoundingBox ( shape . u , shape . v , CFixedVector2D ( shape . hw , shape . hh ) ) ;
CFixedVector2D toBbHalfSize = Geometry : : GetHalfBoundingBox ( u , v , CFixedVector2D ( shape . hw , shape . hh ) ) ;
m_StaticSubdivision . Move ( TAG_TO_INDEX ( tag ) ,
CFixedVector2D ( shape . x , shape . z ) - fromBbHalfSize ,
CFixedVector2D ( shape . x , shape . z ) + fromBbHalfSize ,
CFixedVector2D ( x , z ) - toBbHalfSize ,
CFixedVector2D ( x , z ) + toBbHalfSize ) ;
2010-04-29 16:36:05 -07:00
shape . x = x ;
shape . z = z ;
shape . u = u ;
shape . v = v ;
2010-03-17 16:01:12 -07:00
2015-06-14 12:22:07 -07:00
MakeDirtyStatic ( shape . flags , TAG_TO_INDEX ( tag ) , shape ) ; // dirty the new shape region
2010-07-25 07:11:21 -07:00
}
2010-03-17 16:01:12 -07:00
}
2010-04-29 16:36:05 -07:00
virtual void SetUnitMovingFlag ( tag_t tag , bool moving )
{
2011-04-30 06:01:45 -07:00
ENSURE ( TAG_IS_VALID ( tag ) & & TAG_IS_UNIT ( tag ) ) ;
2010-04-29 16:36:05 -07:00
if ( TAG_IS_UNIT ( tag ) )
{
UnitShape & shape = m_UnitShapes [ TAG_TO_INDEX ( tag ) ] ;
2011-02-10 08:06:28 -08:00
if ( moving )
shape . flags | = FLAG_MOVING ;
else
2011-08-16 04:18:32 -07:00
shape . flags & = ( flags_t ) ~ FLAG_MOVING ;
2011-03-02 16:16:14 -08:00
MakeDirtyDebug ( ) ;
2010-04-29 16:36:05 -07:00
}
}
2010-09-03 02:55:14 -07:00
virtual void SetUnitControlGroup ( tag_t tag , entity_id_t group )
{
2011-04-30 06:01:45 -07:00
ENSURE ( TAG_IS_VALID ( tag ) & & TAG_IS_UNIT ( tag ) ) ;
2010-09-03 02:55:14 -07:00
if ( TAG_IS_UNIT ( tag ) )
{
UnitShape & shape = m_UnitShapes [ TAG_TO_INDEX ( tag ) ] ;
shape . group = group ;
}
}
2012-05-05 12:22:22 -07:00
virtual void SetStaticControlGroup ( tag_t tag , entity_id_t group , entity_id_t group2 )
{
ENSURE ( TAG_IS_VALID ( tag ) & & TAG_IS_STATIC ( tag ) ) ;
if ( TAG_IS_STATIC ( tag ) )
{
StaticShape & shape = m_StaticShapes [ TAG_TO_INDEX ( tag ) ] ;
shape . group = group ;
shape . group2 = group2 ;
}
}
2010-03-17 16:01:12 -07:00
virtual void RemoveShape ( tag_t tag )
{
2011-04-30 06:01:45 -07:00
ENSURE ( TAG_IS_VALID ( tag ) ) ;
2010-03-17 16:01:12 -07:00
2010-04-29 16:36:05 -07:00
if ( TAG_IS_UNIT ( tag ) )
2010-07-25 07:11:21 -07:00
{
2010-09-19 11:08:56 -07:00
UnitShape & shape = m_UnitShapes [ TAG_TO_INDEX ( tag ) ] ;
m_UnitSubdivision . Remove ( TAG_TO_INDEX ( tag ) ,
2015-07-18 01:37:49 -07:00
CFixedVector2D ( shape . x - shape . clearance , shape . z - shape . clearance ) ,
CFixedVector2D ( shape . x + shape . clearance , shape . z + shape . clearance ) ) ;
2010-09-19 11:08:56 -07:00
2015-06-14 12:22:07 -07:00
MakeDirtyUnit ( shape . flags , TAG_TO_INDEX ( tag ) , shape ) ;
2010-04-29 16:36:05 -07:00
m_UnitShapes . erase ( TAG_TO_INDEX ( tag ) ) ;
2010-07-25 07:11:21 -07:00
}
2010-03-17 16:01:12 -07:00
else
2010-07-25 07:11:21 -07:00
{
2010-09-19 11:08:56 -07:00
StaticShape & shape = m_StaticShapes [ TAG_TO_INDEX ( tag ) ] ;
CFixedVector2D center ( shape . x , shape . z ) ;
CFixedVector2D bbHalfSize = Geometry : : GetHalfBoundingBox ( shape . u , shape . v , CFixedVector2D ( shape . hw , shape . hh ) ) ;
m_StaticSubdivision . Remove ( TAG_TO_INDEX ( tag ) , center - bbHalfSize , center + bbHalfSize ) ;
2015-06-14 12:22:07 -07:00
MakeDirtyStatic ( shape . flags , TAG_TO_INDEX ( tag ) , shape ) ;
2010-04-29 16:36:05 -07:00
m_StaticShapes . erase ( TAG_TO_INDEX ( tag ) ) ;
2010-07-25 07:11:21 -07:00
}
2010-03-17 16:01:12 -07:00
}
2017-01-19 18:25:19 -08:00
virtual ObstructionSquare GetObstruction ( tag_t tag ) const
2010-04-29 16:36:05 -07:00
{
2011-04-30 06:01:45 -07:00
ENSURE ( TAG_IS_VALID ( tag ) ) ;
2010-04-29 16:36:05 -07:00
if ( TAG_IS_UNIT ( tag ) )
{
2017-01-19 18:25:19 -08:00
const UnitShape & shape = m_UnitShapes . at ( TAG_TO_INDEX ( tag ) ) ;
2010-04-29 16:36:05 -07:00
CFixedVector2D u ( entity_pos_t : : FromInt ( 1 ) , entity_pos_t : : Zero ( ) ) ;
CFixedVector2D v ( entity_pos_t : : Zero ( ) , entity_pos_t : : FromInt ( 1 ) ) ;
2015-07-18 01:37:49 -07:00
ObstructionSquare o = { shape . x , shape . z , u , v , shape . clearance , shape . clearance } ;
2010-04-29 16:36:05 -07:00
return o ;
}
else
{
2017-01-19 18:25:19 -08:00
const StaticShape & shape = m_StaticShapes . at ( TAG_TO_INDEX ( tag ) ) ;
2010-04-29 16:36:05 -07:00
ObstructionSquare o = { shape . x , shape . z , shape . u , shape . v , shape . hw , shape . hh } ;
return o ;
}
}
2018-01-21 13:21:21 -08:00
virtual fixed DistanceToPoint ( entity_id_t ent , entity_pos_t px , entity_pos_t pz ) const ;
2019-06-06 12:37:23 -07:00
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 MaxDistanceToTarget ( entity_id_t ent , entity_id_t target ) const ;
virtual fixed DistanceBetweenShapes ( const ObstructionSquare & source , const ObstructionSquare & target ) const ;
virtual fixed MaxDistanceBetweenShapes ( const ObstructionSquare & source , const ObstructionSquare & target ) const ;
virtual bool IsInPointRange ( entity_id_t ent , entity_pos_t px , entity_pos_t pz , entity_pos_t minRange , entity_pos_t maxRange , bool opposite ) const ;
virtual bool IsInTargetRange ( entity_id_t ent , entity_id_t target , entity_pos_t minRange , entity_pos_t maxRange , bool opposite ) const ;
virtual bool IsPointInPointRange ( entity_pos_t x , entity_pos_t z , entity_pos_t px , entity_pos_t pz , entity_pos_t minRange , entity_pos_t maxRange ) const ;
2019-07-03 11:06:53 -07:00
virtual bool AreShapesInRange ( const ObstructionSquare & source , const ObstructionSquare & target , entity_pos_t minRange , entity_pos_t maxRange , bool opposite ) const ;
2018-01-21 13:21:21 -08:00
2017-01-19 18:25:19 -08:00
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 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 ;
2010-03-17 16:01:12 -07:00
2015-10-03 01:27:19 -07:00
virtual void Rasterize ( Grid < NavcellData > & grid , const std : : vector < PathfinderPassability > & passClasses , bool fullUpdate ) ;
2017-01-19 18:25:19 -08:00
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 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 ;
2018-03-20 18:44:15 -07:00
virtual void GetStaticObstructionsOnObstruction ( const ObstructionSquare & square , std : : vector < entity_id_t > & out , const IObstructionTestFilter & filter ) const ;
2010-03-17 16:01:12 -07:00
2010-10-30 11:25:34 -07:00
virtual void SetPassabilityCircular ( bool enabled )
{
m_PassabilityCircular = enabled ;
2011-02-27 17:24:12 -08:00
MakeDirtyAll ( ) ;
2014-06-03 15:35:40 -07:00
CMessageObstructionMapShapeChanged msg ;
GetSimContext ( ) . GetComponentManager ( ) . BroadcastMessage ( msg ) ;
2010-10-30 11:25:34 -07:00
}
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
virtual bool GetPassabilityCircular ( ) const
{
return m_PassabilityCircular ;
}
2010-03-20 12:18:01 -07:00
virtual void SetDebugOverlay ( bool enabled )
{
m_DebugOverlayEnabled = enabled ;
m_DebugOverlayDirty = true ;
if ( ! enabled )
m_DebugOverlayLines . clear ( ) ;
}
2011-01-16 06:08:38 -08:00
void RenderSubmit ( SceneCollector & collector ) ;
2010-03-20 12:18:01 -07:00
2015-06-14 12:22:07 -07:00
virtual void UpdateInformations ( GridUpdateInformation & informations )
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
{
2017-07-14 03:09:32 -07:00
if ( ! m_UpdateInformations . dirtinessGrid . blank ( ) )
informations . MergeAndClear ( m_UpdateInformations ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
}
private :
// Dynamic updates for the long-range pathfinder
2015-06-14 12:22:07 -07:00
GridUpdateInformation m_UpdateInformations ;
// These vectors might contain shapes that were deleted
std : : vector < u32 > m_DirtyStaticShapes ;
std : : vector < u32 > m_DirtyUnitShapes ;
2010-03-17 16:01:12 -07:00
/**
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
* Mark all previous Rasterize ( ) d grids as dirty , and the debug display .
2011-02-27 17:24:12 -08:00
* Call this when the world bounds have changed .
2010-03-17 16:01:12 -07:00
*/
2011-02-27 17:24:12 -08:00
void MakeDirtyAll ( )
2010-03-17 16:01:12 -07:00
{
2015-06-14 12:22:07 -07:00
m_UpdateInformations . dirty = true ;
m_UpdateInformations . globallyDirty = true ;
m_UpdateInformations . dirtinessGrid . reset ( ) ;
2010-03-20 12:18:01 -07:00
m_DebugOverlayDirty = true ;
2010-03-17 16:01:12 -07:00
}
2011-03-02 16:16:14 -08:00
/**
* Mark the debug display as dirty .
* Call this when nothing has changed except a unit ' s ' moving ' flag .
*/
void MakeDirtyDebug ( )
{
m_DebugOverlayDirty = true ;
}
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
inline void MarkDirtinessGrid ( const entity_pos_t & x , const entity_pos_t & z , const entity_pos_t & r )
2010-07-25 07:11:21 -07:00
{
2015-06-14 12:22:07 -07:00
MarkDirtinessGrid ( x , z , CFixedVector2D ( r , r ) ) ;
}
inline void MarkDirtinessGrid ( const entity_pos_t & x , const entity_pos_t & z , const CFixedVector2D & hbox )
{
2015-06-23 13:39:11 -07:00
ENSURE ( m_UpdateInformations . dirtinessGrid . m_W = = m_TerrainTiles * Pathfinding : : NAVCELLS_PER_TILE & &
m_UpdateInformations . dirtinessGrid . m_H = = m_TerrainTiles * Pathfinding : : NAVCELLS_PER_TILE ) ;
if ( m_TerrainTiles = = 0 )
2015-06-15 12:48:42 -07:00
return ;
2011-02-27 17:24:12 -08:00
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
u16 j0 , j1 , i0 , i1 ;
2015-06-14 12:22:07 -07:00
Pathfinding : : NearestNavcell ( x - hbox . X , z - hbox . Y , i0 , j0 , m_UpdateInformations . dirtinessGrid . m_W , m_UpdateInformations . dirtinessGrid . m_H ) ;
Pathfinding : : NearestNavcell ( x + hbox . X , z + hbox . Y , i1 , j1 , m_UpdateInformations . dirtinessGrid . m_W , m_UpdateInformations . dirtinessGrid . m_H ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
for ( int j = j0 ; j < j1 ; + + j )
for ( int i = i0 ; i < i1 ; + + i )
2015-06-14 12:22:07 -07:00
m_UpdateInformations . dirtinessGrid . set ( i , j , 1 ) ;
2011-02-27 17:24:12 -08:00
}
/**
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
* Mark all previous Rasterize ( ) d grids as dirty , if they depend on this shape .
* Call this when a static shape has changed .
2011-02-27 17:24:12 -08:00
*/
2015-06-14 12:22:07 -07:00
void MakeDirtyStatic ( flags_t flags , u32 index , const StaticShape & shape )
2011-02-27 17:24:12 -08:00
{
2015-06-14 12:22:07 -07:00
m_DebugOverlayDirty = true ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
if ( flags & ( FLAG_BLOCK_PATHFINDING | FLAG_BLOCK_FOUNDATION ) )
{
2015-06-14 12:22:07 -07:00
m_UpdateInformations . dirty = true ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
2015-06-14 12:22:07 -07:00
if ( std : : find ( m_DirtyStaticShapes . begin ( ) , m_DirtyStaticShapes . end ( ) , index ) = = m_DirtyStaticShapes . end ( ) )
m_DirtyStaticShapes . push_back ( index ) ;
2011-02-27 17:24:12 -08:00
2015-06-18 09:31:38 -07:00
// 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,
// 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.
2015-06-14 12:22:07 -07:00
CFixedVector2D center ( shape . x , shape . z ) ;
2015-06-18 09:31:38 -07:00
CFixedVector2D hbox = Geometry : : GetHalfBoundingBox ( shape . u , shape . v , CFixedVector2D ( shape . hw , shape . hh ) ) ;
CFixedVector2D expand ( m_MaxClearance , m_MaxClearance ) ;
2015-06-14 12:22:07 -07:00
std : : vector < u32 > staticsNear ;
2015-06-18 09:31:38 -07:00
m_StaticSubdivision . GetInRange ( staticsNear , center - hbox - expand * 2 , center + hbox + expand * 2 ) ;
2015-06-14 12:22:07 -07:00
for ( u32 & staticId : staticsNear )
if ( std : : find ( m_DirtyStaticShapes . begin ( ) , m_DirtyStaticShapes . end ( ) , staticId ) = = m_DirtyStaticShapes . end ( ) )
m_DirtyStaticShapes . push_back ( staticId ) ;
std : : vector < u32 > unitsNear ;
2015-06-18 09:31:38 -07:00
m_UnitSubdivision . GetInRange ( unitsNear , center - hbox - expand * 2 , center + hbox + expand * 2 ) ;
2015-06-14 12:22:07 -07:00
for ( u32 & unitId : unitsNear )
if ( std : : find ( m_DirtyUnitShapes . begin ( ) , m_DirtyUnitShapes . end ( ) , unitId ) = = m_DirtyUnitShapes . end ( ) )
m_DirtyUnitShapes . push_back ( unitId ) ;
2015-06-18 09:31:38 -07:00
MarkDirtinessGrid ( shape . x , shape . z , hbox + expand ) ;
2015-06-14 12:22:07 -07:00
}
2010-07-25 07:11:21 -07:00
}
2010-03-17 16:01:12 -07:00
/**
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
* Mark all previous Rasterize ( ) d grids as dirty , if they depend on this shape .
* Call this when a unit shape has changed .
2010-03-17 16:01:12 -07:00
*/
2015-06-14 12:22:07 -07:00
void MakeDirtyUnit ( flags_t flags , u32 index , const UnitShape & shape )
2010-03-17 16:01:12 -07:00
{
2015-06-14 12:22:07 -07:00
m_DebugOverlayDirty = true ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
if ( flags & ( FLAG_BLOCK_PATHFINDING | FLAG_BLOCK_FOUNDATION ) )
{
2015-06-14 12:22:07 -07:00
m_UpdateInformations . dirty = true ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
2015-06-14 12:22:07 -07:00
if ( std : : find ( m_DirtyUnitShapes . begin ( ) , m_DirtyUnitShapes . end ( ) , index ) = = m_DirtyUnitShapes . end ( ) )
m_DirtyUnitShapes . push_back ( index ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
2015-06-18 09:31:38 -07:00
// 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,
// 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.
2015-06-14 12:22:07 -07:00
CFixedVector2D center ( shape . x , shape . z ) ;
std : : vector < u32 > staticsNear ;
2015-07-18 01:37:49 -07:00
m_StaticSubdivision . GetNear ( staticsNear , center , shape . clearance + m_MaxClearance * 2 ) ;
2015-06-14 12:22:07 -07:00
for ( u32 & staticId : staticsNear )
if ( std : : find ( m_DirtyStaticShapes . begin ( ) , m_DirtyStaticShapes . end ( ) , staticId ) = = m_DirtyStaticShapes . end ( ) )
m_DirtyStaticShapes . push_back ( staticId ) ;
std : : vector < u32 > unitsNear ;
2015-09-13 03:18:37 -07:00
m_UnitSubdivision . GetNear ( unitsNear , center , shape . clearance + m_MaxClearance * 2 ) ;
2015-06-14 12:22:07 -07:00
for ( u32 & unitId : unitsNear )
if ( std : : find ( m_DirtyUnitShapes . begin ( ) , m_DirtyUnitShapes . end ( ) , unitId ) = = m_DirtyUnitShapes . end ( ) )
m_DirtyUnitShapes . push_back ( unitId ) ;
2015-07-18 01:37:49 -07:00
MarkDirtinessGrid ( shape . x , shape . z , shape . clearance + m_MaxClearance ) ;
2015-06-14 12:22:07 -07:00
}
2010-03-17 16:01:12 -07:00
}
2010-07-25 07:11:21 -07:00
/**
* Return whether the given point is within the world bounds by at least r
*/
2017-01-19 18:25:19 -08:00
inline bool IsInWorld ( entity_pos_t x , entity_pos_t z , entity_pos_t r ) const
2010-07-25 07:11:21 -07:00
{
return ( m_WorldX0 + r < = x & & x < = m_WorldX1 - r & & m_WorldZ0 + r < = z & & z < = m_WorldZ1 - r ) ;
}
/**
* Return whether the given point is within the world bounds
*/
2017-01-19 18:25:19 -08:00
inline bool IsInWorld ( const CFixedVector2D & p ) const
2010-07-25 07:11:21 -07:00
{
return ( m_WorldX0 < = p . X & & p . X < = m_WorldX1 & & m_WorldZ0 < = p . Y & & p . Y < = m_WorldZ1 ) ;
}
2015-06-17 13:19:53 -07:00
2017-01-19 18:25:19 -08:00
void RasterizeHelper ( Grid < NavcellData > & grid , ICmpObstructionManager : : flags_t requireMask , bool fullUpdate , pass_class_t appliedMask , entity_pos_t clearance = fixed : : Zero ( ) ) const ;
2010-03-17 16:01:12 -07:00
} ;
REGISTER_COMPONENT_TYPE ( ObstructionManager )
2019-06-06 12:37:23 -07:00
/**
* DistanceTo function family , all end up in calculating a vector length , DistanceBetweenShapes or
* MaxDistanceBetweenShapes . The MaxFoo family calculates the opposite edge opposite edge distance .
* When the distance is undefined we return - 1.
*/
2018-01-21 13:21:21 -08:00
fixed CCmpObstructionManager : : DistanceToPoint ( entity_id_t ent , entity_pos_t px , entity_pos_t pz ) const
{
2019-06-06 12:37:23 -07:00
ObstructionSquare obstruction ;
CmpPtr < ICmpObstruction > cmpObstruction ( GetSimContext ( ) , ent ) ;
if ( cmpObstruction & & cmpObstruction - > GetObstructionSquare ( obstruction ) )
{
ObstructionSquare point ;
point . x = px ;
point . z = pz ;
return DistanceBetweenShapes ( obstruction , point ) ;
}
CmpPtr < ICmpPosition > cmpPosition ( GetSimContext ( ) , ent ) ;
if ( ! cmpPosition | | ! cmpPosition - > IsInWorld ( ) )
return fixed : : FromInt ( - 1 ) ;
return ( CFixedVector2D ( cmpPosition - > GetPosition2D ( ) . X , cmpPosition - > GetPosition2D ( ) . Y ) - CFixedVector2D ( px , pz ) ) . Length ( ) ;
}
fixed CCmpObstructionManager : : MaxDistanceToPoint ( entity_id_t ent , entity_pos_t px , entity_pos_t pz ) const
{
ObstructionSquare obstruction ;
CmpPtr < ICmpObstruction > cmpObstruction ( GetSimContext ( ) , ent ) ;
if ( ! cmpObstruction | | ! cmpObstruction - > GetObstructionSquare ( obstruction ) )
{
ObstructionSquare point ;
point . x = px ;
point . z = pz ;
return MaxDistanceBetweenShapes ( obstruction , point ) ;
}
2018-01-21 13:21:21 -08:00
CmpPtr < ICmpPosition > cmpPosition ( GetSimContext ( ) , ent ) ;
if ( ! cmpPosition | | ! cmpPosition - > IsInWorld ( ) )
return fixed : : FromInt ( - 1 ) ;
2019-06-06 12:37:23 -07:00
return ( CFixedVector2D ( cmpPosition - > GetPosition2D ( ) . X , cmpPosition - > GetPosition2D ( ) . Y ) - CFixedVector2D ( px , pz ) ) . Length ( ) ;
}
fixed CCmpObstructionManager : : DistanceToTarget ( entity_id_t ent , entity_id_t target ) const
{
ObstructionSquare obstruction ;
2018-01-21 13:21:21 -08:00
CmpPtr < ICmpObstruction > cmpObstruction ( GetSimContext ( ) , ent ) ;
2019-06-06 12:37:23 -07:00
if ( ! cmpObstruction | | ! cmpObstruction - > GetObstructionSquare ( obstruction ) )
{
CmpPtr < ICmpPosition > cmpPosition ( GetSimContext ( ) , ent ) ;
if ( ! cmpPosition | | ! cmpPosition - > IsInWorld ( ) )
return fixed : : FromInt ( - 1 ) ;
return DistanceToPoint ( target , cmpPosition - > GetPosition2D ( ) . X , cmpPosition - > GetPosition2D ( ) . Y ) ;
}
ObstructionSquare target_obstruction ;
CmpPtr < ICmpObstruction > cmpObstructionTarget ( GetSimContext ( ) , target ) ;
if ( ! cmpObstructionTarget | | ! cmpObstructionTarget - > GetObstructionSquare ( target_obstruction ) )
{
CmpPtr < ICmpPosition > cmpPositionTarget ( GetSimContext ( ) , target ) ;
if ( ! cmpPositionTarget | | ! cmpPositionTarget - > IsInWorld ( ) )
return fixed : : FromInt ( - 1 ) ;
return DistanceToPoint ( ent , cmpPositionTarget - > GetPosition2D ( ) . X , cmpPositionTarget - > GetPosition2D ( ) . Y ) ;
}
return DistanceBetweenShapes ( obstruction , target_obstruction ) ;
}
2018-01-21 13:21:21 -08:00
2019-06-06 12:37:23 -07:00
fixed CCmpObstructionManager : : MaxDistanceToTarget ( entity_id_t ent , entity_id_t target ) const
{
ObstructionSquare obstruction ;
CmpPtr < ICmpObstruction > cmpObstruction ( GetSimContext ( ) , ent ) ;
if ( ! cmpObstruction | | ! cmpObstruction - > GetObstructionSquare ( obstruction ) )
{
CmpPtr < ICmpPosition > cmpPosition ( GetSimContext ( ) , ent ) ;
if ( ! cmpPosition | | ! cmpPosition - > IsInWorld ( ) )
return fixed : : FromInt ( - 1 ) ;
return MaxDistanceToPoint ( target , cmpPosition - > GetPosition2D ( ) . X , cmpPosition - > GetPosition2D ( ) . Y ) ;
}
ObstructionSquare target_obstruction ;
CmpPtr < ICmpObstruction > cmpObstructionTarget ( GetSimContext ( ) , target ) ;
if ( ! cmpObstructionTarget | | ! cmpObstructionTarget - > GetObstructionSquare ( target_obstruction ) )
{
CmpPtr < ICmpPosition > cmpPositionTarget ( GetSimContext ( ) , target ) ;
if ( ! cmpPositionTarget | | ! cmpPositionTarget - > IsInWorld ( ) )
return fixed : : FromInt ( - 1 ) ;
return MaxDistanceToPoint ( ent , cmpPositionTarget - > GetPosition2D ( ) . X , cmpPositionTarget - > GetPosition2D ( ) . Y ) ;
}
return MaxDistanceBetweenShapes ( obstruction , target_obstruction ) ;
}
fixed CCmpObstructionManager : : DistanceBetweenShapes ( const ObstructionSquare & source , const ObstructionSquare & target ) const
{
// Sphere-sphere collision.
if ( source . hh = = fixed : : Zero ( ) & & target . hh = = fixed : : Zero ( ) )
return ( CFixedVector2D ( target . x , target . z ) - CFixedVector2D ( source . x , source . z ) ) . Length ( ) - source . hw - target . hw ;
// Square to square.
if ( source . hh ! = fixed : : Zero ( ) & & target . hh ! = fixed : : Zero ( ) )
return Geometry : : DistanceSquareToSquare (
CFixedVector2D ( target . x , target . z ) - CFixedVector2D ( source . x , source . z ) ,
source . u , source . v , CFixedVector2D ( source . hw , source . hh ) ,
target . u , target . v , CFixedVector2D ( target . hw , target . hh ) ) ;
// To cover both remaining cases, shape a is the square one, shape b is the circular one.
const ObstructionSquare & a = source . hh = = fixed : : Zero ( ) ? target : source ;
const ObstructionSquare & b = source . hh = = fixed : : Zero ( ) ? source : target ;
return Geometry : : DistanceToSquare (
CFixedVector2D ( b . x , b . z ) - CFixedVector2D ( a . x , a . z ) ,
a . u , a . v , CFixedVector2D ( a . hw , a . hh ) , true ) - b . hw ;
}
fixed CCmpObstructionManager : : MaxDistanceBetweenShapes ( const ObstructionSquare & source , const ObstructionSquare & target ) const
{
// Sphere-sphere collision.
if ( source . hh = = fixed : : Zero ( ) & & target . hh = = fixed : : Zero ( ) )
return ( CFixedVector2D ( target . x , target . z ) - CFixedVector2D ( source . x , source . z ) ) . Length ( ) + source . hw + target . hw ;
// Square to square.
if ( source . hh ! = fixed : : Zero ( ) & & target . hh ! = fixed : : Zero ( ) )
return Geometry : : MaxDistanceSquareToSquare (
CFixedVector2D ( target . x , target . z ) - CFixedVector2D ( source . x , source . z ) ,
source . u , source . v , CFixedVector2D ( source . hw , source . hh ) ,
target . u , target . v , CFixedVector2D ( target . hw , target . hh ) ) ;
// To cover both remaining cases, shape a is the square one, shape b is the circular one.
const ObstructionSquare & a = source . hh = = fixed : : Zero ( ) ? target : source ;
const ObstructionSquare & b = source . hh = = fixed : : Zero ( ) ? source : target ;
return Geometry : : MaxDistanceToSquare (
CFixedVector2D ( b . x , b . z ) - CFixedVector2D ( a . x , a . z ) ,
a . u , a . v , CFixedVector2D ( a . hw , a . hh ) , true ) + b . hw ;
}
/**
* IsInRange function family depending on the DistanceTo family .
*
* In range if the edge to edge distance is inferior to maxRange
* and if the opposite edge to opposite edge distance is greater than minRange when the opposite bool is true
* or when the opposite bool is false the edge to edge distance is more than minRange .
*
* Using the opposite egde for minRange means that a unit is in range of a building if it is farther than
* clearance - buildingsize , which is generally going to be negative ( and thus this returns true ) .
* NB : from a game POV , this means units can easily fire on buildings , which is good ,
* but it also means that buildings can easily fire on units . Buildings are usually meant
* to fire from the edge , not the opposite edge , so this looks odd . For this reason one can choose
* to set the opposite bool false and use the edge to egde distance .
*
* We don ' t use squares because the are likely to overflow .
* We use a 0.0001 margin to avoid rounding errors .
*/
bool CCmpObstructionManager : : IsInPointRange ( entity_id_t ent , entity_pos_t px , entity_pos_t pz , entity_pos_t minRange , entity_pos_t maxRange , bool opposite ) const
{
fixed dist = DistanceToPoint ( ent , px , pz ) ;
2019-06-30 11:53:25 -07:00
// Treat -1 max range as infinite
return dist ! = fixed : : FromInt ( - 1 ) & &
2020-11-26 14:28:50 -08:00
( dist < = ( maxRange + fixed : : FromFloat ( 0.0001f ) ) | | maxRange < fixed : : Zero ( ) ) & &
( opposite ? MaxDistanceToPoint ( ent , px , pz ) : dist ) > = minRange - fixed : : FromFloat ( 0.0001f ) ;
2019-06-06 12:37:23 -07:00
}
bool CCmpObstructionManager : : IsInTargetRange ( entity_id_t ent , entity_id_t target , entity_pos_t minRange , entity_pos_t maxRange , bool opposite ) const
{
fixed dist = DistanceToTarget ( ent , target ) ;
2019-06-30 11:53:25 -07:00
// Treat -1 max range as infinite
return dist ! = fixed : : FromInt ( - 1 ) & &
2020-11-26 14:28:50 -08:00
( dist < = ( maxRange + fixed : : FromFloat ( 0.0001f ) ) | | maxRange < fixed : : Zero ( ) ) & &
( opposite ? MaxDistanceToTarget ( ent , target ) : dist ) > = minRange - fixed : : FromFloat ( 0.0001f ) ;
2019-06-06 12:37:23 -07:00
}
bool CCmpObstructionManager : : IsPointInPointRange ( entity_pos_t x , entity_pos_t z , entity_pos_t px , entity_pos_t pz , entity_pos_t minRange , entity_pos_t maxRange ) const
{
entity_pos_t distance = ( CFixedVector2D ( x , z ) - CFixedVector2D ( px , pz ) ) . Length ( ) ;
2019-06-30 11:53:25 -07:00
// Treat -1 max range as infinite
2020-11-26 14:28:50 -08:00
return ( distance < = ( maxRange + fixed : : FromFloat ( 0.0001f ) ) | | maxRange < fixed : : Zero ( ) ) & &
distance > = minRange - fixed : : FromFloat ( 0.0001f ) ;
2018-01-21 13:21:21 -08:00
}
2019-07-03 11:06:53 -07:00
bool CCmpObstructionManager : : AreShapesInRange ( const ObstructionSquare & source , const ObstructionSquare & target , entity_pos_t minRange , entity_pos_t maxRange , bool opposite ) const
{
fixed dist = DistanceBetweenShapes ( source , target ) ;
// Treat -1 max range as infinite
return dist ! = fixed : : FromInt ( - 1 ) & &
2020-11-26 14:28:50 -08:00
( dist < = ( maxRange + fixed : : FromFloat ( 0.0001f ) ) | | maxRange < fixed : : Zero ( ) ) & &
( opposite ? MaxDistanceBetweenShapes ( source , target ) : dist ) > = minRange - fixed : : FromFloat ( 0.0001f ) ;
2019-07-03 11:06:53 -07:00
}
2017-01-19 18:25:19 -08:00
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
2010-03-17 16:01:12 -07:00
{
PROFILE ( " TestLine " ) ;
2010-07-25 07:11:21 -07:00
// 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 ) )
return true ;
2010-09-19 11:08:56 -07:00
CFixedVector2D posMin ( std : : min ( x0 , x1 ) - r , std : : min ( z0 , z1 ) - r ) ;
CFixedVector2D posMax ( std : : max ( x0 , x1 ) + r , std : : max ( z0 , z1 ) + r ) ;
2015-11-06 11:48:08 -08:00
// actual radius used for unit-unit collisions. If relaxClearanceForUnits, will be smaller to allow more overlap.
entity_pos_t unitUnitRadius = r ;
if ( relaxClearanceForUnits )
unitUnitRadius - = entity_pos_t : : FromInt ( 1 ) / 2 ;
2014-08-06 02:21:00 -07:00
std : : vector < entity_id_t > unitShapes ;
2013-09-15 07:03:53 -07:00
m_UnitSubdivision . GetInRange ( unitShapes , posMin , posMax ) ;
2017-11-11 03:14:39 -08:00
for ( const entity_id_t & shape : unitShapes )
2010-03-17 16:01:12 -07:00
{
2017-11-11 03:14:39 -08:00
std : : map < u32 , UnitShape > : : const_iterator it = m_UnitShapes . find ( shape ) ;
2011-04-30 06:01:45 -07:00
ENSURE ( it ! = m_UnitShapes . end ( ) ) ;
2010-09-19 11:08:56 -07:00
2012-05-05 12:22:22 -07:00
if ( ! filter . TestShape ( UNIT_INDEX_TO_TAG ( it - > first ) , it - > second . flags , it - > second . group , INVALID_ENTITY ) )
2010-03-17 16:01:12 -07:00
continue ;
2010-04-29 16:36:05 -07:00
CFixedVector2D center ( it - > second . x , it - > second . z ) ;
2015-11-06 11:48:08 -08:00
CFixedVector2D halfSize ( it - > second . clearance + unitUnitRadius , it - > second . clearance + unitUnitRadius ) ;
2010-09-19 11:08:56 -07:00
if ( Geometry : : TestRayAASquare ( CFixedVector2D ( x0 , z0 ) - center , CFixedVector2D ( x1 , z1 ) - center , halfSize ) )
2010-04-29 16:36:05 -07:00
return true ;
2010-03-17 16:01:12 -07:00
}
2015-11-01 05:38:48 -08:00
std : : vector < entity_id_t > staticShapes ;
m_StaticSubdivision . GetInRange ( staticShapes , posMin , posMax ) ;
2017-11-11 03:14:39 -08:00
for ( const entity_id_t & shape : staticShapes )
2015-11-01 05:38:48 -08:00
{
2017-11-11 03:14:39 -08:00
std : : map < u32 , StaticShape > : : const_iterator it = m_StaticShapes . find ( shape ) ;
2015-11-01 05:38:48 -08:00
ENSURE ( it ! = m_StaticShapes . end ( ) ) ;
2016-11-23 06:09:58 -08:00
2015-11-01 05:38:48 -08:00
if ( ! filter . TestShape ( STATIC_INDEX_TO_TAG ( it - > first ) , it - > second . flags , it - > second . group , it - > second . group2 ) )
continue ;
2016-11-23 06:09:58 -08:00
2015-11-01 05:38:48 -08:00
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 ;
}
2016-11-23 06:09:58 -08:00
2015-11-01 05:38:48 -08:00
return false ;
}
2011-02-10 08:06:28 -08:00
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 ,
2017-01-19 18:25:19 -08:00
std : : vector < entity_id_t > * out ) const
2010-03-17 16:01:12 -07:00
{
2010-04-29 16:36:05 -07:00
PROFILE ( " TestStaticShape " ) ;
2011-02-10 08:06:28 -08:00
if ( out )
out - > clear ( ) ;
2010-05-02 13:32:37 -07:00
fixed s , c ;
2010-04-29 16:36:05 -07:00
sincos_approx ( a , s , c ) ;
CFixedVector2D u ( c , - s ) ;
CFixedVector2D v ( s , c ) ;
CFixedVector2D center ( x , z ) ;
CFixedVector2D halfSize ( w / 2 , h / 2 ) ;
2017-11-11 03:14:39 -08:00
CFixedVector2D corner1 = u . Multiply ( halfSize . X ) + v . Multiply ( halfSize . Y ) ;
CFixedVector2D corner2 = u . Multiply ( halfSize . X ) - v . Multiply ( halfSize . Y ) ;
2010-03-17 16:01:12 -07:00
2010-07-25 07:11:21 -07:00
// Check that all corners are within the world (which means the whole shape must be)
2017-11-11 03:14:39 -08:00
if ( ! IsInWorld ( center + corner1 ) | | ! IsInWorld ( center + corner2 ) | |
! IsInWorld ( center - corner1 ) | | ! IsInWorld ( center - corner2 ) )
2011-02-10 08:06:28 -08:00
{
if ( out )
out - > push_back ( INVALID_ENTITY ) ; // no entity ID, so just push an arbitrary marker
else
return true ;
}
2010-07-25 07:11:21 -07:00
2017-11-11 03:14:39 -08:00
fixed bbHalfWidth = std : : max ( corner1 . X . Absolute ( ) , corner2 . X . Absolute ( ) ) ;
fixed bbHalfHeight = std : : max ( corner1 . Y . Absolute ( ) , corner2 . Y . Absolute ( ) ) ;
CFixedVector2D posMin ( x - bbHalfWidth , z - bbHalfHeight ) ;
CFixedVector2D posMax ( x + bbHalfWidth , z + bbHalfHeight ) ;
std : : vector < entity_id_t > unitShapes ;
m_UnitSubdivision . GetInRange ( unitShapes , posMin , posMax ) ;
for ( entity_id_t & shape : unitShapes )
2010-03-17 16:01:12 -07:00
{
2017-11-11 03:14:39 -08:00
std : : map < u32 , UnitShape > : : const_iterator it = m_UnitShapes . find ( shape ) ;
ENSURE ( it ! = m_UnitShapes . end ( ) ) ;
2012-05-05 12:22:22 -07:00
if ( ! filter . TestShape ( UNIT_INDEX_TO_TAG ( it - > first ) , it - > second . flags , it - > second . group , INVALID_ENTITY ) )
2010-03-17 16:01:12 -07:00
continue ;
2010-04-29 16:36:05 -07:00
CFixedVector2D center1 ( it - > second . x , it - > second . z ) ;
2015-07-18 01:37:49 -07:00
if ( Geometry : : PointIsInSquare ( center1 - center , u , v , CFixedVector2D ( halfSize . X + it - > second . clearance , halfSize . Y + it - > second . clearance ) ) )
2011-02-10 08:06:28 -08:00
{
if ( out )
out - > push_back ( it - > second . entity ) ;
else
return true ;
}
2010-03-17 16:01:12 -07:00
}
2017-11-11 03:14:39 -08:00
std : : vector < entity_id_t > staticShapes ;
m_StaticSubdivision . GetInRange ( staticShapes , posMin , posMax ) ;
for ( entity_id_t & shape : staticShapes )
2010-03-17 16:01:12 -07:00
{
2017-11-11 03:14:39 -08:00
std : : map < u32 , StaticShape > : : const_iterator it = m_StaticShapes . find ( shape ) ;
ENSURE ( it ! = m_StaticShapes . end ( ) ) ;
2012-05-05 12:22:22 -07:00
if ( ! filter . TestShape ( STATIC_INDEX_TO_TAG ( it - > first ) , it - > second . flags , it - > second . group , it - > second . group2 ) )
2010-03-17 16:01:12 -07:00
continue ;
2010-04-29 16:36:05 -07:00
CFixedVector2D center1 ( it - > second . x , it - > second . z ) ;
CFixedVector2D halfSize1 ( it - > second . hw , it - > second . hh ) ;
if ( Geometry : : TestSquareSquare ( center , u , v , halfSize , center1 , it - > second . u , it - > second . v , halfSize1 ) )
2011-02-10 08:06:28 -08:00
{
if ( out )
out - > push_back ( it - > second . entity ) ;
else
return true ;
}
2010-03-17 16:01:12 -07:00
}
2011-02-10 08:06:28 -08:00
if ( out )
return ! out - > empty ( ) ; // collided if the list isn't empty
else
return false ; // didn't collide, if we got this far
2010-03-17 16:01:12 -07:00
}
2011-02-10 08:06:28 -08:00
bool CCmpObstructionManager : : TestUnitShape ( const IObstructionTestFilter & filter ,
2015-07-18 01:37:49 -07:00
entity_pos_t x , entity_pos_t z , entity_pos_t clearance ,
2017-01-19 18:25:19 -08:00
std : : vector < entity_id_t > * out ) const
2010-03-17 16:01:12 -07:00
{
2010-04-29 16:36:05 -07:00
PROFILE ( " TestUnitShape " ) ;
2010-07-25 07:11:21 -07:00
// Check that the shape is within the world
2015-07-18 01:37:49 -07:00
if ( ! IsInWorld ( x , z , clearance ) )
2011-02-10 08:06:28 -08:00
{
if ( out )
out - > push_back ( INVALID_ENTITY ) ; // no entity ID, so just push an arbitrary marker
else
return true ;
}
2010-07-25 07:11:21 -07:00
2010-04-29 16:36:05 -07:00
CFixedVector2D center ( x , z ) ;
2017-11-11 03:14:39 -08:00
CFixedVector2D posMin ( x - clearance , z - clearance ) ;
CFixedVector2D posMax ( x + clearance , z + clearance ) ;
2010-04-29 16:36:05 -07:00
2017-11-11 03:14:39 -08:00
std : : vector < entity_id_t > unitShapes ;
m_UnitSubdivision . GetInRange ( unitShapes , posMin , posMax ) ;
for ( const entity_id_t & shape : unitShapes )
2010-04-29 16:36:05 -07:00
{
2017-11-11 03:14:39 -08:00
std : : map < u32 , UnitShape > : : const_iterator it = m_UnitShapes . find ( shape ) ;
ENSURE ( it ! = m_UnitShapes . end ( ) ) ;
2012-05-05 12:22:22 -07:00
if ( ! filter . TestShape ( UNIT_INDEX_TO_TAG ( it - > first ) , it - > second . flags , it - > second . group , INVALID_ENTITY ) )
2010-04-29 16:36:05 -07:00
continue ;
2015-07-18 01:37:49 -07:00
entity_pos_t c1 = it - > second . clearance ;
2010-04-29 16:36:05 -07:00
2015-07-18 01:37:49 -07:00
if ( ! (
it - > second . x + c1 < x - clearance | |
it - > second . x - c1 > x + clearance | |
it - > second . z + c1 < z - clearance | |
it - > second . z - c1 > z + clearance ) )
2011-02-10 08:06:28 -08:00
{
if ( out )
out - > push_back ( it - > second . entity ) ;
else
return true ;
}
2010-04-29 16:36:05 -07:00
}
2017-11-11 03:14:39 -08:00
std : : vector < entity_id_t > staticShapes ;
m_StaticSubdivision . GetInRange ( staticShapes , posMin , posMax ) ;
for ( const entity_id_t & shape : staticShapes )
2010-04-29 16:36:05 -07:00
{
2017-11-11 03:14:39 -08:00
std : : map < u32 , StaticShape > : : const_iterator it = m_StaticShapes . find ( shape ) ;
ENSURE ( it ! = m_StaticShapes . end ( ) ) ;
2012-05-05 12:22:22 -07:00
if ( ! filter . TestShape ( STATIC_INDEX_TO_TAG ( it - > first ) , it - > second . flags , it - > second . group , it - > second . group2 ) )
2010-04-29 16:36:05 -07:00
continue ;
CFixedVector2D center1 ( it - > second . x , it - > second . z ) ;
2015-07-18 01:37:49 -07:00
if ( Geometry : : PointIsInSquare ( center1 - center , it - > second . u , it - > second . v , CFixedVector2D ( it - > second . hw + clearance , it - > second . hh + clearance ) ) )
2011-02-10 08:06:28 -08:00
{
if ( out )
out - > push_back ( it - > second . entity ) ;
else
return true ;
}
2010-04-29 16:36:05 -07:00
}
2011-02-10 08:06:28 -08:00
if ( out )
return ! out - > empty ( ) ; // collided if the list isn't empty
else
return false ; // didn't collide, if we got this far
2010-03-17 16:01:12 -07:00
}
2015-10-03 01:27:19 -07:00
void CCmpObstructionManager : : Rasterize ( Grid < NavcellData > & grid , const std : : vector < PathfinderPassability > & passClasses , bool fullUpdate )
2010-03-17 16:01:12 -07:00
{
2016-06-25 06:12:35 -07:00
PROFILE3 ( " Rasterize Obstructions " ) ;
2010-04-29 16:36:05 -07:00
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
// Cells are only marked as blocked if the whole cell is strictly inside the shape.
// (That ensures the shape's geometric border is always reachable.)
2010-03-17 16:01:12 -07:00
2015-06-17 13:19:53 -07:00
// Pass classes will get shapes rasterized on them depending on their Obstruction value.
// Classes with another value than "pathfinding" should not use Clearance.
std : : map < entity_pos_t , u16 > pathfindingMasks ;
u16 foundationMask = 0 ;
2015-06-14 12:22:07 -07:00
for ( const PathfinderPassability & passability : passClasses )
2010-03-17 16:01:12 -07:00
{
2015-06-17 13:19:53 -07:00
switch ( passability . m_Obstructions )
{
case PathfinderPassability : : PATHFINDING :
{
2018-03-20 18:44:15 -07:00
std : : map < entity_pos_t , u16 > : : iterator it = pathfindingMasks . find ( passability . m_Clearance ) ;
2015-06-17 13:19:53 -07:00
if ( it = = pathfindingMasks . end ( ) )
pathfindingMasks [ passability . m_Clearance ] = passability . m_Mask ;
else
it - > second | = passability . m_Mask ;
break ;
}
case PathfinderPassability : : FOUNDATION :
foundationMask | = passability . m_Mask ;
break ;
default :
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
continue ;
2015-06-17 13:19:53 -07:00
}
2015-06-14 12:22:07 -07:00
}
2015-06-17 13:19:53 -07:00
// FLAG_BLOCK_PATHFINDING and FLAG_BLOCK_FOUNDATION are the only flags taken into account by MakeDirty* functions,
// so they should be the only ones rasterized using with the help of m_Dirty*Shapes vectors.
for ( auto & maskPair : pathfindingMasks )
RasterizeHelper ( grid , FLAG_BLOCK_PATHFINDING , fullUpdate , maskPair . second , maskPair . first ) ;
RasterizeHelper ( grid , FLAG_BLOCK_FOUNDATION , fullUpdate , foundationMask ) ;
m_DirtyStaticShapes . clear ( ) ;
m_DirtyUnitShapes . clear ( ) ;
}
2017-01-19 18:25:19 -08:00
void CCmpObstructionManager : : RasterizeHelper ( Grid < NavcellData > & grid , ICmpObstructionManager : : flags_t requireMask , bool fullUpdate , pass_class_t appliedMask , entity_pos_t clearance ) const
2015-06-17 13:19:53 -07:00
{
for ( auto & pair : m_StaticShapes )
2015-06-14 12:22:07 -07:00
{
2015-06-17 13:19:53 -07:00
const StaticShape & shape = pair . second ;
if ( ! ( shape . flags & requireMask ) )
continue ;
2015-09-13 03:18:37 -07:00
if ( ! fullUpdate & & std : : find ( m_DirtyStaticShapes . begin ( ) , m_DirtyStaticShapes . end ( ) , pair . first ) = = m_DirtyStaticShapes . end ( ) )
continue ;
2015-06-17 13:19:53 -07:00
// 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 } ;
SimRasterize : : Spans spans ;
SimRasterize : : RasterizeRectWithClearance ( spans , square , clearance , Pathfinding : : NAVCELL_SIZE ) ;
for ( SimRasterize : : Span & span : spans )
2010-04-29 16:36:05 -07:00
{
2015-08-28 04:38:14 -07:00
i16 j = Clamp ( span . j , ( i16 ) 0 , ( i16 ) ( grid . m_H - 1 ) ) ;
i16 i0 = std : : max ( span . i0 , ( i16 ) 0 ) ;
i16 i1 = std : : min ( span . i1 , ( i16 ) grid . m_W ) ;
for ( i16 i = i0 ; i < i1 ; + + i )
grid . set ( i , j , grid . get ( i , j ) | appliedMask ) ;
2010-04-29 16:36:05 -07:00
}
2015-06-17 13:19:53 -07:00
}
2010-03-17 16:01:12 -07:00
2015-06-17 13:19:53 -07:00
for ( auto & pair : m_UnitShapes )
{
2015-09-13 03:18:37 -07:00
if ( ! ( pair . second . flags & requireMask ) )
2015-06-17 13:19:53 -07:00
continue ;
2011-02-10 08:06:28 -08:00
2015-09-13 03:18:37 -07:00
if ( ! fullUpdate & & std : : find ( m_DirtyUnitShapes . begin ( ) , m_DirtyUnitShapes . end ( ) , pair . first ) = = m_DirtyUnitShapes . end ( ) )
2015-06-17 13:19:53 -07:00
continue ;
2010-10-30 11:25:34 -07:00
2015-09-13 03:18:37 -07:00
CFixedVector2D center ( pair . second . x , pair . second . z ) ;
2015-07-18 01:37:49 -07:00
entity_pos_t r = pair . second . clearance + clearance ;
2010-10-30 11:25:34 -07:00
2015-06-17 13:19:53 -07:00
u16 i0 , j0 , i1 , j1 ;
Pathfinding : : NearestNavcell ( center . X - r , center . Y - r , i0 , j0 , grid . m_W , grid . m_H ) ;
Pathfinding : : NearestNavcell ( center . X + r , center . Y + r , i1 , j1 , grid . m_W , grid . m_H ) ;
for ( u16 j = j0 + 1 ; j < j1 ; + + j )
for ( u16 i = i0 + 1 ; i < i1 ; + + i )
grid . set ( i , j , grid . get ( i , j ) | appliedMask ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
}
2010-03-17 16:01:12 -07:00
}
2010-03-20 12:18:01 -07:00
2017-01-19 18:25:19 -08:00
void CCmpObstructionManager : : 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
2015-11-01 05:38:48 -08:00
{
GetUnitObstructionsInRange ( filter , x0 , z0 , x1 , z1 , squares ) ;
GetStaticObstructionsInRange ( filter , x0 , z0 , x1 , z1 , squares ) ;
}
2017-01-19 18:25:19 -08:00
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
2010-04-29 16:36:05 -07:00
{
PROFILE ( " GetObstructionsInRange " ) ;
2011-04-30 06:01:45 -07:00
ENSURE ( x0 < = x1 & & z0 < = z1 ) ;
2010-09-19 11:08:56 -07:00
2014-08-06 02:21:00 -07:00
std : : vector < entity_id_t > unitShapes ;
2013-09-15 07:03:53 -07:00
m_UnitSubdivision . GetInRange ( unitShapes , CFixedVector2D ( x0 , z0 ) , CFixedVector2D ( x1 , z1 ) ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
for ( entity_id_t & unitShape : unitShapes )
2010-04-29 16:36:05 -07:00
{
2018-03-20 18:44:15 -07:00
std : : map < u32 , UnitShape > : : const_iterator it = m_UnitShapes . find ( unitShape ) ;
2011-04-30 06:01:45 -07:00
ENSURE ( it ! = m_UnitShapes . end ( ) ) ;
2010-09-19 11:08:56 -07:00
2012-05-05 12:22:22 -07:00
if ( ! filter . TestShape ( UNIT_INDEX_TO_TAG ( it - > first ) , it - > second . flags , it - > second . group , INVALID_ENTITY ) )
2010-04-29 16:36:05 -07:00
continue ;
2015-07-18 01:37:49 -07:00
entity_pos_t c = it - > second . clearance ;
2010-04-29 16:36:05 -07:00
// Skip this object if it's completely outside the requested range
2015-07-18 01:37:49 -07:00
if ( it - > second . x + c < x0 | | it - > second . x - c > x1 | | it - > second . z + c < z0 | | it - > second . z - c > z1 )
2010-04-29 16:36:05 -07:00
continue ;
CFixedVector2D u ( entity_pos_t : : FromInt ( 1 ) , entity_pos_t : : Zero ( ) ) ;
CFixedVector2D v ( entity_pos_t : : Zero ( ) , entity_pos_t : : FromInt ( 1 ) ) ;
2015-07-18 01:37:49 -07:00
squares . emplace_back ( ObstructionSquare { it - > second . x , it - > second . z , u , v , c , c } ) ;
2010-04-29 16:36:05 -07:00
}
2015-11-01 05:38:48 -08:00
}
2010-04-29 16:36:05 -07:00
2017-01-19 18:25:19 -08:00
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
2015-11-01 05:38:48 -08:00
{
PROFILE ( " GetObstructionsInRange " ) ;
2016-11-23 06:09:58 -08:00
2015-11-01 05:38:48 -08:00
ENSURE ( x0 < = x1 & & z0 < = z1 ) ;
2016-11-23 06:09:58 -08:00
2014-08-06 02:21:00 -07:00
std : : vector < entity_id_t > staticShapes ;
2013-09-15 07:03:53 -07:00
m_StaticSubdivision . GetInRange ( staticShapes , CFixedVector2D ( x0 , z0 ) , CFixedVector2D ( x1 , z1 ) ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
for ( entity_id_t & staticShape : staticShapes )
2010-04-29 16:36:05 -07:00
{
2018-03-20 18:44:15 -07:00
std : : map < u32 , StaticShape > : : const_iterator it = m_StaticShapes . find ( staticShape ) ;
2011-04-30 06:01:45 -07:00
ENSURE ( it ! = m_StaticShapes . end ( ) ) ;
2010-09-19 11:08:56 -07:00
2012-05-05 12:22:22 -07:00
if ( ! filter . TestShape ( STATIC_INDEX_TO_TAG ( it - > first ) , it - > second . flags , it - > second . group , it - > second . group2 ) )
2010-04-29 16:36:05 -07:00
continue ;
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
if ( it - > second . x + r < x0 | | it - > second . x - r > x1 | | it - > second . z + r < z0 | | it - > second . z - r > z1 )
continue ;
// TODO: maybe we should use Geometry::GetHalfBoundingBox to be more precise?
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
squares . emplace_back ( ObstructionSquare { it - > second . x , it - > second . z , it - > second . u , it - > second . v , it - > second . hw , it - > second . hh } ) ;
2010-04-29 16:36:05 -07:00
}
}
2017-01-19 18:25:19 -08:00
void CCmpObstructionManager : : GetUnitsOnObstruction ( const ObstructionSquare & square , std : : vector < entity_id_t > & out , const IObstructionTestFilter & filter , bool strict ) const
2010-04-29 16:36:05 -07:00
{
2016-06-21 03:33:11 -07:00
PROFILE ( " GetUnitsOnObstruction " ) ;
2010-04-29 16:36:05 -07:00
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
// In order to avoid getting units on impassable cells, we want to find all
2018-03-20 18:44:15 -07:00
// units subject to the RasterizeRectWithClearance of the building's shape with the
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
// unit's clearance covers the navcell the unit is on.
2010-04-29 16:36:05 -07:00
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
std : : vector < entity_id_t > unitShapes ;
CFixedVector2D center ( square . x , square . z ) ;
CFixedVector2D expandedBox =
Geometry : : GetHalfBoundingBox ( square . u , square . v , CFixedVector2D ( square . hw , square . hh ) ) +
2015-06-14 12:22:07 -07:00
CFixedVector2D ( m_MaxClearance , m_MaxClearance ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
m_UnitSubdivision . GetInRange ( unitShapes , center - expandedBox , center + expandedBox ) ;
std : : map < entity_pos_t , SimRasterize : : Spans > rasterizedRects ;
2015-09-02 10:40:31 -07:00
for ( const u32 & unitShape : unitShapes )
2010-04-29 16:36:05 -07:00
{
2018-03-20 18:44:15 -07:00
std : : map < u32 , UnitShape > : : const_iterator it = m_UnitShapes . find ( unitShape ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
ENSURE ( it ! = m_UnitShapes . end ( ) ) ;
2017-01-19 18:25:19 -08:00
const UnitShape & shape = it - > second ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
if ( ! filter . TestShape ( UNIT_INDEX_TO_TAG ( unitShape ) , shape . flags , shape . group , INVALID_ENTITY ) )
continue ;
if ( rasterizedRects . find ( shape . clearance ) = = rasterizedRects . end ( ) )
2010-04-29 16:36:05 -07:00
{
2015-11-11 04:28:38 -08:00
// 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,
// 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).
// Foundations need to be non-strict, as otherwise it sometimes detects the builder units
// as being on the shape, so it orders them away.
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
SimRasterize : : Spans & newSpans = rasterizedRects [ shape . clearance ] ;
2015-11-11 04:28:38 -08:00
if ( strict )
SimRasterize : : RasterizeRectWithClearance ( newSpans , square , shape . clearance , Pathfinding : : NAVCELL_SIZE ) ;
else
2015-11-16 14:03:10 -08:00
SimRasterize : : RasterizeRectWithClearance ( newSpans , square , shape . clearance - Pathfinding : : CLEARANCE_EXTENSION_RADIUS , Pathfinding : : NAVCELL_SIZE ) ;
2010-04-29 16:36:05 -07:00
}
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
SimRasterize : : Spans & spans = rasterizedRects [ shape . clearance ] ;
// Check whether the unit's center is on a navcell that's in
// any of the spans
u16 i = ( shape . x / Pathfinding : : NAVCELL_SIZE ) . ToInt_RoundToNegInfinity ( ) ;
u16 j = ( shape . z / Pathfinding : : NAVCELL_SIZE ) . ToInt_RoundToNegInfinity ( ) ;
2015-09-02 10:40:31 -07:00
for ( const SimRasterize : : Span & span : spans )
2012-05-19 16:07:41 -07:00
{
2015-09-02 10:40:31 -07:00
if ( j = = span . j & & span . i0 < = i & & i < span . i1 )
{
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
out . push_back ( shape . entity ) ;
2015-09-02 10:40:31 -07:00
break ;
}
2012-05-19 16:07:41 -07:00
}
}
2010-04-29 16:36:05 -07:00
}
2018-03-20 18:44:15 -07:00
void CCmpObstructionManager : : GetStaticObstructionsOnObstruction ( const ObstructionSquare & square , std : : vector < entity_id_t > & out , const IObstructionTestFilter & filter ) const
{
PROFILE ( " GetStaticObstructionsOnObstruction " ) ;
std : : vector < entity_id_t > staticShapes ;
CFixedVector2D center ( square . x , square . z ) ;
CFixedVector2D expandedBox = Geometry : : GetHalfBoundingBox ( square . u , square . v , CFixedVector2D ( square . hw , square . hh ) ) ;
m_StaticSubdivision . GetInRange ( staticShapes , center - expandedBox , center + expandedBox ) ;
for ( const u32 & staticShape : staticShapes )
{
std : : map < u32 , StaticShape > : : const_iterator it = m_StaticShapes . find ( staticShape ) ;
ENSURE ( it ! = m_StaticShapes . end ( ) ) ;
const StaticShape & shape = it - > second ;
if ( ! filter . TestShape ( STATIC_INDEX_TO_TAG ( staticShape ) , shape . flags , shape . group , shape . group2 ) )
continue ;
if ( Geometry : : TestSquareSquare (
center ,
square . u ,
square . v ,
CFixedVector2D ( square . hw , square . hh ) ,
CFixedVector2D ( shape . x , shape . z ) ,
shape . u ,
shape . v ,
CFixedVector2D ( shape . hw , shape . hh ) ) )
{
out . push_back ( shape . entity ) ;
}
}
}
2011-01-16 06:08:38 -08:00
void CCmpObstructionManager : : RenderSubmit ( SceneCollector & collector )
2010-03-20 12:18:01 -07:00
{
if ( ! m_DebugOverlayEnabled )
return ;
2015-03-15 16:59:48 -07:00
CColor defaultColor ( 0 , 0 , 1 , 1 ) ;
CColor movingColor ( 1 , 0 , 1 , 1 ) ;
CColor boundsColor ( 1 , 1 , 0 , 1 ) ;
2010-03-20 12:18:01 -07:00
// If the shapes have changed, then regenerate all the overlays
if ( m_DebugOverlayDirty )
{
m_DebugOverlayLines . clear ( ) ;
2010-07-25 07:11:21 -07:00
m_DebugOverlayLines . push_back ( SOverlayLine ( ) ) ;
2015-03-15 16:59:48 -07:00
m_DebugOverlayLines . back ( ) . m_Color = boundsColor ;
2011-01-16 06:08:38 -08:00
SimRender : : ConstructSquareOnGround ( GetSimContext ( ) ,
2010-07-25 07:11:21 -07:00
( m_WorldX0 + m_WorldX1 ) . ToFloat ( ) / 2.f , ( m_WorldZ0 + m_WorldZ1 ) . ToFloat ( ) / 2.f ,
( m_WorldX1 - m_WorldX0 ) . ToFloat ( ) , ( m_WorldZ1 - m_WorldZ0 ) . ToFloat ( ) ,
0 , m_DebugOverlayLines . back ( ) , true ) ;
2010-04-29 16:36:05 -07:00
for ( std : : map < u32 , UnitShape > : : iterator it = m_UnitShapes . begin ( ) ; it ! = m_UnitShapes . end ( ) ; + + it )
2010-03-20 12:18:01 -07:00
{
m_DebugOverlayLines . push_back ( SOverlayLine ( ) ) ;
2015-03-15 16:59:48 -07:00
m_DebugOverlayLines . back ( ) . m_Color = ( ( it - > second . flags & FLAG_MOVING ) ? movingColor : defaultColor ) ;
2019-07-14 03:19:18 -07:00
SimRender : : ConstructSquareOnGround ( GetSimContext ( ) , it - > second . x . ToFloat ( ) , it - > second . z . ToFloat ( ) , it - > second . clearance . ToFloat ( ) , it - > second . clearance . ToFloat ( ) , 0 , m_DebugOverlayLines . back ( ) , true ) ;
2010-03-20 12:18:01 -07:00
}
2010-04-29 16:36:05 -07:00
for ( std : : map < u32 , StaticShape > : : iterator it = m_StaticShapes . begin ( ) ; it ! = m_StaticShapes . end ( ) ; + + it )
2010-03-20 12:18:01 -07:00
{
m_DebugOverlayLines . push_back ( SOverlayLine ( ) ) ;
2015-03-15 16:59:48 -07:00
m_DebugOverlayLines . back ( ) . m_Color = defaultColor ;
2011-08-16 04:18:32 -07:00
float a = atan2f ( it - > second . v . X . ToFloat ( ) , it - > second . v . Y . ToFloat ( ) ) ;
2011-01-16 06:08:38 -08:00
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 ) ;
2010-03-20 12:18:01 -07:00
}
m_DebugOverlayDirty = false ;
}
for ( size_t i = 0 ; i < m_DebugOverlayLines . size ( ) ; + + i )
collector . Submit ( & m_DebugOverlayLines [ i ] ) ;
}