cm_load.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // cmodel.c -- model loading
  19. #include "cm_local.h"
  20. #ifdef BSPC
  21. #include "../bspc/l_qfiles.h"
  22. void SetPlaneSignbits (cplane_t *out) {
  23. int bits, j;
  24. // for fast box on planeside test
  25. bits = 0;
  26. for (j=0 ; j<3 ; j++) {
  27. if (out->normal[j] < 0) {
  28. bits |= 1<<j;
  29. }
  30. }
  31. out->signbits = bits;
  32. }
  33. #endif //BSPC
  34. // to allow boxes to be treated as brush models, we allocate
  35. // some extra indexes along with those needed by the map
  36. #define BOX_BRUSHES 1
  37. #define BOX_SIDES 6
  38. #define BOX_LEAFS 2
  39. #define BOX_PLANES 12
  40. #define LL(x) x=LittleLong(x)
  41. clipMap_t cm;
  42. int c_pointcontents;
  43. int c_traces, c_brush_traces, c_patch_traces;
  44. byte *cmod_base;
  45. #ifndef BSPC
  46. cvar_t *cm_noAreas;
  47. cvar_t *cm_noCurves;
  48. cvar_t *cm_playerCurveClip;
  49. #endif
  50. cmodel_t box_model;
  51. cplane_t *box_planes;
  52. cbrush_t *box_brush;
  53. void CM_InitBoxHull (void);
  54. void CM_FloodAreaConnections (void);
  55. /*
  56. ===============================================================================
  57. MAP LOADING
  58. ===============================================================================
  59. */
  60. /*
  61. =================
  62. CMod_LoadShaders
  63. =================
  64. */
  65. void CMod_LoadShaders( lump_t *l ) {
  66. dshader_t *in, *out;
  67. int i, count;
  68. in = (void *)(cmod_base + l->fileofs);
  69. if (l->filelen % sizeof(*in)) {
  70. Com_Error (ERR_DROP, "CMod_LoadShaders: funny lump size");
  71. }
  72. count = l->filelen / sizeof(*in);
  73. if (count < 1) {
  74. Com_Error (ERR_DROP, "Map with no shaders");
  75. }
  76. cm.shaders = Hunk_Alloc( count * sizeof( *cm.shaders ), h_high );
  77. cm.numShaders = count;
  78. Com_Memcpy( cm.shaders, in, count * sizeof( *cm.shaders ) );
  79. out = cm.shaders;
  80. for ( i=0 ; i<count ; i++, in++, out++ ) {
  81. out->contentFlags = LittleLong( out->contentFlags );
  82. out->surfaceFlags = LittleLong( out->surfaceFlags );
  83. }
  84. }
  85. /*
  86. =================
  87. CMod_LoadSubmodels
  88. =================
  89. */
  90. void CMod_LoadSubmodels( lump_t *l ) {
  91. dmodel_t *in;
  92. cmodel_t *out;
  93. int i, j, count;
  94. int *indexes;
  95. in = (void *)(cmod_base + l->fileofs);
  96. if (l->filelen % sizeof(*in))
  97. Com_Error (ERR_DROP, "CMod_LoadSubmodels: funny lump size");
  98. count = l->filelen / sizeof(*in);
  99. if (count < 1)
  100. Com_Error (ERR_DROP, "Map with no models");
  101. cm.cmodels = Hunk_Alloc( count * sizeof( *cm.cmodels ), h_high );
  102. cm.numSubModels = count;
  103. if ( count > MAX_SUBMODELS ) {
  104. Com_Error( ERR_DROP, "MAX_SUBMODELS exceeded" );
  105. }
  106. for ( i=0 ; i<count ; i++, in++, out++)
  107. {
  108. out = &cm.cmodels[i];
  109. for (j=0 ; j<3 ; j++)
  110. { // spread the mins / maxs by a pixel
  111. out->mins[j] = LittleFloat (in->mins[j]) - 1;
  112. out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
  113. }
  114. if ( i == 0 ) {
  115. continue; // world model doesn't need other info
  116. }
  117. // make a "leaf" just to hold the model's brushes and surfaces
  118. out->leaf.numLeafBrushes = LittleLong( in->numBrushes );
  119. indexes = Hunk_Alloc( out->leaf.numLeafBrushes * 4, h_high );
  120. out->leaf.firstLeafBrush = indexes - cm.leafbrushes;
  121. for ( j = 0 ; j < out->leaf.numLeafBrushes ; j++ ) {
  122. indexes[j] = LittleLong( in->firstBrush ) + j;
  123. }
  124. out->leaf.numLeafSurfaces = LittleLong( in->numSurfaces );
  125. indexes = Hunk_Alloc( out->leaf.numLeafSurfaces * 4, h_high );
  126. out->leaf.firstLeafSurface = indexes - cm.leafsurfaces;
  127. for ( j = 0 ; j < out->leaf.numLeafSurfaces ; j++ ) {
  128. indexes[j] = LittleLong( in->firstSurface ) + j;
  129. }
  130. }
  131. }
  132. /*
  133. =================
  134. CMod_LoadNodes
  135. =================
  136. */
  137. void CMod_LoadNodes( lump_t *l ) {
  138. dnode_t *in;
  139. int child;
  140. cNode_t *out;
  141. int i, j, count;
  142. in = (void *)(cmod_base + l->fileofs);
  143. if (l->filelen % sizeof(*in))
  144. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  145. count = l->filelen / sizeof(*in);
  146. if (count < 1)
  147. Com_Error (ERR_DROP, "Map has no nodes");
  148. cm.nodes = Hunk_Alloc( count * sizeof( *cm.nodes ), h_high );
  149. cm.numNodes = count;
  150. out = cm.nodes;
  151. for (i=0 ; i<count ; i++, out++, in++)
  152. {
  153. out->plane = cm.planes + LittleLong( in->planeNum );
  154. for (j=0 ; j<2 ; j++)
  155. {
  156. child = LittleLong (in->children[j]);
  157. out->children[j] = child;
  158. }
  159. }
  160. }
  161. /*
  162. =================
  163. CM_BoundBrush
  164. =================
  165. */
  166. void CM_BoundBrush( cbrush_t *b ) {
  167. b->bounds[0][0] = -b->sides[0].plane->dist;
  168. b->bounds[1][0] = b->sides[1].plane->dist;
  169. b->bounds[0][1] = -b->sides[2].plane->dist;
  170. b->bounds[1][1] = b->sides[3].plane->dist;
  171. b->bounds[0][2] = -b->sides[4].plane->dist;
  172. b->bounds[1][2] = b->sides[5].plane->dist;
  173. }
  174. /*
  175. =================
  176. CMod_LoadBrushes
  177. =================
  178. */
  179. void CMod_LoadBrushes( lump_t *l ) {
  180. dbrush_t *in;
  181. cbrush_t *out;
  182. int i, count;
  183. in = (void *)(cmod_base + l->fileofs);
  184. if (l->filelen % sizeof(*in)) {
  185. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  186. }
  187. count = l->filelen / sizeof(*in);
  188. cm.brushes = Hunk_Alloc( ( BOX_BRUSHES + count ) * sizeof( *cm.brushes ), h_high );
  189. cm.numBrushes = count;
  190. out = cm.brushes;
  191. for ( i=0 ; i<count ; i++, out++, in++ ) {
  192. out->sides = cm.brushsides + LittleLong(in->firstSide);
  193. out->numsides = LittleLong(in->numSides);
  194. out->shaderNum = LittleLong( in->shaderNum );
  195. if ( out->shaderNum < 0 || out->shaderNum >= cm.numShaders ) {
  196. Com_Error( ERR_DROP, "CMod_LoadBrushes: bad shaderNum: %i", out->shaderNum );
  197. }
  198. out->contents = cm.shaders[out->shaderNum].contentFlags;
  199. CM_BoundBrush( out );
  200. }
  201. }
  202. /*
  203. =================
  204. CMod_LoadLeafs
  205. =================
  206. */
  207. void CMod_LoadLeafs (lump_t *l)
  208. {
  209. int i;
  210. cLeaf_t *out;
  211. dleaf_t *in;
  212. int count;
  213. in = (void *)(cmod_base + l->fileofs);
  214. if (l->filelen % sizeof(*in))
  215. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  216. count = l->filelen / sizeof(*in);
  217. if (count < 1)
  218. Com_Error (ERR_DROP, "Map with no leafs");
  219. cm.leafs = Hunk_Alloc( ( BOX_LEAFS + count ) * sizeof( *cm.leafs ), h_high );
  220. cm.numLeafs = count;
  221. out = cm.leafs;
  222. for ( i=0 ; i<count ; i++, in++, out++)
  223. {
  224. out->cluster = LittleLong (in->cluster);
  225. out->area = LittleLong (in->area);
  226. out->firstLeafBrush = LittleLong (in->firstLeafBrush);
  227. out->numLeafBrushes = LittleLong (in->numLeafBrushes);
  228. out->firstLeafSurface = LittleLong (in->firstLeafSurface);
  229. out->numLeafSurfaces = LittleLong (in->numLeafSurfaces);
  230. if (out->cluster >= cm.numClusters)
  231. cm.numClusters = out->cluster + 1;
  232. if (out->area >= cm.numAreas)
  233. cm.numAreas = out->area + 1;
  234. }
  235. cm.areas = Hunk_Alloc( cm.numAreas * sizeof( *cm.areas ), h_high );
  236. cm.areaPortals = Hunk_Alloc( cm.numAreas * cm.numAreas * sizeof( *cm.areaPortals ), h_high );
  237. }
  238. /*
  239. =================
  240. CMod_LoadPlanes
  241. =================
  242. */
  243. void CMod_LoadPlanes (lump_t *l)
  244. {
  245. int i, j;
  246. cplane_t *out;
  247. dplane_t *in;
  248. int count;
  249. int bits;
  250. in = (void *)(cmod_base + l->fileofs);
  251. if (l->filelen % sizeof(*in))
  252. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  253. count = l->filelen / sizeof(*in);
  254. if (count < 1)
  255. Com_Error (ERR_DROP, "Map with no planes");
  256. cm.planes = Hunk_Alloc( ( BOX_PLANES + count ) * sizeof( *cm.planes ), h_high );
  257. cm.numPlanes = count;
  258. out = cm.planes;
  259. for ( i=0 ; i<count ; i++, in++, out++)
  260. {
  261. bits = 0;
  262. for (j=0 ; j<3 ; j++)
  263. {
  264. out->normal[j] = LittleFloat (in->normal[j]);
  265. if (out->normal[j] < 0)
  266. bits |= 1<<j;
  267. }
  268. out->dist = LittleFloat (in->dist);
  269. out->type = PlaneTypeForNormal( out->normal );
  270. out->signbits = bits;
  271. }
  272. }
  273. /*
  274. =================
  275. CMod_LoadLeafBrushes
  276. =================
  277. */
  278. void CMod_LoadLeafBrushes (lump_t *l)
  279. {
  280. int i;
  281. int *out;
  282. int *in;
  283. int count;
  284. in = (void *)(cmod_base + l->fileofs);
  285. if (l->filelen % sizeof(*in))
  286. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  287. count = l->filelen / sizeof(*in);
  288. cm.leafbrushes = Hunk_Alloc( (count + BOX_BRUSHES) * sizeof( *cm.leafbrushes ), h_high );
  289. cm.numLeafBrushes = count;
  290. out = cm.leafbrushes;
  291. for ( i=0 ; i<count ; i++, in++, out++) {
  292. *out = LittleLong (*in);
  293. }
  294. }
  295. /*
  296. =================
  297. CMod_LoadLeafSurfaces
  298. =================
  299. */
  300. void CMod_LoadLeafSurfaces( lump_t *l )
  301. {
  302. int i;
  303. int *out;
  304. int *in;
  305. int count;
  306. in = (void *)(cmod_base + l->fileofs);
  307. if (l->filelen % sizeof(*in))
  308. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  309. count = l->filelen / sizeof(*in);
  310. cm.leafsurfaces = Hunk_Alloc( count * sizeof( *cm.leafsurfaces ), h_high );
  311. cm.numLeafSurfaces = count;
  312. out = cm.leafsurfaces;
  313. for ( i=0 ; i<count ; i++, in++, out++) {
  314. *out = LittleLong (*in);
  315. }
  316. }
  317. /*
  318. =================
  319. CMod_LoadBrushSides
  320. =================
  321. */
  322. void CMod_LoadBrushSides (lump_t *l)
  323. {
  324. int i;
  325. cbrushside_t *out;
  326. dbrushside_t *in;
  327. int count;
  328. int num;
  329. in = (void *)(cmod_base + l->fileofs);
  330. if ( l->filelen % sizeof(*in) ) {
  331. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  332. }
  333. count = l->filelen / sizeof(*in);
  334. cm.brushsides = Hunk_Alloc( ( BOX_SIDES + count ) * sizeof( *cm.brushsides ), h_high );
  335. cm.numBrushSides = count;
  336. out = cm.brushsides;
  337. for ( i=0 ; i<count ; i++, in++, out++) {
  338. num = LittleLong( in->planeNum );
  339. out->plane = &cm.planes[num];
  340. out->shaderNum = LittleLong( in->shaderNum );
  341. if ( out->shaderNum < 0 || out->shaderNum >= cm.numShaders ) {
  342. Com_Error( ERR_DROP, "CMod_LoadBrushSides: bad shaderNum: %i", out->shaderNum );
  343. }
  344. out->surfaceFlags = cm.shaders[out->shaderNum].surfaceFlags;
  345. }
  346. }
  347. /*
  348. =================
  349. CMod_LoadEntityString
  350. =================
  351. */
  352. void CMod_LoadEntityString( lump_t *l ) {
  353. cm.entityString = Hunk_Alloc( l->filelen, h_high );
  354. cm.numEntityChars = l->filelen;
  355. Com_Memcpy (cm.entityString, cmod_base + l->fileofs, l->filelen);
  356. }
  357. /*
  358. =================
  359. CMod_LoadVisibility
  360. =================
  361. */
  362. #define VIS_HEADER 8
  363. void CMod_LoadVisibility( lump_t *l ) {
  364. int len;
  365. byte *buf;
  366. len = l->filelen;
  367. if ( !len ) {
  368. cm.clusterBytes = ( cm.numClusters + 31 ) & ~31;
  369. cm.visibility = Hunk_Alloc( cm.clusterBytes, h_high );
  370. Com_Memset( cm.visibility, 255, cm.clusterBytes );
  371. return;
  372. }
  373. buf = cmod_base + l->fileofs;
  374. cm.vised = qtrue;
  375. cm.visibility = Hunk_Alloc( len, h_high );
  376. cm.numClusters = LittleLong( ((int *)buf)[0] );
  377. cm.clusterBytes = LittleLong( ((int *)buf)[1] );
  378. Com_Memcpy (cm.visibility, buf + VIS_HEADER, len - VIS_HEADER );
  379. }
  380. //==================================================================
  381. /*
  382. =================
  383. CMod_LoadPatches
  384. =================
  385. */
  386. #define MAX_PATCH_VERTS 1024
  387. void CMod_LoadPatches( lump_t *surfs, lump_t *verts ) {
  388. drawVert_t *dv, *dv_p;
  389. dsurface_t *in;
  390. int count;
  391. int i, j;
  392. int c;
  393. cPatch_t *patch;
  394. vec3_t points[MAX_PATCH_VERTS];
  395. int width, height;
  396. int shaderNum;
  397. in = (void *)(cmod_base + surfs->fileofs);
  398. if (surfs->filelen % sizeof(*in))
  399. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  400. cm.numSurfaces = count = surfs->filelen / sizeof(*in);
  401. cm.surfaces = Hunk_Alloc( cm.numSurfaces * sizeof( cm.surfaces[0] ), h_high );
  402. dv = (void *)(cmod_base + verts->fileofs);
  403. if (verts->filelen % sizeof(*dv))
  404. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  405. // scan through all the surfaces, but only load patches,
  406. // not planar faces
  407. for ( i = 0 ; i < count ; i++, in++ ) {
  408. if ( LittleLong( in->surfaceType ) != MST_PATCH ) {
  409. continue; // ignore other surfaces
  410. }
  411. // FIXME: check for non-colliding patches
  412. cm.surfaces[ i ] = patch = Hunk_Alloc( sizeof( *patch ), h_high );
  413. // load the full drawverts onto the stack
  414. width = LittleLong( in->patchWidth );
  415. height = LittleLong( in->patchHeight );
  416. c = width * height;
  417. if ( c > MAX_PATCH_VERTS ) {
  418. Com_Error( ERR_DROP, "ParseMesh: MAX_PATCH_VERTS" );
  419. }
  420. dv_p = dv + LittleLong( in->firstVert );
  421. for ( j = 0 ; j < c ; j++, dv_p++ ) {
  422. points[j][0] = LittleFloat( dv_p->xyz[0] );
  423. points[j][1] = LittleFloat( dv_p->xyz[1] );
  424. points[j][2] = LittleFloat( dv_p->xyz[2] );
  425. }
  426. shaderNum = LittleLong( in->shaderNum );
  427. patch->contents = cm.shaders[shaderNum].contentFlags;
  428. patch->surfaceFlags = cm.shaders[shaderNum].surfaceFlags;
  429. // create the internal facet structure
  430. patch->pc = CM_GeneratePatchCollide( width, height, points );
  431. }
  432. }
  433. //==================================================================
  434. unsigned CM_LumpChecksum(lump_t *lump) {
  435. return LittleLong (Com_BlockChecksum (cmod_base + lump->fileofs, lump->filelen));
  436. }
  437. unsigned CM_Checksum(dheader_t *header) {
  438. unsigned checksums[16];
  439. checksums[0] = CM_LumpChecksum(&header->lumps[LUMP_SHADERS]);
  440. checksums[1] = CM_LumpChecksum(&header->lumps[LUMP_LEAFS]);
  441. checksums[2] = CM_LumpChecksum(&header->lumps[LUMP_LEAFBRUSHES]);
  442. checksums[3] = CM_LumpChecksum(&header->lumps[LUMP_LEAFSURFACES]);
  443. checksums[4] = CM_LumpChecksum(&header->lumps[LUMP_PLANES]);
  444. checksums[5] = CM_LumpChecksum(&header->lumps[LUMP_BRUSHSIDES]);
  445. checksums[6] = CM_LumpChecksum(&header->lumps[LUMP_BRUSHES]);
  446. checksums[7] = CM_LumpChecksum(&header->lumps[LUMP_MODELS]);
  447. checksums[8] = CM_LumpChecksum(&header->lumps[LUMP_NODES]);
  448. checksums[9] = CM_LumpChecksum(&header->lumps[LUMP_SURFACES]);
  449. checksums[10] = CM_LumpChecksum(&header->lumps[LUMP_DRAWVERTS]);
  450. return LittleLong(Com_BlockChecksum(checksums, 11 * 4));
  451. }
  452. /*
  453. ==================
  454. CM_LoadMap
  455. Loads in the map and all submodels
  456. ==================
  457. */
  458. void CM_LoadMap( const char *name, qboolean clientload, int *checksum ) {
  459. int *buf;
  460. int i;
  461. dheader_t header;
  462. int length;
  463. static unsigned last_checksum;
  464. if ( !name || !name[0] ) {
  465. Com_Error( ERR_DROP, "CM_LoadMap: NULL name" );
  466. }
  467. #ifndef BSPC
  468. cm_noAreas = Cvar_Get ("cm_noAreas", "0", CVAR_CHEAT);
  469. cm_noCurves = Cvar_Get ("cm_noCurves", "0", CVAR_CHEAT);
  470. cm_playerCurveClip = Cvar_Get ("cm_playerCurveClip", "1", CVAR_ARCHIVE|CVAR_CHEAT );
  471. #endif
  472. Com_DPrintf( "CM_LoadMap( %s, %i )\n", name, clientload );
  473. if ( !strcmp( cm.name, name ) && clientload ) {
  474. *checksum = last_checksum;
  475. return;
  476. }
  477. // free old stuff
  478. Com_Memset( &cm, 0, sizeof( cm ) );
  479. CM_ClearLevelPatches();
  480. if ( !name[0] ) {
  481. cm.numLeafs = 1;
  482. cm.numClusters = 1;
  483. cm.numAreas = 1;
  484. cm.cmodels = Hunk_Alloc( sizeof( *cm.cmodels ), h_high );
  485. *checksum = 0;
  486. return;
  487. }
  488. //
  489. // load the file
  490. //
  491. #ifndef BSPC
  492. length = FS_ReadFile( name, (void **)&buf );
  493. #else
  494. length = LoadQuakeFile((quakefile_t *) name, (void **)&buf);
  495. #endif
  496. if ( !buf ) {
  497. Com_Error (ERR_DROP, "Couldn't load %s", name);
  498. }
  499. last_checksum = LittleLong (Com_BlockChecksum (buf, length));
  500. *checksum = last_checksum;
  501. header = *(dheader_t *)buf;
  502. for (i=0 ; i<sizeof(dheader_t)/4 ; i++) {
  503. ((int *)&header)[i] = LittleLong ( ((int *)&header)[i]);
  504. }
  505. if ( header.version != BSP_VERSION ) {
  506. Com_Error (ERR_DROP, "CM_LoadMap: %s has wrong version number (%i should be %i)"
  507. , name, header.version, BSP_VERSION );
  508. }
  509. cmod_base = (byte *)buf;
  510. // load into heap
  511. CMod_LoadShaders( &header.lumps[LUMP_SHADERS] );
  512. CMod_LoadLeafs (&header.lumps[LUMP_LEAFS]);
  513. CMod_LoadLeafBrushes (&header.lumps[LUMP_LEAFBRUSHES]);
  514. CMod_LoadLeafSurfaces (&header.lumps[LUMP_LEAFSURFACES]);
  515. CMod_LoadPlanes (&header.lumps[LUMP_PLANES]);
  516. CMod_LoadBrushSides (&header.lumps[LUMP_BRUSHSIDES]);
  517. CMod_LoadBrushes (&header.lumps[LUMP_BRUSHES]);
  518. CMod_LoadSubmodels (&header.lumps[LUMP_MODELS]);
  519. CMod_LoadNodes (&header.lumps[LUMP_NODES]);
  520. CMod_LoadEntityString (&header.lumps[LUMP_ENTITIES]);
  521. CMod_LoadVisibility( &header.lumps[LUMP_VISIBILITY] );
  522. CMod_LoadPatches( &header.lumps[LUMP_SURFACES], &header.lumps[LUMP_DRAWVERTS] );
  523. // we are NOT freeing the file, because it is cached for the ref
  524. FS_FreeFile (buf);
  525. CM_InitBoxHull ();
  526. CM_FloodAreaConnections ();
  527. // allow this to be cached if it is loaded by the server
  528. if ( !clientload ) {
  529. Q_strncpyz( cm.name, name, sizeof( cm.name ) );
  530. }
  531. }
  532. /*
  533. ==================
  534. CM_ClearMap
  535. ==================
  536. */
  537. void CM_ClearMap( void ) {
  538. Com_Memset( &cm, 0, sizeof( cm ) );
  539. CM_ClearLevelPatches();
  540. }
  541. /*
  542. ==================
  543. CM_ClipHandleToModel
  544. ==================
  545. */
  546. cmodel_t *CM_ClipHandleToModel( clipHandle_t handle ) {
  547. if ( handle < 0 ) {
  548. Com_Error( ERR_DROP, "CM_ClipHandleToModel: bad handle %i", handle );
  549. }
  550. if ( handle < cm.numSubModels ) {
  551. return &cm.cmodels[handle];
  552. }
  553. if ( handle == BOX_MODEL_HANDLE ) {
  554. return &box_model;
  555. }
  556. if ( handle < MAX_SUBMODELS ) {
  557. Com_Error( ERR_DROP, "CM_ClipHandleToModel: bad handle %i < %i < %i",
  558. cm.numSubModels, handle, MAX_SUBMODELS );
  559. }
  560. Com_Error( ERR_DROP, "CM_ClipHandleToModel: bad handle %i", handle + MAX_SUBMODELS );
  561. return NULL;
  562. }
  563. /*
  564. ==================
  565. CM_InlineModel
  566. ==================
  567. */
  568. clipHandle_t CM_InlineModel( int index ) {
  569. if ( index < 0 || index >= cm.numSubModels ) {
  570. Com_Error (ERR_DROP, "CM_InlineModel: bad number");
  571. }
  572. return index;
  573. }
  574. int CM_NumClusters( void ) {
  575. return cm.numClusters;
  576. }
  577. int CM_NumInlineModels( void ) {
  578. return cm.numSubModels;
  579. }
  580. char *CM_EntityString( void ) {
  581. return cm.entityString;
  582. }
  583. int CM_LeafCluster( int leafnum ) {
  584. if (leafnum < 0 || leafnum >= cm.numLeafs) {
  585. Com_Error (ERR_DROP, "CM_LeafCluster: bad number");
  586. }
  587. return cm.leafs[leafnum].cluster;
  588. }
  589. int CM_LeafArea( int leafnum ) {
  590. if ( leafnum < 0 || leafnum >= cm.numLeafs ) {
  591. Com_Error (ERR_DROP, "CM_LeafArea: bad number");
  592. }
  593. return cm.leafs[leafnum].area;
  594. }
  595. //=======================================================================
  596. /*
  597. ===================
  598. CM_InitBoxHull
  599. Set up the planes and nodes so that the six floats of a bounding box
  600. can just be stored out and get a proper clipping hull structure.
  601. ===================
  602. */
  603. void CM_InitBoxHull (void)
  604. {
  605. int i;
  606. int side;
  607. cplane_t *p;
  608. cbrushside_t *s;
  609. box_planes = &cm.planes[cm.numPlanes];
  610. box_brush = &cm.brushes[cm.numBrushes];
  611. box_brush->numsides = 6;
  612. box_brush->sides = cm.brushsides + cm.numBrushSides;
  613. box_brush->contents = CONTENTS_BODY;
  614. box_model.leaf.numLeafBrushes = 1;
  615. // box_model.leaf.firstLeafBrush = cm.numBrushes;
  616. box_model.leaf.firstLeafBrush = cm.numLeafBrushes;
  617. cm.leafbrushes[cm.numLeafBrushes] = cm.numBrushes;
  618. for (i=0 ; i<6 ; i++)
  619. {
  620. side = i&1;
  621. // brush sides
  622. s = &cm.brushsides[cm.numBrushSides+i];
  623. s->plane = cm.planes + (cm.numPlanes+i*2+side);
  624. s->surfaceFlags = 0;
  625. // planes
  626. p = &box_planes[i*2];
  627. p->type = i>>1;
  628. p->signbits = 0;
  629. VectorClear (p->normal);
  630. p->normal[i>>1] = 1;
  631. p = &box_planes[i*2+1];
  632. p->type = 3 + (i>>1);
  633. p->signbits = 0;
  634. VectorClear (p->normal);
  635. p->normal[i>>1] = -1;
  636. SetPlaneSignbits( p );
  637. }
  638. }
  639. /*
  640. ===================
  641. CM_TempBoxModel
  642. To keep everything totally uniform, bounding boxes are turned into small
  643. BSP trees instead of being compared directly.
  644. Capsules are handled differently though.
  645. ===================
  646. */
  647. clipHandle_t CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, int capsule ) {
  648. VectorCopy( mins, box_model.mins );
  649. VectorCopy( maxs, box_model.maxs );
  650. if ( capsule ) {
  651. return CAPSULE_MODEL_HANDLE;
  652. }
  653. box_planes[0].dist = maxs[0];
  654. box_planes[1].dist = -maxs[0];
  655. box_planes[2].dist = mins[0];
  656. box_planes[3].dist = -mins[0];
  657. box_planes[4].dist = maxs[1];
  658. box_planes[5].dist = -maxs[1];
  659. box_planes[6].dist = mins[1];
  660. box_planes[7].dist = -mins[1];
  661. box_planes[8].dist = maxs[2];
  662. box_planes[9].dist = -maxs[2];
  663. box_planes[10].dist = mins[2];
  664. box_planes[11].dist = -mins[2];
  665. VectorCopy( mins, box_brush->bounds[0] );
  666. VectorCopy( maxs, box_brush->bounds[1] );
  667. return BOX_MODEL_HANDLE;
  668. }
  669. /*
  670. ===================
  671. CM_ModelBounds
  672. ===================
  673. */
  674. void CM_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs ) {
  675. cmodel_t *cmod;
  676. cmod = CM_ClipHandleToModel( model );
  677. VectorCopy( cmod->mins, mins );
  678. VectorCopy( cmod->maxs, maxs );
  679. }