lookuptable.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. ** Command & Conquer Generals(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. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWPhys *
  23. * *
  24. * $Archive:: /Commando/Code/wwmath/lookuptable.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Byon_g $*
  29. * *
  30. * $Modtime:: 7/23/01 6:18p $*
  31. * *
  32. * $Revision:: 5 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "lookuptable.h"
  38. #include "curve.h"
  39. #include "wwfile.h"
  40. #include "ffactory.h"
  41. #include "chunkio.h"
  42. #include "persistfactory.h"
  43. #include "vector2.h"
  44. /*
  45. ** Static members
  46. */
  47. RefMultiListClass<LookupTableClass> LookupTableMgrClass::Tables;
  48. /*
  49. ** Save-Load stuff. Lookup tables are basically saved 1D curve classes. They are turned
  50. ** into tables at load time. For future expansion, the curve is wrapped in a chunk.
  51. */
  52. enum
  53. {
  54. LOOKUPTABLE_CHUNK_CURVE = 03071200,
  55. LOOKUPTABLE_CHUNK_EXTENTS,
  56. };
  57. /***********************************************************************************************
  58. **
  59. ** LookupTableClass Implementation
  60. **
  61. ***********************************************************************************************/
  62. LookupTableClass::LookupTableClass(int sample_count) :
  63. MinInputValue(0.0f),
  64. MaxInputValue(0.0f),
  65. OutputSamples(sample_count)
  66. {
  67. }
  68. LookupTableClass::~LookupTableClass(void)
  69. {
  70. }
  71. void LookupTableClass::Init(const char * name,Curve1DClass * curve)
  72. {
  73. // copy the name
  74. Name = name;
  75. // Store the min and max input values for the table
  76. curve->Get_Key(0,NULL,&MinInputValue,NULL);
  77. curve->Get_Key(curve->Key_Count()-1,NULL,&MaxInputValue,NULL);
  78. OOMaxMinusMin = 1.0f / (MaxInputValue - MinInputValue);
  79. // Sample the curve and store the output values
  80. for (int i=0; i<OutputSamples.Length(); i++) {
  81. float x = MinInputValue + (MaxInputValue - MinInputValue) * (float)i / (float)(OutputSamples.Length() - 1);
  82. float y;
  83. curve->Evaluate(x,&y);
  84. OutputSamples[i] = y;
  85. }
  86. }
  87. /***********************************************************************************************
  88. **
  89. ** LookupTableManager Implementation
  90. **
  91. ***********************************************************************************************/
  92. void LookupTableMgrClass::Init(void)
  93. {
  94. // create a default table that the user can use in an emergency
  95. LookupTableClass * default_table = NEW_REF(LookupTableClass,(2));
  96. LinearCurve1DClass * default_curve = W3DNEW LinearCurve1DClass;
  97. default_curve->Add_Key(0.5f,0.0f);
  98. default_curve->Add_Key(0.5f,1.0f);
  99. default_table->Init("DefaultTable",default_curve);
  100. Add_Table(default_table);
  101. delete default_curve;
  102. default_table->Release_Ref();
  103. }
  104. void LookupTableMgrClass::Shutdown(void)
  105. {
  106. Reset();
  107. }
  108. void LookupTableMgrClass::Reset(void)
  109. {
  110. while (Tables.Peek_Head() != NULL) {
  111. Tables.Release_Head();
  112. }
  113. }
  114. bool LookupTableMgrClass::Add_Table(LookupTableClass * table)
  115. {
  116. return Tables.Add(table);
  117. }
  118. bool LookupTableMgrClass::Remove_Table(LookupTableClass * table)
  119. {
  120. return Tables.Remove(table);
  121. }
  122. LookupTableClass * LookupTableMgrClass::Get_Table(const char * name,bool try_to_load)
  123. {
  124. // check if we already have this table loaded...
  125. RefMultiListIterator<LookupTableClass> it(&Tables);
  126. for (it.First(); !it.Is_Done(); it.Next()) {
  127. if (stricmp(it.Peek_Obj()->Get_Name(),name) == 0) {
  128. return it.Get_Obj(); // add a reference for the user...
  129. }
  130. }
  131. // otherwise we can try to load it.
  132. LookupTableClass * new_table = NULL;
  133. if (try_to_load) {
  134. FileClass * file = _TheFileFactory->Get_File(name);
  135. if (file && file->Open()) {
  136. ChunkLoadClass cload(file);
  137. Curve1DClass * curve = NULL;
  138. Load_Table_Desc(cload,&curve);
  139. if (curve != NULL) {
  140. new_table = NEW_REF(LookupTableClass,());
  141. new_table->Init(name,curve);
  142. Add_Table(new_table);
  143. delete curve;
  144. }
  145. }
  146. _TheFileFactory->Return_File(file);
  147. }
  148. return new_table; // constructor ref is returned to user.
  149. }
  150. void LookupTableMgrClass::Save_Table_Desc
  151. (
  152. ChunkSaveClass & csave,
  153. Curve1DClass * curve,
  154. const Vector2 & min_corner,
  155. const Vector2 & max_corner
  156. )
  157. {
  158. // save the curve
  159. csave.Begin_Chunk(LOOKUPTABLE_CHUNK_CURVE);
  160. csave.Begin_Chunk(curve->Get_Factory().Chunk_ID());
  161. curve->Get_Factory().Save(csave,curve);
  162. csave.End_Chunk();
  163. csave.End_Chunk();
  164. // save the extents
  165. csave.Begin_Chunk(LOOKUPTABLE_CHUNK_EXTENTS);
  166. csave.Write(&(min_corner.X),sizeof(float));
  167. csave.Write(&(min_corner.Y),sizeof(float));
  168. csave.Write(&(max_corner.X),sizeof(float));
  169. csave.Write(&(max_corner.Y),sizeof(float));
  170. csave.End_Chunk();
  171. }
  172. void LookupTableMgrClass::Load_Table_Desc
  173. (
  174. ChunkLoadClass & cload,
  175. Curve1DClass ** curve_ptr,
  176. Vector2 * set_min_corner,
  177. Vector2 * set_max_corner
  178. )
  179. {
  180. *curve_ptr = NULL;
  181. PersistFactoryClass * factory;
  182. float xmin,xmax;
  183. float ymin,ymax;
  184. xmin = xmax = ymin = ymax = 0.0f;
  185. while (cload.Open_Chunk()) {
  186. switch(cload.Cur_Chunk_ID()) {
  187. case LOOKUPTABLE_CHUNK_CURVE:
  188. cload.Open_Chunk();
  189. factory = SaveLoadSystemClass::Find_Persist_Factory(cload.Cur_Chunk_ID());
  190. WWASSERT(factory != NULL);
  191. if (factory != NULL) {
  192. *curve_ptr = (Curve1DClass *)factory->Load(cload);
  193. }
  194. cload.Close_Chunk();
  195. break;
  196. case LOOKUPTABLE_CHUNK_EXTENTS:
  197. cload.Read(&xmin,sizeof(xmin));
  198. cload.Read(&ymin,sizeof(ymin));
  199. cload.Read(&xmax,sizeof(xmax));
  200. cload.Read(&ymax,sizeof(ymax));
  201. break;
  202. default:
  203. WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",__FILE__,__LINE__));
  204. break;
  205. }
  206. cload.Close_Chunk();
  207. }
  208. if (set_min_corner != NULL) {
  209. set_min_corner->Set(xmin,ymin);
  210. }
  211. if (set_max_corner != NULL) {
  212. set_max_corner->Set(xmax,ymax);
  213. }
  214. }