terrtxm2.cpp 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029
  1. //---------------------------------------------------------------------------
  2. //
  3. // TerrTxm2.h -- File contains class definitions for the Terrain Textures
  4. //
  5. // MechCommander 2 -- Microsoft
  6. //
  7. //---------------------------------------------------------------------------//
  8. // Copyright (C) Microsoft Corporation. All rights reserved. //
  9. //===========================================================================//
  10. //---------------------------------------------------------------------------
  11. // Include Files
  12. #include <windows.h> /*only for declaration of DeleteFile() */
  13. #ifndef TERRTXM2_H
  14. #include "terrtxm2.h"
  15. #endif
  16. #ifndef PATHS_H
  17. #include "paths.h"
  18. #endif
  19. #ifndef TGAINFO_H
  20. #include "tgainfo.h"
  21. #endif
  22. #ifndef CIDENT_H
  23. #include "cident.h"
  24. #endif
  25. #ifndef FILE_H
  26. #include "file.h"
  27. #endif
  28. #ifndef VERTEX_H
  29. #include "vertex.h"
  30. #endif
  31. #ifndef TERRAIN_H
  32. #include "terrain.h"
  33. #endif
  34. #ifndef CAMERA_H
  35. #include "camera.h"
  36. #endif
  37. #include "resizeimage.h"
  38. #include <io.h>
  39. #include <sys\stat.h>
  40. #define COLOR_MAP_HEAP_SIZE 20480000
  41. #define COLOR_TXM_HEAP_SIZE 4096
  42. #define COLOR_MAP_TEXTURE_SIZE 256
  43. #define COLOR_MAP_RES float(COLOR_MAP_TEXTURE_SIZE)
  44. bool forceShadowBurnIn = false;
  45. void* DecodeJPG( const char* FileName, BYTE* Data, DWORD DataSize, DWORD* TextureWidth, DWORD* TextureHeight, bool TextureLoad, void *pDestSurf );
  46. DWORD TerrainColorMap::terrainTypeIDs[ TOTAL_COLORMAP_TYPES ] =
  47. {
  48. 20000,
  49. 20001,
  50. 20002,
  51. 20003,
  52. 20004
  53. };
  54. #define MBOK 1
  55. //---------------------------------------------------------------------------
  56. // Class TerrainColorMap
  57. void TerrainColorMap::init (void)
  58. {
  59. ColorMap = NULL;
  60. colorMapHeap = NULL;
  61. colorMapRAMHeap = NULL;
  62. numTextures = 0;
  63. textures = NULL;
  64. txmRAM = NULL;
  65. numTexturesAcross = fractionPerTexture = 0.0f;
  66. colorMapStarted = false;
  67. detailTextureRAM = NULL;
  68. detailTextureNodeIndex = 0xffffffff;
  69. detailTextureTilingFactor = 30.0f;
  70. waterTextureRAM = NULL;
  71. waterTextureNodeIndex = 0xffffffff;
  72. waterTextureTilingFactor = 48.0f;
  73. numWaterDetailFrames = 0;
  74. int i;
  75. for (i = 0; i < MAX_WATER_DETAIL_TEXTURES; i++)
  76. {
  77. waterDetailNodeIndex[i] = 0xffffffff;
  78. }
  79. waterDetailFrameRate = 8;
  80. waterDetailTilingFactor = 45.0f;
  81. hGauss = 5.0f;
  82. roughDistance = -1.0f;
  83. }
  84. void TerrainColorMap::destroy (void)
  85. {
  86. if (textures)
  87. {
  88. colorMapHeap->Free(textures);
  89. textures = NULL;
  90. }
  91. if (txmRAM)
  92. {
  93. for (unsigned long i=0;i<numTextures;i++)
  94. {
  95. colorMapRAMHeap->Free(txmRAM[i].ourRAM);
  96. txmRAM[i].ourRAM = NULL;
  97. }
  98. colorMapRAMHeap->Free(txmRAM);
  99. txmRAM = NULL;
  100. }
  101. if (ColorMap)
  102. {
  103. colorMapRAMHeap->Free(ColorMap);
  104. ColorMap = NULL;
  105. }
  106. if (colorMapHeap)
  107. {
  108. delete colorMapHeap;
  109. colorMapHeap = NULL;
  110. }
  111. if (colorMapRAMHeap)
  112. {
  113. delete colorMapRAMHeap;
  114. colorMapRAMHeap = NULL;
  115. }
  116. numTextures = 0;
  117. }
  118. //---------------------------------------------------------------------------
  119. void TerrainColorMap::getColorMapData (MemoryPtr ourRAM, long index, long width)
  120. {
  121. long numWide = width / COLOR_MAP_TEXTURE_SIZE;
  122. long startCol = ((index % numWide) * COLOR_MAP_TEXTURE_SIZE);
  123. if (startCol > 0)
  124. startCol-= (index % numWide);
  125. long startRow = ((index / numWide) * width * COLOR_MAP_TEXTURE_SIZE);
  126. if (startRow > 0)
  127. startRow -= (index / numWide) * width;
  128. MemoryPtr ourColor = ColorMap + (startCol + startRow) * sizeof(DWORD);
  129. for (long i=0;i<COLOR_MAP_TEXTURE_SIZE;i++)
  130. {
  131. memcpy(ourRAM,ourColor,COLOR_MAP_TEXTURE_SIZE * sizeof(DWORD));
  132. ourRAM += COLOR_MAP_TEXTURE_SIZE * sizeof(DWORD);
  133. ourColor += width * sizeof(DWORD);
  134. }
  135. }
  136. //---------------------------------------------------------------------------
  137. inline void fractalPass (float *heightMap, long edgeSize, long THRESHOLD, long NOISE)
  138. {
  139. //Add a bunch o Gaussian noise to the new hi-res height map to break up the lines.
  140. // This works as follows:
  141. // If there is a Height Difference between the points, Add noise based on difference.
  142. // If there is NO height difference, DO NOT ADD NOISE. Let smooth be smooth!
  143. float *noiseMap = (float *) malloc(sizeof(float) * edgeSize * edgeSize);
  144. for (long y=THRESHOLD;y<(edgeSize-THRESHOLD);y++)
  145. {
  146. for (long x=THRESHOLD;x<(edgeSize-THRESHOLD);x++)
  147. {
  148. if (RandomNumber(THRESHOLD) == 0)
  149. {
  150. float noise = float(NOISE * 0.5f) - RandomNumber(NOISE);
  151. noiseMap[x + (y * edgeSize)] = noise;
  152. }
  153. else
  154. {
  155. noiseMap[x + (y * edgeSize)] = 0.0f;
  156. }
  157. }
  158. }
  159. for (long i=0;i<edgeSize * edgeSize;i++)
  160. {
  161. heightMap[i] += noiseMap[i];
  162. }
  163. free(noiseMap);
  164. }
  165. //---------------------------------------------------------------------------
  166. void rescaleMap (float *dst, float *src, long dstSize, long srcSize)
  167. {
  168. Image source, dest;
  169. source.xSize = source.ySize = srcSize;
  170. source.data = src;
  171. dest.xSize = dest.ySize = dstSize;
  172. dest.data = dst;
  173. // zoom(&dest, &source, mitchellFilter, MitchellSupport);
  174. zoom(&dest, &source, triangleFilter, triangleSupport);
  175. }
  176. //---------------------------------------------------------------------------
  177. void TerrainColorMap::refractalizeBaseMesh (char *fileName, long Threshold, long Noise)
  178. {
  179. //Find max and min vertex elevations for scaling below.
  180. float maxVertex = land->getTerrainElevation(0,0);
  181. float minVertex = maxVertex;
  182. for (long y=0;y<Terrain::realVerticesMapSide;y++)
  183. {
  184. for (long x=0;x<Terrain::realVerticesMapSide;x++)
  185. {
  186. float currentElevation = land->getTerrainElevation(y,x);
  187. if (currentElevation < minVertex)
  188. minVertex = currentElevation;
  189. if (currentElevation > maxVertex)
  190. maxVertex = currentElevation;
  191. }
  192. }
  193. float scalar = 0.0f;
  194. //Check if Map has no elevation!!
  195. if (maxVertex != minVertex)
  196. {
  197. scalar = 255.0f / (maxVertex - minVertex);
  198. }
  199. //Create an image which is x by x for the existing terrain.
  200. // Scale it into the range of 0 to 255.
  201. // these can be floats!!!!!!!
  202. float *srcData = (float *)malloc(sizeof(float) * Terrain::realVerticesMapSide * Terrain::realVerticesMapSide);
  203. memset(srcData,0,sizeof(float) * Terrain::realVerticesMapSide * Terrain::realVerticesMapSide);
  204. for (y=0;y<Terrain::realVerticesMapSide;y++)
  205. {
  206. for (long x=0;x<Terrain::realVerticesMapSide;x++)
  207. {
  208. float currentElevation = land->getTerrainElevation(y,x);
  209. float scaledValue = (currentElevation - minVertex) * scalar;
  210. srcData[x + (y * Terrain::realVerticesMapSide)] = scaledValue;
  211. }
  212. }
  213. //Spit out original Targa as well.
  214. MemoryPtr sourceData = (MemoryPtr)malloc(Terrain::realVerticesMapSide * Terrain::realVerticesMapSide);
  215. memset(sourceData,0,Terrain::realVerticesMapSide * Terrain::realVerticesMapSide);
  216. float *tmpEdge = srcData;
  217. MemoryPtr tmpOutput = sourceData;
  218. for (long i=0;i<Terrain::realVerticesMapSide * Terrain::realVerticesMapSide;i++)
  219. {
  220. *tmpOutput = (BYTE)CLAMP(*tmpEdge,BLACK_PIXEL,WHITE_PIXEL);
  221. tmpOutput++;
  222. tmpEdge++;
  223. }
  224. FullPathFileName OEMheightName;
  225. OEMheightName.init(terrainPath,fileName,".tga");
  226. SetFileAttributes(OEMheightName,FILE_ATTRIBUTE_NORMAL);
  227. TGAFileHeader tgaOutput;
  228. tgaOutput.cm_entry_size = 0;
  229. tgaOutput.cm_first_entry = 0;
  230. tgaOutput.cm_length = 0;
  231. tgaOutput.color_map = 0;
  232. tgaOutput.height = Terrain::realVerticesMapSide;
  233. tgaOutput.image_descriptor = 32; //Right side up!!
  234. tgaOutput.image_id_len = 0;
  235. tgaOutput.image_type = UNC_GRAY;
  236. tgaOutput.pixel_depth = 8;
  237. tgaOutput.width = Terrain::realVerticesMapSide;
  238. tgaOutput.x_origin = 0;
  239. tgaOutput.y_origin = 0;
  240. File OEMtgaFile;
  241. long result = OEMtgaFile.create(OEMheightName);
  242. if (result != NO_ERR)
  243. STOP(("Couldnt create height map %s on refractalize. Error: %d",OEMheightName,result));
  244. OEMtgaFile.write((MemoryPtr)&tgaOutput,sizeof(TGAFileHeader));
  245. OEMtgaFile.write(sourceData,Terrain::realVerticesMapSide * Terrain::realVerticesMapSide);
  246. OEMtgaFile.close();
  247. long edgeSize = (numTexturesAcross * COLOR_MAP_RES);
  248. float *dstData = (float *)malloc(sizeof(float) * edgeSize * edgeSize);
  249. memset(dstData,0,sizeof(float) * edgeSize * edgeSize);
  250. rescaleMap(dstData,srcData,edgeSize,Terrain::realVerticesMapSide);
  251. //Now, apply refractalization to dstData.
  252. if (Noise)
  253. fractalPass(dstData,edgeSize,Threshold,Noise);
  254. //Save dstData as the height map.
  255. char newName[1024];
  256. sprintf(newName,"%s.height",fileName);
  257. FullPathFileName heightName;
  258. heightName.init(terrainPath,newName,".tga");
  259. SetFileAttributes(heightName,FILE_ATTRIBUTE_NORMAL);
  260. MemoryPtr outputData = (MemoryPtr)malloc(edgeSize * edgeSize);
  261. memset(outputData,0,sizeof(BYTE) * edgeSize * edgeSize);
  262. tmpEdge = dstData;
  263. tmpOutput = outputData;
  264. for (i=0;i<edgeSize*edgeSize;i++)
  265. {
  266. *tmpOutput = (BYTE)CLAMP(*tmpEdge,BLACK_PIXEL,WHITE_PIXEL);
  267. tmpOutput++;
  268. tmpEdge++;
  269. }
  270. tgaOutput.cm_entry_size = 0;
  271. tgaOutput.cm_first_entry = 0;
  272. tgaOutput.cm_length = 0;
  273. tgaOutput.color_map = 0;
  274. tgaOutput.height = edgeSize;
  275. tgaOutput.image_descriptor = 32; //Right side up!!
  276. tgaOutput.image_id_len = 0;
  277. tgaOutput.image_type = UNC_TRUE;
  278. tgaOutput.pixel_depth = 24;
  279. tgaOutput.width = edgeSize;
  280. tgaOutput.x_origin = 0;
  281. tgaOutput.y_origin = 0;
  282. //flipTopToBottom(outputData,8,edgeSize,edgeSize);
  283. File tgaFile;
  284. result = tgaFile.create(heightName);
  285. if (result != NO_ERR)
  286. STOP(("Couldnt create height map %s on refractalize. Error: %d",heightName,result));
  287. tgaFile.write((MemoryPtr)&tgaOutput,sizeof(TGAFileHeader));
  288. MemoryPtr outputByte = outputData;
  289. MemoryPtr output24Bit = (MemoryPtr)malloc(edgeSize * edgeSize * 3);
  290. MemoryPtr output24Temp = output24Bit;
  291. for (i=0;i<edgeSize*edgeSize;i++)
  292. {
  293. *output24Temp = *outputByte;
  294. output24Temp++;
  295. *output24Temp = *outputByte;
  296. output24Temp++;
  297. *output24Temp = *outputByte;
  298. output24Temp++;
  299. outputByte++;
  300. }
  301. tgaFile.write(output24Bit,edgeSize * edgeSize * 3);
  302. tgaFile.close();
  303. free(output24Bit);
  304. //ReBurn the shadows.
  305. recalcLight(fileName);
  306. //Destroy RAM allocated. No Leaking!!
  307. free(dstData);
  308. free(srcData);
  309. free(sourceData);
  310. free(outputData);
  311. }
  312. float ContrastEnhance = 1.5f;
  313. float ShadowEnhance = 2.0f;
  314. //---------------------------------------------------------------------------
  315. void TerrainColorMap::burnInShadows (bool doBumpPass, char *fileName)
  316. {
  317. //-----------------------------------------------------------------
  318. // for each pixel in the colormap, figure out where light is and
  319. // darken/lighten color based on light angle and shadows
  320. //first create a height map which is pixel for pixel identical to
  321. // the color map.
  322. long pixelWidth = numTexturesAcross * COLOR_MAP_TEXTURE_SIZE;
  323. float *heightMap = (float *)malloc(sizeof(float) * pixelWidth * pixelWidth);
  324. gosASSERT(heightMap != NULL);
  325. memset(heightMap,0,sizeof(float) * pixelWidth * pixelWidth);
  326. float *shadowMap = (float *)malloc(sizeof(float) * pixelWidth * pixelWidth);
  327. gosASSERT(shadowMap != NULL);
  328. memset(shadowMap,0,sizeof(float) * pixelWidth * pixelWidth);
  329. float worldUnitsPerPixel = (Terrain::worldUnitsMapSide / pixelWidth);
  330. float startY = Terrain::mapTopLeft3d.y;
  331. float *hMap = heightMap;
  332. float *sMap = shadowMap;
  333. if (Terrain::userMin == Terrain::userMax)
  334. {
  335. //Spread 'em out so the lighting actually works!!
  336. Terrain::userMin = 0;
  337. Terrain::userMax = 500;
  338. }
  339. //First, check if there is a height Map on disk. If so, use it, not a fractally generated one.
  340. bool heightMapExists = false;
  341. float highPoint = 0.0f;
  342. if (fileName)
  343. {
  344. char newName[1024];
  345. sprintf(newName,"%s.height",fileName);
  346. FullPathFileName heightName;
  347. heightName.init(terrainPath,newName,".tga");
  348. if (fileExists(heightName))
  349. {
  350. heightMapExists = true;
  351. File heightMapFile;
  352. long result = heightMapFile.open(heightName);
  353. if (result != NO_ERR)
  354. STOP(("Unable to find Hi-Res Height Data"));
  355. MemoryPtr tgaFileImage = (MemoryPtr)malloc(heightMapFile.fileSize());
  356. gosASSERT(tgaFileImage != NULL);
  357. heightMapFile.read(tgaFileImage,heightMapFile.fileSize());
  358. TGAFileHeader heightMapInfo;
  359. memcpy(&heightMapInfo,tgaFileImage,sizeof(TGAFileHeader));
  360. if (heightMapInfo.width != pixelWidth)
  361. {
  362. PAUSE(("Hi-Res Height Map wrong size %d. Should be %d. No shadows will be burnt. Press Continue",heightMapInfo.width,pixelWidth));
  363. return;
  364. }
  365. if (heightMapInfo.image_type == UNC_TRUE)
  366. {
  367. MemoryPtr loadBuffer = tgaFileImage + sizeof(TGAFileHeader);
  368. if (heightMapInfo.width != heightMapInfo.height)
  369. STOP(("Height Map is not a perfect Square"));
  370. //-----------------------------------------------------------------
  371. // Check if 24 or 32 bit. If 24, do the necessary stuff to it.
  372. // FIrst find MAX and MIN values for height field.
  373. BYTE mapMin = 255;
  374. BYTE mapMax = 0;
  375. if (heightMapInfo.pixel_depth == 24)
  376. {
  377. //24-Bit color means we must skip to every third color data.
  378. MemoryPtr lMap = loadBuffer;
  379. for (long i = 0;i<(heightMapInfo.width * heightMapInfo.width);i++)
  380. {
  381. BYTE val = *lMap;
  382. lMap += 3;
  383. if (val > mapMax)
  384. mapMax = val;
  385. if (val < mapMin)
  386. mapMin = val;
  387. }
  388. }
  389. else
  390. {
  391. //32-bit color means skip three instead of two bytes.
  392. MemoryPtr lMap = loadBuffer;
  393. for (long i = 0;i<(heightMapInfo.width * heightMapInfo.width);i++)
  394. {
  395. BYTE val = *lMap;
  396. lMap += 4;
  397. if (val > mapMax)
  398. mapMax = val;
  399. if (val < mapMin)
  400. mapMin = val;
  401. }
  402. }
  403. //Now create Height Map in Floating Point Space.
  404. if (heightMapInfo.pixel_depth == 24)
  405. {
  406. //24-Bit color means we must skip to every third color data.
  407. float * hMap = heightMap;
  408. MemoryPtr lMap = loadBuffer;
  409. for (long i = 0;i<(heightMapInfo.width * heightMapInfo.width);i++)
  410. {
  411. float val = (float)(*lMap);
  412. lMap += 3;
  413. float h = Terrain::userMin;
  414. if (0.0 != mapMax)
  415. {
  416. h += (val - mapMin)/mapMax * ( Terrain::userMax - Terrain::userMin );
  417. *hMap = h * ShadowEnhance;
  418. if (highPoint < *hMap)
  419. highPoint = *hMap;
  420. hMap++;
  421. }
  422. }
  423. }
  424. else
  425. {
  426. //32-bit color means skip three instead of two bytes.
  427. float * hMap = heightMap;
  428. MemoryPtr lMap = loadBuffer;
  429. for (long i = 0;i<(heightMapInfo.width * heightMapInfo.width);i++)
  430. {
  431. float val = (float)(*lMap);
  432. lMap += 4;
  433. float h = Terrain::userMin;
  434. if (0.0 != mapMax)
  435. {
  436. h += (val - mapMin)/mapMax * ( Terrain::userMax - Terrain::userMin );
  437. *hMap = h * ShadowEnhance;
  438. if (highPoint < *hMap)
  439. highPoint = *hMap;
  440. hMap++;
  441. }
  442. }
  443. }
  444. free(tgaFileImage);
  445. tgaFileImage = NULL;
  446. //------------------------------------------------------------------------
  447. // Must check image_descriptor to see if we need to un upside down image.
  448. //bool left = (colorMapInfo.iimage_descriptor & 16) != 0;
  449. bool top = (heightMapInfo.image_descriptor & 32) != 0;
  450. if (!top)
  451. {
  452. flipTopToBottom((MemoryPtr)heightMap,32,heightMapInfo.width,heightMapInfo.height);
  453. }
  454. }
  455. }
  456. }
  457. else
  458. {
  459. long skipLong = 1;
  460. for (long y=0;y<pixelWidth;y++)
  461. {
  462. float startX = Terrain::mapTopLeft3d.x;
  463. for (long x=0;x<pixelWidth;x++)
  464. {
  465. Stuff::Vector3D pos;
  466. pos.x = startX;
  467. pos.y = startY;
  468. pos.z = 0.0f;
  469. if (!(x%skipLong) && !(y%skipLong))
  470. *hMap = land->getTerrainElevation(pos);
  471. else
  472. *hMap = 0.0f;
  473. *sMap = 0.0f;
  474. if (highPoint < *hMap)
  475. highPoint = *hMap;
  476. hMap++;
  477. sMap++;
  478. startX += worldUnitsPerPixel;
  479. }
  480. startY -= worldUnitsPerPixel;
  481. }
  482. }
  483. //----------------------------------------------------------
  484. // We now have a MUCH more accurate height map then we did.
  485. // Do normal calculations first.
  486. Stuff::Vector3D lightDir;
  487. lightDir.x = lightDir.y = 0.0f;
  488. lightDir.z = 1.0f;
  489. if (eye)
  490. lightDir = eye->lightDirection;
  491. Stuff::Vector3D shadowDir(lightDir);
  492. shadowDir *= worldUnitsPerPixel; //Distance which is the per pixel distance for checking shadows
  493. //---------------------
  494. //Shadow Map Pass Here
  495. highPoint *= ShadowEnhance;
  496. float *thisHeight = heightMap;
  497. float *thisShadow = shadowMap;
  498. for (long y=0;y<pixelWidth;y++)
  499. {
  500. for (long x=0;x<pixelWidth;x++)
  501. {
  502. //---------------------------------------------
  503. // No problem
  504. // Generate at will!
  505. float v0,v1,v2,v3,v4,v5,v6,v7,v8;
  506. v0 = *thisHeight;
  507. if (x && y)
  508. v1 = *(thisHeight - pixelWidth - 1);
  509. else
  510. v1 = v0;
  511. if (y)
  512. v2 = *(thisHeight - pixelWidth );
  513. else
  514. v2 = v0;
  515. if (y && (x < (pixelWidth - 1)))
  516. v3 = *(thisHeight - pixelWidth + 1);
  517. else
  518. v3 = v0;
  519. if (x < (pixelWidth - 1))
  520. v4 = *(thisHeight + 1);
  521. else
  522. v4 = v0;
  523. if ((x < (pixelWidth - 1)) && (y < (pixelWidth - 1)))
  524. v5 = *(thisHeight + pixelWidth + 1);
  525. else
  526. v5 = v0;
  527. if ((y < (pixelWidth - 1)))
  528. v6 = *(thisHeight + pixelWidth );
  529. else
  530. v6 = v0;
  531. if (x && (y < (pixelWidth - 1)))
  532. v7 = *(thisHeight + pixelWidth - 1);
  533. else
  534. v7 = v0;
  535. if (x)
  536. v8 = *(thisHeight - 1);
  537. else
  538. v8 = v0;
  539. if (Terrain::recalcShadows || forceShadowBurnIn)
  540. {
  541. //-----------------------------------------------------
  542. // Try and project shadow lines.
  543. Stuff::Vector3D vertexPos;
  544. vertexPos.x = ((float(x) * worldUnitsPerPixel) + Terrain::mapTopLeft3d.x);
  545. vertexPos.y = (Terrain::mapTopLeft3d.y - (float(y) * worldUnitsPerPixel));
  546. vertexPos.z = *thisHeight * ShadowEnhance;
  547. if ((shadowDir.x != 0.0f) || (shadowDir.y != 0.0f))
  548. {
  549. vertexPos.Add(vertexPos,shadowDir);
  550. if (!heightMapExists)
  551. {
  552. while (eye && (vertexPos.z < highPoint) && Terrain::IsValidTerrainPosition(vertexPos))
  553. {
  554. float elev = land->getTerrainElevation(vertexPos) * ShadowEnhance;
  555. if (elev >= vertexPos.z)
  556. {
  557. *thisShadow = -1.0f; //Mark as shadowed
  558. break; //Stop Looking!!
  559. }
  560. vertexPos.Add(vertexPos,shadowDir);
  561. }
  562. }
  563. else
  564. {
  565. float tx = x;
  566. float ty = y;
  567. while (eye && (vertexPos.z < highPoint) && Terrain::IsValidTerrainPosition(vertexPos))
  568. {
  569. //Figure out index into array from vertexPos and use REAL height data for shadows.
  570. long tileX = tx;
  571. long tileY = ty;
  572. float elev = heightMap[tileX + (tileY * pixelWidth)];
  573. if (elev > vertexPos.z)
  574. {
  575. *thisShadow = -1.0f; //Mark as shadowed
  576. break; //Stop Looking!!
  577. }
  578. tx += lightDir.x;
  579. ty -= lightDir.y;
  580. vertexPos.Add(vertexPos,shadowDir);
  581. }
  582. }
  583. }
  584. }
  585. if (*thisShadow != -1.0f)
  586. {
  587. Stuff::Vector3D normals[8];
  588. Stuff::Vector3D triVect[2];
  589. //-------------------------------------
  590. // Tri 021
  591. triVect[0].x = 0.0f;
  592. triVect[0].y = worldUnitsPerPixel;
  593. triVect[0].z = (v2 - v0) * ContrastEnhance;
  594. triVect[1].x = -worldUnitsPerPixel;
  595. triVect[1].y = worldUnitsPerPixel;
  596. triVect[1].z = (v1 - v0) * ContrastEnhance;
  597. normals[0].Cross(triVect[0],triVect[1]);
  598. gosASSERT(normals[0].z > 0.0);
  599. normals[0].Normalize(normals[0]);
  600. //-------------------------------------
  601. // Tri 032
  602. triVect[0].x = worldUnitsPerPixel;
  603. triVect[0].y = worldUnitsPerPixel;
  604. triVect[0].z = (v3 - v0) * ContrastEnhance;
  605. triVect[1].x = 0.0f;
  606. triVect[1].y = worldUnitsPerPixel;
  607. triVect[1].z = (v2 - v0) * ContrastEnhance;
  608. normals[1].Cross(triVect[0],triVect[1]);
  609. gosASSERT(normals[1].z > 0.0);
  610. normals[1].Normalize(normals[1]);
  611. //-------------------------------------
  612. // Tri 043
  613. triVect[0].x = worldUnitsPerPixel;
  614. triVect[0].y = 0.0f;
  615. triVect[0].z = (v4 - v0) * ContrastEnhance;
  616. triVect[1].x = worldUnitsPerPixel;
  617. triVect[1].y = worldUnitsPerPixel;
  618. triVect[1].z = (v3 - v0) * ContrastEnhance;
  619. normals[2].Cross(triVect[0],triVect[1]);
  620. gosASSERT(normals[2].z > 0.0);
  621. normals[2].Normalize(normals[2]);
  622. //-------------------------------------
  623. // Tri 054
  624. triVect[0].x = worldUnitsPerPixel;
  625. triVect[0].y = -worldUnitsPerPixel;
  626. triVect[0].z = (v5 - v0) * ContrastEnhance;
  627. triVect[1].x = worldUnitsPerPixel;
  628. triVect[1].y = 0.0f;
  629. triVect[1].z = (v4 - v0) * ContrastEnhance;
  630. normals[3].Cross(triVect[0],triVect[1]);
  631. gosASSERT(normals[3].z > 0.0);
  632. normals[3].Normalize(normals[3]);
  633. //-------------------------------------
  634. // Tri 065
  635. triVect[0].x = 0;
  636. triVect[0].y = -worldUnitsPerPixel;
  637. triVect[0].z = (v6 - v0) * ContrastEnhance;
  638. triVect[1].x = worldUnitsPerPixel;
  639. triVect[1].y = -worldUnitsPerPixel;
  640. triVect[1].z = (v5 - v0) * ContrastEnhance;
  641. normals[4].Cross(triVect[0],triVect[1]);
  642. gosASSERT(normals[4].z > 0.0);
  643. normals[4].Normalize(normals[4]);
  644. //-------------------------------------
  645. // Tri 076
  646. triVect[0].x = -worldUnitsPerPixel;
  647. triVect[0].y = -worldUnitsPerPixel;
  648. triVect[0].z = (v7 - v0) * ContrastEnhance;
  649. triVect[1].x = 0.0;
  650. triVect[1].y = -worldUnitsPerPixel;
  651. triVect[1].z = (v6 - v0) * ContrastEnhance;
  652. normals[5].Cross(triVect[0],triVect[1]);
  653. gosASSERT(normals[5].z > 0.0);
  654. normals[5].Normalize(normals[5]);
  655. //-------------------------------------
  656. // Tri 087
  657. triVect[0].x = -worldUnitsPerPixel;
  658. triVect[0].y = 0.0;
  659. triVect[0].z = (v8 - v0) * ContrastEnhance;
  660. triVect[1].x = -worldUnitsPerPixel;
  661. triVect[1].y = -worldUnitsPerPixel;
  662. triVect[1].z = (v7 - v0) * ContrastEnhance;
  663. normals[6].Cross(triVect[0],triVect[1]);
  664. gosASSERT(normals[6].z > 0.0);
  665. normals[6].Normalize(normals[6]);
  666. //-------------------------------------
  667. // Tri 018
  668. triVect[0].x = -worldUnitsPerPixel;
  669. triVect[0].y = worldUnitsPerPixel;
  670. triVect[0].z = (v1 - v0) * ContrastEnhance;
  671. triVect[1].x = -worldUnitsPerPixel;
  672. triVect[1].y = 0.0;
  673. triVect[1].z = (v8 - v0) * ContrastEnhance;
  674. normals[7].Cross(triVect[0],triVect[1]);
  675. gosASSERT(normals[7].z > 0.0);
  676. normals[7].Normalize(normals[7]);
  677. Stuff::Vector3D vertexNormal;
  678. vertexNormal.x = normals[0].x + normals[1].x + normals[2].x + normals[3].x + normals[4].x + normals[5].x + normals[6].x + normals[7].x;
  679. vertexNormal.y = normals[0].y + normals[1].y + normals[2].y + normals[3].y + normals[4].y + normals[5].y + normals[6].y + normals[7].y;
  680. vertexNormal.z = normals[0].z + normals[1].z + normals[2].z + normals[3].z + normals[4].z + normals[5].z + normals[6].z + normals[7].z;
  681. vertexNormal.x /= 8.0;
  682. vertexNormal.y /= 8.0;
  683. vertexNormal.z /= 8.0;
  684. gosASSERT(vertexNormal.z > 0.0);
  685. *thisShadow = vertexNormal * lightDir;
  686. }
  687. thisHeight++;
  688. thisShadow++;
  689. }
  690. }
  691. //Smooth out the shadow map to make shadows better.
  692. for (long i=pixelWidth;i<((pixelWidth * pixelWidth)-pixelWidth);i++)
  693. {
  694. if (shadowMap[i] == -1.0f)
  695. {
  696. float v1,v2,v3,v4,v5,v6,v7,v8;
  697. //All of the pixels around this one should be no more then 0.3f
  698. v1 = shadowMap[i - pixelWidth - 1];
  699. v2 = shadowMap[i - pixelWidth ];
  700. v3 = shadowMap[i - pixelWidth + 1];
  701. v4 = shadowMap[i + 1];
  702. v5 = shadowMap[i + pixelWidth + 1];
  703. v6 = shadowMap[i + pixelWidth ];
  704. v7 = shadowMap[i + pixelWidth - 1];
  705. v8 = shadowMap[i - 1];
  706. if (v1 > 0.2f)
  707. shadowMap[i - pixelWidth - 1] = 0.2f;
  708. if (v2 > 0.2f)
  709. shadowMap[i - pixelWidth ] = 0.2f;
  710. if (v3 > 0.2f)
  711. shadowMap[i - pixelWidth + 1] = 0.2f;
  712. if (v4 > 0.2f)
  713. shadowMap[i + 1] = 0.2f;
  714. if (v5 > 0.2f)
  715. shadowMap[i + pixelWidth + 1] = 0.2f;
  716. if (v6 > 0.2f)
  717. shadowMap[i + pixelWidth ] = 0.2f;
  718. if (v7 > 0.2f)
  719. shadowMap[i + pixelWidth - 1] = 0.2f;
  720. if (v8 > 0.2f)
  721. shadowMap[i - 1] = 0.2f;
  722. }
  723. }
  724. // Shadow map is now done being calculated.
  725. // Apply the shadows to the magical terrain.
  726. DWORD *cMap = (DWORD *)ColorMap;
  727. for (i=0;i<(pixelWidth * pixelWidth);i++)
  728. {
  729. if (shadowMap[i] != 0.0f)
  730. {
  731. float lightFactor = 0.0f;
  732. if (shadowMap[i] != -1.0f) //Otherwise, its a shadow and light is 0!!
  733. {
  734. lightFactor = shadowMap[i];
  735. }
  736. else
  737. {
  738. lightFactor = 0.0f;
  739. }
  740. DWORD lightr, lightg, lightb;
  741. lightr = eye->getLightRed(lightFactor);
  742. lightg = eye->getLightGreen(lightFactor);
  743. lightb = eye->getLightBlue(lightFactor);
  744. DWORD currentColor = *cMap;
  745. float currentBlue = currentColor & 0xff;
  746. float currentGreen = (currentColor >> 8) & 0xff;
  747. float currentRed = (currentColor >> 16) & 0xff;
  748. currentRed *= ((float)lightr / 255.0f);
  749. currentBlue *= ((float)lightb / 255.0f);
  750. currentGreen *= ((float)lightg / 255.0f);
  751. lightr = currentRed;
  752. lightg = currentGreen;
  753. lightb = currentBlue;
  754. *cMap = (0xff << 24) + (lightr << 16) + (lightg << 8) + (lightb);
  755. }
  756. cMap++;
  757. }
  758. //All Done. Get rid of the height and Shadow maps
  759. free(heightMap);
  760. free(shadowMap);
  761. }
  762. //---------------------------------------------------------------------------
  763. void saveTGAFile(MemoryPtr ColorMap, char * fileName, long pixelWidth)
  764. {
  765. TGAFileHeader colorMapInfo;
  766. colorMapInfo.image_id_len = 0;
  767. colorMapInfo.color_map = 0;
  768. colorMapInfo.image_type = UNC_TRUE;
  769. colorMapInfo.cm_first_entry= 0;
  770. colorMapInfo.cm_length = 0;
  771. colorMapInfo.cm_entry_size = 0;
  772. colorMapInfo.x_origin = 0;
  773. colorMapInfo.y_origin = 0;
  774. colorMapInfo.width = pixelWidth;
  775. colorMapInfo.height = pixelWidth;
  776. colorMapInfo.pixel_depth = 32.0;
  777. colorMapInfo.image_descriptor = 32; //DO NOT FLIP!
  778. char newName[1024];
  779. sprintf(newName,"%s.burnin",fileName);
  780. FullPathFileName outputName;
  781. outputName.init(texturePath,newName,".tga");
  782. _chmod(outputName,_S_IREAD | _S_IWRITE);
  783. File outputFile;
  784. outputFile.create(outputName);
  785. outputFile.write((MemoryPtr)(&colorMapInfo),sizeof(TGAFileHeader));
  786. outputFile.write(ColorMap,pixelWidth*pixelWidth*sizeof(DWORD));
  787. outputFile.close();
  788. }
  789. //---------------------------------------------------------------------------
  790. inline bool textureIsOKFormat (const char *fileName)
  791. {
  792. File tgaFile;
  793. long result = tgaFile.open(fileName);
  794. if (result == NO_ERR)
  795. {
  796. struct TGAFileHeader tgaHeader;
  797. tgaFile.read((MemoryPtr)&tgaHeader,sizeof(TGAFileHeader));
  798. if (((tgaHeader.image_type == UNC_TRUE) || (tgaHeader.image_type == RLE_TRUE)) &&
  799. (tgaHeader.width == tgaHeader.height) &&
  800. ((tgaHeader.width == 32) ||
  801. (tgaHeader.width == 64) ||
  802. (tgaHeader.width == 128) ||
  803. (tgaHeader.width == 256)))
  804. return true;
  805. tgaFile.close();
  806. }
  807. return false;
  808. }
  809. //---------------------------------------------------------------------------
  810. void TerrainColorMap::resetDetailTexture (const char *fileName)
  811. {
  812. if (!textureIsOKFormat(fileName))
  813. {
  814. char msg[2048];
  815. sprintf(msg,"Texture %s is not 24bit or 32bit, 32x32, 64x64, 128x128 or 256x256 TGA File. Not loaded!",fileName);
  816. MessageBox( NULL, msg, NULL, MBOK );
  817. return;
  818. }
  819. mcTextureManager->removeTextureNode (detailTextureNodeIndex);
  820. detailTextureNodeIndex = 0xffffffff;
  821. #if 0
  822. //Load up the detail texture.
  823. // Detail texture is named same as colormap with .detail in name.
  824. // if no file exists, no texture drawn.
  825. char dName[1024];
  826. sprintf(dName,"%s.detail",fileName);
  827. FullPathFileName detailFile;
  828. detailFile.init(texturePath,dName,".tga");
  829. if (fileExists(detailFile)) //Otherwise, its already 0xffffffff!!
  830. detailTextureNodeIndex = mcTextureManager->loadTexture(detailFile,gos_Texture_Alpha,gosHint_DontShrink);
  831. #else
  832. detailTextureNodeIndex = mcTextureManager->loadTexture(fileName,gos_Texture_Alpha,gosHint_DontShrink);
  833. #endif
  834. }
  835. //---------------------------------------------------------------------------
  836. void TerrainColorMap::resetWaterTexture (const char *fileName)
  837. {
  838. if (!textureIsOKFormat(fileName))
  839. {
  840. char msg[2048];
  841. sprintf(msg,"Texture %s is not 24bit or 32bit, 32x32, 64x64, 128x128 or 256x256 TGA File. Not loaded!",fileName);
  842. MessageBox( NULL, msg, NULL, MBOK );
  843. return;
  844. }
  845. mcTextureManager->removeTextureNode (waterTextureNodeIndex);
  846. waterTextureNodeIndex = 0xffffffff;
  847. #if 0
  848. //load up the water texture.
  849. // Water texture is named the same as the colormap with .water in name.
  850. // If no file exists, no texture drawn!!
  851. char dName[1024];
  852. sprintf(dName,"%s.water",fileName);
  853. FullPathFileName waterFile;
  854. waterFile.init(texturePath,dName,".tga");
  855. if (fileExists(waterFile)) //Otherwise, its already 0xffffffff!!
  856. waterTextureNodeIndex = mcTextureManager->loadTexture(waterFile,gos_Texture_Solid,0);
  857. #else
  858. waterTextureNodeIndex = mcTextureManager->loadTexture(fileName,gos_Texture_Solid,0);
  859. #endif
  860. }
  861. //---------------------------------------------------------------------------
  862. void TerrainColorMap::resetWaterDetailTextures (char *fileName)
  863. {
  864. //Then, load up the water detail texture(s).
  865. // Water detail texture is named the same as the colormap with .water0000 in name
  866. // Where 0000 is the frame number of the animation for the water detail.
  867. // If the first frame does not exist, no texture is drawn!!
  868. for (long i=0;i<MAX_WATER_DETAIL_TEXTURES;i++)
  869. {
  870. char waterFile[1024];
  871. if (strlen("0000.tga") > strlen(fileName))
  872. {
  873. strcpy(waterFile, "0000.tga");
  874. }
  875. else
  876. {
  877. strcpy(waterFile, fileName);
  878. char dName[1024];
  879. sprintf(dName,"%04d.tga",i);
  880. char *subStringToBeReplaced = &(waterFile[strlen(waterFile)-strlen("0000.tga")]);
  881. strcpy(subStringToBeReplaced, dName);
  882. }
  883. bool textureIsOK = true;
  884. if (!textureIsOKFormat(waterFile))
  885. {
  886. //PAUSE(("Texture %s is Not 24bit or 32bit TGA File. Not loaded. Press Continue",fileName));
  887. textureIsOK = false;
  888. }
  889. if (textureIsOK && fileExists(waterFile))
  890. {
  891. if (!i) //If we found the first one OK, erase the current ones!!
  892. {
  893. for (long j=0;j<MAX_WATER_DETAIL_TEXTURES;j++)
  894. {
  895. mcTextureManager->removeTextureNode (waterDetailNodeIndex[j]);
  896. waterDetailNodeIndex[j] = 0xffffffff;
  897. }
  898. numWaterDetailFrames = 0;
  899. }
  900. waterDetailNodeIndex[i] = mcTextureManager->loadTexture(waterFile,gos_Texture_Alpha,gosHint_DontShrink);
  901. numWaterDetailFrames++;
  902. }
  903. else
  904. {
  905. if (!i)
  906. break; //No water detail!
  907. waterDetailNodeIndex[i] = 0xffffffff;
  908. }
  909. }
  910. }
  911. //---------------------------------------------------------------------------
  912. void TerrainColorMap::recalcLight(char *fileName)
  913. {
  914. colorMapRAMHeap = new UserHeap;
  915. colorMapRAMHeap->init(COLOR_MAP_HEAP_SIZE,"ColorMap");
  916. FullPathFileName colorMapName;
  917. colorMapName.init(texturePath,fileName,".tga");
  918. char newName[1024];
  919. sprintf(newName,"%s.burnin",fileName);
  920. FullPathFileName burnInName;
  921. burnInName.init(texturePath,newName,".tga");
  922. File colorMapFile;
  923. long result = colorMapFile.open(colorMapName);
  924. if (result != NO_ERR)
  925. {
  926. PAUSE(("Unable to open Terrain Color Map %s. Cannot Re-light map. Press Continue",colorMapName));
  927. return;
  928. }
  929. MemoryPtr tgaFileImage = (MemoryPtr)malloc(colorMapFile.fileSize());
  930. gosASSERT(tgaFileImage != NULL);
  931. colorMapFile.read(tgaFileImage,colorMapFile.fileSize());
  932. TGAFileHeader colorMapInfo;
  933. memcpy(&colorMapInfo,tgaFileImage,sizeof(TGAFileHeader));
  934. if (colorMapInfo.image_type == UNC_TRUE)
  935. {
  936. MemoryPtr loadBuffer = tgaFileImage + sizeof(TGAFileHeader);
  937. if (colorMapInfo.width != colorMapInfo.height)
  938. STOP(("Color Map is not a perfect Square"));
  939. //-----------------------------------------------------------------
  940. // Check if 24 or 32 bit. If 24, do the necessary stuff to it.
  941. ColorMap = (MemoryPtr)colorMapRAMHeap->Malloc(colorMapInfo.width * colorMapInfo.width * sizeof(DWORD));
  942. gosASSERT(ColorMap != NULL);
  943. if (colorMapInfo.pixel_depth == 24)
  944. {
  945. //24-Bit color means we must add in an opaque alpha to each 24 bits of color data.
  946. MemoryPtr cMap = ColorMap;
  947. MemoryPtr lMap = loadBuffer;
  948. for (long i = 0;i<(colorMapInfo.width * colorMapInfo.width);i++)
  949. {
  950. *cMap = *lMap; //Red
  951. cMap++;
  952. lMap++;
  953. *cMap = *lMap; //Green
  954. cMap++;
  955. lMap++;
  956. *cMap = *lMap; //Blue
  957. cMap++;
  958. lMap++;
  959. *cMap = 0xff; //Alpha
  960. cMap++;
  961. }
  962. }
  963. else
  964. {
  965. //32-bit color means all we have to do is copy the buffer.
  966. memcpy(ColorMap,loadBuffer,colorMapInfo.width * colorMapInfo.width * sizeof(DWORD));
  967. }
  968. free(tgaFileImage);
  969. tgaFileImage = NULL;
  970. numTextures = colorMapInfo.width / COLOR_MAP_TEXTURE_SIZE;
  971. numTexturesAcross = numTextures;
  972. fractionPerTexture = 1.0f / numTextures;
  973. float checkNum = float(colorMapInfo.width) / float(COLOR_MAP_TEXTURE_SIZE);
  974. if (checkNum != float(numTextures))
  975. STOP(("Color Map is %d pixels wide which is not even divisible by %d",colorMapInfo.width,COLOR_MAP_TEXTURE_SIZE));
  976. numTextures *= numTextures;
  977. txmRAM = (ColorMapRAM *)colorMapRAMHeap->Malloc(sizeof(ColorMapRAM) * numTextures);
  978. gosASSERT(txmRAM != NULL);
  979. //------------------------------------------------------------------------
  980. // Must check image_descriptor to see if we need to un upside down image.
  981. //bool left = (colorMapInfo.iimage_descriptor & 16) != 0;
  982. bool top = (colorMapInfo.image_descriptor & 32) != 0;
  983. if (!top)
  984. {
  985. flipTopToBottom(ColorMap,32,colorMapInfo.width,colorMapInfo.height);
  986. }
  987. //Apply shadow map. calc every time for now. Save as in editor, eventually.
  988. burnInShadows(true,fileName);
  989. saveTGAFile(ColorMap,fileName,colorMapInfo.width);
  990. //Now, divide up the color map into separate COLOR_MAP_TEXTURE_SIZE textures.
  991. // and hand the data to the textureManager.
  992. for (unsigned long i=0;i<numTextures;i++)
  993. {
  994. mcTextureManager->removeTextureNode(textures[i].mcTextureNodeIndex);
  995. txmRAM[i].ourRAM = (MemoryPtr)colorMapRAMHeap->Malloc(sizeof(DWORD) * COLOR_MAP_TEXTURE_SIZE * COLOR_MAP_TEXTURE_SIZE);
  996. gosASSERT(txmRAM[i].ourRAM != NULL);
  997. getColorMapData(txmRAM[i].ourRAM,i, colorMapInfo.width);
  998. textures[i].mcTextureNodeIndex = mcTextureManager->textureFromMemory((DWORD *)txmRAM[i].ourRAM,gos_Texture_Solid,gosHint_DontShrink,COLOR_MAP_TEXTURE_SIZE);
  999. }
  1000. }
  1001. //At this point, the color Map DATA should be freeable!!
  1002. // All of the textures have been passed to the mcTextureManager!
  1003. for (unsigned long i=0;i<numTextures;i++)
  1004. {
  1005. colorMapRAMHeap->Free(txmRAM[i].ourRAM);
  1006. txmRAM[i].ourRAM = NULL;
  1007. }
  1008. colorMapRAMHeap->Free(txmRAM);
  1009. txmRAM = NULL;
  1010. colorMapRAMHeap->Free(ColorMap);
  1011. ColorMap = NULL;
  1012. if (colorMapRAMHeap)
  1013. {
  1014. delete colorMapRAMHeap;
  1015. colorMapRAMHeap = NULL;
  1016. }
  1017. }
  1018. //---------------------------------------------------------------------------
  1019. void TerrainColorMap::resetBaseTexture (char *fileName)
  1020. {
  1021. //First, free up the existing colormap.
  1022. for (unsigned long i=0;i<numTextures;i++)
  1023. {
  1024. mcTextureManager->removeTextureNode(textures[i].mcTextureNodeIndex);
  1025. textures[i].mcTextureNodeIndex = 0xffffffff;
  1026. }
  1027. colorMapRAMHeap = new UserHeap;
  1028. colorMapRAMHeap->init(COLOR_MAP_HEAP_SIZE,"ColorMap");
  1029. FullPathFileName colorMapName;
  1030. colorMapName.init(texturePath,fileName,".tga");
  1031. char newName[1024];
  1032. sprintf(newName,"%s.burnin",fileName);
  1033. FullPathFileName burnInName;
  1034. burnInName.init(texturePath,newName,".tga");
  1035. bool burnedIn = false;
  1036. File colorMapFile;
  1037. long result = colorMapFile.open(burnInName);
  1038. if (result != NO_ERR)
  1039. {
  1040. result = colorMapFile.open(colorMapName);
  1041. if (result != NO_ERR)
  1042. STOP(("Unable to open Terrain Color Map %s",colorMapName));
  1043. }
  1044. else
  1045. {
  1046. burnedIn = true;
  1047. }
  1048. MemoryPtr tgaFileImage = (MemoryPtr)malloc(colorMapFile.fileSize());
  1049. gosASSERT(tgaFileImage != NULL);
  1050. colorMapFile.read(tgaFileImage,colorMapFile.fileSize());
  1051. TGAFileHeader colorMapInfo;
  1052. memcpy(&colorMapInfo,tgaFileImage,sizeof(TGAFileHeader));
  1053. if (colorMapInfo.image_type == UNC_TRUE)
  1054. {
  1055. MemoryPtr loadBuffer = tgaFileImage + sizeof(TGAFileHeader);
  1056. if (colorMapInfo.width != colorMapInfo.height)
  1057. STOP(("Color Map is not a perfect Square"));
  1058. //-----------------------------------------------------------------
  1059. // Check if 24 or 32 bit. If 24, do the necessary stuff to it.
  1060. ColorMap = (MemoryPtr)colorMapRAMHeap->Malloc(colorMapInfo.width * colorMapInfo.width * sizeof(DWORD));
  1061. gosASSERT(ColorMap != NULL);
  1062. if (colorMapInfo.pixel_depth == 24)
  1063. {
  1064. //24-Bit color means we must add in an opaque alpha to each 24 bits of color data.
  1065. MemoryPtr cMap = ColorMap;
  1066. MemoryPtr lMap = loadBuffer;
  1067. for (long i = 0;i<(colorMapInfo.width * colorMapInfo.width);i++)
  1068. {
  1069. *cMap = *lMap; //Red
  1070. cMap++;
  1071. lMap++;
  1072. *cMap = *lMap; //Green
  1073. cMap++;
  1074. lMap++;
  1075. *cMap = *lMap; //Blue
  1076. cMap++;
  1077. lMap++;
  1078. *cMap = 0xff; //Alpha
  1079. cMap++;
  1080. }
  1081. }
  1082. else
  1083. {
  1084. //32-bit color means all we have to do is copy the buffer.
  1085. memcpy(ColorMap,loadBuffer,colorMapInfo.width * colorMapInfo.width * sizeof(DWORD));
  1086. }
  1087. free(tgaFileImage);
  1088. tgaFileImage = NULL;
  1089. numTextures = colorMapInfo.width / COLOR_MAP_TEXTURE_SIZE;
  1090. numTexturesAcross = numTextures;
  1091. fractionPerTexture = 1.0f / numTextures;
  1092. float checkNum = float(colorMapInfo.width) / float(COLOR_MAP_TEXTURE_SIZE);
  1093. if (checkNum != float(numTextures))
  1094. STOP(("Color Map is %d pixels wide which is not even divisible by %d",colorMapInfo.width,COLOR_MAP_TEXTURE_SIZE));
  1095. numTextures *= numTextures;
  1096. textures = (ColorMapTextures *)colorMapHeap->Malloc(sizeof(ColorMapTextures) * numTextures);
  1097. gosASSERT(textures != NULL);
  1098. txmRAM = (ColorMapRAM *)colorMapRAMHeap->Malloc(sizeof(ColorMapRAM) * numTextures);
  1099. gosASSERT(txmRAM != NULL);
  1100. //------------------------------------------------------------------------
  1101. // Must check image_descriptor to see if we need to un upside down image.
  1102. //bool left = (colorMapInfo.iimage_descriptor & 16) != 0;
  1103. bool top = (colorMapInfo.image_descriptor & 32) != 0;
  1104. if (!top)
  1105. {
  1106. flipTopToBottom(ColorMap,32,colorMapInfo.width,colorMapInfo.height);
  1107. }
  1108. //Apply shadow map. calc every time for now. Save as in editor, eventually.
  1109. if (!burnedIn)
  1110. {
  1111. burnInShadows(true,fileName);
  1112. saveTGAFile(ColorMap,fileName,colorMapInfo.width);
  1113. }
  1114. //Now, divide up the color map into separate COLOR_MAP_TEXTURE_SIZE textures.
  1115. // and hand the data to the textureManager.
  1116. for (unsigned long i=0;i<numTextures;i++)
  1117. {
  1118. txmRAM[i].ourRAM = (MemoryPtr)colorMapRAMHeap->Malloc(sizeof(DWORD) * COLOR_MAP_TEXTURE_SIZE * COLOR_MAP_TEXTURE_SIZE);
  1119. gosASSERT(txmRAM[i].ourRAM != NULL);
  1120. getColorMapData(txmRAM[i].ourRAM,i, colorMapInfo.width);
  1121. textures[i].mcTextureNodeIndex = mcTextureManager->textureFromMemory((DWORD *)txmRAM[i].ourRAM,gos_Texture_Solid,gosHint_DontShrink,COLOR_MAP_TEXTURE_SIZE);
  1122. }
  1123. }
  1124. //At this point, the color Map DATA should be freeable!!
  1125. // All of the textures have been passed to the mcTextureManager!
  1126. for (i=0;i<numTextures;i++)
  1127. {
  1128. colorMapRAMHeap->Free(txmRAM[i].ourRAM);
  1129. txmRAM[i].ourRAM = NULL;
  1130. }
  1131. colorMapRAMHeap->Free(txmRAM);
  1132. txmRAM = NULL;
  1133. colorMapRAMHeap->Free(ColorMap);
  1134. ColorMap = NULL;
  1135. if (colorMapRAMHeap)
  1136. {
  1137. delete colorMapRAMHeap;
  1138. colorMapRAMHeap = NULL;
  1139. }
  1140. }
  1141. //---------------------------------------------------------------------------
  1142. //Used by editor for TacMap
  1143. void TerrainColorMap::getScaledColorMap (MemoryPtr bfr, long dWidth)
  1144. {
  1145. bool wasColorMapAround = true;
  1146. if (!ColorMap)
  1147. {
  1148. wasColorMapAround = false;
  1149. char *fileName = Terrain::colorMapName;
  1150. if (!fileName)
  1151. fileName = Terrain::terrainName;
  1152. colorMapRAMHeap = new UserHeap;
  1153. colorMapRAMHeap->init(COLOR_MAP_HEAP_SIZE,"ColorMap");
  1154. FullPathFileName colorMapName;
  1155. colorMapName.init(texturePath,fileName,".tga");
  1156. char newName[1024];
  1157. sprintf(newName,"%s.burnin",fileName);
  1158. FullPathFileName burnInName;
  1159. burnInName.init(texturePath,newName,".tga");
  1160. //This is what I meant. DO NOT use burnin unless we have to!
  1161. File colorMapFile;
  1162. long result = colorMapFile.open(burnInName);
  1163. if (result != NO_ERR)
  1164. {
  1165. result = colorMapFile.open(colorMapName);
  1166. if (result != NO_ERR)
  1167. {
  1168. #if defined(DEBUG) || defined(PROFILE)
  1169. PAUSE(("Unable to open Terrain Color Map %s. Press Continue",colorMapName));
  1170. #endif
  1171. return;
  1172. }
  1173. }
  1174. MemoryPtr tgaFileImage = (MemoryPtr)malloc(colorMapFile.fileSize());
  1175. gosASSERT(tgaFileImage != NULL);
  1176. colorMapFile.read(tgaFileImage,colorMapFile.fileSize());
  1177. TGAFileHeader colorMapInfo;
  1178. memcpy(&colorMapInfo,tgaFileImage,sizeof(TGAFileHeader));
  1179. if (colorMapInfo.image_type == UNC_TRUE)
  1180. {
  1181. MemoryPtr loadBuffer = tgaFileImage + sizeof(TGAFileHeader);
  1182. if (colorMapInfo.width != colorMapInfo.height)
  1183. STOP(("Color Map is not a perfect Square"));
  1184. //-----------------------------------------------------------------
  1185. // Check if 24 or 32 bit. If 24, do the necessary stuff to it.
  1186. ColorMap = (MemoryPtr)colorMapRAMHeap->Malloc(colorMapInfo.width * colorMapInfo.width * sizeof(DWORD));
  1187. gosASSERT(ColorMap != NULL);
  1188. if (colorMapInfo.pixel_depth == 24)
  1189. {
  1190. //24-Bit color means we must add in an opaque alpha to each 24 bits of color data.
  1191. MemoryPtr cMap = ColorMap;
  1192. MemoryPtr lMap = loadBuffer;
  1193. for (long i = 0;i<(colorMapInfo.width * colorMapInfo.width);i++)
  1194. {
  1195. *cMap = *lMap; //Red
  1196. cMap++;
  1197. lMap++;
  1198. *cMap = *lMap; //Green
  1199. cMap++;
  1200. lMap++;
  1201. *cMap = *lMap; //Blue
  1202. cMap++;
  1203. lMap++;
  1204. *cMap = 0xff; //Alpha
  1205. cMap++;
  1206. }
  1207. }
  1208. else
  1209. {
  1210. //32-bit color means all we have to do is copy the buffer.
  1211. memcpy(ColorMap,loadBuffer,colorMapInfo.width * colorMapInfo.width * sizeof(DWORD));
  1212. }
  1213. free(tgaFileImage);
  1214. tgaFileImage = NULL;
  1215. DWORD numTextures = colorMapInfo.width / COLOR_MAP_TEXTURE_SIZE;
  1216. numTexturesAcross = numTextures;
  1217. //------------------------------------------------------------------------
  1218. // Must check image_descriptor to see if we need to un upside down image.
  1219. //bool left = (colorMapInfo.iimage_descriptor & 16) != 0;
  1220. bool top = (colorMapInfo.image_descriptor & 32) != 0;
  1221. if (!top)
  1222. {
  1223. flipTopToBottom(ColorMap,32,colorMapInfo.width,colorMapInfo.height);
  1224. }
  1225. }
  1226. }
  1227. //Grab every xth pixel from every yth scan line!
  1228. float cMapWidth = numTexturesAcross * COLOR_MAP_TEXTURE_SIZE;
  1229. float xSkip = cMapWidth / float(dWidth);
  1230. float ySkip = xSkip;
  1231. long xOffset = 0, yOffset = 0;
  1232. DWORD *currentColor = (DWORD *)ColorMap;
  1233. DWORD *currentBfr = (DWORD *)bfr;
  1234. for (long i=0;i<(dWidth * dWidth);i++)
  1235. {
  1236. *currentBfr = *currentColor;
  1237. xOffset++;
  1238. if (xOffset >= dWidth)
  1239. {
  1240. xOffset = 0;
  1241. yOffset++;
  1242. }
  1243. currentBfr++;
  1244. currentColor = ((DWORD *)ColorMap) + long(xOffset * xSkip) + (long(yOffset*ySkip) * (long)cMapWidth);
  1245. }
  1246. if (!wasColorMapAround)
  1247. {
  1248. delete colorMapRAMHeap;
  1249. colorMapRAMHeap = NULL;
  1250. ColorMap = NULL;
  1251. }
  1252. }
  1253. static long sReadIdFloat(FitIniFile* missionFile, const char *varName, float &value) {
  1254. long result = 0;
  1255. float tmpFloat;
  1256. result = missionFile->readIdFloat((char *)varName, tmpFloat);
  1257. if (NO_ERR != result) {
  1258. //assert(false);
  1259. } else {
  1260. value = tmpFloat;
  1261. }
  1262. return result;
  1263. }
  1264. //---------------------------------------------------------------------------
  1265. long TerrainColorMap::init (char *fileName)
  1266. {
  1267. bool usedJPG = false;
  1268. if (!colorMapStarted)
  1269. {
  1270. //Load up the detail texture first.
  1271. // Detail texture is named same as colormap with .detail in name.
  1272. // if no file exists, no texture drawn.
  1273. char dName[1024];
  1274. sprintf(dName,"%s.detail",fileName);
  1275. FullPathFileName detailFile;
  1276. detailFile.init(texturePath,dName,".tga");
  1277. if (!fileExists(detailFile))
  1278. {
  1279. /* If a detail texture doesn't exist for this mission, use the default detail texture.*/
  1280. detailFile.destroy();
  1281. sprintf(dName,"defaults\\default_detail");
  1282. detailFile.init(texturePath,dName,".tga");
  1283. }
  1284. if (fileExists(detailFile)) //Otherwise, its already 0xffffffff!!
  1285. detailTextureNodeIndex = mcTextureManager->loadTexture(detailFile,gos_Texture_Alpha,gosHint_DontShrink);
  1286. else
  1287. gosASSERT(false);
  1288. //Ok, now load up the water texture.
  1289. // Water texture is named the same as the colormap with .water in name.
  1290. // If no file exists, no texture drawn!!
  1291. sprintf(dName,"%s.water",fileName);
  1292. FullPathFileName waterFile;
  1293. waterFile.init(texturePath,dName,".tga");
  1294. if (!fileExists(waterFile))
  1295. {
  1296. /* If a water texture doesn't exist for this mission, use the default water texture.*/
  1297. waterFile.destroy();
  1298. sprintf(dName,"defaults\\default_water");
  1299. waterFile.init(texturePath,dName,".tga");
  1300. }
  1301. if (fileExists(waterFile))
  1302. waterTextureNodeIndex = mcTextureManager->loadTexture(waterFile,gos_Texture_Solid,0);
  1303. else
  1304. gosASSERT(false);
  1305. //Then, load up the water detail texture(s).
  1306. // Water detail texture is named the same as the colormap with .water0000 in name
  1307. // Where 0000 is the frame number of the animation for the water detail.
  1308. // If the first frame does not exist, no texture is drawn!!
  1309. char waterDetailBaseName[1024];
  1310. sprintf(waterDetailBaseName,"%s.water",fileName);
  1311. {
  1312. sprintf(dName,"%s%04d",waterDetailBaseName,0);
  1313. FullPathFileName waterFile;
  1314. waterFile.init(texturePath,dName,".tga");
  1315. if (!fileExists(waterFile))
  1316. {
  1317. sprintf(waterDetailBaseName,"defaults\\default_water");
  1318. }
  1319. }
  1320. for (long i=0;i<MAX_WATER_DETAIL_TEXTURES;i++)
  1321. {
  1322. waterDetailNodeIndex[i] = 0xffffffff;
  1323. }
  1324. sprintf(dName,"%s%04d",waterDetailBaseName,0);
  1325. waterFile.init(texturePath,dName,".tga");
  1326. resetWaterDetailTextures((char *)waterFile);
  1327. {
  1328. detailTextureTilingFactor = 30.0f;
  1329. waterTextureTilingFactor = 48.0f;
  1330. waterDetailTilingFactor = 45.0f;
  1331. FullPathFileName missionFitFilePath;
  1332. missionFitFilePath.init(missionPath,fileName,".fit");
  1333. FitIniFile missionFitIni;
  1334. if (fileExists(missionFitFilePath))
  1335. {
  1336. missionFitIni.open((char*)(const char*)missionFitFilePath);
  1337. long result = missionFitIni.seekBlock( "Terrain" );
  1338. gosASSERT( result == NO_ERR );
  1339. result = sReadIdFloat(&missionFitIni, "DetailTextureTilingFactor", detailTextureTilingFactor);
  1340. result = sReadIdFloat(&missionFitIni, "WaterTextureTilingFactor", waterTextureTilingFactor);
  1341. result = sReadIdFloat(&missionFitIni, "WaterDetailTilingFactor", waterDetailTilingFactor);
  1342. missionFitIni.close();
  1343. }
  1344. }
  1345. colorMapHeap = new UserHeap;
  1346. colorMapHeap->init(COLOR_TXM_HEAP_SIZE,"ColorTXM");
  1347. colorMapRAMHeap = new UserHeap;
  1348. colorMapRAMHeap->init(COLOR_MAP_HEAP_SIZE,"ColorMap");
  1349. FullPathFileName colorMapName;
  1350. colorMapName.init(texturePath,fileName,".tga");
  1351. char newName[1024];
  1352. sprintf(newName,"%s.burnin",fileName);
  1353. FullPathFileName burnInName;
  1354. burnInName.init(texturePath,newName,".tga");
  1355. FullPathFileName burnInJpg;
  1356. burnInJpg.init(texturePath,newName,".jpg");
  1357. //NEW!!
  1358. // Look for the JPG first.
  1359. // If its there, read it in, pass it to the Decoder and bypass the rest of this!!
  1360. DWORD jpgColorMapWidth = 0;
  1361. DWORD jpgColorMapHeight = 0;
  1362. File colorMapFile;
  1363. long result = colorMapFile.open(burnInJpg);
  1364. if (result == NO_ERR)
  1365. {
  1366. long fileSize = colorMapFile.fileSize();
  1367. MemoryPtr jpgData = (MemoryPtr)malloc(fileSize);
  1368. colorMapFile.read(jpgData,fileSize);
  1369. ColorMap = (MemoryPtr)DecodeJPG(burnInJpg, jpgData, fileSize, &jpgColorMapWidth, &jpgColorMapHeight, false, NULL);
  1370. DWORD numTextures = jpgColorMapWidth / COLOR_MAP_TEXTURE_SIZE;
  1371. numTexturesAcross = numTextures;
  1372. fractionPerTexture = 1.0f / numTextures;
  1373. float checkNum = float(jpgColorMapWidth) / float(COLOR_MAP_TEXTURE_SIZE);
  1374. if (checkNum != float(numTextures))
  1375. STOP(("Color Map is %d pixels wide which is not even divisible by %d",jpgColorMapWidth,COLOR_MAP_TEXTURE_SIZE));
  1376. numTextures *= numTextures;
  1377. textures = (ColorMapTextures *)colorMapHeap->Malloc(sizeof(ColorMapTextures) * numTextures);
  1378. gosASSERT(textures != NULL);
  1379. txmRAM = (ColorMapRAM *)colorMapRAMHeap->Malloc(sizeof(ColorMapRAM) * numTextures);
  1380. gosASSERT(txmRAM != NULL);
  1381. //Now, divide up the color map into separate COLOR_MAP_TEXTURE_SIZE textures.
  1382. // and hand the data to the textureManager.
  1383. for (unsigned long i=0;i<numTextures;i++)
  1384. {
  1385. txmRAM[i].ourRAM = (MemoryPtr)colorMapRAMHeap->Malloc(sizeof(DWORD) * COLOR_MAP_TEXTURE_SIZE * COLOR_MAP_TEXTURE_SIZE);
  1386. gosASSERT(txmRAM[i].ourRAM != NULL);
  1387. getColorMapData(txmRAM[i].ourRAM,i, jpgColorMapWidth);
  1388. textures[i].mcTextureNodeIndex = mcTextureManager->textureFromMemory((DWORD *)txmRAM[i].ourRAM,gos_Texture_Solid,gosHint_DontShrink,COLOR_MAP_TEXTURE_SIZE);
  1389. }
  1390. free(jpgData);
  1391. jpgData = NULL;
  1392. colorMapStarted = true;
  1393. usedJPG = true;
  1394. }
  1395. else
  1396. {
  1397. bool burnedIn = false;
  1398. File colorMapFile;
  1399. result = colorMapFile.open(burnInName);
  1400. if (result != NO_ERR)
  1401. {
  1402. result = colorMapFile.open(colorMapName);
  1403. if (result != NO_ERR)
  1404. STOP(("Unable to open Terrain Color Map %s",colorMapName));
  1405. }
  1406. else
  1407. {
  1408. burnedIn = true;
  1409. }
  1410. MemoryPtr tgaFileImage = (MemoryPtr)malloc(colorMapFile.fileSize());
  1411. gosASSERT(tgaFileImage != NULL);
  1412. colorMapFile.read(tgaFileImage,colorMapFile.fileSize());
  1413. TGAFileHeader colorMapInfo;
  1414. memcpy(&colorMapInfo,tgaFileImage,sizeof(TGAFileHeader));
  1415. if (colorMapInfo.image_type == UNC_TRUE)
  1416. {
  1417. MemoryPtr loadBuffer = tgaFileImage + sizeof(TGAFileHeader);
  1418. if (colorMapInfo.width != colorMapInfo.height)
  1419. STOP(("Color Map is not a perfect Square"));
  1420. //-----------------------------------------------------------------
  1421. // Check if 24 or 32 bit. If 24, do the necessary stuff to it.
  1422. ColorMap = (MemoryPtr)colorMapRAMHeap->Malloc(colorMapInfo.width * colorMapInfo.width * sizeof(DWORD));
  1423. gosASSERT(ColorMap != NULL);
  1424. if (colorMapInfo.pixel_depth == 24)
  1425. {
  1426. //24-Bit color means we must add in an opaque alpha to each 24 bits of color data.
  1427. MemoryPtr cMap = ColorMap;
  1428. MemoryPtr lMap = loadBuffer;
  1429. for (long i = 0;i<(colorMapInfo.width * colorMapInfo.width);i++)
  1430. {
  1431. *cMap = *lMap; //Red
  1432. cMap++;
  1433. lMap++;
  1434. *cMap = *lMap; //Green
  1435. cMap++;
  1436. lMap++;
  1437. *cMap = *lMap; //Blue
  1438. cMap++;
  1439. lMap++;
  1440. *cMap = 0xff; //Alpha
  1441. cMap++;
  1442. }
  1443. }
  1444. else
  1445. {
  1446. //32-bit color means all we have to do is copy the buffer.
  1447. memcpy(ColorMap,loadBuffer,colorMapInfo.width * colorMapInfo.width * sizeof(DWORD));
  1448. }
  1449. free(tgaFileImage);
  1450. tgaFileImage = NULL;
  1451. DWORD numTextures = colorMapInfo.width / COLOR_MAP_TEXTURE_SIZE;
  1452. numTexturesAcross = numTextures;
  1453. fractionPerTexture = 1.0f / numTextures;
  1454. float checkNum = float(colorMapInfo.width) / float(COLOR_MAP_TEXTURE_SIZE);
  1455. if (checkNum != float(numTextures))
  1456. STOP(("Color Map is %d pixels wide which is not even divisible by %d",colorMapInfo.width,COLOR_MAP_TEXTURE_SIZE));
  1457. numTextures *= numTextures;
  1458. textures = (ColorMapTextures *)colorMapHeap->Malloc(sizeof(ColorMapTextures) * numTextures);
  1459. gosASSERT(textures != NULL);
  1460. txmRAM = (ColorMapRAM *)colorMapRAMHeap->Malloc(sizeof(ColorMapRAM) * numTextures);
  1461. gosASSERT(txmRAM != NULL);
  1462. //------------------------------------------------------------------------
  1463. // Must check image_descriptor to see if we need to un upside down image.
  1464. //bool left = (colorMapInfo.iimage_descriptor & 16) != 0;
  1465. bool top = (colorMapInfo.image_descriptor & 32) != 0;
  1466. if (!top)
  1467. {
  1468. flipTopToBottom(ColorMap,32,colorMapInfo.width,colorMapInfo.height);
  1469. }
  1470. //Apply shadow map. calc every time for now. Save as in editor, eventually.
  1471. if (!burnedIn)
  1472. {
  1473. burnInShadows(true,fileName);
  1474. saveTGAFile(ColorMap,fileName,colorMapInfo.width);
  1475. }
  1476. //Now, divide up the color map into separate COLOR_MAP_TEXTURE_SIZE textures.
  1477. // and hand the data to the textureManager.
  1478. for (unsigned long i=0;i<numTextures;i++)
  1479. {
  1480. txmRAM[i].ourRAM = (MemoryPtr)colorMapRAMHeap->Malloc(sizeof(DWORD) * COLOR_MAP_TEXTURE_SIZE * COLOR_MAP_TEXTURE_SIZE);
  1481. gosASSERT(txmRAM[i].ourRAM != NULL);
  1482. getColorMapData(txmRAM[i].ourRAM,i, colorMapInfo.width);
  1483. textures[i].mcTextureNodeIndex = mcTextureManager->textureFromMemory((DWORD *)txmRAM[i].ourRAM,gos_Texture_Solid,gosHint_DontShrink,COLOR_MAP_TEXTURE_SIZE);
  1484. }
  1485. }
  1486. colorMapStarted = true;
  1487. }
  1488. }
  1489. //At this point, the color Map DATA should be freeable!!
  1490. // All of the textures have been passed to the mcTextureManager!
  1491. for (unsigned long i=0;i<numTextures;i++)
  1492. {
  1493. colorMapRAMHeap->Free(txmRAM[i].ourRAM);
  1494. txmRAM[i].ourRAM = NULL;
  1495. }
  1496. colorMapRAMHeap->Free(txmRAM);
  1497. txmRAM = NULL;
  1498. if (usedJPG)
  1499. {
  1500. gos_Free(ColorMap);
  1501. ColorMap = NULL;
  1502. }
  1503. else
  1504. {
  1505. colorMapRAMHeap->Free(ColorMap);
  1506. ColorMap = NULL;
  1507. }
  1508. if (colorMapRAMHeap)
  1509. {
  1510. delete colorMapRAMHeap;
  1511. colorMapRAMHeap = NULL;
  1512. }
  1513. return 0;
  1514. }
  1515. float textureOffset = 0.4f;
  1516. //---------------------------------------------------------------------------
  1517. DWORD TerrainColorMap::getTextureHandle (VertexPtr vMin, VertexPtr vMax, TerrainUVData *uvData)
  1518. {
  1519. float posX = 0.0f, posY = 0.0f, maxX = 0.0f, maxY = 0.0f;
  1520. Stuff::Vector3D pos1(vMin->vx,vMin->vy,0.0f),pos2(vMax->vx,vMax->vy,0.0f);
  1521. if (Terrain::IsValidTerrainPosition(pos1) && Terrain::IsValidTerrainPosition(pos2))
  1522. {
  1523. //-----------------------------------------------------------------------------------------------------
  1524. //Since we have quads with tris in both directions, we need to determine what max and min really are!!
  1525. if (vMin->vx > vMax->vx)
  1526. {
  1527. //Tris are in a weird arrangement. Swap max and min X.
  1528. posX = (vMax->vx - Terrain::mapTopLeft3d.x) * Terrain::oneOverWorldUnitsMapSide;
  1529. maxX = (vMin->vx - Terrain::mapTopLeft3d.x) * Terrain::oneOverWorldUnitsMapSide;
  1530. }
  1531. else
  1532. {
  1533. //Tris in normal arrangement. Just calc 'em out.
  1534. posX = (vMin->vx - Terrain::mapTopLeft3d.x) * Terrain::oneOverWorldUnitsMapSide;
  1535. maxX = (vMax->vx - Terrain::mapTopLeft3d.x) * Terrain::oneOverWorldUnitsMapSide;
  1536. }
  1537. posY = (Terrain::mapTopLeft3d.y - vMin->vy) * Terrain::oneOverWorldUnitsMapSide;
  1538. maxY = (Terrain::mapTopLeft3d.y - vMax->vy) * Terrain::oneOverWorldUnitsMapSide;
  1539. //------------------------------------------------------
  1540. // Figure out which texture by the vertex v's position.
  1541. //We now have the position in x and y as fraction from 0.0 to 1.0
  1542. // The texture is easy. Just mutiply by number of textures across.
  1543. #define EDGE_ADJUST_FACTOR 0.0005f
  1544. long txmNumX = (posX + EDGE_ADJUST_FACTOR) * numTexturesAcross;
  1545. long txmNumY = (posY + EDGE_ADJUST_FACTOR) * numTexturesAcross;
  1546. long resultTexture = txmNumX + (txmNumY * numTexturesAcross);
  1547. // Now we need the UV Coords in this texture. This is the fraction from 0.0 to 1.0
  1548. // across the texture we are as vMin and vMax.
  1549. //
  1550. // IMPORTANT OPTIMIZATION NOTE: We only need to do this ONCE per terrain face at load time.
  1551. // It never changes!!!!!!!!
  1552. // We could calc as we get to the terrain faces and just know they're done, too!
  1553. // Could also store in the new PostcompVertex Structure!!
  1554. //Also need to adjust UVs by texturePixelAdjust to handle overlaping correctly.
  1555. float minX = (float)txmNumX * fractionPerTexture;
  1556. uvData->maxU = (maxX - minX) * numTexturesAcross;
  1557. uvData->minU = (posX - minX) * numTexturesAcross;
  1558. float minY = (float)txmNumY * fractionPerTexture;
  1559. uvData->maxV = (maxY - minY) * numTexturesAcross;
  1560. uvData->minV = (posY - minY) * numTexturesAcross;
  1561. /*
  1562. float textureAdjustFactor = (textureOffset / COLOR_MAP_RES);
  1563. if (uvData->minU <= textureAdjustFactor)
  1564. uvData->minU = textureAdjustFactor;
  1565. else
  1566. uvData->minU += xAdjust;
  1567. if (uvData->minV <= textureAdjustFactor)
  1568. uvData->minV = textureAdjustFactor;
  1569. else
  1570. uvData->minV += yAdjust;
  1571. if (uvData->maxU >= 1.0f)
  1572. uvData->maxU = 1.0f - textureAdjustFactor;
  1573. else
  1574. uvData->maxU += xAdjust;
  1575. if (uvData->maxV >= 1.0f)
  1576. uvData->maxV = 1.0f - textureAdjustFactor;
  1577. else
  1578. uvData->maxV += yAdjust;
  1579. */
  1580. #if 0
  1581. if ((uvData->minU < 0.0f) || (uvData->minU >= 1.0f))
  1582. STOP(("UvData our of range in minU %f",uvData->minU));
  1583. if ((uvData->minV < 0.0f) || (uvData->minV >= 1.0f))
  1584. STOP(("UvData our of range in minV %f",uvData->minV));
  1585. if ((uvData->maxU < 0.0f) || (uvData->maxU >= 1.0f))
  1586. STOP(("UvData our of range in maxU %f",uvData->maxU));
  1587. if ((uvData->maxV < 0.0f) || (uvData->maxV >= 1.0f))
  1588. STOP(("UvData our of range in maxV %f",uvData->maxV));
  1589. #endif
  1590. mcTextureManager->get_gosTextureHandle(textures[resultTexture].mcTextureNodeIndex);
  1591. return textures[resultTexture].mcTextureNodeIndex;
  1592. }
  1593. uvData->minU = uvData->minV = uvData->maxU = uvData->maxV = 0.0f;
  1594. return 0;
  1595. }
  1596. long TerrainColorMap::saveDetailTexture(const char *fileName)
  1597. {
  1598. char dName[1024];
  1599. sprintf(dName,"%s.detail",fileName);
  1600. FullPathFileName detailFile;
  1601. detailFile.init(texturePath,dName,".tga");
  1602. return mcTextureManager->saveTexture(detailTextureNodeIndex, detailFile);
  1603. }
  1604. long TerrainColorMap::saveWaterTexture(const char *fileName)
  1605. {
  1606. char dName[1024];
  1607. sprintf(dName,"%s.water",fileName);
  1608. FullPathFileName waterFile;
  1609. waterFile.init(texturePath,dName,".tga");
  1610. return mcTextureManager->saveTexture(waterTextureNodeIndex, waterFile);
  1611. }
  1612. long TerrainColorMap::saveWaterDetail(const char *fileName)
  1613. {
  1614. long result = NO_ERR;
  1615. int i;
  1616. for (i = 0; i < getWaterDetailNumFrames(); i++)
  1617. {
  1618. char dName[1024];
  1619. sprintf(dName,"%s.water%04d",fileName, i);
  1620. FullPathFileName waterDetailFile;
  1621. waterDetailFile.init(texturePath,dName,".tga");
  1622. long lResult = mcTextureManager->saveTexture(waterDetailNodeIndex[i], waterDetailFile);
  1623. if (NO_ERR != lResult)
  1624. {
  1625. result = lResult;
  1626. }
  1627. }
  1628. for (i = getWaterDetailNumFrames(); i < MAX_WATER_DETAIL_TEXTURES; i++)
  1629. {
  1630. char dName[1024];
  1631. sprintf(dName,"%s.water%04d",fileName, i);
  1632. FullPathFileName waterDetailFile;
  1633. waterDetailFile.init(texturePath,dName,".tga");
  1634. File textureFile;
  1635. long textureFileOpenResult = textureFile.open(waterDetailFile);
  1636. textureFile.close();
  1637. if (NO_ERR != textureFileOpenResult)
  1638. {
  1639. break;
  1640. }
  1641. textureFileOpenResult = textureFile.create(waterDetailFile);
  1642. textureFile.deleteFile(); /*what is this supposed to do?*/
  1643. textureFile.close();
  1644. DeleteFile(waterDetailFile);
  1645. }
  1646. return result;
  1647. }
  1648. long TerrainColorMap::saveTilingFactors(FitIniFile *fitFile)
  1649. {
  1650. long result = NO_ERR;
  1651. fitFile->writeIdFloat( "DetailTextureTilingFactor", getDetailTilingFactor() );
  1652. fitFile->writeIdFloat( "WaterTextureTilingFactor", getWaterTextureTilingFactor() );
  1653. fitFile->writeIdFloat( "WaterDetailTilingFactor", getWaterDetailTilingFactor() );
  1654. return result;
  1655. }
  1656. //---------------------------------------------------------------------------