AASFile.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "AASFile.h"
  23. #include "AASFile_local.h"
  24. /*
  25. ===============================================================================
  26. idReachability
  27. ===============================================================================
  28. */
  29. /*
  30. ================
  31. Reachability_Write
  32. ================
  33. */
  34. bool Reachability_Write( idFile *fp, idReachability *reach ) {
  35. fp->WriteFloatString( "\t\t%d %d (%f %f %f) (%f %f %f) %d %d",
  36. (int) reach->travelType, (int) reach->toAreaNum, reach->start.x, reach->start.y, reach->start.z,
  37. reach->end.x, reach->end.y, reach->end.z, reach->edgeNum, (int) reach->travelTime );
  38. return true;
  39. }
  40. /*
  41. ================
  42. Reachability_Read
  43. ================
  44. */
  45. bool Reachability_Read( idLexer &src, idReachability *reach ) {
  46. reach->travelType = src.ParseInt();
  47. reach->toAreaNum = src.ParseInt();
  48. src.Parse1DMatrix( 3, reach->start.ToFloatPtr() );
  49. src.Parse1DMatrix( 3, reach->end.ToFloatPtr() );
  50. reach->edgeNum = src.ParseInt();
  51. reach->travelTime = src.ParseInt();
  52. return true;
  53. }
  54. /*
  55. ================
  56. idReachability::CopyBase
  57. ================
  58. */
  59. void idReachability::CopyBase( idReachability &reach ) {
  60. travelType = reach.travelType;
  61. toAreaNum = reach.toAreaNum;
  62. start = reach.start;
  63. end = reach.end;
  64. edgeNum = reach.edgeNum;
  65. travelTime = reach.travelTime;
  66. }
  67. /*
  68. ===============================================================================
  69. idReachability_Special
  70. ===============================================================================
  71. */
  72. /*
  73. ================
  74. Reachability_Special_Write
  75. ================
  76. */
  77. bool Reachability_Special_Write( idFile *fp, idReachability_Special *reach ) {
  78. int i;
  79. const idKeyValue *keyValue;
  80. fp->WriteFloatString( "\n\t\t{\n" );
  81. for ( i = 0; i < reach->dict.GetNumKeyVals(); i++ ) {
  82. keyValue = reach->dict.GetKeyVal( i );
  83. fp->WriteFloatString( "\t\t\t\"%s\" \"%s\"\n", keyValue->GetKey().c_str(), keyValue->GetValue().c_str() );
  84. }
  85. fp->WriteFloatString( "\t\t}\n" );
  86. return true;
  87. }
  88. /*
  89. ================
  90. Reachability_Special_Read
  91. ================
  92. */
  93. bool Reachability_Special_Read( idLexer &src, idReachability_Special *reach ) {
  94. idToken key, value;
  95. src.ExpectTokenString( "{" );
  96. while( src.ReadToken( &key ) ) {
  97. if ( key == "}" ) {
  98. return true;
  99. }
  100. src.ExpectTokenType( TT_STRING, 0, &value );
  101. reach->dict.Set( key, value );
  102. }
  103. return false;
  104. }
  105. /*
  106. ===============================================================================
  107. idAASSettings
  108. ===============================================================================
  109. */
  110. /*
  111. ============
  112. idAASSettings::idAASSettings
  113. ============
  114. */
  115. idAASSettings::idAASSettings() {
  116. numBoundingBoxes = 1;
  117. boundingBoxes[0] = idBounds( idVec3( -16, -16, 0 ), idVec3( 16, 16, 72 ) );
  118. usePatches = false;
  119. writeBrushMap = false;
  120. playerFlood = false;
  121. noOptimize = false;
  122. allowSwimReachabilities = false;
  123. allowFlyReachabilities = false;
  124. fileExtension = "aas48";
  125. // physics settings
  126. gravity = idVec3( 0, 0, -1066 );
  127. gravityDir = gravity;
  128. gravityValue = gravityDir.Normalize();
  129. invGravityDir = -gravityDir;
  130. maxStepHeight = 14.0f;
  131. maxBarrierHeight = 32.0f;
  132. maxWaterJumpHeight = 20.0f;
  133. maxFallHeight = 64.0f;
  134. minFloorCos = 0.7f;
  135. // fixed travel times
  136. tt_barrierJump = 100;
  137. tt_startCrouching = 100;
  138. tt_waterJump = 100;
  139. tt_startWalkOffLedge = 100;
  140. }
  141. /*
  142. ============
  143. idAASSettings::ParseBool
  144. ============
  145. */
  146. bool idAASSettings::ParseBool( idLexer &src, bool &b ) {
  147. if ( !src.ExpectTokenString( "=" ) ) {
  148. return false;
  149. }
  150. b = src.ParseBool();
  151. return true;
  152. }
  153. /*
  154. ============
  155. idAASSettings::ParseInt
  156. ============
  157. */
  158. bool idAASSettings::ParseInt( idLexer &src, int &i ) {
  159. if ( !src.ExpectTokenString( "=" ) ) {
  160. return false;
  161. }
  162. i = src.ParseInt();
  163. return true;
  164. }
  165. /*
  166. ============
  167. idAASSettings::ParseFloat
  168. ============
  169. */
  170. bool idAASSettings::ParseFloat( idLexer &src, float &f ) {
  171. if ( !src.ExpectTokenString( "=" ) ) {
  172. return false;
  173. }
  174. f = src.ParseFloat();
  175. return true;
  176. }
  177. /*
  178. ============
  179. idAASSettings::ParseVector
  180. ============
  181. */
  182. bool idAASSettings::ParseVector( idLexer &src, idVec3 &vec ) {
  183. if ( !src.ExpectTokenString( "=" ) ) {
  184. return false;
  185. }
  186. return ( src.Parse1DMatrix( 3, vec.ToFloatPtr() ) != 0 );
  187. }
  188. /*
  189. ============
  190. idAASSettings::ParseBBoxes
  191. ============
  192. */
  193. bool idAASSettings::ParseBBoxes( idLexer &src ) {
  194. idToken token;
  195. idBounds bounds;
  196. numBoundingBoxes = 0;
  197. if ( !src.ExpectTokenString( "{" ) ) {
  198. return false;
  199. }
  200. while( src.ReadToken( &token ) ) {
  201. if ( token == "}" ) {
  202. return true;
  203. }
  204. src.UnreadToken( &token );
  205. src.Parse1DMatrix( 3, bounds[0].ToFloatPtr() );
  206. if ( !src.ExpectTokenString( "-" ) ) {
  207. return false;
  208. }
  209. src.Parse1DMatrix( 3, bounds[1].ToFloatPtr() );
  210. boundingBoxes[numBoundingBoxes++] = bounds;
  211. }
  212. return false;
  213. }
  214. /*
  215. ============
  216. idAASSettings::FromParser
  217. ============
  218. */
  219. bool idAASSettings::FromParser( idLexer &src ) {
  220. idToken token;
  221. if ( !src.ExpectTokenString( "{" ) ) {
  222. return false;
  223. }
  224. // parse the file
  225. while ( 1 ) {
  226. if ( !src.ReadToken( &token ) ) {
  227. break;
  228. }
  229. if ( token == "}" ) {
  230. break;
  231. }
  232. if ( token == "bboxes" ) {
  233. if ( !ParseBBoxes( src ) ) { return false; }
  234. }
  235. else if ( token == "usePatches" ) {
  236. if ( !ParseBool( src, usePatches ) ) { return false; }
  237. }
  238. else if ( token == "writeBrushMap" ) {
  239. if ( !ParseBool( src, writeBrushMap ) ) { return false; }
  240. }
  241. else if ( token == "playerFlood" ) {
  242. if ( !ParseBool( src, playerFlood ) ) { return false; }
  243. }
  244. else if ( token == "allowSwimReachabilities" ) {
  245. if ( !ParseBool( src, allowSwimReachabilities ) ) { return false; }
  246. }
  247. else if ( token == "allowFlyReachabilities" ) {
  248. if ( !ParseBool( src, allowFlyReachabilities ) ) { return false; }
  249. }
  250. else if ( token == "fileExtension" ) {
  251. src.ExpectTokenString( "=" );
  252. src.ExpectTokenType( TT_STRING, 0, &token );
  253. fileExtension = token;
  254. }
  255. else if ( token == "gravity" ) {
  256. ParseVector( src, gravity );
  257. gravityDir = gravity;
  258. gravityValue = gravityDir.Normalize();
  259. invGravityDir = -gravityDir;
  260. }
  261. else if ( token == "maxStepHeight" ) {
  262. if ( !ParseFloat( src, maxStepHeight ) ) { return false; }
  263. }
  264. else if ( token == "maxBarrierHeight" ) {
  265. if ( !ParseFloat( src, maxBarrierHeight ) ) { return false; }
  266. }
  267. else if ( token == "maxWaterJumpHeight" ) {
  268. if ( !ParseFloat( src, maxWaterJumpHeight ) ) { return false; }
  269. }
  270. else if ( token == "maxFallHeight" ) {
  271. if ( !ParseFloat( src, maxFallHeight ) ) { return false; }
  272. }
  273. else if ( token == "minFloorCos" ) {
  274. if ( !ParseFloat( src, minFloorCos ) ) { return false; }
  275. }
  276. else if ( token == "tt_barrierJump" ) {
  277. if ( !ParseInt( src, tt_barrierJump ) ) { return false; }
  278. }
  279. else if ( token == "tt_startCrouching" ) {
  280. if ( !ParseInt( src, tt_startCrouching ) ) { return false; }
  281. }
  282. else if ( token == "tt_waterJump" ) {
  283. if ( !ParseInt( src, tt_waterJump ) ) { return false; }
  284. }
  285. else if ( token == "tt_startWalkOffLedge" ) {
  286. if ( !ParseInt( src, tt_startWalkOffLedge ) ) { return false; }
  287. }
  288. else {
  289. src.Error( "invalid token '%s'", token.c_str() );
  290. }
  291. }
  292. if ( numBoundingBoxes <= 0 ) {
  293. src.Error( "no valid bounding box" );
  294. }
  295. return true;
  296. }
  297. /*
  298. ============
  299. idAASSettings::FromFile
  300. ============
  301. */
  302. bool idAASSettings::FromFile( const idStr &fileName ) {
  303. idLexer src( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS | LEXFL_NOSTRINGCONCAT );
  304. idStr name;
  305. name = fileName;
  306. common->Printf( "loading %s\n", name.c_str() );
  307. if ( !src.LoadFile( name ) ) {
  308. common->Error( "WARNING: couldn't load %s\n", name.c_str() );
  309. return false;
  310. }
  311. if ( !src.ExpectTokenString( "settings" ) ) {
  312. common->Error( "%s is not a settings file", name.c_str() );
  313. return false;
  314. }
  315. if ( !FromParser( src ) ) {
  316. common->Error( "failed to parse %s", name.c_str() );
  317. return false;
  318. }
  319. return true;
  320. }
  321. /*
  322. ============
  323. idAASSettings::FromDict
  324. ============
  325. */
  326. bool idAASSettings::FromDict( const char *name, const idDict *dict ) {
  327. idBounds bounds;
  328. if ( !dict->GetVector( "mins", "0 0 0", bounds[ 0 ] ) ) {
  329. common->Error( "Missing 'mins' in entityDef '%s'", name );
  330. }
  331. if ( !dict->GetVector( "maxs", "0 0 0", bounds[ 1 ] ) ) {
  332. common->Error( "Missing 'maxs' in entityDef '%s'", name );
  333. }
  334. numBoundingBoxes = 1;
  335. boundingBoxes[0] = bounds;
  336. if ( !dict->GetBool( "usePatches", "0", usePatches ) ) {
  337. common->Error( "Missing 'usePatches' in entityDef '%s'", name );
  338. }
  339. if ( !dict->GetBool( "writeBrushMap", "0", writeBrushMap ) ) {
  340. common->Error( "Missing 'writeBrushMap' in entityDef '%s'", name );
  341. }
  342. if ( !dict->GetBool( "playerFlood", "0", playerFlood ) ) {
  343. common->Error( "Missing 'playerFlood' in entityDef '%s'", name );
  344. }
  345. if ( !dict->GetBool( "allowSwimReachabilities", "0", allowSwimReachabilities ) ) {
  346. common->Error( "Missing 'allowSwimReachabilities' in entityDef '%s'", name );
  347. }
  348. if ( !dict->GetBool( "allowFlyReachabilities", "0", allowFlyReachabilities ) ) {
  349. common->Error( "Missing 'allowFlyReachabilities' in entityDef '%s'", name );
  350. }
  351. if ( !dict->GetString( "fileExtension", "", fileExtension ) ) {
  352. common->Error( "Missing 'fileExtension' in entityDef '%s'", name );
  353. }
  354. if ( !dict->GetVector( "gravity", "0 0 -1066", gravity ) ) {
  355. common->Error( "Missing 'gravity' in entityDef '%s'", name );
  356. }
  357. gravityDir = gravity;
  358. gravityValue = gravityDir.Normalize();
  359. invGravityDir = -gravityDir;
  360. if ( !dict->GetFloat( "maxStepHeight", "0", maxStepHeight ) ) {
  361. common->Error( "Missing 'maxStepHeight' in entityDef '%s'", name );
  362. }
  363. if ( !dict->GetFloat( "maxBarrierHeight", "0", maxBarrierHeight ) ) {
  364. common->Error( "Missing 'maxBarrierHeight' in entityDef '%s'", name );
  365. }
  366. if ( !dict->GetFloat( "maxWaterJumpHeight", "0", maxWaterJumpHeight ) ) {
  367. common->Error( "Missing 'maxWaterJumpHeight' in entityDef '%s'", name );
  368. }
  369. if ( !dict->GetFloat( "maxFallHeight", "0", maxFallHeight ) ) {
  370. common->Error( "Missing 'maxFallHeight' in entityDef '%s'", name );
  371. }
  372. if ( !dict->GetFloat( "minFloorCos", "0", minFloorCos ) ) {
  373. common->Error( "Missing 'minFloorCos' in entityDef '%s'", name );
  374. }
  375. if ( !dict->GetInt( "tt_barrierJump", "0", tt_barrierJump ) ) {
  376. common->Error( "Missing 'tt_barrierJump' in entityDef '%s'", name );
  377. }
  378. if ( !dict->GetInt( "tt_startCrouching", "0", tt_startCrouching ) ) {
  379. common->Error( "Missing 'tt_startCrouching' in entityDef '%s'", name );
  380. }
  381. if ( !dict->GetInt( "tt_waterJump", "0", tt_waterJump ) ) {
  382. common->Error( "Missing 'tt_waterJump' in entityDef '%s'", name );
  383. }
  384. if ( !dict->GetInt( "tt_startWalkOffLedge", "0", tt_startWalkOffLedge ) ) {
  385. common->Error( "Missing 'tt_startWalkOffLedge' in entityDef '%s'", name );
  386. }
  387. return true;
  388. }
  389. /*
  390. ============
  391. idAASSettings::WriteToFile
  392. ============
  393. */
  394. bool idAASSettings::WriteToFile( idFile *fp ) const {
  395. int i;
  396. fp->WriteFloatString( "{\n" );
  397. fp->WriteFloatString( "\tbboxes\n\t{\n" );
  398. for ( i = 0; i < numBoundingBoxes; i++ ) {
  399. fp->WriteFloatString( "\t\t(%f %f %f)-(%f %f %f)\n", boundingBoxes[i][0].x, boundingBoxes[i][0].y,
  400. boundingBoxes[i][0].z, boundingBoxes[i][1].x, boundingBoxes[i][1].y, boundingBoxes[i][1].z );
  401. }
  402. fp->WriteFloatString( "\t}\n" );
  403. fp->WriteFloatString( "\tusePatches = %d\n", usePatches );
  404. fp->WriteFloatString( "\twriteBrushMap = %d\n", writeBrushMap );
  405. fp->WriteFloatString( "\tplayerFlood = %d\n", playerFlood );
  406. fp->WriteFloatString( "\tallowSwimReachabilities = %d\n", allowSwimReachabilities );
  407. fp->WriteFloatString( "\tallowFlyReachabilities = %d\n", allowFlyReachabilities );
  408. fp->WriteFloatString( "\tfileExtension = \"%s\"\n", fileExtension.c_str() );
  409. fp->WriteFloatString( "\tgravity = (%f %f %f)\n", gravity.x, gravity.y, gravity.z );
  410. fp->WriteFloatString( "\tmaxStepHeight = %f\n", maxStepHeight );
  411. fp->WriteFloatString( "\tmaxBarrierHeight = %f\n", maxBarrierHeight );
  412. fp->WriteFloatString( "\tmaxWaterJumpHeight = %f\n", maxWaterJumpHeight );
  413. fp->WriteFloatString( "\tmaxFallHeight = %f\n", maxFallHeight );
  414. fp->WriteFloatString( "\tminFloorCos = %f\n", minFloorCos );
  415. fp->WriteFloatString( "\ttt_barrierJump = %d\n", tt_barrierJump );
  416. fp->WriteFloatString( "\ttt_startCrouching = %d\n", tt_startCrouching );
  417. fp->WriteFloatString( "\ttt_waterJump = %d\n", tt_waterJump );
  418. fp->WriteFloatString( "\ttt_startWalkOffLedge = %d\n", tt_startWalkOffLedge );
  419. fp->WriteFloatString( "}\n" );
  420. return true;
  421. }
  422. /*
  423. ============
  424. idAASSettings::ValidForBounds
  425. ============
  426. */
  427. bool idAASSettings::ValidForBounds( const idBounds &bounds ) const {
  428. int i;
  429. for ( i = 0; i < 3; i++ ) {
  430. if ( bounds[0][i] < boundingBoxes[0][0][i] ) {
  431. return false;
  432. }
  433. if ( bounds[1][i] > boundingBoxes[0][1][i] ) {
  434. return false;
  435. }
  436. }
  437. return true;
  438. }
  439. /*
  440. ============
  441. idAASSettings::ValidEntity
  442. ============
  443. */
  444. bool idAASSettings::ValidEntity( const char *classname ) const {
  445. idStr use_aas;
  446. idVec3 size;
  447. idBounds bounds;
  448. if ( playerFlood ) {
  449. if ( !strcmp( classname, "info_player_start" ) || !strcmp( classname , "info_player_deathmatch" ) || !strcmp( classname, "func_teleporter" ) ) {
  450. return true;
  451. }
  452. }
  453. const idDeclEntityDef *decl = static_cast<const idDeclEntityDef *>( declManager->FindType( DECL_ENTITYDEF, classname, false ) );
  454. if ( ( decl != NULL ) && decl->dict.GetString( "use_aas", NULL, use_aas ) && !fileExtension.Icmp( use_aas ) ) {
  455. if ( decl->dict.GetVector( "mins", NULL, bounds[0] ) ) {
  456. decl->dict.GetVector( "maxs", NULL, bounds[1] );
  457. } else if ( decl->dict.GetVector( "size", NULL, size ) ) {
  458. bounds[ 0 ].Set( size.x * -0.5f, size.y * -0.5f, 0.0f );
  459. bounds[ 1 ].Set( size.x * 0.5f, size.y * 0.5f, size.z );
  460. }
  461. if ( !ValidForBounds( bounds ) ) {
  462. common->Error( "%s cannot use %s\n", classname, fileExtension.c_str() );
  463. }
  464. return true;
  465. }
  466. return false;
  467. }
  468. /*
  469. ===============================================================================
  470. idAASFileLocal
  471. ===============================================================================
  472. */
  473. #define AAS_LIST_GRANULARITY 1024
  474. #define AAS_INDEX_GRANULARITY 4096
  475. #define AAS_PLANE_GRANULARITY 4096
  476. #define AAS_VERTEX_GRANULARITY 4096
  477. #define AAS_EDGE_GRANULARITY 4096
  478. /*
  479. ================
  480. idAASFileLocal::idAASFileLocal
  481. ================
  482. */
  483. idAASFileLocal::idAASFileLocal() {
  484. planeList.SetGranularity( AAS_PLANE_GRANULARITY );
  485. vertices.SetGranularity( AAS_VERTEX_GRANULARITY );
  486. edges.SetGranularity( AAS_EDGE_GRANULARITY );
  487. edgeIndex.SetGranularity( AAS_INDEX_GRANULARITY );
  488. faces.SetGranularity( AAS_LIST_GRANULARITY );
  489. faceIndex.SetGranularity( AAS_INDEX_GRANULARITY );
  490. areas.SetGranularity( AAS_LIST_GRANULARITY );
  491. nodes.SetGranularity( AAS_LIST_GRANULARITY );
  492. portals.SetGranularity( AAS_LIST_GRANULARITY );
  493. portalIndex.SetGranularity( AAS_INDEX_GRANULARITY );
  494. clusters.SetGranularity( AAS_LIST_GRANULARITY );
  495. }
  496. /*
  497. ================
  498. idAASFileLocal::~idAASFileLocal
  499. ================
  500. */
  501. idAASFileLocal::~idAASFileLocal() {
  502. int i;
  503. idReachability *reach, *next;
  504. for ( i = 0; i < areas.Num(); i++ ) {
  505. for ( reach = areas[i].reach; reach; reach = next ) {
  506. next = reach->next;
  507. delete reach;
  508. }
  509. }
  510. }
  511. /*
  512. ================
  513. idAASFileLocal::Clear
  514. ================
  515. */
  516. void idAASFileLocal::Clear() {
  517. planeList.Clear();
  518. vertices.Clear();
  519. edges.Clear();
  520. edgeIndex.Clear();
  521. faces.Clear();
  522. faceIndex.Clear();
  523. areas.Clear();
  524. nodes.Clear();
  525. portals.Clear();
  526. portalIndex.Clear();
  527. clusters.Clear();
  528. }
  529. /*
  530. ================
  531. idAASFileLocal::Write
  532. ================
  533. */
  534. bool idAASFileLocal::Write( const idStr &fileName, unsigned int mapFileCRC ) {
  535. int i, num;
  536. idFile *aasFile;
  537. idReachability *reach;
  538. common->Printf( "[Write AAS]\n" );
  539. common->Printf( "writing %s\n", fileName.c_str() );
  540. name = fileName;
  541. crc = mapFileCRC;
  542. aasFile = fileSystem->OpenFileWrite( fileName, "fs_basepath" );
  543. if ( !aasFile ) {
  544. common->Error( "Error opening %s", fileName.c_str() );
  545. return false;
  546. }
  547. aasFile->WriteFloatString( "%s \"%s\"\n\n", AAS_FILEID, AAS_FILEVERSION );
  548. aasFile->WriteFloatString( "%u\n\n", mapFileCRC );
  549. // write out the settings
  550. aasFile->WriteFloatString( "settings\n" );
  551. settings.WriteToFile( aasFile );
  552. // write out planes
  553. aasFile->WriteFloatString( "planes %d {\n", planeList.Num() );
  554. for ( i = 0; i < planeList.Num(); i++ ) {
  555. aasFile->WriteFloatString( "\t%d ( %f %f %f %f )\n", i,
  556. planeList[i].Normal().x, planeList[i].Normal().y, planeList[i].Normal().z, planeList[i].Dist() );
  557. }
  558. aasFile->WriteFloatString( "}\n" );
  559. // write out vertices
  560. aasFile->WriteFloatString( "vertices %d {\n", vertices.Num() );
  561. for ( i = 0; i < vertices.Num(); i++ ) {
  562. aasFile->WriteFloatString( "\t%d ( %f %f %f )\n", i, vertices[i].x, vertices[i].y, vertices[i].z );
  563. }
  564. aasFile->WriteFloatString( "}\n" );
  565. // write out edges
  566. aasFile->WriteFloatString( "edges %d {\n", edges.Num() );
  567. for ( i = 0; i < edges.Num(); i++ ) {
  568. aasFile->WriteFloatString( "\t%d ( %d %d )\n", i, edges[i].vertexNum[0], edges[i].vertexNum[1] );
  569. }
  570. aasFile->WriteFloatString( "}\n" );
  571. // write out edgeIndex
  572. aasFile->WriteFloatString( "edgeIndex %d {\n", edgeIndex.Num() );
  573. for ( i = 0; i < edgeIndex.Num(); i++ ) {
  574. aasFile->WriteFloatString( "\t%d ( %d )\n", i, edgeIndex[i] );
  575. }
  576. aasFile->WriteFloatString( "}\n" );
  577. // write out faces
  578. aasFile->WriteFloatString( "faces %d {\n", faces.Num() );
  579. for ( i = 0; i < faces.Num(); i++ ) {
  580. aasFile->WriteFloatString( "\t%d ( %d %d %d %d %d %d )\n", i, faces[i].planeNum, faces[i].flags,
  581. faces[i].areas[0], faces[i].areas[1], faces[i].firstEdge, faces[i].numEdges );
  582. }
  583. aasFile->WriteFloatString( "}\n" );
  584. // write out faceIndex
  585. aasFile->WriteFloatString( "faceIndex %d {\n", faceIndex.Num() );
  586. for ( i = 0; i < faceIndex.Num(); i++ ) {
  587. aasFile->WriteFloatString( "\t%d ( %d )\n", i, faceIndex[i] );
  588. }
  589. aasFile->WriteFloatString( "}\n" );
  590. // write out areas
  591. aasFile->WriteFloatString( "areas %d {\n", areas.Num() );
  592. for ( i = 0; i < areas.Num(); i++ ) {
  593. for ( num = 0, reach = areas[i].reach; reach; reach = reach->next ) {
  594. num++;
  595. }
  596. aasFile->WriteFloatString( "\t%d ( %d %d %d %d %d %d ) %d {\n", i, areas[i].flags, areas[i].contents,
  597. areas[i].firstFace, areas[i].numFaces, areas[i].cluster, areas[i].clusterAreaNum, num );
  598. for ( reach = areas[i].reach; reach; reach = reach->next ) {
  599. Reachability_Write( aasFile, reach );
  600. switch( reach->travelType ) {
  601. case TFL_SPECIAL:
  602. Reachability_Special_Write( aasFile, static_cast<idReachability_Special *>(reach) );
  603. break;
  604. }
  605. aasFile->WriteFloatString( "\n" );
  606. }
  607. aasFile->WriteFloatString( "\t}\n" );
  608. }
  609. aasFile->WriteFloatString( "}\n" );
  610. // write out nodes
  611. aasFile->WriteFloatString( "nodes %d {\n", nodes.Num() );
  612. for ( i = 0; i < nodes.Num(); i++ ) {
  613. aasFile->WriteFloatString( "\t%d ( %d %d %d )\n", i, nodes[i].planeNum, nodes[i].children[0], nodes[i].children[1] );
  614. }
  615. aasFile->WriteFloatString( "}\n" );
  616. // write out portals
  617. aasFile->WriteFloatString( "portals %d {\n", portals.Num() );
  618. for ( i = 0; i < portals.Num(); i++ ) {
  619. aasFile->WriteFloatString( "\t%d ( %d %d %d %d %d )\n", i, portals[i].areaNum, portals[i].clusters[0],
  620. portals[i].clusters[1], portals[i].clusterAreaNum[0], portals[i].clusterAreaNum[1] );
  621. }
  622. aasFile->WriteFloatString( "}\n" );
  623. // write out portalIndex
  624. aasFile->WriteFloatString( "portalIndex %d {\n", portalIndex.Num() );
  625. for ( i = 0; i < portalIndex.Num(); i++ ) {
  626. aasFile->WriteFloatString( "\t%d ( %d )\n", i, portalIndex[i] );
  627. }
  628. aasFile->WriteFloatString( "}\n" );
  629. // write out clusters
  630. aasFile->WriteFloatString( "clusters %d {\n", clusters.Num() );
  631. for ( i = 0; i < clusters.Num(); i++ ) {
  632. aasFile->WriteFloatString( "\t%d ( %d %d %d %d )\n", i, clusters[i].numAreas, clusters[i].numReachableAreas,
  633. clusters[i].firstPortal, clusters[i].numPortals );
  634. }
  635. aasFile->WriteFloatString( "}\n" );
  636. // close file
  637. fileSystem->CloseFile( aasFile );
  638. common->Printf( "done.\n" );
  639. return true;
  640. }
  641. /*
  642. ================
  643. idAASFileLocal::ParseIndex
  644. ================
  645. */
  646. bool idAASFileLocal::ParseIndex( idLexer &src, idList<aasIndex_t> &indexes ) {
  647. int numIndexes, i;
  648. aasIndex_t index;
  649. numIndexes = src.ParseInt();
  650. indexes.Resize( numIndexes );
  651. if ( !src.ExpectTokenString( "{" ) ) {
  652. return false;
  653. }
  654. for ( i = 0; i < numIndexes; i++ ) {
  655. src.ParseInt();
  656. src.ExpectTokenString( "(" );
  657. index = src.ParseInt();
  658. src.ExpectTokenString( ")" );
  659. indexes.Append( index );
  660. }
  661. if ( !src.ExpectTokenString( "}" ) ) {
  662. return false;
  663. }
  664. return true;
  665. }
  666. /*
  667. ================
  668. idAASFileLocal::ParsePlanes
  669. ================
  670. */
  671. bool idAASFileLocal::ParsePlanes( idLexer &src ) {
  672. int numPlanes, i;
  673. idPlane plane;
  674. idVec4 vec;
  675. numPlanes = src.ParseInt();
  676. planeList.Resize( numPlanes );
  677. if ( !src.ExpectTokenString( "{" ) ) {
  678. return false;
  679. }
  680. for ( i = 0; i < numPlanes; i++ ) {
  681. src.ParseInt();
  682. if ( !src.Parse1DMatrix( 4, vec.ToFloatPtr() ) ) {
  683. return false;
  684. }
  685. plane.SetNormal( vec.ToVec3() );
  686. plane.SetDist( vec[3] );
  687. planeList.Append( plane );
  688. }
  689. if ( !src.ExpectTokenString( "}" ) ) {
  690. return false;
  691. }
  692. return true;
  693. }
  694. /*
  695. ================
  696. idAASFileLocal::ParseVertices
  697. ================
  698. */
  699. bool idAASFileLocal::ParseVertices( idLexer &src ) {
  700. int numVertices, i;
  701. idVec3 vec;
  702. numVertices = src.ParseInt();
  703. vertices.Resize( numVertices );
  704. if ( !src.ExpectTokenString( "{" ) ) {
  705. return false;
  706. }
  707. for ( i = 0; i < numVertices; i++ ) {
  708. src.ParseInt();
  709. if ( !src.Parse1DMatrix( 3, vec.ToFloatPtr() ) ) {
  710. return false;
  711. }
  712. vertices.Append( vec );
  713. }
  714. if ( !src.ExpectTokenString( "}" ) ) {
  715. return false;
  716. }
  717. return true;
  718. }
  719. /*
  720. ================
  721. idAASFileLocal::ParseEdges
  722. ================
  723. */
  724. bool idAASFileLocal::ParseEdges( idLexer &src ) {
  725. int numEdges, i;
  726. aasEdge_t edge;
  727. numEdges = src.ParseInt();
  728. edges.Resize( numEdges );
  729. if ( !src.ExpectTokenString( "{" ) ) {
  730. return false;
  731. }
  732. for ( i = 0; i < numEdges; i++ ) {
  733. src.ParseInt();
  734. src.ExpectTokenString( "(" );
  735. edge.vertexNum[0] = src.ParseInt();
  736. edge.vertexNum[1] = src.ParseInt();
  737. src.ExpectTokenString( ")" );
  738. edges.Append( edge );
  739. }
  740. if ( !src.ExpectTokenString( "}" ) ) {
  741. return false;
  742. }
  743. return true;
  744. }
  745. /*
  746. ================
  747. idAASFileLocal::ParseFaces
  748. ================
  749. */
  750. bool idAASFileLocal::ParseFaces( idLexer &src ) {
  751. int numFaces, i;
  752. aasFace_t face;
  753. numFaces = src.ParseInt();
  754. faces.Resize( numFaces );
  755. if ( !src.ExpectTokenString( "{" ) ) {
  756. return false;
  757. }
  758. for ( i = 0; i < numFaces; i++ ) {
  759. src.ParseInt();
  760. src.ExpectTokenString( "(" );
  761. face.planeNum = src.ParseInt();
  762. face.flags = src.ParseInt();
  763. face.areas[0] = src.ParseInt();
  764. face.areas[1] = src.ParseInt();
  765. face.firstEdge = src.ParseInt();
  766. face.numEdges = src.ParseInt();
  767. src.ExpectTokenString( ")" );
  768. faces.Append( face );
  769. }
  770. if ( !src.ExpectTokenString( "}" ) ) {
  771. return false;
  772. }
  773. return true;
  774. }
  775. /*
  776. ================
  777. idAASFileLocal::ParseReachabilities
  778. ================
  779. */
  780. bool idAASFileLocal::ParseReachabilities( idLexer &src, int areaNum ) {
  781. int num, j;
  782. aasArea_t *area;
  783. idReachability reach, *newReach;
  784. idReachability_Special *special;
  785. area = &areas[areaNum];
  786. num = src.ParseInt();
  787. src.ExpectTokenString( "{" );
  788. area->reach = NULL;
  789. area->rev_reach = NULL;
  790. area->travelFlags = AreaContentsTravelFlags( areaNum );
  791. for ( j = 0; j < num; j++ ) {
  792. Reachability_Read( src, &reach );
  793. switch( reach.travelType ) {
  794. case TFL_SPECIAL:
  795. newReach = special = new (TAG_AAS) idReachability_Special();
  796. Reachability_Special_Read( src, special );
  797. break;
  798. default:
  799. newReach = new (TAG_AAS) idReachability();
  800. break;
  801. }
  802. newReach->CopyBase( reach );
  803. newReach->fromAreaNum = areaNum;
  804. newReach->next = area->reach;
  805. area->reach = newReach;
  806. }
  807. src.ExpectTokenString( "}" );
  808. return true;
  809. }
  810. /*
  811. ================
  812. idAASFileLocal::LinkReversedReachability
  813. ================
  814. */
  815. void idAASFileLocal::LinkReversedReachability() {
  816. int i;
  817. idReachability *reach;
  818. // link reversed reachabilities
  819. for ( i = 0; i < areas.Num(); i++ ) {
  820. for ( reach = areas[i].reach; reach; reach = reach->next ) {
  821. reach->rev_next = areas[reach->toAreaNum].rev_reach;
  822. areas[reach->toAreaNum].rev_reach = reach;
  823. }
  824. }
  825. }
  826. /*
  827. ================
  828. idAASFileLocal::ParseAreas
  829. ================
  830. */
  831. bool idAASFileLocal::ParseAreas( idLexer &src ) {
  832. int numAreas, i;
  833. aasArea_t area;
  834. numAreas = src.ParseInt();
  835. areas.Resize( numAreas );
  836. if ( !src.ExpectTokenString( "{" ) ) {
  837. return false;
  838. }
  839. for ( i = 0; i < numAreas; i++ ) {
  840. src.ParseInt();
  841. src.ExpectTokenString( "(" );
  842. area.flags = src.ParseInt();
  843. area.contents = src.ParseInt();
  844. area.firstFace = src.ParseInt();
  845. area.numFaces = src.ParseInt();
  846. area.cluster = src.ParseInt();
  847. area.clusterAreaNum = src.ParseInt();
  848. src.ExpectTokenString( ")" );
  849. areas.Append( area );
  850. ParseReachabilities( src, i );
  851. }
  852. if ( !src.ExpectTokenString( "}" ) ) {
  853. return false;
  854. }
  855. LinkReversedReachability();
  856. return true;
  857. }
  858. /*
  859. ================
  860. idAASFileLocal::ParseNodes
  861. ================
  862. */
  863. bool idAASFileLocal::ParseNodes( idLexer &src ) {
  864. int numNodes, i;
  865. aasNode_t node;
  866. numNodes = src.ParseInt();
  867. nodes.Resize( numNodes );
  868. if ( !src.ExpectTokenString( "{" ) ) {
  869. return false;
  870. }
  871. for ( i = 0; i < numNodes; i++ ) {
  872. src.ParseInt();
  873. src.ExpectTokenString( "(" );
  874. node.planeNum = src.ParseInt();
  875. node.children[0] = src.ParseInt();
  876. node.children[1] = src.ParseInt();
  877. src.ExpectTokenString( ")" );
  878. nodes.Append( node );
  879. }
  880. if ( !src.ExpectTokenString( "}" ) ) {
  881. return false;
  882. }
  883. return true;
  884. }
  885. /*
  886. ================
  887. idAASFileLocal::ParsePortals
  888. ================
  889. */
  890. bool idAASFileLocal::ParsePortals( idLexer &src ) {
  891. int numPortals, i;
  892. aasPortal_t portal;
  893. numPortals = src.ParseInt();
  894. portals.Resize( numPortals );
  895. if ( !src.ExpectTokenString( "{" ) ) {
  896. return false;
  897. }
  898. for ( i = 0; i < numPortals; i++ ) {
  899. src.ParseInt();
  900. src.ExpectTokenString( "(" );
  901. portal.areaNum = src.ParseInt();
  902. portal.clusters[0] = src.ParseInt();
  903. portal.clusters[1] = src.ParseInt();
  904. portal.clusterAreaNum[0] = src.ParseInt();
  905. portal.clusterAreaNum[1] = src.ParseInt();
  906. src.ExpectTokenString( ")" );
  907. portals.Append( portal );
  908. }
  909. if ( !src.ExpectTokenString( "}" ) ) {
  910. return false;
  911. }
  912. return true;
  913. }
  914. /*
  915. ================
  916. idAASFileLocal::ParseClusters
  917. ================
  918. */
  919. bool idAASFileLocal::ParseClusters( idLexer &src ) {
  920. int numClusters, i;
  921. aasCluster_t cluster;
  922. numClusters = src.ParseInt();
  923. clusters.Resize( numClusters );
  924. if ( !src.ExpectTokenString( "{" ) ) {
  925. return false;
  926. }
  927. for ( i = 0; i < numClusters; i++ ) {
  928. src.ParseInt();
  929. src.ExpectTokenString( "(" );
  930. cluster.numAreas = src.ParseInt();
  931. cluster.numReachableAreas = src.ParseInt();
  932. cluster.firstPortal = src.ParseInt();
  933. cluster.numPortals = src.ParseInt();
  934. src.ExpectTokenString( ")" );
  935. clusters.Append( cluster );
  936. }
  937. if ( !src.ExpectTokenString( "}" ) ) {
  938. return false;
  939. }
  940. return true;
  941. }
  942. /*
  943. ================
  944. idAASFileLocal::FinishAreas
  945. ================
  946. */
  947. void idAASFileLocal::FinishAreas() {
  948. int i;
  949. for ( i = 0; i < areas.Num(); i++ ) {
  950. areas[i].center = AreaReachableGoal( i );
  951. areas[i].bounds = AreaBounds( i );
  952. }
  953. }
  954. /*
  955. ================
  956. idAASFileLocal::Load
  957. ================
  958. */
  959. bool idAASFileLocal::Load( const idStr &fileName, unsigned int mapFileCRC ) {
  960. idLexer src( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGESCAPECHARS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWPATHNAMES );
  961. idToken token;
  962. int depth;
  963. unsigned int c;
  964. name = fileName;
  965. crc = mapFileCRC;
  966. common->Printf( "[Load AAS]\n" );
  967. common->Printf( "loading %s\n", name.c_str() );
  968. if ( !src.LoadFile( name ) ) {
  969. return false;
  970. }
  971. if ( !src.ExpectTokenString( AAS_FILEID ) ) {
  972. common->Warning( "Not an AAS file: '%s'", name.c_str() );
  973. return false;
  974. }
  975. if ( !src.ReadToken( &token ) || token != AAS_FILEVERSION ) {
  976. common->Warning( "AAS file '%s' has version %s instead of %s", name.c_str(), token.c_str(), AAS_FILEVERSION );
  977. return false;
  978. }
  979. if ( !src.ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ) ) {
  980. common->Warning( "AAS file '%s' has no map file CRC", name.c_str() );
  981. return false;
  982. }
  983. c = token.GetUnsignedLongValue();
  984. if ( mapFileCRC && c != mapFileCRC ) {
  985. common->Warning( "AAS file '%s' is out of date", name.c_str() );
  986. return false;
  987. }
  988. // clear the file in memory
  989. Clear();
  990. // parse the file
  991. while ( 1 ) {
  992. if ( !src.ReadToken( &token ) ) {
  993. break;
  994. }
  995. if ( token == "settings" ) {
  996. if ( !settings.FromParser( src ) ) { return false; }
  997. }
  998. else if ( token == "planes" ) {
  999. if ( !ParsePlanes( src ) ) { return false; }
  1000. }
  1001. else if ( token == "vertices" ) {
  1002. if ( !ParseVertices( src ) ) { return false; }
  1003. }
  1004. else if ( token == "edges" ) {
  1005. if ( !ParseEdges( src ) ) { return false; }
  1006. }
  1007. else if ( token == "edgeIndex" ) {
  1008. if ( !ParseIndex( src, edgeIndex ) ) { return false; }
  1009. }
  1010. else if ( token == "faces" ) {
  1011. if ( !ParseFaces( src ) ) { return false; }
  1012. }
  1013. else if ( token == "faceIndex" ) {
  1014. if ( !ParseIndex( src, faceIndex ) ) { return false; }
  1015. }
  1016. else if ( token == "areas" ) {
  1017. if ( !ParseAreas( src ) ) { return false; }
  1018. }
  1019. else if ( token == "nodes" ) {
  1020. if ( !ParseNodes( src ) ) { return false; }
  1021. }
  1022. else if ( token == "portals" ) {
  1023. if ( !ParsePortals( src ) ) { return false; }
  1024. }
  1025. else if ( token == "portalIndex" ) {
  1026. if ( !ParseIndex( src, portalIndex ) ) { return false; }
  1027. }
  1028. else if ( token == "clusters" ) {
  1029. if ( !ParseClusters( src ) ) { return false; }
  1030. }
  1031. else {
  1032. src.Error( "idAASFileLocal::Load: bad token \"%s\"", token.c_str() );
  1033. return false;
  1034. }
  1035. }
  1036. FinishAreas();
  1037. depth = MaxTreeDepth();
  1038. if ( depth > MAX_AAS_TREE_DEPTH ) {
  1039. src.Error( "idAASFileLocal::Load: tree depth = %d", depth );
  1040. }
  1041. common->UpdateLevelLoadPacifier();
  1042. common->Printf( "done.\n" );
  1043. return true;
  1044. }
  1045. /*
  1046. ================
  1047. idAASFileLocal::MemorySize
  1048. ================
  1049. */
  1050. int idAASFileLocal::MemorySize() const {
  1051. int size;
  1052. size = planeList.Size();
  1053. size += vertices.Size();
  1054. size += edges.Size();
  1055. size += edgeIndex.Size();
  1056. size += faces.Size();
  1057. size += faceIndex.Size();
  1058. size += areas.Size();
  1059. size += nodes.Size();
  1060. size += portals.Size();
  1061. size += portalIndex.Size();
  1062. size += clusters.Size();
  1063. size += sizeof( idReachability_Walk ) * NumReachabilities();
  1064. return size;
  1065. }
  1066. /*
  1067. ================
  1068. idAASFileLocal::PrintInfo
  1069. ================
  1070. */
  1071. void idAASFileLocal::PrintInfo() const {
  1072. common->Printf( "%6d KB file size\n", MemorySize() >> 10 );
  1073. common->Printf( "%6d areas\n", areas.Num() );
  1074. common->Printf( "%6d max tree depth\n", MaxTreeDepth() );
  1075. ReportRoutingEfficiency();
  1076. }
  1077. /*
  1078. ================
  1079. idAASFileLocal::NumReachabilities
  1080. ================
  1081. */
  1082. int idAASFileLocal::NumReachabilities() const {
  1083. int i, num;
  1084. idReachability *reach;
  1085. num = 0;
  1086. for ( i = 0; i < areas.Num(); i++ ) {
  1087. for ( reach = areas[i].reach; reach; reach = reach->next ) {
  1088. num++;
  1089. }
  1090. }
  1091. return num;
  1092. }
  1093. /*
  1094. ================
  1095. idAASFileLocal::ReportRoutingEfficiency
  1096. ================
  1097. */
  1098. void idAASFileLocal::ReportRoutingEfficiency() const {
  1099. int numReachableAreas, total, i, n;
  1100. numReachableAreas = 0;
  1101. total = 0;
  1102. for ( i = 0; i < clusters.Num(); i++ ) {
  1103. n = clusters[i].numReachableAreas;
  1104. numReachableAreas += n;
  1105. total += n * n;
  1106. }
  1107. total += numReachableAreas * portals.Num();
  1108. common->Printf( "%6d reachable areas\n", numReachableAreas );
  1109. common->Printf( "%6d reachabilities\n", NumReachabilities() );
  1110. common->Printf( "%6d KB max routing cache\n", ( total * 3 ) >> 10 );
  1111. }
  1112. /*
  1113. ================
  1114. idAASFileLocal::DeleteReachabilities
  1115. ================
  1116. */
  1117. void idAASFileLocal::DeleteReachabilities() {
  1118. int i;
  1119. idReachability *reach, *nextReach;
  1120. for ( i = 0; i < areas.Num(); i++ ) {
  1121. for ( reach = areas[i].reach; reach; reach = nextReach ) {
  1122. nextReach = reach->next;
  1123. delete reach;
  1124. }
  1125. areas[i].reach = NULL;
  1126. areas[i].rev_reach = NULL;
  1127. }
  1128. }
  1129. /*
  1130. ================
  1131. idAASFileLocal::DeleteClusters
  1132. ================
  1133. */
  1134. void idAASFileLocal::DeleteClusters() {
  1135. aasPortal_t portal;
  1136. aasCluster_t cluster;
  1137. portals.Clear();
  1138. portalIndex.Clear();
  1139. clusters.Clear();
  1140. // first portal is a dummy
  1141. memset( &portal, 0, sizeof( portal ) );
  1142. portals.Append( portal );
  1143. // first cluster is a dummy
  1144. memset( &cluster, 0, sizeof( cluster ) );
  1145. clusters.Append( cluster );
  1146. }