DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

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 }