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. 113 typedef struct place_s {
164 typedef struct opening_s {
189 static 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);
541 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)
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);
774 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)
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));
1430 int 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",
#define PATHFINDING_MIN_STEPUP
#define SizedPosToVec(p, actorSize, v)
SizedPosToVect locates the center of an actor based on size and position.
#define VectorCopy(src, dest)
#define PATHFINDING_BIG_STEPDOWN
void Sys_Error(const char *error,...)
#define VectorSet(v, x, y, z)
void setCeiling(const actorSizeEnum_t actorSize, const int x, const int y, const int z, const int val)
#define ModelCeilingToQuant(x)
void setFloor(const int actorSize, const int x, const int y, const int z, const int val)
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
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.
#define RT_STEPUP_PY(r, actorSize, x, y, z)
#define RT_CONN_PX_PY(r, actorSize, x, y, z)
void RT_WriteCSVFiles(const Routing &routing, const char *baseFilename, const GridBox &box)
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.
#define RT_CONN_NY(r, actorSize, x, y, 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.
#define RT_CONN_NX_PY(r, actorSize, x, y, z)
#define RT_CONN_PX_NY(r, actorSize, x, y, z)
#define RT_STEPUP_PX_NY(r, actorSize, x, y, z)
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
#define RT_STEPUP_NX_NY(r, actorSize, x, y, z)
const vec4_t dvecs[PATHFINDING_DIRECTIONS]
bool isUsable(void) const
An 'opening' describes the connection between two adjacent spaces where an actor can exist in a cell...
static void RT_StepupSet(RoutingData *rtd, const int x, const int y, const int z, const int dir, const int val)
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.
void set(const AABB &other)
Copies the values from the given aabb.
void Com_Printf(const char *const fmt,...)
static const AABB actor1x1Box(-half1x1Width, -half1x1Width, 0, half1x1Width, half1x1Width, 0)
#define RT_STEPUP_PX_PY(r, actorSize, x, y, z)
void setStepup(const int actorSize, const int x, const int y, const int z, const int dir, const int val)
#define ACTOR_MAX_HEIGHT
The tallest actor's height in QUANT sized units.
#define CELL_HEIGHT
A cell's height in QUANT sized units.
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_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 void RT_PlaceInit(const Routing &routing, const actorSizeEnum_t actorSize, place_t *p, const int x, const int y, const int z)
void UFO_assert(bool condition, const char *fmt,...)
static trace_t RT_ObstructedTrace(const RoutingData *rtd, const Line &traceLine, int hi, int lo)
Helper function to trace for walls.
#define PATHFINDING_WIDTH
absolute max
#define RT_CONN_PX(r, actorSize, x, y, z)
Some macros to access routing table values as described above.
#define RT_STEPUP_NX(r, actorSize, x, y, z)
#define PATHFINDING_MAX_STEPUP
actorSizeEnum_t actorSize
#define RT_CONN_PY(r, actorSize, x, y, z)
A 'place' is a part of a grid column where an actor can exist Unlike for a grid-cell, floor and ceiling are absolute values.
bool RT_AllCellsBelowAreFilled(const Routing &routing, const int actorSize, const pos3_t pos)
Check if pos is on solid ground.
#define VecToPos(v, p)
Map boundary is +/- MAX_WORLD_WIDTH - to get into the positive area we add the possible max negative ...
#define PosToVec(p, v)
Pos boundary size is +/- 128 - to get into the positive area we add the possible max negative value a...
int FS_Printf(qFILE *f, const char *msg,...)
Can print chunks for 1024 chars into a file.
#define PATHFINDING_MICROSTEP_SKIP
The number of microsteps that can be stepped over by an actor. Used to allow an actor to stepup when ...
RoutingData(mapTiles_t *mapTiles, Routing &r, actorSizeEnum_t actorSize, const char **list)
#define VectorInterpolation(p1, p2, frac, mid)
static int RT_CalcNewZ(const RoutingData *rtd, const int ax, const int ay, const int top, const int hi)
#define PATHFINDING_MICROSTEP_SIZE
The size (in model units) of a microstep. Must be a power of 2 and less than UNIT_SIZE.
grid pathfinding and routing
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...
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.
#define ModelFloorToQuant(x)
These macros are meant to correctly convert from model units to QUANT units and back.
byte getCeiling(const int actorSize, const pos3_t pos) const
#define RT_STEPUP_PX(r, actorSize, x, y, z)
static bool RT_PlaceDoesIntersectEnough(const place_t *p, const place_t *other)
#define RT_CONN_NX_NY(r, actorSize, x, y, z)
static const AABB actor2x2Box(-half2x2Width, -half2x2Width, 0, half2x2Width, half2x2Width, 0)
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.
#define PATHFINDING_HEIGHT
15 max, adjusting above 8 will require a rewrite to the DV code
#define VectorAdd(a, b, dest)
#define PATHFINDING_LEGROOMHEIGHT
#define PATHFINDING_MIN_OPENING
#define RT_STEPUP_NY(r, actorSize, x, y, z)
void Com_DefaultExtension(char *path, size_t len, const char *extension)
Sets a default extension if there is none.
#define PATHFINDING_BIG_STEPUP
The home of the routing tables.
void setConn(const int actorSize, const int x, const int y, const int z, const int dir, const int val)
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.
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 const AABB footBox(-halfMicrostepSize, -halfMicrostepSize, 0, halfMicrostepSize, halfMicrostepSize, 0)
#define RT_CONN_NX(r, actorSize, x, y, z)
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 ...
definitions common between client and server, but not game lib
void shift(const vec3_t shiftVec)
shove the whole box by the given vector
static void RT_ConnSetNoGo(RoutingData *rtd, const int x, const int y, const int z, const int dir)
#define PATHFINDING_NO_STEPUP
RT_data_s contains the essential data that is passed to most of the RT_* functions.
#define RT_STEPUP_NX_PY(r, actorSize, x, y, z)
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...
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...
#define ACTOR_SIZE_NORMAL
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.
#define ACTOR_SIZE_INVALID
#define TRACE_VISIBLE_LEVELS
#define PLAYER_STANDING_HEIGHT
#define halfMicrostepSize
#define VectorSubtract(a, b, dest)
static mapTiles_t mapTiles
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.