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 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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user