00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "common.h"
00029 #include "routing.h"
00030
00031
00032
00033
00034
00035
00036
00037 qboolean debugTrace = qfalse;
00038
00039
00040
00041
00042
00043
00044
00045 #define RT_NO_OPENING -1
00046
00047
00048 #define halfMicrostepSize (PATHFINDING_MICROSTEP_SIZE / 2 - DIST_EPSILON)
00049
00050 static const box_t footBox = {{-halfMicrostepSize, -halfMicrostepSize, 0},
00051 { halfMicrostepSize, halfMicrostepSize, 0}};
00052
00053
00054 #define half1x1Width (UNIT_SIZE * 1 / 2 - WALL_SIZE - DIST_EPSILON)
00055 #define half2x2Width (UNIT_SIZE * 2 / 2 - WALL_SIZE - DIST_EPSILON)
00056
00057 static const box_t actor1x1Box = {{-half1x1Width, -half1x1Width, 0},
00058 { half1x1Width, half1x1Width, 0}};
00059 static const box_t actor2x2Box = {{-half2x2Width, -half2x2Width, 0},
00060 { half2x2Width, half2x2Width, 0}};
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 typedef struct place_s {
00073 pos3_t cell;
00074 int floor;
00075 int ceiling;
00076 int floorZ;
00077 qboolean usable;
00078 } place_t;
00079
00080 static inline void RT_PlaceInit (const routing_t *map, const actorSizeEnum_t actorSize, place_t *p, const int x, const int y, const int z)
00081 {
00082 const int relCeiling = RT_CEILING(map, actorSize, x, y, z);
00083 p->cell[0] = x;
00084 p->cell[1] = y;
00085 p->cell[2] = z;
00086 p->floor = RT_FLOOR(map, actorSize, x, y, z) + z * CELL_HEIGHT;
00087 p->ceiling = relCeiling + z * CELL_HEIGHT;
00088 p->floorZ = max(0, p->floor / CELL_HEIGHT) ;
00089 p->usable = (relCeiling && p->floor > -1 && p->ceiling - p->floor >= PATHFINDING_MIN_OPENING) ? qtrue : qfalse;
00090 }
00091
00092 static inline qboolean RT_PlaceIsUsable (const place_t* p)
00093 {
00094 return p->usable;
00095 }
00096
00097 static inline qboolean RT_PlaceDoesIntersectEnough (const place_t* p, const place_t* other)
00098 {
00099 return (min(p->ceiling, other->ceiling) - max(p->floor, other->floor) >= PATHFINDING_MIN_OPENING);
00100 }
00101
00108 static inline int RT_PlaceIsShifted (const place_t* p, const place_t* other)
00109 {
00110 if (!RT_PlaceIsUsable(p) || !RT_PlaceIsUsable(other))
00111 return 0;
00112 if (p->floor < other->floor && p->ceiling < other->ceiling)
00113 return 1;
00114 if (p->floor > other->floor && p->ceiling > other->ceiling)
00115 return 2;
00116 return 0;
00117 }
00118
00123 typedef struct opening_s {
00124 int size;
00125 int base;
00126 int stepup;
00127 int invstepup;
00128 } opening_t;
00129
00130
00131
00132
00133
00134
00135
00136 #ifdef DEBUG
00137
00149 static void RT_DumpMap (const routing_t *map, actorSizeEnum_t actorSize, int lx, int ly, int lz, int hx, int hy, int hz)
00150 {
00151 int x, y, z;
00152
00153 Com_Printf("\nRT_DumpMap (%i %i %i) (%i %i %i)\n", lx, ly, lz, hx, hy, hz);
00154 for (z = hz; z >= lz; --z) {
00155 Com_Printf("\nLayer %i:\n ", z);
00156 for (x = lx; x <= hx; ++x) {
00157 Com_Printf("%9i", x);
00158 }
00159 Com_Printf("\n");
00160 for (y = hy; y >= ly; --y) {
00161 Com_Printf("%3i ", y);
00162 for (x = lx; x <= hx; ++x) {
00163 Com_Printf("%s%s%s%s "
00164 , RT_CONN_NX(map, actorSize, x, y, z) ? "w" : " "
00165 , RT_CONN_PY(map, actorSize, x, y, z) ? "n" : " "
00166 , RT_CONN_NY(map, actorSize, x, y, z) ? "s" : " "
00167 , RT_CONN_PX(map, actorSize, x, y, z) ? "e" : " "
00168 );
00169 }
00170 Com_Printf("\n");
00171 }
00172 }
00173 }
00174
00179 void RT_DumpWholeMap (mapTiles_t *mapTiles, const routing_t *map)
00180 {
00181 box_t box;
00182 vec3_t normal, origin;
00183 pos3_t start, end, test;
00184 trace_t trace;
00185 int i;
00186
00187
00188 VectorClear(start);
00189 VectorSet(end, PATHFINDING_WIDTH - 1, PATHFINDING_WIDTH - 1, PATHFINDING_HEIGHT - 1);
00190 VectorSet(normal, UNIT_SIZE / 2, UNIT_SIZE / 2, UNIT_HEIGHT / 2);
00191 VectorClear(origin);
00192
00193 for (i = 0; i < 3; i++) {
00194
00195 while (end[i] > start[i]) {
00196
00197 VectorCopy(start, test);
00198 test[i] = end[i] - 1;
00199
00200 PosToVec(test, box.mins);
00201 VectorSubtract(box.mins, normal, box.mins);
00202 PosToVec(end, box.maxs);
00203 VectorAdd(box.maxs, normal, box.maxs);
00204
00205 trace = RT_COMPLETEBOXTRACE_SIZE(mapTiles, origin, origin, &box, NULL);
00206 if (trace.fraction < 1.0)
00207 break;
00208
00209 end[i]--;
00210 }
00211
00212
00213 while (end[i] > start[i]) {
00214
00215 VectorCopy(end, test);
00216 test[i] = start[i] + 1;
00217
00218 PosToVec(start, box.mins);
00219 VectorSubtract(box.mins, normal, box.mins);
00220 PosToVec(test, box.maxs);
00221 VectorAdd(box.maxs, normal, box.maxs);
00222
00223 trace = RT_COMPLETEBOXTRACE_SIZE(mapTiles, origin, origin, &box, NULL);
00224 if (trace.fraction < 1.0)
00225 break;
00226
00227 start[i]++;
00228 }
00229 }
00230
00231
00232 RT_DumpMap(map, 0, start[0], start[1], start[2], end[0], end[1], end[2]);
00233 }
00234 #endif
00235
00244 void RT_GetMapSize (mapTiles_t *mapTiles, vec3_t map_min, vec3_t map_max)
00245 {
00246 box_t box;
00247 const vec3_t normal = {UNIT_SIZE / 2, UNIT_SIZE / 2, UNIT_HEIGHT / 2};
00248 pos3_t start, end, test;
00249 vec3_t origin;
00250 int i;
00251 trace_t trace;
00252
00253
00254 VectorSet(start, 0, 0, 0);
00255 VectorSet(end, PATHFINDING_WIDTH - 1, PATHFINDING_WIDTH - 1, PATHFINDING_HEIGHT - 1);
00256 VectorCopy(vec3_origin, origin);
00257
00258 for (i = 0; i < 3; i++) {
00259
00260 while (end[i] > start[i]) {
00261
00262 VectorCopy(start, test);
00263 test[i] = end[i];
00264
00265 PosToVec(test, box.mins);
00266 VectorSubtract(box.mins, normal, box.mins);
00267 PosToVec(end, box.maxs);
00268 VectorAdd(box.maxs, normal, box.maxs);
00269
00270 trace = RT_COMPLETEBOXTRACE_SIZE(mapTiles, origin, origin, &box, NULL);
00271 if (trace.fraction < 1.0)
00272 break;
00273
00274 end[i]--;
00275 }
00276
00277
00278 while (end[i] > start[i]) {
00279
00280 VectorCopy(end, test);
00281 test[i] = start[i];
00282
00283 PosToVec(start, box.mins);
00284 VectorSubtract(box.mins, normal, box.mins);
00285 PosToVec(test, box.maxs);
00286 VectorAdd(box.maxs, normal, box.maxs);
00287
00288 trace = RT_COMPLETEBOXTRACE_SIZE(mapTiles, origin, origin, &box, NULL);
00289 if (trace.fraction < 1.0)
00290 break;
00291
00292 start[i]++;
00293 }
00294 }
00295
00296
00297
00298
00299 PosToVec(start, map_min);
00300 PosToVec(end, map_max);
00301
00302
00303 VectorSubtract(map_min, normal, map_min);
00304 VectorAdd(map_max, normal, map_max);
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00323 qboolean RT_AllCellsBelowAreFilled (const routing_t * map, const int actorSize, const pos3_t pos)
00324 {
00325 int i;
00326
00327
00328 if (pos[2] == 0)
00329 return qtrue;
00330
00331 for (i = 0; i < pos[2]; i++) {
00332 if (RT_CEILING(map, actorSize, pos[0], pos[1], i) != 0)
00333 return qfalse;
00334 }
00335 return qtrue;
00336 }
00337
00353 int RT_CheckCell (mapTiles_t *mapTiles, routing_t * map, const int actorSize, const int x, const int y, const int z, const char **list)
00354 {
00355
00356 const float halfActorWidth = UNIT_SIZE * actorSize / 2 - WALL_SIZE - DIST_EPSILON;
00357
00358 const box_t legBox = {{-halfMicrostepSize, -halfMicrostepSize, 0},
00359 { halfMicrostepSize, halfMicrostepSize, QuantToModel(PATHFINDING_LEGROOMHEIGHT) - DIST_EPSILON * 2}};
00360
00361 const box_t torsoBox = {{-halfActorWidth, -halfActorWidth, QuantToModel(PATHFINDING_LEGROOMHEIGHT)},
00362 { halfActorWidth, halfActorWidth, QuantToModel(PATHFINDING_MIN_OPENING) - DIST_EPSILON * 2}};
00363
00364 const box_t ceilBox = {{-halfActorWidth, -halfActorWidth, 0},
00365 { halfActorWidth, halfActorWidth, 0}};
00366
00367 vec3_t start, end;
00368 vec3_t tstart, tend;
00369 box_t box;
00370 pos3_t pos;
00371 float bottom, top;
00372 float initial;
00373 int bottomQ, topQ;
00374 int i;
00375 int fz, cz;
00376 trace_t tr;
00377
00378 assert(actorSize > ACTOR_SIZE_INVALID && actorSize <= ACTOR_MAX_SIZE);
00379 assert(map);
00380
00381 assert((x >= 0) && (x <= PATHFINDING_WIDTH - actorSize));
00382 assert((y >= 0) && (y <= PATHFINDING_WIDTH - actorSize));
00383 assert(z < PATHFINDING_HEIGHT);
00384
00385
00386 VectorSet(pos, x, y, z);
00387 SizedPosToVec(pos, actorSize, end);
00388
00389
00390 VectorCopy(end, start);
00391
00392
00393
00394 initial = start[2] + UNIT_HEIGHT / 2;
00395 start[2] += UNIT_HEIGHT / 2 - QUANT;
00396 end[2] = -UNIT_HEIGHT * 2;
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 while (qtrue) {
00410 if (debugTrace)
00411 Com_Printf("[(%i, %i, %i, %i)]Casting floor (%f, %f, %f) to (%f, %f, %f)\n",
00412 x, y, z, actorSize, start[0], start[1], start[2], end[0], end[1], end[2]);
00413
00414 tr = RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, start, end, &footBox, list);
00415 if (tr.fraction >= 1.0) {
00416
00417 if (debugTrace)
00418 Com_Printf("Reached bottom of map. No floor in cell(s). %f\n", tr.endpos[2]);
00419
00420 for (i = z; i >= 0 ; i--) {
00421
00422 RT_FLOOR(map, actorSize, x, y, i) = -1 - i * CELL_HEIGHT;
00423 RT_CEILING(map, actorSize, x, y, i) = 0;
00424 }
00425
00426 return 0;
00427 }
00428
00429
00430 bottom = tr.endpos[2];
00431
00432 assert(initial > bottom);
00433
00434 if (debugTrace)
00435 Com_Printf("Potential floor found at %f.\n", bottom);
00436
00437
00438 VectorCopy(tr.endpos, tstart);
00439
00440
00441 VectorAdd(tstart, legBox.mins, box.mins);
00442 VectorAdd(tstart, legBox.maxs, box.maxs);
00443
00444 if (debugTrace)
00445 Com_Printf(" Casting leg room (%f, %f, %f) to (%f, %f, %f)\n",
00446 box.mins[0], box.mins[1], box.mins[2], box.maxs[0], box.maxs[1], box.maxs[2]);
00447 tr = RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, vec3_origin, vec3_origin, &box, list);
00448 if (tr.fraction < 1.0) {
00449 if (debugTrace)
00450 Com_Printf("Cannot use found surface- leg obstruction found.\n");
00451
00452
00453
00454
00455
00456 start[2] = bottom - QuantToModel(PATHFINDING_MIN_OPENING);
00457
00458 if (start[2] <= QuantToModel(PATHFINDING_MIN_OPENING)) {
00459
00460 if (debugTrace)
00461 Com_Printf("Reached bottom of map. No floor in cell(s).\n");
00462
00463 for (i = z; i >= 0 ; i--) {
00464
00465 RT_FLOOR(map, actorSize, x, y, i) = CELL_HEIGHT;
00466 RT_CEILING(map, actorSize, x, y, i) = 0;
00467 }
00468
00469 return 0;
00470 }
00471
00472 continue;
00473 }
00474
00475
00476 VectorAdd(tstart, torsoBox.mins, box.mins);
00477 VectorAdd(tstart, torsoBox.maxs, box.maxs);
00478
00479 if (debugTrace)
00480 Com_Printf(" Casting torso room (%f, %f, %f) to (%f, %f, %f)\n",
00481 box.mins[0], box.mins[1], box.mins[2], box.maxs[0], box.maxs[1], box.maxs[2]);
00482 tr = RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, vec3_origin, vec3_origin, &box, list);
00483 if (tr.fraction < 1.0) {
00484 if (debugTrace)
00485 Com_Printf("Cannot use found surface- torso obstruction found.\n");
00486
00487
00488
00489
00490
00491 start[2] = bottom - QuantToModel(PATHFINDING_MIN_OPENING);
00492
00493 if (start[2] <= QuantToModel(PATHFINDING_MIN_OPENING)) {
00494
00495 if (debugTrace)
00496 Com_Printf("Reached bottom of map. No floor in cell(s).\n");
00497
00498 for (i = z; i >= 0 ; i--) {
00499
00500 RT_FLOOR(map, actorSize, x, y, i) = CELL_HEIGHT;
00501 RT_CEILING(map, actorSize, x, y, i) = 0;
00502 }
00503
00504 return 0;
00505 }
00506
00507 continue;
00508 }
00509
00510
00511
00512
00513
00514
00515 tstart[2] = box.maxs[2];
00516 VectorCopy(tstart, tend);
00517 tend[2] = PATHFINDING_HEIGHT * UNIT_HEIGHT;
00518
00519 if (debugTrace)
00520 Com_Printf(" Casting ceiling (%f, %f, %f) to (%f, %f, %f)\n",
00521 tstart[0], tstart[1], tstart[2], tend[0], tend[1], tend[2]);
00522
00523 tr = RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, tstart, tend, &ceilBox, list);
00524
00525
00526 top = tr.endpos[2];
00527
00528
00529
00530
00531
00532
00533
00534 if (tr.endpos[2] > (z + 1) * UNIT_HEIGHT)
00535 top = min(tr.endpos[2], (z + 1) * UNIT_HEIGHT + QuantToModel(RT_FLOOR(map, actorSize, x, y, z + 1) - 1));
00536
00537
00538 top = tr.endpos[2];
00539
00540
00541 break;
00542 }
00543
00544 assert(bottom <= top);
00545
00546
00547
00548
00549 bottom -= 2 * DIST_EPSILON;
00550 top += 2 * DIST_EPSILON;
00551 bottomQ = ModelFloorToQuant(bottom);
00552 topQ = ModelCeilingToQuant(top);
00553 fz = floor(bottomQ / CELL_HEIGHT);
00555 cz = min(z, (int)(floor((topQ - 1) / CELL_HEIGHT)));
00556
00557 assert(fz <= cz);
00558
00559 if (debugTrace)
00560 Com_Printf("Valid ceiling found, bottom=%f, top=%f, fz=%i, cz=%i.\n", bottom, top, fz, cz);
00561
00562
00563 for (i = fz; i <= cz; i++) {
00564
00565 RT_FLOOR(map, actorSize, x, y, i) = bottomQ - i * CELL_HEIGHT;
00566
00567 RT_CEILING(map, actorSize, x, y, i) = topQ - i * CELL_HEIGHT;
00568 if (debugTrace) {
00569 Com_Printf("floor(%i, %i, %i, %i)=%i.\n", x, y, i, actorSize, RT_FLOOR(map, actorSize, x, y, i));
00570 Com_Printf("ceil(%i, %i, %i, %i)=%i.\n", x, y, i, actorSize, RT_CEILING(map, actorSize, x, y, i));
00571 }
00572 }
00573
00574
00575 for (i = cz + 1; i <= z; i++) {
00576 RT_FLOOR(map, actorSize, x, y, i) = CELL_HEIGHT;
00577 RT_CEILING(map, actorSize, x, y, i) = 0;
00578 if (debugTrace) {
00579 Com_Printf("floor(%i, %i, %i)=%i.\n", x, y, i, RT_FLOOR(map, actorSize, x, y, i));
00580 Com_Printf("ceil(%i, %i, %i)=%i.\n", x, y, i, RT_CEILING(map, actorSize, x, y, i));
00581 }
00582 }
00583
00584
00585 return fz;
00586 }
00587
00588
00601 static int RT_FillPassageData (routing_t * map, const actorSizeEnum_t actorSize, const int dir, const int x, const int y, const int z, const int openingSize, const int openingBase, const int stepup)
00602 {
00603 const int openingTop = openingBase + openingSize;
00604 int fz, cz;
00605 int i;
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 fz = z;
00621 cz = min(PATHFINDING_HEIGHT - 1, ceil((float)openingTop / CELL_HEIGHT) - 1);
00622
00623
00624 if (cz < z) {
00625
00626 RT_CONN(map, actorSize, x, y, z, dir) = 0;
00627 RT_STEPUP(map, actorSize, x, y, z, dir) = PATHFINDING_NO_STEPUP;
00628 if (debugTrace)
00629 Com_Printf("Passage found but below current cell, opening_base=%i, opening_top=%i, z = %i, cz = %i.\n", openingBase, openingTop, z, cz);
00630 return z;
00631 }
00632
00633 if (debugTrace)
00634 Com_Printf("Passage found, opening_base=%i, opening_size=%i, opening_top=%i, stepup=%i. (%i to %i)\n", openingBase, openingSize, openingTop, stepup, fz, cz);
00635
00636 assert(fz <= z && z <= cz);
00637
00638
00639 for (i = fz; i <= cz; i++) {
00640
00641
00642 RT_CONN_TEST(map, actorSize, x, y, i, dir);
00643 assert (openingTop - max(openingBase, i * CELL_HEIGHT) >= 0);
00644 RT_CONN(map, actorSize, x, y, i, dir) = openingTop - max(openingBase, i * CELL_HEIGHT);
00645
00646 RT_STEPUP(map, actorSize, x, y, i, dir) = 0;
00647 if (debugTrace) {
00648 Com_Printf("RT_CONN for (%i, %i, %i) as:%i dir:%i = %i\n", x, y, i, actorSize, dir, RT_CONN(map, actorSize, x, y, i, dir));
00649 }
00650 }
00651
00652 RT_STEPUP(map, actorSize, x, y, z, dir) = stepup;
00653 if (debugTrace) {
00654 Com_Printf("Final RT_STEPUP for (%i, %i, %i) as:%i dir:%i = %i\n", x, y, z, actorSize, dir, stepup);
00655 }
00656
00657
00658
00659
00660
00661 if (fz == cz || z == cz || RT_FLOOR(map, actorSize, x, y, cz) < 0)
00662 return cz;
00663 return cz - 1;
00664 }
00665
00674 static trace_t RT_ObstructedTrace (mapTiles_t *mapTiles, const vec3_t start, const vec3_t end, actorSizeEnum_t actorSize, int hi, int lo, const char **list)
00675 {
00676 box_t box;
00677 const float halfActorWidth = UNIT_SIZE * actorSize / 2 - WALL_SIZE - DIST_EPSILON;
00678
00679
00680 VectorSet(box.maxs, halfActorWidth, halfActorWidth, QuantToModel(hi) - DIST_EPSILON);
00681 VectorSet(box.mins, -halfActorWidth, -halfActorWidth, QuantToModel(lo) + DIST_EPSILON);
00682
00683
00684 return RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, start, end, &box, list);
00685 }
00686
00687
00697 static int RT_FindOpeningFloorFrac (mapTiles_t *mapTiles, const vec3_t start, const vec3_t end, const actorSizeEnum_t actorSize, const float frac, const int startingHeight, const char **list)
00698 {
00699 vec3_t mstart, mend;
00700 trace_t tr;
00701 const box_t* box = (actorSize == ACTOR_SIZE_NORMAL ? &actor1x1Box : &actor2x2Box);
00702
00703
00704 VectorInterpolation(start, end, frac, mstart);
00705 VectorCopy(mstart, mend);
00706 mstart[2] = QuantToModel(startingHeight) + (QUANT / 2);
00707 mend[2] = -QUANT;
00708
00709 tr = RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, mstart, mend, box, list);
00710
00711 if (debugTrace)
00712 Com_Printf("Brush found at %f.\n", tr.endpos[2]);
00713
00714
00715
00716
00717 return ModelFloorToQuant(tr.endpos[2] - DIST_EPSILON);
00718 }
00719
00720
00730 static int RT_FindOpeningCeilingFrac (mapTiles_t *mapTiles, const vec3_t start, const vec3_t end, const actorSizeEnum_t actorSize, const float frac, const int startingHeight, const char **list)
00731 {
00732 vec3_t mstart, mend;
00733 trace_t tr;
00734 const box_t* box = (actorSize == ACTOR_SIZE_NORMAL ? &actor1x1Box : &actor2x2Box);
00736
00737 VectorInterpolation(start, end, frac, mstart);
00738 VectorCopy(mstart, mend);
00739 mstart[2] = QuantToModel(startingHeight) - (QUANT / 2);
00740 mend[2] = UNIT_HEIGHT * PATHFINDING_HEIGHT + QUANT;
00741
00742 tr = RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, mstart, mend, box, list);
00743
00744 if (debugTrace)
00745 Com_Printf("Brush found at %f.\n", tr.endpos[2]);
00746
00747
00748
00749 return ModelCeilingToQuant(tr.endpos[2] + DIST_EPSILON);
00750 }
00751
00752
00762 static int RT_FindOpeningFloor (mapTiles_t *mapTiles, const vec3_t start, const vec3_t end, const actorSizeEnum_t actorSize, const int startingHeight, const int floorLimit, const char **list)
00763 {
00764
00765 int midfloor;
00766
00767 if (start[0] == end[0] || start[1] == end[1]) {
00768
00769 midfloor = RT_FindOpeningFloorFrac(mapTiles, start, end, actorSize, 0.5, startingHeight, list);
00770 if (debugTrace)
00771 Com_Printf("midfloor:%i.\n", midfloor);
00772 } else {
00773 int midfloor2;
00774
00775
00776
00777 midfloor = RT_FindOpeningFloorFrac(mapTiles, start, end, actorSize, 0.33, startingHeight, list);
00778 if (debugTrace)
00779 Com_Printf("1/3floor:%i.\n", midfloor);
00780
00781
00782 midfloor2 = RT_FindOpeningFloorFrac(mapTiles, start, end, actorSize, 0.66, startingHeight, list);
00783 if (debugTrace)
00784 Com_Printf("2/3floor:%i.\n", midfloor2);
00785 midfloor = max(midfloor, midfloor2);
00786 }
00787
00788
00789 return max(floorLimit, midfloor);
00790 }
00791
00792
00802 static int RT_FindOpeningCeiling (mapTiles_t *mapTiles, const vec3_t start, const vec3_t end, const actorSizeEnum_t actorSize, const int startingHeight, const int ceilLimit, const char **list)
00803 {
00804 int midceil;
00805
00806 if (start[0] == end[0] || start[1] == end[1]) {
00807
00808 midceil = RT_FindOpeningCeilingFrac(mapTiles, start, end, actorSize, 0.5, startingHeight, list);
00809 if (debugTrace)
00810 Com_Printf("midceil:%i.\n", midceil);
00811 } else {
00812 int midceil2;
00813
00814
00815
00816 midceil = RT_FindOpeningCeilingFrac(mapTiles, start, end, actorSize, 0.33, startingHeight, list);
00817 if (debugTrace)
00818 Com_Printf("1/3ceil:%i.\n", midceil);
00819
00820
00821 midceil2 = RT_FindOpeningCeilingFrac(mapTiles, start, end, actorSize, 0.66, startingHeight, list);
00822 if (debugTrace)
00823 Com_Printf("2/3ceil:%i.\n", midceil2);
00824 midceil = min(midceil, midceil2);
00825 }
00826
00827
00828 return min(ceilLimit, midceil);
00829 }
00830
00831
00832 static int RT_CalcNewZ (const routing_t * map, const actorSizeEnum_t actorSize, const int ax, const int ay, const int top, const int hi)
00833 {
00834 int temp_z, adj_lo;
00835
00836 temp_z = min(floor((hi - 1) / CELL_HEIGHT), PATHFINDING_HEIGHT - 1);
00837 adj_lo = RT_FLOOR(map, actorSize, ax, ay, temp_z) + temp_z * CELL_HEIGHT;
00838 if (adj_lo > hi) {
00839 temp_z--;
00840 adj_lo = RT_FLOOR(map, actorSize, ax, ay, temp_z) + temp_z * CELL_HEIGHT;
00841 }
00847 if (adj_lo >= 0 && top - adj_lo >= PATHFINDING_MIN_OPENING - PATHFINDING_MIN_STEPUP) {
00848 if (debugTrace)
00849 Com_Printf("Found floor in destination cell: %i (%i).\n", adj_lo, temp_z);
00850 return floor(adj_lo / CELL_HEIGHT);
00851 }
00852 if (debugTrace)
00853 Com_Printf("Skipping found floor in destination cell- not enough opening: %i (%i).\n", adj_lo, temp_z);
00854
00855 return RT_NO_OPENING;
00856 }
00857
00858
00875 static int RT_TraceOpening (mapTiles_t *mapTiles, const routing_t * map, const actorSizeEnum_t actorSize, 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 *lo_val, int *hi_val, const char **list)
00876 {
00877 trace_t tr = RT_ObstructedTrace(mapTiles, start, end, actorSize, hi, lo, list);
00878 if (tr.fraction >= 1.0) {
00879 lo = RT_FindOpeningFloor(mapTiles, start, end, actorSize, lo, bottom, list);
00880 hi = RT_FindOpeningCeiling(mapTiles, start, end, actorSize, hi, top, list);
00881 if (hi - lo >= PATHFINDING_MIN_OPENING) {
00882 int temp_z;
00883 if (lo == -1) {
00884 if (debugTrace)
00885 Com_Printf("Bailing- no floor in destination cell.\n");
00886 *lo_val = *hi_val = 0;
00887 return RT_NO_OPENING;
00888 }
00889
00890 *lo_val = lo;
00891 *hi_val = hi;
00892
00893 temp_z = RT_CalcNewZ(map, actorSize, ax, ay, top, hi);
00894 if (temp_z != RT_NO_OPENING)
00895 return temp_z;
00896 }
00897 }
00898 *lo_val = *hi_val = hi;
00899 return RT_NO_OPENING;
00900 }
00901
00902
00916 static int RT_FindOpening (mapTiles_t *mapTiles, const routing_t * map, const actorSizeEnum_t actorSize, place_t* from, const int ax, const int ay, const int bottom, const int top, int *lo_val, int *hi_val, const char **list)
00917 {
00918 vec3_t start, end;
00919 pos3_t pos;
00920 int temp_z;
00921
00922 const int endfloor = RT_FLOOR(map, actorSize, ax, ay, from->cell[2]) + from->cell[2] * CELL_HEIGHT;
00923 const int hifloor = max (endfloor, bottom);
00924
00925 if (debugTrace)
00926 Com_Printf("ef:%i t:%i b:%i\n", endfloor, top, bottom);
00927
00928 if (bottom == -1) {
00929 if (debugTrace)
00930 Com_Printf("Bailing- no floor in current cell.\n");
00931 *lo_val = *hi_val = 0;
00932 return RT_NO_OPENING;
00933 }
00934
00935
00936 SizedPosToVec(from->cell, actorSize, start);
00937
00938
00939 VectorSet(pos, ax, ay, from->cell[2]);
00940 SizedPosToVec(pos, actorSize, end);
00941
00942
00943 start[2] = end[2] = 0;
00944
00945
00946
00947 if (from->ceiling >= PATHFINDING_HEIGHT * CELL_HEIGHT
00948 && from->cell[2] * CELL_HEIGHT + RT_CEILING(map, actorSize, ax, ay, from->cell[2]) >= PATHFINDING_HEIGHT * CELL_HEIGHT) {
00949 vec3_t sky, earth;
00950 const box_t* box = (actorSize == ACTOR_SIZE_NORMAL ? &actor1x1Box : &actor2x2Box);
00951 trace_t tr;
00952 int tempBottom;
00953
00954 if (debugTrace)
00955 Com_Printf("Using sky trace.\n");
00956
00957 VectorInterpolation(start, end, 0.5, sky);
00958 VectorCopy(sky, earth);
00959 sky[2] = UNIT_HEIGHT * PATHFINDING_HEIGHT;
00960 earth[2] = QuantToModel(bottom);
00961
00962 tr = RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, sky, earth, box, list);
00963 tempBottom = ModelFloorToQuant(tr.endpos[2]);
00964 if (tempBottom <= bottom + PATHFINDING_MIN_STEPUP) {
00965 const int hi = bottom + PATHFINDING_MIN_OPENING;
00966 if (debugTrace)
00967 Com_Printf("Found opening with sky trace.\n");
00968 *lo_val = tempBottom;
00969 *hi_val = CELL_HEIGHT * PATHFINDING_HEIGHT;
00970 return RT_CalcNewZ(map, actorSize, ax, ay, top, hi);
00971 }
00972 if (debugTrace)
00973 Com_Printf("Failed sky trace.\n");
00974 }
00975
00976
00977
00978
00979
00980
00981 if (top - bottom < PATHFINDING_MIN_OPENING * 2) {
00982 const int lo = top - PATHFINDING_MIN_OPENING;
00983 const int hi = bottom + PATHFINDING_MIN_OPENING;
00984 if (debugTrace)
00985 Com_Printf("Tracing closed space from %i to %i.\n", bottom, top);
00986 temp_z = RT_TraceOpening(mapTiles, map, actorSize, start, end, ax, ay, hifloor, top, lo, hi, lo_val, hi_val, list);
00987 } else {
00988
00989 int lo = bottom;
00990 temp_z = 0;
00991 while (lo <= top - PATHFINDING_MIN_OPENING) {
00992
00993 if (debugTrace)
00994 Com_Printf("Tracing open space from %i.\n", lo);
00995 temp_z = RT_TraceOpening(mapTiles, map, actorSize, start, end, ax, ay, bottom, top, lo, lo + 1, lo_val, hi_val, list);
00996 if (temp_z != RT_NO_OPENING)
00997 break;
00998
00999
01000 lo = *hi_val + PATHFINDING_MIN_OPENING;
01001 }
01002 }
01003 return temp_z;
01004 }
01005
01006
01019 static int RT_MicroTrace (mapTiles_t *mapTiles, const routing_t * map, const actorSizeEnum_t actorSize, place_t* from, const int ax, const int ay, const int az, const int stairwaySituation, opening_t* opening, const char **list)
01020 {
01021
01022
01023 int top = opening->base + opening->size;
01024 signed char bases[UNIT_SIZE / PATHFINDING_MICROSTEP_SIZE + 1];
01025 float sx, sy, ex, ey;
01026
01027 const int steps = UNIT_SIZE / PATHFINDING_MICROSTEP_SIZE;
01028 trace_t tr;
01029 int i, current_h, highest_h, highest_i = 0, skipped, newBottom;
01030 vec3_t start, end;
01031 pos3_t pos;
01032 int last_step;
01033
01034
01035 bases[0] = from->floor;
01036 bases[steps] = last_step = max(0, RT_FLOOR(map, actorSize, ax, ay, az)) + az * CELL_HEIGHT;
01037
01038
01039 SizedPosToVec(from->cell, actorSize, start);
01040
01041
01042 VectorSet(pos, ax, ay, az);
01043 SizedPosToVec(pos, actorSize, end);
01044
01045
01046 start[2] = QuantToModel(opening->base) + 1;
01047 end[2] = -QUANT;
01048
01049
01050 sx = start[0];
01051 sy = start[1];
01052 ex = end[0];
01053 ey = end[1];
01054
01055 newBottom = max(bases[0], bases[steps]);
01056
01057 for (i = 1; i < steps; i++) {
01058 start[0] = end[0] = sx + (ex - sx) * (i / (float)steps);
01059 start[1] = end[1] = sy + (ey - sy) * (i / (float)steps);
01060
01061
01062 tr = RT_COMPLETEBOXTRACE_PASSAGE(mapTiles, start, end, &footBox, list);
01063 if (tr.fraction >= 1.0) {
01064 bases[i] = -1;
01065 } else {
01066 bases[i] = ModelFloorToQuant(tr.endpos[2] - DIST_EPSILON);
01067
01068
01069
01070
01071
01072
01073 if (i == floor(steps / 2.0) && bases[i] < opening->base - PATHFINDING_MIN_STEPUP) {
01074 if (debugTrace)
01075 Com_Printf("Adjusting middle trace- the known base is too high. \n");
01076 bases[i] = opening->base - PATHFINDING_MIN_STEPUP;
01077 }
01078 }
01079
01080 if (debugTrace)
01081 Com_Printf("Microstep %i from (%f, %f, %f) to (%f, %f, %f) = %i [%f]\n",
01082 i, start[0], start[1], start[2], end[0], end[1], end[2], bases[i], tr.endpos[2]);\
01083
01084 newBottom = max(newBottom, bases[i]);
01085 }
01086
01087 if (debugTrace)
01088 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]);
01089
01090
01092
01093
01094 current_h = bases[0];
01095 highest_h = -1;
01096 highest_i = 1;
01097 opening->stepup = 0;
01098 skipped = 0;
01099 for (i = 1; i <= steps; i++) {
01100 if (debugTrace)
01101 Com_Printf("Tracing forward i:%i h:%i\n", i, current_h);
01102
01103 if (bases[i] >= current_h || ++skipped > PATHFINDING_MICROSTEP_SKIP) {
01104 if (skipped == PATHFINDING_MICROSTEP_SKIP) {
01105 i = highest_i;
01106 if (debugTrace)
01107 Com_Printf(" Skipped too many steps, reverting to i:%i\n", i);
01108 }
01109 opening->stepup = max(opening->stepup, bases[i] - current_h);
01110 current_h = bases[i];
01111 highest_h = -2;
01112 highest_i = i + 1;
01113 skipped = 0;
01114 if (debugTrace)
01115 Com_Printf(" Advancing b:%i stepup:%i\n", bases[i], opening->stepup);
01116 } else {
01117
01118
01119 if (bases[i] > highest_h) {
01120 highest_h = bases[i];
01121 highest_i = i;
01122 }
01123 if (debugTrace)
01124 Com_Printf(" Skipped because we are falling, skip:%i.\n", skipped);
01125
01126 if (i == steps) {
01127 skipped = PATHFINDING_MICROSTEP_SKIP;
01128 i = highest_i - 1;
01129 if (debugTrace)
01130 Com_Printf(" Tripping skip counter to perform last tests.\n");
01131 }
01132 }
01133 }
01134
01136
01137
01138 current_h = bases[steps];
01139 highest_h = -1;
01140 highest_i = steps - 1;
01141 opening->invstepup = 0;
01142 skipped = 0;
01143 for (i = steps - 1; i >= 0; i--) {
01144 if (debugTrace)
01145 Com_Printf("Tracing backward i:%i h:%i\n", i, current_h);
01146
01147 if (bases[i] >= current_h || ++skipped > PATHFINDING_MICROSTEP_SKIP) {
01148 if (skipped == PATHFINDING_MICROSTEP_SKIP) {
01149 i = highest_i;
01150 if (debugTrace)
01151 Com_Printf(" Skipped too many steps, reverting to i:%i\n", i);
01152 }
01153 opening->invstepup = max(opening->invstepup, bases[i] - current_h);
01154 current_h = bases[i];
01155 highest_h = -2;
01156 highest_i = i - 1;
01157 skipped = 0;
01158 if (debugTrace)
01159 Com_Printf(" Advancing b:%i stepup:%i\n", bases[i], opening->invstepup);
01160 } else {
01161
01162
01163 if (bases[i] > highest_h) {
01164 highest_h = bases[i];
01165 highest_i = i;
01166 }
01167 if (debugTrace)
01168 Com_Printf(" Skipped because we are falling, skip:%i.\n", skipped);
01169
01170 if (i == 0) {
01171 skipped = PATHFINDING_MICROSTEP_SKIP;
01172 i = highest_i + 1;
01173 if (debugTrace)
01174 Com_Printf(" Tripping skip counter to perform last tests.\n");
01175 }
01176 }
01177 }
01178
01179 if (stairwaySituation) {
01180 const int middle = bases[4];
01181
01182 if (stairwaySituation == 1) {
01183 if (bases[1] <= middle &&
01184 bases[2] <= middle &&
01185 bases[3] <= middle ) {
01186 if (debugTrace)
01187 Com_Printf("Addition granted by ugly stair hack-stepping up.\n");
01188 return opening->base - middle;
01189 }
01190 } else if (stairwaySituation == 2) {
01191 if (bases[5] <= middle &&
01192 bases[6] <= middle &&
01193 bases[7] <= middle )
01194 if (debugTrace)
01195 Com_Printf("Addition granted by ugly stair hack-stepping down.\n");
01196 return opening->base - middle;
01197 }
01198 }
01199
01200
01201 return opening->base - newBottom;
01202 }
01203
01204
01214 static int RT_TraceOnePassage (mapTiles_t *mapTiles, const routing_t * map, const actorSizeEnum_t actorSize, place_t* from, place_t* to, opening_t* opening, const char **list)
01215 {
01216 int hi;
01217 const int z = from->cell[2];
01218 int az;
01219 const int lower = max(from->floor, to->floor);
01220 const int upper = min(from->ceiling, to->ceiling);
01221 const int ax = to->cell[0];
01222 const int ay = to->cell[1];
01223
01224 az = RT_FindOpening(mapTiles, map, actorSize, from, ax, ay, lower, upper, &opening->base, &hi, list);
01225
01226 opening->size = hi - opening->base;
01227 az = to->floorZ;
01228
01229
01230
01231
01232
01233 if (az != RT_NO_OPENING && opening->size >= PATHFINDING_MIN_OPENING - PATHFINDING_MIN_STEPUP) {
01234 const int srcFloor = from->floor;
01235 const int dstFloor = RT_FLOOR(map, actorSize, ax, ay, az) + az * CELL_HEIGHT;
01236
01238 if (opening->size < CELL_HEIGHT
01239 || abs(srcFloor - opening->base) > PATHFINDING_MIN_STEPUP
01240 || abs(dstFloor - opening->base) > PATHFINDING_MIN_STEPUP) {
01241 int stairway = RT_PlaceIsShifted(from,to);
01242
01243
01244 const int bonusSize = RT_MicroTrace(mapTiles, map, actorSize, from, ax, ay, az, stairway, opening, list);
01245 opening->base -= bonusSize;
01246 opening->size = hi - opening->base;
01247 } else {
01248
01249 opening->stepup = max(0, opening->base - srcFloor);
01250 opening->invstepup = max(0, opening->base - dstFloor);
01251 }
01252
01253
01254 if (opening->stepup > PATHFINDING_MAX_STEPUP) {
01255 opening->stepup = PATHFINDING_NO_STEPUP;
01256 } else {
01257
01258 if (az < z && opening->invstepup <= PATHFINDING_MAX_STEPUP)
01259
01260 opening->stepup |= PATHFINDING_BIG_STEPDOWN;
01261 else if (az > z)
01262 opening->stepup |= PATHFINDING_BIG_STEPUP;
01263 }
01264
01265
01266 if (opening->invstepup > PATHFINDING_MAX_STEPUP) {
01267 opening->invstepup = PATHFINDING_NO_STEPUP;
01268 } else {
01269
01270 if (az > z)
01271 opening->invstepup |= PATHFINDING_BIG_STEPDOWN;
01272 else if (az < z)
01273 opening->invstepup |= PATHFINDING_BIG_STEPUP;
01274 }
01275
01276 if (opening->size >= PATHFINDING_MIN_OPENING) {
01277 return opening->size;
01278 }
01279 }
01280
01281 if (debugTrace)
01282 Com_Printf(" No opening found.\n");
01283 opening->stepup = PATHFINDING_NO_STEPUP;
01284 opening->invstepup = PATHFINDING_NO_STEPUP;
01285 return 0;
01286 }
01287
01299 static void RT_TracePassage (mapTiles_t *mapTiles, const routing_t * map, const actorSizeEnum_t actorSize, const int x, const int y, const int z, const int ax, const int ay, opening_t* opening, const char **list)
01300 {
01301 int aboveCeil, lowCeil;
01303 place_t from, to, above;
01304 place_t* placeToCheck = NULL;
01305
01306 RT_PlaceInit(map, actorSize, &from, x, y, z);
01307 RT_PlaceInit(map, actorSize, &to, ax, ay, z);
01308
01309 aboveCeil = (z < PATHFINDING_HEIGHT - 1) ? RT_CEILING(map, actorSize, ax, ay, z + 1) + (z + 1) * CELL_HEIGHT : to.ceiling;
01310 lowCeil = min(from.ceiling, (RT_CEILING(map, actorSize, ax, ay, z) == 0 || to.ceiling - from.floor < PATHFINDING_MIN_OPENING) ? aboveCeil : to.ceiling);
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330 if (RT_PlaceIsUsable(&to) && RT_PlaceDoesIntersectEnough(&from, &to)) {
01331 placeToCheck = &to;
01332 }
01333 else if (z < PATHFINDING_HEIGHT - 1) {
01334 RT_PlaceInit(map, actorSize, &above, ax, ay, z + 1);
01335 if (RT_PlaceIsUsable(&above) && RT_PlaceDoesIntersectEnough(&from, &above)) {
01336 placeToCheck = &above;
01337 }
01338 }
01339 if (!placeToCheck) {
01340 if (debugTrace)
01341 Com_Printf(" No opening found. c:%i lc:%i.\n", from.ceiling, lowCeil);
01342
01343 opening->stepup = PATHFINDING_NO_STEPUP;
01344 opening->invstepup = PATHFINDING_NO_STEPUP;
01345 opening->base = lowCeil;
01346 opening->size = 0;
01347 return;
01348 }
01349
01350
01351
01352
01353
01354
01355 if (debugTrace)
01356 Com_Printf(" Testing up c:%i lc:%i.\n", from.ceiling, lowCeil);
01357
01358 RT_TraceOnePassage(mapTiles, map, actorSize, &from, placeToCheck, opening, list);
01359 if (opening->size < PATHFINDING_MIN_OPENING) {
01360 if (debugTrace)
01361 Com_Printf(" No opening found.\n");
01362
01363 opening->stepup = PATHFINDING_NO_STEPUP;
01364 opening->invstepup = PATHFINDING_NO_STEPUP;
01365 opening->base = lowCeil;
01366 opening->size = 0;
01367 }
01368 }
01369
01370
01382 static int RT_UpdateConnection (mapTiles_t *mapTiles, routing_t * map, const actorSizeEnum_t actorSize, const int x, const int y, const int ax, const int ay, const int z, const int dir, const char **list)
01383 {
01384 const int ceiling = RT_CEILING(map, actorSize, x, y, z);
01385 const int adjCeiling = RT_CEILING(map, actorSize, ax, ay, z);
01386 const int absCeiling = ceiling + z * CELL_HEIGHT;
01387 const int exadjCeiling = (z < PATHFINDING_HEIGHT - 1) ? RT_CEILING(map, actorSize, ax, ay, z + 1) : adjCeiling;
01388 const int exabs_adj_ceiling = (z < PATHFINDING_HEIGHT - 1) ? adjCeiling + (z + 1) * CELL_HEIGHT : absCeiling;
01389 const int absAdjCeiling = adjCeiling + z * CELL_HEIGHT;
01390 const int absFloor = RT_FLOOR(map, actorSize, x, y, z) + z * CELL_HEIGHT;
01391 const int absAdjFloor = RT_FLOOR(map, actorSize, ax, ay, z) + z * CELL_HEIGHT;
01392 opening_t opening;
01393 int new_z1, az = z;
01394 #if RT_IS_BIDIRECTIONAL == 1
01395 int new_z2;
01396 #endif
01397
01398 if (debugTrace)
01399 Com_Printf("\n(%i, %i, %i) to (%i, %i, %i) as:%i\n", x, y, z, ax, ay, z, actorSize);
01400
01401
01402 if (adjCeiling == 0 && (exadjCeiling == 0 || ceiling == 0)) {
01403
01404 RT_CONN(map, actorSize, x, y, z, dir) = 0;
01405 RT_STEPUP(map, actorSize, x, y, z, dir) = PATHFINDING_NO_STEPUP;
01406 #if RT_IS_BIDIRECTIONAL == 1
01407 RT_CONN(map, actorSize, ax, ay, z, dir ^ 1) = 0;
01408 RT_STEPUP(map, actorSize, ax, ay, z, dir ^ 1) = PATHFINDING_NO_STEPUP;
01409 #endif
01410 if (debugTrace)
01411 Com_Printf("Current cell filled. c:%i ac:%i\n", RT_CEILING(map, actorSize, x, y, z), RT_CEILING(map, actorSize, ax, ay, z));
01412 return z;
01413 }
01414
01415
01416 #if RT_IS_BIDIRECTIONAL == 1
01417 if (ceiling == 0 && adjCeiling != 0) {
01418 return RT_UpdateConnection(map, actorSize, ax, ay, x, y, z, dir ^ 1);
01419 }
01420 #endif
01421
01426 if (absCeiling < absAdjFloor || exabs_adj_ceiling < absFloor) {
01427
01428 RT_CONN(map, actorSize, x, y, z, dir) = 0;
01429 RT_STEPUP(map, actorSize, x, y, z, dir) = PATHFINDING_NO_STEPUP;
01430 #if RT_IS_BIDIRECTIONAL == 1
01431 RT_CONN(map, actorSize, ax, ay, z, dir ^ 1) = 0;
01432 RT_STEPUP(map, actorSize, ax, ay, z, dir ^ 1) = PATHFINDING_NO_STEPUP;
01433 #endif
01434 if (debugTrace)
01435 Com_Printf("Ceiling lower than floor. f:%i c:%i af:%i ac:%i\n", absFloor, absCeiling, absAdjFloor, absAdjCeiling);
01436 return z;
01437 }
01438
01439
01440 RT_TracePassage(mapTiles, map, actorSize, x, y, z, ax, ay, &opening, list);
01441 if (debugTrace) {
01442 Com_Printf("Final RT_STEPUP for (%i, %i, %i) as:%i dir:%i = %i\n", x, y, z, actorSize, dir, opening.stepup);
01443 }
01444
01445
01446 new_z1 = RT_FillPassageData(map, actorSize, dir, x, y, z, opening.size, opening.base, opening.stepup);
01447
01448 if (opening.stepup & PATHFINDING_BIG_STEPUP) {
01449
01450 #if RT_IS_BIDIRECTIONAL == 1
01451 RT_CONN(map, actorSize, ax, ay, z, dir ^ 1) = 0;
01452 RT_STEPUP(map, actorSize, ax, ay, z, dir ^ 1) = PATHFINDING_NO_STEPUP;
01453 #endif
01454 az++;
01455 } else if (opening.stepup & PATHFINDING_BIG_STEPDOWN) {
01456 az--;
01457 }
01458 #if RT_IS_BIDIRECTIONAL == 1
01459 new_z2 = RT_FillPassageData(map, actorSize, dir ^ 1, ax, ay, az, opening.size, opening.base, opening.invstepup);
01460 if (new_z2 == az && az < z)
01461 new_z2++;
01462 return min(new_z1, new_z2);
01463 #else
01464 return new_z1;
01465 #endif
01466 }
01467
01468
01477 void RT_UpdateConnectionColumn (mapTiles_t *mapTiles, routing_t * map, const int actorSize, const int x, const int y, const int dir, const char **list)
01478 {
01479 int z = 0;
01480 int new_z;
01482
01483 const int ax = x + dvecs[dir][0];
01484 const int ay = y + dvecs[dir][1];
01485
01486 assert(actorSize > ACTOR_SIZE_INVALID && actorSize <= ACTOR_MAX_SIZE);
01487 assert(map);
01488 assert((x >= 0) && (x <= PATHFINDING_WIDTH - actorSize));
01489 assert((y >= 0) && (y <= PATHFINDING_WIDTH - actorSize));
01490
01491
01492 if (x == 119 && y == 136 && dir == 2)
01493 new_z = 17;
01494
01495
01496 RT_CONN_TEST(map, actorSize, x, y, z, dir);
01497
01498
01499
01500
01501 if (ax < 0 || ax > PATHFINDING_WIDTH - actorSize || ay < 0 || y > PATHFINDING_WIDTH - actorSize) {
01502
01503 RT_CONN(map, actorSize, x, y, z, dir) = 0;
01504 RT_STEPUP(map, actorSize, x, y, z, dir) = PATHFINDING_NO_STEPUP;
01505
01506 if (debugTrace)
01507 Com_Printf("Destination cell non-existant.\n");
01508 return;
01509 }
01510
01511
01512 RT_CONN_TEST(map, actorSize, ax, ay, z, dir);
01513
01514
01515 for (z = 0; z < PATHFINDING_HEIGHT; z++) {
01516 new_z = RT_UpdateConnection(mapTiles, map, actorSize, x, y, ax, ay, z, dir, list);
01517 assert(new_z >= z);
01518 z = new_z;
01519 }
01520 }
01521
01522 void RT_WriteCSVFiles (const routing_t *map, const char* baseFilename, const ipos3_t mins, const ipos3_t maxs)
01523 {
01524 char filename[MAX_OSPATH], ext[MAX_OSPATH];
01525 qFILE f;
01526 int i, x, y, z;
01527
01528
01529 for (i = 1; i <= ACTOR_MAX_SIZE; i++) {
01530 strncpy(filename, baseFilename, sizeof(filename) - 1);
01531 sprintf(ext, ".%i.elevation.csv", i);
01532 Com_DefaultExtension(filename, sizeof(filename), ext);
01533 FS_OpenFile(filename, &f, FILE_WRITE);
01534 if (!f.f)
01535 Sys_Error("Could not open file %s.", filename);
01536 FS_Printf(&f, ",");
01537 for (x = mins[0]; x <= maxs[0] - i + 1; x++)
01538 FS_Printf(&f, "x:%i,", x);
01539 FS_Printf(&f, "\n");
01540 for (z = maxs[2]; z >= mins[2]; z--) {
01541 for (y = maxs[1]; y >= mins[1] - i + 1; y--) {
01542 FS_Printf(&f, "z:%i y:%i,", z ,y);
01543 for (x = mins[0]; x <= maxs[0] - i + 1; x++) {
01544
01545 FS_Printf(&f, "h:%i c:%i,", RT_FLOOR(map, i, x, y, z), RT_CEILING(map, i, x, y, z));
01546 }
01547 FS_Printf(&f, "\n");
01548 }
01549 FS_Printf(&f, "\n");
01550 }
01551 FS_CloseFile(&f);
01552 }
01553
01554
01555 for (i = 1; i <= ACTOR_MAX_SIZE; i++) {
01556 strncpy(filename, baseFilename, sizeof(filename) - 1);
01557 sprintf(ext, ".%i.walls.csv", i);
01558 Com_DefaultExtension(filename, sizeof(filename), ext);
01559 FS_OpenFile(filename, &f, FILE_WRITE);
01560 if (!f.f)
01561 Sys_Error("Could not open file %s.", filename);
01562 FS_Printf(&f, ",");
01563 for (x = mins[0]; x <= maxs[0] - i + 1; x++)
01564 FS_Printf(&f, "x:%i,", x);
01565 FS_Printf(&f, "\n");
01566 for (z = maxs[2]; z >= mins[2]; z--) {
01567 for (y = maxs[1]; y >= mins[1] - i + 1; y--) {
01568 FS_Printf(&f, "z:%i y:%i,", z ,y);
01569 for (x = mins[0]; x <= maxs[0] - i + 1; x++) {
01570
01571 FS_Printf(&f, "\"");
01572
01573
01574 FS_Printf(&f, "%3i-%3i ", RT_CONN_NX_PY(map, i, x, y, z), RT_STEPUP_NX_PY(map, i, x, y, z));
01575
01576
01577 FS_Printf(&f, "%3i-%3i ", RT_CONN_PY(map, i, x, y, z), RT_STEPUP_PY(map, i, x, y, z));
01578
01579
01580 FS_Printf(&f, "%3i-%3i ", RT_CONN_PX_PY(map, i, x, y, z), RT_STEPUP_PX_PY(map, i, x, y, z));
01581
01582 FS_Printf(&f, "\n");
01583
01584
01585 FS_Printf(&f, "%3i-%3i ", RT_CONN_NX(map, i, x, y, z), RT_STEPUP_NX(map, i, x, y, z));
01586
01587
01588 FS_Printf(&f, "_%+2i_ ", RT_FLOOR(map, i, x, y, z));
01589
01590
01591 FS_Printf(&f, "%3i-%3i ", RT_CONN_PX(map, i, x, y, z), RT_STEPUP_PX(map, i, x, y, z));
01592
01593 FS_Printf(&f, "\n");
01594
01595
01596 FS_Printf(&f, "%3i-%3i ", RT_CONN_NX_NY(map, i, x, y, z), RT_STEPUP_NX_NY(map, i, x, y, z));
01597
01598
01599 FS_Printf(&f, "%3i-%3i ", RT_CONN_NY(map, i, x, y, z), RT_STEPUP_NY(map, i, x, y, z));
01600
01601
01602 FS_Printf(&f, "%3i-%3i ", RT_CONN_PX_NY(map, i, x, y, z), RT_STEPUP_PX_NY(map, i, x, y, z));
01603
01604 FS_Printf(&f, "\",");
01605 }
01606 FS_Printf(&f, "\n");
01607 }
01608 FS_Printf(&f, "\n");
01609 }
01610 FS_CloseFile(&f);
01611 }
01612 }