textures.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. #ifdef SYSTEM_WIN32
  2. #pragma warning(disable:4996)
  3. #endif
  4. #include "csg.h"
  5. #define MAXWADNAME 16
  6. #define MAX_TEXFILES 128
  7. // FindMiptex
  8. // TEX_InitFromWad
  9. // FindTexture
  10. // LoadLump
  11. // AddAnimatingTextures
  12. typedef struct
  13. {
  14. char identification[4]; // should be WAD2/WAD3
  15. int numlumps;
  16. int infotableofs;
  17. } wadinfo_t;
  18. typedef struct
  19. {
  20. int filepos;
  21. int disksize;
  22. int size; // uncompressed
  23. char type;
  24. char compression;
  25. char pad1, pad2;
  26. char name[MAXWADNAME]; // must be null terminated
  27. int iTexFile; // index of the wad this texture is located in
  28. } lumpinfo_t;
  29. std::deque< std::string > g_WadInclude;
  30. std::map< int, bool > s_WadIncludeMap;
  31. static int nummiptex = 0;
  32. static lumpinfo_t miptex[MAX_MAP_TEXTURES];
  33. static int nTexLumps = 0;
  34. static lumpinfo_t* lumpinfo = NULL;
  35. static int nTexFiles = 0;
  36. static FILE* texfiles[MAX_TEXFILES];
  37. // fix for 64 bit machines
  38. #if SIZEOF_CHARP == 8
  39. static char* texmap64[MAX_MAP_BRUSHES];
  40. static int tex_max64=0;
  41. static inline int texmap64_store(char *texname)
  42. {
  43. int curr_tex;
  44. ThreadLock();
  45. if (tex_max64 >= MAX_MAP_BRUSHES) // no assert?
  46. {
  47. printf("MAX_MAP_BRUSHES exceeded!\n");
  48. exit(-1);
  49. }
  50. curr_tex = tex_max64;
  51. texmap64[tex_max64] = texname;
  52. tex_max64++;
  53. ThreadUnlock();
  54. return curr_tex;
  55. }
  56. static inline char* texmap64_retrieve( int index)
  57. {
  58. if(index > tex_max64)
  59. {
  60. printf("retrieving bogus texture index %d\n", index);
  61. exit(-1);
  62. }
  63. return texmap64[index];
  64. }
  65. #else // SIZEOF_CHARP != 8, almost certainly 4
  66. #define texmap64_store( A ) ( (int) A)
  67. #define texmap64_retrieve( A ) ( (char*) A)
  68. #endif // SIZEOF_CHARP
  69. // =====================================================================================
  70. // CleanupName
  71. // =====================================================================================
  72. static void CleanupName(const char* const in, char* out)
  73. {
  74. int i;
  75. for (i = 0; i < MAXWADNAME; i++)
  76. {
  77. if (!in[i])
  78. {
  79. break;
  80. }
  81. out[i] = toupper(in[i]);
  82. }
  83. for (; i < MAXWADNAME; i++)
  84. {
  85. out[i] = 0;
  86. }
  87. }
  88. // =====================================================================================
  89. // lump_sorters
  90. // =====================================================================================
  91. static int CDECL lump_sorter_by_wad_and_name(const void* lump1, const void* lump2)
  92. {
  93. lumpinfo_t* plump1 = (lumpinfo_t*)lump1;
  94. lumpinfo_t* plump2 = (lumpinfo_t*)lump2;
  95. if (plump1->iTexFile == plump2->iTexFile)
  96. {
  97. return strcmp(plump1->name, plump2->name);
  98. }
  99. else
  100. {
  101. return plump1->iTexFile - plump2->iTexFile;
  102. }
  103. }
  104. static int CDECL lump_sorter_by_name(const void* lump1, const void* lump2)
  105. {
  106. lumpinfo_t* plump1 = (lumpinfo_t*)lump1;
  107. lumpinfo_t* plump2 = (lumpinfo_t*)lump2;
  108. return strcmp(plump1->name, plump2->name);
  109. }
  110. // =====================================================================================
  111. // FindMiptex
  112. // Find and allocate a texture into the lump data
  113. // =====================================================================================
  114. static int FindMiptex(const char* const name)
  115. {
  116. int i;
  117. ThreadLock();
  118. for (i = 0; i < nummiptex; i++)
  119. {
  120. if (!strcmp(name, miptex[i].name))
  121. {
  122. ThreadUnlock();
  123. return i;
  124. }
  125. }
  126. hlassume(nummiptex < MAX_MAP_TEXTURES, assume_MAX_MAP_TEXTURES);
  127. safe_strncpy(miptex[i].name, name, MAXWADNAME);
  128. nummiptex++;
  129. ThreadUnlock();
  130. return i;
  131. }
  132. // =====================================================================================
  133. // TEX_InitFromWad
  134. // =====================================================================================
  135. bool TEX_InitFromWad()
  136. {
  137. int i, j;
  138. wadinfo_t wadinfo;
  139. char szTmpWad[1024]; // arbitrary, but needs to be large.
  140. char* pszWadFile;
  141. const char* pszWadroot;
  142. wadpath_t* currentwad;
  143. Log("\n\nChecking Wadfiles (max. expected texture size is %i bytes):\n\n", MAX_TEXTURE_SIZE); //SILENCER //Indentation and blank lines make it much easier to view
  144. szTmpWad[0] = 0;
  145. pszWadroot = getenv("WADROOT");
  146. #ifdef HLCSG_AUTOWAD
  147. autowad_UpdateUsedWads();
  148. #endif
  149. // for eachwadpath
  150. for (i = 0; i < g_iNumWadPaths; i++)
  151. {
  152. FILE* texfile; // temporary used in this loop
  153. bool bExcludeThisWad = false;
  154. currentwad = g_pWadPaths[i];
  155. pszWadFile = currentwad->path;
  156. #ifdef HLCSG_AUTOWAD
  157. #ifdef _DEBUG
  158. Log("[dbg] Attempting to parse wad: '%s'\n", pszWadFile);
  159. #endif
  160. if (g_bWadAutoDetect && !currentwad->usedtextures)
  161. continue;
  162. #ifdef _DEBUG
  163. Log("[dbg] Parsing wad\n");
  164. #endif
  165. #endif
  166. texfiles[nTexFiles] = fopen(pszWadFile, "rb");
  167. #ifdef SYSTEM_WIN32
  168. if (!texfiles[nTexFiles])
  169. {
  170. // cant find it, maybe this wad file has a hard code drive
  171. if (pszWadFile[1] == ':')
  172. {
  173. pszWadFile += 2; // skip past the drive
  174. texfiles[nTexFiles] = fopen(pszWadFile, "rb");
  175. }
  176. }
  177. #endif
  178. if (!texfiles[nTexFiles] && pszWadroot)
  179. {
  180. char szTmp[_MAX_PATH];
  181. char szFile[_MAX_PATH];
  182. char szSubdir[_MAX_PATH];
  183. ExtractFile(pszWadFile, szFile);
  184. ExtractFilePath(pszWadFile, szTmp);
  185. ExtractFile(szTmp, szSubdir);
  186. // szSubdir will have a trailing separator
  187. safe_snprintf(szTmp, _MAX_PATH, "%s" SYSTEM_SLASH_STR "%s%s", pszWadroot, szSubdir, szFile);
  188. texfiles[nTexFiles] = fopen(szTmp, "rb");
  189. #ifdef SYSTEM_POSIX
  190. if (!texfiles[nTexFiles])
  191. {
  192. // if we cant find it, Convert to lower case and try again
  193. strlwr(szTmp);
  194. texfiles[nTexFiles] = fopen(szTmp, "rb");
  195. }
  196. #endif
  197. }
  198. if (!texfiles[nTexFiles])
  199. {
  200. // still cant find it, error out
  201. Log(" "); //SILENCER //Indentation and blank lines make it much easier to view
  202. Fatal(assume_COULD_NOT_FIND_WAD, "Could not open wad file %s", pszWadFile);
  203. continue;
  204. }
  205. // look and see if we're supposed to include the textures from this WAD in the bsp.
  206. WadInclude_i it;
  207. for (it = g_WadInclude.begin(); it != g_WadInclude.end(); it++)
  208. {
  209. if (stristr(pszWadFile, it->c_str()))
  210. {
  211. //SILENCER //Indentation and blank lines make it much easier to view
  212. Log(" Including Wadfile: %s:\n", pszWadFile);
  213. bExcludeThisWad = true; // wadincluding this one
  214. s_WadIncludeMap[nTexFiles] = true;
  215. break;
  216. }
  217. }
  218. if (!bExcludeThisWad)
  219. {
  220. //SILENCER //Indentation and blank lines make it much easier to view
  221. Log(" Using Wadfile: %s:\n", pszWadFile);
  222. safe_snprintf(szTmpWad, 1024, "%s%s;", szTmpWad, pszWadFile);
  223. }
  224. // temp assignment to make things cleaner:
  225. texfile = texfiles[nTexFiles];
  226. // read in this wadfiles information
  227. SafeRead(texfile, &wadinfo, sizeof(wadinfo));
  228. // make sure its a valid format
  229. if (strncmp(wadinfo.identification, "WAD2", 4) && strncmp(wadinfo.identification, "WAD3", 4))
  230. {
  231. Log(" "); //SILENCER //Indentation and blank lines make it much easier to view
  232. Error("%s isn't a Wadfile!", pszWadFile);
  233. }
  234. wadinfo.numlumps = LittleLong(wadinfo.numlumps);
  235. wadinfo.infotableofs = LittleLong(wadinfo.infotableofs);
  236. // read in lump
  237. if (fseek(texfile, wadinfo.infotableofs, SEEK_SET)) {
  238. Log(" "); //SILENCER //Indentation and blank lines make it much easier to view
  239. Warning("fseek to %d in wadfile %s failed", wadinfo.infotableofs, pszWadFile);
  240. }
  241. // memalloc for this lump
  242. lumpinfo = (lumpinfo_t*)realloc(lumpinfo, (nTexLumps + wadinfo.numlumps) * sizeof(lumpinfo_t));
  243. // for each texlump
  244. for (j = 0; j < wadinfo.numlumps; j++, nTexLumps++)
  245. {
  246. SafeRead(texfile, &lumpinfo[nTexLumps], (sizeof(lumpinfo_t) - sizeof(int)) ); // iTexFile is NOT read from file
  247. if (!TerminatedString(lumpinfo[nTexLumps].name, MAXWADNAME))
  248. {
  249. lumpinfo[nTexLumps].name[MAXWADNAME - 1] = 0;
  250. Log(" "); //SILENCER //Indentation and blank lines make it much easier to view
  251. Warning("Unterminated texture name : wad[%s] texture[%d] name[%s]\n", pszWadFile, nTexLumps, lumpinfo[nTexLumps].name);
  252. }
  253. CleanupName(lumpinfo[nTexLumps].name, lumpinfo[nTexLumps].name);
  254. lumpinfo[nTexLumps].filepos = LittleLong(lumpinfo[nTexLumps].filepos);
  255. lumpinfo[nTexLumps].disksize = LittleLong(lumpinfo[nTexLumps].disksize);
  256. lumpinfo[nTexLumps].iTexFile = nTexFiles;
  257. if (lumpinfo[nTexLumps].disksize > MAX_TEXTURE_SIZE)
  258. {
  259. Log(" "); //SILENCER //Indentation and blank lines make it much easier to view
  260. Warning("Larger than expected texture (%d bytes): '%s'",
  261. lumpinfo[nTexLumps].disksize, lumpinfo[nTexLumps].name);
  262. }
  263. }
  264. // AJM: this feature is dependant on autowad. :(
  265. // CONSIDER: making it standard?
  266. #ifdef HLCSG_AUTOWAD
  267. {
  268. double percused = ((float)(currentwad->usedtextures) / (float)(g_numUsedTextures)) * 100;
  269. //SILENCER //Indentation and blank lines make it much easier to view:
  270. Log(" Contains %i used texture%s, %2.2f percent of map. (%d textures in wad)\n\n",
  271. currentwad->usedtextures, currentwad->usedtextures == 1 ? "" : "s", percused, wadinfo.numlumps);
  272. }
  273. #endif
  274. nTexFiles++;
  275. hlassume(nTexFiles < MAX_TEXFILES, assume_MAX_TEXFILES);
  276. }
  277. //Log("num of used textures: %i\n", g_numUsedTextures);
  278. // AJM: Tommy suggested i add this warning message in, and it certainly doesnt
  279. // hurt to be cautious. Especially one of the possible side effects he mentioned was svc_bad
  280. if (nTexFiles > 8)
  281. {
  282. Warning("More than 8 wadfiles are in use. (%i)\n"
  283. "This may be harmless, and if no strange side effects are occurring, then\n"
  284. "it can safely be ignored. However, if your map starts exhibiting strange\n"
  285. "or obscure errors, consider this as suspect. One of the possible side\n"
  286. "effects is getting an svc_bad error, by which a client drops from the game."
  287. , nTexFiles); //SILENCER: Added the note about possible svc_bad to the warning message.
  288. }
  289. // sort texlumps in memory by name
  290. qsort((void*)lumpinfo, (size_t) nTexLumps, sizeof(lumpinfo[0]), lump_sorter_by_name);
  291. SetKeyValue(&g_entities[0], "wad", szTmpWad);
  292. Log("\n");
  293. CheckFatal();
  294. return true;
  295. }
  296. // =====================================================================================
  297. // FindTexture
  298. // =====================================================================================
  299. lumpinfo_t* FindTexture(const lumpinfo_t* const source)
  300. {
  301. //Log("** PnFNFUNC: FindTexture\n");
  302. lumpinfo_t* found = NULL;
  303. found = (lumpinfo_t*)bsearch(source, (void*)lumpinfo, (size_t) nTexLumps, sizeof(lumpinfo[0]), lump_sorter_by_name);
  304. if (!found)
  305. {
  306. Warning("::FindTexture() texture %s not found!", source->name);
  307. if (!strcmp(source->name, "NULL"))
  308. {
  309. Log("Are you sure you included zhlt.wad in your wadpath list?\n");
  310. }
  311. }
  312. return found;
  313. }
  314. // =====================================================================================
  315. // TestIncludeTextureNamed
  316. // check to see if this texture should never be included -- should fix problematic
  317. // sky behavior.
  318. //
  319. // TODO : fix any texture used by this code so that it is always contained in a
  320. // non-included wad or throw warning and include anyway
  321. // =====================================================================================
  322. bool TestIncludeTextureNamed(const char* const name)
  323. {
  324. bool shouldInclude = true;
  325. /* switch(name[0])
  326. {
  327. case 'a': case 'A':
  328. if(!stricmp(name,"AAATRIGGER"))
  329. { shouldInclude = false; }
  330. break;
  331. case 'c': case 'C':
  332. if(!stricmp(name,"CLIP"))
  333. { shouldInclude = false; }
  334. break;
  335. case 'h': case 'H':
  336. if(!stricmp(name,"HINT"))
  337. { shouldInclude = false; }
  338. break;
  339. // case 'n': case 'N':
  340. // if(!stricmp(name,"NULL"))
  341. // { shouldInclude = false; }
  342. // break;
  343. case 'o': case 'O':
  344. if(!stricmp(name,"ORIGIN"))
  345. { shouldInclude = false; }
  346. break;
  347. case 's': case 'S':
  348. if(!stricmp(name,"SKY") || !stricmp(name,"SKIP"))
  349. { shouldInclude = false; }
  350. break;
  351. }
  352. */
  353. if(!shouldInclude)
  354. { Warning("Overriding inclusion of common texture: %s",name); }
  355. return shouldInclude;
  356. }
  357. // =====================================================================================
  358. // LoadLump
  359. // =====================================================================================
  360. int LoadLump(const lumpinfo_t* const source, byte* dest, int* texsize)
  361. {
  362. //Log("** PnFNFUNC: LoadLump\n");
  363. *texsize = 0;
  364. if (source->filepos)
  365. {
  366. if (fseek(texfiles[source->iTexFile], source->filepos, SEEK_SET)) {
  367. Log(" "); //SILENCER //Indentation and blank lines make it much easier to view
  368. Warning("fseek to %d failed\n", source->filepos);
  369. }
  370. *texsize = source->disksize;
  371. bool wadinclude = false;
  372. std::map< int, bool >::iterator it;
  373. it = s_WadIncludeMap.find(source->iTexFile);
  374. if (it != s_WadIncludeMap.end())
  375. {
  376. wadinclude = it->second;
  377. }
  378. // Should we just load the texture header w/o the palette & bitmap?
  379. if ((g_wadtextures && !wadinclude) || !TestIncludeTextureNamed(source->name))
  380. {
  381. // Just read the miptex header and zero out the data offsets.
  382. // We will load the entire texture from the WAD at engine runtime
  383. int i;
  384. miptex_t* miptex = (miptex_t*)dest;
  385. SafeRead(texfiles[source->iTexFile], dest, sizeof(miptex_t));
  386. for (i = 0; i < MIPLEVELS; i++)
  387. miptex->offsets[i] = 0;
  388. return sizeof(miptex_t);
  389. }
  390. else
  391. {
  392. Developer(DEVELOPER_LEVEL_MESSAGE,"Including texture %s\n",source->name);
  393. // Load the entire texture here so the BSP contains the texture
  394. SafeRead(texfiles[source->iTexFile], dest, source->disksize);
  395. return source->disksize;
  396. }
  397. }
  398. Log(" "); //SILENCER //Indentation and blank lines make it much easier to view
  399. Warning("::LoadLump() texture %s not found!", source->name);
  400. return 0;
  401. }
  402. // =====================================================================================
  403. // AddAnimatingTextures
  404. // =====================================================================================
  405. void AddAnimatingTextures()
  406. {
  407. int base;
  408. int i, j, k;
  409. char name[MAXWADNAME];
  410. base = nummiptex;
  411. for (i = 0; i < base; i++)
  412. {
  413. if ((miptex[i].name[0] != '+') && (miptex[i].name[0] != '-'))
  414. {
  415. continue;
  416. }
  417. safe_strncpy(name, miptex[i].name, MAXWADNAME);
  418. for (j = 0; j < 20; j++)
  419. {
  420. if (j < 10)
  421. {
  422. name[1] = '0' + j;
  423. }
  424. else
  425. {
  426. name[1] = 'A' + j - 10; // alternate animation
  427. }
  428. // see if this name exists in the wadfile
  429. for (k = 0; k < nTexLumps; k++)
  430. {
  431. if (!strcmp(name, lumpinfo[k].name))
  432. {
  433. FindMiptex(name); // add to the miptex list
  434. break;
  435. }
  436. }
  437. }
  438. }
  439. if (nummiptex - base)
  440. {
  441. Log("Added %i additional animating textures.\n\n", nummiptex - base);
  442. }
  443. }
  444. // =====================================================================================
  445. // GetWadPath
  446. // AJM: this sub is obsolete
  447. // =====================================================================================
  448. char* GetWadPath()
  449. {
  450. const char* path = ValueForKey(&g_entities[0], "_wad");
  451. if (!path || !path[0])
  452. {
  453. path = ValueForKey(&g_entities[0], "wad");
  454. if (!path || !path[0])
  455. {
  456. Warning("no wadfile specified");
  457. return strdup("");
  458. }
  459. }
  460. return strdup(path);
  461. }
  462. // =====================================================================================
  463. // WriteMiptex
  464. // =====================================================================================
  465. void WriteMiptex()
  466. {
  467. int len, texsize, totaltexsize = 0;
  468. byte* data;
  469. dmiptexlump_t* l;
  470. double start, end;
  471. g_texdatasize = 0;
  472. start = I_FloatTime();
  473. {
  474. if (!TEX_InitFromWad())
  475. return;
  476. AddAnimatingTextures();
  477. }
  478. end = I_FloatTime();
  479. Verbose("TEX_InitFromWad & AddAnimatingTextures elapsed time = %ldms\n", (long)(end - start));
  480. start = I_FloatTime();
  481. {
  482. int i;
  483. for (i = 0; i < nummiptex; i++)
  484. {
  485. lumpinfo_t* found;
  486. found = FindTexture(miptex + i);
  487. if (found)
  488. {
  489. miptex[i] = *found;
  490. }
  491. else
  492. {
  493. miptex[i].iTexFile = miptex[i].filepos = miptex[i].disksize = 0;
  494. }
  495. }
  496. }
  497. end = I_FloatTime();
  498. Verbose("FindTextures elapsed time = %ldms\n", (long)(end - start));
  499. start = I_FloatTime();
  500. {
  501. int i;
  502. texinfo_t* tx = g_texinfo;
  503. // Sort them FIRST by wadfile and THEN by name for most efficient loading in the engine.
  504. qsort((void*)miptex, (size_t) nummiptex, sizeof(miptex[0]), lump_sorter_by_wad_and_name);
  505. // Sleazy Hack 104 Pt 2 - After sorting the miptex array, reset the texinfos to point to the right miptexs
  506. for (i = 0; i < g_numtexinfo; i++, tx++)
  507. {
  508. char* miptex_name = texmap64_retrieve(tx->miptex);
  509. tx->miptex = FindMiptex(miptex_name);
  510. // Free up the originally strdup()'ed miptex_name
  511. free(miptex_name);
  512. }
  513. }
  514. end = I_FloatTime();
  515. Verbose("qsort(miptex) elapsed time = %ldms\n", (long)(end - start));
  516. start = I_FloatTime();
  517. {
  518. int i;
  519. // Now setup to get the miptex data (or just the headers if using -wadtextures) from the wadfile
  520. l = (dmiptexlump_t*)g_dtexdata;
  521. data = (byte*) & l->dataofs[nummiptex];
  522. l->nummiptex = nummiptex;
  523. for (i = 0; i < nummiptex; i++)
  524. {
  525. l->dataofs[i] = data - (byte*) l;
  526. len = LoadLump(miptex + i, data, &texsize);
  527. if (!len)
  528. {
  529. l->dataofs[i] = -1; // didn't find the texture
  530. }
  531. else
  532. {
  533. totaltexsize += texsize;
  534. hlassume(totaltexsize < g_max_map_miptex, assume_MAX_MAP_MIPTEX);
  535. }
  536. data += len;
  537. }
  538. g_texdatasize = data - g_dtexdata;
  539. }
  540. end = I_FloatTime();
  541. Log("Texture usage is at %1.2f MB (of %1.2f MB max)\n", (float)totaltexsize / (1024 * 1024),
  542. (float)g_max_map_miptex / (1024 * 1024));
  543. Verbose("LoadLump() elapsed time = %ldms\n", (long)(end - start));
  544. }
  545. //==========================================================================
  546. // =====================================================================================
  547. // TexinfoForBrushTexture
  548. // =====================================================================================
  549. int TexinfoForBrushTexture(const plane_t* const plane, brush_texture_t* bt, const vec3_t origin)
  550. {
  551. vec3_t vecs[2];
  552. int sv, tv;
  553. vec_t ang, sinv, cosv;
  554. vec_t ns, nt;
  555. texinfo_t tx;
  556. texinfo_t* tc;
  557. int i, j, k;
  558. memset(&tx, 0, sizeof(tx));
  559. if(!strncmp(bt->name,"BEVEL",5))
  560. {
  561. tx.flags |= TEX_BEVEL;
  562. safe_strncpy(bt->name,"NULL",5);
  563. }
  564. tx.miptex = FindMiptex(bt->name);
  565. // Note: FindMiptex() still needs to be called here to add it to the global miptex array
  566. // Very Sleazy Hack 104 - since the tx.miptex index will be bogus after we sort the miptex array later
  567. // Put the string name of the miptex in this "index" until after we are done sorting it in WriteMiptex().
  568. tx.miptex = texmap64_store(strdup(bt->name));
  569. // set the special flag
  570. if (bt->name[0] == '*'
  571. || !strncasecmp(bt->name, "sky", 3)
  572. // =====================================================================================
  573. //Cpt_Andrew - Env_Sky Check
  574. // =====================================================================================
  575. || !strncasecmp(bt->name, "env_sky", 5)
  576. // =====================================================================================
  577. || !strncasecmp(bt->name, "clip", 4)
  578. || !strncasecmp(bt->name, "origin", 6)
  579. #ifdef ZHLT_NULLTEX // AJM
  580. || !strncasecmp(bt->name, "null", 4)
  581. #endif
  582. || !strncasecmp(bt->name, "aaatrigger", 10)
  583. )
  584. {
  585. tx.flags |= TEX_SPECIAL;
  586. }
  587. if (bt->txcommand)
  588. {
  589. memcpy(tx.vecs, bt->vects.quark.vects, sizeof(tx.vecs));
  590. if (origin[0] || origin[1] || origin[2])
  591. {
  592. tx.vecs[0][3] += DotProduct(origin, tx.vecs[0]);
  593. tx.vecs[1][3] += DotProduct(origin, tx.vecs[1]);
  594. }
  595. }
  596. else
  597. {
  598. if (g_nMapFileVersion < 220)
  599. {
  600. TextureAxisFromPlane(plane, vecs[0], vecs[1]);
  601. }
  602. if (!bt->vects.valve.scale[0])
  603. {
  604. bt->vects.valve.scale[0] = 1;
  605. }
  606. if (!bt->vects.valve.scale[1])
  607. {
  608. bt->vects.valve.scale[1] = 1;
  609. }
  610. if (g_nMapFileVersion < 220)
  611. {
  612. // rotate axis
  613. if (bt->vects.valve.rotate == 0)
  614. {
  615. sinv = 0;
  616. cosv = 1;
  617. }
  618. else if (bt->vects.valve.rotate == 90)
  619. {
  620. sinv = 1;
  621. cosv = 0;
  622. }
  623. else if (bt->vects.valve.rotate == 180)
  624. {
  625. sinv = 0;
  626. cosv = -1;
  627. }
  628. else if (bt->vects.valve.rotate == 270)
  629. {
  630. sinv = -1;
  631. cosv = 0;
  632. }
  633. else
  634. {
  635. ang = bt->vects.valve.rotate / 180 * Q_PI;
  636. sinv = sin(ang);
  637. cosv = cos(ang);
  638. }
  639. if (vecs[0][0])
  640. {
  641. sv = 0;
  642. }
  643. else if (vecs[0][1])
  644. {
  645. sv = 1;
  646. }
  647. else
  648. {
  649. sv = 2;
  650. }
  651. if (vecs[1][0])
  652. {
  653. tv = 0;
  654. }
  655. else if (vecs[1][1])
  656. {
  657. tv = 1;
  658. }
  659. else
  660. {
  661. tv = 2;
  662. }
  663. for (i = 0; i < 2; i++)
  664. {
  665. ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
  666. nt = sinv * vecs[i][sv] + cosv * vecs[i][tv];
  667. vecs[i][sv] = ns;
  668. vecs[i][tv] = nt;
  669. }
  670. for (i = 0; i < 2; i++)
  671. {
  672. for (j = 0; j < 3; j++)
  673. {
  674. tx.vecs[i][j] = vecs[i][j] / bt->vects.valve.scale[i];
  675. }
  676. }
  677. }
  678. else
  679. {
  680. vec_t scale;
  681. scale = 1 / bt->vects.valve.scale[0];
  682. VectorScale(bt->vects.valve.UAxis, scale, tx.vecs[0]);
  683. scale = 1 / bt->vects.valve.scale[1];
  684. VectorScale(bt->vects.valve.VAxis, scale, tx.vecs[1]);
  685. }
  686. tx.vecs[0][3] = bt->vects.valve.shift[0] + DotProduct(origin, tx.vecs[0]);
  687. tx.vecs[1][3] = bt->vects.valve.shift[1] + DotProduct(origin, tx.vecs[1]);
  688. }
  689. //
  690. // find the g_texinfo
  691. //
  692. ThreadLock();
  693. tc = g_texinfo;
  694. for (i = 0; i < g_numtexinfo; i++, tc++)
  695. {
  696. // Sleazy hack 104, Pt 3 - Use strcmp on names to avoid dups
  697. if (strcmp(texmap64_retrieve((tc->miptex)), texmap64_retrieve((tx.miptex))) != 0)
  698. {
  699. continue;
  700. }
  701. if (tc->flags != tx.flags)
  702. {
  703. continue;
  704. }
  705. for (j = 0; j < 2; j++)
  706. {
  707. for (k = 0; k < 4; k++)
  708. {
  709. if (tc->vecs[j][k] != tx.vecs[j][k])
  710. {
  711. goto skip;
  712. }
  713. }
  714. }
  715. ThreadUnlock();
  716. return i;
  717. skip:;
  718. }
  719. hlassume(g_numtexinfo < MAX_MAP_TEXINFO, assume_MAX_MAP_TEXINFO);
  720. *tc = tx;
  721. g_numtexinfo++;
  722. ThreadUnlock();
  723. return i;
  724. }