1
0
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:
Ykkrosh 2010-07-31 21:22:39 +00:00
parent 4883ddabc3
commit 423b31c130
7 changed files with 67 additions and 29 deletions

View File

@ -250,7 +250,7 @@ public:
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 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)
{
@ -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;
CFixedVector2D center(x, z);
// First look for obstructions that are covering the exact target point
NullObstructionFilter filter;
GetObstructionsInRange(filter, x, z, x, z, squares);
// Building squares are more important but returned last, so check backwards
for (std::vector<ObstructionSquare>::reverse_iterator it = squares.rbegin(); it != squares.rend(); ++it)

View File

@ -1115,11 +1115,11 @@ static bool CheckVisibility(CFixedVector2D a, CFixedVector2D b, const std::vecto
continue;
// 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
// then the finite lines can't intersect, otherwise they're crossing
// Check the finite edge is crossing the infinitely-extended ray too.
// (Given the previous tests, it can only be crossing in one direction.)
fixed s = (edges[i].p0 - 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;
}
@ -1450,6 +1450,7 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter, enti
break;
}
// Check the lines to every other vertex
for (size_t n = 0; n < vertexes.size(); ++n)
{
if (vertexes[n].status == Vertex::CLOSED)
@ -1467,13 +1468,13 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter, enti
/*
// Render the edges that we examine
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;
xz.push_back(vertexes[curr.id].p.X.ToFloat());
xz.push_back(vertexes[curr.id].p.Y.ToFloat());
xz.push_back(npos.X.ToFloat());
xz.push_back(npos.Y.ToFloat());
SimRender::ConstructLineOnGround(GetSimContext(), xz, m_DebugOverlayShortPathLines.back());
SimRender::ConstructLineOnGround(GetSimContext(), xz, m_DebugOverlayShortPathLines.back(), false);
//*/
if (visible)

View File

@ -71,28 +71,27 @@ cassert(sizeof(EntityData) == 12);
/**
* 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.
*/
struct EntityDistanceOrdering
{
EntityDistanceOrdering(const CSimContext& context, const CFixedVector2D& source) :
context(context), source(source)
EntityDistanceOrdering(const std::map<entity_id_t, EntityData>& entities, const CFixedVector2D& source) :
m_EntityData(entities), m_Source(source)
{
}
bool operator()(entity_id_t a, entity_id_t b)
{
CmpPtr<ICmpPosition> cmpPositionA(context, a);
CmpPtr<ICmpPosition> cmpPositionB(context, b);
// (these positions will be valid and in the world, else ExecuteQuery wouldn't have returned it)
CFixedVector2D vecA = cmpPositionA->GetPosition2D() - source;
CFixedVector2D vecB = cmpPositionB->GetPosition2D() - source;
const EntityData& da = m_EntityData.find(a)->second;
const EntityData& db = m_EntityData.find(b)->second;
CFixedVector2D vecA = CFixedVector2D(da.x, da.z) - m_Source;
CFixedVector2D vecB = CFixedVector2D(db.x, db.z) - m_Source;
return (vecA.CompareLength(vecB) < 0);
}
const CSimContext& context;
CFixedVector2D source;
const std::map<entity_id_t, EntityData>& m_EntityData;
CFixedVector2D m_Source;
private:
EntityDistanceOrdering& operator=(const EntityDistanceOrdering&);
@ -318,7 +317,7 @@ public:
// Return the list sorted by distance from the entity
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;
}
@ -353,7 +352,7 @@ public:
// Return the list sorted by distance from the entity
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;
}
@ -407,7 +406,7 @@ private:
// 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)
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.back().second.added.swap(added);

View File

@ -501,8 +501,15 @@ bool CCmpUnitMotion::MoveToPoint(entity_pos_t x, entity_pos_t z)
if (cmpObstructionManager.null())
return false;
ICmpObstructionManager::tag_t tag;
CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), GetEntityId());
if (!cmpObstruction.null())
tag = cmpObstruction->GetObstruction();
SkipTagObstructionFilter filter(tag);
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
// 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;
}
CmpPtr<ICmpPathfinder> cmpPathfinder (GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
if (cmpPathfinder.null())
return false;

View File

@ -200,7 +200,7 @@ public:
* obstructions that cover the given point are more important than those that only cover
* 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.

View File

@ -17,6 +17,7 @@
#include "simulation2/system/ComponentTest.h"
#include "simulation2/components/ICmpObstructionManager.h"
#include "simulation2/components/ICmpPathfinder.h"
#include "graphics/MapReader.h"
@ -89,4 +90,35 @@ public:
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());
}
};

View File

@ -22,6 +22,7 @@
#include "scriptinterface/ScriptInterface.h"
#include "lib/secure_crt.h"
#include "lib/utf8.h"
#include <sstream>
#include <iomanip>
@ -132,13 +133,12 @@ void CDebugSerializer::PutString(const char* name, const std::string& value)
void CDebugSerializer::PutScriptVal(const char* name, jsval value)
{
std::string source;
// TODO: should be wstring
std::wstring source = m_ScriptInterface.ToString(value);
if (!m_ScriptInterface.CallFunction(value, "toSource", source))
throw PSERROR_Serialize_ScriptError();
LibError err; // silently ignore encoding errors
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)