mapper.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  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. *** 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 : G *
  23. * *
  24. * $Archive:: /VSS_Sync/ww3d2/mapper.cpp $*
  25. * *
  26. * $Author:: Vss_sync $*
  27. * *
  28. * $Modtime:: 10/29/01 3:30p $*
  29. * *
  30. * $Revision:: 34 $*
  31. * *
  32. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  33. #include "mapper.h"
  34. #include "ww3d.h"
  35. #include "ini.h"
  36. #include "chunkio.h"
  37. #include "w3derr.h"
  38. #include "meshmatdesc.h"
  39. #include "dx8wrapper.h"
  40. #include "wwdebug.h"
  41. #include "matinfo.h"
  42. #include "rendobj.h"
  43. #include "mesh.h"
  44. #include <random.h>
  45. Random4Class rand4;
  46. inline DWORD F2DW( FLOAT f ) { return *((DWORD*)&f); }
  47. // HY 1/26/01
  48. // Rewritten to use DX 8 texture matrices
  49. TextureMapperClass::TextureMapperClass(unsigned int stage)
  50. {
  51. Stage = stage;
  52. if (Stage >= MeshMatDescClass::MAX_TEX_STAGES) Stage = MeshMatDescClass::MAX_TEX_STAGES - 1;
  53. }
  54. LinearOffsetTextureMapperClass::LinearOffsetTextureMapperClass(const Vector2 &offset_per_sec, const Vector2 &scale, unsigned int stage) :
  55. ScaleTextureMapperClass(scale, stage),
  56. LastUsedSyncTime(WW3D::Get_Sync_Time())
  57. {
  58. CurrentUVOffset.X = 0.0f;
  59. CurrentUVOffset.Y = 0.0f;
  60. // HY 5/16/01
  61. // This is horrible disgusting legacy from the unmentionable API we used before
  62. // leaving it unchanged because the artists have worked around it
  63. UVOffsetDeltaPerMS = offset_per_sec * -0.001f;
  64. }
  65. LinearOffsetTextureMapperClass::LinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  66. ScaleTextureMapperClass(ini,section,stage),
  67. LastUsedSyncTime(WW3D::Get_Sync_Time())
  68. {
  69. CurrentUVOffset.X = 0.0f;
  70. CurrentUVOffset.Y = 0.0f;
  71. float u_offset_per_sec = ini.Get_Float(section, "UPerSec", 0.0f);
  72. float v_offset_per_sec = ini.Get_Float(section, "VPerSec", 0.0f);
  73. UVOffsetDeltaPerMS = Vector2(u_offset_per_sec, v_offset_per_sec) * -0.001f;
  74. }
  75. LinearOffsetTextureMapperClass::LinearOffsetTextureMapperClass(const LinearOffsetTextureMapperClass & src) :
  76. ScaleTextureMapperClass(src),
  77. UVOffsetDeltaPerMS(src.UVOffsetDeltaPerMS),
  78. LastUsedSyncTime(WW3D::Get_Sync_Time())
  79. {
  80. CurrentUVOffset.X = 0.0f;
  81. CurrentUVOffset.Y = 0.0f;
  82. }
  83. void LinearOffsetTextureMapperClass::Apply(int uv_array_index)
  84. {
  85. unsigned int delta = WW3D::Get_Sync_Time() - LastUsedSyncTime;
  86. float del = (float)delta;
  87. float offset_u = CurrentUVOffset.X + UVOffsetDeltaPerMS.X * del;
  88. float offset_v = CurrentUVOffset.Y + UVOffsetDeltaPerMS.Y * del;
  89. // ensure both coordinates of offset are in [0, 1] range:
  90. offset_u = offset_u - WWMath::Floor(offset_u);
  91. offset_v = offset_v - WWMath::Floor(offset_v);
  92. // Set up the offset matrix
  93. Matrix3D m(true);
  94. // According to the docs this should work since its 2D
  95. // otherwise change to translate
  96. m[0].Z=offset_u;
  97. m[0].X=Scale.X;
  98. m[1].Z=offset_v;
  99. m[1].Y=Scale.Y;
  100. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  101. // Disable Texgen
  102. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU | uv_array_index);
  103. // Tell rasterizer to expect 2D texture coordinates
  104. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  105. // Update state
  106. CurrentUVOffset.X = offset_u;
  107. CurrentUVOffset.Y = offset_v;
  108. LastUsedSyncTime = WW3D::Get_Sync_Time();
  109. }
  110. // Scale mapper
  111. // HY 5/16/01
  112. ScaleTextureMapperClass::ScaleTextureMapperClass(const Vector2 &scale, unsigned int stage) :
  113. TextureMapperClass(stage),
  114. Scale(scale)
  115. {
  116. }
  117. ScaleTextureMapperClass::ScaleTextureMapperClass(unsigned int stage) :
  118. TextureMapperClass(stage),
  119. Scale(1.0f,1.0f)
  120. {
  121. }
  122. ScaleTextureMapperClass::ScaleTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  123. TextureMapperClass(stage)
  124. {
  125. Scale.U = ini.Get_Float(section, "UScale", 1.0f);
  126. Scale.V = ini.Get_Float(section, "VScale", 1.0f);
  127. }
  128. ScaleTextureMapperClass::ScaleTextureMapperClass(const ScaleTextureMapperClass & src) :
  129. TextureMapperClass(src),
  130. Scale(src.Scale)
  131. {
  132. }
  133. void ScaleTextureMapperClass::Apply(int uv_array_index)
  134. {
  135. // Set up the scale matrix
  136. Matrix3D m(true);
  137. m[0].X=Scale.U;
  138. m[1].Y=Scale.V;
  139. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  140. // Disable Texgen
  141. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU | uv_array_index);
  142. // Tell rasterizer to expect 2D texture coordinates
  143. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  144. }
  145. // Grid Mapper
  146. // HY 5/16/01
  147. GridTextureMapperClass::GridTextureMapperClass(float fps, unsigned int gridwidth_log2, unsigned int stage) :
  148. TextureMapperClass(stage)
  149. {
  150. LastFrame = 0;
  151. initialize(fps, gridwidth_log2);
  152. }
  153. GridTextureMapperClass::GridTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  154. TextureMapperClass(stage)
  155. {
  156. float fps = ini.Get_Float(section,"FPS", 1.0f);
  157. unsigned int gridwidth_log2 = ini.Get_Int(section,"Log2Width", 1);
  158. LastFrame=ini.Get_Int(section,"Last",0);
  159. initialize(fps, gridwidth_log2);
  160. }
  161. GridTextureMapperClass::GridTextureMapperClass(const GridTextureMapperClass & src) :
  162. TextureMapperClass(src),
  163. Sign(src.Sign),
  164. MSPerFrame(src.MSPerFrame),
  165. OOGridWidth(src.OOGridWidth),
  166. GridWidthLog2(src.GridWidthLog2),
  167. LastFrame(src.LastFrame)
  168. {
  169. Reset();
  170. }
  171. void GridTextureMapperClass::Apply(int uv_array_index)
  172. {
  173. update_temporal_state();
  174. float u_offset, v_offset;
  175. calculate_uv_offset(&u_offset, &v_offset);
  176. // Set up the offset matrix
  177. Matrix3D m(true);
  178. // According to the docs this should work since its 2D
  179. // otherwise change to translate
  180. m[0].Z = u_offset;
  181. m[1].Z = v_offset;
  182. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage), m);
  183. // Disable Texgen
  184. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | uv_array_index);
  185. // Tell rasterizer to expect 2D texture coordinates
  186. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
  187. }
  188. void GridTextureMapperClass::Reset(void)
  189. {
  190. Remainder = 0;
  191. CurrentFrame = Sign == -1 ? (1 << (GridWidthLog2 + GridWidthLog2)) - 1 : 0;
  192. LastUsedSyncTime = WW3D::Get_Sync_Time();
  193. }
  194. void GridTextureMapperClass::Set_Frame_Per_Second(float fps)
  195. {
  196. initialize(fps, GridWidthLog2);
  197. }
  198. void GridTextureMapperClass::initialize(float fps, unsigned int gridwidth_log2)
  199. {
  200. unsigned int grid_width = (1 << gridwidth_log2);
  201. if (LastFrame == 0) LastFrame = (grid_width * grid_width);
  202. LastUsedSyncTime = WW3D::Get_Sync_Time();
  203. GridWidthLog2 = gridwidth_log2;
  204. OOGridWidth = 1.0f / (float)(grid_width);
  205. if (fps == 0.0f) {
  206. // Value of MSPerFrame does not matter as long as it is not 0 - sign will multiply results,
  207. // zeroing them out.
  208. Sign = 0;
  209. MSPerFrame = 1;
  210. CurrentFrame = 0;
  211. } else if (fps < 0.0f) {
  212. Sign = -1;
  213. MSPerFrame = (unsigned int)(1000.0f / fabs(fps));
  214. CurrentFrame = LastFrame - 1;
  215. } else {
  216. Sign = 1;
  217. MSPerFrame = (unsigned int)(1000.0f / fabs(fps));
  218. CurrentFrame = 0;
  219. }
  220. Remainder = 0;
  221. }
  222. void GridTextureMapperClass::update_temporal_state(void)
  223. {
  224. unsigned int now = WW3D::Get_Sync_Time();
  225. unsigned int delta = now - LastUsedSyncTime;
  226. Remainder += delta;
  227. LastUsedSyncTime = now;
  228. int new_frame = (int)CurrentFrame + ((int)(Remainder / MSPerFrame) * Sign);
  229. new_frame=new_frame % LastFrame;
  230. if (new_frame<0) {
  231. CurrentFrame=LastFrame+new_frame;
  232. } else {
  233. CurrentFrame=(unsigned int) new_frame;
  234. }
  235. Remainder = Remainder % MSPerFrame;
  236. }
  237. void GridTextureMapperClass::calculate_uv_offset(float * u_offset, float * v_offset)
  238. {
  239. unsigned int row_mask = ~(0xFFFFFFFF << GridWidthLog2);
  240. unsigned int col_mask = row_mask << GridWidthLog2;
  241. unsigned int x = CurrentFrame & row_mask;
  242. unsigned int y = (CurrentFrame & col_mask) >> GridWidthLog2;
  243. *u_offset = x * OOGridWidth;
  244. *v_offset = y * OOGridWidth;
  245. }
  246. // Rotate Mapper
  247. // HY 5/16/01
  248. RotateTextureMapperClass::RotateTextureMapperClass(float rad_per_sec, const Vector2 &center, unsigned int stage) :
  249. ScaleTextureMapperClass(stage),
  250. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  251. CurrentAngle(0.0f),
  252. RadiansPerMilliSec(rad_per_sec/1000.0f),
  253. Center(center)
  254. {
  255. }
  256. RotateTextureMapperClass::RotateTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  257. ScaleTextureMapperClass(ini,section,stage),
  258. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  259. CurrentAngle(0.0f)
  260. {
  261. RadiansPerMilliSec=2*WWMATH_PI*ini.Get_Float(section,"Speed",0.1f)/1000.0f;
  262. Center.U=ini.Get_Float(section,"UCenter",0.0f);
  263. Center.V=ini.Get_Float(section,"VCenter",0.0f);
  264. }
  265. RotateTextureMapperClass::RotateTextureMapperClass(const RotateTextureMapperClass & src) :
  266. ScaleTextureMapperClass(src),
  267. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  268. RadiansPerMilliSec(src.RadiansPerMilliSec),
  269. CurrentAngle(0.0f),
  270. Center(src.Center)
  271. {
  272. }
  273. void RotateTextureMapperClass::Apply(int uv_array_index)
  274. {
  275. unsigned int now = WW3D::Get_Sync_Time();
  276. unsigned int delta = now - LastUsedSyncTime;
  277. LastUsedSyncTime=now;
  278. CurrentAngle+=RadiansPerMilliSec * delta;
  279. CurrentAngle=fmodf(CurrentAngle,2*WWMATH_PI);
  280. if (CurrentAngle<0.0f) CurrentAngle+=2*WWMATH_PI;
  281. // Set up the rotation matrix
  282. float c,s;
  283. c=WWMath::Cos(CurrentAngle);
  284. s=WWMath::Sin(CurrentAngle);
  285. Matrix4 m(true);
  286. // subtract center
  287. // rotate
  288. // add center
  289. // then scale
  290. m[0].Set(Scale.X*c,-Scale.X*s,-Scale.X*(c*Center.U-s*Center.V-Center.U),0.0f);
  291. m[1].Set(Scale.Y*s,Scale.Y*c,-Scale.Y*(s*Center.U+c*Center.V-Center.V),0.0f);
  292. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  293. // Disable Texgen
  294. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU | uv_array_index);
  295. // Tell rasterizer to expect 2D texture coordinates
  296. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  297. }
  298. // SineLinearOffset Mapper
  299. // HY 5/16/01
  300. SineLinearOffsetTextureMapperClass::SineLinearOffsetTextureMapperClass(const Vector3 &uafp, const Vector3 &vafp, unsigned int stage) :
  301. TextureMapperClass(stage),
  302. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  303. UAFP(uafp),
  304. VAFP(vafp),
  305. CurrentAngle(0.0f)
  306. {
  307. }
  308. SineLinearOffsetTextureMapperClass::SineLinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  309. TextureMapperClass(stage),
  310. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  311. CurrentAngle(0.0f)
  312. {
  313. UAFP.X = ini.Get_Float(section, "UAmp", 1.0f);
  314. UAFP.Y = ini.Get_Float(section, "UFreq", 1.0f);
  315. UAFP.Z = ini.Get_Float(section, "UPhase", 0.0f);
  316. VAFP.X = ini.Get_Float(section, "VAmp", 1.0f);
  317. VAFP.Y = ini.Get_Float(section, "VFreq", 1.0f);
  318. VAFP.Z = ini.Get_Float(section, "VPhase", 0.0f);
  319. }
  320. SineLinearOffsetTextureMapperClass::SineLinearOffsetTextureMapperClass(const SineLinearOffsetTextureMapperClass & src) :
  321. TextureMapperClass(src),
  322. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  323. UAFP(src.UAFP),
  324. VAFP(src.VAFP),
  325. CurrentAngle(0.0f)
  326. {
  327. }
  328. void SineLinearOffsetTextureMapperClass::Apply(int uv_array_index)
  329. {
  330. unsigned int now = WW3D::Get_Sync_Time();
  331. unsigned int delta = now - LastUsedSyncTime;
  332. LastUsedSyncTime=now;
  333. const float ms_to_radians=2*WWMATH_PI/1000.0f;
  334. CurrentAngle+=delta*ms_to_radians;
  335. float offset_u=UAFP.X*sin(UAFP.Y*CurrentAngle+UAFP.Z*WWMATH_PI);
  336. float offset_v=VAFP.X*sin(VAFP.Y*CurrentAngle+VAFP.Z*WWMATH_PI);
  337. // ensure both coordinates of offset are in [0, 1] range:
  338. offset_u = offset_u - WWMath::Floor(offset_u);
  339. offset_v = offset_v - WWMath::Floor(offset_v);
  340. // Set up the offset matrix
  341. Matrix3D m(true);
  342. // According to the docs this should work since its 2D
  343. // otherwise change to translate
  344. m[0].Z=offset_u;
  345. m[1].Z=offset_v;
  346. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  347. // Disable Texgen
  348. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU | uv_array_index);
  349. // Tell rasterizer to expect 2D texture coordinates
  350. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  351. }
  352. // StepLinearOffset Mapper
  353. // HY 5/16/01
  354. StepLinearOffsetTextureMapperClass::StepLinearOffsetTextureMapperClass(const Vector2 &step, float steps_per_sec, unsigned int stage) :
  355. TextureMapperClass(stage),
  356. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  357. Step(step),
  358. StepsPerMilliSec(steps_per_sec/1000.0f),
  359. CurrentStep(0.0f,0.0f),
  360. Remainder(0)
  361. {
  362. }
  363. StepLinearOffsetTextureMapperClass::StepLinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  364. TextureMapperClass(stage),
  365. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  366. CurrentStep(0.0f,0.0f),
  367. Remainder(0)
  368. {
  369. Step.U = ini.Get_Float(section, "UStep", 0.0f);
  370. Step.V = ini.Get_Float(section, "VStep", 0.0f);
  371. StepsPerMilliSec = ini.Get_Float(section, "SPS", 0.0f)/1000.0f;
  372. }
  373. StepLinearOffsetTextureMapperClass::StepLinearOffsetTextureMapperClass(const StepLinearOffsetTextureMapperClass & src) :
  374. TextureMapperClass(src),
  375. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  376. Step(src.Step),
  377. StepsPerMilliSec(src.StepsPerMilliSec),
  378. CurrentStep(0.0f,0.0f),
  379. Remainder(0)
  380. {
  381. }
  382. void StepLinearOffsetTextureMapperClass::Apply(int uv_array_index)
  383. {
  384. unsigned int now = WW3D::Get_Sync_Time();
  385. unsigned int delta = now - LastUsedSyncTime;
  386. LastUsedSyncTime=now;
  387. Remainder+=delta;
  388. int num_steps=(int) (StepsPerMilliSec*Remainder);
  389. if (num_steps!=0)
  390. {
  391. CurrentStep+=Step*num_steps;
  392. Remainder-=num_steps/(float)StepsPerMilliSec;
  393. }
  394. // ensure both coordinates of offset are in [0, 1] range:
  395. CurrentStep.U -= WWMath::Floor(CurrentStep.U);
  396. CurrentStep.V -= WWMath::Floor(CurrentStep.V);
  397. // Set up the offset matrix
  398. Matrix3D m(true);
  399. // According to the docs this should work since its 2D
  400. // otherwise change to translate
  401. m[0].Z=CurrentStep.U;
  402. m[1].Z=CurrentStep.V;
  403. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  404. // Disable Texgen
  405. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU | uv_array_index);
  406. // Tell rasterizer to expect 2D texture coordinates
  407. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  408. }
  409. void StepLinearOffsetTextureMapperClass::Reset(void)
  410. {
  411. LastUsedSyncTime = WW3D::Get_Sync_Time();
  412. CurrentStep.Set(0.0f,0.0f);
  413. Remainder=0;
  414. }
  415. // ZigZagLinearOffset Mapper
  416. // HY 5/16/01
  417. ZigZagLinearOffsetTextureMapperClass::ZigZagLinearOffsetTextureMapperClass(const Vector2 &speed, float period, unsigned int stage) :
  418. TextureMapperClass(stage),
  419. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  420. Speed(speed/1000.0f),
  421. Period(period*1000.0f),
  422. Remainder(0)
  423. {
  424. // since we're zigzagging, a negative period is the same as a positive one
  425. if (Period<0.0f) Period=-Period;
  426. Half_Period=0.5f*Period;
  427. }
  428. ZigZagLinearOffsetTextureMapperClass::ZigZagLinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  429. TextureMapperClass(stage),
  430. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  431. Remainder(0)
  432. {
  433. Speed.U = ini.Get_Float(section, "UPerSec", 0.0f)/1000.0f;
  434. Speed.V = ini.Get_Float(section, "VPerSec", 0.0f)/1000.0f;
  435. Period = ini.Get_Float(section, "Period", 0.0f)*1000.0f;
  436. if (Period<0.0f) Period=-Period;
  437. Half_Period=0.5f*Period;
  438. }
  439. ZigZagLinearOffsetTextureMapperClass::ZigZagLinearOffsetTextureMapperClass(const ZigZagLinearOffsetTextureMapperClass & src) :
  440. TextureMapperClass(src),
  441. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  442. Speed(src.Speed),
  443. Period(src.Period),
  444. Half_Period(src.Half_Period),
  445. Remainder(0)
  446. {
  447. }
  448. void ZigZagLinearOffsetTextureMapperClass::Apply(int uv_array_index)
  449. {
  450. unsigned int now = WW3D::Get_Sync_Time();
  451. unsigned int delta = now - LastUsedSyncTime;
  452. LastUsedSyncTime=now;
  453. Remainder+=delta;
  454. float offset_u=0.0f;
  455. float offset_v=0.0f;
  456. if (Period>0.0f)
  457. {
  458. // figure out the fractional number of periods
  459. int num_periods=(int) (Remainder/Period);
  460. Remainder-=num_periods*Period;
  461. float time=0.0f;
  462. if (Remainder>Half_Period) {
  463. time=Period-Remainder;
  464. } else {
  465. time=Remainder;
  466. }
  467. offset_u=Speed.U * time;
  468. offset_v=Speed.V * time;
  469. }
  470. // ensure both coordinates of offset are in [0, 1] range:
  471. offset_u = offset_u - WWMath::Floor(offset_u);
  472. offset_v = offset_v - WWMath::Floor(offset_v);
  473. // Set up the offset matrix
  474. Matrix3D m(true);
  475. // According to the docs this should work since its 2D
  476. // otherwise change to translate
  477. m[0].Z=offset_u;
  478. m[1].Z=offset_v;
  479. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  480. // Disable Texgen
  481. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU | uv_array_index);
  482. // Tell rasterizer to expect 2D texture coordinates
  483. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  484. }
  485. void ZigZagLinearOffsetTextureMapperClass::Reset(void)
  486. {
  487. LastUsedSyncTime = WW3D::Get_Sync_Time();
  488. Remainder=0;
  489. }
  490. // ----------------------------------------------------------------------------
  491. //
  492. // Environment mapper calculates the texture coordinates based on
  493. // transformed normals
  494. //
  495. // ----------------------------------------------------------------------------
  496. void ClassicEnvironmentMapperClass::Apply(int uv_array_index)
  497. {
  498. // The canonical environment map
  499. // scale the normal by (.5,.5) and add (.5,.5) to move it to (0,1) range
  500. // and ignore the Z component
  501. Matrix3D matenv( 0.5f, 0.0f, 0.0f, 0.5f,
  502. 0.0f, 0.5f, 0.0f, 0.5f,
  503. 0.0f, 0.0f, 1.0f, 0.0f );
  504. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),matenv);
  505. // Get camera normals
  506. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  507. // Tell rasterizer to expect 2D matrices
  508. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  509. }
  510. void EnvironmentMapperClass::Apply(int uv_array_index)
  511. {
  512. // The canonical environment map
  513. // scale the normal by (.25,.25) and add (.5,.5) to move it to (0,1) range
  514. // the additional half is to fudge the 1+z normalization factor
  515. // and ignore the Z component
  516. Matrix3D matenv( 0.25f, 0.0f, 0.0f, 0.5f,
  517. 0.0f, 0.25f, 0.0f, 0.5f,
  518. 0.0f, 0.0f, 1.0f, 0.0f );
  519. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),matenv);
  520. // Get camera reflection vector
  521. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
  522. // Tell rasterizer to expect 2D matrices
  523. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  524. }
  525. EdgeMapperClass::EdgeMapperClass(unsigned int stage) :
  526. TextureMapperClass(stage),
  527. VSpeed(0.0f),
  528. UseReflect(false),
  529. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  530. VOffset(0.0f)
  531. {
  532. }
  533. EdgeMapperClass::EdgeMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  534. TextureMapperClass(stage),
  535. VSpeed(0.0f),
  536. UseReflect(false),
  537. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  538. VOffset(0.0f)
  539. {
  540. VSpeed=ini.Get_Float(section, "VPerSec", 0.0f);
  541. VOffset=ini.Get_Float(section, "VStart", 0.0f);
  542. UseReflect=ini.Get_Bool(section, "UseReflect", false);
  543. }
  544. EdgeMapperClass::EdgeMapperClass(const EdgeMapperClass & src):
  545. TextureMapperClass(src.Stage),
  546. VSpeed(src.VSpeed),
  547. UseReflect(src.UseReflect),
  548. VOffset(src.VOffset),
  549. LastUsedSyncTime(WW3D::Get_Sync_Time())
  550. {
  551. }
  552. void EdgeMapperClass::Apply(int uv_array_index)
  553. {
  554. unsigned int now=WW3D::Get_Sync_Time();
  555. float delta=(now-LastUsedSyncTime)*0.001f;
  556. LastUsedSyncTime=now;
  557. VOffset+=delta*VSpeed;
  558. VOffset-=WWMath::Floor(VOffset);
  559. // takes the Z component and
  560. // uses it to index the texture
  561. Matrix3D matenv( 0.0f, 0.0f, 0.5f, 0.5f,
  562. 0.0f, 0.0f, 0.0f, VOffset,
  563. 0.0f, 0.0f, 1.0f, 0.0f );
  564. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),matenv);
  565. // Get camera reflection vector
  566. if (UseReflect)
  567. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
  568. else
  569. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  570. // Tell rasterizer to expect 2D matrices
  571. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  572. }
  573. void EdgeMapperClass::Reset(void)
  574. {
  575. LastUsedSyncTime = WW3D::Get_Sync_Time();
  576. VOffset = 0.0f;
  577. }
  578. void WSClassicEnvironmentMapperClass::Apply(int uv_array_index)
  579. {
  580. // The canonical environment map
  581. // scale the normal by (.5,.5) and add (.5,.5) to move it to (0,1) range
  582. // and ignore the Z component
  583. Matrix3D matenv( 0.5f, 0.0f, 0.0f, 0.5f,
  584. 0.0f, 0.5f, 0.0f, 0.5f,
  585. 0.0f, 0.0f, 1.0f, 0.0f );
  586. // multiply by inverse of view transform
  587. Matrix4 mat;
  588. DX8Wrapper::Get_Transform(D3DTS_VIEW,mat);
  589. Matrix3D mat2(mat[0].X,mat[1].X,mat[2].X,0.0f,
  590. mat[0].Y,mat[1].Y,mat[2].Y,0.0f,
  591. mat[0].Z,mat[1].Z,mat[2].Z,0.0f);
  592. matenv=matenv*mat2;
  593. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),matenv);
  594. // Get camera normals
  595. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  596. // Tell rasterizer to expect 2D matrices
  597. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  598. }
  599. void WSEnvironmentMapperClass::Apply(int uv_array_index)
  600. {
  601. // The canonical environment map
  602. // scale the normal by (.25,.25) and add (.5,.5) to move it to (0,1) range
  603. // the additional half is to fudge the 1+z normalization factor
  604. // and ignore the Z component
  605. Matrix3D matenv( 0.25f, 0.0f, 0.0f, 0.5f,
  606. 0.0f, 0.25f, 0.0f, 0.5f,
  607. 0.0f, 0.0f, 1.0f, 0.0f );
  608. // multiply by inverse of view transform
  609. Matrix4 mat;
  610. DX8Wrapper::Get_Transform(D3DTS_VIEW,mat);
  611. Matrix3D mat2(mat[0].X,mat[1].X,mat[2].X,0.0f,
  612. mat[0].Y,mat[1].Y,mat[2].Y,0.0f,
  613. mat[0].Z,mat[1].Z,mat[2].Z,0.0f);
  614. matenv=matenv*mat2;
  615. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),matenv);
  616. // Get camera reflection
  617. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
  618. // Tell rasterizer to expect 2D matrices
  619. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  620. }
  621. void ScreenMapperClass::Apply(int uv_array_index)
  622. {
  623. unsigned int delta = WW3D::Get_Sync_Time() - LastUsedSyncTime;
  624. float del = (float)delta;
  625. float offset_u = CurrentUVOffset.X + UVOffsetDeltaPerMS.X * del;
  626. float offset_v = CurrentUVOffset.Y + UVOffsetDeltaPerMS.Y * del;
  627. // ensure both coordinates of offset are in [0, 1] range:
  628. offset_u = offset_u - WWMath::Floor(offset_u);
  629. offset_v = offset_v - WWMath::Floor(offset_v);
  630. // multiply by projection matrix
  631. // followed by scale and translation
  632. Matrix4 mat;
  633. DX8Wrapper::Get_Transform(D3DTS_PROJECTION,mat);
  634. mat[0]*=Scale.X; // entire row since we're pre-multiplying
  635. mat[1]*=Scale.Y;
  636. Vector4 last(mat[3]); // this gets the w
  637. last*=offset_u; // multiply by w because the projected flag will divide by w
  638. mat[0]+=last;
  639. last=mat[3];
  640. last*=offset_v;
  641. mat[1]+=last;
  642. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),mat);
  643. // Get camera space position
  644. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEPOSITION);
  645. // Tell rasterizer what to expect
  646. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_PROJECTED | D3DTTFF_COUNT3);
  647. // Update state
  648. CurrentUVOffset.X = offset_u;
  649. CurrentUVOffset.Y = offset_v;
  650. LastUsedSyncTime = WW3D::Get_Sync_Time();
  651. }
  652. void GridClassicEnvironmentMapperClass::Apply(int uv_array_index)
  653. {
  654. update_temporal_state();
  655. float u_offset, v_offset;
  656. calculate_uv_offset(&u_offset, &v_offset);
  657. float del = 0.5f * OOGridWidth;
  658. // Set up the offset matrix
  659. Matrix3D tform( del, 0.0f, 0.0f, u_offset + del,
  660. 0.0f, del, 0.0f, v_offset + del,
  661. 0.0f, 0.0f, 1.0f, 0.0f );
  662. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),tform);
  663. // Get camera normals
  664. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  665. // Tell rasterizer to expect 2D matrices
  666. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  667. }
  668. void GridEnvironmentMapperClass::Apply(int uv_array_index)
  669. {
  670. update_temporal_state();
  671. float u_offset, v_offset;
  672. calculate_uv_offset(&u_offset, &v_offset);
  673. // Set up the offset matrix
  674. Matrix3D m(true);
  675. // According to the docs this should work since its 2D
  676. // otherwise change to translate
  677. m[0].Z = u_offset;
  678. m[1].Z = v_offset;
  679. float del=0.5f * OOGridWidth;
  680. // Set up the offset matrix
  681. Matrix3D tform( del, 0.0f, 0.0f, u_offset + del,
  682. 0.0f, del, 0.0f, v_offset + del,
  683. 0.0f, 0.0f, 1.0f, 0.0f );
  684. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),tform);
  685. // Get camera space reflection
  686. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
  687. // Tell rasterizer to expect 2D matrices
  688. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  689. }
  690. RandomTextureMapperClass::RandomTextureMapperClass(float fps, unsigned int stage):
  691. TextureMapperClass(stage),
  692. FPMS(fps/1000.0f),
  693. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  694. Speed(0.0f,0.0f),
  695. Remainder(0)
  696. {
  697. randomize();
  698. }
  699. RandomTextureMapperClass::RandomTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage):
  700. TextureMapperClass(stage),
  701. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  702. Remainder(0)
  703. {
  704. FPMS = ini.Get_Float(section, "FPS", 0.0f)/1000.0f;
  705. Speed.U = ini.Get_Float(section, "UPerSec", 0.0f)/1000.0f;
  706. Speed.V = ini.Get_Float(section, "VPerSec", 0.0f)/1000.0f;
  707. randomize();
  708. }
  709. RandomTextureMapperClass::RandomTextureMapperClass(const RandomTextureMapperClass & src):
  710. TextureMapperClass(src),
  711. FPMS(src.FPMS),
  712. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  713. Speed(src.Speed),
  714. Remainder(0)
  715. {
  716. randomize();
  717. }
  718. void RandomTextureMapperClass::randomize(void)
  719. {
  720. CurrentAngle=2*WWMATH_PI*rand4.Get_Float();
  721. Center.U=rand4.Get_Float();
  722. Center.V=rand4.Get_Float();
  723. }
  724. void RandomTextureMapperClass::Apply(int uv_array_index)
  725. {
  726. unsigned int now = WW3D::Get_Sync_Time();
  727. unsigned int delta=now-LastUsedSyncTime;
  728. LastUsedSyncTime=now;
  729. Remainder+=delta;
  730. if (FPMS!=0.0f) {
  731. int num_frames=(int) (Remainder*FPMS);
  732. if (num_frames!=0) {
  733. randomize();
  734. Remainder-=num_frames/FPMS;
  735. }
  736. }
  737. // Set up the random matrix
  738. Matrix3D m(true);
  739. m.Rotate_Z(CurrentAngle);
  740. float uoff=Center.U + Remainder*Speed.U;
  741. float voff=Center.V + Remainder*Speed.V;
  742. uoff=fmodf(uoff,1.0f);
  743. voff=fmodf(voff,1.0f);
  744. m[0].Z=uoff;
  745. m[1].Z=voff;
  746. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  747. // Disable Texgen
  748. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU | uv_array_index);
  749. // Tell rasterizer to expect 2D texture coordinates
  750. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  751. }
  752. void RandomTextureMapperClass::Reset(void)
  753. {
  754. LastUsedSyncTime = WW3D::Get_Sync_Time();
  755. Remainder=0;
  756. }
  757. // BumpEnv Mapper
  758. // GTH 8/22/01
  759. BumpEnvTextureMapperClass::BumpEnvTextureMapperClass(float rad_per_sec, float scale_factor, const Vector2 & offset_per_sec, const Vector2 &scale, unsigned int stage) :
  760. LinearOffsetTextureMapperClass(offset_per_sec,scale, stage),
  761. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  762. CurrentAngle(0.0f),
  763. RadiansPerSecond(rad_per_sec),
  764. ScaleFactor(scale_factor)
  765. {
  766. }
  767. BumpEnvTextureMapperClass::BumpEnvTextureMapperClass(INIClass &ini, char *section, unsigned int stage) :
  768. LinearOffsetTextureMapperClass(ini,section,stage),
  769. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  770. CurrentAngle(0.0f)
  771. {
  772. RadiansPerSecond = 2*WWMATH_PI*ini.Get_Float(section,"BumpRotation",0.0f);
  773. ScaleFactor = ini.Get_Float(section,"BumpScale",1.0f);
  774. }
  775. BumpEnvTextureMapperClass::BumpEnvTextureMapperClass(const BumpEnvTextureMapperClass & src) :
  776. LinearOffsetTextureMapperClass(src),
  777. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  778. CurrentAngle(0.0f),
  779. RadiansPerSecond(src.RadiansPerSecond),
  780. ScaleFactor(src.ScaleFactor)
  781. {
  782. }
  783. void BumpEnvTextureMapperClass::Apply(int uv_array_index)
  784. {
  785. LinearOffsetTextureMapperClass::Apply(uv_array_index);
  786. unsigned int now = WW3D::Get_Sync_Time();
  787. unsigned int delta = now - LastUsedSyncTime;
  788. LastUsedSyncTime=now;
  789. CurrentAngle+=RadiansPerSecond * delta * 0.001f;
  790. CurrentAngle=fmodf(CurrentAngle,2*WWMATH_PI);
  791. // Compute the sine and cosine for the bump matrix
  792. float c,s;
  793. c=ScaleFactor * WWMath::Fast_Cos(CurrentAngle);
  794. s=ScaleFactor * WWMath::Fast_Sin(CurrentAngle);
  795. // Set the Bump Environment Matrix
  796. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT00, F2DW(c));
  797. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT01, F2DW(-s));
  798. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT10, F2DW(s));
  799. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT11, F2DW(c));
  800. }
  801. /*
  802. ** Utility functions
  803. */
  804. void Reset_All_Texture_Mappers(RenderObjClass *robj, bool make_unique)
  805. {
  806. if (robj->Class_ID()==RenderObjClass::CLASSID_MESH) {
  807. MeshClass *mesh=(MeshClass*) robj;
  808. MaterialInfoClass *minfo = robj->Get_Material_Info();
  809. if (minfo && minfo->Has_Time_Variant_Texture_Mappers()) {
  810. if (make_unique) {
  811. mesh->Make_Unique();
  812. minfo->Make_Vertex_Materials_Unique();
  813. }
  814. minfo->Reset_Texture_Mappers();
  815. minfo->Release_Ref();
  816. }
  817. } else {
  818. int num_obj = robj->Get_Num_Sub_Objects();
  819. RenderObjClass *sub_obj;
  820. for (int i = 0; i < num_obj; i++) {
  821. sub_obj = robj->Get_Sub_Object(i);
  822. if (sub_obj) {
  823. Reset_All_Texture_Mappers(sub_obj, make_unique);
  824. sub_obj->Release_Ref();
  825. }
  826. }
  827. }
  828. }