mapper.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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:: /Commando/Code/ww3d2/mapper.cpp $*
  25. * *
  26. * $Org Author:: Hector_y $*
  27. * *
  28. * $Author:: Kenny Mitchell *
  29. * *
  30. * $Modtime:: 06/26/02 4:04p $*
  31. * *
  32. * $Revision:: 33 $*
  33. * *
  34. * 06/26/02 KM Matrix name change to avoid MAX conflicts *
  35. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  36. #include "mapper.h"
  37. #include "ww3d.h"
  38. #include "ini.h"
  39. #include "chunkio.h"
  40. #include "w3derr.h"
  41. #include "meshmatdesc.h"
  42. #include "dx8wrapper.h"
  43. #include "wwdebug.h"
  44. #include "matinfo.h"
  45. #include "rendobj.h"
  46. #include "mesh.h"
  47. #include <random.h>
  48. #include <bound.h>
  49. Random4Class rand4;
  50. inline DWORD F2DW( FLOAT f ) { return *((DWORD*)&f); }
  51. // HY 1/26/01
  52. // Rewritten to use DX 8 texture matrices
  53. TextureMapperClass::TextureMapperClass(unsigned int stage)
  54. {
  55. Stage = stage;
  56. if (Stage >= MeshMatDescClass::MAX_TEX_STAGES) Stage = MeshMatDescClass::MAX_TEX_STAGES - 1;
  57. }
  58. // Scale mapper
  59. // HY 5/16/01
  60. ScaleTextureMapperClass::ScaleTextureMapperClass(const Vector2 &scale, unsigned int stage) :
  61. TextureMapperClass(stage),
  62. Scale(scale)
  63. {
  64. }
  65. ScaleTextureMapperClass::ScaleTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  66. TextureMapperClass(stage)
  67. {
  68. Scale.U = ini.Get_Float(section, "UScale", 1.0f);
  69. Scale.V = ini.Get_Float(section, "VScale", 1.0f);
  70. }
  71. ScaleTextureMapperClass::ScaleTextureMapperClass(const ScaleTextureMapperClass & src) :
  72. TextureMapperClass(src),
  73. Scale(src.Scale)
  74. {
  75. }
  76. void ScaleTextureMapperClass::Apply(int uv_array_index)
  77. {
  78. // Set up the texture matrix
  79. Matrix4x4 m;
  80. Calculate_Texture_Matrix(m);
  81. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  82. // Disable Texgen
  83. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU | uv_array_index);
  84. // Tell rasterizer to expect 2D texture coordinates
  85. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  86. }
  87. void ScaleTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  88. {
  89. tex_matrix.Make_Identity();
  90. tex_matrix[0].X = Scale.U;
  91. tex_matrix[1].Y = Scale.V;
  92. }
  93. // Linear Offset Mapper
  94. LinearOffsetTextureMapperClass::LinearOffsetTextureMapperClass(const Vector2 &offset_per_sec,
  95. const Vector2 & start_offset, bool clamp_fix, const Vector2 &scale, unsigned int stage) :
  96. ScaleTextureMapperClass(scale, stage),
  97. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  98. StartingUVOffset(start_offset),
  99. ClampFix(clamp_fix)
  100. {
  101. CurrentUVOffset = StartingUVOffset;
  102. // HY 5/16/01
  103. // This is horrible disgusting legacy from the unmentionable API we used before
  104. // leaving it unchanged because the artists have worked around it
  105. UVOffsetDeltaPerMS = offset_per_sec * -0.001f;
  106. }
  107. LinearOffsetTextureMapperClass::LinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  108. ScaleTextureMapperClass(ini,section,stage),
  109. LastUsedSyncTime(WW3D::Get_Sync_Time())
  110. {
  111. float u_offset_per_sec = ini.Get_Float(section, "UPerSec", 0.0f);
  112. float v_offset_per_sec = ini.Get_Float(section, "VPerSec", 0.0f);
  113. UVOffsetDeltaPerMS = Vector2(u_offset_per_sec, v_offset_per_sec) * -0.001f;
  114. float u_start_offset = ini.Get_Float(section, "UOffset", 0.0f);
  115. float v_start_offset = ini.Get_Float(section, "VOffset", 0.0f);
  116. StartingUVOffset.Set(u_start_offset, v_start_offset);
  117. CurrentUVOffset = StartingUVOffset;
  118. ClampFix = ini.Get_Bool(section, "ClampFix", false);
  119. }
  120. LinearOffsetTextureMapperClass::LinearOffsetTextureMapperClass(const LinearOffsetTextureMapperClass & src) :
  121. ScaleTextureMapperClass(src),
  122. UVOffsetDeltaPerMS(src.UVOffsetDeltaPerMS),
  123. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  124. StartingUVOffset(src.StartingUVOffset),
  125. ClampFix(src.ClampFix)
  126. {
  127. CurrentUVOffset = StartingUVOffset; // Reset a mapper as it is created
  128. }
  129. void LinearOffsetTextureMapperClass::Reset(void)
  130. {
  131. Set_Current_UV_Offset(Vector2(0.0f, 0.0f));
  132. LastUsedSyncTime = WW3D::Get_Sync_Time();
  133. }
  134. void LinearOffsetTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  135. {
  136. unsigned int delta = WW3D::Get_Sync_Time() - LastUsedSyncTime;
  137. float del = (float)delta;
  138. float offset_u = CurrentUVOffset.X + UVOffsetDeltaPerMS.X * del;
  139. float offset_v = CurrentUVOffset.Y + UVOffsetDeltaPerMS.Y * del;
  140. // We need to clamp these texture coordinates to a reasonable range so the hardware doesn't
  141. // choke on them. We do this in one of two ways:
  142. // If ClampFix is not TRUE we use the fractional part of the offset, restricting it between
  143. // 0 and 1 with wraparound. This works well for tiled textures.
  144. // If ClampFix is TRUE we clamp the offsets between -Scale and +Scale with no wraparound.
  145. // This works well for clamped textures.
  146. if (!ClampFix) {
  147. offset_u = offset_u - WWMath::Floor(offset_u);
  148. offset_v = offset_v - WWMath::Floor(offset_v);
  149. } else {
  150. offset_u = WWMath::Clamp(offset_u, -Scale.X, Scale.X);
  151. offset_v = WWMath::Clamp(offset_v, -Scale.Y, Scale.Y);
  152. }
  153. // Set up the offset matrix
  154. tex_matrix.Make_Identity();
  155. // According to the docs this should work since its 2D
  156. // otherwise change to translate
  157. tex_matrix[0].Z=offset_u;
  158. tex_matrix[0].X=Scale.X;
  159. tex_matrix[1].Z=offset_v;
  160. tex_matrix[1].Y=Scale.Y;
  161. // Update state
  162. CurrentUVOffset.X = offset_u;
  163. CurrentUVOffset.Y = offset_v;
  164. LastUsedSyncTime = WW3D::Get_Sync_Time();
  165. }
  166. // Grid Mapper
  167. // HY 5/16/01
  168. GridTextureMapperClass::GridTextureMapperClass(float fps, unsigned int gridwidth_log2, unsigned int last_frame, unsigned int offset, unsigned int stage) :
  169. TextureMapperClass(stage),
  170. LastFrame(last_frame),
  171. Offset(offset)
  172. {
  173. initialize(fps, gridwidth_log2);
  174. }
  175. GridTextureMapperClass::GridTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  176. TextureMapperClass(stage)
  177. {
  178. float fps = ini.Get_Float(section, "FPS", 1.0f);
  179. unsigned int gridwidth_log2 = ini.Get_Int(section, "Log2Width", 1);
  180. LastFrame = ini.Get_Int(section, "Last", 0);
  181. Offset = ini.Get_Int(section, "Offset", 0);
  182. initialize(fps, gridwidth_log2);
  183. }
  184. GridTextureMapperClass::GridTextureMapperClass(const GridTextureMapperClass & src) :
  185. TextureMapperClass(src),
  186. Sign(src.Sign),
  187. MSPerFrame(src.MSPerFrame),
  188. OOGridWidth(src.OOGridWidth),
  189. GridWidthLog2(src.GridWidthLog2),
  190. LastFrame(src.LastFrame),
  191. Offset(src.Offset)
  192. {
  193. Reset();
  194. }
  195. void GridTextureMapperClass::Apply(int uv_array_index)
  196. {
  197. // Set up the texture matrix
  198. Matrix4x4 m;
  199. Calculate_Texture_Matrix(m);
  200. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage), m);
  201. // Disable Texgen
  202. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | uv_array_index);
  203. // Tell rasterizer to expect 2D texture coordinates
  204. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
  205. }
  206. void GridTextureMapperClass::Reset(void)
  207. {
  208. Remainder = 0;
  209. if (Sign >= 0) {
  210. CurrentFrame = Offset;
  211. } else {
  212. CurrentFrame = (LastFrame - 1) - Offset;
  213. }
  214. LastUsedSyncTime = WW3D::Get_Sync_Time();
  215. }
  216. void GridTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  217. {
  218. update_temporal_state();
  219. float u_offset, v_offset;
  220. calculate_uv_offset(&u_offset, &v_offset);
  221. // Set up the offset matrix
  222. tex_matrix.Make_Identity();
  223. // According to the docs this should work since its 2D
  224. // otherwise change to translate
  225. tex_matrix[0].Z = u_offset;
  226. tex_matrix[1].Z = v_offset;
  227. }
  228. void GridTextureMapperClass::Set_Frame_Per_Second(float fps)
  229. {
  230. initialize(fps, GridWidthLog2);
  231. }
  232. void GridTextureMapperClass::initialize(float fps, unsigned int gridwidth_log2)
  233. {
  234. unsigned int grid_width = (1 << gridwidth_log2);
  235. if (LastFrame == 0) LastFrame = (grid_width * grid_width);
  236. Offset = Offset % LastFrame;
  237. LastUsedSyncTime = WW3D::Get_Sync_Time();
  238. GridWidthLog2 = gridwidth_log2;
  239. OOGridWidth = 1.0f / (float)(grid_width);
  240. if (fps == 0.0f) {
  241. // Value of MSPerFrame does not matter as long as it is not 0 - sign will multiply results,
  242. // zeroing them out.
  243. Sign = 0;
  244. MSPerFrame = 1;
  245. CurrentFrame = Offset;
  246. } else if (fps < 0.0f) {
  247. Sign = -1;
  248. MSPerFrame = (unsigned int)(1000.0f / fabs(fps));
  249. CurrentFrame = (LastFrame - 1) - Offset;
  250. } else {
  251. Sign = 1;
  252. MSPerFrame = (unsigned int)(1000.0f / fabs(fps));
  253. CurrentFrame = Offset;
  254. }
  255. Remainder = 0;
  256. }
  257. void GridTextureMapperClass::update_temporal_state(void)
  258. {
  259. unsigned int now = WW3D::Get_Sync_Time();
  260. unsigned int delta = now - LastUsedSyncTime;
  261. Remainder += delta;
  262. LastUsedSyncTime = now;
  263. int new_frame = (int)CurrentFrame + ((int)(Remainder / MSPerFrame) * Sign);
  264. new_frame=new_frame % LastFrame;
  265. if (new_frame<0) {
  266. CurrentFrame=LastFrame+new_frame;
  267. } else {
  268. CurrentFrame=(unsigned int) new_frame;
  269. }
  270. Remainder = Remainder % MSPerFrame;
  271. }
  272. void GridTextureMapperClass::calculate_uv_offset(float * u_offset, float * v_offset)
  273. {
  274. unsigned int row_mask = ~(0xFFFFFFFF << GridWidthLog2);
  275. unsigned int col_mask = row_mask << GridWidthLog2;
  276. unsigned int x = CurrentFrame & row_mask;
  277. unsigned int y = (CurrentFrame & col_mask) >> GridWidthLog2;
  278. *u_offset = x * OOGridWidth;
  279. *v_offset = y * OOGridWidth;
  280. }
  281. // Rotate Mapper
  282. // HY 5/16/01
  283. RotateTextureMapperClass::RotateTextureMapperClass(float rad_per_sec, const Vector2 &center, const Vector2 &scale, unsigned int stage) :
  284. ScaleTextureMapperClass(scale, stage),
  285. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  286. CurrentAngle(0.0f),
  287. RadiansPerMilliSec(rad_per_sec/1000.0f),
  288. Center(center)
  289. {
  290. }
  291. RotateTextureMapperClass::RotateTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  292. ScaleTextureMapperClass(ini, section, stage),
  293. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  294. CurrentAngle(0.0f)
  295. {
  296. RadiansPerMilliSec=2*WWMATH_PI*ini.Get_Float(section,"Speed",0.1f)/1000.0f;
  297. Center.U=ini.Get_Float(section,"UCenter",0.0f);
  298. Center.V=ini.Get_Float(section,"VCenter",0.0f);
  299. }
  300. RotateTextureMapperClass::RotateTextureMapperClass(const RotateTextureMapperClass & src) :
  301. ScaleTextureMapperClass(src),
  302. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  303. RadiansPerMilliSec(src.RadiansPerMilliSec),
  304. CurrentAngle(0.0f),
  305. Center(src.Center)
  306. {
  307. }
  308. void RotateTextureMapperClass::Reset(void)
  309. {
  310. CurrentAngle = 0.0f;
  311. LastUsedSyncTime = WW3D::Get_Sync_Time();
  312. }
  313. void RotateTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  314. {
  315. unsigned int now = WW3D::Get_Sync_Time();
  316. unsigned int delta = now - LastUsedSyncTime;
  317. LastUsedSyncTime=now;
  318. CurrentAngle+=RadiansPerMilliSec * delta;
  319. CurrentAngle=fmodf(CurrentAngle,2*WWMATH_PI);
  320. if (CurrentAngle<0.0f) CurrentAngle+=2*WWMATH_PI;
  321. // Set up the rotation matrix
  322. float c,s;
  323. c=WWMath::Cos(CurrentAngle);
  324. s=WWMath::Sin(CurrentAngle);
  325. tex_matrix.Make_Identity();
  326. // subtract center
  327. // rotate
  328. // add center
  329. // then scale
  330. tex_matrix[0].Set(Scale.X * c, -Scale.X * s, -Scale.X * (c * Center.U - s * Center.V - Center.U), 0.0f);
  331. tex_matrix[1].Set(Scale.Y * s, Scale.Y * c, -Scale.Y * (s * Center.U + c * Center.V - Center.V), 0.0f);
  332. }
  333. // SineLinearOffset Mapper
  334. // HY 5/16/01
  335. SineLinearOffsetTextureMapperClass::SineLinearOffsetTextureMapperClass(const Vector3 &uafp, const Vector3 &vafp, const Vector2 &scale, unsigned int stage) :
  336. ScaleTextureMapperClass(scale, stage),
  337. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  338. UAFP(uafp),
  339. VAFP(vafp),
  340. CurrentAngle(0.0f)
  341. {
  342. }
  343. SineLinearOffsetTextureMapperClass::SineLinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  344. ScaleTextureMapperClass(ini, section, stage),
  345. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  346. CurrentAngle(0.0f)
  347. {
  348. UAFP.X = ini.Get_Float(section, "UAmp", 1.0f);
  349. UAFP.Y = ini.Get_Float(section, "UFreq", 1.0f);
  350. UAFP.Z = ini.Get_Float(section, "UPhase", 0.0f);
  351. VAFP.X = ini.Get_Float(section, "VAmp", 1.0f);
  352. VAFP.Y = ini.Get_Float(section, "VFreq", 1.0f);
  353. VAFP.Z = ini.Get_Float(section, "VPhase", 0.0f);
  354. }
  355. SineLinearOffsetTextureMapperClass::SineLinearOffsetTextureMapperClass(const SineLinearOffsetTextureMapperClass & src) :
  356. ScaleTextureMapperClass(src),
  357. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  358. UAFP(src.UAFP),
  359. VAFP(src.VAFP),
  360. CurrentAngle(0.0f)
  361. {
  362. }
  363. void SineLinearOffsetTextureMapperClass::Reset(void)
  364. {
  365. CurrentAngle = 0.0f;
  366. LastUsedSyncTime = WW3D::Get_Sync_Time();
  367. }
  368. void SineLinearOffsetTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  369. {
  370. unsigned int now = WW3D::Get_Sync_Time();
  371. unsigned int delta = now - LastUsedSyncTime;
  372. LastUsedSyncTime=now;
  373. const float ms_to_radians=2*WWMATH_PI/1000.0f;
  374. CurrentAngle+=delta*ms_to_radians;
  375. float offset_u=UAFP.X*sin(UAFP.Y*CurrentAngle+UAFP.Z*WWMATH_PI);
  376. float offset_v=VAFP.X*sin(VAFP.Y*CurrentAngle+VAFP.Z*WWMATH_PI);
  377. // Set up the offset matrix
  378. tex_matrix.Make_Identity();
  379. // According to the docs this should work since its 2D
  380. // otherwise change to translate
  381. tex_matrix[0].Z = offset_u;
  382. tex_matrix[0].X = Scale.X;
  383. tex_matrix[1].Z = offset_v;
  384. tex_matrix[1].Y = Scale.Y;
  385. }
  386. // StepLinearOffset Mapper
  387. // HY 5/16/01
  388. StepLinearOffsetTextureMapperClass::StepLinearOffsetTextureMapperClass(const Vector2 &step,
  389. float steps_per_sec, bool clamp_fix, const Vector2 &scale, unsigned int stage) :
  390. ScaleTextureMapperClass(scale, stage),
  391. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  392. Step(step),
  393. StepsPerMilliSec(steps_per_sec/1000.0f),
  394. CurrentStep(0.0f,0.0f),
  395. Remainder(0),
  396. ClampFix(clamp_fix)
  397. {
  398. }
  399. StepLinearOffsetTextureMapperClass::StepLinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  400. ScaleTextureMapperClass(ini, section, stage),
  401. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  402. CurrentStep(0.0f,0.0f),
  403. Remainder(0)
  404. {
  405. Step.U = ini.Get_Float(section, "UStep", 0.0f);
  406. Step.V = ini.Get_Float(section, "VStep", 0.0f);
  407. StepsPerMilliSec = ini.Get_Float(section, "SPS", 0.0f)/1000.0f;
  408. ClampFix = ini.Get_Bool(section, "ClampFix", false);
  409. }
  410. StepLinearOffsetTextureMapperClass::StepLinearOffsetTextureMapperClass(const StepLinearOffsetTextureMapperClass & src) :
  411. ScaleTextureMapperClass(src),
  412. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  413. Step(src.Step),
  414. StepsPerMilliSec(src.StepsPerMilliSec),
  415. CurrentStep(0.0f,0.0f),
  416. Remainder(0),
  417. ClampFix(src.ClampFix)
  418. {
  419. }
  420. void StepLinearOffsetTextureMapperClass::Reset(void)
  421. {
  422. LastUsedSyncTime = WW3D::Get_Sync_Time();
  423. CurrentStep.Set(0.0f,0.0f);
  424. Remainder=0;
  425. }
  426. void StepLinearOffsetTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  427. {
  428. unsigned int now = WW3D::Get_Sync_Time();
  429. unsigned int delta = now - LastUsedSyncTime;
  430. LastUsedSyncTime=now;
  431. Remainder+=delta;
  432. int num_steps=(int) (StepsPerMilliSec*Remainder);
  433. if (num_steps!=0)
  434. {
  435. CurrentStep+=Step*num_steps;
  436. Remainder-=num_steps/(float)StepsPerMilliSec;
  437. }
  438. // We need to clamp these texture coordinates to a reasonable range so the hardware doesn't
  439. // choke on them. We do this in one of two ways:
  440. // If ClampFix is not TRUE we use the fractional part of the offset, restricting it between
  441. // 0 and 1 with wraparound. This works well for tiled textures.
  442. // If ClampFix is TRUE we clamp the offsets between -Scale and +Scale with no wraparound.
  443. // This works well for clamped textures.
  444. if (!ClampFix) {
  445. CurrentStep.U -= WWMath::Floor(CurrentStep.U);
  446. CurrentStep.V -= WWMath::Floor(CurrentStep.V);
  447. } else {
  448. CurrentStep.U = WWMath::Clamp(CurrentStep.U, -Scale.X, Scale.X);
  449. CurrentStep.V = WWMath::Clamp(CurrentStep.V, -Scale.Y, Scale.Y);
  450. }
  451. // Set up the offset matrix
  452. tex_matrix.Make_Identity();
  453. // According to the docs this should work since its 2D
  454. // otherwise change to translate
  455. tex_matrix[0].Z = CurrentStep.U;
  456. tex_matrix[0].X = Scale.X;
  457. tex_matrix[1].Z = CurrentStep.V;
  458. tex_matrix[1].Y = Scale.Y;
  459. }
  460. // ZigZagLinearOffset Mapper
  461. // HY 5/16/01
  462. ZigZagLinearOffsetTextureMapperClass::ZigZagLinearOffsetTextureMapperClass(const Vector2 &speed, float period, const Vector2 &scale, unsigned int stage) :
  463. ScaleTextureMapperClass(scale, stage),
  464. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  465. Speed(speed/1000.0f),
  466. Period(period*1000.0f),
  467. Remainder(0)
  468. {
  469. // since we're zigzagging, a negative period is the same as a positive one
  470. if (Period<0.0f) Period=-Period;
  471. Half_Period=0.5f*Period;
  472. }
  473. ZigZagLinearOffsetTextureMapperClass::ZigZagLinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  474. ScaleTextureMapperClass(ini, section, stage),
  475. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  476. Remainder(0)
  477. {
  478. Speed.U = ini.Get_Float(section, "UPerSec", 0.0f)/1000.0f;
  479. Speed.V = ini.Get_Float(section, "VPerSec", 0.0f)/1000.0f;
  480. Period = ini.Get_Float(section, "Period", 0.0f)*1000.0f;
  481. if (Period<0.0f) Period=-Period;
  482. Half_Period=0.5f*Period;
  483. }
  484. ZigZagLinearOffsetTextureMapperClass::ZigZagLinearOffsetTextureMapperClass(const ZigZagLinearOffsetTextureMapperClass & src) :
  485. ScaleTextureMapperClass(src),
  486. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  487. Speed(src.Speed),
  488. Period(src.Period),
  489. Half_Period(src.Half_Period),
  490. Remainder(0)
  491. {
  492. }
  493. void ZigZagLinearOffsetTextureMapperClass::Reset(void)
  494. {
  495. LastUsedSyncTime = WW3D::Get_Sync_Time();
  496. Remainder=0;
  497. }
  498. void ZigZagLinearOffsetTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  499. {
  500. unsigned int now = WW3D::Get_Sync_Time();
  501. unsigned int delta = now - LastUsedSyncTime;
  502. LastUsedSyncTime=now;
  503. Remainder+=delta;
  504. float offset_u=0.0f;
  505. float offset_v=0.0f;
  506. if (Period>0.0f)
  507. {
  508. // figure out the fractional number of periods
  509. int num_periods=(int) (Remainder/Period);
  510. Remainder-=num_periods*Period;
  511. float time=0.0f;
  512. if (Remainder>Half_Period) {
  513. time=Period-Remainder;
  514. } else {
  515. time=Remainder;
  516. }
  517. offset_u=Speed.U * time;
  518. offset_v=Speed.V * time;
  519. }
  520. // Set up the offset matrix
  521. tex_matrix.Make_Identity();
  522. // According to the docs this should work since its 2D
  523. // otherwise change to translate
  524. tex_matrix[0].Z = offset_u;
  525. tex_matrix[0].X = Scale.X;
  526. tex_matrix[1].Z = offset_v;
  527. tex_matrix[1].Y = Scale.Y;
  528. }
  529. // ----------------------------------------------------------------------------
  530. //
  531. // Environment mapper calculates the texture coordinates based on
  532. // transformed normals
  533. //
  534. // ----------------------------------------------------------------------------
  535. void ClassicEnvironmentMapperClass::Apply(int uv_array_index)
  536. {
  537. // Set up the texture matrix
  538. Matrix4x4 m;
  539. Calculate_Texture_Matrix(m);
  540. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  541. // Get camera normals
  542. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  543. // Tell rasterizer to expect 2D matrices
  544. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  545. }
  546. void ClassicEnvironmentMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  547. {
  548. // The canonical environment map
  549. // scale the normal by (.5,.5) and add (.5,.5) to move it to (0,1) range
  550. // and ignore the Z component
  551. tex_matrix.Init( 0.5f, 0.0f, 0.0f, 0.5f,
  552. 0.0f, 0.5f, 0.0f, 0.5f,
  553. 0.0f, 0.0f, 1.0f, 0.0f,
  554. 0.0f, 0.0f, 0.0f, 1.0f);
  555. }
  556. void EnvironmentMapperClass::Apply(int uv_array_index)
  557. {
  558. // Set up the texture matrix
  559. Matrix4x4 m;
  560. Calculate_Texture_Matrix(m);
  561. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  562. // Get camera reflection vector
  563. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
  564. // Tell rasterizer to expect 2D matrices
  565. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  566. }
  567. void EnvironmentMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  568. {
  569. // The canonical environment map
  570. // scale the normal by (.5,.5) and add (.5,.5) to move it to (0,1) range
  571. tex_matrix.Init( 0.5f, 0.0f, 0.0f, 0.5f,
  572. 0.0f, 0.5f, 0.0f, 0.5f,
  573. 0.0f, 0.0f, 1.0f, 0.0f,
  574. 0.0f, 0.0f, 0.0f, 1.0f );
  575. }
  576. // Edge mapper
  577. EdgeMapperClass::EdgeMapperClass(unsigned int stage) :
  578. TextureMapperClass(stage),
  579. VSpeed(0.0f),
  580. UseReflect(false),
  581. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  582. VOffset(0.0f)
  583. {
  584. }
  585. EdgeMapperClass::EdgeMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  586. TextureMapperClass(stage),
  587. VSpeed(0.0f),
  588. UseReflect(false),
  589. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  590. VOffset(0.0f)
  591. {
  592. VSpeed=ini.Get_Float(section, "VPerSec", 0.0f);
  593. VOffset=ini.Get_Float(section, "VStart", 0.0f);
  594. UseReflect=ini.Get_Bool(section, "UseReflect", false);
  595. }
  596. EdgeMapperClass::EdgeMapperClass(const EdgeMapperClass & src):
  597. TextureMapperClass(src.Stage),
  598. VSpeed(src.VSpeed),
  599. UseReflect(src.UseReflect),
  600. VOffset(src.VOffset),
  601. LastUsedSyncTime(WW3D::Get_Sync_Time())
  602. {
  603. }
  604. void EdgeMapperClass::Apply(int uv_array_index)
  605. {
  606. // Set up the texture matrix
  607. Matrix4x4 m;
  608. Calculate_Texture_Matrix(m);
  609. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  610. // Get camera reflection vector
  611. if (UseReflect)
  612. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
  613. else
  614. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  615. // Tell rasterizer to expect 2D matrices
  616. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  617. }
  618. void EdgeMapperClass::Reset(void)
  619. {
  620. LastUsedSyncTime = WW3D::Get_Sync_Time();
  621. VOffset = 0.0f;
  622. }
  623. void EdgeMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  624. {
  625. unsigned int now=WW3D::Get_Sync_Time();
  626. float delta=(now-LastUsedSyncTime)*0.001f;
  627. LastUsedSyncTime=now;
  628. VOffset+=delta*VSpeed;
  629. VOffset-=WWMath::Floor(VOffset);
  630. // takes the Z component and
  631. // uses it to index the texture
  632. tex_matrix.Init( 0.0f, 0.0f, 0.5f, 0.5f,
  633. 0.0f, 0.0f, 0.0f, VOffset,
  634. 0.0f, 0.0f, 1.0f, 0.0f,
  635. 0.0f, 0.0f, 0.0f, 1.0f );
  636. }
  637. WSEnvMapperClass::WSEnvMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  638. TextureMapperClass(stage),
  639. Axis(AXISTYPE_Z)
  640. {
  641. char temp[2];
  642. ini.Get_String(section, "Axis", "Z", &temp[0], 2);
  643. switch(temp[0]) {
  644. case 'X':
  645. case 'x':
  646. Axis = AXISTYPE_X;
  647. break;
  648. case 'Y':
  649. case 'y':
  650. Axis = AXISTYPE_Y;
  651. break;
  652. case 'Z':
  653. case 'z':
  654. Axis = AXISTYPE_Z;
  655. break;
  656. default:
  657. Axis = AXISTYPE_Z;
  658. break;
  659. }
  660. }
  661. void WSEnvMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  662. {
  663. // The canonical environment map
  664. // scale the normal by (.5,.5) and add (.5,.5) to move it to (0,1) range
  665. switch (Axis) {
  666. case AXISTYPE_X:
  667. tex_matrix.Init( 0.0f, 0.5f, 0.0f, 0.5f,
  668. 0.0f, 0.0f, 0.5f, 0.5f,
  669. 0.0f, 0.0f, 1.0f, 0.0f,
  670. 0.0f, 0.0f, 0.0f, 1.0f );
  671. break;
  672. case AXISTYPE_Y:
  673. tex_matrix.Init( 0.5f, 0.0f, 0.0f, 0.5f,
  674. 0.0f, 0.0f, 0.5f, 0.5f,
  675. 0.0f, 0.0f, 1.0f, 0.0f,
  676. 0.0f, 0.0f, 0.0f, 1.0f );
  677. break;
  678. case AXISTYPE_Z:
  679. default:
  680. tex_matrix.Init( 0.5f, 0.0f, 0.0f, 0.5f,
  681. 0.0f, 0.5f, 0.0f, 0.5f,
  682. 0.0f, 0.0f, 1.0f, 0.0f,
  683. 0.0f, 0.0f, 0.0f, 1.0f );
  684. break;
  685. }
  686. // multiply by inverse of view transform
  687. Matrix4x4 mat;
  688. DX8Wrapper::Get_Transform(D3DTS_VIEW,mat);
  689. Matrix4x4 mat2( mat[0].X, mat[1].X, mat[2].X, 0.0f,
  690. mat[0].Y, mat[1].Y, mat[2].Y, 0.0f,
  691. mat[0].Z, mat[1].Z, mat[2].Z, 0.0f,
  692. 0.0f, 0.0f, 0.0f, 1.0f );
  693. tex_matrix = tex_matrix * mat2;
  694. }
  695. void WSClassicEnvironmentMapperClass::Apply(int uv_array_index)
  696. {
  697. // Set up the texture matrix
  698. Matrix4x4 m;
  699. Calculate_Texture_Matrix(m);
  700. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  701. // Get camera normals
  702. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  703. // Tell rasterizer to expect 2D matrices
  704. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  705. }
  706. void WSEnvironmentMapperClass::Apply(int uv_array_index)
  707. {
  708. // Set up the texture matrix
  709. Matrix4x4 m;
  710. Calculate_Texture_Matrix(m);
  711. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  712. // Get camera reflection
  713. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
  714. // Tell rasterizer to expect 2D matrices
  715. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  716. }
  717. void GridClassicEnvironmentMapperClass::Apply(int uv_array_index)
  718. {
  719. // Set up the texture matrix
  720. Matrix4x4 m;
  721. Calculate_Texture_Matrix(m);
  722. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  723. // Get camera normals
  724. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  725. // Tell rasterizer to expect 2D matrices
  726. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  727. }
  728. void GridClassicEnvironmentMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  729. {
  730. update_temporal_state();
  731. float u_offset, v_offset;
  732. calculate_uv_offset(&u_offset, &v_offset);
  733. float del = 0.5f * OOGridWidth;
  734. // Set up the offset matrix
  735. tex_matrix.Init( del, 0.0f, 0.0f, u_offset + del,
  736. 0.0f, del, 0.0f, v_offset + del,
  737. 0.0f, 0.0f, 1.0f, 0.0f,
  738. 0.0f, 0.0f, 0.0f, 1.0f );
  739. }
  740. void GridEnvironmentMapperClass::Apply(int uv_array_index)
  741. {
  742. // Set up the texture matrix
  743. Matrix4x4 m;
  744. Calculate_Texture_Matrix(m);
  745. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  746. // Get camera space reflection
  747. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
  748. // Tell rasterizer to expect 2D matrices
  749. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  750. }
  751. void GridEnvironmentMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  752. {
  753. update_temporal_state();
  754. float u_offset, v_offset;
  755. calculate_uv_offset(&u_offset, &v_offset);
  756. float del=0.5f * OOGridWidth;
  757. // Set up the offset matrix
  758. tex_matrix.Init( del, 0.0f, 0.0f, u_offset + del,
  759. 0.0f, del, 0.0f, v_offset + del,
  760. 0.0f, 0.0f, 1.0f, 0.0f,
  761. 0.0f, 0.0f, 0.0f, 1.0f );
  762. }
  763. void ScreenMapperClass::Apply(int uv_array_index)
  764. {
  765. // Set up the texture matrix
  766. Matrix4x4 m;
  767. Calculate_Texture_Matrix(m);
  768. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  769. // Get camera space position
  770. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEPOSITION);
  771. // Tell rasterizer what to expect
  772. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_PROJECTED | D3DTTFF_COUNT3);
  773. }
  774. void ScreenMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  775. {
  776. unsigned int delta = WW3D::Get_Sync_Time() - LastUsedSyncTime;
  777. float del = (float)delta;
  778. float offset_u = CurrentUVOffset.X + UVOffsetDeltaPerMS.X * del;
  779. float offset_v = CurrentUVOffset.Y + UVOffsetDeltaPerMS.Y * del;
  780. // We need to clamp these texture coordinates to a reasonable range so the hardware doesn't
  781. // choke on them. We do this in one of two ways:
  782. // If ClampFix is not TRUE we use the fractional part of the offset, restricting it between
  783. // 0 and 1 with wraparound. This works well for tiled textures.
  784. // If ClampFix is TRUE we clamp the offsets between -Scale and +Scale with no wraparound.
  785. // This works well for clamped textures.
  786. if (!ClampFix) {
  787. offset_u = offset_u - WWMath::Floor(offset_u);
  788. offset_v = offset_v - WWMath::Floor(offset_v);
  789. } else {
  790. offset_u = WWMath::Clamp(offset_u, -Scale.X, Scale.X);
  791. offset_v = WWMath::Clamp(offset_v, -Scale.Y, Scale.Y);
  792. }
  793. // multiply by projection matrix
  794. // followed by scale and translation
  795. DX8Wrapper::Get_Transform(D3DTS_PROJECTION, tex_matrix);
  796. tex_matrix[0] *= Scale.X; // entire row since we're pre-multiplying
  797. tex_matrix[1] *= Scale.Y;
  798. Vector4 last(tex_matrix[3]); // this gets the w
  799. last *= offset_u; // multiply by w because the projected flag will divide by w
  800. tex_matrix[0] += last;
  801. last = tex_matrix[3];
  802. last *= offset_v;
  803. tex_matrix[1] += last;
  804. // Update state
  805. CurrentUVOffset.X = offset_u;
  806. CurrentUVOffset.Y = offset_v;
  807. LastUsedSyncTime = WW3D::Get_Sync_Time();
  808. }
  809. RandomTextureMapperClass::RandomTextureMapperClass(float fps, const Vector2 &scale, unsigned int stage):
  810. ScaleTextureMapperClass(scale, stage),
  811. FPMS(fps/1000.0f),
  812. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  813. Speed(0.0f,0.0f),
  814. Remainder(0)
  815. {
  816. randomize();
  817. }
  818. RandomTextureMapperClass::RandomTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage):
  819. ScaleTextureMapperClass(ini, section, stage),
  820. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  821. Remainder(0)
  822. {
  823. FPMS = ini.Get_Float(section, "FPS", 0.0f)/1000.0f;
  824. Speed.U = ini.Get_Float(section, "UPerSec", 0.0f)/1000.0f;
  825. Speed.V = ini.Get_Float(section, "VPerSec", 0.0f)/1000.0f;
  826. randomize();
  827. }
  828. RandomTextureMapperClass::RandomTextureMapperClass(const RandomTextureMapperClass & src):
  829. ScaleTextureMapperClass(src),
  830. FPMS(src.FPMS),
  831. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  832. Speed(src.Speed),
  833. Remainder(0)
  834. {
  835. randomize();
  836. }
  837. void RandomTextureMapperClass::randomize(void)
  838. {
  839. CurrentAngle=2*WWMATH_PI*rand4.Get_Float();
  840. Center.U=rand4.Get_Float();
  841. Center.V=rand4.Get_Float();
  842. }
  843. void RandomTextureMapperClass::Reset(void)
  844. {
  845. LastUsedSyncTime = WW3D::Get_Sync_Time();
  846. Remainder=0;
  847. }
  848. void RandomTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  849. {
  850. unsigned int now = WW3D::Get_Sync_Time();
  851. unsigned int delta=now-LastUsedSyncTime;
  852. LastUsedSyncTime=now;
  853. Remainder+=delta;
  854. if (FPMS!=0.0f) {
  855. int num_frames=(int) (Remainder*FPMS);
  856. if (num_frames!=0) {
  857. randomize();
  858. Remainder-=num_frames/FPMS;
  859. }
  860. }
  861. // Set up the random matrix - start with a rotation matrix of 'CurrentAngle' about the Z-axis.
  862. // We apply the scale matrix to the right of the unscaled rotate/offset matrix, because we
  863. // don't want the scaling to affect the offset. So we get:
  864. // [ c -s uoff ] [ Sx 0 0 ] [ cSx -sSy uoff ]
  865. // [ s c voff ] * [ 0 Sy 0 ] = [ sSx cSy voff ]
  866. // [ 0 0 1 ] [ 0 0 1 ] [ 0 0 1 ]
  867. float c = cosf(CurrentAngle);
  868. float s = sinf(CurrentAngle);
  869. tex_matrix.Make_Identity();
  870. tex_matrix[0][0] = c * Scale.X;
  871. tex_matrix[0][1] = -s * Scale.Y;
  872. tex_matrix[1][0] = s * Scale.X;
  873. tex_matrix[1][1] = c * Scale.Y;
  874. // Offset matrix
  875. float uoff = Center.U + Remainder * Speed.U;
  876. float voff = Center.V + Remainder * Speed.V;
  877. uoff = fmodf(uoff, 1.0f);
  878. voff = fmodf(voff, 1.0f);
  879. tex_matrix[0].Z = uoff;
  880. tex_matrix[1].Z = voff;
  881. }
  882. // BumpEnv Mapper
  883. // GTH 8/22/01
  884. BumpEnvTextureMapperClass::BumpEnvTextureMapperClass(float rad_per_sec, float scale_factor,
  885. const Vector2 & offset_per_sec, const Vector2 & start_offset, bool clamp_fix,
  886. const Vector2 &scale, unsigned int stage) :
  887. LinearOffsetTextureMapperClass(offset_per_sec, start_offset, clamp_fix, scale, stage),
  888. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  889. CurrentAngle(0.0f),
  890. RadiansPerSecond(rad_per_sec),
  891. ScaleFactor(scale_factor)
  892. {
  893. }
  894. BumpEnvTextureMapperClass::BumpEnvTextureMapperClass(INIClass &ini, char *section, unsigned int stage) :
  895. LinearOffsetTextureMapperClass(ini, section, stage),
  896. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  897. CurrentAngle(0.0f)
  898. {
  899. RadiansPerSecond = 2*WWMATH_PI*ini.Get_Float(section,"BumpRotation",0.0f);
  900. ScaleFactor = ini.Get_Float(section,"BumpScale",1.0f);
  901. }
  902. BumpEnvTextureMapperClass::BumpEnvTextureMapperClass(const BumpEnvTextureMapperClass & src) :
  903. LinearOffsetTextureMapperClass(src),
  904. LastUsedSyncTime(WW3D::Get_Sync_Time()),
  905. CurrentAngle(0.0f),
  906. RadiansPerSecond(src.RadiansPerSecond),
  907. ScaleFactor(src.ScaleFactor)
  908. {
  909. }
  910. void BumpEnvTextureMapperClass::Apply(int uv_array_index)
  911. {
  912. LinearOffsetTextureMapperClass::Apply(uv_array_index);
  913. unsigned int now = WW3D::Get_Sync_Time();
  914. unsigned int delta = now - LastUsedSyncTime;
  915. LastUsedSyncTime=now;
  916. CurrentAngle+=RadiansPerSecond * delta * 0.001f;
  917. CurrentAngle=fmodf(CurrentAngle,2*WWMATH_PI);
  918. // Compute the sine and cosine for the bump matrix
  919. float c,s;
  920. c=ScaleFactor * WWMath::Fast_Cos(CurrentAngle);
  921. s=ScaleFactor * WWMath::Fast_Sin(CurrentAngle);
  922. // Set the Bump Environment Matrix
  923. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT00, F2DW(c));
  924. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT01, F2DW(-s));
  925. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT10, F2DW(s));
  926. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT11, F2DW(c));
  927. }
  928. /*
  929. ** Utility functions
  930. */
  931. void Reset_All_Texture_Mappers(RenderObjClass *robj, bool make_unique)
  932. {
  933. if (robj->Class_ID()==RenderObjClass::CLASSID_MESH) {
  934. MeshClass *mesh=(MeshClass*) robj;
  935. MaterialInfoClass *minfo = robj->Get_Material_Info();
  936. if (minfo && minfo->Has_Time_Variant_Texture_Mappers()) {
  937. if (make_unique) {
  938. mesh->Make_Unique();
  939. minfo->Make_Vertex_Materials_Unique();
  940. }
  941. minfo->Reset_Texture_Mappers();
  942. minfo->Release_Ref();
  943. }
  944. } else {
  945. int num_obj = robj->Get_Num_Sub_Objects();
  946. RenderObjClass *sub_obj;
  947. for (int i = 0; i < num_obj; i++) {
  948. sub_obj = robj->Get_Sub_Object(i);
  949. if (sub_obj) {
  950. Reset_All_Texture_Mappers(sub_obj, make_unique);
  951. sub_obj->Release_Ref();
  952. }
  953. }
  954. }
  955. }
  956. GridWSEnvMapperClass::GridWSEnvMapperClass(float fps, unsigned int gridwidth_log2, unsigned int last_frame, unsigned int offset, AxisType axis, unsigned int stage):
  957. GridTextureMapperClass(fps, gridwidth_log2, last_frame, offset, stage),
  958. Axis(axis)
  959. {
  960. }
  961. GridWSEnvMapperClass::GridWSEnvMapperClass(const GridWSEnvMapperClass & src) :
  962. GridTextureMapperClass(src),
  963. Axis(src.Axis)
  964. {
  965. }
  966. GridWSEnvMapperClass::GridWSEnvMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
  967. GridTextureMapperClass(ini, section, stage),
  968. Axis(AXISTYPE_Z)
  969. {
  970. char temp[2];
  971. ini.Get_String(section, "Axis", "Z", &temp[0], 2);
  972. switch(temp[0]) {
  973. case 'X':
  974. case 'x':
  975. Axis = AXISTYPE_X;
  976. break;
  977. case 'Y':
  978. case 'y':
  979. Axis = AXISTYPE_Y;
  980. break;
  981. case 'Z':
  982. case 'z':
  983. Axis = AXISTYPE_Z;
  984. break;
  985. default:
  986. Axis = AXISTYPE_Z;
  987. break;
  988. }
  989. }
  990. void GridWSEnvMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  991. {
  992. // multiply by inverse of view transform
  993. Matrix4x4 mat;
  994. DX8Wrapper::Get_Transform(D3DTS_VIEW,mat);
  995. Matrix4x4 mv ( mat[0].X, mat[1].X, mat[2].X, 0.0f,
  996. mat[0].Y, mat[1].Y, mat[2].Y, 0.0f,
  997. mat[0].Z, mat[1].Z, mat[2].Z, 0.0f,
  998. 0.0f, 0.0f, 0.0f, 1.0f );
  999. update_temporal_state();
  1000. float u_offset, v_offset;
  1001. calculate_uv_offset(&u_offset, &v_offset);
  1002. float del=0.5f * OOGridWidth;
  1003. // Set up the offset matrix
  1004. Matrix4x4 md;
  1005. switch (Axis) {
  1006. case AXISTYPE_X:
  1007. md.Init( 0.0f, del, 0.0f, u_offset + del,
  1008. 0.0f, 0.0f, del, v_offset + del,
  1009. 0.0f, 0.0f, 1.0f, 0.0f,
  1010. 0.0f, 0.0f, 0.0f, 1.0f );
  1011. break;
  1012. case AXISTYPE_Y:
  1013. md.Init( del, 0.0f, 0.0f, u_offset + del,
  1014. 0.0f, 0.0f, del, v_offset + del,
  1015. 0.0f, 0.0f, 1.0f, 0.0f,
  1016. 0.0f, 0.0f, 0.0f, 1.0f );
  1017. break;
  1018. case AXISTYPE_Z:
  1019. default:
  1020. md.Init( del, 0.0f, 0.0f, u_offset + del,
  1021. 0.0f, del, 0.0f, v_offset + del,
  1022. 0.0f, 0.0f, 1.0f, 0.0f,
  1023. 0.0f, 0.0f, 0.0f, 1.0f );
  1024. break;
  1025. }
  1026. // multiply by inverse of view transform, then
  1027. // change the world space reflection vector to a UV coordinate
  1028. // then offset by the grid coordinate
  1029. tex_matrix = md * mv;
  1030. }
  1031. /***********************************************************************************************
  1032. * GridWSClassicEnvironmentMapperClass::GridWSClassicEnvironmentMapperClass -- Grid WS Env Map *
  1033. * *
  1034. * *
  1035. * *
  1036. * *
  1037. * INPUT: *
  1038. * *
  1039. * OUTPUT: *
  1040. * *
  1041. * WARNINGS: *
  1042. * *
  1043. * HISTORY: *
  1044. *=============================================================================================*/
  1045. GridWSClassicEnvironmentMapperClass::GridWSClassicEnvironmentMapperClass(float fps, unsigned int gridwidth_log2, unsigned int last_frame, unsigned int offset, AxisType axis, unsigned int stage) :
  1046. GridWSEnvMapperClass(fps, gridwidth_log2, last_frame, offset, axis, stage)
  1047. {
  1048. }
  1049. GridWSClassicEnvironmentMapperClass::GridWSClassicEnvironmentMapperClass(const INIClass &ini, const char *section, unsigned int stage):
  1050. GridWSEnvMapperClass(ini,section,stage)
  1051. {
  1052. }
  1053. GridWSClassicEnvironmentMapperClass::GridWSClassicEnvironmentMapperClass(const GridWSEnvMapperClass & src):
  1054. GridWSEnvMapperClass(src)
  1055. {
  1056. }
  1057. void GridWSClassicEnvironmentMapperClass::Apply(int uv_array_index)
  1058. {
  1059. // Set up the texture matrix
  1060. Matrix4x4 m;
  1061. Calculate_Texture_Matrix(m);
  1062. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  1063. // Get camera normals
  1064. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  1065. // Tell rasterizer to expect 2D matrices
  1066. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  1067. }
  1068. /***********************************************************************************************
  1069. * GridWSEnvironmentMapperClass::GridWSEnvironmentMapperClass -- grid ws env *
  1070. * *
  1071. * *
  1072. * *
  1073. * *
  1074. * INPUT: *
  1075. * *
  1076. * OUTPUT: *
  1077. * *
  1078. * WARNINGS: *
  1079. * *
  1080. * HISTORY: *
  1081. * 1/29/2002 hy : Created. *
  1082. *=============================================================================================*/
  1083. GridWSEnvironmentMapperClass::GridWSEnvironmentMapperClass(float fps, unsigned int gridwidth_log2, unsigned int last_frame, unsigned int offset, AxisType axis, unsigned int stage) :
  1084. GridWSEnvMapperClass(fps, gridwidth_log2, last_frame, offset, axis, stage)
  1085. {
  1086. }
  1087. GridWSEnvironmentMapperClass::GridWSEnvironmentMapperClass(const INIClass &ini, const char *section, unsigned int stage):
  1088. GridWSEnvMapperClass(ini, section, stage)
  1089. {
  1090. }
  1091. GridWSEnvironmentMapperClass::GridWSEnvironmentMapperClass(const GridWSEnvMapperClass & src):
  1092. GridWSEnvMapperClass(src)
  1093. {
  1094. }
  1095. void GridWSEnvironmentMapperClass::Apply(int uv_array_index)
  1096. {
  1097. // Set up the texture matrix
  1098. Matrix4x4 m;
  1099. Calculate_Texture_Matrix(m);
  1100. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
  1101. // Get camera space reflection
  1102. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
  1103. // Tell rasterizer to expect 2D matrices
  1104. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  1105. }