46#define RT_NO_OPENING -1
49#define halfMicrostepSize (PATHFINDING_MICROSTEP_SIZE / 2 - DIST_EPSILON)
54#define half1x1Width (UNIT_SIZE * 1 / 2 - WALL_SIZE - DIST_EPSILON)
55#define half2x2Width (UNIT_SIZE * 2 / 2 - WALL_SIZE - DIST_EPSILON)
65#if defined(COMPILE_MAP)
66 #define RT_COMPLETEBOXTRACE_SIZE(mapTiles, b, list, lvl) TR_SingleTileBoxTrace((mapTiles), Line(), (b), (lvl), MASK_NO_LIGHTCLIP, 0)
67 #define RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, line, b, list) TR_SingleTileBoxTrace((mapTiles), (line), (b), TRACE_ALL_LEVELS, MASK_IMPASSABLE, MASK_PASSABLE)
69#elif defined(COMPILE_UFO)
70 #define RT_COMPLETEBOXTRACE_SIZE(mapTiles, b, list, lvl) CM_EntCompleteBoxTrace((mapTiles), Line(), (b), (lvl), MASK_NO_LIGHTCLIP, 0, (list))
71 #define RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, line, b, list) CM_EntCompleteBoxTrace((mapTiles), (line), (b), TRACE_ALL_LEVELS, MASK_IMPASSABLE, MASK_PASSABLE, (list))
74 #error Either COMPILE_MAP or COMPILE_UFO must be defined in order for tracing.c to work.
113typedef struct place_s {
164typedef struct opening_s {
189static void RT_DumpMap (
const Routing& routing,
actorSizeEnum_t actorSize,
int lx,
int ly,
int lz,
int hx,
int hy,
int hz)
191 Com_Printf(
"\nRT_DumpMap (%i %i %i) (%i %i %i)\n", lx, ly, lz, hx, hy, hz);
192 for (
int z = hz; z >= lz; --z) {
194 for (
int x = lx; x <= hx; ++x) {
198 for (
int y = hy; y >= ly; --y) {
200 for (
int x = lx; x <= hx; ++x) {
202 ,
RT_CONN_NX(routing, actorSize, x, y, z) ?
"w" :
" "
203 ,
RT_CONN_PY(routing, actorSize, x, y, z) ?
"n" :
" "
204 ,
RT_CONN_NY(routing, actorSize, x, y, z) ?
"s" :
" "
205 ,
RT_CONN_PX(routing, actorSize, x, y, z) ?
"e" :
" "
230 RT_DumpMap(routing,
ACTOR_SIZE_NORMAL, start[0], start[1], start[2], end[0], end[1], end[2]);
262 for (
int i = 0;
i < 3;
i++) {
265 while (end[
i] > start[
i]) {
283 while (end[
i] > start[
i]) {
337 for (
int i = 0;
i < pos[2];
i++) {
338 if (routing.
getCeiling(actorSize, pos[0], pos[1],
i) != 0)
371 const AABB ceilBox(-halfActorWidth, -halfActorWidth, 0,
372 halfActorWidth, halfActorWidth, 0);
417 routing.
setFilled(actorSize, x, y, 0, z);
422 if (
tr.fraction >= 1.0) {
423 routing.
setFilled(actorSize, x, y, 0, z);
428 bottom =
tr.endpos[2];
431 assert(initial > bottom);
442 if (
tr.fraction < 1.0) {
458 if (
tr.fraction < 1.0) {
474 tstart[2] = box.
maxs[2];
478 tr = RT_COMPLETEBOXTRACE_PASSAGE(
mapTiles,
Line(tstart, tend), &ceilBox, list);
491 top = std::min(
tr.endpos[2], topf);
501 UFO_assert(bottom <= top,
"\nassert(bottom <= top): x=%i y=%i bottom=%f top=%f\n", x, y, bottom, top);
512 const int cz = std::min(z, (
int)(floorf((topQ - 1) /
CELL_HEIGHT)));
517 for (
int i = fz;
i <= cz;
i++) {
525 routing.
setFilled(actorSize, x, y, cz + 1, z);
541static int RT_FillPassageData (
RoutingData* rtd,
const int dir,
const int x,
const int y,
const int z,
const int openingSize,
const int openingBase,
const int stepup)
543 const int openingTop = openingBase + openingSize;
560 int cz = ceil((
float)openingTop /
CELL_HEIGHT) - 1;
572 assert(fz <= z && z <= cz);
575 for (
int i = fz;
i <= cz;
i++) {
577 const int oh = openingTop - std::max(openingBase,
i *
CELL_HEIGHT);
613 return RT_COMPLETEBOXTRACE_PASSAGE(rtd->
mapTiles, traceLine, &box, rtd->
list);
688 if (start[0] == end[0] || start[1] == end[1]) {
698 midfloor = std::max(midfloor, midfloor2);
702 return std::max(floorLimit, midfloor);
719 if (start[0] == end[0] || start[1] == end[1]) {
729 midceil = std::min(midceil, midceil2);
733 return std::min(ceilLimit, midceil);
774static int RT_TraceOpening (
const RoutingData* rtd,
const vec3_t start,
const vec3_t end,
const int ax,
const int ay,
const int bottom,
const int top,
int lo,
int hi,
int* foundLow,
int* foundHigh)
777 if (
tr.fraction >= 1.0) {
783 *foundLow = *foundHigh = 0;
790 const int tempZ =
RT_CalcNewZ(rtd, ax, ay, top, hi);
795 *foundLow = *foundHigh = hi;
816 *foundLow = *foundHigh = 0;
831 start[2] = end[2] = 0;
852 *foundLow = tempBottom;
869 tempZ =
RT_TraceOpening(rtd, start, end, ax, ay, bottom, top, lo, hi, foundLow, foundHigh);
877 tempZ =
RT_TraceOpening(rtd, start, end, ax, ay, bottom, top, lo, lo + 1, foundLow, foundHigh);
904 const int top = opening->
base + opening->
size;
912 bases[0] = from->
floor;
914 bases[steps] = std::max(0, floorVal) + az *
CELL_HEIGHT;
928 const float sx = start[0];
929 const float sy = start[1];
930 const float ex = end[0];
931 const float ey = end[1];
933 int newBottom = std::max(bases[0], bases[steps]);
935 for (
int i = 1;
i < steps;
i++) {
936 start[0] = end[0] = sx + (ex - sx) * (
i / (
float)steps);
937 start[1] = end[1] = sy + (ey - sy) * (
i / (
float)steps);
941 if (
tr.fraction >= 1.0f) {
953 Com_Printf(
"Adjusting middle trace- the known base is too high. \n");
959 Com_Printf(
"Microstep %i from (%f, %f, %f) to (%f, %f, %f) = %i [%f]\n",
960 i, start[0], start[1], start[2], end[0], end[1], end[2], bases[
i],
tr.endpos[2]);\
962 newBottom = std::max(newBottom, (
int)bases[
i]);
966 Com_Printf(
"z:%i az:%i bottom:%i new_bottom:%i top:%i bases[0]:%i bases[%i]:%i\n", from->
cell[2], az, opening->
base, newBottom, top, bases[0], steps, bases[steps]);
972 int current_h = bases[0];
977 for (
int i = 1;
i <= steps;
i++) {
979 Com_Printf(
"Tracing forward i:%i h:%i\n",
i, current_h);
985 Com_Printf(
" Skipped too many steps, reverting to i:%i\n",
i);
987 opening->
stepup = std::max(opening->
stepup, bases[
i] - current_h);
988 current_h = bases[
i];
997 if (bases[
i] > highest_h) {
998 highest_h = bases[
i];
1002 Com_Printf(
" Skipped because we are falling, skip:%i.\n", skipped);
1008 Com_Printf(
" Tripping skip counter to perform last tests.\n");
1016 current_h = bases[steps];
1018 highest_i = steps - 1;
1021 for (
int i = steps - 1;
i >= 0;
i--) {
1023 Com_Printf(
"Tracing backward i:%i h:%i\n",
i, current_h);
1029 Com_Printf(
" Skipped too many steps, reverting to i:%i\n",
i);
1032 current_h = bases[
i];
1041 if (bases[
i] > highest_h) {
1042 highest_h = bases[
i];
1046 Com_Printf(
" Skipped because we are falling, skip:%i.\n", skipped);
1052 Com_Printf(
" Tripping skip counter to perform last tests.\n");
1057 if (stairwaySituation) {
1058 const int middle = bases[4];
1060 if (stairwaySituation == 1) {
1061 if (bases[1] <= middle &&
1062 bases[2] <= middle &&
1063 bases[3] <= middle ) {
1065 Com_Printf(
"Addition granted by ugly stair hack-stepping up.\n");
1066 return opening->
base - middle;
1068 }
else if (stairwaySituation == 2) {
1069 if (bases[5] <= middle &&
1070 bases[6] <= middle &&
1071 bases[7] <= middle ) {
1073 Com_Printf(
"Addition granted by ugly stair hack-stepping down.\n");
1074 return opening->
base - middle;
1080 return opening->
base - newBottom;
1095 const int z = from->
cell[2];
1096 const int lower = std::max(from->
floor, to->
floor);
1098 const int ax = to->
cell[0];
1099 const int ay = to->
cell[1];
1103 opening->
size = hi - opening->
base;
1104 const int az = to->
floorZ;
1111 const int srcFloor = from->
floor;
1120 const int bonusSize =
RT_MicroTrace(rtd, from, ax, ay, az, stairway, opening);
1121 opening->
base -= bonusSize;
1122 opening->
size = hi - opening->
base;
1125 opening->
stepup = std::max(0, opening->
base - srcFloor);
1153 return opening->
size;
1173 const place_t* placeToCheck =
nullptr;
1204 placeToCheck = &above;
1207 if (!placeToCheck) {
1211 opening->
base = lowCeil;
1226 opening->
base = lowCeil;
1247 if ((adjCeiling == 0 && upperAdjCeiling == 0) || ceiling == 0) {
1263 if (absCeiling < absAdjFloor || absExtAdjCeiling < absFloor) {
1299 const int ax = x +
dvecs[dir][0];
1300 const int ay = y +
dvecs[dir][1];
1309 if (x == 126 && y == 129 && dir == 2) {
1322 for (z = minZ; z < maxZ; z++) {
1337 sprintf(ext,
".%i.elevation.csv",
i);
1352 FS_Printf(&
f,
"h:%i c:%i,", routing.
getFloor(
i, x, y, z), routing.
getCeiling(
i, x, y, z));
1363 sprintf(ext,
".%i.walls.csv",
i);
1381 FS_Printf(&
f,
"%3i-%3i ",
RT_CONN_NX_PY(routing,
i, x, y, z),
RT_STEPUP_NX_PY(routing,
i, x, y, z));
1384 FS_Printf(&
f,
"%3i-%3i ",
RT_CONN_PY(routing,
i, x, y, z),
RT_STEPUP_PY(routing,
i, x, y, z));
1387 FS_Printf(&
f,
"%3i-%3i ",
RT_CONN_PX_PY(routing,
i, x, y, z),
RT_STEPUP_PX_PY(routing,
i, x, y, z));
1392 FS_Printf(&
f,
"%3i-%3i ",
RT_CONN_NX(routing,
i, x, y, z),
RT_STEPUP_NX(routing,
i, x, y, z));
1398 FS_Printf(&
f,
"%3i-%3i ",
RT_CONN_PX(routing,
i, x, y, z),
RT_STEPUP_PX(routing,
i, x, y, z));
1403 FS_Printf(&
f,
"%3i-%3i ",
RT_CONN_NX_NY(routing,
i, x, y, z),
RT_STEPUP_NX_NY(routing,
i, x, y, z));
1406 FS_Printf(&
f,
"%3i-%3i ",
RT_CONN_NY(routing,
i, x, y, z),
RT_STEPUP_NY(routing,
i, x, y, z));
1409 FS_Printf(&
f,
"%3i-%3i ",
RT_CONN_PX_NY(routing,
i, x, y, z),
RT_STEPUP_PX_NY(routing,
i, x, y, z));
1430int RT_DebugSpecial (
mapTiles_t*
mapTiles,
Routing& routing,
const int actorSize,
const int x,
const int y,
const int dir,
const char** list)
1435 const int ax = x +
dvecs[dir][0];
1436 const int ay = y +
dvecs[dir][1];
1450 Com_Printf(
"data at cursor XYZ(%i, %i, %i) Floor(%i) Ceiling(%i)\n", x, y, z,
1451 routing.
getFloor(actorSize, x, y, z),
1453 Com_Printf(
"connections ortho: (PX=%i, NX=%i, PY=%i, NY=%i))\n",
1458 Com_Printf(
"connections diago: (PX_PY=%i, NX_NY=%i, NX_PY=%i, PX_NY=%i))\n",
1463 Com_Printf(
"stepup ortho: (PX=%i, NX=%i, PY=%i, NY=%i))\n",
void set(const AABB &other)
Copies the values from the given aabb.
void shift(const vec3_t shiftVec)
shove the whole box by the given vector
RT_data_s contains the essential data that is passed to most of the RT_* functions.
actorSizeEnum_t actorSize
RoutingData(mapTiles_t *mapTiles, Routing &r, actorSizeEnum_t actorSize, const char **list)
void setStepup(const int actorSize, const int x, const int y, const int z, const int dir, const int val)
void setFilled(const actorSizeEnum_t actorSize, const int x, const int y, const int lowZ, const int highZ)
signed char getFloor(const actorSizeEnum_t actorSize, const pos3_t pos) const
void setCeiling(const actorSizeEnum_t actorSize, const int x, const int y, const int z, const int val)
byte getCeiling(const int actorSize, const pos3_t pos) const
void setConn(const int actorSize, const int x, const int y, const int z, const int dir, const int val)
void setFloor(const int actorSize, const int x, const int y, const int z, const int val)
static const AABB actor1x1Box(-half1x1Width, -half1x1Width, 0, half1x1Width, half1x1Width, 0)
void RT_GetMapSize(mapTiles_t *mapTiles, AABB &mapBox)
Calculate the map size via model data and store grid size in map_min and map_max. This is done with e...
static int RT_TraceOpening(const RoutingData *rtd, const vec3_t start, const vec3_t end, const int ax, const int ay, const int bottom, const int top, int lo, int hi, int *foundLow, int *foundHigh)
Performs actual trace to find a passage between two points given an upper and lower bound.
static int RT_PlaceIsShifted(const place_t *p, const place_t *other)
This function detects a special stairway situation, where one place is right in front of a stairway a...
bool RT_CanActorStandHere(const Routing &routing, const int actorSize, const pos3_t pos)
Check if an actor can stand(up) in the cell given by pos.
static void RT_PlaceInit(const Routing &routing, const actorSizeEnum_t actorSize, place_t *p, const int x, const int y, const int z)
static int RT_FillPassageData(RoutingData *rtd, const int dir, const int x, const int y, const int z, const int openingSize, const int openingBase, const int stepup)
Performs traces to find a passage between two points given an upper and lower bound.
int RT_CheckCell(mapTiles_t *mapTiles, Routing &routing, const int actorSize, const int x, const int y, const int z, const char **list)
This function looks to see if an actor of a given size can occupy a cell(s) and if so identifies the ...
static int RT_UpdateConnection(RoutingData *rtd, const int x, const int y, const int ax, const int ay, const int z, const int dir)
Routing Function to update the connection between two fields.
static int RT_CalcNewZ(const RoutingData *rtd, const int ax, const int ay, const int top, const int hi)
static void RT_ConnSetNoGo(RoutingData *rtd, const int x, const int y, const int z, const int dir)
static int RT_FindOpeningCeilingFrac(const RoutingData *rtd, const vec3_t start, const vec3_t end, const float frac, const int startingHeight)
Performs a trace to find the ceiling of a passage a fraction of the way from start to end.
static int RT_MicroTrace(RoutingData *rtd, const place_t *from, const int ax, const int ay, const int az, const int stairwaySituation, opening_t *opening)
Performs small traces to find places when an actor can step up.
static int RT_FindOpeningFloorFrac(const RoutingData *rtd, const vec3_t start, const vec3_t end, const float frac, const int startingHeight)
Performs a trace to find the floor of a passage a fraction of the way from start to end.
#define halfMicrostepSize
static void RT_TracePassage(RoutingData *rtd, const int x, const int y, const int z, const int ax, const int ay, opening_t *opening)
Performs traces to find a passage between two points.
void RT_WriteCSVFiles(const Routing &routing, const char *baseFilename, const GridBox &box)
static trace_t RT_ObstructedTrace(const RoutingData *rtd, const Line &traceLine, int hi, int lo)
Helper function to trace for walls.
static int RT_FindOpeningCeiling(const RoutingData *rtd, const vec3_t start, const vec3_t end, const int startingHeight, const int ceilLimit)
Performs traces to find the approximate ceiling of a passage.
static const AABB actor2x2Box(-half2x2Width, -half2x2Width, 0, half2x2Width, half2x2Width, 0)
static int RT_TraceOnePassage(RoutingData *rtd, const place_t *from, const place_t *to, opening_t *opening)
Performs traces to find a passage between two points given an upper and lower bound.
static void RT_StepupSet(RoutingData *rtd, const int x, const int y, const int z, const int dir, const int val)
bool RT_AllCellsBelowAreFilled(const Routing &routing, const int actorSize, const pos3_t pos)
Check if pos is on solid ground.
static const AABB footBox(-halfMicrostepSize, -halfMicrostepSize, 0, halfMicrostepSize, halfMicrostepSize, 0)
static int RT_FindOpeningFloor(const RoutingData *rtd, const vec3_t start, const vec3_t end, const int startingHeight, const int floorLimit)
Performs traces to find the approximate floor of a passage.
static bool RT_PlaceDoesIntersectEnough(const place_t *p, const place_t *other)
void RT_UpdateConnectionColumn(mapTiles_t *mapTiles, Routing &routing, const int actorSize, const int x, const int y, const int dir, const char **list, const int minZ, const int maxZ)
Routing Function to update the connection between two fields.
static int RT_FindOpening(RoutingData *rtd, const place_t *from, const int ax, const int ay, const int bottom, const int top, int *foundLow, int *foundHigh)
Performs traces to find a passage between two points given an upper and lower bound.
void Com_Printf(const char *const fmt,...)
definitions common between client and server, but not game lib
#define PATHFINDING_MIN_OPENING
#define PATHFINDING_MICROSTEP_SKIP
The number of microsteps that can be stepped over by an actor. Used to allow an actor to stepup when ...
#define PATHFINDING_LEGROOMHEIGHT
#define PATHFINDING_WIDTH
absolute max
#define CELL_HEIGHT
A cell's height in QUANT sized units.
#define ACTOR_MAX_HEIGHT
The tallest actor's height in QUANT sized units.
#define PATHFINDING_MIN_STEPUP
#define PATHFINDING_MAX_STEPUP
#define ACTOR_SIZE_NORMAL
#define PATHFINDING_HEIGHT
15 max, adjusting above 8 will require a rewrite to the DV code
#define PATHFINDING_MICROSTEP_SIZE
The size (in model units) of a microstep. Must be a power of 2 and less than UNIT_SIZE.
#define ACTOR_SIZE_INVALID
#define PATHFINDING_NO_STEPUP
int FS_Printf(qFILE *f, const char *msg,...)
Can print chunks for 1024 chars into a file.
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
void Sys_Error(const char *error,...)
const vec4_t dvecs[PATHFINDING_DIRECTIONS]
#define PosToVec(p, v)
Pos boundary size is +/- 128 - to get into the positive area we add the possible max negative value a...
#define VecToPos(v, p)
Map boundary is +/- MAX_WORLD_WIDTH - to get into the positive area we add the possible max negative ...
#define PLAYER_STANDING_HEIGHT
grid pathfinding and routing
#define RT_STEPUP_NX(r, actorSize, x, y, z)
#define ModelFloorToQuant(x)
These macros are meant to correctly convert from model units to QUANT units and back.
#define RT_CONN_NX_NY(r, actorSize, x, y, z)
#define RT_STEPUP_NX_NY(r, actorSize, x, y, z)
#define RT_CONN_PY(r, actorSize, x, y, z)
#define RT_STEPUP_PX(r, actorSize, x, y, z)
#define RT_STEPUP_PX_PY(r, actorSize, x, y, z)
#define ModelCeilingToQuant(x)
#define RT_CONN_NX_PY(r, actorSize, x, y, z)
#define RT_STEPUP_PX_NY(r, actorSize, x, y, z)
#define RT_CONN_NY(r, actorSize, x, y, z)
#define RT_CONN_PX(r, actorSize, x, y, z)
Some macros to access routing table values as described above.
#define RT_CONN_PX_NY(r, actorSize, x, y, z)
#define RT_STEPUP_NX_PY(r, actorSize, x, y, z)
#define RT_CONN_PX_PY(r, actorSize, x, y, z)
#define SizedPosToVec(p, actorSize, v)
SizedPosToVect locates the center of an actor based on size and position.
#define RT_STEPUP_PY(r, actorSize, x, y, z)
#define RT_STEPUP_NY(r, actorSize, x, y, z)
#define RT_CONN_NX(r, actorSize, x, y, z)
void Com_DefaultExtension(char *path, size_t len, const char *extension)
Sets a default extension if there is none.
void UFO_assert(bool condition, const char *fmt,...)
An 'opening' describes the connection between two adjacent spaces where an actor can exist in a cell.
A 'place' is a part of a grid column where an actor can exist Unlike for a grid-cell,...
bool isUsable(void) const
static mapTiles_t mapTiles
#define TRACE_VISIBLE_LEVELS
#define PATHFINDING_BIG_STEPUP
The home of the routing tables.
#define PATHFINDING_BIG_STEPDOWN
#define VectorInterpolation(p1, p2, frac, mid)
#define VectorSubtract(a, b, dest)
#define VectorCopy(src, dest)
#define VectorAdd(a, b, dest)
#define VectorSet(v, x, y, z)