forked from 0ad/0ad
Fix units trying to move outside themselves when ordered to their current location.
Remove redundant comparisons in pathfinder. Simplify range query result ordering. Avoid throwing exception on script errors in debug serializer. This was SVN commit r7828.
This commit is contained in:
parent
4883ddabc3
commit
423b31c130
@ -250,7 +250,7 @@ public:
|
|||||||
|
|
||||||
virtual bool Rasterise(Grid<u8>& grid);
|
virtual bool Rasterise(Grid<u8>& grid);
|
||||||
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);
|
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);
|
||||||
virtual bool FindMostImportantObstruction(entity_pos_t x, entity_pos_t z, entity_pos_t r, ObstructionSquare& square);
|
virtual bool FindMostImportantObstruction(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, ObstructionSquare& square);
|
||||||
|
|
||||||
virtual void SetDebugOverlay(bool enabled)
|
virtual void SetDebugOverlay(bool enabled)
|
||||||
{
|
{
|
||||||
@ -554,14 +554,13 @@ void CCmpObstructionManager::GetObstructionsInRange(const IObstructionTestFilter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCmpObstructionManager::FindMostImportantObstruction(entity_pos_t x, entity_pos_t z, entity_pos_t r, ObstructionSquare& square)
|
bool CCmpObstructionManager::FindMostImportantObstruction(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, ObstructionSquare& square)
|
||||||
{
|
{
|
||||||
std::vector<ObstructionSquare> squares;
|
std::vector<ObstructionSquare> squares;
|
||||||
|
|
||||||
CFixedVector2D center(x, z);
|
CFixedVector2D center(x, z);
|
||||||
|
|
||||||
// First look for obstructions that are covering the exact target point
|
// First look for obstructions that are covering the exact target point
|
||||||
NullObstructionFilter filter;
|
|
||||||
GetObstructionsInRange(filter, x, z, x, z, squares);
|
GetObstructionsInRange(filter, x, z, x, z, squares);
|
||||||
// Building squares are more important but returned last, so check backwards
|
// Building squares are more important but returned last, so check backwards
|
||||||
for (std::vector<ObstructionSquare>::reverse_iterator it = squares.rbegin(); it != squares.rend(); ++it)
|
for (std::vector<ObstructionSquare>::reverse_iterator it = squares.rbegin(); it != squares.rend(); ++it)
|
||||||
|
@ -1115,11 +1115,11 @@ static bool CheckVisibility(CFixedVector2D a, CFixedVector2D b, const std::vecto
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// The ray is crossing the infinitely-extended edge from in front to behind.
|
// The ray is crossing the infinitely-extended edge from in front to behind.
|
||||||
// If the edge's points are the same side of the infinitely-extended ray
|
// Check the finite edge is crossing the infinitely-extended ray too.
|
||||||
// then the finite lines can't intersect, otherwise they're crossing
|
// (Given the previous tests, it can only be crossing in one direction.)
|
||||||
fixed s = (edges[i].p0 - a).Dot(abn);
|
fixed s = (edges[i].p0 - a).Dot(abn);
|
||||||
fixed t = (edges[i].p1 - a).Dot(abn);
|
fixed t = (edges[i].p1 - a).Dot(abn);
|
||||||
if ((s <= fixed::Zero() && t >= fixed::Zero()) || (s >= fixed::Zero() && t <= fixed::Zero()))
|
if (s <= fixed::Zero() && t >= fixed::Zero())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1450,6 +1450,7 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter, enti
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the lines to every other vertex
|
||||||
for (size_t n = 0; n < vertexes.size(); ++n)
|
for (size_t n = 0; n < vertexes.size(); ++n)
|
||||||
{
|
{
|
||||||
if (vertexes[n].status == Vertex::CLOSED)
|
if (vertexes[n].status == Vertex::CLOSED)
|
||||||
@ -1467,13 +1468,13 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter, enti
|
|||||||
/*
|
/*
|
||||||
// Render the edges that we examine
|
// Render the edges that we examine
|
||||||
m_DebugOverlayShortPathLines.push_back(SOverlayLine());
|
m_DebugOverlayShortPathLines.push_back(SOverlayLine());
|
||||||
m_DebugOverlayShortPathLines.back().m_Color = visible ? CColor(0, 1, 0, 1) : CColor(0, 0, 0, 1);
|
m_DebugOverlayShortPathLines.back().m_Color = visible ? CColor(0, 1, 0, 0.5) : CColor(1, 0, 0, 0.5);
|
||||||
std::vector<float> xz;
|
std::vector<float> xz;
|
||||||
xz.push_back(vertexes[curr.id].p.X.ToFloat());
|
xz.push_back(vertexes[curr.id].p.X.ToFloat());
|
||||||
xz.push_back(vertexes[curr.id].p.Y.ToFloat());
|
xz.push_back(vertexes[curr.id].p.Y.ToFloat());
|
||||||
xz.push_back(npos.X.ToFloat());
|
xz.push_back(npos.X.ToFloat());
|
||||||
xz.push_back(npos.Y.ToFloat());
|
xz.push_back(npos.Y.ToFloat());
|
||||||
SimRender::ConstructLineOnGround(GetSimContext(), xz, m_DebugOverlayShortPathLines.back());
|
SimRender::ConstructLineOnGround(GetSimContext(), xz, m_DebugOverlayShortPathLines.back(), false);
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
if (visible)
|
if (visible)
|
||||||
|
@ -71,28 +71,27 @@ cassert(sizeof(EntityData) == 12);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Functor for sorting entities by distance from a source point.
|
* Functor for sorting entities by distance from a source point.
|
||||||
* It must only be passed entities that has a Position component
|
* It must only be passed entities that are in 'entities'
|
||||||
* and are currently in the world.
|
* and are currently in the world.
|
||||||
*/
|
*/
|
||||||
struct EntityDistanceOrdering
|
struct EntityDistanceOrdering
|
||||||
{
|
{
|
||||||
EntityDistanceOrdering(const CSimContext& context, const CFixedVector2D& source) :
|
EntityDistanceOrdering(const std::map<entity_id_t, EntityData>& entities, const CFixedVector2D& source) :
|
||||||
context(context), source(source)
|
m_EntityData(entities), m_Source(source)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(entity_id_t a, entity_id_t b)
|
bool operator()(entity_id_t a, entity_id_t b)
|
||||||
{
|
{
|
||||||
CmpPtr<ICmpPosition> cmpPositionA(context, a);
|
const EntityData& da = m_EntityData.find(a)->second;
|
||||||
CmpPtr<ICmpPosition> cmpPositionB(context, b);
|
const EntityData& db = m_EntityData.find(b)->second;
|
||||||
// (these positions will be valid and in the world, else ExecuteQuery wouldn't have returned it)
|
CFixedVector2D vecA = CFixedVector2D(da.x, da.z) - m_Source;
|
||||||
CFixedVector2D vecA = cmpPositionA->GetPosition2D() - source;
|
CFixedVector2D vecB = CFixedVector2D(db.x, db.z) - m_Source;
|
||||||
CFixedVector2D vecB = cmpPositionB->GetPosition2D() - source;
|
|
||||||
return (vecA.CompareLength(vecB) < 0);
|
return (vecA.CompareLength(vecB) < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSimContext& context;
|
const std::map<entity_id_t, EntityData>& m_EntityData;
|
||||||
CFixedVector2D source;
|
CFixedVector2D m_Source;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EntityDistanceOrdering& operator=(const EntityDistanceOrdering&);
|
EntityDistanceOrdering& operator=(const EntityDistanceOrdering&);
|
||||||
@ -318,7 +317,7 @@ public:
|
|||||||
|
|
||||||
// Return the list sorted by distance from the entity
|
// Return the list sorted by distance from the entity
|
||||||
CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
|
CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
|
||||||
std::stable_sort(r.begin(), r.end(), EntityDistanceOrdering(GetSimContext(), pos));
|
std::stable_sort(r.begin(), r.end(), EntityDistanceOrdering(m_EntityData, pos));
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -353,7 +352,7 @@ public:
|
|||||||
|
|
||||||
// Return the list sorted by distance from the entity
|
// Return the list sorted by distance from the entity
|
||||||
CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
|
CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
|
||||||
std::stable_sort(r.begin(), r.end(), EntityDistanceOrdering(GetSimContext(), pos));
|
std::stable_sort(r.begin(), r.end(), EntityDistanceOrdering(m_EntityData, pos));
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -407,7 +406,7 @@ private:
|
|||||||
// Return the 'added' list sorted by distance from the entity
|
// Return the 'added' list sorted by distance from the entity
|
||||||
// (Don't bother sorting 'removed' because they might not even have positions or exist any more)
|
// (Don't bother sorting 'removed' because they might not even have positions or exist any more)
|
||||||
CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
|
CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
|
||||||
std::stable_sort(added.begin(), added.end(), EntityDistanceOrdering(GetSimContext(), pos));
|
std::stable_sort(added.begin(), added.end(), EntityDistanceOrdering(m_EntityData, pos));
|
||||||
|
|
||||||
messages.push_back(std::make_pair(q.source, CMessageRangeUpdate(it->first)));
|
messages.push_back(std::make_pair(q.source, CMessageRangeUpdate(it->first)));
|
||||||
messages.back().second.added.swap(added);
|
messages.back().second.added.swap(added);
|
||||||
|
@ -501,8 +501,15 @@ bool CCmpUnitMotion::MoveToPoint(entity_pos_t x, entity_pos_t z)
|
|||||||
if (cmpObstructionManager.null())
|
if (cmpObstructionManager.null())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
ICmpObstructionManager::tag_t tag;
|
||||||
|
CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), GetEntityId());
|
||||||
|
if (!cmpObstruction.null())
|
||||||
|
tag = cmpObstruction->GetObstruction();
|
||||||
|
|
||||||
|
SkipTagObstructionFilter filter(tag);
|
||||||
|
|
||||||
ICmpObstructionManager::ObstructionSquare obstruction;
|
ICmpObstructionManager::ObstructionSquare obstruction;
|
||||||
if (cmpObstructionManager->FindMostImportantObstruction(x, z, m_Radius, obstruction))
|
if (cmpObstructionManager->FindMostImportantObstruction(filter, x, z, m_Radius, obstruction))
|
||||||
{
|
{
|
||||||
// If we're aiming inside a building, then aim for the outline of the building instead
|
// If we're aiming inside a building, then aim for the outline of the building instead
|
||||||
// TODO: if we're aiming at a unit then maybe a circle would look nicer?
|
// TODO: if we're aiming at a unit then maybe a circle would look nicer?
|
||||||
@ -890,7 +897,7 @@ bool CCmpUnitMotion::PickNextWaypoint(const CFixedVector2D& pos, bool avoidMovin
|
|||||||
goal.z = targetZ;
|
goal.z = targetZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
CmpPtr<ICmpPathfinder> cmpPathfinder (GetSimContext(), SYSTEM_ENTITY);
|
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
|
||||||
if (cmpPathfinder.null())
|
if (cmpPathfinder.null())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ public:
|
|||||||
* obstructions that cover the given point are more important than those that only cover
|
* obstructions that cover the given point are more important than those that only cover
|
||||||
* the point expanded by the radius.
|
* the point expanded by the radius.
|
||||||
*/
|
*/
|
||||||
virtual bool FindMostImportantObstruction(entity_pos_t x, entity_pos_t z, entity_pos_t r, ObstructionSquare& square) = 0;
|
virtual bool FindMostImportantObstruction(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, ObstructionSquare& square) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the obstruction square representing the given shape.
|
* Get the obstruction square representing the given shape.
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "simulation2/system/ComponentTest.h"
|
#include "simulation2/system/ComponentTest.h"
|
||||||
|
|
||||||
|
#include "simulation2/components/ICmpObstructionManager.h"
|
||||||
#include "simulation2/components/ICmpPathfinder.h"
|
#include "simulation2/components/ICmpPathfinder.h"
|
||||||
|
|
||||||
#include "graphics/MapReader.h"
|
#include "graphics/MapReader.h"
|
||||||
@ -89,4 +90,35 @@ public:
|
|||||||
cmp->ComputePath(x0, z0, goal, cmp->GetPassabilityClass("default"), cmp->GetCostClass("default"), path);
|
cmp->ComputePath(x0, z0, goal, cmp->GetPassabilityClass("default"), cmp->GetCostClass("default"), path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_performance_short_DISABLED()
|
||||||
|
{
|
||||||
|
CTerrain terrain;
|
||||||
|
terrain.Initialize(5, NULL);
|
||||||
|
|
||||||
|
CSimulation2 sim2(NULL, &terrain);
|
||||||
|
sim2.LoadDefaultScripts();
|
||||||
|
sim2.ResetState();
|
||||||
|
|
||||||
|
const entity_pos_t range = entity_pos_t::FromInt(CELL_SIZE*12);
|
||||||
|
|
||||||
|
CmpPtr<ICmpObstructionManager> cmpObstructionMan(sim2, SYSTEM_ENTITY);
|
||||||
|
CmpPtr<ICmpPathfinder> cmpPathfinder(sim2, SYSTEM_ENTITY);
|
||||||
|
|
||||||
|
srand(0);
|
||||||
|
for (size_t i = 0; i < 200; ++i)
|
||||||
|
{
|
||||||
|
fixed x = fixed::FromFloat(1.5f*range.ToFloat() * rand()/(float)RAND_MAX);
|
||||||
|
fixed z = fixed::FromFloat(1.5f*range.ToFloat() * rand()/(float)RAND_MAX);
|
||||||
|
// printf("# %f %f\n", x.ToFloat(), z.ToFloat());
|
||||||
|
cmpObstructionMan->AddUnitShape(x, z, fixed::FromInt(2), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
NullObstructionFilter filter;
|
||||||
|
ICmpPathfinder::Goal goal = { ICmpPathfinder::Goal::POINT, range, range };
|
||||||
|
ICmpPathfinder::Path path;
|
||||||
|
cmpPathfinder->ComputeShortPath(filter, range/3, range/3, fixed::FromInt(2), range, goal, 0, path);
|
||||||
|
for (size_t i = 0; i < path.m_Waypoints.size(); ++i)
|
||||||
|
printf("# %d: %f %f\n", (int)i, path.m_Waypoints[i].x.ToFloat(), path.m_Waypoints[i].z.ToFloat());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "scriptinterface/ScriptInterface.h"
|
#include "scriptinterface/ScriptInterface.h"
|
||||||
|
|
||||||
#include "lib/secure_crt.h"
|
#include "lib/secure_crt.h"
|
||||||
|
#include "lib/utf8.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@ -132,13 +133,12 @@ void CDebugSerializer::PutString(const char* name, const std::string& value)
|
|||||||
|
|
||||||
void CDebugSerializer::PutScriptVal(const char* name, jsval value)
|
void CDebugSerializer::PutScriptVal(const char* name, jsval value)
|
||||||
{
|
{
|
||||||
std::string source;
|
std::wstring source = m_ScriptInterface.ToString(value);
|
||||||
// TODO: should be wstring
|
|
||||||
|
|
||||||
if (!m_ScriptInterface.CallFunction(value, "toSource", source))
|
LibError err; // silently ignore encoding errors
|
||||||
throw PSERROR_Serialize_ScriptError();
|
std::string sourcea = utf8_from_wstring(source, &err);
|
||||||
|
|
||||||
m_Stream << INDENT << name << ": " << source << "\n";
|
m_Stream << INDENT << name << ": " << sourcea << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDebugSerializer::PutRaw(const char* name, const u8* data, size_t len)
|
void CDebugSerializer::PutRaw(const char* name, const u8* data, size_t len)
|
||||||
|
Loading…
Reference in New Issue
Block a user