qbsp.cpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533
  1. /*
  2. BINARY SPACE PARTITION -aka- B S P
  3. Code based on original code from Valve Software,
  4. Modified by Sean "Zoner" Cavanaugh ([email protected]) with permission.
  5. Modified by Tony "Merl" Moore ([email protected]) [AJM]
  6. */
  7. #ifdef SYSTEM_WIN32
  8. #define WIN32_LEAN_AND_MEAN
  9. #include <windows.h>
  10. #pragma warning(disable:4996)
  11. #endif
  12. #include "bsp5.h"
  13. /*
  14. NOTES
  15. */
  16. static FILE* polyfiles[NUM_HULLS];
  17. int g_hullnum = 0;
  18. static face_t* validfaces[MAX_INTERNAL_MAP_PLANES];
  19. char g_bspfilename[_MAX_PATH];
  20. char g_pointfilename[_MAX_PATH];
  21. char g_linefilename[_MAX_PATH];
  22. char g_portfilename[_MAX_PATH];
  23. // command line flags
  24. bool g_noopt = DEFAULT_NOOPT; // don't optimize BSP on write
  25. bool g_nofill = DEFAULT_NOFILL; // dont fill "-nofill"
  26. bool g_notjunc = DEFAULT_NOTJUNC;
  27. bool g_noclip = DEFAULT_NOCLIP; // no clipping hull "-noclip"
  28. bool g_chart = DEFAULT_CHART; // print out chart? "-chart"
  29. bool g_estimate = DEFAULT_ESTIMATE; // estimate mode "-estimate"
  30. bool g_info = DEFAULT_INFO;
  31. bool g_bLeakOnly = DEFAULT_LEAKONLY; // leakonly mode "-leakonly"
  32. bool g_bLeaked = false;
  33. int g_subdivide_size = DEFAULT_SUBDIVIDE_SIZE;
  34. #ifdef ZHLT_NULLTEX // AJM
  35. bool g_bUseNullTex = DEFAULT_NULLTEX; // "-nonulltex"
  36. #endif
  37. #ifdef ZHLT_DETAIL // AJM
  38. bool g_bDetailBrushes = DEFAULT_DETAIL; // "-nodetail"
  39. #endif
  40. #ifdef ZHLT_PROGRESSFILE // AJM
  41. char* g_progressfile = DEFAULT_PROGRESSFILE; // "-progressfile path"
  42. #endif
  43. #ifdef ZHLT_INFO_COMPILE_PARAMETERS// AJM
  44. // =====================================================================================
  45. // GetParamsFromEnt
  46. // this function is called from parseentity when it encounters the
  47. // info_compile_parameters entity. each tool should have its own version of this
  48. // to handle its own specific settings.
  49. // =====================================================================================
  50. void GetParamsFromEnt(entity_t* mapent)
  51. {
  52. int iTmp;
  53. Log("\nCompile Settings detected from info_compile_parameters entity\n");
  54. // verbose(choices) : "Verbose compile messages" : 0 = [ 0 : "Off" 1 : "On" ]
  55. iTmp = IntForKey(mapent, "verbose");
  56. if (iTmp == 1)
  57. {
  58. g_verbose = true;
  59. }
  60. else if (iTmp == 0)
  61. {
  62. g_verbose = false;
  63. }
  64. Log("%30s [ %-9s ]\n", "Compile Option", "setting");
  65. Log("%30s [ %-9s ]\n", "Verbose Compile Messages", g_verbose ? "on" : "off");
  66. // estimate(choices) :"Estimate Compile Times?" : 0 = [ 0: "Yes" 1: "No" ]
  67. if (IntForKey(mapent, "estimate"))
  68. {
  69. g_estimate = true;
  70. }
  71. else
  72. {
  73. g_estimate = false;
  74. }
  75. Log("%30s [ %-9s ]\n", "Estimate Compile Times", g_estimate ? "on" : "off");
  76. // priority(choices) : "Priority Level" : 0 = [ 0 : "Normal" 1 : "High" -1 : "Low" ]
  77. if (!strcmp(ValueForKey(mapent, "priority"), "1"))
  78. {
  79. g_threadpriority = eThreadPriorityHigh;
  80. Log("%30s [ %-9s ]\n", "Thread Priority", "high");
  81. }
  82. else if (!strcmp(ValueForKey(mapent, "priority"), "-1"))
  83. {
  84. g_threadpriority = eThreadPriorityLow;
  85. Log("%30s [ %-9s ]\n", "Thread Priority", "low");
  86. }
  87. /*
  88. hlbsp(choices) : "HLBSP" : 0 =
  89. [
  90. 0 : "Off"
  91. 1 : "Normal"
  92. 2 : "Leakonly"
  93. ]
  94. */
  95. iTmp = IntForKey(mapent, "hlbsp");
  96. if (iTmp == 0)
  97. {
  98. Fatal(assume_TOOL_CANCEL,
  99. "%s flag was not checked in info_compile_parameters entity, execution of %s cancelled", g_Program, g_Program);
  100. CheckFatal();
  101. }
  102. else if (iTmp == 1)
  103. {
  104. g_bLeakOnly = false;
  105. }
  106. else if (iTmp == 2)
  107. {
  108. g_bLeakOnly = true;
  109. }
  110. Log("%30s [ %-9s ]\n", "Leakonly Mode", g_bLeakOnly ? "on" : "off");
  111. iTmp = IntForKey(mapent, "noopt");
  112. if(iTmp == 0)
  113. {
  114. g_noopt = false;
  115. }
  116. else
  117. {
  118. g_noopt = true;
  119. }
  120. /*
  121. nocliphull(choices) : "Generate clipping hulls" : 0 =
  122. [
  123. 0 : "Yes"
  124. 1 : "No"
  125. ]
  126. */
  127. iTmp = IntForKey(mapent, "nocliphull");
  128. if (iTmp == 0)
  129. {
  130. g_noclip = false;
  131. }
  132. else if (iTmp == 1)
  133. {
  134. g_noclip = true;
  135. }
  136. Log("%30s [ %-9s ]\n", "Clipping Hull Generation", g_noclip ? "off" : "on");
  137. //////////////////
  138. Verbose("\n");
  139. }
  140. #endif
  141. // =====================================================================================
  142. // Extract File stuff (ExtractFile | ExtractFilePath | ExtractFileBase)
  143. //
  144. // With VS 2005 - and the 64 bit build, i had to pull 3 classes over from
  145. // cmdlib.cpp even with the proper includes to get rid of the lnk2001 error
  146. //
  147. // amckern - [email protected]
  148. // =====================================================================================
  149. #define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/')
  150. void ExtractFileBase(const char* const path, char* dest)
  151. {
  152. hlassert (path != dest);
  153. const char* src;
  154. src = path + strlen(path) - 1;
  155. //
  156. // back up until a \ or the start
  157. //
  158. while (src != path && !PATHSEPARATOR(*(src - 1)))
  159. src--;
  160. while (*src && *src != '.')
  161. {
  162. *dest++ = *src++;
  163. }
  164. *dest = 0;
  165. }
  166. void ExtractFilePath(const char* const path, char* dest)
  167. {
  168. hlassert (path != dest);
  169. const char* src;
  170. src = path + strlen(path) - 1;
  171. //
  172. // back up until a \ or the start
  173. //
  174. while (src != path && !PATHSEPARATOR(*(src - 1)))
  175. src--;
  176. memcpy(dest, path, src - path);
  177. dest[src - path] = 0;
  178. }
  179. void ExtractFile(const char* const path, char* dest)
  180. {
  181. hlassert (path != dest);
  182. const char* src;
  183. src = path + strlen(path) - 1;
  184. while (src != path && !PATHSEPARATOR(*(src - 1)))
  185. src--;
  186. while (*src)
  187. {
  188. *dest++ = *src++;
  189. }
  190. *dest = 0;
  191. }
  192. // =====================================================================================
  193. // NewFaceFromFace
  194. // Duplicates the non point information of a face, used by SplitFace and MergeFace.
  195. // =====================================================================================
  196. face_t* NewFaceFromFace(const face_t* const in)
  197. {
  198. face_t* newf;
  199. newf = AllocFace();
  200. newf->planenum = in->planenum;
  201. newf->texturenum = in->texturenum;
  202. newf->original = in->original;
  203. newf->contents = in->contents;
  204. return newf;
  205. }
  206. // =====================================================================================
  207. // SplitFaceTmp
  208. // blah
  209. // =====================================================================================
  210. static void SplitFaceTmp(face_t* in, const dplane_t* const split, face_t** front, face_t** back)
  211. {
  212. vec_t dists[MAXEDGES + 1];
  213. int sides[MAXEDGES + 1];
  214. int counts[3];
  215. vec_t dot;
  216. int i;
  217. int j;
  218. face_t* newf;
  219. face_t* new2;
  220. vec_t* p1;
  221. vec_t* p2;
  222. vec3_t mid;
  223. if (in->numpoints < 0)
  224. {
  225. Error("SplitFace: freed face");
  226. }
  227. counts[0] = counts[1] = counts[2] = 0;
  228. // determine sides for each point
  229. for (i = 0; i < in->numpoints; i++)
  230. {
  231. dot = DotProduct(in->pts[i], split->normal);
  232. dot -= split->dist;
  233. dists[i] = dot;
  234. if (dot > ON_EPSILON)
  235. {
  236. sides[i] = SIDE_FRONT;
  237. }
  238. else if (dot < -ON_EPSILON)
  239. {
  240. sides[i] = SIDE_BACK;
  241. }
  242. else
  243. {
  244. sides[i] = SIDE_ON;
  245. }
  246. counts[sides[i]]++;
  247. }
  248. sides[i] = sides[0];
  249. dists[i] = dists[0];
  250. if (!counts[0])
  251. {
  252. *front = NULL;
  253. *back = in;
  254. return;
  255. }
  256. if (!counts[1])
  257. {
  258. *front = in;
  259. *back = NULL;
  260. return;
  261. }
  262. *back = newf = NewFaceFromFace(in);
  263. *front = new2 = NewFaceFromFace(in);
  264. // distribute the points and generate splits
  265. for (i = 0; i < in->numpoints; i++)
  266. {
  267. if (newf->numpoints > MAXEDGES || new2->numpoints > MAXEDGES)
  268. {
  269. Error("SplitFace: numpoints > MAXEDGES");
  270. }
  271. p1 = in->pts[i];
  272. if (sides[i] == SIDE_ON)
  273. {
  274. VectorCopy(p1, newf->pts[newf->numpoints]);
  275. newf->numpoints++;
  276. VectorCopy(p1, new2->pts[new2->numpoints]);
  277. new2->numpoints++;
  278. continue;
  279. }
  280. if (sides[i] == SIDE_FRONT)
  281. {
  282. VectorCopy(p1, new2->pts[new2->numpoints]);
  283. new2->numpoints++;
  284. }
  285. else
  286. {
  287. VectorCopy(p1, newf->pts[newf->numpoints]);
  288. newf->numpoints++;
  289. }
  290. if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i])
  291. {
  292. continue;
  293. }
  294. // generate a split point
  295. p2 = in->pts[(i + 1) % in->numpoints];
  296. dot = dists[i] / (dists[i] - dists[i + 1]);
  297. for (j = 0; j < 3; j++)
  298. { // avoid round off error when possible
  299. if (split->normal[j] == 1)
  300. {
  301. mid[j] = split->dist;
  302. }
  303. else if (split->normal[j] == -1)
  304. {
  305. mid[j] = -split->dist;
  306. }
  307. else
  308. {
  309. mid[j] = p1[j] + dot * (p2[j] - p1[j]);
  310. }
  311. }
  312. VectorCopy(mid, newf->pts[newf->numpoints]);
  313. newf->numpoints++;
  314. VectorCopy(mid, new2->pts[new2->numpoints]);
  315. new2->numpoints++;
  316. }
  317. if (newf->numpoints > MAXEDGES || new2->numpoints > MAXEDGES)
  318. {
  319. Error("SplitFace: numpoints > MAXEDGES");
  320. }
  321. }
  322. // =====================================================================================
  323. // SplitFace
  324. // blah
  325. // =====================================================================================
  326. void SplitFace(face_t* in, const dplane_t* const split, face_t** front, face_t** back)
  327. {
  328. SplitFaceTmp(in, split, front, back);
  329. // free the original face now that is is represented by the fragments
  330. if (*front && *back)
  331. {
  332. FreeFace(in);
  333. }
  334. }
  335. // =====================================================================================
  336. // AllocFace
  337. // =====================================================================================
  338. face_t* AllocFace()
  339. {
  340. face_t* f;
  341. f = (face_t*)malloc(sizeof(face_t));
  342. memset(f, 0, sizeof(face_t));
  343. f->planenum = -1;
  344. return f;
  345. }
  346. // =====================================================================================
  347. // FreeFace
  348. // =====================================================================================
  349. void FreeFace(face_t* f)
  350. {
  351. free(f);
  352. }
  353. // =====================================================================================
  354. // AllocSurface
  355. // =====================================================================================
  356. surface_t* AllocSurface()
  357. {
  358. surface_t* s;
  359. s = (surface_t*)malloc(sizeof(surface_t));
  360. memset(s, 0, sizeof(surface_t));
  361. return s;
  362. }
  363. // =====================================================================================
  364. // FreeSurface
  365. // =====================================================================================
  366. void FreeSurface(surface_t* s)
  367. {
  368. free(s);
  369. }
  370. // =====================================================================================
  371. // AllocPortal
  372. // =====================================================================================
  373. portal_t* AllocPortal()
  374. {
  375. portal_t* p;
  376. p = (portal_t*)malloc(sizeof(portal_t));
  377. memset(p, 0, sizeof(portal_t));
  378. return p;
  379. }
  380. // =====================================================================================
  381. // FreePortal
  382. // =====================================================================================
  383. void FreePortal(portal_t* p) // consider: inline
  384. {
  385. free(p);
  386. }
  387. // =====================================================================================
  388. // AllocNode
  389. // blah
  390. // =====================================================================================
  391. node_t* AllocNode()
  392. {
  393. node_t* n;
  394. n = (node_t*)malloc(sizeof(node_t));
  395. memset(n, 0, sizeof(node_t));
  396. return n;
  397. }
  398. // =====================================================================================
  399. // AddPointToBounds
  400. // =====================================================================================
  401. void AddPointToBounds(const vec3_t v, vec3_t mins, vec3_t maxs)
  402. {
  403. int i;
  404. vec_t val;
  405. for (i = 0; i < 3; i++)
  406. {
  407. val = v[i];
  408. if (val < mins[i])
  409. {
  410. mins[i] = val;
  411. }
  412. if (val > maxs[i])
  413. {
  414. maxs[i] = val;
  415. }
  416. }
  417. }
  418. // =====================================================================================
  419. // AddFaceToBounds
  420. // =====================================================================================
  421. static void AddFaceToBounds(const face_t* const f, vec3_t mins, vec3_t maxs)
  422. {
  423. int i;
  424. for (i = 0; i < f->numpoints; i++)
  425. {
  426. AddPointToBounds(f->pts[i], mins, maxs);
  427. }
  428. }
  429. // =====================================================================================
  430. // ClearBounds
  431. // =====================================================================================
  432. static void ClearBounds(vec3_t mins, vec3_t maxs)
  433. {
  434. mins[0] = mins[1] = mins[2] = 99999;
  435. maxs[0] = maxs[1] = maxs[2] = -99999;
  436. }
  437. // =====================================================================================
  438. // SurflistFromValidFaces
  439. // blah
  440. // =====================================================================================
  441. static surfchain_t* SurflistFromValidFaces()
  442. {
  443. surface_t* n;
  444. int i;
  445. face_t* f;
  446. face_t* next;
  447. surfchain_t* sc;
  448. sc = (surfchain_t*)malloc(sizeof(*sc));
  449. ClearBounds(sc->mins, sc->maxs);
  450. sc->surfaces = NULL;
  451. // grab planes from both sides
  452. for (i = 0; i < g_numplanes; i += 2)
  453. {
  454. if (!validfaces[i] && !validfaces[i + 1])
  455. {
  456. continue;
  457. }
  458. n = AllocSurface();
  459. n->next = sc->surfaces;
  460. sc->surfaces = n;
  461. ClearBounds(n->mins, n->maxs);
  462. n->planenum = i;
  463. n->faces = NULL;
  464. for (f = validfaces[i]; f; f = next)
  465. {
  466. next = f->next;
  467. f->next = n->faces;
  468. n->faces = f;
  469. AddFaceToBounds(f, n->mins, n->maxs);
  470. }
  471. for (f = validfaces[i + 1]; f; f = next)
  472. {
  473. next = f->next;
  474. f->next = n->faces;
  475. n->faces = f;
  476. AddFaceToBounds(f, n->mins, n->maxs);
  477. }
  478. AddPointToBounds(n->mins, sc->mins, sc->maxs);
  479. AddPointToBounds(n->maxs, sc->mins, sc->maxs);
  480. validfaces[i] = NULL;
  481. validfaces[i + 1] = NULL;
  482. }
  483. // merge all possible polygons
  484. MergeAll(sc->surfaces);
  485. return sc;
  486. }
  487. #ifdef ZHLT_NULLTEX// AJM
  488. // =====================================================================================
  489. // CheckFaceForNull
  490. // Returns true if the passed face is facetype null
  491. // =====================================================================================
  492. bool CheckFaceForNull(const face_t* const f)
  493. {
  494. // null faces are only of facetype face_null if we are using null texture stripping
  495. if (g_bUseNullTex)
  496. {
  497. texinfo_t* info;
  498. miptex_t* miptex;
  499. int ofs;
  500. info = &g_texinfo[f->texturenum];
  501. ofs = ((dmiptexlump_t*)g_dtexdata)->dataofs[info->miptex];
  502. miptex = (miptex_t*)(&g_dtexdata[ofs]);
  503. if (!strcasecmp(miptex->name, "null"))
  504. return true;
  505. else
  506. return false;
  507. }
  508. else // otherwise, under normal cases, null textured faces should be facetype face_normal
  509. {
  510. return false;
  511. }
  512. }
  513. // =====================================================================================
  514. //Cpt_Andrew - UTSky Check
  515. // =====================================================================================
  516. bool CheckFaceForEnv_Sky(const face_t* const f)
  517. {
  518. texinfo_t* info;
  519. miptex_t* miptex;
  520. int ofs;
  521. info = &g_texinfo[f->texturenum];
  522. ofs = ((dmiptexlump_t*)g_dtexdata)->dataofs[info->miptex];
  523. miptex = (miptex_t*)(&g_dtexdata[ofs]);
  524. if (!strcasecmp(miptex->name, "env_sky"))
  525. return true;
  526. else
  527. return false;
  528. }
  529. // =====================================================================================
  530. #endif
  531. // SILENCER -->
  532. // =====================================================================================
  533. // CheckFaceForBlocklight
  534. // Returns true if the passed face is facetype blocklight
  535. // =====================================================================================
  536. // Not yet implemented - just altered copypasta here
  537. /*bool CheckFaceForBlocklight(const face_t* const f)
  538. {
  539. texinfo_t* info;
  540. miptex_t* miptex;
  541. int ofs;
  542. info = &g_texinfo[f->texturenum];
  543. ofs = ((dmiptexlump_t*)g_dtexdata)->dataofs[info->miptex];
  544. miptex = (miptex_t*)(&g_dtexdata[ofs]);
  545. if (!strcasecmp(miptex->name, "blocklight"))
  546. return true;
  547. else
  548. return false;
  549. }*/
  550. // <-- SILENCER
  551. #ifdef ZHLT_DETAIL
  552. // =====================================================================================
  553. // CheckFaceForDetail
  554. // Returns true if the passed face is part of a detail brush
  555. // =====================================================================================
  556. bool CheckFaceForDetail(const face_t* const f)
  557. {
  558. if (f->contents == CONTENTS_DETAIL)
  559. {
  560. //Log("CheckFaceForDetail:: got a detail face");
  561. return true;
  562. }
  563. return false;
  564. }
  565. #endif
  566. // =====================================================================================
  567. // CheckFaceForHint
  568. // Returns true if the passed face is facetype hint
  569. // =====================================================================================
  570. bool CheckFaceForHint(const face_t* const f)
  571. {
  572. texinfo_t* info;
  573. miptex_t* miptex;
  574. int ofs;
  575. info = &g_texinfo[f->texturenum];
  576. ofs = ((dmiptexlump_t *)g_dtexdata)->dataofs[info->miptex];
  577. miptex = (miptex_t *)(&g_dtexdata[ofs]);
  578. if (!strcasecmp(miptex->name, "hint"))
  579. {
  580. return true;
  581. }
  582. else
  583. {
  584. return false;
  585. }
  586. }
  587. // =====================================================================================
  588. // CheckFaceForSkipt
  589. // Returns true if the passed face is facetype skip
  590. // =====================================================================================
  591. bool CheckFaceForSkip(const face_t* const f)
  592. {
  593. texinfo_t* info;
  594. miptex_t* miptex;
  595. int ofs;
  596. info = &g_texinfo[f->texturenum];
  597. ofs = ((dmiptexlump_t*)g_dtexdata)->dataofs[info->miptex];
  598. miptex = (miptex_t*)(&g_dtexdata[ofs]);
  599. if (!strcasecmp(miptex->name, "skip"))
  600. {
  601. return true;
  602. }
  603. else
  604. {
  605. return false;
  606. }
  607. }
  608. // =====================================================================================
  609. // SetFaceType
  610. // =====================================================================================
  611. static facestyle_e SetFaceType(face_t* f)
  612. {
  613. if (CheckFaceForHint(f))
  614. {
  615. f->facestyle = face_hint;
  616. }
  617. else if (CheckFaceForSkip(f))
  618. {
  619. f->facestyle = face_skip;
  620. }
  621. #ifdef ZHLT_NULLTEX // AJM
  622. else if (CheckFaceForNull(f))
  623. {
  624. f->facestyle = face_null;
  625. }
  626. #endif
  627. // SILENCER --> Not yet implemented - just altered copypasta here
  628. /*
  629. else if(CheckFaceForBlocklight(f))
  630. {
  631. f->facestyle = face_blocklight;
  632. }
  633. */
  634. // <-- SILENCER
  635. // =====================================================================================
  636. //Cpt_Andrew - Env_Sky Check
  637. // =====================================================================================
  638. //else if (CheckFaceForUTSky(f))
  639. else if (CheckFaceForEnv_Sky(f))
  640. {
  641. f->facestyle = face_null;
  642. }
  643. // =====================================================================================
  644. #ifdef ZHLT_DETAIL
  645. else if (CheckFaceForDetail(f))
  646. {
  647. //Log("SetFaceType::detail face\n");
  648. f->facestyle = face_detail;
  649. }
  650. #endif
  651. else
  652. {
  653. f->facestyle = face_normal;
  654. }
  655. return f->facestyle;
  656. }
  657. // =====================================================================================
  658. // ReadSurfs
  659. // =====================================================================================
  660. static surfchain_t* ReadSurfs(FILE* file)
  661. {
  662. int r;
  663. int planenum, g_texinfo, contents, numpoints;
  664. face_t* f;
  665. int i;
  666. double v[3];
  667. int line = 0;
  668. // read in the polygons
  669. while (1)
  670. {
  671. line++;
  672. r = fscanf(file, "%i %i %i %i\n", &planenum, &g_texinfo, &contents, &numpoints);
  673. if (r == 0 || r == -1)
  674. {
  675. return NULL;
  676. }
  677. if (planenum == -1) // end of model
  678. {
  679. break;
  680. }
  681. if (r != 4)
  682. {
  683. Error("ReadSurfs (line %i): scanf failure", line);
  684. }
  685. if (numpoints > MAXPOINTS)
  686. {
  687. Error("ReadSurfs (line %i): %i > MAXPOINTS\nThis is caused by a face with too many verticies (typically found on end-caps of high-poly cylinders)\n", line, numpoints);
  688. }
  689. if (planenum > g_numplanes)
  690. {
  691. Error("ReadSurfs (line %i): %i > g_numplanes\n", line, planenum);
  692. }
  693. if (g_texinfo > g_numtexinfo)
  694. {
  695. Error("ReadSurfs (line %i): %i > g_numtexinfo", line, g_texinfo);
  696. }
  697. if (!strcasecmp(GetTextureByNumber(g_texinfo), "skip"))
  698. {
  699. Verbose("ReadSurfs (line %i): skipping a surface", line);
  700. for (i = 0; i < numpoints; i++)
  701. {
  702. line++;
  703. //Verbose("skipping line %d", line);
  704. r = fscanf(file, "%lf %lf %lf\n", &v[0], &v[1], &v[2]);
  705. if (r != 3)
  706. {
  707. Error("::ReadSurfs (face_skip), fscanf of points failed at line %i", line);
  708. }
  709. }
  710. fscanf(file, "\n");
  711. continue;
  712. }
  713. f = AllocFace();
  714. f->planenum = planenum;
  715. f->texturenum = g_texinfo;
  716. f->contents = contents;
  717. f->numpoints = numpoints;
  718. f->next = validfaces[planenum];
  719. validfaces[planenum] = f;
  720. SetFaceType(f);
  721. for (i = 0; i < f->numpoints; i++)
  722. {
  723. line++;
  724. r = fscanf(file, "%lf %lf %lf\n", &v[0], &v[1], &v[2]);
  725. if (r != 3)
  726. {
  727. Error("::ReadSurfs (face_normal), fscanf of points failed at line %i", line);
  728. }
  729. VectorCopy(v, f->pts[i]);
  730. }
  731. fscanf(file, "\n");
  732. }
  733. return SurflistFromValidFaces();
  734. }
  735. #ifdef HLBSP_THREADS// AJM
  736. // =====================================================================================
  737. // ProcessModelThreaded
  738. // time to compl
  739. // =====================================================================================
  740. void ProcessModel(int modelnum)
  741. {
  742. surfchain_t* surfs;
  743. node_t* nodes;
  744. dmodel_t* model;
  745. int startleafs;
  746. surfs = ReadSurfs(polyfiles[0]);
  747. if (!surfs)
  748. return; // all models are done
  749. hlassume(g_nummodels < MAX_MAP_MODELS, assume_MAX_MAP_MODELS);
  750. startleafs = g_numleafs;
  751. int modnum = g_nummodels;
  752. model = &g_dmodels[modnum];
  753. g_nummodels++;
  754. // Log("ProcessModel: %i (%i f)\n", modnum, model->numfaces);
  755. VectorCopy(surfs->mins, model->mins);
  756. VectorCopy(surfs->maxs, model->maxs);
  757. // SolidBSP generates a node tree
  758. nodes = SolidBSP(surfs);
  759. // build all the portals in the bsp tree
  760. // some portals are solid polygons, and some are paths to other leafs
  761. if (g_nummodels == 1 && !g_nofill) // assume non-world bmodels are simple
  762. {
  763. nodes = FillOutside(nodes, (g_bLeaked != true), 0); // make a leakfile if bad
  764. }
  765. FreePortals(nodes);
  766. // fix tjunctions
  767. tjunc(nodes);
  768. MakeFaceEdges();
  769. // emit the faces for the bsp file
  770. model->headnode[0] = g_numnodes;
  771. model->firstface = g_numfaces;
  772. WriteDrawNodes(nodes);
  773. model->numfaces = g_numfaces - model->firstface;
  774. model->visleafs = g_numleafs - startleafs;
  775. if (g_noclip)
  776. {
  777. return true;
  778. }
  779. // the clipping hulls are simpler
  780. for (g_hullnum = 1; g_hullnum < NUM_HULLS; g_hullnum++)
  781. {
  782. surfs = ReadSurfs(polyfiles[g_hullnum]);
  783. nodes = SolidBSP(surfs);
  784. if (g_nummodels == 1 && !g_nofill) // assume non-world bmodels are simple
  785. {
  786. nodes = FillOutside(nodes, (g_bLeaked != true), g_hullnum);
  787. }
  788. FreePortals(nodes);
  789. model->headnode[g_hullnum] = g_numclipnodes;
  790. WriteClipNodes(nodes);
  791. }
  792. return true;
  793. }
  794. #else
  795. // =====================================================================================
  796. // ProcessModel
  797. // =====================================================================================
  798. static bool ProcessModel()
  799. {
  800. surfchain_t* surfs;
  801. node_t* nodes;
  802. dmodel_t* model;
  803. int startleafs;
  804. surfs = ReadSurfs(polyfiles[0]);
  805. if (!surfs)
  806. return false; // all models are done
  807. hlassume(g_nummodels < MAX_MAP_MODELS, assume_MAX_MAP_MODELS);
  808. startleafs = g_numleafs;
  809. int modnum = g_nummodels;
  810. model = &g_dmodels[modnum];
  811. g_nummodels++;
  812. // Log("ProcessModel: %i (%i f)\n", modnum, model->numfaces);
  813. VectorCopy(surfs->mins, model->mins);
  814. VectorCopy(surfs->maxs, model->maxs);
  815. // SolidBSP generates a node tree
  816. nodes = SolidBSP(surfs,modnum==0);
  817. // build all the portals in the bsp tree
  818. // some portals are solid polygons, and some are paths to other leafs
  819. if (g_nummodels == 1 && !g_nofill) // assume non-world bmodels are simple
  820. {
  821. nodes = FillOutside(nodes, (g_bLeaked != true), 0); // make a leakfile if bad
  822. }
  823. FreePortals(nodes);
  824. // fix tjunctions
  825. tjunc(nodes);
  826. MakeFaceEdges();
  827. // emit the faces for the bsp file
  828. model->headnode[0] = g_numnodes;
  829. model->firstface = g_numfaces;
  830. WriteDrawNodes(nodes);
  831. model->numfaces = g_numfaces - model->firstface;
  832. model->visleafs = g_numleafs - startleafs;
  833. if (g_noclip)
  834. {
  835. /*
  836. KGP 12/31/03 - store empty content type in headnode pointers to signify
  837. lack of clipping information in a way that doesn't crash the half-life
  838. engine at runtime.
  839. */
  840. model->headnode[1] = CONTENTS_EMPTY;
  841. model->headnode[2] = CONTENTS_EMPTY;
  842. model->headnode[3] = CONTENTS_EMPTY;
  843. return true;
  844. }
  845. // the clipping hulls are simpler
  846. for (g_hullnum = 1; g_hullnum < NUM_HULLS; g_hullnum++)
  847. {
  848. surfs = ReadSurfs(polyfiles[g_hullnum]);
  849. nodes = SolidBSP(surfs,modnum==0);
  850. if (g_nummodels == 1 && !g_nofill) // assume non-world bmodels are simple
  851. {
  852. nodes = FillOutside(nodes, (g_bLeaked != true), g_hullnum);
  853. }
  854. FreePortals(nodes);
  855. /*
  856. KGP 12/31/03 - need to test that the head clip node isn't empty; if it is
  857. we need to set model->headnode equal to the content type of the head, or create
  858. a trivial single-node case where the content type is the same for both leaves
  859. if setting the content type is invalid.
  860. */
  861. if(nodes->planenum == -1) //empty!
  862. {
  863. model->headnode[g_hullnum] = nodes->contents;
  864. }
  865. else
  866. {
  867. model->headnode[g_hullnum] = g_numclipnodes;
  868. WriteClipNodes(nodes);
  869. }
  870. }
  871. return true;
  872. }
  873. #endif
  874. // =====================================================================================
  875. // Usage
  876. // =====================================================================================
  877. static void Usage()
  878. {
  879. Banner();
  880. Log("\n-= %s Options =-\n\n", g_Program);
  881. Log(" -leakonly : Run BSP only enough to check for LEAKs\n");
  882. Log(" -subdivide # : Sets the face subdivide size\n");
  883. Log(" -maxnodesize # : Sets the maximum portal node size\n\n");
  884. Log(" -notjunc : Don't break edges on t-junctions (not for final runs)\n");
  885. Log(" -noclip : Don't process the clipping hull (not for final runs)\n");
  886. Log(" -nofill : Don't fill outside (will mask LEAKs) (not for final runs)\n");
  887. Log(" -noopt : Don't optimize planes on BSP write (not for final runs)\n\n");
  888. Log(" -texdata # : Alter maximum texture memory limit (in kb)\n");
  889. Log(" -lightdata # : Alter maximum lighting memory limit (in kb)\n");
  890. Log(" -chart : display bsp statitics\n");
  891. Log(" -low | -high : run program an altered priority level\n");
  892. Log(" -nolog : don't generate the compile logfiles\n");
  893. Log(" -threads # : manually specify the number of threads to run\n");
  894. Log(" -noconcolors : Disable Windows console text coloring\n");
  895. #ifdef SYSTEM_WIN32
  896. Log(" -estimate : display estimated time during compile\n");
  897. #endif
  898. #ifdef ZHLT_PROGRESSFILE // AJM
  899. Log(" -progressfile path : specify the path to a file for progress estimate output\n");
  900. #endif
  901. #ifdef SYSTEM_POSIX
  902. Log(" -noestimate : do not display continuous compile time estimates\n");
  903. #endif
  904. #ifdef ZHLT_NULLTEX // AJM
  905. Log(" -nonulltex : Don't strip NULL faces\n");
  906. #endif
  907. #ifdef ZHLT_DETAIL // AJM
  908. Log(" -nodetail : don't handle detail brushes\n");
  909. #endif
  910. Log(" -verbose : compile with verbose messages\n");
  911. Log(" -noinfo : Do not show tool configuration information\n");
  912. Log(" -dev # : compile with developer message\n\n");
  913. Log(" mapfile : The mapfile to compile\n\n");
  914. exit(1);
  915. }
  916. // =====================================================================================
  917. // Settings
  918. // =====================================================================================
  919. static void Settings()
  920. {
  921. char* tmp;
  922. if (!g_info)
  923. return;
  924. Log("\nCurrent %s Settings\n", g_Program);
  925. Log("Name | Setting | Default\n" "-------------------|-------------|-------------------------\n");
  926. // ZHLT Common Settings
  927. if (DEFAULT_NUMTHREADS == -1)
  928. {
  929. Log("threads [ %9d ] [ Varies ]\n", g_numthreads);
  930. }
  931. else
  932. {
  933. Log("threads [ %9d ] [ %9d ]\n", g_numthreads, DEFAULT_NUMTHREADS);
  934. }
  935. Log("verbose [ %9s ] [ %9s ]\n", g_verbose ? "on" : "off", DEFAULT_VERBOSE ? "on" : "off");
  936. Log("log [ %9s ] [ %9s ]\n", g_log ? "on" : "off", DEFAULT_LOG ? "on" : "off");
  937. Log("developer [ %9d ] [ %9d ]\n", g_developer, DEFAULT_DEVELOPER);
  938. Log("chart [ %9s ] [ %9s ]\n", g_chart ? "on" : "off", DEFAULT_CHART ? "on" : "off");
  939. Log("estimate [ %9s ] [ %9s ]\n", g_estimate ? "on" : "off", DEFAULT_ESTIMATE ? "on" : "off");
  940. Log("max texture memory [ %9d ] [ %9d ]\n", g_max_map_miptex, DEFAULT_MAX_MAP_MIPTEX);
  941. switch (g_threadpriority)
  942. {
  943. case eThreadPriorityNormal:
  944. default:
  945. tmp = "Normal";
  946. break;
  947. case eThreadPriorityLow:
  948. tmp = "Low";
  949. break;
  950. case eThreadPriorityHigh:
  951. tmp = "High";
  952. break;
  953. }
  954. Log("priority [ %9s ] [ %9s ]\n", tmp, "Normal");
  955. Log("\n");
  956. // HLBSP Specific Settings
  957. Log("noclip [ %9s ] [ %9s ]\n", g_noclip ? "on" : "off", DEFAULT_NOCLIP ? "on" : "off");
  958. Log("nofill [ %9s ] [ %9s ]\n", g_nofill ? "on" : "off", DEFAULT_NOFILL ? "on" : "off");
  959. Log("noopt [ %9s ] [ %9s ]\n", g_noopt ? "on" : "off", DEFAULT_NOOPT ? "on" : "off");
  960. #ifdef ZHLT_NULLTEX // AJM
  961. Log("null tex. stripping [ %9s ] [ %9s ]\n", g_bUseNullTex ? "on" : "off", DEFAULT_NULLTEX ? "on" : "off" );
  962. #endif
  963. #ifdef ZHLT_DETAIL // AJM
  964. Log("detail brushes [ %9s ] [ %9s ]\n", g_bDetailBrushes ? "on" : "off", DEFAULT_DETAIL ? "on" : "off" );
  965. #endif
  966. Log("notjunc [ %9s ] [ %9s ]\n", g_notjunc ? "on" : "off", DEFAULT_NOTJUNC ? "on" : "off");
  967. Log("subdivide size [ %9d ] [ %9d ] (Min %d) (Max %d)\n",
  968. g_subdivide_size, DEFAULT_SUBDIVIDE_SIZE, MIN_SUBDIVIDE_SIZE, MAX_SUBDIVIDE_SIZE);
  969. Log("max node size [ %9d ] [ %9d ] (Min %d) (Max %d)\n",
  970. g_maxnode_size, DEFAULT_MAXNODE_SIZE, MIN_MAXNODE_SIZE, MAX_MAXNODE_SIZE);
  971. Log("\n\n");
  972. }
  973. // =====================================================================================
  974. // ProcessFile
  975. // =====================================================================================
  976. static void ProcessFile(const char* const filename)
  977. {
  978. int i;
  979. char name[_MAX_PATH];
  980. // delete existing files
  981. safe_snprintf(g_portfilename, _MAX_PATH, "%s.prt", filename);
  982. unlink(g_portfilename);
  983. safe_snprintf(g_pointfilename, _MAX_PATH, "%s.pts", filename);
  984. unlink(g_pointfilename);
  985. safe_snprintf(g_linefilename, _MAX_PATH, "%s.lin", filename);
  986. unlink(g_linefilename);
  987. // open the hull files
  988. for (i = 0; i < NUM_HULLS; i++)
  989. {
  990. //mapname.p[0-3]
  991. sprintf(name, "%s.p%i", filename, i);
  992. polyfiles[i] = fopen(name, "r");
  993. if (!polyfiles[i])
  994. Error("Can't open %s", name);
  995. }
  996. // load the output of csg
  997. safe_snprintf(g_bspfilename, _MAX_PATH, "%s.bsp", filename);
  998. LoadBSPFile(g_bspfilename);
  999. ParseEntities(NULL, NULL);
  1000. Settings(); // AJM: moved here due to info_compile_parameters entity
  1001. // init the tables to be shared by all models
  1002. BeginBSPFile();
  1003. #ifdef HLBSP_THREADS // AJM
  1004. NamedRunThreadsOnIndividual(nummodels, g_estimate, ProcessModel);
  1005. #else
  1006. // process each model individually
  1007. while (ProcessModel())
  1008. ;
  1009. #endif
  1010. // SILENCER -->
  1011. // Just warn the mapper, don't abort the compilation.
  1012. // It is up to him whether to try this or not.
  1013. if(g_numclipnodes > 32767) {
  1014. Warning("%i out of 32767 clipnodes maximum.\n"
  1015. " Your compiled map will have unsolid brushes, through which\n"
  1016. " the player can fall outside world. Try to make use of the clip\n"
  1017. " texture to simplify the clipping of complex structures and details,\n"
  1018. " if you did not already.", g_numclipnodes);
  1019. }
  1020. // <-- SILENCER
  1021. // write the updated bsp file out
  1022. FinishBSPFile();
  1023. }
  1024. // =====================================================================================
  1025. // main
  1026. // =====================================================================================
  1027. int main(const int argc, char** argv)
  1028. {
  1029. int i;
  1030. double start, end;
  1031. const char* mapname_from_arg = NULL;
  1032. g_Program = "hlbsp";
  1033. // if we dont have any command line argvars, print out usage and die
  1034. if (argc == 1)
  1035. Usage();
  1036. // check command line args
  1037. for (i = 1; i < argc; i++)
  1038. {
  1039. if (!strcasecmp(argv[i], "-threads"))
  1040. {
  1041. if (i < argc)
  1042. {
  1043. int g_numthreads = atoi(argv[++i]);
  1044. if (g_numthreads < 1)
  1045. {
  1046. Log("Expected value of at least 1 for '-threads'\n");
  1047. Usage();
  1048. }
  1049. }
  1050. else
  1051. {
  1052. Usage();
  1053. }
  1054. }
  1055. else if (!strcasecmp(argv[i], "-notjunc"))
  1056. {
  1057. g_notjunc = true;
  1058. }
  1059. else if (!strcasecmp(argv[i], "-noclip"))
  1060. {
  1061. g_noclip = true;
  1062. }
  1063. else if (!strcasecmp(argv[i], "-nofill"))
  1064. {
  1065. g_nofill = true;
  1066. }
  1067. #ifdef SYSTEM_WIN32
  1068. else if (!strcasecmp(argv[i], "-estimate"))
  1069. {
  1070. g_estimate = true;
  1071. }
  1072. #endif
  1073. #ifdef SYSTEM_POSIX
  1074. else if (!strcasecmp(argv[i], "-noestimate"))
  1075. {
  1076. g_estimate = false;
  1077. }
  1078. #endif
  1079. #ifdef ZHLT_NETVIS
  1080. else if (!strcasecmp(argv[i], "-client"))
  1081. {
  1082. if (i < argc)
  1083. {
  1084. g_clientid = atoi(argv[++i]);
  1085. }
  1086. else
  1087. {
  1088. Usage();
  1089. }
  1090. }
  1091. #endif
  1092. #ifdef ZHLT_PROGRESSFILE // AJM
  1093. else if (!strcasecmp(argv[i], "-progressfile"))
  1094. {
  1095. if (i < argc)
  1096. {
  1097. g_progressfile = argv[++i];
  1098. }
  1099. else
  1100. {
  1101. Log("Error: -progressfile: expected path to progress file following parameter\n");
  1102. Usage();
  1103. }
  1104. }
  1105. #endif
  1106. else if (!strcasecmp(argv[i], "-dev"))
  1107. {
  1108. if (i < argc)
  1109. {
  1110. g_developer = (developer_level_t)atoi(argv[++i]);
  1111. }
  1112. else
  1113. {
  1114. Usage();
  1115. }
  1116. }
  1117. else if (!strcasecmp(argv[i], "-verbose"))
  1118. {
  1119. g_verbose = true;
  1120. }
  1121. else if (!strcasecmp(argv[i], "-noinfo"))
  1122. {
  1123. g_info = false;
  1124. }
  1125. else if (!strcasecmp(argv[i], "-leakonly"))
  1126. {
  1127. g_bLeakOnly = true;
  1128. }
  1129. else if (!strcasecmp(argv[i], "-chart"))
  1130. {
  1131. g_chart = true;
  1132. }
  1133. else if (!strcasecmp(argv[i], "-low"))
  1134. {
  1135. g_threadpriority = eThreadPriorityLow;
  1136. }
  1137. else if (!strcasecmp(argv[i], "-high"))
  1138. {
  1139. g_threadpriority = eThreadPriorityHigh;
  1140. }
  1141. else if (!strcasecmp(argv[i], "-nolog"))
  1142. {
  1143. g_log = false;
  1144. }
  1145. #ifdef ZHLT_NULLTEX // AJM
  1146. else if (!strcasecmp(argv[i], "-nonulltex"))
  1147. {
  1148. g_bUseNullTex = false;
  1149. }
  1150. #endif
  1151. #ifdef ZHLT_DETAIL // AJM
  1152. else if (!strcasecmp(argv[i], "-nodetail"))
  1153. {
  1154. g_bDetailBrushes = false;
  1155. }
  1156. #endif
  1157. else if (!strcasecmp(argv[i], "-noopt"))
  1158. {
  1159. g_noopt = true;
  1160. }
  1161. else if (!strcasecmp(argv[i], "-subdivide"))
  1162. {
  1163. if (i < argc)
  1164. {
  1165. g_subdivide_size = atoi(argv[++i]);
  1166. if (g_subdivide_size > MAX_SUBDIVIDE_SIZE)
  1167. {
  1168. Warning
  1169. ("Maximum value for subdivide size is %i, '-subdivide %i' ignored",
  1170. MAX_SUBDIVIDE_SIZE, g_subdivide_size);
  1171. g_subdivide_size = MAX_SUBDIVIDE_SIZE;
  1172. }
  1173. else if (g_subdivide_size < MIN_SUBDIVIDE_SIZE)
  1174. {
  1175. Warning
  1176. ("Mininum value for subdivide size is %i, '-subdivide %i' ignored",
  1177. MIN_SUBDIVIDE_SIZE, g_subdivide_size);
  1178. g_subdivide_size = MAX_SUBDIVIDE_SIZE;
  1179. }
  1180. }
  1181. else
  1182. {
  1183. Usage();
  1184. }
  1185. }
  1186. else if (!strcasecmp(argv[i], "-maxnodesize"))
  1187. {
  1188. if (i < argc)
  1189. {
  1190. g_maxnode_size = atoi(argv[++i]);
  1191. if (g_maxnode_size > MAX_MAXNODE_SIZE)
  1192. {
  1193. Warning
  1194. ("Maximum value for max node size is %i, '-maxnodesize %i' ignored",
  1195. MAX_MAXNODE_SIZE, g_maxnode_size);
  1196. g_maxnode_size = MAX_MAXNODE_SIZE;
  1197. }
  1198. else if (g_maxnode_size < MIN_MAXNODE_SIZE)
  1199. {
  1200. Warning
  1201. ("Mininimum value for max node size is %i, '-maxnodesize %i' ignored",
  1202. MIN_MAXNODE_SIZE, g_maxnode_size);
  1203. g_maxnode_size = MAX_MAXNODE_SIZE;
  1204. }
  1205. }
  1206. else
  1207. {
  1208. Usage();
  1209. }
  1210. }
  1211. else if (!strcasecmp(argv[i], "-texdata"))
  1212. {
  1213. if (i < argc)
  1214. {
  1215. int x = atoi(argv[++i]) * 1024;
  1216. if (x > g_max_map_miptex)
  1217. {
  1218. g_max_map_miptex = x;
  1219. }
  1220. }
  1221. else
  1222. {
  1223. Usage();
  1224. }
  1225. }
  1226. else if (!strcasecmp(argv[i], "-lightdata"))
  1227. {
  1228. if (i < argc)
  1229. {
  1230. int x = atoi(argv[++i]) * 1024;
  1231. if (x > g_max_map_lightdata)
  1232. {
  1233. g_max_map_lightdata = x;
  1234. }
  1235. }
  1236. else
  1237. {
  1238. Usage();
  1239. }
  1240. }
  1241. // SILENCER -->
  1242. else if (!strcasecmp(argv[i], "-noconcolors"))
  1243. {
  1244. g_noConColors = true;
  1245. }
  1246. // <-- SILENCER
  1247. else if (argv[i][0] == '-')
  1248. {
  1249. Log("Unknown option \"%s\"\n", argv[i]);
  1250. Usage();
  1251. }
  1252. else if (!mapname_from_arg)
  1253. {
  1254. mapname_from_arg = argv[i];
  1255. }
  1256. else
  1257. {
  1258. Log("Unknown option \"%s\"\n", argv[i]);
  1259. Usage();
  1260. }
  1261. }
  1262. if (!mapname_from_arg)
  1263. {
  1264. Log("No mapfile specified\n");
  1265. Usage();
  1266. }
  1267. safe_strncpy(g_Mapname, mapname_from_arg, _MAX_PATH);
  1268. FlipSlashes(g_Mapname);
  1269. StripExtension(g_Mapname);
  1270. OpenLog(g_clientid);
  1271. atexit(CloseLog);
  1272. ThreadSetDefault();
  1273. ThreadSetPriority(g_threadpriority);
  1274. LogStart(argc, argv);
  1275. CheckForErrorLog();
  1276. dtexdata_init();
  1277. atexit(dtexdata_free);
  1278. //Settings();
  1279. // END INIT
  1280. // Load the .void files for allowable entities in the void
  1281. {
  1282. char g_source[_MAX_PATH];
  1283. char strSystemEntitiesVoidFile[_MAX_PATH];
  1284. char strMapEntitiesVoidFile[_MAX_PATH];
  1285. safe_strncpy(g_source, mapname_from_arg, _MAX_PATH);
  1286. StripExtension(g_source);
  1287. // try looking in the current directory
  1288. safe_strncpy(strSystemEntitiesVoidFile, ENTITIES_VOID, _MAX_PATH);
  1289. if (!q_exists(strSystemEntitiesVoidFile))
  1290. {
  1291. char tmp[_MAX_PATH];
  1292. // try looking in the directory we were run from
  1293. #ifdef SYSTEM_WIN32
  1294. GetModuleFileName(NULL, tmp, _MAX_PATH);
  1295. #else
  1296. safe_strncpy(tmp, argv[0], _MAX_PATH);
  1297. #endif
  1298. ExtractFilePath(tmp, strSystemEntitiesVoidFile);
  1299. safe_strncat(strSystemEntitiesVoidFile, ENTITIES_VOID, _MAX_PATH);
  1300. }
  1301. // Set the optional level specific lights filename
  1302. safe_strncpy(strMapEntitiesVoidFile, g_source, _MAX_PATH);
  1303. DefaultExtension(strMapEntitiesVoidFile, ENTITIES_VOID_EXT);
  1304. LoadAllowableOutsideList(strSystemEntitiesVoidFile); // default entities.void
  1305. if (*strMapEntitiesVoidFile)
  1306. {
  1307. LoadAllowableOutsideList(strMapEntitiesVoidFile); // automatic mapname.void
  1308. }
  1309. }
  1310. // BEGIN BSP
  1311. start = I_FloatTime();
  1312. ProcessFile(g_Mapname);
  1313. end = I_FloatTime();
  1314. LogTimeElapsed(end - start);
  1315. // END BSP
  1316. FreeAllowableOutsideList();
  1317. return 0;
  1318. }