2
===========================================================================
3
Copyright (C) 1999-2005 Id Software, Inc.
5
This file is part of Quake III Arena source code.
7
Quake III Arena source code is free software; you can redistribute it
8
and/or modify it under the terms of the GNU General Public License as
9
published by the Free Software Foundation; either version 2 of the License,
10
or (at your option) any later version.
12
Quake III Arena source code is distributed in the hope that it will be
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with Quake III Arena source code; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
===========================================================================
23
/*****************************************************************************
24
* name: be_aas_debug.c
26
* desc: AAS debug code
28
* $Archive: /MissionPack/code/botlib/be_aas_debug.c $
30
*****************************************************************************/
32
#include "../qcommon/q_shared.h"
35
#include "l_precomp.h"
41
#include "be_interface.h"
42
#include "be_aas_funcs.h"
43
#include "be_aas_def.h"
45
#define MAX_DEBUGLINES 1024
46
#define MAX_DEBUGPOLYGONS 8192
48
int debuglines[MAX_DEBUGLINES];
49
int debuglinevisible[MAX_DEBUGLINES];
52
static int debugpolygons[MAX_DEBUGPOLYGONS];
54
//===========================================================================
59
//===========================================================================
60
void AAS_ClearShownPolygons(void)
64
for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
66
if (debugpolygons[i]) botimport.DebugPolygonDelete(debugpolygons[i]);
71
for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
73
botimport.DebugPolygonDelete(i);
77
} //end of the function AAS_ClearShownPolygons
78
//===========================================================================
83
//===========================================================================
84
void AAS_ShowPolygon(int color, int numpoints, vec3_t *points)
88
for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
90
if (!debugpolygons[i])
92
debugpolygons[i] = botimport.DebugPolygonCreate(color, numpoints, points);
96
} //end of the function AAS_ShowPolygon
97
//===========================================================================
101
// Changes Globals: -
102
//===========================================================================
103
void AAS_ClearShownDebugLines(void)
107
//make all lines invisible
108
for (i = 0; i < MAX_DEBUGLINES; i++)
112
//botimport.DebugLineShow(debuglines[i], NULL, NULL, LINECOLOR_NONE);
113
botimport.DebugLineDelete(debuglines[i]);
115
debuglinevisible[i] = qfalse;
118
} //end of the function AAS_ClearShownDebugLines
119
//===========================================================================
123
// Changes Globals: -
124
//===========================================================================
125
void AAS_DebugLine(vec3_t start, vec3_t end, int color)
129
for (line = 0; line < MAX_DEBUGLINES; line++)
131
if (!debuglines[line])
133
debuglines[line] = botimport.DebugLineCreate();
134
debuglinevisible[line] = qfalse;
137
if (!debuglinevisible[line])
139
botimport.DebugLineShow(debuglines[line], start, end, color);
140
debuglinevisible[line] = qtrue;
144
} //end of the function AAS_DebugLine
145
//===========================================================================
149
// Changes Globals: -
150
//===========================================================================
151
void AAS_PermanentLine(vec3_t start, vec3_t end, int color)
155
line = botimport.DebugLineCreate();
156
botimport.DebugLineShow(line, start, end, color);
157
} //end of the function AAS_PermenentLine
158
//===========================================================================
162
// Changes Globals: -
163
//===========================================================================
164
void AAS_DrawPermanentCross(vec3_t origin, float size, int color)
169
for (i = 0; i < 3; i++)
171
VectorCopy(origin, start);
173
VectorCopy(origin, end);
175
AAS_DebugLine(start, end, color);
176
debugline = botimport.DebugLineCreate();
177
botimport.DebugLineShow(debugline, start, end, color);
179
} //end of the function AAS_DrawPermanentCross
180
//===========================================================================
184
// Changes Globals: -
185
//===========================================================================
186
void AAS_DrawPlaneCross(vec3_t point, vec3_t normal, float dist, int type, int color)
188
int n0, n1, n2, j, line, lines[2];
189
vec3_t start1, end1, start2, end2;
191
//make a cross in the hit plane at the hit point
192
VectorCopy(point, start1);
193
VectorCopy(point, end1);
194
VectorCopy(point, start2);
195
VectorCopy(point, end2);
209
start1[n0] = (dist - (start1[n1] * normal[n1] +
210
start1[n2] * normal[n2])) / normal[n0];
211
end1[n0] = (dist - (end1[n1] * normal[n1] +
212
end1[n2] * normal[n2])) / normal[n0];
213
start2[n0] = (dist - (start2[n1] * normal[n1] +
214
start2[n2] * normal[n2])) / normal[n0];
215
end2[n0] = (dist - (end2[n1] * normal[n1] +
216
end2[n2] * normal[n2])) / normal[n0];
218
for (j = 0, line = 0; j < 2 && line < MAX_DEBUGLINES; line++)
220
if (!debuglines[line])
222
debuglines[line] = botimport.DebugLineCreate();
223
lines[j++] = debuglines[line];
224
debuglinevisible[line] = qtrue;
227
else if (!debuglinevisible[line])
229
lines[j++] = debuglines[line];
230
debuglinevisible[line] = qtrue;
233
botimport.DebugLineShow(lines[0], start1, end1, color);
234
botimport.DebugLineShow(lines[1], start2, end2, color);
235
} //end of the function AAS_DrawPlaneCross
236
//===========================================================================
240
// Changes Globals: -
241
//===========================================================================
242
void AAS_ShowBoundingBox(vec3_t origin, vec3_t mins, vec3_t maxs)
244
vec3_t bboxcorners[8];
249
bboxcorners[0][0] = origin[0] + maxs[0];
250
bboxcorners[0][1] = origin[1] + maxs[1];
251
bboxcorners[0][2] = origin[2] + maxs[2];
253
bboxcorners[1][0] = origin[0] + mins[0];
254
bboxcorners[1][1] = origin[1] + maxs[1];
255
bboxcorners[1][2] = origin[2] + maxs[2];
257
bboxcorners[2][0] = origin[0] + mins[0];
258
bboxcorners[2][1] = origin[1] + mins[1];
259
bboxcorners[2][2] = origin[2] + maxs[2];
261
bboxcorners[3][0] = origin[0] + maxs[0];
262
bboxcorners[3][1] = origin[1] + mins[1];
263
bboxcorners[3][2] = origin[2] + maxs[2];
265
Com_Memcpy(bboxcorners[4], bboxcorners[0], sizeof(vec3_t) * 4);
266
for (i = 0; i < 4; i++) bboxcorners[4 + i][2] = origin[2] + mins[2];
268
for (i = 0; i < 4; i++)
270
for (j = 0, line = 0; j < 3 && line < MAX_DEBUGLINES; line++)
272
if (!debuglines[line])
274
debuglines[line] = botimport.DebugLineCreate();
275
lines[j++] = debuglines[line];
276
debuglinevisible[line] = qtrue;
279
else if (!debuglinevisible[line])
281
lines[j++] = debuglines[line];
282
debuglinevisible[line] = qtrue;
286
botimport.DebugLineShow(lines[0], bboxcorners[i],
287
bboxcorners[(i+1)&3], LINECOLOR_RED);
289
botimport.DebugLineShow(lines[1], bboxcorners[4+i],
290
bboxcorners[4+((i+1)&3)], LINECOLOR_RED);
292
botimport.DebugLineShow(lines[2], bboxcorners[i],
293
bboxcorners[4+i], LINECOLOR_RED);
295
} //end of the function AAS_ShowBoundingBox
296
//===========================================================================
300
// Changes Globals: -
301
//===========================================================================
302
void AAS_ShowFace(int facenum)
304
int i, color, edgenum;
310
color = LINECOLOR_YELLOW;
311
//check if face number is in range
312
if (facenum >= aasworld.numfaces)
314
botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
316
face = &aasworld.faces[facenum];
317
//walk through the edges of the face
318
for (i = 0; i < face->numedges; i++)
321
edgenum = abs(aasworld.edgeindex[face->firstedge + i]);
322
//check if edge number is in range
323
if (edgenum >= aasworld.numedges)
325
botimport.Print(PRT_ERROR, "edgenum %d out of range\n", edgenum);
327
edge = &aasworld.edges[edgenum];
328
if (color == LINECOLOR_RED) color = LINECOLOR_GREEN;
329
else if (color == LINECOLOR_GREEN) color = LINECOLOR_BLUE;
330
else if (color == LINECOLOR_BLUE) color = LINECOLOR_YELLOW;
331
else color = LINECOLOR_RED;
332
AAS_DebugLine(aasworld.vertexes[edge->v[0]],
333
aasworld.vertexes[edge->v[1]],
336
plane = &aasworld.planes[face->planenum];
337
edgenum = abs(aasworld.edgeindex[face->firstedge]);
338
edge = &aasworld.edges[edgenum];
339
VectorCopy(aasworld.vertexes[edge->v[0]], start);
340
VectorMA(start, 20, plane->normal, end);
341
AAS_DebugLine(start, end, LINECOLOR_RED);
342
} //end of the function AAS_ShowFace
343
//===========================================================================
347
// Changes Globals: -
348
//===========================================================================
349
void AAS_ShowFacePolygon(int facenum, int color, int flip)
351
int i, edgenum, numpoints;
356
//check if face number is in range
357
if (facenum >= aasworld.numfaces)
359
botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
361
face = &aasworld.faces[facenum];
362
//walk through the edges of the face
366
for (i = face->numedges-1; i >= 0; i--)
369
edgenum = aasworld.edgeindex[face->firstedge + i];
370
edge = &aasworld.edges[abs(edgenum)];
371
VectorCopy(aasworld.vertexes[edge->v[edgenum < 0]], points[numpoints]);
377
for (i = 0; i < face->numedges; i++)
380
edgenum = aasworld.edgeindex[face->firstedge + i];
381
edge = &aasworld.edges[abs(edgenum)];
382
VectorCopy(aasworld.vertexes[edge->v[edgenum < 0]], points[numpoints]);
386
AAS_ShowPolygon(color, numpoints, points);
387
} //end of the function AAS_ShowFacePolygon
388
//===========================================================================
392
// Changes Globals: -
393
//===========================================================================
394
void AAS_ShowArea(int areanum, int groundfacesonly)
396
int areaedges[MAX_DEBUGLINES];
397
int numareaedges, i, j, n, color = 0, line;
398
int facenum, edgenum;
406
if (areanum < 0 || areanum >= aasworld.numareas)
408
botimport.Print(PRT_ERROR, "area %d out of range [0, %d]\n",
409
areanum, aasworld.numareas);
412
//pointer to the convex area
413
area = &aasworld.areas[areanum];
414
//walk through the faces of the area
415
for (i = 0; i < area->numfaces; i++)
417
facenum = abs(aasworld.faceindex[area->firstface + i]);
418
//check if face number is in range
419
if (facenum >= aasworld.numfaces)
421
botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
423
face = &aasworld.faces[facenum];
427
if (!(face->faceflags & (FACE_GROUND | FACE_LADDER))) continue;
429
//walk through the edges of the face
430
for (j = 0; j < face->numedges; j++)
433
edgenum = abs(aasworld.edgeindex[face->firstedge + j]);
434
//check if edge number is in range
435
if (edgenum >= aasworld.numedges)
437
botimport.Print(PRT_ERROR, "edgenum %d out of range\n", edgenum);
439
//check if the edge is stored already
440
for (n = 0; n < numareaedges; n++)
442
if (areaedges[n] == edgenum) break;
444
if (n == numareaedges && numareaedges < MAX_DEBUGLINES)
446
areaedges[numareaedges++] = edgenum;
449
//AAS_ShowFace(facenum);
452
for (n = 0; n < numareaedges; n++)
454
for (line = 0; line < MAX_DEBUGLINES; line++)
456
if (!debuglines[line])
458
debuglines[line] = botimport.DebugLineCreate();
459
debuglinevisible[line] = qfalse;
462
if (!debuglinevisible[line])
467
if (line >= MAX_DEBUGLINES) return;
468
edge = &aasworld.edges[areaedges[n]];
469
if (color == LINECOLOR_RED) color = LINECOLOR_BLUE;
470
else if (color == LINECOLOR_BLUE) color = LINECOLOR_GREEN;
471
else if (color == LINECOLOR_GREEN) color = LINECOLOR_YELLOW;
472
else color = LINECOLOR_RED;
473
botimport.DebugLineShow(debuglines[line],
474
aasworld.vertexes[edge->v[0]],
475
aasworld.vertexes[edge->v[1]],
477
debuglinevisible[line] = qtrue;
479
} //end of the function AAS_ShowArea
480
//===========================================================================
484
// Changes Globals: -
485
//===========================================================================
486
void AAS_ShowAreaPolygons(int areanum, int color, int groundfacesonly)
493
if (areanum < 0 || areanum >= aasworld.numareas)
495
botimport.Print(PRT_ERROR, "area %d out of range [0, %d]\n",
496
areanum, aasworld.numareas);
499
//pointer to the convex area
500
area = &aasworld.areas[areanum];
501
//walk through the faces of the area
502
for (i = 0; i < area->numfaces; i++)
504
facenum = abs(aasworld.faceindex[area->firstface + i]);
505
//check if face number is in range
506
if (facenum >= aasworld.numfaces)
508
botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
510
face = &aasworld.faces[facenum];
514
if (!(face->faceflags & (FACE_GROUND | FACE_LADDER))) continue;
516
AAS_ShowFacePolygon(facenum, color, face->frontarea != areanum);
518
} //end of the function AAS_ShowAreaPolygons
519
//===========================================================================
523
// Changes Globals: -
524
//===========================================================================
525
void AAS_DrawCross(vec3_t origin, float size, int color)
530
for (i = 0; i < 3; i++)
532
VectorCopy(origin, start);
534
VectorCopy(origin, end);
536
AAS_DebugLine(start, end, color);
538
} //end of the function AAS_DrawCross
539
//===========================================================================
543
// Changes Globals: -
544
//===========================================================================
545
void AAS_PrintTravelType(int traveltype)
550
switch(traveltype & TRAVELTYPE_MASK)
552
case TRAVEL_INVALID: str = "TRAVEL_INVALID"; break;
553
case TRAVEL_WALK: str = "TRAVEL_WALK"; break;
554
case TRAVEL_CROUCH: str = "TRAVEL_CROUCH"; break;
555
case TRAVEL_BARRIERJUMP: str = "TRAVEL_BARRIERJUMP"; break;
556
case TRAVEL_JUMP: str = "TRAVEL_JUMP"; break;
557
case TRAVEL_LADDER: str = "TRAVEL_LADDER"; break;
558
case TRAVEL_WALKOFFLEDGE: str = "TRAVEL_WALKOFFLEDGE"; break;
559
case TRAVEL_SWIM: str = "TRAVEL_SWIM"; break;
560
case TRAVEL_WATERJUMP: str = "TRAVEL_WATERJUMP"; break;
561
case TRAVEL_TELEPORT: str = "TRAVEL_TELEPORT"; break;
562
case TRAVEL_ELEVATOR: str = "TRAVEL_ELEVATOR"; break;
563
case TRAVEL_ROCKETJUMP: str = "TRAVEL_ROCKETJUMP"; break;
564
case TRAVEL_BFGJUMP: str = "TRAVEL_BFGJUMP"; break;
565
case TRAVEL_GRAPPLEHOOK: str = "TRAVEL_GRAPPLEHOOK"; break;
566
case TRAVEL_JUMPPAD: str = "TRAVEL_JUMPPAD"; break;
567
case TRAVEL_FUNCBOB: str = "TRAVEL_FUNCBOB"; break;
568
default: str = "UNKNOWN TRAVEL TYPE"; break;
570
botimport.Print(PRT_MESSAGE, "%s", str);
572
} //end of the function AAS_PrintTravelType
573
//===========================================================================
577
// Changes Globals: -
578
//===========================================================================
579
void AAS_DrawArrow(vec3_t start, vec3_t end, int linecolor, int arrowcolor)
581
vec3_t dir, cross, p1, p2, up = {0, 0, 1};
584
VectorSubtract(end, start, dir);
585
VectorNormalize(dir);
586
dot = DotProduct(dir, up);
587
if (dot > 0.99 || dot < -0.99) VectorSet(cross, 1, 0, 0);
588
else CrossProduct(dir, up, cross);
590
VectorMA(end, -6, dir, p1);
592
VectorMA(p1, 6, cross, p1);
593
VectorMA(p2, -6, cross, p2);
595
AAS_DebugLine(start, end, linecolor);
596
AAS_DebugLine(p1, end, arrowcolor);
597
AAS_DebugLine(p2, end, arrowcolor);
598
} //end of the function AAS_DrawArrow
599
//===========================================================================
603
// Changes Globals: -
604
//===========================================================================
605
void AAS_ShowReachability(aas_reachability_t *reach)
607
vec3_t dir, cmdmove, velocity;
609
aas_clientmove_t move;
611
AAS_ShowAreaPolygons(reach->areanum, 5, qtrue);
612
//AAS_ShowArea(reach->areanum, qtrue);
613
AAS_DrawArrow(reach->start, reach->end, LINECOLOR_BLUE, LINECOLOR_YELLOW);
615
if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP ||
616
(reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
618
AAS_HorizontalVelocityForJump(aassettings.phys_jumpvel, reach->start, reach->end, &speed);
620
VectorSubtract(reach->end, reach->start, dir);
622
VectorNormalize(dir);
624
VectorScale(dir, speed, velocity);
625
//set the command movement
626
VectorClear(cmdmove);
627
cmdmove[2] = aassettings.phys_jumpvel;
629
AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
630
velocity, cmdmove, 3, 30, 0.1f,
631
SE_HITGROUND|SE_ENTERWATER|SE_ENTERSLIME|
632
SE_ENTERLAVA|SE_HITGROUNDDAMAGE, 0, qtrue);
634
if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP)
636
AAS_JumpReachRunStart(reach, dir);
637
AAS_DrawCross(dir, 4, LINECOLOR_BLUE);
640
else if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_ROCKETJUMP)
642
zvel = AAS_RocketJumpZVelocity(reach->start);
643
AAS_HorizontalVelocityForJump(zvel, reach->start, reach->end, &speed);
645
VectorSubtract(reach->end, reach->start, dir);
647
VectorNormalize(dir);
648
//get command movement
649
VectorScale(dir, speed, cmdmove);
650
VectorSet(velocity, 0, 0, zvel);
652
AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
653
velocity, cmdmove, 30, 30, 0.1f,
654
SE_ENTERWATER|SE_ENTERSLIME|
655
SE_ENTERLAVA|SE_HITGROUNDDAMAGE|
656
SE_TOUCHJUMPPAD|SE_HITGROUNDAREA, reach->areanum, qtrue);
658
else if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMPPAD)
660
VectorSet(cmdmove, 0, 0, 0);
662
VectorSubtract(reach->end, reach->start, dir);
664
VectorNormalize(dir);
666
//NOTE: the edgenum is the horizontal velocity
667
VectorScale(dir, reach->edgenum, velocity);
668
//NOTE: the facenum is the Z velocity
669
velocity[2] = reach->facenum;
671
AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
672
velocity, cmdmove, 30, 30, 0.1f,
673
SE_ENTERWATER|SE_ENTERSLIME|
674
SE_ENTERLAVA|SE_HITGROUNDDAMAGE|
675
SE_TOUCHJUMPPAD|SE_HITGROUNDAREA, reach->areanum, qtrue);
677
} //end of the function AAS_ShowReachability
678
//===========================================================================
682
// Changes Globals: -
683
//===========================================================================
684
void AAS_ShowReachableAreas(int areanum)
686
aas_areasettings_t *settings;
687
static aas_reachability_t reach;
688
static int index, lastareanum;
689
static float lasttime;
691
if (areanum != lastareanum)
694
lastareanum = areanum;
696
settings = &aasworld.areasettings[areanum];
698
if (!settings->numreachableareas) return;
700
if (index >= settings->numreachableareas) index = 0;
702
if (AAS_Time() - lasttime > 1.5)
704
Com_Memcpy(&reach, &aasworld.reachability[settings->firstreachablearea + index], sizeof(aas_reachability_t));
706
lasttime = AAS_Time();
707
AAS_PrintTravelType(reach.traveltype & TRAVELTYPE_MASK);
708
botimport.Print(PRT_MESSAGE, "\n");
710
AAS_ShowReachability(&reach);
711
} //end of the function ShowReachableAreas
713
void AAS_FloodAreas_r(int areanum, int cluster, int *done)
715
int nextareanum, i, facenum;
718
aas_areasettings_t *settings;
719
aas_reachability_t *reach;
721
AAS_ShowAreaPolygons(areanum, 1, qtrue);
722
//pointer to the convex area
723
area = &aasworld.areas[areanum];
724
settings = &aasworld.areasettings[areanum];
725
//walk through the faces of the area
726
for (i = 0; i < area->numfaces; i++)
728
facenum = abs(aasworld.faceindex[area->firstface + i]);
729
face = &aasworld.faces[facenum];
730
if (face->frontarea == areanum)
731
nextareanum = face->backarea;
733
nextareanum = face->frontarea;
736
if (done[nextareanum])
738
done[nextareanum] = qtrue;
739
if (aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
741
if (AAS_AreaCluster(nextareanum) != cluster)
743
AAS_FloodAreas_r(nextareanum, cluster, done);
746
for (i = 0; i < settings->numreachableareas; i++)
748
reach = &aasworld.reachability[settings->firstreachablearea + i];
749
nextareanum = reach->areanum;
752
if (done[nextareanum])
754
done[nextareanum] = qtrue;
755
if (aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
757
if (AAS_AreaCluster(nextareanum) != cluster)
760
if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
762
AAS_DebugLine(reach->start, reach->end, 1);
765
AAS_FloodAreas_r(nextareanum, cluster, done);
769
void AAS_FloodAreas(vec3_t origin)
771
int areanum, cluster, *done;
773
done = (int *) GetClearedMemory(aasworld.numareas * sizeof(int));
774
areanum = AAS_PointAreaNum(origin);
775
cluster = AAS_AreaCluster(areanum);
776
AAS_FloodAreas_r(areanum, cluster, done);