LightMapPacker.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : LightMap *
  23. * *
  24. * $Archive:: /Commando/Code/Tool $*
  25. * *
  26. * $Author:: Ian_l $*
  27. * *
  28. * $Modtime:: 6/06/01 5:40p $*
  29. * *
  30. * $Revision:: 35 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #ifndef _LIGHTMAPPACKER_H
  36. #define _LIGHTMAPPACKER_H
  37. // Includes.
  38. #include "ProceduralTexture.h"
  39. #include "StringBuilder.h"
  40. #include "Triangle.h"
  41. #include "vector.h"
  42. #include "vector2.h"
  43. #include "matrix3.h"
  44. #include "listnode.h"
  45. #include "Targa.h"
  46. #include "w3d_file.h"
  47. #include <srPixelConvert.hpp>
  48. #include <srColorSurface.hpp>
  49. // Defines.
  50. #define UNPACKED_TEXEL_BYTE_COUNT 4 // No. of bytes for internal unpacked texel format (ARGB).
  51. class ColorSurface : public srColorSurface
  52. {
  53. public:
  54. ColorSurface (srPixelConvert::e_surfaceType pixelformat, short width, short height)
  55. : srColorSurface (pixelformat, width, height)
  56. {}
  57. };
  58. class TrueColorTarga : public Targa
  59. {
  60. public:
  61. // Public functions.
  62. TrueColorTarga();
  63. TrueColorTarga (unsigned width, unsigned height, unsigned pixeldepth);
  64. TrueColorTarga (unsigned width, unsigned height, unsigned pixeldepth, const W3dRGBStruct &clearcolor);
  65. void Reformat (unsigned width, unsigned height, unsigned pixeldepth);
  66. void Reformat (unsigned width, unsigned height, unsigned pixeldepth, const W3dRGBStruct &clearcolor);
  67. unsigned Width() const {return (Header.Width);}
  68. unsigned Height() const {return (Header.Height);}
  69. unsigned Pixel_Depth() const {return (Header.PixelDepth);}
  70. void Scale (unsigned width, unsigned height) {Scale (*this, width, height);}
  71. void Scale (TrueColorTarga &destination) {Scale (destination, destination.Width(), destination.Height());}
  72. void Scale (float filtererror) {Scale (*this, filtererror);}
  73. void Transpose() {Transpose (*this);}
  74. void Pad (unsigned padwidth, unsigned padheight, const W3dRGBStruct &padcolor, DynamicVectorClass <PackingTriangle*> &triangleptrs)
  75. {
  76. Pad (*this, padwidth, padheight, padcolor, triangleptrs);
  77. }
  78. char *Load (const char *pathname);
  79. char *Save (const char *pathname);
  80. void Blit (TrueColorTarga &destination, unsigned x, unsigned y);
  81. void Scale (TrueColorTarga &destination, unsigned width, unsigned height);
  82. int Compare (TrueColorTarga &comparison, float epsilon);
  83. int Compare (TrueColorTarga &comparison, unsigned x, unsigned y, float epsilon);
  84. bool Fill (const W3dRGBStruct &fillcolor);
  85. void Add (TrueColorTarga &targa);
  86. void Rasterize (TrueColorTarga &destination, const W3dRGBStruct &fillcolor, unsigned vertexcount, const W3dRGBStruct *vertexcolors, Vector2 *uvs);
  87. bool Get_Color (const Vector2 &t, W3dRGBStruct &color) const;
  88. bool Set_Color (unsigned x, unsigned y, const W3dRGBStruct &color);
  89. protected:
  90. enum TransposeEnum {
  91. UNTRANSPOSED,
  92. TRANSPOSED,
  93. TRANSPOSE_COUNT
  94. };
  95. struct UnpackedTexelStruct {
  96. UnpackedTexelStruct () {}
  97. UnpackedTexelStruct (unsigned char r, unsigned char g, unsigned char b, unsigned char a)
  98. {
  99. Set (r, g, b, a);
  100. }
  101. void Set (unsigned char r, unsigned char g, unsigned char b, unsigned char a)
  102. {
  103. Byte [0] = a;
  104. Byte [1] = r;
  105. Byte [2] = g;
  106. Byte [3] = b;
  107. }
  108. unsigned char Alpha() const {return (Byte [0]);}
  109. unsigned char Red() const {return (Byte [1]);}
  110. unsigned char Green() const {return (Byte [2]);}
  111. unsigned char Blue() const {return (Byte [3]);}
  112. // Equality operator.
  113. bool operator == (const UnpackedTexelStruct &t) {
  114. ASSERT (sizeof (unsigned long) == sizeof (Byte));
  115. return (*((unsigned long*) Byte) == *((unsigned long*) t.Byte));
  116. }
  117. // Inequality operator.
  118. bool operator != (const UnpackedTexelStruct &t) {
  119. return (!(*this == t));
  120. }
  121. // Addition operator.
  122. UnpackedTexelStruct operator += (UnpackedTexelStruct t)
  123. {
  124. Byte [0] = MIN (((unsigned) Byte [0]) + ((unsigned) t.Byte [0]), (unsigned) UCHAR_MAX);
  125. Byte [1] = MIN (((unsigned) Byte [1]) + ((unsigned) t.Byte [1]), (unsigned) UCHAR_MAX);
  126. Byte [2] = MIN (((unsigned) Byte [2]) + ((unsigned) t.Byte [2]), (unsigned) UCHAR_MAX);
  127. Byte [3] = MIN (((unsigned) Byte [3]) + ((unsigned) t.Byte [3]), (unsigned) UCHAR_MAX);
  128. return (*this);
  129. }
  130. // Public data.
  131. unsigned char Byte [UNPACKED_TEXEL_BYTE_COUNT];
  132. };
  133. struct PointStruct {
  134. // Equality operator.
  135. bool operator == (const PointStruct &p) {
  136. return ((X == p.X) && (Y == p.Y));
  137. }
  138. // Inequality operator.
  139. bool operator != (const PointStruct &p) {
  140. return (!(*this == p));
  141. }
  142. // Public data.
  143. int X;
  144. int Y;
  145. };
  146. void Clear (const UnpackedTexelStruct &cleartexel);
  147. private:
  148. // Inlines.
  149. unsigned char *Get_Texel (int x, int y) const;
  150. UnpackedTexelStruct *Unpack_Texel (unsigned char *packedtexelptr, unsigned packedbytespertexel, UnpackedTexelStruct &unpackedtexel) const;
  151. void Pack_Texel (const UnpackedTexelStruct &unpackedtexel, unsigned char *packedtexelptr, unsigned packedbytespertexel);
  152. // Static functions.
  153. static srPixelConvert::e_surfaceType Pixel_Format (unsigned pixeldepth);
  154. void Scale (TrueColorTarga &destination, float filtererror);
  155. void Transpose (TrueColorTarga &destination);
  156. bool Fill_Four_Connected (unsigned x, unsigned y, const UnpackedTexelStruct &filltexel, DynamicVectorClass <PointStruct> &fourconnectedarray);
  157. void Pad (TrueColorTarga &destination, unsigned verticalpadthickness, unsigned horizontalpadthickness, const W3dRGBStruct &padcolor, DynamicVectorClass <PackingTriangle*> &triangleptrs);
  158. };
  159. class Page : public TrueColorTarga
  160. {
  161. public:
  162. // Public functions.
  163. Page (unsigned bitdepth, const W3dRGBStruct &clearcolor);
  164. ~Page ();
  165. bool Pack (TrueColorTarga &targa, float epsilon, DynamicVectorClass <PackingTriangle*> &triangleptrs);
  166. float Packing_Efficiency() const
  167. {
  168. return (((float) UsedTexelCount) / (((unsigned) Width()) * ((unsigned) Height())));
  169. }
  170. float Replica_Efficiency() const
  171. {
  172. return (((float) ReplicaTexelCount) / (((unsigned) Width()) * ((unsigned) Height())));
  173. }
  174. private:
  175. class Region : public GenericNode {
  176. public:
  177. // Public functions.
  178. Region () {}
  179. Region (const Region &region)
  180. {
  181. Set (region.X0, region.Y0, region.X1, region.Y1);
  182. }
  183. unsigned Width () {return (X1 - X0 + 1);}
  184. unsigned Height() {return (Y1 - Y0 + 1);}
  185. void Set (unsigned x0, unsigned y0, unsigned x1, unsigned y1)
  186. {
  187. X0 = x0; Y0 = y0; X1 = x1; Y1 = y1;
  188. }
  189. bool Accomodates (unsigned width, unsigned height, Region &targetregion);
  190. bool Intersects (const Region &targetregion, unsigned &subregioncount, Region **subregions);
  191. // Public data.
  192. unsigned X0, Y0;
  193. unsigned X1, Y1;
  194. };
  195. // Private functions.
  196. bool Replica_Region (TrueColorTarga &targa, float epsilon, Region &replicaregion);
  197. bool Lowest_Cost_Region (TrueColorTarga &targa, unsigned &lowestcost, Region &lowestcostregion);
  198. void Insert_Region (const Region &insertionregion);
  199. bool Contains (const Region &testregion);
  200. // Statistics functions.
  201. void Reset_Statistics();
  202. // Private data.
  203. GenericList VacantRegionList;
  204. GenericList UsedRegionList;
  205. // Statistics counters.
  206. unsigned AssetCount;
  207. unsigned UsedTexelCount;
  208. unsigned ReplicaTexelCount;
  209. };
  210. class TargaLoader {
  211. public:
  212. // Public functions.
  213. TargaLoader (float samplerate, W3dRGBStruct fillcolor);
  214. ~TargaLoader();
  215. TrueColorTarga *Load (const Triangle &triangle);
  216. private:
  217. struct TargaCacheStruct {
  218. TargaCacheStruct()
  219. {
  220. Ptr = NULL;
  221. }
  222. ~TargaCacheStruct()
  223. {
  224. if (Ptr != NULL) delete Ptr;
  225. }
  226. // Equality operator.
  227. bool operator == (const TargaCacheStruct &t) {
  228. return ((ID == t.ID) && (Ptr == t.Ptr));
  229. }
  230. // Inequality operator.
  231. bool operator != (const TargaCacheStruct &t) {
  232. return (!(*this == t));
  233. }
  234. // Data.
  235. unsigned ID;
  236. TrueColorTarga *Ptr;
  237. };
  238. // Private functions.
  239. TargaLoader() {}
  240. unsigned Index (unsigned id)
  241. {
  242. return (id % ((unsigned) Cache.Length()));
  243. }
  244. // Private data.
  245. VectorClass <TargaCacheStruct> Cache; // A simple array of targacache objects.
  246. DynamicVectorClass <TrueColorTarga*> CleanupList; // List of targas that have been displaced from the cache but cannot
  247. // yet be deleted because they may still be referenced.
  248. float SampleRate; // No. of texels per unit length.
  249. W3dRGBStruct FillColor; // Color to replace during fill operations.
  250. };
  251. class TrianglePacker {
  252. public:
  253. TrianglePacker (const PackingTriangle *principaltriangleptr, const DynamicVectorClass <Triangle> &adjtriangles, unsigned groupid, unsigned edgeblendthickness, float samplerate, W3dRGBStruct fillcolor);
  254. DynamicVectorClass <PackingTriangle*> &Principal_Triangles() {return (PrincipalTriangles);}
  255. // Query functions.
  256. unsigned Width() const {return (UpperBound.U - LowerBound.U);}
  257. unsigned Height() const {return (UpperBound.V - LowerBound.V);}
  258. // Operations.
  259. TrianglePacker *Merge (const TrianglePacker &trianglepacker);
  260. void Rasterize (TargaLoader &targaloader, ProceduralTexture *proceduraltexture, TrueColorTarga &rasterizedtarga);
  261. // Statistics.
  262. unsigned Adjacent_Face_Count() const
  263. {
  264. return (AdjacentTriangles [ADJACENT_PROJECTION_COMMON].Count() +
  265. AdjacentTriangles [ADJACENT_PROJECTION_VALID].Count() +
  266. AdjacentTriangles [ADJACENT_PROJECTION_NONE].Count());
  267. }
  268. unsigned Blended_Face_Count() const
  269. {
  270. return (AdjacentTriangles [ADJACENT_PROJECTION_COMMON].Count() +
  271. AdjacentTriangles [ADJACENT_PROJECTION_VALID].Count());
  272. }
  273. float Edge_Blend_Area() const;
  274. private:
  275. enum ProjectionEnum {
  276. PROJECTION_Y_POSITIVE,
  277. PROJECTION_Y_NEGATIVE,
  278. PROJECTION_Z_POSITIVE,
  279. PROJECTION_Z_NEGATIVE,
  280. PROJECTION_X_POSITIVE,
  281. PROJECTION_X_NEGATIVE,
  282. PROJECTION_COUNT
  283. };
  284. enum AdjacentProjectionEnum {
  285. ADJACENT_PROJECTION_COMMON, // Adjacent triangles that use the same projection as this object.
  286. ADJACENT_PROJECTION_VALID, // Adjacent triangles that map to a different projection but have non-zero area if object's projection is used.
  287. ADJACENT_PROJECTION_NONE, // Adjacent triangles that cannot be projected using object's projection.
  288. ADJACENT_PROJECTION_COUNT
  289. };
  290. class ProjectionTriangle {
  291. public:
  292. // Public functions.
  293. ProjectionTriangle() {}
  294. ProjectionTriangle (const Vector3 *points, const Vector2 *sourceuvs, const TrueColorTarga *sourcetargaptr, const Vector2 *projectionuvs);
  295. // Public data.
  296. Vector3 Points [Triangle::VERTICES_COUNT];
  297. Vector2 SourceUVs [Triangle::VERTICES_COUNT];
  298. TrueColorTarga *SourceTargaPtr;
  299. Vector2 ProjectionUVs [Triangle::VERTICES_COUNT];
  300. };
  301. class SampleSurface {
  302. public:
  303. // Public functions.
  304. SampleSurface (unsigned width, unsigned height, ProceduralTexture *blendtexture = NULL);
  305. bool Sample (const Vector2 &samplepoint, const ProjectionTriangle &projectiontriangle, unsigned priority);
  306. bool Sample (float alpha, float beta, const ProjectionTriangle &projectiontriangle, unsigned priority);
  307. bool Get_Color (unsigned x, unsigned y, W3dRGBStruct &color)
  308. {
  309. SampleStruct *sampleptr;
  310. ASSERT ((x < Width) && (y < Height));
  311. sampleptr = Surface + (y * Width + x);
  312. if (sampleptr->Count > 0) {
  313. float oocount;
  314. unsigned r, g, b;
  315. oocount = 1.0f / sampleptr->Count;
  316. r = sampleptr->Red * oocount;
  317. g = sampleptr->Green * oocount;
  318. b = sampleptr->Blue * oocount;
  319. color.Set ((uint8) MIN (r, UCHAR_MAX), (uint8) MIN (g, UCHAR_MAX), (uint8) MIN (b, UCHAR_MAX));
  320. return (true);
  321. } else {
  322. return (false);
  323. }
  324. }
  325. unsigned Priority (unsigned x, unsigned y)
  326. {
  327. SampleStruct *sampleptr;
  328. ASSERT ((x < Width) && (y < Height));
  329. sampleptr = Surface + (y * Width + x);
  330. return (sampleptr->Priority);
  331. }
  332. float Sampling_Ratio() {return (((float) SampledTexelCount) / ((float) (Width * Height)));}
  333. private:
  334. struct SampleStruct {
  335. unsigned Red;
  336. unsigned Green;
  337. unsigned Blue;
  338. unsigned Count;
  339. unsigned Priority;
  340. };
  341. SampleSurface() {}
  342. unsigned Width;
  343. unsigned Height;
  344. unsigned SampledTexelCount;
  345. SampleStruct *Surface;
  346. ProceduralTexture *BlendTexture;
  347. };
  348. // Private functions.
  349. TrianglePacker() {}
  350. TrianglePacker (const TrianglePacker &trianglepacker); // Copy constructor.
  351. void Set_Bounds();
  352. bool Can_Project (const Vector3 &normal);
  353. Vector2 Project (const Vector3 &point) const;
  354. // void Get_Projection_Triangle (const Triangle &triangle, ProjectionTriangleStruct &projectiontriangle);
  355. bool Sample (const Vector2 &samplepoint, const ProjectionTriangle &projectiontriangle, W3dRGBStruct &color);
  356. static ProjectionEnum Get_Projection (const Vector3 &normal);
  357. // Private data.
  358. ProjectionEnum Projection; // Texture projection to be used for rasterization.
  359. unsigned GroupID;
  360. unsigned EdgeBlendThickness;
  361. float SampleRate; // No. of texels per unit length.
  362. W3dRGBStruct FillColor; // Color to replace during fill operations.
  363. DynamicVectorClass <PackingTriangle*> PrincipalTriangles; // Set of triangles that will be rasterized in their entirety (ie. not edge blended).
  364. DynamicVectorClass <Triangle> AdjacentTriangles [ADJACENT_PROJECTION_COUNT]; // Set of triangles that will be edge-blended.
  365. Vector2 LowerBound; // Lower bound of all principal triangle points projected onto the texel plane.
  366. Vector2 UpperBound; // Upper bound of all principal triangle points projected onto the texel plane.
  367. };
  368. class LightmapPacker {
  369. public:
  370. enum ThicknessEnum {
  371. EDGE_BLEND_THICKNESS = 2 // No. of texels to pad around every packed map.
  372. // NOTE: The edge blend thickness is designed to prevent
  373. // bleeding between adjacent maps under mip-mapping. The
  374. // no, of allowable mip-maps is dependant upon this
  375. // thickness value.
  376. };
  377. enum StatisticsEnum {
  378. STATISTICS_PAGE_FORMAT,
  379. STATISTICS_LIGHTMAPS_PROCESSED,
  380. STATISTICS_ADJACENT_FACE_BLEND_PERCENTAGE,
  381. STATISTICS_EDGE_BLEND_EFFICIENCY,
  382. STATISTICS_SCALING_EFFICIENCY,
  383. STATISTICS_PAGES_CREATED,
  384. STATISTICS_PACKING_EFFICIENCY,
  385. STATISTICS_CULLING_EFFICIENCY,
  386. STATISTICS_TEXTURE_SWAP_EFFICIENCY,
  387. STATISTICS_OVERSIZE_LIGHTMAPS,
  388. STATISTICS_COUNT,
  389. STATISTICS_STRING_SIZE = 32 // Size of statistic string in bytes.
  390. };
  391. LightmapPacker();
  392. Finish();
  393. ~LightmapPacker();
  394. void Submit (PackingTriangle *principaltriangleptr, const DynamicVectorClass <Triangle> &adjtriangles);
  395. TrianglePacker *Merge (TrianglePacker *trianglepackerptr);
  396. void Pack (ProceduralTexture *proceduraltexture = NULL);
  397. void Pack (TrueColorTarga &targa, DynamicVectorClass <PackingTriangle*> &triangleptrs);
  398. static const char *Lightmap_Pathname (unsigned pageindex);
  399. static const char *Asset_Directory();
  400. static const char *Asset_Directory (const char *filename);
  401. static void Delete_Assets();
  402. static void Copy_Assets (const char *pathname);
  403. static const char *Get_Statistic (unsigned index) {ASSERT (index < STATISTICS_COUNT); return (_Statistics [index]);}
  404. private:
  405. // Statistics functions.
  406. void Reset_Statistics();
  407. void Update_Statistics (const Page &page);
  408. void Update_Statistics (const TrianglePacker &trianglepacker);
  409. void Collate_Statistics();
  410. W3dRGBStruct FillColor; // Color used to pad unused texels in lightmaps.
  411. float ScaleFactor; // Global lightmap scaling factor (0.0...1.0).
  412. float FilterError; // Maximum allowed variance between a color component of original
  413. // lightmap and that of packed lightmap, expressed as a fraction
  414. // of color component's total range ie. a setting of 0.0 will
  415. // allow no variance (packed lightmap must match original) and
  416. // a setting of 1.0 allows complete variance.
  417. float SampleRate; // Sample rate used by rasterizers (such as Edge_Blend()) in texels per unit length.
  418. unsigned PageBitDepth; // Bit depth of page texels.
  419. int CurrentPageIndex; // Current page (-1 indicates no page exists).
  420. DynamicVectorClass <TrianglePacker*> TrianglePackerPtrs;
  421. DynamicVectorClass <Page*> PagePtrs;
  422. TextureNameNode *PlaceholderTextureNameNodePtr;
  423. // Statistics counters.
  424. unsigned FaceCount;
  425. unsigned LightmapCount;
  426. unsigned AdjacentFaceCount;
  427. unsigned BlendedFaceCount;
  428. double EdgeBlendAreaSum;
  429. __int64 UnscaledTexelCount;
  430. __int64 ScaledTexelCount;
  431. double PackingEfficiencySum;
  432. double ReplicaEfficiencySum;
  433. unsigned TextureSwapCount;
  434. unsigned OversizeCount;
  435. unsigned AllFillColorCount;
  436. static unsigned _BasePageIndex;
  437. static char _Statistics [STATISTICS_COUNT][STATISTICS_STRING_SIZE];
  438. };
  439. /***********************************************************************************************
  440. * TrueColorTarga::Get_Color -- *
  441. * *
  442. * INPUT: *
  443. * *
  444. * OUTPUT: *
  445. * *
  446. * WARNINGS: *
  447. * *
  448. * HISTORY: *
  449. * 06/27/00 IML : Created. *
  450. *=============================================================================================*/
  451. inline bool TrueColorTarga::Get_Color (const Vector2 &t, W3dRGBStruct &color) const
  452. {
  453. int x, y;
  454. unsigned char *texelptr;
  455. UnpackedTexelStruct unpackedtexel;
  456. x = t.U * Width();
  457. y = t.V * Height();
  458. texelptr = Get_Texel (x, y);
  459. if (texelptr == NULL) return (false);
  460. Unpack_Texel (texelptr, TGA_BytesPerPixel (Pixel_Depth()), unpackedtexel);
  461. color.Set (unpackedtexel.Red(), unpackedtexel.Green(), unpackedtexel.Blue());
  462. return (true);
  463. }
  464. /***********************************************************************************************
  465. * TrueColorTarga::Set_Color -- *
  466. * *
  467. * INPUT: *
  468. * *
  469. * OUTPUT: *
  470. * *
  471. * WARNINGS: *
  472. * *
  473. * HISTORY: *
  474. * 06/27/00 IML : Created. *
  475. *=============================================================================================*/
  476. inline bool TrueColorTarga::Set_Color (unsigned x, unsigned y, const W3dRGBStruct &color)
  477. {
  478. UnpackedTexelStruct unpackedtexel (color.R, color.G, color.B, 0);
  479. unsigned char *texelptr;
  480. texelptr = Get_Texel (x, y);
  481. if (texelptr != NULL) {
  482. Pack_Texel (unpackedtexel, texelptr, TGA_BytesPerPixel (Pixel_Depth()));
  483. return (true);
  484. } else {
  485. return (false);
  486. }
  487. }
  488. /***********************************************************************************************
  489. * TrueColorTarga::Get_Texel -- *
  490. * *
  491. * INPUT: *
  492. * *
  493. * OUTPUT: *
  494. * *
  495. * WARNINGS: *
  496. * *
  497. * HISTORY: *
  498. * 9/27/99 IML : Created. *
  499. *=============================================================================================*/
  500. inline unsigned char *TrueColorTarga::Get_Texel (int x, int y) const
  501. {
  502. // Check for (x, y) out of range.
  503. if ((x < 0) || (x >= ((int) Width ()))) return (NULL);
  504. if ((y < 0) || (y >= ((int) Height()))) return (NULL);
  505. return ((unsigned char*) GetImage()) + (((Width() * y) + x) * TGA_BytesPerPixel (Pixel_Depth()));
  506. }
  507. /***********************************************************************************************
  508. * TrueColorTarga::Unpack_Texel -- *
  509. * *
  510. * INPUT: *
  511. * *
  512. * OUTPUT: *
  513. * *
  514. * WARNINGS: *
  515. * *
  516. * HISTORY: *
  517. * 9/27/99 IML : Created. *
  518. *=============================================================================================*/
  519. inline TrueColorTarga::UnpackedTexelStruct *TrueColorTarga::Unpack_Texel (unsigned char *packedtexelptr, unsigned packedbytespertexel, UnpackedTexelStruct &unpackedtexel) const
  520. {
  521. switch (packedbytespertexel) {
  522. case 4:
  523. // Packed format same as unpacked format.
  524. ASSERT (sizeof (UnpackedTexelStruct) == 4);
  525. unpackedtexel = *((UnpackedTexelStruct*) packedtexelptr);
  526. break;
  527. case 3:
  528. // Unpack to ordering ARGB. Set Alpha to zero.
  529. unpackedtexel.Byte [0] = 0; // Alpha
  530. unpackedtexel.Byte [1] = *(packedtexelptr + 0); // Red
  531. unpackedtexel.Byte [2] = *(packedtexelptr + 1); // Green
  532. unpackedtexel.Byte [3] = *(packedtexelptr + 2); // Blue
  533. break;
  534. case 2:
  535. {
  536. static unsigned char _alpha [2] = {0x00, 0xff};
  537. unsigned short packedtexel = *((unsigned short*) packedtexelptr);
  538. // Unpack to ordering ARGB. Bit replicate Alpha.
  539. unpackedtexel.Byte [0] = _alpha [packedtexel >> 15]; // Alpha
  540. unpackedtexel.Byte [1] = ((packedtexel & 0x7c00) >> 7) | 0x3; // Red
  541. unpackedtexel.Byte [2] = ((packedtexel & 0x03e0) >> 2) | 0x3; // Green
  542. unpackedtexel.Byte [3] = ((packedtexel & 0x001f) << 3) | 0x3; // Blue
  543. }
  544. break;
  545. default:
  546. // Unrecognized byte count.
  547. ASSERT (0);
  548. break;
  549. }
  550. return (&unpackedtexel);
  551. }
  552. /***********************************************************************************************
  553. * TrueColorTarga::Pack_Texel -- *
  554. * *
  555. * INPUT: *
  556. * *
  557. * OUTPUT: *
  558. * *
  559. * WARNINGS: *
  560. * *
  561. * HISTORY: *
  562. * 9/27/99 IML : Created. *
  563. *=============================================================================================*/
  564. inline void TrueColorTarga::Pack_Texel (const UnpackedTexelStruct &unpackedtexel, unsigned char *packedtexelptr, unsigned packedbytespertexel)
  565. {
  566. switch (packedbytespertexel) {
  567. case 4:
  568. *(packedtexelptr + 0) = unpackedtexel.Byte [0];
  569. *(packedtexelptr + 1) = unpackedtexel.Byte [1];
  570. *(packedtexelptr + 2) = unpackedtexel.Byte [2];
  571. *(packedtexelptr + 3) = unpackedtexel.Byte [3];
  572. break;
  573. case 3:
  574. // Pack to ordering RGB. Lose Alpha.
  575. *(packedtexelptr + 0) = unpackedtexel.Byte [1];
  576. *(packedtexelptr + 1) = unpackedtexel.Byte [2];
  577. *(packedtexelptr + 2) = unpackedtexel.Byte [3];
  578. break;
  579. case 2:
  580. {
  581. unsigned a, r, g, b;
  582. // Pack to ordering ARGB. Round Alpha, Red, Green, Blue.
  583. a = unpackedtexel.Byte [0] >> 7;
  584. r = MIN (0x1f, (unpackedtexel.Byte [1] >> 3) + ((unpackedtexel.Byte [1] & 0x4) >> 2));
  585. g = MIN (0x1f, (unpackedtexel.Byte [2] >> 3) + ((unpackedtexel.Byte [2] & 0x4) >> 2));
  586. b = MIN (0x1f, (unpackedtexel.Byte [3] >> 3) + ((unpackedtexel.Byte [3] & 0x4) >> 2));
  587. *((unsigned short*) packedtexelptr) = ((a << 15) | (r << 10) | (g << 5) | b);
  588. }
  589. break;
  590. default:
  591. // Unrecognized byte count.
  592. ASSERT (0);
  593. break;
  594. }
  595. }
  596. #endif // LIGHTMAPPACKER_H