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
/* Copyright (C) 2015 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"
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"
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 >
void operator ( ) ( S & serialize , const char * UNUSED ( name ) , UnitShape & value )
{
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 >
void operator ( ) ( S & serialize , const char * UNUSED ( name ) , StaticShape & value )
{
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 ;
m_UpdateInformations . globalRecompute = 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 ) ;
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
}
2015-07-18 01:37:49 -07:00
virtual ObstructionSquare GetUnitShapeObstruction ( entity_pos_t x , entity_pos_t z , entity_pos_t clearance )
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 ;
}
virtual ObstructionSquare GetStaticShapeObstruction ( entity_pos_t x , entity_pos_t z , entity_angle_t a , entity_pos_t w , entity_pos_t h )
{
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
}
2010-04-29 16:36:05 -07:00
virtual ObstructionSquare GetObstruction ( tag_t tag )
{
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 ) )
{
UnitShape & shape = m_UnitShapes [ TAG_TO_INDEX ( tag ) ] ;
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
{
StaticShape & shape = m_StaticShapes [ TAG_TO_INDEX ( tag ) ] ;
ObstructionSquare o = { shape . x , shape . z , shape . u , shape . v , shape . hw , shape . hh } ;
return o ;
}
}
2015-11-06 11:48:08 -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 ) ;
2011-02-10 08:06:28 -08:00
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 ) ;
virtual bool TestUnitShape ( const IObstructionTestFilter & filter , entity_pos_t x , entity_pos_t z , entity_pos_t r , std : : vector < entity_id_t > * out ) ;
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 ) ;
2010-04-29 16:36:05 -07: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 ) ;
2015-11-01 05:38:48 -08:00
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 ) ;
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 ) ;
2015-11-11 04:28:38 -08:00
virtual void GetUnitsOnObstruction ( const ObstructionSquare & square , std : : vector < entity_id_t > & out , const IObstructionTestFilter & filter , bool strict = false ) ;
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
{
2015-06-14 12:22:07 -07:00
// If the pathfinder wants to perform a full update, don't change that.
if ( m_UpdateInformations . dirty & & ! informations . globalRecompute )
informations = m_UpdateInformations ;
2010-03-17 16:01:12 -07:00
2015-06-14 12:22:07 -07:00
m_UpdateInformations . Clean ( ) ;
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 . globalRecompute = 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
*/
2015-11-11 12:50:02 -08:00
inline bool IsInWorld ( entity_pos_t x , entity_pos_t z , entity_pos_t r )
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
*/
2015-11-11 12:50:02 -08:00
inline bool IsInWorld ( const CFixedVector2D & p )
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
2015-10-03 03:32:30 -07:00
void RasterizeHelper ( Grid < NavcellData > & grid , ICmpObstructionManager : : flags_t requireMask , bool fullUpdate , pass_class_t appliedMask , entity_pos_t clearance = fixed : : Zero ( ) ) ;
2010-03-17 16:01:12 -07:00
} ;
REGISTER_COMPONENT_TYPE ( ObstructionManager )
2015-11-06 11:48:08 -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 )
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 ) ;
2014-08-06 02:21:00 -07:00
for ( size_t i = 0 ; i < unitShapes . size ( ) ; + + i )
2010-03-17 16:01:12 -07:00
{
2010-09-19 11:08:56 -07:00
std : : map < u32 , UnitShape > : : iterator it = m_UnitShapes . find ( unitShapes [ i ] ) ;
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 ) ;
for ( size_t i = 0 ; i < staticShapes . size ( ) ; + + i )
{
std : : map < u32 , StaticShape > : : iterator it = m_StaticShapes . find ( staticShapes [ i ] ) ;
ENSURE ( it ! = m_StaticShapes . end ( ) ) ;
if ( ! filter . TestShape ( STATIC_INDEX_TO_TAG ( it - > first ) , it - > second . flags , it - > second . group , it - > second . group2 ) )
continue ;
CFixedVector2D center ( it - > second . x , it - > second . z ) ;
CFixedVector2D halfSize ( it - > second . hw + r , it - > second . hh + r ) ;
if ( Geometry : : TestRaySquare ( CFixedVector2D ( x0 , z0 ) - center , CFixedVector2D ( x1 , z1 ) - center , it - > second . u , it - > second . v , halfSize ) )
return true ;
}
return false ;
}
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 ,
std : : vector < entity_id_t > * out )
2010-03-17 16:01:12 -07:00
{
2010-04-29 16:36:05 -07:00
PROFILE ( " TestStaticShape " ) ;
2010-09-19 11:08:56 -07:00
// TODO: should use the subdivision stuff here, if performance is non-negligible
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 ) ;
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)
if ( ! IsInWorld ( center + u . Multiply ( halfSize . X ) + v . Multiply ( halfSize . Y ) ) | |
! IsInWorld ( center + u . Multiply ( halfSize . X ) - v . Multiply ( halfSize . Y ) ) | |
! IsInWorld ( center - u . Multiply ( halfSize . X ) + v . Multiply ( halfSize . Y ) ) | |
! IsInWorld ( center - u . Multiply ( halfSize . X ) - v . Multiply ( halfSize . Y ) ) )
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
for ( std : : map < u32 , UnitShape > : : iterator it = m_UnitShapes . begin ( ) ; it ! = m_UnitShapes . end ( ) ; + + it )
2010-03-17 16:01:12 -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 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
}
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-17 16:01:12 -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-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 ,
2011-02-10 08:06:28 -08:00
std : : vector < entity_id_t > * out )
2010-03-17 16:01:12 -07:00
{
2010-04-29 16:36:05 -07:00
PROFILE ( " TestUnitShape " ) ;
2010-09-19 11:08:56 -07:00
// TODO: should use the subdivision stuff here, if performance is non-negligible
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 ) ;
for ( std : : map < u32 , UnitShape > : : iterator it = m_UnitShapes . begin ( ) ; it ! = m_UnitShapes . end ( ) ; + + it )
{
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
}
for ( std : : map < u32 , StaticShape > : : iterator it = m_StaticShapes . begin ( ) ; it ! = m_StaticShapes . end ( ) ; + + it )
{
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 :
{
auto it = pathfindingMasks . find ( passability . m_Clearance ) ;
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 ( ) ;
}
2015-10-03 03:32:30 -07:00
void CCmpObstructionManager : : RasterizeHelper ( Grid < NavcellData > & grid , ICmpObstructionManager : : flags_t requireMask , bool fullUpdate , pass_class_t appliedMask , entity_pos_t clearance )
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
2010-04-29 16:36:05 -07: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 )
2015-11-01 05:38:48 -08:00
{
GetUnitObstructionsInRange ( filter , x0 , z0 , x1 , z1 , squares ) ;
GetStaticObstructionsInRange ( filter , x0 , z0 , x1 , z1 , squares ) ;
}
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 )
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
{
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
auto 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
2015-11-01 05:38:48 -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 )
{
PROFILE ( " GetObstructionsInRange " ) ;
ENSURE ( x0 < = x1 & & z0 < = z1 ) ;
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
{
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
auto 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
}
}
2015-11-11 04:28:38 -08:00
void CCmpObstructionManager : : GetUnitsOnObstruction ( const ObstructionSquare & square , std : : vector < entity_id_t > & out , const IObstructionTestFilter & filter , bool strict )
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
// units s.t. the RasterizeRectWithClearance of the building's shape with the
// 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
{
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
auto it = m_UnitShapes . find ( unitShape ) ;
ENSURE ( it ! = m_UnitShapes . end ( ) ) ;
UnitShape & shape = it - > second ;
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
}
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 ) ;
2015-07-18 01:37:49 -07:00
SimRender : : ConstructSquareOnGround ( GetSimContext ( ) , it - > second . x . ToFloat ( ) , it - > second . z . ToFloat ( ) , it - > second . clearance . ToFloat ( ) * 2 , it - > second . clearance . ToFloat ( ) * 2 , 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 ] ) ;
}