Simplify rayCast parameters, remove only call to fpathTileLOS, ignore blocking tiles on destination when raycasting.

The fpathTileLOS call seemed useless, since if the path is blocked, there's not much chance
that the destination can be reached by going in a straight line, anyway.

If sending two trucks to build a cyborg factory, the second truck no longer goes in circles
just before the destination when the first truck arrives first. However, this is because it
now no longer ignores the last waypoint, but the main issue is that the second-last waypoint
seems to be missing.
master
Cyp 2011-12-24 20:55:28 +01:00
parent b9200fddfb
commit 1cc62d6d9d
5 changed files with 16 additions and 57 deletions

View File

@ -546,37 +546,6 @@ static void fpathExecute(PATHJOB *psJob, PATHRESULT *psResult)
}
}
// Variables for the callback
static bool obstruction;
/** The visibility ray callback
*/
static bool fpathVisCallback(Vector3i pos, int32_t dist, void *data)
{
DROID *psDroid = (DROID *)data;
if (fpathBlockingTile(map_coord(pos.x), map_coord(pos.y), getPropulsionStats(psDroid)->propulsionType))
{
// found an obstruction
obstruction = true;
return false;
}
return true;
}
bool fpathTileLOS(DROID *psDroid, Vector3i dest)
{
Vector2i dir = removeZ(dest - psDroid->pos);
// Initialise the callback variables
obstruction = false;
rayCast(psDroid->pos, iAtan2(dir), iHypot(dir), fpathVisCallback, psDroid);
return !obstruction;
}
/** Find the length of the job queue. Function is thread-safe. */
static int fpathJobQueueLength(void)
{

View File

@ -110,10 +110,6 @@ extern void fpathSetDirectRoute(DROID* psDroid, SDWORD targetX, SDWORD targetY);
/** Clean up path jobs and results for a droid. Function is thread-safe. */
extern void fpathRemoveDroidData(int id);
/** Check LOS (Line Of Sight) between two world positions.
*/
extern bool fpathTileLOS(DROID *psDroid, Vector3i dest);
/** Quick O(1) test of whether it is theoretically possible to go from origin to destination
* using the given propulsion type. orig and dest are in world coordinates. */
bool fpathCheck(Position orig, Position dest, PROPULSION_TYPE propulsion);

View File

@ -536,12 +536,13 @@ struct BLOCKING_CALLBACK_DATA
{
PROPULSION_TYPE propulsionType;
bool blocking;
Vector2i dst;
};
static bool moveBlockingTileCallback(Vector3i pos, int32_t dist, void *data_)
static bool moveBlockingTileCallback(Vector2i pos, int32_t dist, void *data_)
{
BLOCKING_CALLBACK_DATA *data = (BLOCKING_CALLBACK_DATA *)data_;
data->blocking |= fpathBlockingTile(map_coord(pos.x), map_coord(pos.y), data->propulsionType);
data->blocking |= pos != data->dst && fpathBlockingTile(map_coord(pos.x), map_coord(pos.y), data->propulsionType);
return !data->blocking;
}
@ -551,12 +552,12 @@ static int32_t moveDirectPathToWaypoint(DROID *psDroid, unsigned positionIndex)
Vector2i src = removeZ(psDroid->pos);
Vector2i dst = psDroid->sMove.asPath[positionIndex];
Vector2i delta = dst - src;
uint16_t dir = iAtan2(delta);
int32_t dist = iHypot(delta);
BLOCKING_CALLBACK_DATA data;
data.propulsionType = getPropulsionStats(psDroid)->propulsionType;
data.blocking = false;
rayCast(Vector3i(src, 0), dir, dist, &moveBlockingTileCallback, &data);
data.dst = dst;
rayCast(src, dst, &moveBlockingTileCallback, &data);
return data.blocking? -1 - dist : dist;
}
@ -788,8 +789,7 @@ static bool moveBlocked(DROID *psDroid)
objTrace(psDroid->id, "BLOCKED");
// if the unit cannot see the next way point - reroute it's got stuck
if ((bMultiPlayer || psDroid->player == selectedPlayer) &&
psDroid->sMove.pathIndex != psDroid->sMove.numPoints &&
!fpathTileLOS(psDroid, Vector3i(psDroid->sMove.destination, 0)))
psDroid->sMove.pathIndex != psDroid->sMove.numPoints)
{
objTrace(psDroid->id, "Trying to reroute to (%d,%d)", psDroid->sMove.destination.x, psDroid->sMove.destination.y);
moveDroidTo(psDroid, psDroid->sMove.destination.x, psDroid->sMove.destination.y);

View File

@ -63,10 +63,8 @@ static bool tryStep(int32_t &tile, int32_t step, int32_t &cur, int32_t end, int3
return true;
}
void rayCast(Vector3i src, uint16_t direction, uint32_t length, RAY_CALLBACK callback, void *data)
void rayCast(Vector2i src, Vector2i dst, RAY_CALLBACK callback, void *data)
{
Vector3i dst = src + Vector3i(iSinCosR(direction, length), 0);
if (!callback(src, 0, data) || src == dst) // Start at src.
{
return; // Callback gave up after the first point, or there are no other points.
@ -110,7 +108,7 @@ void rayCast(Vector3i src, uint16_t direction, uint32_t length, RAY_CALLBACK cal
// But make sure it's on the right tile, since it could be off-by-one if the line passes exactly through a grid intersection.
avg.x = std::min(std::max(avg.x, world_coord(selTile.x)), world_coord(selTile.x + 1) - 1);
avg.y = std::min(std::max(avg.y, world_coord(selTile.y)), world_coord(selTile.y + 1) - 1);
if (!worldOnMap(avg) || !callback(Vector3i(avg, src.z), iHypot(avg), data))
if (!worldOnMap(avg) || !callback(avg, iHypot(avg), data))
{
return; // Callback doesn't want any more points, or we reached the edge of the map, so return.
}
@ -129,7 +127,7 @@ void rayCast(Vector3i src, uint16_t direction, uint32_t length, RAY_CALLBACK cal
//-----------------------------------------------------------------------------------
/* Will return false when we've hit the edge of the grid */
static bool getTileHeightCallback(Vector3i pos, int32_t dist, void *data)
static bool getTileHeightCallback(Vector2i pos, int32_t dist, void *data)
{
HeightCallbackHelp_t *help = (HeightCallbackHelp_t *)data;
#ifdef TEST_RAY
@ -194,7 +192,9 @@ void getBestPitchToEdgeOfGrid(UDWORD x, UDWORD y, uint16_t direction, uint16_t *
{
HeightCallbackHelp_t help = {map_Height(x,y), 0};
rayCast(Vector3i(x, y, 0), direction, 5430, getTileHeightCallback, &help); // FIXME Magic value
Vector3i src(x, y, 0);
Vector3i delta(iSinCosR(direction, 5430), 0);
rayCast(src, src + delta, getTileHeightCallback, &help); // FIXME Magic value
*pitch = help.pitch;
}

View File

@ -26,11 +26,6 @@
#include "lib/framework/vector.h"
#define NUM_RAYS 360
// maximum length for a visiblity ray
#define RAY_MAXLEN INT_MAX
/*!
* The raycast intersection callback.
@ -39,18 +34,17 @@
* \param data Payload (store intermediate results here)
* \return true if ore points are required, false otherwise
*/
typedef bool (*RAY_CALLBACK)(Vector3i pos, int32_t dist, void* data);
typedef bool (*RAY_CALLBACK)(Vector2i pos, int32_t dist, void* data);
/*!
* Cast a ray from a position into a certain direction
* \param pos Position to cast from
* \param dir Direction to cast into
* \param length Maximum length
* \param src Position to cast from
* \param dst Position to cast to (casts to end of map, if dst is off the map)
* \param callback Callback to call for each passed tile
* \param data Data to pass through to the callback
*/
extern void rayCast(Vector3i pos, uint16_t dir, uint32_t length, RAY_CALLBACK callback, void *data);
void rayCast(Vector2i src, Vector2i dst, RAY_CALLBACK callback, void *data);
// Calculates the maximum height and distance found along a line from any