cmodel.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // cmodel.c -- model loading
  16. #include "qcommon.h"
  17. typedef struct
  18. {
  19. cplane_t *plane;
  20. int children[2]; // negative numbers are leafs
  21. } cnode_t;
  22. typedef struct
  23. {
  24. cplane_t *plane;
  25. mapsurface_t *surface;
  26. } cbrushside_t;
  27. typedef struct
  28. {
  29. int contents;
  30. int cluster;
  31. int area;
  32. unsigned short firstleafbrush;
  33. unsigned short numleafbrushes;
  34. } cleaf_t;
  35. typedef struct
  36. {
  37. int contents;
  38. int numsides;
  39. int firstbrushside;
  40. int checkcount; // to avoid repeated testings
  41. } cbrush_t;
  42. typedef struct
  43. {
  44. int numareaportals;
  45. int firstareaportal;
  46. int floodnum; // if two areas have equal floodnums, they are connected
  47. int floodvalid;
  48. } carea_t;
  49. int checkcount;
  50. char map_name[MAX_QPATH];
  51. int numbrushsides;
  52. cbrushside_t map_brushsides[MAX_MAP_BRUSHSIDES];
  53. int numtexinfo;
  54. mapsurface_t map_surfaces[MAX_MAP_TEXINFO];
  55. int numplanes;
  56. cplane_t map_planes[MAX_MAP_PLANES+6]; // extra for box hull
  57. int numnodes;
  58. cnode_t map_nodes[MAX_MAP_NODES+6]; // extra for box hull
  59. int numleafs = 1; // allow leaf funcs to be called without a map
  60. cleaf_t map_leafs[MAX_MAP_LEAFS];
  61. int emptyleaf, solidleaf;
  62. int numleafbrushes;
  63. unsigned short map_leafbrushes[MAX_MAP_LEAFBRUSHES];
  64. int numcmodels;
  65. cmodel_t map_cmodels[MAX_MAP_MODELS];
  66. int numbrushes;
  67. cbrush_t map_brushes[MAX_MAP_BRUSHES];
  68. int numvisibility;
  69. byte map_visibility[MAX_MAP_VISIBILITY];
  70. dvis_t *map_vis = (dvis_t *)map_visibility;
  71. int numentitychars;
  72. char map_entitystring[MAX_MAP_ENTSTRING];
  73. int numareas = 1;
  74. carea_t map_areas[MAX_MAP_AREAS];
  75. int numareaportals;
  76. dareaportal_t map_areaportals[MAX_MAP_AREAPORTALS];
  77. int numclusters = 1;
  78. mapsurface_t nullsurface;
  79. int floodvalid;
  80. qboolean portalopen[MAX_MAP_AREAPORTALS];
  81. cvar_t *map_noareas;
  82. void CM_InitBoxHull (void);
  83. void FloodAreaConnections (void);
  84. int c_pointcontents;
  85. int c_traces, c_brush_traces;
  86. /*
  87. ===============================================================================
  88. MAP LOADING
  89. ===============================================================================
  90. */
  91. byte *cmod_base;
  92. /*
  93. =================
  94. CMod_LoadSubmodels
  95. =================
  96. */
  97. void CMod_LoadSubmodels (lump_t *l)
  98. {
  99. dmodel_t *in;
  100. cmodel_t *out;
  101. int i, j, count;
  102. in = (void *)(cmod_base + l->fileofs);
  103. if (l->filelen % sizeof(*in))
  104. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  105. count = l->filelen / sizeof(*in);
  106. if (count < 1)
  107. Com_Error (ERR_DROP, "Map with no models");
  108. if (count > MAX_MAP_MODELS)
  109. Com_Error (ERR_DROP, "Map has too many models");
  110. numcmodels = count;
  111. for ( i=0 ; i<count ; i++, in++, out++)
  112. {
  113. out = &map_cmodels[i];
  114. for (j=0 ; j<3 ; j++)
  115. { // spread the mins / maxs by a pixel
  116. out->mins[j] = LittleFloat (in->mins[j]) - 1;
  117. out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
  118. out->origin[j] = LittleFloat (in->origin[j]);
  119. }
  120. out->headnode = LittleLong (in->headnode);
  121. }
  122. }
  123. /*
  124. =================
  125. CMod_LoadSurfaces
  126. =================
  127. */
  128. void CMod_LoadSurfaces (lump_t *l)
  129. {
  130. texinfo_t *in;
  131. mapsurface_t *out;
  132. int i, count;
  133. in = (void *)(cmod_base + l->fileofs);
  134. if (l->filelen % sizeof(*in))
  135. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  136. count = l->filelen / sizeof(*in);
  137. if (count < 1)
  138. Com_Error (ERR_DROP, "Map with no surfaces");
  139. if (count > MAX_MAP_TEXINFO)
  140. Com_Error (ERR_DROP, "Map has too many surfaces");
  141. numtexinfo = count;
  142. out = map_surfaces;
  143. for ( i=0 ; i<count ; i++, in++, out++)
  144. {
  145. strncpy (out->c.name, in->texture, sizeof(out->c.name)-1);
  146. strncpy (out->rname, in->texture, sizeof(out->rname)-1);
  147. out->c.flags = LittleLong (in->flags);
  148. out->c.value = LittleLong (in->value);
  149. }
  150. }
  151. /*
  152. =================
  153. CMod_LoadNodes
  154. =================
  155. */
  156. void CMod_LoadNodes (lump_t *l)
  157. {
  158. dnode_t *in;
  159. int child;
  160. cnode_t *out;
  161. int i, j, count;
  162. in = (void *)(cmod_base + l->fileofs);
  163. if (l->filelen % sizeof(*in))
  164. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  165. count = l->filelen / sizeof(*in);
  166. if (count < 1)
  167. Com_Error (ERR_DROP, "Map has no nodes");
  168. if (count > MAX_MAP_NODES)
  169. Com_Error (ERR_DROP, "Map has too many nodes");
  170. out = map_nodes;
  171. numnodes = count;
  172. for (i=0 ; i<count ; i++, out++, in++)
  173. {
  174. out->plane = map_planes + LittleLong(in->planenum);
  175. for (j=0 ; j<2 ; j++)
  176. {
  177. child = LittleLong (in->children[j]);
  178. out->children[j] = child;
  179. }
  180. }
  181. }
  182. /*
  183. =================
  184. CMod_LoadBrushes
  185. =================
  186. */
  187. void CMod_LoadBrushes (lump_t *l)
  188. {
  189. dbrush_t *in;
  190. cbrush_t *out;
  191. int i, count;
  192. in = (void *)(cmod_base + l->fileofs);
  193. if (l->filelen % sizeof(*in))
  194. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  195. count = l->filelen / sizeof(*in);
  196. if (count > MAX_MAP_BRUSHES)
  197. Com_Error (ERR_DROP, "Map has too many brushes");
  198. out = map_brushes;
  199. numbrushes = count;
  200. for (i=0 ; i<count ; i++, out++, in++)
  201. {
  202. out->firstbrushside = LittleLong(in->firstside);
  203. out->numsides = LittleLong(in->numsides);
  204. out->contents = LittleLong(in->contents);
  205. }
  206. }
  207. /*
  208. =================
  209. CMod_LoadLeafs
  210. =================
  211. */
  212. void CMod_LoadLeafs (lump_t *l)
  213. {
  214. int i;
  215. cleaf_t *out;
  216. dleaf_t *in;
  217. int count;
  218. in = (void *)(cmod_base + l->fileofs);
  219. if (l->filelen % sizeof(*in))
  220. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  221. count = l->filelen / sizeof(*in);
  222. if (count < 1)
  223. Com_Error (ERR_DROP, "Map with no leafs");
  224. // need to save space for box planes
  225. if (count > MAX_MAP_PLANES)
  226. Com_Error (ERR_DROP, "Map has too many planes");
  227. out = map_leafs;
  228. numleafs = count;
  229. numclusters = 0;
  230. for ( i=0 ; i<count ; i++, in++, out++)
  231. {
  232. out->contents = LittleLong (in->contents);
  233. out->cluster = LittleShort (in->cluster);
  234. out->area = LittleShort (in->area);
  235. out->firstleafbrush = LittleShort (in->firstleafbrush);
  236. out->numleafbrushes = LittleShort (in->numleafbrushes);
  237. if (out->cluster >= numclusters)
  238. numclusters = out->cluster + 1;
  239. }
  240. if (map_leafs[0].contents != CONTENTS_SOLID)
  241. Com_Error (ERR_DROP, "Map leaf 0 is not CONTENTS_SOLID");
  242. solidleaf = 0;
  243. emptyleaf = -1;
  244. for (i=1 ; i<numleafs ; i++)
  245. {
  246. if (!map_leafs[i].contents)
  247. {
  248. emptyleaf = i;
  249. break;
  250. }
  251. }
  252. if (emptyleaf == -1)
  253. Com_Error (ERR_DROP, "Map does not have an empty leaf");
  254. }
  255. /*
  256. =================
  257. CMod_LoadPlanes
  258. =================
  259. */
  260. void CMod_LoadPlanes (lump_t *l)
  261. {
  262. int i, j;
  263. cplane_t *out;
  264. dplane_t *in;
  265. int count;
  266. int bits;
  267. in = (void *)(cmod_base + l->fileofs);
  268. if (l->filelen % sizeof(*in))
  269. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  270. count = l->filelen / sizeof(*in);
  271. if (count < 1)
  272. Com_Error (ERR_DROP, "Map with no planes");
  273. // need to save space for box planes
  274. if (count > MAX_MAP_PLANES)
  275. Com_Error (ERR_DROP, "Map has too many planes");
  276. out = map_planes;
  277. numplanes = count;
  278. for ( i=0 ; i<count ; i++, in++, out++)
  279. {
  280. bits = 0;
  281. for (j=0 ; j<3 ; j++)
  282. {
  283. out->normal[j] = LittleFloat (in->normal[j]);
  284. if (out->normal[j] < 0)
  285. bits |= 1<<j;
  286. }
  287. out->dist = LittleFloat (in->dist);
  288. out->type = LittleLong (in->type);
  289. out->signbits = bits;
  290. }
  291. }
  292. /*
  293. =================
  294. CMod_LoadLeafBrushes
  295. =================
  296. */
  297. void CMod_LoadLeafBrushes (lump_t *l)
  298. {
  299. int i;
  300. unsigned short *out;
  301. unsigned short *in;
  302. int count;
  303. in = (void *)(cmod_base + l->fileofs);
  304. if (l->filelen % sizeof(*in))
  305. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  306. count = l->filelen / sizeof(*in);
  307. if (count < 1)
  308. Com_Error (ERR_DROP, "Map with no planes");
  309. // need to save space for box planes
  310. if (count > MAX_MAP_LEAFBRUSHES)
  311. Com_Error (ERR_DROP, "Map has too many leafbrushes");
  312. out = map_leafbrushes;
  313. numleafbrushes = count;
  314. for ( i=0 ; i<count ; i++, in++, out++)
  315. *out = LittleShort (*in);
  316. }
  317. /*
  318. =================
  319. CMod_LoadBrushSides
  320. =================
  321. */
  322. void CMod_LoadBrushSides (lump_t *l)
  323. {
  324. int i, j;
  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. count = l->filelen / sizeof(*in);
  333. // need to save space for box planes
  334. if (count > MAX_MAP_BRUSHSIDES)
  335. Com_Error (ERR_DROP, "Map has too many planes");
  336. out = map_brushsides;
  337. numbrushsides = count;
  338. for ( i=0 ; i<count ; i++, in++, out++)
  339. {
  340. num = LittleShort (in->planenum);
  341. out->plane = &map_planes[num];
  342. j = LittleShort (in->texinfo);
  343. if (j >= numtexinfo)
  344. Com_Error (ERR_DROP, "Bad brushside texinfo");
  345. out->surface = &map_surfaces[j];
  346. }
  347. }
  348. /*
  349. =================
  350. CMod_LoadAreas
  351. =================
  352. */
  353. void CMod_LoadAreas (lump_t *l)
  354. {
  355. int i;
  356. carea_t *out;
  357. darea_t *in;
  358. int count;
  359. in = (void *)(cmod_base + l->fileofs);
  360. if (l->filelen % sizeof(*in))
  361. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  362. count = l->filelen / sizeof(*in);
  363. if (count > MAX_MAP_AREAS)
  364. Com_Error (ERR_DROP, "Map has too many areas");
  365. out = map_areas;
  366. numareas = count;
  367. for ( i=0 ; i<count ; i++, in++, out++)
  368. {
  369. out->numareaportals = LittleLong (in->numareaportals);
  370. out->firstareaportal = LittleLong (in->firstareaportal);
  371. out->floodvalid = 0;
  372. out->floodnum = 0;
  373. }
  374. }
  375. /*
  376. =================
  377. CMod_LoadAreaPortals
  378. =================
  379. */
  380. void CMod_LoadAreaPortals (lump_t *l)
  381. {
  382. int i;
  383. dareaportal_t *out;
  384. dareaportal_t *in;
  385. int count;
  386. in = (void *)(cmod_base + l->fileofs);
  387. if (l->filelen % sizeof(*in))
  388. Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
  389. count = l->filelen / sizeof(*in);
  390. if (count > MAX_MAP_AREAS)
  391. Com_Error (ERR_DROP, "Map has too many areas");
  392. out = map_areaportals;
  393. numareaportals = count;
  394. for ( i=0 ; i<count ; i++, in++, out++)
  395. {
  396. out->portalnum = LittleLong (in->portalnum);
  397. out->otherarea = LittleLong (in->otherarea);
  398. }
  399. }
  400. /*
  401. =================
  402. CMod_LoadVisibility
  403. =================
  404. */
  405. void CMod_LoadVisibility (lump_t *l)
  406. {
  407. int i;
  408. numvisibility = l->filelen;
  409. if (l->filelen > MAX_MAP_VISIBILITY)
  410. Com_Error (ERR_DROP, "Map has too large visibility lump");
  411. memcpy (map_visibility, cmod_base + l->fileofs, l->filelen);
  412. map_vis->numclusters = LittleLong (map_vis->numclusters);
  413. for (i=0 ; i<map_vis->numclusters ; i++)
  414. {
  415. map_vis->bitofs[i][0] = LittleLong (map_vis->bitofs[i][0]);
  416. map_vis->bitofs[i][1] = LittleLong (map_vis->bitofs[i][1]);
  417. }
  418. }
  419. /*
  420. =================
  421. CMod_LoadEntityString
  422. =================
  423. */
  424. void CMod_LoadEntityString (lump_t *l)
  425. {
  426. numentitychars = l->filelen;
  427. if (l->filelen > MAX_MAP_ENTSTRING)
  428. Com_Error (ERR_DROP, "Map has too large entity lump");
  429. memcpy (map_entitystring, cmod_base + l->fileofs, l->filelen);
  430. }
  431. /*
  432. ==================
  433. CM_LoadMap
  434. Loads in the map and all submodels
  435. ==================
  436. */
  437. cmodel_t *CM_LoadMap (char *name, qboolean clientload, unsigned *checksum)
  438. {
  439. unsigned *buf;
  440. int i;
  441. dheader_t header;
  442. int length;
  443. static unsigned last_checksum;
  444. map_noareas = Cvar_Get ("map_noareas", "0", 0);
  445. if ( !strcmp (map_name, name) && (clientload || !Cvar_VariableValue ("flushmap")) )
  446. {
  447. *checksum = last_checksum;
  448. if (!clientload)
  449. {
  450. memset (portalopen, 0, sizeof(portalopen));
  451. FloodAreaConnections ();
  452. }
  453. return &map_cmodels[0]; // still have the right version
  454. }
  455. // free old stuff
  456. numplanes = 0;
  457. numnodes = 0;
  458. numleafs = 0;
  459. numcmodels = 0;
  460. numvisibility = 0;
  461. numentitychars = 0;
  462. map_entitystring[0] = 0;
  463. map_name[0] = 0;
  464. if (!name || !name[0])
  465. {
  466. numleafs = 1;
  467. numclusters = 1;
  468. numareas = 1;
  469. *checksum = 0;
  470. return &map_cmodels[0]; // cinematic servers won't have anything at all
  471. }
  472. //
  473. // load the file
  474. //
  475. length = FS_LoadFile (name, (void **)&buf);
  476. if (!buf)
  477. Com_Error (ERR_DROP, "Couldn't load %s", name);
  478. last_checksum = LittleLong (Com_BlockChecksum (buf, length));
  479. *checksum = last_checksum;
  480. header = *(dheader_t *)buf;
  481. for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
  482. ((int *)&header)[i] = LittleLong ( ((int *)&header)[i]);
  483. if (header.version != BSPVERSION)
  484. Com_Error (ERR_DROP, "CMod_LoadBrushModel: %s has wrong version number (%i should be %i)"
  485. , name, header.version, BSPVERSION);
  486. cmod_base = (byte *)buf;
  487. // load into heap
  488. CMod_LoadSurfaces (&header.lumps[LUMP_TEXINFO]);
  489. CMod_LoadLeafs (&header.lumps[LUMP_LEAFS]);
  490. CMod_LoadLeafBrushes (&header.lumps[LUMP_LEAFBRUSHES]);
  491. CMod_LoadPlanes (&header.lumps[LUMP_PLANES]);
  492. CMod_LoadBrushes (&header.lumps[LUMP_BRUSHES]);
  493. CMod_LoadBrushSides (&header.lumps[LUMP_BRUSHSIDES]);
  494. CMod_LoadSubmodels (&header.lumps[LUMP_MODELS]);
  495. CMod_LoadNodes (&header.lumps[LUMP_NODES]);
  496. CMod_LoadAreas (&header.lumps[LUMP_AREAS]);
  497. CMod_LoadAreaPortals (&header.lumps[LUMP_AREAPORTALS]);
  498. CMod_LoadVisibility (&header.lumps[LUMP_VISIBILITY]);
  499. CMod_LoadEntityString (&header.lumps[LUMP_ENTITIES]);
  500. FS_FreeFile (buf);
  501. CM_InitBoxHull ();
  502. memset (portalopen, 0, sizeof(portalopen));
  503. FloodAreaConnections ();
  504. strcpy (map_name, name);
  505. return &map_cmodels[0];
  506. }
  507. /*
  508. ==================
  509. CM_InlineModel
  510. ==================
  511. */
  512. cmodel_t *CM_InlineModel (char *name)
  513. {
  514. int num;
  515. if (!name || name[0] != '*')
  516. Com_Error (ERR_DROP, "CM_InlineModel: bad name");
  517. num = atoi (name+1);
  518. if (num < 1 || num >= numcmodels)
  519. Com_Error (ERR_DROP, "CM_InlineModel: bad number");
  520. return &map_cmodels[num];
  521. }
  522. int CM_NumClusters (void)
  523. {
  524. return numclusters;
  525. }
  526. int CM_NumInlineModels (void)
  527. {
  528. return numcmodels;
  529. }
  530. char *CM_EntityString (void)
  531. {
  532. return map_entitystring;
  533. }
  534. int CM_LeafContents (int leafnum)
  535. {
  536. if (leafnum < 0 || leafnum >= numleafs)
  537. Com_Error (ERR_DROP, "CM_LeafContents: bad number");
  538. return map_leafs[leafnum].contents;
  539. }
  540. int CM_LeafCluster (int leafnum)
  541. {
  542. if (leafnum < 0 || leafnum >= numleafs)
  543. Com_Error (ERR_DROP, "CM_LeafCluster: bad number");
  544. return map_leafs[leafnum].cluster;
  545. }
  546. int CM_LeafArea (int leafnum)
  547. {
  548. if (leafnum < 0 || leafnum >= numleafs)
  549. Com_Error (ERR_DROP, "CM_LeafArea: bad number");
  550. return map_leafs[leafnum].area;
  551. }
  552. //=======================================================================
  553. cplane_t *box_planes;
  554. int box_headnode;
  555. cbrush_t *box_brush;
  556. cleaf_t *box_leaf;
  557. /*
  558. ===================
  559. CM_InitBoxHull
  560. Set up the planes and nodes so that the six floats of a bounding box
  561. can just be stored out and get a proper clipping hull structure.
  562. ===================
  563. */
  564. void CM_InitBoxHull (void)
  565. {
  566. int i;
  567. int side;
  568. cnode_t *c;
  569. cplane_t *p;
  570. cbrushside_t *s;
  571. box_headnode = numnodes;
  572. box_planes = &map_planes[numplanes];
  573. if (numnodes+6 > MAX_MAP_NODES
  574. || numbrushes+1 > MAX_MAP_BRUSHES
  575. || numleafbrushes+1 > MAX_MAP_LEAFBRUSHES
  576. || numbrushsides+6 > MAX_MAP_BRUSHSIDES
  577. || numplanes+12 > MAX_MAP_PLANES)
  578. Com_Error (ERR_DROP, "Not enough room for box tree");
  579. box_brush = &map_brushes[numbrushes];
  580. box_brush->numsides = 6;
  581. box_brush->firstbrushside = numbrushsides;
  582. box_brush->contents = CONTENTS_MONSTER;
  583. box_leaf = &map_leafs[numleafs];
  584. box_leaf->contents = CONTENTS_MONSTER;
  585. box_leaf->firstleafbrush = numleafbrushes;
  586. box_leaf->numleafbrushes = 1;
  587. map_leafbrushes[numleafbrushes] = numbrushes;
  588. for (i=0 ; i<6 ; i++)
  589. {
  590. side = i&1;
  591. // brush sides
  592. s = &map_brushsides[numbrushsides+i];
  593. s->plane = map_planes + (numplanes+i*2+side);
  594. s->surface = &nullsurface;
  595. // nodes
  596. c = &map_nodes[box_headnode+i];
  597. c->plane = map_planes + (numplanes+i*2);
  598. c->children[side] = -1 - emptyleaf;
  599. if (i != 5)
  600. c->children[side^1] = box_headnode+i + 1;
  601. else
  602. c->children[side^1] = -1 - numleafs;
  603. // planes
  604. p = &box_planes[i*2];
  605. p->type = i>>1;
  606. p->signbits = 0;
  607. VectorClear (p->normal);
  608. p->normal[i>>1] = 1;
  609. p = &box_planes[i*2+1];
  610. p->type = 3 + (i>>1);
  611. p->signbits = 0;
  612. VectorClear (p->normal);
  613. p->normal[i>>1] = -1;
  614. }
  615. }
  616. /*
  617. ===================
  618. CM_HeadnodeForBox
  619. To keep everything totally uniform, bounding boxes are turned into small
  620. BSP trees instead of being compared directly.
  621. ===================
  622. */
  623. int CM_HeadnodeForBox (vec3_t mins, vec3_t maxs)
  624. {
  625. box_planes[0].dist = maxs[0];
  626. box_planes[1].dist = -maxs[0];
  627. box_planes[2].dist = mins[0];
  628. box_planes[3].dist = -mins[0];
  629. box_planes[4].dist = maxs[1];
  630. box_planes[5].dist = -maxs[1];
  631. box_planes[6].dist = mins[1];
  632. box_planes[7].dist = -mins[1];
  633. box_planes[8].dist = maxs[2];
  634. box_planes[9].dist = -maxs[2];
  635. box_planes[10].dist = mins[2];
  636. box_planes[11].dist = -mins[2];
  637. return box_headnode;
  638. }
  639. /*
  640. ==================
  641. CM_PointLeafnum_r
  642. ==================
  643. */
  644. int CM_PointLeafnum_r (vec3_t p, int num)
  645. {
  646. float d;
  647. cnode_t *node;
  648. cplane_t *plane;
  649. while (num >= 0)
  650. {
  651. node = map_nodes + num;
  652. plane = node->plane;
  653. if (plane->type < 3)
  654. d = p[plane->type] - plane->dist;
  655. else
  656. d = DotProduct (plane->normal, p) - plane->dist;
  657. if (d < 0)
  658. num = node->children[1];
  659. else
  660. num = node->children[0];
  661. }
  662. c_pointcontents++; // optimize counter
  663. return -1 - num;
  664. }
  665. int CM_PointLeafnum (vec3_t p)
  666. {
  667. if (!numplanes)
  668. return 0; // sound may call this without map loaded
  669. return CM_PointLeafnum_r (p, 0);
  670. }
  671. /*
  672. =============
  673. CM_BoxLeafnums
  674. Fills in a list of all the leafs touched
  675. =============
  676. */
  677. int leaf_count, leaf_maxcount;
  678. int *leaf_list;
  679. float *leaf_mins, *leaf_maxs;
  680. int leaf_topnode;
  681. void CM_BoxLeafnums_r (int nodenum)
  682. {
  683. cplane_t *plane;
  684. cnode_t *node;
  685. int s;
  686. while (1)
  687. {
  688. if (nodenum < 0)
  689. {
  690. if (leaf_count >= leaf_maxcount)
  691. {
  692. // Com_Printf ("CM_BoxLeafnums_r: overflow\n");
  693. return;
  694. }
  695. leaf_list[leaf_count++] = -1 - nodenum;
  696. return;
  697. }
  698. node = &map_nodes[nodenum];
  699. plane = node->plane;
  700. // s = BoxOnPlaneSide (leaf_mins, leaf_maxs, plane);
  701. s = BOX_ON_PLANE_SIDE(leaf_mins, leaf_maxs, plane);
  702. if (s == 1)
  703. nodenum = node->children[0];
  704. else if (s == 2)
  705. nodenum = node->children[1];
  706. else
  707. { // go down both
  708. if (leaf_topnode == -1)
  709. leaf_topnode = nodenum;
  710. CM_BoxLeafnums_r (node->children[0]);
  711. nodenum = node->children[1];
  712. }
  713. }
  714. }
  715. int CM_BoxLeafnums_headnode (vec3_t mins, vec3_t maxs, int *list, int listsize, int headnode, int *topnode)
  716. {
  717. leaf_list = list;
  718. leaf_count = 0;
  719. leaf_maxcount = listsize;
  720. leaf_mins = mins;
  721. leaf_maxs = maxs;
  722. leaf_topnode = -1;
  723. CM_BoxLeafnums_r (headnode);
  724. if (topnode)
  725. *topnode = leaf_topnode;
  726. return leaf_count;
  727. }
  728. int CM_BoxLeafnums (vec3_t mins, vec3_t maxs, int *list, int listsize, int *topnode)
  729. {
  730. return CM_BoxLeafnums_headnode (mins, maxs, list,
  731. listsize, map_cmodels[0].headnode, topnode);
  732. }
  733. /*
  734. ==================
  735. CM_PointContents
  736. ==================
  737. */
  738. int CM_PointContents (vec3_t p, int headnode)
  739. {
  740. int l;
  741. if (!numnodes) // map not loaded
  742. return 0;
  743. l = CM_PointLeafnum_r (p, headnode);
  744. return map_leafs[l].contents;
  745. }
  746. /*
  747. ==================
  748. CM_TransformedPointContents
  749. Handles offseting and rotation of the end points for moving and
  750. rotating entities
  751. ==================
  752. */
  753. int CM_TransformedPointContents (vec3_t p, int headnode, vec3_t origin, vec3_t angles)
  754. {
  755. vec3_t p_l;
  756. vec3_t temp;
  757. vec3_t forward, right, up;
  758. int l;
  759. // subtract origin offset
  760. VectorSubtract (p, origin, p_l);
  761. // rotate start and end into the models frame of reference
  762. if (headnode != box_headnode &&
  763. (angles[0] || angles[1] || angles[2]) )
  764. {
  765. AngleVectors (angles, forward, right, up);
  766. VectorCopy (p_l, temp);
  767. p_l[0] = DotProduct (temp, forward);
  768. p_l[1] = -DotProduct (temp, right);
  769. p_l[2] = DotProduct (temp, up);
  770. }
  771. l = CM_PointLeafnum_r (p_l, headnode);
  772. return map_leafs[l].contents;
  773. }
  774. /*
  775. ===============================================================================
  776. BOX TRACING
  777. ===============================================================================
  778. */
  779. // 1/32 epsilon to keep floating point happy
  780. #define DIST_EPSILON (0.03125)
  781. vec3_t trace_start, trace_end;
  782. vec3_t trace_mins, trace_maxs;
  783. vec3_t trace_extents;
  784. trace_t trace_trace;
  785. int trace_contents;
  786. qboolean trace_ispoint; // optimized case
  787. /*
  788. ================
  789. CM_ClipBoxToBrush
  790. ================
  791. */
  792. void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2,
  793. trace_t *trace, cbrush_t *brush)
  794. {
  795. int i, j;
  796. cplane_t *plane, *clipplane;
  797. float dist;
  798. float enterfrac, leavefrac;
  799. vec3_t ofs;
  800. float d1, d2;
  801. qboolean getout, startout;
  802. float f;
  803. cbrushside_t *side, *leadside;
  804. enterfrac = -1;
  805. leavefrac = 1;
  806. clipplane = NULL;
  807. if (!brush->numsides)
  808. return;
  809. c_brush_traces++;
  810. getout = false;
  811. startout = false;
  812. leadside = NULL;
  813. for (i=0 ; i<brush->numsides ; i++)
  814. {
  815. side = &map_brushsides[brush->firstbrushside+i];
  816. plane = side->plane;
  817. // FIXME: special case for axial
  818. if (!trace_ispoint)
  819. { // general box case
  820. // push the plane out apropriately for mins/maxs
  821. // FIXME: use signbits into 8 way lookup for each mins/maxs
  822. for (j=0 ; j<3 ; j++)
  823. {
  824. if (plane->normal[j] < 0)
  825. ofs[j] = maxs[j];
  826. else
  827. ofs[j] = mins[j];
  828. }
  829. dist = DotProduct (ofs, plane->normal);
  830. dist = plane->dist - dist;
  831. }
  832. else
  833. { // special point case
  834. dist = plane->dist;
  835. }
  836. d1 = DotProduct (p1, plane->normal) - dist;
  837. d2 = DotProduct (p2, plane->normal) - dist;
  838. if (d2 > 0)
  839. getout = true; // endpoint is not in solid
  840. if (d1 > 0)
  841. startout = true;
  842. // if completely in front of face, no intersection
  843. if (d1 > 0 && d2 >= d1)
  844. return;
  845. if (d1 <= 0 && d2 <= 0)
  846. continue;
  847. // crosses face
  848. if (d1 > d2)
  849. { // enter
  850. f = (d1-DIST_EPSILON) / (d1-d2);
  851. if (f > enterfrac)
  852. {
  853. enterfrac = f;
  854. clipplane = plane;
  855. leadside = side;
  856. }
  857. }
  858. else
  859. { // leave
  860. f = (d1+DIST_EPSILON) / (d1-d2);
  861. if (f < leavefrac)
  862. leavefrac = f;
  863. }
  864. }
  865. if (!startout)
  866. { // original point was inside brush
  867. trace->startsolid = true;
  868. if (!getout)
  869. trace->allsolid = true;
  870. return;
  871. }
  872. if (enterfrac < leavefrac)
  873. {
  874. if (enterfrac > -1 && enterfrac < trace->fraction)
  875. {
  876. if (enterfrac < 0)
  877. enterfrac = 0;
  878. trace->fraction = enterfrac;
  879. trace->plane = *clipplane;
  880. trace->surface = &(leadside->surface->c);
  881. trace->contents = brush->contents;
  882. }
  883. }
  884. }
  885. /*
  886. ================
  887. CM_TestBoxInBrush
  888. ================
  889. */
  890. void CM_TestBoxInBrush (vec3_t mins, vec3_t maxs, vec3_t p1,
  891. trace_t *trace, cbrush_t *brush)
  892. {
  893. int i, j;
  894. cplane_t *plane;
  895. float dist;
  896. vec3_t ofs;
  897. float d1;
  898. cbrushside_t *side;
  899. if (!brush->numsides)
  900. return;
  901. for (i=0 ; i<brush->numsides ; i++)
  902. {
  903. side = &map_brushsides[brush->firstbrushside+i];
  904. plane = side->plane;
  905. // FIXME: special case for axial
  906. // general box case
  907. // push the plane out apropriately for mins/maxs
  908. // FIXME: use signbits into 8 way lookup for each mins/maxs
  909. for (j=0 ; j<3 ; j++)
  910. {
  911. if (plane->normal[j] < 0)
  912. ofs[j] = maxs[j];
  913. else
  914. ofs[j] = mins[j];
  915. }
  916. dist = DotProduct (ofs, plane->normal);
  917. dist = plane->dist - dist;
  918. d1 = DotProduct (p1, plane->normal) - dist;
  919. // if completely in front of face, no intersection
  920. if (d1 > 0)
  921. return;
  922. }
  923. // inside this brush
  924. trace->startsolid = trace->allsolid = true;
  925. trace->fraction = 0;
  926. trace->contents = brush->contents;
  927. }
  928. /*
  929. ================
  930. CM_TraceToLeaf
  931. ================
  932. */
  933. void CM_TraceToLeaf (int leafnum)
  934. {
  935. int k;
  936. int brushnum;
  937. cleaf_t *leaf;
  938. cbrush_t *b;
  939. leaf = &map_leafs[leafnum];
  940. if ( !(leaf->contents & trace_contents))
  941. return;
  942. // trace line against all brushes in the leaf
  943. for (k=0 ; k<leaf->numleafbrushes ; k++)
  944. {
  945. brushnum = map_leafbrushes[leaf->firstleafbrush+k];
  946. b = &map_brushes[brushnum];
  947. if (b->checkcount == checkcount)
  948. continue; // already checked this brush in another leaf
  949. b->checkcount = checkcount;
  950. if ( !(b->contents & trace_contents))
  951. continue;
  952. CM_ClipBoxToBrush (trace_mins, trace_maxs, trace_start, trace_end, &trace_trace, b);
  953. if (!trace_trace.fraction)
  954. return;
  955. }
  956. }
  957. /*
  958. ================
  959. CM_TestInLeaf
  960. ================
  961. */
  962. void CM_TestInLeaf (int leafnum)
  963. {
  964. int k;
  965. int brushnum;
  966. cleaf_t *leaf;
  967. cbrush_t *b;
  968. leaf = &map_leafs[leafnum];
  969. if ( !(leaf->contents & trace_contents))
  970. return;
  971. // trace line against all brushes in the leaf
  972. for (k=0 ; k<leaf->numleafbrushes ; k++)
  973. {
  974. brushnum = map_leafbrushes[leaf->firstleafbrush+k];
  975. b = &map_brushes[brushnum];
  976. if (b->checkcount == checkcount)
  977. continue; // already checked this brush in another leaf
  978. b->checkcount = checkcount;
  979. if ( !(b->contents & trace_contents))
  980. continue;
  981. CM_TestBoxInBrush (trace_mins, trace_maxs, trace_start, &trace_trace, b);
  982. if (!trace_trace.fraction)
  983. return;
  984. }
  985. }
  986. /*
  987. ==================
  988. CM_RecursiveHullCheck
  989. ==================
  990. */
  991. void CM_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2)
  992. {
  993. cnode_t *node;
  994. cplane_t *plane;
  995. float t1, t2, offset;
  996. float frac, frac2;
  997. float idist;
  998. int i;
  999. vec3_t mid;
  1000. int side;
  1001. float midf;
  1002. if (trace_trace.fraction <= p1f)
  1003. return; // already hit something nearer
  1004. // if < 0, we are in a leaf node
  1005. if (num < 0)
  1006. {
  1007. CM_TraceToLeaf (-1-num);
  1008. return;
  1009. }
  1010. //
  1011. // find the point distances to the seperating plane
  1012. // and the offset for the size of the box
  1013. //
  1014. node = map_nodes + num;
  1015. plane = node->plane;
  1016. if (plane->type < 3)
  1017. {
  1018. t1 = p1[plane->type] - plane->dist;
  1019. t2 = p2[plane->type] - plane->dist;
  1020. offset = trace_extents[plane->type];
  1021. }
  1022. else
  1023. {
  1024. t1 = DotProduct (plane->normal, p1) - plane->dist;
  1025. t2 = DotProduct (plane->normal, p2) - plane->dist;
  1026. if (trace_ispoint)
  1027. offset = 0;
  1028. else
  1029. offset = fabs(trace_extents[0]*plane->normal[0]) +
  1030. fabs(trace_extents[1]*plane->normal[1]) +
  1031. fabs(trace_extents[2]*plane->normal[2]);
  1032. }
  1033. #if 0
  1034. CM_RecursiveHullCheck (node->children[0], p1f, p2f, p1, p2);
  1035. CM_RecursiveHullCheck (node->children[1], p1f, p2f, p1, p2);
  1036. return;
  1037. #endif
  1038. // see which sides we need to consider
  1039. if (t1 >= offset && t2 >= offset)
  1040. {
  1041. CM_RecursiveHullCheck (node->children[0], p1f, p2f, p1, p2);
  1042. return;
  1043. }
  1044. if (t1 < -offset && t2 < -offset)
  1045. {
  1046. CM_RecursiveHullCheck (node->children[1], p1f, p2f, p1, p2);
  1047. return;
  1048. }
  1049. // put the crosspoint DIST_EPSILON pixels on the near side
  1050. if (t1 < t2)
  1051. {
  1052. idist = 1.0/(t1-t2);
  1053. side = 1;
  1054. frac2 = (t1 + offset + DIST_EPSILON)*idist;
  1055. frac = (t1 - offset + DIST_EPSILON)*idist;
  1056. }
  1057. else if (t1 > t2)
  1058. {
  1059. idist = 1.0/(t1-t2);
  1060. side = 0;
  1061. frac2 = (t1 - offset - DIST_EPSILON)*idist;
  1062. frac = (t1 + offset + DIST_EPSILON)*idist;
  1063. }
  1064. else
  1065. {
  1066. side = 0;
  1067. frac = 1;
  1068. frac2 = 0;
  1069. }
  1070. // move up to the node
  1071. if (frac < 0)
  1072. frac = 0;
  1073. if (frac > 1)
  1074. frac = 1;
  1075. midf = p1f + (p2f - p1f)*frac;
  1076. for (i=0 ; i<3 ; i++)
  1077. mid[i] = p1[i] + frac*(p2[i] - p1[i]);
  1078. CM_RecursiveHullCheck (node->children[side], p1f, midf, p1, mid);
  1079. // go past the node
  1080. if (frac2 < 0)
  1081. frac2 = 0;
  1082. if (frac2 > 1)
  1083. frac2 = 1;
  1084. midf = p1f + (p2f - p1f)*frac2;
  1085. for (i=0 ; i<3 ; i++)
  1086. mid[i] = p1[i] + frac2*(p2[i] - p1[i]);
  1087. CM_RecursiveHullCheck (node->children[side^1], midf, p2f, mid, p2);
  1088. }
  1089. //======================================================================
  1090. /*
  1091. ==================
  1092. CM_BoxTrace
  1093. ==================
  1094. */
  1095. trace_t CM_BoxTrace (vec3_t start, vec3_t end,
  1096. vec3_t mins, vec3_t maxs,
  1097. int headnode, int brushmask)
  1098. {
  1099. int i;
  1100. checkcount++; // for multi-check avoidance
  1101. c_traces++; // for statistics, may be zeroed
  1102. // fill in a default trace
  1103. memset (&trace_trace, 0, sizeof(trace_trace));
  1104. trace_trace.fraction = 1;
  1105. trace_trace.surface = &(nullsurface.c);
  1106. if (!numnodes) // map not loaded
  1107. return trace_trace;
  1108. trace_contents = brushmask;
  1109. VectorCopy (start, trace_start);
  1110. VectorCopy (end, trace_end);
  1111. VectorCopy (mins, trace_mins);
  1112. VectorCopy (maxs, trace_maxs);
  1113. //
  1114. // check for position test special case
  1115. //
  1116. if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2])
  1117. {
  1118. int leafs[1024];
  1119. int i, numleafs;
  1120. vec3_t c1, c2;
  1121. int topnode;
  1122. VectorAdd (start, mins, c1);
  1123. VectorAdd (start, maxs, c2);
  1124. for (i=0 ; i<3 ; i++)
  1125. {
  1126. c1[i] -= 1;
  1127. c2[i] += 1;
  1128. }
  1129. numleafs = CM_BoxLeafnums_headnode (c1, c2, leafs, 1024, headnode, &topnode);
  1130. for (i=0 ; i<numleafs ; i++)
  1131. {
  1132. CM_TestInLeaf (leafs[i]);
  1133. if (trace_trace.allsolid)
  1134. break;
  1135. }
  1136. VectorCopy (start, trace_trace.endpos);
  1137. return trace_trace;
  1138. }
  1139. //
  1140. // check for point special case
  1141. //
  1142. if (mins[0] == 0 && mins[1] == 0 && mins[2] == 0
  1143. && maxs[0] == 0 && maxs[1] == 0 && maxs[2] == 0)
  1144. {
  1145. trace_ispoint = true;
  1146. VectorClear (trace_extents);
  1147. }
  1148. else
  1149. {
  1150. trace_ispoint = false;
  1151. trace_extents[0] = -mins[0] > maxs[0] ? -mins[0] : maxs[0];
  1152. trace_extents[1] = -mins[1] > maxs[1] ? -mins[1] : maxs[1];
  1153. trace_extents[2] = -mins[2] > maxs[2] ? -mins[2] : maxs[2];
  1154. }
  1155. //
  1156. // general sweeping through world
  1157. //
  1158. CM_RecursiveHullCheck (headnode, 0, 1, start, end);
  1159. if (trace_trace.fraction == 1)
  1160. {
  1161. VectorCopy (end, trace_trace.endpos);
  1162. }
  1163. else
  1164. {
  1165. for (i=0 ; i<3 ; i++)
  1166. trace_trace.endpos[i] = start[i] + trace_trace.fraction * (end[i] - start[i]);
  1167. }
  1168. return trace_trace;
  1169. }
  1170. /*
  1171. ==================
  1172. CM_TransformedBoxTrace
  1173. Handles offseting and rotation of the end points for moving and
  1174. rotating entities
  1175. ==================
  1176. */
  1177. #ifdef _WIN32
  1178. #pragma optimize( "", off )
  1179. #endif
  1180. trace_t CM_TransformedBoxTrace (vec3_t start, vec3_t end,
  1181. vec3_t mins, vec3_t maxs,
  1182. int headnode, int brushmask,
  1183. vec3_t origin, vec3_t angles)
  1184. {
  1185. trace_t trace;
  1186. vec3_t start_l, end_l;
  1187. vec3_t a;
  1188. vec3_t forward, right, up;
  1189. vec3_t temp;
  1190. qboolean rotated;
  1191. // subtract origin offset
  1192. VectorSubtract (start, origin, start_l);
  1193. VectorSubtract (end, origin, end_l);
  1194. // rotate start and end into the models frame of reference
  1195. if (headnode != box_headnode &&
  1196. (angles[0] || angles[1] || angles[2]) )
  1197. rotated = true;
  1198. else
  1199. rotated = false;
  1200. if (rotated)
  1201. {
  1202. AngleVectors (angles, forward, right, up);
  1203. VectorCopy (start_l, temp);
  1204. start_l[0] = DotProduct (temp, forward);
  1205. start_l[1] = -DotProduct (temp, right);
  1206. start_l[2] = DotProduct (temp, up);
  1207. VectorCopy (end_l, temp);
  1208. end_l[0] = DotProduct (temp, forward);
  1209. end_l[1] = -DotProduct (temp, right);
  1210. end_l[2] = DotProduct (temp, up);
  1211. }
  1212. // sweep the box through the model
  1213. trace = CM_BoxTrace (start_l, end_l, mins, maxs, headnode, brushmask);
  1214. if (rotated && trace.fraction != 1.0)
  1215. {
  1216. // FIXME: figure out how to do this with existing angles
  1217. VectorNegate (angles, a);
  1218. AngleVectors (a, forward, right, up);
  1219. VectorCopy (trace.plane.normal, temp);
  1220. trace.plane.normal[0] = DotProduct (temp, forward);
  1221. trace.plane.normal[1] = -DotProduct (temp, right);
  1222. trace.plane.normal[2] = DotProduct (temp, up);
  1223. }
  1224. trace.endpos[0] = start[0] + trace.fraction * (end[0] - start[0]);
  1225. trace.endpos[1] = start[1] + trace.fraction * (end[1] - start[1]);
  1226. trace.endpos[2] = start[2] + trace.fraction * (end[2] - start[2]);
  1227. return trace;
  1228. }
  1229. #ifdef _WIN32
  1230. #pragma optimize( "", on )
  1231. #endif
  1232. /*
  1233. ===============================================================================
  1234. PVS / PHS
  1235. ===============================================================================
  1236. */
  1237. /*
  1238. ===================
  1239. CM_DecompressVis
  1240. ===================
  1241. */
  1242. void CM_DecompressVis (byte *in, byte *out)
  1243. {
  1244. int c;
  1245. byte *out_p;
  1246. int row;
  1247. row = (numclusters+7)>>3;
  1248. out_p = out;
  1249. if (!in || !numvisibility)
  1250. { // no vis info, so make all visible
  1251. while (row)
  1252. {
  1253. *out_p++ = 0xff;
  1254. row--;
  1255. }
  1256. return;
  1257. }
  1258. do
  1259. {
  1260. if (*in)
  1261. {
  1262. *out_p++ = *in++;
  1263. continue;
  1264. }
  1265. c = in[1];
  1266. in += 2;
  1267. if ((out_p - out) + c > row)
  1268. {
  1269. c = row - (out_p - out);
  1270. Com_DPrintf ("warning: Vis decompression overrun\n");
  1271. }
  1272. while (c)
  1273. {
  1274. *out_p++ = 0;
  1275. c--;
  1276. }
  1277. } while (out_p - out < row);
  1278. }
  1279. byte pvsrow[MAX_MAP_LEAFS/8];
  1280. byte phsrow[MAX_MAP_LEAFS/8];
  1281. byte *CM_ClusterPVS (int cluster)
  1282. {
  1283. if (cluster == -1)
  1284. memset (pvsrow, 0, (numclusters+7)>>3);
  1285. else
  1286. CM_DecompressVis (map_visibility + map_vis->bitofs[cluster][DVIS_PVS], pvsrow);
  1287. return pvsrow;
  1288. }
  1289. byte *CM_ClusterPHS (int cluster)
  1290. {
  1291. if (cluster == -1)
  1292. memset (phsrow, 0, (numclusters+7)>>3);
  1293. else
  1294. CM_DecompressVis (map_visibility + map_vis->bitofs[cluster][DVIS_PHS], phsrow);
  1295. return phsrow;
  1296. }
  1297. /*
  1298. ===============================================================================
  1299. AREAPORTALS
  1300. ===============================================================================
  1301. */
  1302. void FloodArea_r (carea_t *area, int floodnum)
  1303. {
  1304. int i;
  1305. dareaportal_t *p;
  1306. if (area->floodvalid == floodvalid)
  1307. {
  1308. if (area->floodnum == floodnum)
  1309. return;
  1310. Com_Error (ERR_DROP, "FloodArea_r: reflooded");
  1311. }
  1312. area->floodnum = floodnum;
  1313. area->floodvalid = floodvalid;
  1314. p = &map_areaportals[area->firstareaportal];
  1315. for (i=0 ; i<area->numareaportals ; i++, p++)
  1316. {
  1317. if (portalopen[p->portalnum])
  1318. FloodArea_r (&map_areas[p->otherarea], floodnum);
  1319. }
  1320. }
  1321. /*
  1322. ====================
  1323. FloodAreaConnections
  1324. ====================
  1325. */
  1326. void FloodAreaConnections (void)
  1327. {
  1328. int i;
  1329. carea_t *area;
  1330. int floodnum;
  1331. // all current floods are now invalid
  1332. floodvalid++;
  1333. floodnum = 0;
  1334. // area 0 is not used
  1335. for (i=1 ; i<numareas ; i++)
  1336. {
  1337. area = &map_areas[i];
  1338. if (area->floodvalid == floodvalid)
  1339. continue; // already flooded into
  1340. floodnum++;
  1341. FloodArea_r (area, floodnum);
  1342. }
  1343. }
  1344. void CM_SetAreaPortalState (int portalnum, qboolean open)
  1345. {
  1346. if (portalnum > numareaportals)
  1347. Com_Error (ERR_DROP, "areaportal > numareaportals");
  1348. portalopen[portalnum] = open;
  1349. FloodAreaConnections ();
  1350. }
  1351. qboolean CM_AreasConnected (int area1, int area2)
  1352. {
  1353. if (map_noareas->value)
  1354. return true;
  1355. if (area1 > numareas || area2 > numareas)
  1356. Com_Error (ERR_DROP, "area > numareas");
  1357. if (map_areas[area1].floodnum == map_areas[area2].floodnum)
  1358. return true;
  1359. return false;
  1360. }
  1361. /*
  1362. =================
  1363. CM_WriteAreaBits
  1364. Writes a length byte followed by a bit vector of all the areas
  1365. that area in the same flood as the area parameter
  1366. This is used by the client refreshes to cull visibility
  1367. =================
  1368. */
  1369. int CM_WriteAreaBits (byte *buffer, int area)
  1370. {
  1371. int i;
  1372. int floodnum;
  1373. int bytes;
  1374. bytes = (numareas+7)>>3;
  1375. if (map_noareas->value)
  1376. { // for debugging, send everything
  1377. memset (buffer, 255, bytes);
  1378. }
  1379. else
  1380. {
  1381. memset (buffer, 0, bytes);
  1382. floodnum = map_areas[area].floodnum;
  1383. for (i=0 ; i<numareas ; i++)
  1384. {
  1385. if (map_areas[i].floodnum == floodnum || !area)
  1386. buffer[i>>3] |= 1<<(i&7);
  1387. }
  1388. }
  1389. return bytes;
  1390. }
  1391. /*
  1392. ===================
  1393. CM_WritePortalState
  1394. Writes the portal state to a savegame file
  1395. ===================
  1396. */
  1397. void CM_WritePortalState (FILE *f)
  1398. {
  1399. fwrite (portalopen, sizeof(portalopen), 1, f);
  1400. }
  1401. /*
  1402. ===================
  1403. CM_ReadPortalState
  1404. Reads the portal state from a savegame file
  1405. and recalculates the area connections
  1406. ===================
  1407. */
  1408. void CM_ReadPortalState (FILE *f)
  1409. {
  1410. FS_Read (portalopen, sizeof(portalopen), f);
  1411. FloodAreaConnections ();
  1412. }
  1413. /*
  1414. =============
  1415. CM_HeadnodeVisible
  1416. Returns true if any leaf under headnode has a cluster that
  1417. is potentially visible
  1418. =============
  1419. */
  1420. qboolean CM_HeadnodeVisible (int nodenum, byte *visbits)
  1421. {
  1422. int leafnum;
  1423. int cluster;
  1424. cnode_t *node;
  1425. if (nodenum < 0)
  1426. {
  1427. leafnum = -1-nodenum;
  1428. cluster = map_leafs[leafnum].cluster;
  1429. if (cluster == -1)
  1430. return false;
  1431. if (visbits[cluster>>3] & (1<<(cluster&7)))
  1432. return true;
  1433. return false;
  1434. }
  1435. node = &map_nodes[nodenum];
  1436. if (CM_HeadnodeVisible(node->children[0], visbits))
  1437. return true;
  1438. return CM_HeadnodeVisible(node->children[1], visbits);
  1439. }