AAS_debug.cpp (13902B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #pragma hdrstop 30 #include "../../idlib/precompiled.h" 31 32 #include "AAS_local.h" 33 #include "../Game_local.h" // for cvars and debug drawing 34 35 36 /* 37 ============ 38 idAASLocal::DrawCone 39 ============ 40 */ 41 void idAASLocal::DrawCone( const idVec3 &origin, const idVec3 &dir, float radius, const idVec4 &color ) const { 42 int i; 43 idMat3 axis; 44 idVec3 center, top, p, lastp; 45 46 axis[2] = dir; 47 axis[2].NormalVectors( axis[0], axis[1] ); 48 axis[1] = -axis[1]; 49 50 center = origin + dir; 51 top = center + dir * (3.0f * radius); 52 lastp = center + radius * axis[1]; 53 54 for ( i = 20; i <= 360; i += 20 ) { 55 p = center + sin( DEG2RAD(i) ) * radius * axis[0] + cos( DEG2RAD(i) ) * radius * axis[1]; 56 gameRenderWorld->DebugLine( color, lastp, p, 0 ); 57 gameRenderWorld->DebugLine( color, p, top, 0 ); 58 lastp = p; 59 } 60 } 61 62 /* 63 ============ 64 idAASLocal::DrawReachability 65 ============ 66 */ 67 void idAASLocal::DrawReachability( const idReachability *reach ) const { 68 gameRenderWorld->DebugArrow( colorCyan, reach->start, reach->end, 2 ); 69 70 if ( gameLocal.GetLocalPlayer() ) { 71 gameRenderWorld->DrawText( va( "%d", reach->edgeNum ), ( reach->start + reach->end ) * 0.5f, 0.1f, colorWhite, gameLocal.GetLocalPlayer()->viewAxis ); 72 } 73 74 switch( reach->travelType ) { 75 case TFL_WALK: { 76 //const idReachability_Walk *walk = static_cast<const idReachability_Walk *>(reach); 77 break; 78 } 79 default: { 80 break; 81 } 82 } 83 } 84 85 /* 86 ============ 87 idAASLocal::DrawEdge 88 ============ 89 */ 90 void idAASLocal::DrawEdge( int edgeNum, bool arrow ) const { 91 const aasEdge_t *edge; 92 idVec4 *color; 93 94 if ( !file ) { 95 return; 96 } 97 98 edge = &file->GetEdge( edgeNum ); 99 color = &colorRed; 100 if ( arrow ) { 101 gameRenderWorld->DebugArrow( *color, file->GetVertex( edge->vertexNum[0] ), file->GetVertex( edge->vertexNum[1] ), 1 ); 102 } else { 103 gameRenderWorld->DebugLine( *color, file->GetVertex( edge->vertexNum[0] ), file->GetVertex( edge->vertexNum[1] ) ); 104 } 105 106 if ( gameLocal.GetLocalPlayer() ) { 107 gameRenderWorld->DrawText( va( "%d", edgeNum ), ( file->GetVertex( edge->vertexNum[0] ) + file->GetVertex( edge->vertexNum[1] ) ) * 0.5f + idVec3(0,0,4), 0.1f, colorRed, gameLocal.GetLocalPlayer()->viewAxis ); 108 } 109 } 110 111 /* 112 ============ 113 idAASLocal::DrawFace 114 ============ 115 */ 116 void idAASLocal::DrawFace( int faceNum, bool side ) const { 117 int i, j, numEdges, firstEdge; 118 const aasFace_t *face; 119 idVec3 mid, end; 120 121 if ( !file ) { 122 return; 123 } 124 125 face = &file->GetFace( faceNum ); 126 numEdges = face->numEdges; 127 firstEdge = face->firstEdge; 128 129 mid = vec3_origin; 130 for ( i = 0; i < numEdges; i++ ) { 131 DrawEdge( abs( file->GetEdgeIndex( firstEdge + i ) ), ( face->flags & FACE_FLOOR ) != 0 ); 132 j = file->GetEdgeIndex( firstEdge + i ); 133 mid += file->GetVertex( file->GetEdge( abs( j ) ).vertexNum[ j < 0 ] ); 134 } 135 136 mid /= numEdges; 137 if ( side ) { 138 end = mid - 5.0f * file->GetPlane( file->GetFace( faceNum ).planeNum ).Normal(); 139 } else { 140 end = mid + 5.0f * file->GetPlane( file->GetFace( faceNum ).planeNum ).Normal(); 141 } 142 gameRenderWorld->DebugArrow( colorGreen, mid, end, 1 ); 143 } 144 145 /* 146 ============ 147 idAASLocal::DrawArea 148 ============ 149 */ 150 void idAASLocal::DrawArea( int areaNum ) const { 151 int i, numFaces, firstFace; 152 const aasArea_t *area; 153 idReachability *reach; 154 155 if ( !file ) { 156 return; 157 } 158 159 area = &file->GetArea( areaNum ); 160 numFaces = area->numFaces; 161 firstFace = area->firstFace; 162 163 for ( i = 0; i < numFaces; i++ ) { 164 DrawFace( abs( file->GetFaceIndex( firstFace + i ) ), file->GetFaceIndex( firstFace + i ) < 0 ); 165 } 166 167 for ( reach = area->reach; reach; reach = reach->next ) { 168 DrawReachability( reach ); 169 } 170 } 171 172 /* 173 ============ 174 idAASLocal::DefaultSearchBounds 175 ============ 176 */ 177 const idBounds &idAASLocal::DefaultSearchBounds() const { 178 return file->GetSettings().boundingBoxes[0]; 179 } 180 181 /* 182 ============ 183 idAASLocal::ShowArea 184 ============ 185 */ 186 void idAASLocal::ShowArea( const idVec3 &origin ) const { 187 static int lastAreaNum; 188 int areaNum; 189 const aasArea_t *area; 190 idVec3 org; 191 192 areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) ); 193 org = origin; 194 PushPointIntoAreaNum( areaNum, org ); 195 196 if ( aas_goalArea.GetInteger() ) { 197 int travelTime; 198 idReachability *reach; 199 200 RouteToGoalArea( areaNum, org, aas_goalArea.GetInteger(), TFL_WALK|TFL_AIR, travelTime, &reach ); 201 gameLocal.Printf( "\rtt = %4d", travelTime ); 202 if ( reach ) { 203 gameLocal.Printf( " to area %4d", reach->toAreaNum ); 204 DrawArea( reach->toAreaNum ); 205 } 206 } 207 208 if ( areaNum != lastAreaNum ) { 209 area = &file->GetArea( areaNum ); 210 gameLocal.Printf( "area %d: ", areaNum ); 211 if ( area->flags & AREA_LEDGE ) { 212 gameLocal.Printf( "AREA_LEDGE " ); 213 } 214 if ( area->flags & AREA_REACHABLE_WALK ) { 215 gameLocal.Printf( "AREA_REACHABLE_WALK " ); 216 } 217 if ( area->flags & AREA_REACHABLE_FLY ) { 218 gameLocal.Printf( "AREA_REACHABLE_FLY " ); 219 } 220 if ( area->contents & AREACONTENTS_CLUSTERPORTAL ) { 221 gameLocal.Printf( "AREACONTENTS_CLUSTERPORTAL " ); 222 } 223 if ( area->contents & AREACONTENTS_OBSTACLE ) { 224 gameLocal.Printf( "AREACONTENTS_OBSTACLE " ); 225 } 226 gameLocal.Printf( "\n" ); 227 lastAreaNum = areaNum; 228 } 229 230 if ( org != origin ) { 231 idBounds bnds = file->GetSettings().boundingBoxes[ 0 ]; 232 bnds[ 1 ].z = bnds[ 0 ].z; 233 gameRenderWorld->DebugBounds( colorYellow, bnds, org ); 234 } 235 236 DrawArea( areaNum ); 237 } 238 239 /* 240 ============ 241 idAASLocal::ShowWalkPath 242 ============ 243 */ 244 void idAASLocal::ShowWalkPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const { 245 int i, areaNum, curAreaNum, travelTime; 246 idReachability *reach; 247 idVec3 org, areaCenter; 248 aasPath_t path; 249 250 if ( !file ) { 251 return; 252 } 253 254 org = origin; 255 areaNum = PointReachableAreaNum( org, DefaultSearchBounds(), AREA_REACHABLE_WALK ); 256 PushPointIntoAreaNum( areaNum, org ); 257 curAreaNum = areaNum; 258 259 for ( i = 0; i < 100; i++ ) { 260 261 if ( !RouteToGoalArea( curAreaNum, org, goalAreaNum, TFL_WALK|TFL_AIR, travelTime, &reach ) ) { 262 break; 263 } 264 265 if ( !reach ) { 266 break; 267 } 268 269 gameRenderWorld->DebugArrow( colorGreen, org, reach->start, 2 ); 270 DrawReachability( reach ); 271 272 if ( reach->toAreaNum == goalAreaNum ) { 273 break; 274 } 275 276 curAreaNum = reach->toAreaNum; 277 org = reach->end; 278 } 279 280 if ( WalkPathToGoal( path, areaNum, origin, goalAreaNum, goalOrigin, TFL_WALK|TFL_AIR ) ) { 281 gameRenderWorld->DebugArrow( colorBlue, origin, path.moveGoal, 2 ); 282 } 283 } 284 285 /* 286 ============ 287 idAASLocal::ShowFlyPath 288 ============ 289 */ 290 void idAASLocal::ShowFlyPath( const idVec3 &origin, int goalAreaNum, const idVec3 &goalOrigin ) const { 291 int i, areaNum, curAreaNum, travelTime; 292 idReachability *reach; 293 idVec3 org, areaCenter; 294 aasPath_t path; 295 296 if ( !file ) { 297 return; 298 } 299 300 org = origin; 301 areaNum = PointReachableAreaNum( org, DefaultSearchBounds(), AREA_REACHABLE_FLY ); 302 PushPointIntoAreaNum( areaNum, org ); 303 curAreaNum = areaNum; 304 305 for ( i = 0; i < 100; i++ ) { 306 307 if ( !RouteToGoalArea( curAreaNum, org, goalAreaNum, TFL_WALK|TFL_FLY|TFL_AIR, travelTime, &reach ) ) { 308 break; 309 } 310 311 if ( !reach ) { 312 break; 313 } 314 315 gameRenderWorld->DebugArrow( colorPurple, org, reach->start, 2 ); 316 DrawReachability( reach ); 317 318 if ( reach->toAreaNum == goalAreaNum ) { 319 break; 320 } 321 322 curAreaNum = reach->toAreaNum; 323 org = reach->end; 324 } 325 326 if ( FlyPathToGoal( path, areaNum, origin, goalAreaNum, goalOrigin, TFL_WALK|TFL_FLY|TFL_AIR ) ) { 327 gameRenderWorld->DebugArrow( colorBlue, origin, path.moveGoal, 2 ); 328 } 329 } 330 331 /* 332 ============ 333 idAASLocal::ShowWallEdges 334 ============ 335 */ 336 void idAASLocal::ShowWallEdges( const idVec3 &origin ) const { 337 int i, areaNum, numEdges, edges[1024]; 338 idVec3 start, end; 339 idPlayer *player; 340 341 player = gameLocal.GetLocalPlayer(); 342 if ( !player ) { 343 return; 344 } 345 346 areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) ); 347 numEdges = GetWallEdges( areaNum, idBounds( origin ).Expand( 256.0f ), TFL_WALK, edges, 1024 ); 348 for ( i = 0; i < numEdges; i++ ) { 349 GetEdge( edges[i], start, end ); 350 gameRenderWorld->DebugLine( colorRed, start, end ); 351 gameRenderWorld->DrawText( va( "%d", edges[i] ), ( start + end ) * 0.5f, 0.1f, colorWhite, player->viewAxis ); 352 } 353 } 354 355 /* 356 ============ 357 idAASLocal::ShowHideArea 358 ============ 359 */ 360 void idAASLocal::ShowHideArea( const idVec3 &origin, int targetAreaNum ) const { 361 int areaNum, numObstacles; 362 idVec3 target; 363 aasGoal_t goal; 364 aasObstacle_t obstacles[10]; 365 366 areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) ); 367 target = AreaCenter( targetAreaNum ); 368 369 // consider the target an obstacle 370 obstacles[0].absBounds = idBounds( target ).Expand( 16 ); 371 numObstacles = 1; 372 373 DrawCone( target, idVec3(0,0,1), 16.0f, colorYellow ); 374 375 idAASFindCover findCover( target ); 376 if ( FindNearestGoal( goal, areaNum, origin, target, TFL_WALK|TFL_AIR, obstacles, numObstacles, findCover ) ) { 377 DrawArea( goal.areaNum ); 378 ShowWalkPath( origin, goal.areaNum, goal.origin ); 379 DrawCone( goal.origin, idVec3(0,0,1), 16.0f, colorWhite ); 380 } 381 } 382 383 /* 384 ============ 385 idAASLocal::PullPlayer 386 ============ 387 */ 388 bool idAASLocal::PullPlayer( const idVec3 &origin, int toAreaNum ) const { 389 int areaNum; 390 idVec3 areaCenter, dir, vel; 391 idAngles delta; 392 aasPath_t path; 393 idPlayer *player; 394 395 player = gameLocal.GetLocalPlayer(); 396 if ( !player ) { 397 return true; 398 } 399 400 idPhysics *physics = player->GetPhysics(); 401 if ( !physics ) { 402 return true; 403 } 404 405 if ( !toAreaNum ) { 406 return false; 407 } 408 409 areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) ); 410 areaCenter = AreaCenter( toAreaNum ); 411 if ( player->GetPhysics()->GetAbsBounds().Expand( 8 ).ContainsPoint( areaCenter ) ) { 412 return false; 413 } 414 if ( WalkPathToGoal( path, areaNum, origin, toAreaNum, areaCenter, TFL_WALK|TFL_AIR ) ) { 415 dir = path.moveGoal - origin; 416 dir[2] *= 0.5f; 417 dir.Normalize(); 418 delta = dir.ToAngles() - player->cmdAngles - player->GetDeltaViewAngles(); 419 delta.Normalize180(); 420 player->SetDeltaViewAngles( player->GetDeltaViewAngles() + delta * 0.1f ); 421 dir[2] = 0.0f; 422 dir.Normalize(); 423 dir *= 100.0f; 424 vel = physics->GetLinearVelocity(); 425 dir[2] = vel[2]; 426 physics->SetLinearVelocity( dir ); 427 return true; 428 } 429 else { 430 return false; 431 } 432 } 433 434 /* 435 ============ 436 idAASLocal::RandomPullPlayer 437 ============ 438 */ 439 void idAASLocal::RandomPullPlayer( const idVec3 &origin ) const { 440 int rnd, i, n; 441 442 if ( !PullPlayer( origin, aas_pullPlayer.GetInteger() ) ) { 443 444 rnd = gameLocal.random.RandomFloat() * file->GetNumAreas(); 445 446 for ( i = 0; i < file->GetNumAreas(); i++ ) { 447 n = (rnd + i) % file->GetNumAreas(); 448 if ( file->GetArea( n ).flags & (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) ) { 449 aas_pullPlayer.SetInteger( n ); 450 } 451 } 452 } else { 453 ShowWalkPath( origin, aas_pullPlayer.GetInteger(), AreaCenter( aas_pullPlayer.GetInteger() ) ); 454 } 455 } 456 457 /* 458 ============ 459 idAASLocal::ShowPushIntoArea 460 ============ 461 */ 462 void idAASLocal::ShowPushIntoArea( const idVec3 &origin ) const { 463 int areaNum; 464 idVec3 target; 465 466 target = origin; 467 areaNum = PointReachableAreaNum( target, DefaultSearchBounds(), (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) ); 468 PushPointIntoAreaNum( areaNum, target ); 469 gameRenderWorld->DebugArrow( colorGreen, origin, target, 1 ); 470 } 471 472 /* 473 ============ 474 idAASLocal::Test 475 ============ 476 */ 477 void idAASLocal::Test( const idVec3 &origin ) { 478 479 if ( !file ) { 480 return; 481 } 482 483 if ( aas_randomPullPlayer.GetBool() ) { 484 RandomPullPlayer( origin ); 485 } 486 if ( ( aas_pullPlayer.GetInteger() > 0 ) && ( aas_pullPlayer.GetInteger() < file->GetNumAreas() ) ) { 487 ShowWalkPath( origin, aas_pullPlayer.GetInteger(), AreaCenter( aas_pullPlayer.GetInteger() ) ); 488 PullPlayer( origin, aas_pullPlayer.GetInteger() ); 489 } 490 if ( ( aas_showPath.GetInteger() > 0 ) && ( aas_showPath.GetInteger() < file->GetNumAreas() ) ) { 491 ShowWalkPath( origin, aas_showPath.GetInteger(), AreaCenter( aas_showPath.GetInteger() ) ); 492 } 493 if ( ( aas_showFlyPath.GetInteger() > 0 ) && ( aas_showFlyPath.GetInteger() < file->GetNumAreas() ) ) { 494 ShowFlyPath( origin, aas_showFlyPath.GetInteger(), AreaCenter( aas_showFlyPath.GetInteger() ) ); 495 } 496 if ( ( aas_showHideArea.GetInteger() > 0 ) && ( aas_showHideArea.GetInteger() < file->GetNumAreas() ) ) { 497 ShowHideArea( origin, aas_showHideArea.GetInteger() ); 498 } 499 if ( aas_showAreas.GetBool() ) { 500 ShowArea( origin ); 501 } 502 if ( aas_showWallEdges.GetBool() ) { 503 ShowWallEdges( origin ); 504 } 505 if ( aas_showPushIntoArea.GetBool() ) { 506 ShowPushIntoArea( origin ); 507 } 508 }