map_sin.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  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. //-----------------------------------------------------------------------------
  19. //
  20. // $Logfile:: /MissionPack/code/bspc/map_sin.c $
  21. #include "qbsp.h"
  22. #include "l_bsp_sin.h"
  23. #include "aas_map.h" //AAS_CreateMapBrushes
  24. //====================================================================
  25. /*
  26. ===========
  27. Sin_BrushContents
  28. ===========
  29. */
  30. int Sin_BrushContents(mapbrush_t *b)
  31. {
  32. int contents;
  33. side_t *s;
  34. int i;
  35. #ifdef SIN
  36. float trans = 0;
  37. #else
  38. int trans;
  39. #endif
  40. s = &b->original_sides[0];
  41. contents = s->contents;
  42. #ifdef SIN
  43. trans = sin_texinfo[s->texinfo].translucence;
  44. #else
  45. trans = texinfo[s->texinfo].flags;
  46. #endif
  47. for (i=1 ; i<b->numsides ; i++, s++)
  48. {
  49. s = &b->original_sides[i];
  50. #ifdef SIN
  51. trans += sin_texinfo[s->texinfo].translucence;
  52. #else
  53. trans |= texinfo[s->texinfo].flags;
  54. #endif
  55. if (s->contents != contents)
  56. {
  57. #ifdef SIN
  58. if (
  59. ( s->contents & CONTENTS_DETAIL && !(contents & CONTENTS_DETAIL) ) ||
  60. ( !(s->contents & CONTENTS_DETAIL) && contents & CONTENTS_DETAIL )
  61. )
  62. {
  63. s->contents |= CONTENTS_DETAIL;
  64. contents |= CONTENTS_DETAIL;
  65. continue;
  66. }
  67. #endif
  68. printf ("Entity %i, Brush %i: mixed face contents\n"
  69. , b->entitynum, b->brushnum);
  70. break;
  71. }
  72. }
  73. #ifdef SIN
  74. if (contents & CONTENTS_FENCE)
  75. {
  76. // contents |= CONTENTS_TRANSLUCENT;
  77. contents |= CONTENTS_DETAIL;
  78. contents |= CONTENTS_DUMMYFENCE;
  79. contents &= ~CONTENTS_SOLID;
  80. contents &= ~CONTENTS_FENCE;
  81. contents |= CONTENTS_WINDOW;
  82. }
  83. #endif
  84. // if any side is translucent, mark the contents
  85. // and change solid to window
  86. #ifdef SIN
  87. if ( trans > 0 )
  88. #else
  89. if ( trans & (SURF_TRANS33|SURF_TRANS66) )
  90. #endif
  91. {
  92. contents |= CONTENTS_Q2TRANSLUCENT;
  93. if (contents & CONTENTS_SOLID)
  94. {
  95. contents &= ~CONTENTS_SOLID;
  96. contents |= CONTENTS_WINDOW;
  97. }
  98. }
  99. return contents;
  100. } //*/
  101. //============================================================================
  102. /*
  103. =================
  104. ParseBrush
  105. =================
  106. * /
  107. void ParseBrush (entity_t *mapent)
  108. {
  109. mapbrush_t *b;
  110. int i,j, k;
  111. int mt;
  112. side_t *side, *s2;
  113. int planenum;
  114. brush_texture_t td;
  115. #ifdef SIN
  116. textureref_t newref;
  117. #endif
  118. int planepts[3][3];
  119. if (nummapbrushes == MAX_MAP_BRUSHES)
  120. Error ("nummapbrushes == MAX_MAP_BRUSHES");
  121. b = &mapbrushes[nummapbrushes];
  122. b->original_sides = &brushsides[nummapbrushsides];
  123. b->entitynum = num_entities-1;
  124. b->brushnum = nummapbrushes - mapent->firstbrush;
  125. do
  126. {
  127. if (!GetToken (true))
  128. break;
  129. if (!strcmp (token, "}") )
  130. break;
  131. if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
  132. Error ("MAX_MAP_BRUSHSIDES");
  133. side = &brushsides[nummapbrushsides];
  134. // read the three point plane definition
  135. for (i=0 ; i<3 ; i++)
  136. {
  137. if (i != 0)
  138. GetToken (true);
  139. if (strcmp (token, "(") )
  140. Error ("parsing brush");
  141. for (j=0 ; j<3 ; j++)
  142. {
  143. GetToken (false);
  144. planepts[i][j] = atoi(token);
  145. }
  146. GetToken (false);
  147. if (strcmp (token, ")") )
  148. Error ("parsing brush");
  149. }
  150. //
  151. // read the texturedef
  152. //
  153. GetToken (false);
  154. strcpy (td.name, token);
  155. GetToken (false);
  156. td.shift[0] = atoi(token);
  157. GetToken (false);
  158. td.shift[1] = atoi(token);
  159. GetToken (false);
  160. #ifdef SIN
  161. td.rotate = atof(token);
  162. #else
  163. td.rotate = atoi(token);
  164. #endif
  165. GetToken (false);
  166. td.scale[0] = atof(token);
  167. GetToken (false);
  168. td.scale[1] = atof(token);
  169. // find default flags and values
  170. mt = FindMiptex (td.name);
  171. #ifdef SIN
  172. // clear out the masks on newref
  173. memset(&newref,0,sizeof(newref));
  174. // copy over the name
  175. strcpy( newref.name, td.name );
  176. ParseSurfaceInfo( &newref );
  177. MergeRefs( &bsp_textureref[mt], &newref, &td.tref );
  178. side->contents = td.tref.contents;
  179. side->surf = td.tref.flags;
  180. #else
  181. td.flags = textureref[mt].flags;
  182. td.value = textureref[mt].value;
  183. side->contents = textureref[mt].contents;
  184. side->surf = td.flags = textureref[mt].flags;
  185. if (TokenAvailable())
  186. {
  187. GetToken (false);
  188. side->contents = atoi(token);
  189. GetToken (false);
  190. side->surf = td.flags = atoi(token);
  191. GetToken (false);
  192. td.value = atoi(token);
  193. }
  194. #endif
  195. // translucent objects are automatically classified as detail
  196. #ifdef SIN
  197. if ( td.tref.translucence > 0 )
  198. #else
  199. if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
  200. #endif
  201. side->contents |= CONTENTS_DETAIL;
  202. if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
  203. side->contents |= CONTENTS_DETAIL;
  204. if (fulldetail)
  205. side->contents &= ~CONTENTS_DETAIL;
  206. if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1)
  207. | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) )
  208. side->contents |= CONTENTS_SOLID;
  209. // hints and skips are never detail, and have no content
  210. if (side->surf & (SURF_HINT|SURF_SKIP) )
  211. {
  212. side->contents = 0;
  213. #ifndef SIN // I think this is a bug of some kind
  214. side->surf &= ~CONTENTS_DETAIL;
  215. #endif
  216. }
  217. //
  218. // find the plane number
  219. //
  220. planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
  221. if (planenum == -1)
  222. {
  223. printf ("Entity %i, Brush %i: plane with no normal\n"
  224. , b->entitynum, b->brushnum);
  225. continue;
  226. }
  227. //
  228. // see if the plane has been used already
  229. //
  230. for (k=0 ; k<b->numsides ; k++)
  231. {
  232. s2 = b->original_sides + k;
  233. if (s2->planenum == planenum)
  234. {
  235. printf ("Entity %i, Brush %i: duplicate plane\n"
  236. , b->entitynum, b->brushnum);
  237. break;
  238. }
  239. if ( s2->planenum == (planenum^1) )
  240. {
  241. printf ("Entity %i, Brush %i: mirrored plane\n"
  242. , b->entitynum, b->brushnum);
  243. break;
  244. }
  245. }
  246. if (k != b->numsides)
  247. continue; // duplicated
  248. //
  249. // keep this side
  250. //
  251. side = b->original_sides + b->numsides;
  252. side->planenum = planenum;
  253. #ifdef SIN
  254. side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
  255. &td, vec3_origin, &newref);
  256. //
  257. // save off lightinfo
  258. //
  259. side->lightinfo = LightinfoForBrushTexture ( &td );
  260. #else
  261. side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
  262. &td, vec3_origin);
  263. #endif
  264. // save the td off in case there is an origin brush and we
  265. // have to recalculate the texinfo
  266. side_brushtextures[nummapbrushsides] = td;
  267. #ifdef SIN
  268. // save off the merged tref for animating textures
  269. side_newrefs[nummapbrushsides] = newref;
  270. #endif
  271. nummapbrushsides++;
  272. b->numsides++;
  273. } while (1);
  274. // get the content for the entire brush
  275. b->contents = Sin_BrushContents (b);
  276. // allow detail brushes to be removed
  277. if (nodetail && (b->contents & CONTENTS_DETAIL) )
  278. {
  279. b->numsides = 0;
  280. return;
  281. }
  282. // allow water brushes to be removed
  283. if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
  284. {
  285. b->numsides = 0;
  286. return;
  287. }
  288. // create windings for sides and bounds for brush
  289. MakeBrushWindings (b);
  290. // brushes that will not be visible at all will never be
  291. // used as bsp splitters
  292. if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
  293. {
  294. c_clipbrushes++;
  295. for (i=0 ; i<b->numsides ; i++)
  296. b->original_sides[i].texinfo = TEXINFO_NODE;
  297. }
  298. //
  299. // origin brushes are removed, but they set
  300. // the rotation origin for the rest of the brushes
  301. // in the entity. After the entire entity is parsed,
  302. // the planenums and texinfos will be adjusted for
  303. // the origin brush
  304. //
  305. if (b->contents & CONTENTS_ORIGIN)
  306. {
  307. char string[32];
  308. vec3_t origin;
  309. if (num_entities == 1)
  310. {
  311. Error ("Entity %i, Brush %i: origin brushes not allowed in world"
  312. , b->entitynum, b->brushnum);
  313. return;
  314. }
  315. VectorAdd (b->mins, b->maxs, origin);
  316. VectorScale (origin, 0.5, origin);
  317. sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  318. SetKeyValue (&entities[b->entitynum], "origin", string);
  319. VectorCopy (origin, entities[b->entitynum].origin);
  320. // don't keep this brush
  321. b->numsides = 0;
  322. return;
  323. }
  324. AddBrushBevels (b);
  325. nummapbrushes++;
  326. mapent->numbrushes++;
  327. } //*/
  328. /*
  329. ================
  330. MoveBrushesToWorld
  331. Takes all of the brushes from the current entity and
  332. adds them to the world's brush list.
  333. Used by func_group and func_areaportal
  334. ================
  335. * /
  336. void MoveBrushesToWorld (entity_t *mapent)
  337. {
  338. int newbrushes;
  339. int worldbrushes;
  340. mapbrush_t *temp;
  341. int i;
  342. // this is pretty gross, because the brushes are expected to be
  343. // in linear order for each entity
  344. newbrushes = mapent->numbrushes;
  345. worldbrushes = entities[0].numbrushes;
  346. temp = malloc(newbrushes*sizeof(mapbrush_t));
  347. memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
  348. #if 0 // let them keep their original brush numbers
  349. for (i=0 ; i<newbrushes ; i++)
  350. temp[i].entitynum = 0;
  351. #endif
  352. // make space to move the brushes (overlapped copy)
  353. memmove (mapbrushes + worldbrushes + newbrushes,
  354. mapbrushes + worldbrushes,
  355. sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) );
  356. // copy the new brushes down
  357. memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes);
  358. // fix up indexes
  359. entities[0].numbrushes += newbrushes;
  360. for (i=1 ; i<num_entities ; i++)
  361. entities[i].firstbrush += newbrushes;
  362. free (temp);
  363. mapent->numbrushes = 0;
  364. } //*/
  365. /*
  366. ================
  367. ParseMapEntity
  368. ================
  369. * /
  370. qboolean Sin_ParseMapEntity (void)
  371. {
  372. entity_t *mapent;
  373. epair_t *e;
  374. side_t *s;
  375. int i, j;
  376. int startbrush, startsides;
  377. vec_t newdist;
  378. mapbrush_t *b;
  379. if (!GetToken (true))
  380. return false;
  381. if (strcmp (token, "{") )
  382. Error ("ParseEntity: { not found");
  383. if (num_entities == MAX_MAP_ENTITIES)
  384. Error ("num_entities == MAX_MAP_ENTITIES");
  385. startbrush = nummapbrushes;
  386. startsides = nummapbrushsides;
  387. mapent = &entities[num_entities];
  388. num_entities++;
  389. memset (mapent, 0, sizeof(*mapent));
  390. mapent->firstbrush = nummapbrushes;
  391. mapent->numbrushes = 0;
  392. // mapent->portalareas[0] = -1;
  393. // mapent->portalareas[1] = -1;
  394. do
  395. {
  396. if (!GetToken (true))
  397. Error ("ParseEntity: EOF without closing brace");
  398. if (!strcmp (token, "}") )
  399. break;
  400. if (!strcmp (token, "{") )
  401. ParseBrush (mapent);
  402. else
  403. {
  404. e = ParseEpair ();
  405. #ifdef SIN
  406. //HACK HACK HACK
  407. // MED Gotta do this here
  408. if ( !stricmp(e->key, "surfacefile") )
  409. {
  410. if (!surfacefile[0])
  411. {
  412. strcpy( surfacefile, e->value );
  413. }
  414. printf ("--- ParseSurfaceFile ---\n");
  415. printf ("Surface script: %s\n", surfacefile);
  416. if (!ParseSurfaceFile(surfacefile))
  417. {
  418. Error ("Script file not found: %s\n", surfacefile);
  419. }
  420. }
  421. #endif
  422. e->next = mapent->epairs;
  423. mapent->epairs = e;
  424. }
  425. } while (1);
  426. #ifdef SIN
  427. if (!(strlen(ValueForKey(mapent, "origin"))) && ((num_entities-1) != 0))
  428. {
  429. mapbrush_t *brush;
  430. vec3_t origin;
  431. char string[32];
  432. vec3_t mins, maxs;
  433. int start, end;
  434. // Calculate bounds
  435. start = mapent->firstbrush;
  436. end = start + mapent->numbrushes;
  437. ClearBounds (mins, maxs);
  438. for (j=start ; j<end ; j++)
  439. {
  440. brush = &mapbrushes[j];
  441. if (!brush->numsides)
  442. continue; // not a real brush (origin brush) - shouldn't happen
  443. AddPointToBounds (brush->mins, mins, maxs);
  444. AddPointToBounds (brush->maxs, mins, maxs);
  445. }
  446. // Set the origin to be the centroid of the entity.
  447. VectorAdd ( mins, maxs, origin);
  448. VectorScale( origin, 0.5f, origin );
  449. sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  450. SetKeyValue ( mapent, "origin", string);
  451. // qprintf("Setting origin to %s\n",string);
  452. }
  453. #endif
  454. GetVectorForKey (mapent, "origin", mapent->origin);
  455. #ifdef SIN
  456. if (
  457. (!strcmp ("func_areaportal", ValueForKey (mapent, "classname"))) ||
  458. (!strcmp ("func_group", ValueForKey (mapent, "classname"))) ||
  459. (!strcmp ("detail", ValueForKey (mapent, "classname")) && !entitydetails)
  460. )
  461. {
  462. VectorClear( mapent->origin );
  463. }
  464. #endif
  465. //
  466. // if there was an origin brush, offset all of the planes and texinfo
  467. //
  468. if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
  469. {
  470. for (i=0 ; i<mapent->numbrushes ; i++)
  471. {
  472. b = &mapbrushes[mapent->firstbrush + i];
  473. for (j=0 ; j<b->numsides ; j++)
  474. {
  475. s = &b->original_sides[j];
  476. newdist = mapplanes[s->planenum].dist -
  477. DotProduct (mapplanes[s->planenum].normal, mapent->origin);
  478. s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
  479. #ifdef SIN
  480. s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
  481. &side_brushtextures[s-brushsides], mapent->origin, &side_newrefs[s-brushsides]);
  482. //
  483. // save off lightinfo
  484. //
  485. s->lightinfo = LightinfoForBrushTexture ( &side_brushtextures[s-brushsides] );
  486. #else
  487. s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
  488. &side_brushtextures[s-brushsides], mapent->origin);
  489. #endif
  490. }
  491. MakeBrushWindings (b);
  492. }
  493. }
  494. // group entities are just for editor convenience
  495. // toss all brushes into the world entity
  496. if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
  497. {
  498. MoveBrushesToWorld (mapent);
  499. mapent->numbrushes = 0;
  500. mapent->wasdetail = true;
  501. FreeValueKeys( mapent );
  502. return true;
  503. }
  504. #ifdef SIN
  505. // detail entities are just for editor convenience
  506. // toss all brushes into the world entity as detail brushes
  507. if (!strcmp ("detail", ValueForKey (mapent, "classname")) && !entitydetails)
  508. {
  509. for (i=0 ; i<mapent->numbrushes ; i++)
  510. {
  511. int j;
  512. side_t * s;
  513. b = &mapbrushes[mapent->firstbrush + i];
  514. if (nodetail)
  515. {
  516. b->numsides = 0;
  517. continue;
  518. }
  519. if (!fulldetail)
  520. {
  521. // set the contents for the entire brush
  522. b->contents |= CONTENTS_DETAIL;
  523. // set the contents in the sides as well
  524. for (j=0, s=b->original_sides ; j<b->numsides ; j++,s++)
  525. {
  526. s->contents |= CONTENTS_DETAIL;
  527. }
  528. }
  529. else
  530. {
  531. // set the contents for the entire brush
  532. b->contents |= CONTENTS_SOLID;
  533. // set the contents in the sides as well
  534. for (j=0, s=b->original_sides ; j<b->numsides ; j++,s++)
  535. {
  536. s->contents |= CONTENTS_SOLID;
  537. }
  538. }
  539. }
  540. MoveBrushesToWorld (mapent);
  541. mapent->wasdetail = true;
  542. FreeValueKeys( mapent );
  543. // kill off the entity
  544. // num_entities--;
  545. return true;
  546. }
  547. #endif
  548. // areaportal entities move their brushes, but don't eliminate
  549. // the entity
  550. if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
  551. {
  552. char str[128];
  553. if (mapent->numbrushes != 1)
  554. Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);
  555. b = &mapbrushes[nummapbrushes-1];
  556. b->contents = CONTENTS_AREAPORTAL;
  557. c_areaportals++;
  558. mapent->areaportalnum = c_areaportals;
  559. // set the portal number as "style"
  560. sprintf (str, "%i", c_areaportals);
  561. SetKeyValue (mapent, "style", str);
  562. MoveBrushesToWorld (mapent);
  563. return true;
  564. }
  565. return true;
  566. } //end of the function Sin_ParseMapEntity */
  567. //===================================================================
  568. /*
  569. ================
  570. LoadMapFile
  571. ================
  572. * /
  573. void Sin_LoadMapFile (char *filename)
  574. {
  575. int i;
  576. #ifdef SIN
  577. int num_detailsides=0;
  578. int num_detailbrushes=0;
  579. int num_worldsides=0;
  580. int num_worldbrushes=0;
  581. int j,k;
  582. #endif
  583. qprintf ("--- LoadMapFile ---\n");
  584. LoadScriptFile (filename);
  585. nummapbrushsides = 0;
  586. num_entities = 0;
  587. while (ParseMapEntity ())
  588. {
  589. }
  590. ClearBounds (map_mins, map_maxs);
  591. for (i=0 ; i<entities[0].numbrushes ; i++)
  592. {
  593. if (mapbrushes[i].mins[0] > 4096)
  594. continue; // no valid points
  595. AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
  596. AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
  597. }
  598. #ifdef SIN
  599. for (j=0; j<num_entities; j++)
  600. {
  601. for (i=0 ; i<entities[j].numbrushes ; i++)
  602. {
  603. side_t * s;
  604. mapbrush_t *b;
  605. b = &mapbrushes[entities[j].firstbrush + i];
  606. if (b->numsides && b->contents & CONTENTS_DETAIL)
  607. num_detailbrushes++;
  608. else if (b->numsides)
  609. num_worldbrushes++;
  610. for (k=0, s=b->original_sides ; k<b->numsides ; k++,s++)
  611. {
  612. if (s->contents & CONTENTS_DETAIL)
  613. num_detailsides++;
  614. else
  615. num_worldsides++;
  616. }
  617. }
  618. }
  619. #endif
  620. qprintf ("%5i brushes\n", nummapbrushes);
  621. qprintf ("%5i clipbrushes\n", c_clipbrushes);
  622. qprintf ("%5i total sides\n", nummapbrushsides);
  623. qprintf ("%5i boxbevels\n", c_boxbevels);
  624. qprintf ("%5i edgebevels\n", c_edgebevels);
  625. qprintf ("%5i entities\n", num_entities);
  626. qprintf ("%5i planes\n", nummapplanes);
  627. qprintf ("%5i areaportals\n", c_areaportals);
  628. qprintf ("size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2],
  629. map_maxs[0],map_maxs[1],map_maxs[2]);
  630. #ifdef SIN
  631. qprintf ("%5i detailbrushes\n", num_detailbrushes);
  632. qprintf ("%5i worldbrushes\n", num_worldbrushes);
  633. qprintf ("%5i detailsides\n", num_detailsides);
  634. qprintf ("%5i worldsides\n", num_worldsides);
  635. #endif
  636. } //end of the function Sin_LoadMap */
  637. #ifdef ME //Begin MAP loading from BSP file
  638. //===========================================================================
  639. //
  640. // Parameter: -
  641. // Returns: -
  642. // Changes Globals: -
  643. //===========================================================================
  644. void Sin_CreateMapTexinfo(void)
  645. {
  646. int i;
  647. vec_t defaultvec[4] = {1, 0, 0, 0};
  648. memcpy(map_texinfo[0].vecs[0], defaultvec, sizeof(defaultvec));
  649. memcpy(map_texinfo[0].vecs[1], defaultvec, sizeof(defaultvec));
  650. map_texinfo[0].flags = 0;
  651. map_texinfo[0].value = 0;
  652. strcpy(map_texinfo[0].texture, "generic/misc/red"); //no texture
  653. map_texinfo[0].nexttexinfo = -1;
  654. for (i = 1; i < sin_numtexinfo; i++)
  655. {
  656. memcpy(map_texinfo[i].vecs, sin_texinfo[i].vecs, sizeof(float) * 2 * 4);
  657. map_texinfo[i].flags = sin_texinfo[i].flags;
  658. map_texinfo[i].value = 0;
  659. strcpy(map_texinfo[i].texture, sin_texinfo[i].texture);
  660. map_texinfo[i].nexttexinfo = -1;
  661. } //end for
  662. } //end of the function Sin_CreateMapTexinfo
  663. //===========================================================================
  664. //
  665. // Parameter: -
  666. // Returns: -
  667. // Changes Globals: -
  668. //===========================================================================
  669. void Sin_SetLeafBrushesModelNumbers(int leafnum, int modelnum)
  670. {
  671. int i, brushnum;
  672. sin_dleaf_t *leaf;
  673. leaf = &sin_dleafs[leafnum];
  674. for (i = 0; i < leaf->numleafbrushes; i++)
  675. {
  676. brushnum = sin_dleafbrushes[leaf->firstleafbrush + i];
  677. brushmodelnumbers[brushnum] = modelnum;
  678. dbrushleafnums[brushnum] = leafnum;
  679. } //end for
  680. } //end of the function Sin_SetLeafBrushesModelNumbers
  681. //===========================================================================
  682. //
  683. // Parameter: -
  684. // Returns: -
  685. // Changes Globals: -
  686. //===========================================================================
  687. void Sin_InitNodeStack(void)
  688. {
  689. nodestackptr = nodestack;
  690. nodestacksize = 0;
  691. } //end of the function Sin_InitNodeStack
  692. //===========================================================================
  693. //
  694. // Parameter: -
  695. // Returns: -
  696. // Changes Globals: -
  697. //===========================================================================
  698. void Sin_PushNodeStack(int num)
  699. {
  700. *nodestackptr = num;
  701. nodestackptr++;
  702. nodestacksize++;
  703. //
  704. if (nodestackptr >= &nodestack[NODESTACKSIZE])
  705. {
  706. Error("Sin_PushNodeStack: stack overflow\n");
  707. } //end if
  708. } //end of the function Sin_PushNodeStack
  709. //===========================================================================
  710. //
  711. // Parameter: -
  712. // Returns: -
  713. // Changes Globals: -
  714. //===========================================================================
  715. int Sin_PopNodeStack(void)
  716. {
  717. //if the stack is empty
  718. if (nodestackptr <= nodestack) return -1;
  719. //decrease stack pointer
  720. nodestackptr--;
  721. nodestacksize--;
  722. //return the top value from the stack
  723. return *nodestackptr;
  724. } //end of the function Sin_PopNodeStack
  725. //===========================================================================
  726. //
  727. // Parameter: -
  728. // Returns: -
  729. // Changes Globals: -
  730. //===========================================================================
  731. void Sin_SetBrushModelNumbers(entity_t *mapent)
  732. {
  733. int n, pn;
  734. int leafnum;
  735. //
  736. Sin_InitNodeStack();
  737. //head node (root) of the bsp tree
  738. n = sin_dmodels[mapent->modelnum].headnode;
  739. pn = 0;
  740. do
  741. {
  742. //if we are in a leaf (negative node number)
  743. if (n < 0)
  744. {
  745. //number of the leaf
  746. leafnum = (-n) - 1;
  747. //set the brush numbers
  748. Sin_SetLeafBrushesModelNumbers(leafnum, mapent->modelnum);
  749. //walk back into the tree to find a second child to continue with
  750. for (pn = Sin_PopNodeStack(); pn >= 0; n = pn, pn = Sin_PopNodeStack())
  751. {
  752. //if we took the first child at the parent node
  753. if (sin_dnodes[pn].children[0] == n) break;
  754. } //end for
  755. //if the stack wasn't empty (if not processed whole tree)
  756. if (pn >= 0)
  757. {
  758. //push the parent node again
  759. Sin_PushNodeStack(pn);
  760. //we proceed with the second child of the parent node
  761. n = sin_dnodes[pn].children[1];
  762. } //end if
  763. } //end if
  764. else
  765. {
  766. //push the current node onto the stack
  767. Sin_PushNodeStack(n);
  768. //walk forward into the tree to the first child
  769. n = sin_dnodes[n].children[0];
  770. } //end else
  771. } while(pn >= 0);
  772. } //end of the function Sin_SetBrushModelNumbers
  773. //===========================================================================
  774. //
  775. // Parameter: -
  776. // Returns: -
  777. // Changes Globals: -
  778. //===========================================================================
  779. void Sin_BSPBrushToMapBrush(sin_dbrush_t *bspbrush, entity_t *mapent)
  780. {
  781. mapbrush_t *b;
  782. int i, k, n;
  783. side_t *side, *s2;
  784. int planenum;
  785. sin_dbrushside_t *bspbrushside;
  786. sin_dplane_t *bspplane;
  787. if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
  788. Error ("nummapbrushes >= MAX_MAPFILE_BRUSHES");
  789. b = &mapbrushes[nummapbrushes];
  790. b->original_sides = &brushsides[nummapbrushsides];
  791. b->entitynum = mapent-entities;
  792. b->brushnum = nummapbrushes - mapent->firstbrush;
  793. b->leafnum = dbrushleafnums[bspbrush - sin_dbrushes];
  794. for (n = 0; n < bspbrush->numsides; n++)
  795. {
  796. //pointer to the bsp brush side
  797. bspbrushside = &sin_dbrushsides[bspbrush->firstside + n];
  798. if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
  799. {
  800. Error ("MAX_MAPFILE_BRUSHSIDES");
  801. } //end if
  802. //pointer to the map brush side
  803. side = &brushsides[nummapbrushsides];
  804. //if the BSP brush side is textured
  805. if (sin_dbrushsidetextured[bspbrush->firstside + n]) side->flags |= SFL_TEXTURED;
  806. else side->flags &= ~SFL_TEXTURED;
  807. //ME: can get side contents and surf directly from BSP file
  808. side->contents = bspbrush->contents;
  809. //if the texinfo is TEXINFO_NODE
  810. if (bspbrushside->texinfo < 0) side->surf = 0;
  811. else side->surf = sin_texinfo[bspbrushside->texinfo].flags;
  812. // translucent objects are automatically classified as detail
  813. if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
  814. side->contents |= CONTENTS_DETAIL;
  815. if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
  816. side->contents |= CONTENTS_DETAIL;
  817. if (fulldetail)
  818. side->contents &= ~CONTENTS_DETAIL;
  819. if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1)
  820. | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) )
  821. side->contents |= CONTENTS_SOLID;
  822. // hints and skips are never detail, and have no content
  823. if (side->surf & (SURF_HINT|SURF_SKIP) )
  824. {
  825. side->contents = 0;
  826. side->surf &= ~CONTENTS_DETAIL;
  827. }
  828. //ME: get a plane for this side
  829. bspplane = &sin_dplanes[bspbrushside->planenum];
  830. planenum = FindFloatPlane(bspplane->normal, bspplane->dist);
  831. //
  832. // see if the plane has been used already
  833. //
  834. //ME: this really shouldn't happen!!!
  835. //ME: otherwise the bsp file is corrupted??
  836. //ME: still it seems to happen, maybe Johny Boy's
  837. //ME: brush bevel adding is crappy ?
  838. for (k = 0; k < b->numsides; k++)
  839. {
  840. s2 = b->original_sides + k;
  841. if (s2->planenum == planenum)
  842. {
  843. Log_Print("Entity %i, Brush %i: duplicate plane\n"
  844. , b->entitynum, b->brushnum);
  845. break;
  846. }
  847. if ( s2->planenum == (planenum^1) )
  848. {
  849. Log_Print("Entity %i, Brush %i: mirrored plane\n"
  850. , b->entitynum, b->brushnum);
  851. break;
  852. }
  853. }
  854. if (k != b->numsides)
  855. continue; // duplicated
  856. //
  857. // keep this side
  858. //
  859. //ME: reset pointer to side, why? hell I dunno (pointer is set above already)
  860. side = b->original_sides + b->numsides;
  861. //ME: store the plane number
  862. side->planenum = planenum;
  863. //ME: texinfo is already stored when bsp is loaded
  864. //NOTE: check for TEXINFO_NODE, otherwise crash in Sin_BrushContents
  865. if (bspbrushside->texinfo < 0) side->texinfo = 0;
  866. else side->texinfo = bspbrushside->texinfo;
  867. // save the td off in case there is an origin brush and we
  868. // have to recalculate the texinfo
  869. // ME: don't need to recalculate because it's already done
  870. // (for non-world entities) in the BSP file
  871. // side_brushtextures[nummapbrushsides] = td;
  872. nummapbrushsides++;
  873. b->numsides++;
  874. } //end for
  875. // get the content for the entire brush
  876. b->contents = bspbrush->contents;
  877. Sin_BrushContents(b);
  878. if (BrushExists(b))
  879. {
  880. c_squattbrushes++;
  881. b->numsides = 0;
  882. return;
  883. } //end if
  884. //if we're creating AAS
  885. if (create_aas)
  886. {
  887. //create the AAS brushes from this brush, don't add brush bevels
  888. AAS_CreateMapBrushes(b, mapent, false);
  889. return;
  890. } //end if
  891. // allow detail brushes to be removed
  892. if (nodetail && (b->contents & CONTENTS_DETAIL) )
  893. {
  894. b->numsides = 0;
  895. return;
  896. } //end if
  897. // allow water brushes to be removed
  898. if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
  899. {
  900. b->numsides = 0;
  901. return;
  902. } //end if
  903. // create windings for sides and bounds for brush
  904. MakeBrushWindings(b);
  905. //mark brushes without winding or with a tiny window as bevels
  906. MarkBrushBevels(b);
  907. // brushes that will not be visible at all will never be
  908. // used as bsp splitters
  909. if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
  910. {
  911. c_clipbrushes++;
  912. for (i = 0; i < b->numsides; i++)
  913. b->original_sides[i].texinfo = TEXINFO_NODE;
  914. } //end for
  915. //
  916. // origin brushes are removed, but they set
  917. // the rotation origin for the rest of the brushes
  918. // in the entity. After the entire entity is parsed,
  919. // the planenums and texinfos will be adjusted for
  920. // the origin brush
  921. //
  922. //ME: not needed because the entities in the BSP file already
  923. // have an origin set
  924. // if (b->contents & CONTENTS_ORIGIN)
  925. // {
  926. // char string[32];
  927. // vec3_t origin;
  928. //
  929. // if (num_entities == 1)
  930. // {
  931. // Error ("Entity %i, Brush %i: origin brushes not allowed in world"
  932. // , b->entitynum, b->brushnum);
  933. // return;
  934. // }
  935. //
  936. // VectorAdd (b->mins, b->maxs, origin);
  937. // VectorScale (origin, 0.5, origin);
  938. //
  939. // sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  940. // SetKeyValue (&entities[b->entitynum], "origin", string);
  941. //
  942. // VectorCopy (origin, entities[b->entitynum].origin);
  943. //
  944. // // don't keep this brush
  945. // b->numsides = 0;
  946. //
  947. // return;
  948. // }
  949. //ME: the bsp brushes already have bevels, so we won't try to
  950. // add them again (especially since Johny Boy's bevel adding might
  951. // be crappy)
  952. // AddBrushBevels(b);
  953. nummapbrushes++;
  954. mapent->numbrushes++;
  955. } //end of the function Sin_BSPBrushToMapBrush
  956. //===========================================================================
  957. //===========================================================================
  958. void Sin_ParseBSPBrushes(entity_t *mapent)
  959. {
  960. int i, testnum = 0;
  961. //give all the brushes that belong to this entity the number of the
  962. //BSP model used by this entity
  963. Sin_SetBrushModelNumbers(mapent);
  964. //now parse all the brushes with the correct mapent->modelnum
  965. for (i = 0; i < sin_numbrushes; i++)
  966. {
  967. if (brushmodelnumbers[i] == mapent->modelnum)
  968. {
  969. testnum++;
  970. Sin_BSPBrushToMapBrush(&sin_dbrushes[i], mapent);
  971. } //end if
  972. } //end for
  973. } //end of the function Sin_ParseBSPBrushes
  974. //===========================================================================
  975. //===========================================================================
  976. qboolean Sin_ParseBSPEntity(int entnum)
  977. {
  978. entity_t *mapent;
  979. char *model;
  980. int startbrush, startsides;
  981. startbrush = nummapbrushes;
  982. startsides = nummapbrushsides;
  983. mapent = &entities[entnum];//num_entities];
  984. mapent->firstbrush = nummapbrushes;
  985. mapent->numbrushes = 0;
  986. mapent->modelnum = -1; //-1 = no model
  987. model = ValueForKey(mapent, "model");
  988. if (model && *model == '*')
  989. {
  990. mapent->modelnum = atoi(&model[1]);
  991. //Log_Print("model = %s\n", model);
  992. //Log_Print("mapent->modelnum = %d\n", mapent->modelnum);
  993. } //end if
  994. GetVectorForKey(mapent, "origin", mapent->origin);
  995. //if this is the world entity it has model number zero
  996. //the world entity has no model key
  997. if (!strcmp("worldspawn", ValueForKey(mapent, "classname")))
  998. {
  999. mapent->modelnum = 0;
  1000. } //end if
  1001. //if the map entity has a BSP model (a modelnum of -1 is used for
  1002. //entities that aren't using a BSP model)
  1003. if (mapent->modelnum >= 0)
  1004. {
  1005. //parse the bsp brushes
  1006. Sin_ParseBSPBrushes(mapent);
  1007. } //end if
  1008. //
  1009. //the origin of the entity is already taken into account
  1010. //
  1011. //func_group entities can't be in the bsp file
  1012. //
  1013. //check out the func_areaportal entities
  1014. if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
  1015. {
  1016. c_areaportals++;
  1017. mapent->areaportalnum = c_areaportals;
  1018. return true;
  1019. } //end if
  1020. return true;
  1021. } //end of the function Sin_ParseBSPEntity
  1022. //===========================================================================
  1023. //
  1024. // Parameter: -
  1025. // Returns: -
  1026. // Changes Globals: -
  1027. //===========================================================================
  1028. void Sin_LoadMapFromBSP(char *filename, int offset, int length)
  1029. {
  1030. int i;
  1031. Log_Print("-- Sin_LoadMapFromBSP --\n");
  1032. //loaded map type
  1033. loadedmaptype = MAPTYPE_SIN;
  1034. Log_Print("Loading map from %s...\n", filename);
  1035. //load the bsp file
  1036. Sin_LoadBSPFile(filename, offset, length);
  1037. //create an index from bsp planes to map planes
  1038. //DPlanes2MapPlanes();
  1039. //clear brush model numbers
  1040. for (i = 0; i < MAX_MAPFILE_BRUSHES; i++)
  1041. brushmodelnumbers[i] = -1;
  1042. nummapbrushsides = 0;
  1043. num_entities = 0;
  1044. Sin_ParseEntities();
  1045. //
  1046. for (i = 0; i < num_entities; i++)
  1047. {
  1048. Sin_ParseBSPEntity(i);
  1049. } //end for
  1050. //get the map mins and maxs from the world model
  1051. ClearBounds(map_mins, map_maxs);
  1052. for (i = 0; i < entities[0].numbrushes; i++)
  1053. {
  1054. if (mapbrushes[i].mins[0] > 4096)
  1055. continue; //no valid points
  1056. AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
  1057. AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
  1058. } //end for
  1059. //
  1060. Sin_CreateMapTexinfo();
  1061. } //end of the function Sin_LoadMapFromBSP
  1062. void Sin_ResetMapLoading(void)
  1063. {
  1064. //reset for map loading from bsp
  1065. memset(nodestack, 0, NODESTACKSIZE * sizeof(int));
  1066. nodestackptr = NULL;
  1067. nodestacksize = 0;
  1068. memset(brushmodelnumbers, 0, MAX_MAPFILE_BRUSHES * sizeof(int));
  1069. } //end of the function Sin_ResetMapLoading
  1070. //End MAP loading from BSP file
  1071. #endif //ME