ringobj.cpp 72 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  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 : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/ringobj.cpp $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 11/24/01 6:17p $*
  29. * *
  30. * $Revision:: 27 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * RingRenderObjClass::RingRenderObjClass -- Constructor *
  35. * RingRenderObjClass::RingRenderObjClass -- Constructor - init from a definition *
  36. * RingRenderObjClass::RingRenderObjClass -- Copy constructor *
  37. * RingRenderObjClass::~RingRenderObjClass -- destructor *
  38. * RingRenderObjClass::operator -- assignment operator *
  39. * RingRenderObjClass::Get_Num_Polys -- returns number of polygons *
  40. * RingRenderObjClass::Get_Name -- returns name *
  41. * RingRenderObjClass::Set_Name -- sets the name *
  42. * RingRenderObjClass::Set_Color -- Sets the color of the Ring *
  43. * RingRenderObjClass::Init_Ring_Render_System -- global initialization needed for Ring *
  44. * RingRenderObjClass::Shutdown_Ring_Render_System -- cleanup Ring render system *
  45. * RingRenderObjClass::Set_Ring_Display_Mask -- Sets global display mask for all Ringes *
  46. * RingRenderObjClass::Get_Ring_Display_Mask -- returns the display mask *
  47. * RingRenderObjClass::update_mesh_data -- Updates vertex positions, etc *
  48. * RingRenderObjClass::render_Ring -- submits the Ring to the GERD *
  49. * RingRenderObjClass::vis_render_Ring -- submits Ring to the GERD for VIS *
  50. * RingRenderObjClass::RingRenderObjClass -- constructor *
  51. * RingRenderObjClass::RingRenderObjClass -- Constructor - init from a definition *
  52. * RingRenderObjClass::RingRenderObjClass -- copy constructor *
  53. * RingRenderObjClass::RingRenderObjClass -- Constructor from a wwmath aaRing *
  54. * RingRenderObjClass::operator -- assignment operator *
  55. * RingRenderObjClass::Clone -- clones the Ring *
  56. * RingRenderObjClass::Class_ID -- returns the class-id for AARing's *
  57. * RingRenderObjClass::Render -- render this Ring *
  58. * RingRenderObjClass::Special_Render -- special render this Ring (vis) *
  59. * RingRenderObjClass::Set_Transform -- set the transform for this Ring *
  60. * RingRenderObjClass::Set_Position -- Set the position of this Ring *
  61. * RingRenderObjClass::update_cached_Ring -- update the world-space version of this Ring *
  62. * RingRenderObjClass::Cast_Ray -- cast a ray against this Ring *
  63. * RingRenderObjClass::Cast_AARing -- cast an AARing against this Ring *
  64. * RingRenderObjClass::Cast_OBRing -- cast an OBRing against this Ring *
  65. * RingRenderObjClass::Get_Obj_Space_Bounding_Sphere -- return the object-space bounding sper*
  66. * RingRenderObjClass::Get_Obj_Space_Bounding_Box -- returns the obj-space bounding box *
  67. * RingRenderObjClass::Scale -- scales ring uniformly. *
  68. * RingRenderObjClass::Scale -- scales ring non-uniformly. *
  69. * RingRenderObjClass::Update_Cached_Bounding_Volumes -- Updates world-space bounding volum *
  70. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  71. #include "ringobj.h"
  72. #include "w3d_util.h"
  73. #include "wwdebug.h"
  74. #include "vertmaterial.h"
  75. #include "ww3d.h"
  76. #include "chunkio.h"
  77. #include "rinfo.h"
  78. #include "coltest.h"
  79. #include "inttest.h"
  80. #include "matrix3.h"
  81. #include "wwmath.h"
  82. #include "assetmgr.h"
  83. #include "wwstring.h"
  84. #include "bound.h"
  85. #include "camera.h"
  86. #include "statistics.h"
  87. #include "predlod.h"
  88. #include "dx8wrapper.h"
  89. #include "dx8indexbuffer.h"
  90. #include "dx8vertexbuffer.h"
  91. #include "sortingrenderer.h"
  92. #include "vector3i.h"
  93. #include "visrasterizer.h"
  94. static bool Ring_Array_Valid = false;
  95. /**
  96. ** RingMeshClass
  97. ** A set of LODs of RingMeshes are re-used by all RingRenderObjClasses.
  98. */
  99. class RingMeshClass
  100. {
  101. friend class RingRenderObjClass;
  102. public:
  103. // Constructor
  104. RingMeshClass(void);
  105. RingMeshClass(float radius, int slices);
  106. // Destructor
  107. ~RingMeshClass(void);
  108. void Generate(float radius, int slices);
  109. int Get_Num_Polys(void) { return face_ct; };
  110. void Scale (const Vector2 &inner_scale, const Vector2 &outer_scale);
  111. void Set_Tiling (int count);
  112. private:
  113. void Free(void);
  114. float Radius;
  115. int Slices;
  116. int face_ct; //# of faces
  117. int TileCount;
  118. Vector2 InnerScale;
  119. Vector2 OuterScale;
  120. int Vertex_ct; // vertex count
  121. Vector3 *vtx; // array of vertices
  122. Vector2 *orig_vtx; // array of vertices representing a 'unit' ring
  123. Vector3 *vtx_normal; // array of vertex normals
  124. Vector2 *vtx_uv; // array of vertex uv coordinates
  125. TriIndex *tri_poly; // array of triangle polys, vertex indices (can be discard if switch to fan renderer)
  126. };
  127. RingMeshClass RingMeshArray[RING_NUM_LOD];
  128. float RingLODCosts[RING_NUM_LOD + 1]; // RING_NUM_LOD doesn't include the null LOD
  129. /*
  130. ** RingRenderObjClass Implementation
  131. */
  132. /***********************************************************************************************
  133. * RingRenderObjClass::RingRenderObjClass -- Constructor *
  134. * *
  135. * INPUT: *
  136. * *
  137. * OUTPUT: *
  138. * *
  139. * WARNINGS: *
  140. * *
  141. * HISTORY: *
  142. * 1/19/00 gth : Created. *
  143. *=============================================================================================*/
  144. RingRenderObjClass::RingRenderObjClass(void)
  145. : anim_time (0.0F),
  146. IsAnimating(false),
  147. LODBias(1.0f),
  148. CurrentLOD(RING_NUM_LOD), // RING_NUM_LOD does not include the null LOD
  149. AnimDuration (0.0F),
  150. RingMaterial (NULL),
  151. RingTexture (NULL),
  152. Color (0.75F,0.75F,0.75F),
  153. InnerScale (1, 1),
  154. OuterScale (1, 1),
  155. Alpha (1.0F),
  156. Flags(0),
  157. TextureTileCount(5),
  158. ObjSpaceCenter (0, 0, 0),
  159. ObjSpaceExtent (1, 1, 1),
  160. InnerExtent (0.5F, 0.5F),
  161. OuterExtent (1.0F, 1.0F)
  162. {
  163. Generate_Shared_Mesh_Arrays ();
  164. memset(Name,0,sizeof(Name));
  165. Init_Material () ;
  166. // So that the object is ready for use after construction, we will
  167. // complete its initialization by initializing its value array
  168. // according to a screen area of 1.
  169. calculate_value_array(1.0f, Value);
  170. }
  171. /***********************************************************************************************
  172. * RingRenderObjClass::RingRenderObjClass -- Constructor - init from a definition *
  173. * *
  174. * INPUT: *
  175. * *
  176. * OUTPUT: *
  177. * *
  178. * WARNINGS: *
  179. * *
  180. * HISTORY: *
  181. * 1/19/00 gth : Created. *
  182. *=============================================================================================*/
  183. RingRenderObjClass::RingRenderObjClass(const W3dRingStruct & def)
  184. : anim_time (0.0F),
  185. IsAnimating(false),
  186. LODBias(1.0f),
  187. CurrentLOD(RING_NUM_LOD), // RING_NUM_LOD does not include the null LOD
  188. AnimDuration (0.0F),
  189. RingMaterial (NULL),
  190. RingTexture (NULL),
  191. Color (0.75F,0.75F,0.75F),
  192. InnerScale (1, 1),
  193. OuterScale (1, 1),
  194. Alpha (1.0F),
  195. Flags(0),
  196. TextureTileCount(5),
  197. ObjSpaceCenter (0, 0, 0),
  198. ObjSpaceExtent (1, 1, 1),
  199. InnerExtent (0.5F, 0.5F),
  200. OuterExtent (1.0F, 1.0F)
  201. {
  202. Generate_Shared_Mesh_Arrays ();
  203. Init_Material ();
  204. //
  205. // Initialize from the defintion
  206. //
  207. Set_Name(def.Name);
  208. Set_Local_Center_Extent ( Vector3 (def.Center.X, def.Center.Y, def.Center.Z),
  209. Vector3 (def.Extent.X, def.Extent.Y, def.Extent.Z));
  210. if (def.TextureName[0] != 0) {
  211. RingTexture = WW3DAssetManager::Get_Instance ()->Get_Texture (def.TextureName);
  212. }
  213. // So that the object is ready for use after construction, we will
  214. // complete its initialization by initializing its value array
  215. // according to a screen area of 1.
  216. calculate_value_array(1.0f, Value);
  217. }
  218. /***********************************************************************************************
  219. * RingRenderObjClass::RingRenderObjClass -- Copy constructor *
  220. * *
  221. * INPUT: *
  222. * *
  223. * OUTPUT: *
  224. * *
  225. * WARNINGS: *
  226. * *
  227. * HISTORY: *
  228. * 1/19/00 gth : Created. *
  229. *=============================================================================================*/
  230. RingRenderObjClass::RingRenderObjClass(const RingRenderObjClass & src)
  231. : anim_time (0.0F),
  232. IsAnimating(false),
  233. LODBias(1.0f),
  234. CurrentLOD(RING_NUM_LOD), // RING_NUM_LOD does not include the null LOD
  235. AnimDuration (0.0F),
  236. RingMaterial (NULL),
  237. RingTexture (NULL),
  238. Color (0.75F,0.75F,0.75F),
  239. InnerScale (1, 1),
  240. OuterScale (1, 1),
  241. Alpha (1.0F),
  242. Flags(0),
  243. TextureTileCount(5),
  244. ObjSpaceCenter (0, 0, 0),
  245. ObjSpaceExtent (1, 1, 1),
  246. InnerExtent (0.5F, 0.5F),
  247. OuterExtent (1.0F, 1.0F)
  248. {
  249. Generate_Shared_Mesh_Arrays ();
  250. Init_Material ();
  251. *this = src;
  252. // So that the object is ready for use after construction, we will
  253. // complete its initialization by initializing its value array
  254. // according to a screen area of 1.
  255. calculate_value_array(1.0f, Value);
  256. }
  257. /***********************************************************************************************
  258. * RingRenderObjClass::~RingRenderObjClass -- destructor *
  259. * *
  260. * INPUT: *
  261. * *
  262. * OUTPUT: *
  263. * *
  264. * WARNINGS: *
  265. * *
  266. * HISTORY: *
  267. * 2/7/2001 gth : Created. *
  268. *=============================================================================================*/
  269. RingRenderObjClass::~RingRenderObjClass()
  270. {
  271. REF_PTR_RELEASE(RingMaterial);
  272. REF_PTR_RELEASE(RingTexture);
  273. } // destructor
  274. /***********************************************************************************************
  275. * RingRenderObjClass::operator -- assignment operator *
  276. * *
  277. * INPUT: *
  278. * *
  279. * OUTPUT: *
  280. * *
  281. * WARNINGS: *
  282. * *
  283. * HISTORY: *
  284. * 1/19/00 gth : Created. *
  285. *=============================================================================================*/
  286. RingRenderObjClass & RingRenderObjClass::operator = (const RingRenderObjClass & that)
  287. {
  288. if (this != &that) {
  289. RenderObjClass::operator = (that);
  290. Set_Name(that.Get_Name());
  291. Color = that.Color;
  292. Alpha = that.Alpha;
  293. InnerScale = that.InnerScale;
  294. OuterScale = that.OuterScale;
  295. Flags = that.Flags;
  296. RingShader = that.RingShader;
  297. CachedBox = that.CachedBox;
  298. anim_time = that.anim_time;
  299. AnimDuration = that.AnimDuration;
  300. ObjSpaceCenter = that.ObjSpaceCenter;
  301. ObjSpaceExtent = that.ObjSpaceExtent;
  302. ColorChannel = that.ColorChannel;
  303. AlphaChannel = that.AlphaChannel;
  304. InnerScaleChannel = that.InnerScaleChannel;
  305. OuterScaleChannel = that.OuterScaleChannel;
  306. InnerExtent = that.InnerExtent;
  307. OuterExtent = that.OuterExtent;
  308. TextureTileCount = that.TextureTileCount;
  309. Set_Texture (that.RingTexture);
  310. }
  311. return *this;
  312. }
  313. /***********************************************************************************************
  314. * RingRenderObjClass::Generate_Shared_Mesh_Arrays -- Generates mesh LOD arrays. *
  315. * *
  316. * INPUT: *
  317. * *
  318. * OUTPUT: *
  319. * *
  320. * WARNINGS: *
  321. * *
  322. * HISTORY: *
  323. * 03/08/00 pds : Created. *
  324. *=============================================================================================*/
  325. void RingRenderObjClass::Generate_Shared_Mesh_Arrays (void)
  326. {
  327. // Generate shared Mesh Arrays
  328. if (!Ring_Array_Valid) {
  329. float size = RING_LOWEST_LOD;
  330. float step = (RING_HIGHEST_LOD - RING_LOWEST_LOD);
  331. step /= RING_NUM_LOD;
  332. // For NULL LOD set Cost to a small nonzero amount to avoid divisions by zero.
  333. RingLODCosts[0] = 0.000001f;
  334. for(int i=0; i < RING_NUM_LOD; i++) {
  335. RingMeshArray[i].Generate(1.0f, size);
  336. RingLODCosts[i + 1] = RingMeshArray[i].Get_Num_Polys();
  337. size+=step;
  338. }
  339. Ring_Array_Valid = true;
  340. }
  341. return ;
  342. }
  343. // This is used both by Prepare_LOD and Calculate_Cost_Value_Arrays.
  344. void RingRenderObjClass::calculate_value_array(float screen_area, float *values) const
  345. {
  346. values[0] = AT_MIN_LOD;
  347. for (int lod = 1; lod <= RING_NUM_LOD; lod++) {
  348. float polycount = RingLODCosts[lod];
  349. float benefit_factor = 1 - (0.5f / (polycount * polycount));
  350. values[lod] = (benefit_factor * screen_area * LODBias) / polycount;
  351. }
  352. values[RING_NUM_LOD + 1] = AT_MAX_LOD; // Post-inc value will flag max LOD.
  353. }
  354. /***********************************************************************************************
  355. * RingRenderObjClass::Init_Material -- Sets up the material and default shader for the Ring.*
  356. * *
  357. * INPUT: *
  358. * *
  359. * OUTPUT: *
  360. * *
  361. * WARNINGS: *
  362. * *
  363. * HISTORY: *
  364. * 03/08/00 pds : Created. *
  365. *=============================================================================================*/
  366. void RingRenderObjClass::Init_Material (void)
  367. {
  368. REF_PTR_RELEASE (RingMaterial);
  369. RingMaterial = NEW_REF(VertexMaterialClass,());
  370. RingMaterial->Set_Ambient(0,0,0);
  371. RingMaterial->Set_Diffuse(0,0,0);
  372. RingMaterial->Set_Specular(0,0,0);
  373. RingMaterial->Set_Emissive(1,1,1);
  374. RingMaterial->Set_Opacity(0.25f);
  375. RingMaterial->Set_Shininess(0.0f);
  376. // Texturing, zbuffer, primary gradient, alpha blending
  377. RingShader = ShaderClass::_PresetAlphaShader;
  378. } // Init_Material
  379. /***********************************************************************************************
  380. * RingRenderObjClass::Get_Num_Polys -- returns number of polygons *
  381. * *
  382. * INPUT: *
  383. * *
  384. * OUTPUT: *
  385. * *
  386. * WARNINGS: *
  387. * *
  388. * HISTORY: *
  389. * 1/19/00 gth : Created. *
  390. *=============================================================================================*/
  391. int RingRenderObjClass::Get_Num_Polys(void) const
  392. {
  393. return RingLODCosts[CurrentLOD];
  394. }
  395. /***********************************************************************************************
  396. * RingRenderObjClass::Set_Texture *
  397. * *
  398. * INPUT: *
  399. * *
  400. * OUTPUT: *
  401. * *
  402. * WARNINGS: *
  403. * *
  404. * HISTORY: *
  405. * 1/19/00 gth : Created. *
  406. *=============================================================================================*/
  407. void RingRenderObjClass::Set_Texture(TextureClass *tf)
  408. {
  409. REF_PTR_SET(RingTexture,tf);
  410. }
  411. /***********************************************************************************************
  412. * RingRenderObjClass::Get_Name -- returns name *
  413. * *
  414. * INPUT: *
  415. * *
  416. * OUTPUT: *
  417. * *
  418. * WARNINGS: *
  419. * *
  420. * HISTORY: *
  421. * 1/19/00 gth : Created. *
  422. *=============================================================================================*/
  423. const char * RingRenderObjClass::Get_Name(void) const
  424. {
  425. return Name;
  426. }
  427. /***********************************************************************************************
  428. * RingRenderObjClass::Set_Name -- sets the name *
  429. * *
  430. * INPUT: *
  431. * *
  432. * OUTPUT: *
  433. * *
  434. * WARNINGS: *
  435. * *
  436. * HISTORY: *
  437. * 1/19/00 gth : Created. *
  438. *=============================================================================================*/
  439. void RingRenderObjClass::Set_Name(const char * name)
  440. {
  441. WWASSERT(name != NULL);
  442. WWASSERT(strlen(name) < 2*W3D_NAME_LEN);
  443. strcpy(Name,name);
  444. }
  445. /***********************************************************************************************
  446. * RingRenderObjClass::render_ring -- submits the box to the GERD *
  447. * *
  448. * INPUT: *
  449. * *
  450. * OUTPUT: *
  451. * *
  452. * WARNINGS: *
  453. * *
  454. * HISTORY: *
  455. * 1/19/00 gth : Created. *
  456. *=============================================================================================*/
  457. void RingRenderObjClass::render_ring(RenderInfoClass & rinfo,const Vector3 & center,const Vector3 & extent)
  458. {
  459. // Should never get here with NULL LOD
  460. if (CurrentLOD == 0) {
  461. WWASSERT(0);
  462. return;
  463. }
  464. RingMeshClass & ring = RingMeshArray[CurrentLOD - 1];
  465. if (RingTexture) {
  466. RingShader.Set_Texturing (ShaderClass::TEXTURING_ENABLE);
  467. } else {
  468. RingShader.Set_Texturing (ShaderClass::TEXTURING_DISABLE);
  469. }
  470. DX8Wrapper::Set_Shader(RingShader);
  471. DX8Wrapper::Set_Texture(0,RingTexture);
  472. DX8Wrapper::Set_Material(RingMaterial);
  473. // Enable sorting if the primitive is translucent, alpha testing is not enabled, and sorting is enabled globally.
  474. const bool sort = (RingShader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO) && (RingShader.Get_Alpha_Test() == ShaderClass::ALPHATEST_DISABLE) && (WW3D::Is_Sorting_Enabled());
  475. const unsigned int buffer_type = sort ? BUFFER_TYPE_DYNAMIC_SORTING : BUFFER_TYPE_DYNAMIC_DX8;
  476. DynamicVBAccessClass vb(buffer_type, dynamic_fvf_type, ring.Vertex_ct);
  477. {
  478. DynamicVBAccessClass::WriteLockClass Lock(&vb);
  479. VertexFormatXYZNDUV2 *vb = Lock.Get_Formatted_Vertex_Array();
  480. //
  481. // set up the vertex color+alpha
  482. //
  483. unsigned color;
  484. if (RingShader.Get_Dst_Blend_Func () == ShaderClass::DSTBLEND_ONE) {
  485. color = DX8Wrapper::Convert_Color(Alpha * Color,1.0f);
  486. } else {
  487. color = DX8Wrapper::Convert_Color(Color,Alpha);
  488. }
  489. for (int i=0; i<ring.Vertex_ct; i++)
  490. {
  491. vb->x = ring.vtx[i].X;
  492. vb->y = ring.vtx[i].Y;
  493. vb->z = ring.vtx[i].Z;
  494. vb->nx = ring.vtx_normal[i].X; // may not need this!
  495. vb->ny = ring.vtx_normal[i].Y;
  496. vb->nz = ring.vtx_normal[i].Z;
  497. vb->diffuse = color;
  498. if (RingTexture) {
  499. vb->u1 = ring.vtx_uv[i].X;
  500. vb->v1 = ring.vtx_uv[i].Y;
  501. }
  502. vb++;
  503. }
  504. }
  505. DynamicIBAccessClass ib(buffer_type, ring.face_ct * 3);
  506. {
  507. DynamicIBAccessClass::WriteLockClass Lock(&ib);
  508. unsigned short *mem=Lock.Get_Index_Array();
  509. for (int i=0; i<ring.face_ct; i++)
  510. {
  511. mem[3*i]=ring.tri_poly[i].I;
  512. mem[3*i+1]=ring.tri_poly[i].J;
  513. mem[3*i+2]=ring.tri_poly[i].K;
  514. }
  515. }
  516. DX8Wrapper::Set_Vertex_Buffer(vb);
  517. DX8Wrapper::Set_Index_Buffer(ib,0);
  518. if (sort) {
  519. SortingRendererClass::Insert_Triangles(Get_Bounding_Sphere(), 0, ring.face_ct, 0, ring.Vertex_ct);
  520. } else {
  521. DX8Wrapper::Draw_Triangles(0, ring.face_ct, 0, ring.Vertex_ct);
  522. }
  523. } // render_ring
  524. /***********************************************************************************************
  525. * RingRenderObjClass::vis_render_ring -- submits box to the GERD for VIS *
  526. * *
  527. * this renders the ring with the specified VIS-ID. *
  528. * *
  529. * INPUT: *
  530. * *
  531. * OUTPUT: *
  532. * *
  533. * WARNINGS: *
  534. * *
  535. * HISTORY: *
  536. * 1/19/00 gth : Created. *
  537. *=============================================================================================*/
  538. void RingRenderObjClass::vis_render_ring(SpecialRenderInfoClass & rinfo,const Vector3 & center,const Vector3 & extent)
  539. {
  540. WWASSERT(0);
  541. } // vis_render_ring
  542. /***********************************************************************************************
  543. * RingRenderObjClass::Clone -- clones the ring *
  544. * *
  545. * INPUT: *
  546. * *
  547. * OUTPUT: *
  548. * *
  549. * WARNINGS: *
  550. * *
  551. * HISTORY: *
  552. * 1/19/00 gth : Created. *
  553. *=============================================================================================*/
  554. RenderObjClass * RingRenderObjClass::Clone(void) const
  555. {
  556. return W3DNEW RingRenderObjClass(*this);
  557. }
  558. /***********************************************************************************************
  559. * RingRenderObjClass::Class_ID -- returns the class-id for Rings's *
  560. * *
  561. * INPUT: *
  562. * *
  563. * OUTPUT: *
  564. * *
  565. * WARNINGS: *
  566. * *
  567. * HISTORY: *
  568. * 1/19/00 gth : Created. *
  569. *=============================================================================================*/
  570. int RingRenderObjClass::Class_ID(void) const
  571. {
  572. return RenderObjClass::CLASSID_RING;
  573. }
  574. /***********************************************************************************************
  575. * RingRenderObjClass::Render -- render this ring *
  576. * *
  577. * INPUT: *
  578. * *
  579. * OUTPUT: *
  580. * *
  581. * WARNINGS: *
  582. * *
  583. * HISTORY: *
  584. * 1/19/00 gth : Created. *
  585. *=============================================================================================*/
  586. void RingRenderObjClass::Render(RenderInfoClass & rinfo)
  587. {
  588. // NULL LOD
  589. if (CurrentLOD == 0) return;
  590. if (Is_Not_Hidden_At_All() == false) {
  591. return;
  592. }
  593. unsigned int sort_level = SORT_LEVEL_NONE;
  594. if (!WW3D::Is_Sorting_Enabled()) {
  595. sort_level = RingShader.Guess_Sort_Level();
  596. }
  597. if (WW3D::Are_Static_Sort_Lists_Enabled() && sort_level != SORT_LEVEL_NONE) {
  598. WW3D::Add_To_Static_Sort_List(this, sort_level);
  599. } else {
  600. // Process texture reductions:
  601. // if (RingTexture) RingTexture->Process_Reduction();
  602. Matrix3D temp = Transform;
  603. // Do Time Based Animation
  604. animate ();
  605. //
  606. // Scale the inner and outer parts of the ring.
  607. //
  608. Vector2 inner_scale (InnerExtent.X * InnerScale.X, InnerExtent.Y * InnerScale.Y);
  609. Vector2 outer_scale (OuterExtent.X * OuterScale.X, OuterExtent.Y * OuterScale.Y);
  610. RingMeshArray[CurrentLOD - 1].Scale(inner_scale, outer_scale);
  611. //
  612. // Make sure this mesh uses the correct UV tiling
  613. //
  614. if (RingTexture != NULL) {
  615. RingMeshArray[CurrentLOD - 1].Set_Tiling (TextureTileCount);
  616. }
  617. //
  618. // Should we force the ring to be camera aligned?
  619. // (this will cause the ring to be parallel to the screen)
  620. //
  621. if (Flags & USE_CAMERA_ALIGN) {
  622. Vector3 obj_position;
  623. Vector3 camera_z_vector;
  624. rinfo.Camera.Get_Transform().Get_Z_Vector(&camera_z_vector);
  625. Transform.Get_Translation(&obj_position);
  626. Matrix3D temp;
  627. temp.Look_At(obj_position, obj_position + camera_z_vector, 0.0f);
  628. DX8Wrapper::Set_Transform(D3DTS_WORLD, temp);
  629. } else {
  630. DX8Wrapper::Set_Transform(D3DTS_WORLD, Transform);
  631. }
  632. //
  633. // Pass the geometry on to DX8
  634. //
  635. render_ring (rinfo, ObjSpaceCenter, ObjSpaceExtent);
  636. }
  637. } // Render
  638. /***********************************************************************************************
  639. * RingRenderObjClass::Get_Default_Color - get the default (or first frame) value *
  640. * *
  641. * INPUT: *
  642. * *
  643. * OUTPUT: *
  644. * *
  645. * WARNINGS: *
  646. * *
  647. * HISTORY: *
  648. * 3/13/2000 pds : Created. *
  649. *=============================================================================================*/
  650. Vector3 RingRenderObjClass::Get_Default_Color(void) const
  651. {
  652. Vector3 value;
  653. if (ColorChannel.Get_Key_Count () > 0) {
  654. value = ColorChannel.Get_Key (0).Get_Value ();
  655. } else {
  656. value = Color;
  657. }
  658. return value;
  659. }
  660. /***********************************************************************************************
  661. * RingRenderObjClass::Get_Default_Alpha - get the default (or first frame) value *
  662. * *
  663. * INPUT: *
  664. * *
  665. * OUTPUT: *
  666. * *
  667. * WARNINGS: *
  668. * *
  669. * HISTORY: *
  670. * 3/13/2000 pds : Created. *
  671. *=============================================================================================*/
  672. float RingRenderObjClass::Get_Default_Alpha(void) const
  673. {
  674. float value;
  675. if (AlphaChannel.Get_Key_Count () > 0) {
  676. value = AlphaChannel.Get_Key (0).Get_Value ();
  677. } else {
  678. value = Alpha;
  679. }
  680. return value;
  681. }
  682. /***********************************************************************************************
  683. * RingRenderObjClass::Get_Default_Inner_Scale - get the default (or first frame) value *
  684. * *
  685. * INPUT: *
  686. * *
  687. * OUTPUT: *
  688. * *
  689. * WARNINGS: *
  690. * *
  691. * HISTORY: *
  692. * 3/13/2000 pds : Created. *
  693. *=============================================================================================*/
  694. Vector2 RingRenderObjClass::Get_Default_Inner_Scale(void) const
  695. {
  696. Vector2 value;
  697. if (InnerScaleChannel.Get_Key_Count () > 0) {
  698. value = InnerScaleChannel.Get_Key (0).Get_Value ();
  699. } else {
  700. value = InnerScale;
  701. }
  702. return value;
  703. }
  704. /***********************************************************************************************
  705. * RingRenderObjClass::Get_Default_Outer_Scale - get the default (or first frame) value *
  706. * *
  707. * INPUT: *
  708. * *
  709. * OUTPUT: *
  710. * *
  711. * WARNINGS: *
  712. * *
  713. * HISTORY: *
  714. * 3/13/2000 pds : Created. *
  715. *=============================================================================================*/
  716. Vector2 RingRenderObjClass::Get_Default_Outer_Scale(void) const
  717. {
  718. Vector2 value;
  719. if (OuterScaleChannel.Get_Key_Count () > 0) {
  720. value = OuterScaleChannel.Get_Key (0).Get_Value ();
  721. } else {
  722. value = OuterScale;
  723. }
  724. return value;
  725. }
  726. /***********************************************************************************************
  727. * RingRenderObjClass::Special_Render -- special render this box (vis) *
  728. * *
  729. * INPUT: *
  730. * *
  731. * OUTPUT: *
  732. * *
  733. * WARNINGS: *
  734. , * *
  735. * HISTORY: *
  736. * 1/19/00 gth : Created. *
  737. *=============================================================================================*/
  738. void RingRenderObjClass::Special_Render(SpecialRenderInfoClass & rinfo)
  739. {
  740. Matrix3D temp(1);
  741. temp.Translate(Transform.Get_Translation());
  742. if (rinfo.RenderType == SpecialRenderInfoClass::RENDER_VIS) {
  743. WWASSERT(rinfo.VisRasterizer != NULL);
  744. rinfo.VisRasterizer->Set_Model_Transform(temp);
  745. vis_render_ring(rinfo,ObjSpaceCenter,ObjSpaceExtent);
  746. }
  747. }
  748. /***********************************************************************************************
  749. * RingRenderObjClass::Set_Transform -- set the transform for this box *
  750. * *
  751. * INPUT: *
  752. * *
  753. * OUTPUT: *
  754. * *
  755. * WARNINGS: *
  756. * *
  757. * HISTORY: *
  758. * 1/19/00 gth : Created. *
  759. *=============================================================================================*/
  760. void RingRenderObjClass::Set_Transform(const Matrix3D &m)
  761. {
  762. RenderObjClass::Set_Transform(m);
  763. update_cached_box();
  764. }
  765. /***********************************************************************************************
  766. * RingRenderObjClass::Set_Position -- Set the position of this box *
  767. * *
  768. * INPUT: *
  769. * *
  770. * OUTPUT: *
  771. * *
  772. * WARNINGS: *
  773. * *
  774. * HISTORY: *
  775. * 1/19/00 gth : Created. *
  776. *=============================================================================================*/
  777. void RingRenderObjClass::Set_Position(const Vector3 &v)
  778. {
  779. RenderObjClass::Set_Position(v);
  780. update_cached_box();
  781. }
  782. /***********************************************************************************************
  783. * RingRenderObjClass::update_cached_box -- update the world-space version of this box *
  784. * *
  785. * INPUT: *
  786. * *
  787. * OUTPUT: *
  788. * *
  789. * WARNINGS: *
  790. * *
  791. * HISTORY: *
  792. * 1/19/00 gth : Created. *
  793. *=============================================================================================*/
  794. void RingRenderObjClass::update_cached_box(void)
  795. {
  796. CachedBox.Center = Transform.Get_Translation() + ObjSpaceCenter;
  797. CachedBox.Extent = ObjSpaceExtent;
  798. }
  799. /***********************************************************************************************
  800. * RingRenderObjClass::Get_Obj_Space_Bounding_Ring -- return the object-space bounding sphe *
  801. * *
  802. * INPUT: *
  803. * *
  804. * OUTPUT: *
  805. * *
  806. * WARNINGS: *
  807. * *
  808. * HISTORY: *
  809. * 1/19/00 gth : Created. *
  810. *=============================================================================================*/
  811. void RingRenderObjClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
  812. {
  813. sphere.Center = ObjSpaceCenter;
  814. sphere.Radius = ObjSpaceExtent.Length();
  815. }
  816. /***********************************************************************************************
  817. * RingRenderObjClass::Get_Obj_Space_Bounding_Box -- returns the obj-space bounding box *
  818. * *
  819. * INPUT: *
  820. * *
  821. * OUTPUT: *
  822. * *
  823. * WARNINGS: *
  824. * *
  825. * HISTORY: *
  826. * 1/19/00 gth : Created. *
  827. *=============================================================================================*/
  828. void RingRenderObjClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
  829. {
  830. box.Center = ObjSpaceCenter;
  831. box.Extent = ObjSpaceExtent;
  832. }
  833. void RingRenderObjClass::Prepare_LOD(CameraClass &camera)
  834. {
  835. if (Is_Not_Hidden_At_All() == false) {
  836. return;
  837. }
  838. calculate_value_array(Get_Screen_Size(camera), Value);
  839. PredictiveLODOptimizerClass::Add_Object(this);
  840. }
  841. void RingRenderObjClass::Increment_LOD(void)
  842. {
  843. if (CurrentLOD < RING_NUM_LOD) CurrentLOD++;
  844. }
  845. void RingRenderObjClass::Decrement_LOD(void)
  846. {
  847. if (CurrentLOD > 0) CurrentLOD--;
  848. }
  849. float RingRenderObjClass::Get_Cost(void) const
  850. {
  851. return Get_Num_Polys(); // Currently cost == polys
  852. }
  853. float RingRenderObjClass::Get_Value(void) const
  854. {
  855. return Value[CurrentLOD];
  856. }
  857. float RingRenderObjClass::Get_Post_Increment_Value(void) const
  858. {
  859. return Value[CurrentLOD + 1];
  860. }
  861. void RingRenderObjClass::Set_LOD_Level(int lod)
  862. {
  863. CurrentLOD = Bound(lod, 0, RING_NUM_LOD); // RING_NUM_LOD doesn't include the null LOD
  864. }
  865. int RingRenderObjClass::Get_LOD_Level(void) const
  866. {
  867. return CurrentLOD;
  868. }
  869. int RingRenderObjClass::Get_LOD_Count(void) const
  870. {
  871. return RING_NUM_LOD + 1; // RING_NUM_LOD doesn't include the null LOD
  872. }
  873. int RingRenderObjClass::Calculate_Cost_Value_Arrays(float screen_area, float *values, float *costs) const
  874. {
  875. calculate_value_array(screen_area, values);
  876. for (int lod = 0; lod <= RING_NUM_LOD; lod++) {
  877. costs[lod] = RingLODCosts[lod];
  878. }
  879. // We currently don't support max screen size or minimum LOD clamping for ring objects
  880. return 0;
  881. }
  882. /***********************************************************************************************
  883. * RingRenderObjClass::Scale -- scales ring uniformly. *
  884. * *
  885. * INPUT: *
  886. * *
  887. * OUTPUT: *
  888. * *
  889. * WARNINGS: *
  890. * *
  891. * HISTORY: *
  892. * 7/01/02 NH : Created. *
  893. *=============================================================================================*/
  894. void RingRenderObjClass::Scale(float scale)
  895. {
  896. if (scale == 1.0f) return;
  897. // Scale default values
  898. InnerScale *= scale;
  899. OuterScale *= scale;
  900. // Loop over all keys in inner and outer scale channel and scale values.
  901. int i;
  902. int inner_count = InnerScaleChannel.Get_Key_Count();
  903. for (i = 0; i < inner_count; i++) {
  904. const PrimitiveAnimationChannelClass<Vector2>::KeyClass &key = InnerScaleChannel.Get_Key(i);
  905. InnerScaleChannel.Set_Key_Value(i, key.Get_Value() * scale);
  906. }
  907. int outer_count = OuterScaleChannel.Get_Key_Count();
  908. for (i = 0; i < outer_count; i++) {
  909. const PrimitiveAnimationChannelClass<Vector2>::KeyClass &key = OuterScaleChannel.Get_Key(i);
  910. OuterScaleChannel.Set_Key_Value(i, key.Get_Value() * scale);
  911. }
  912. }
  913. /***********************************************************************************************
  914. * RingRenderObjClass::Scale -- scales ring non-uniformly. *
  915. * *
  916. * INPUT: *
  917. * *
  918. * OUTPUT: *
  919. * *
  920. * WARNINGS: *
  921. * *
  922. * HISTORY: *
  923. * 7/01/02 NH : Created. *
  924. *=============================================================================================*/
  925. void RingRenderObjClass::Scale(float scalex, float scaley, float scalez)
  926. {
  927. // Scale default values
  928. InnerScale.X *= scalex;
  929. InnerScale.Y *= scaley;
  930. OuterScale.X *= scalex;
  931. OuterScale.Y *= scaley;
  932. // Loop over all keys in inner and outer scale channel and scale values.
  933. int i;
  934. int inner_count = InnerScaleChannel.Get_Key_Count();
  935. for (i = 0; i < inner_count; i++) {
  936. const PrimitiveAnimationChannelClass<Vector2>::KeyClass &key = InnerScaleChannel.Get_Key(i);
  937. Vector2 key_val = key.Get_Value();
  938. key_val.X *= scalex;
  939. key_val.Y *= scaley;
  940. InnerScaleChannel.Set_Key_Value(i, key_val);
  941. }
  942. int outer_count = OuterScaleChannel.Get_Key_Count();
  943. for (i = 0; i < outer_count; i++) {
  944. const PrimitiveAnimationChannelClass<Vector2>::KeyClass &key = OuterScaleChannel.Get_Key(i);
  945. Vector2 key_val = key.Get_Value();
  946. key_val.X *= scalex;
  947. key_val.Y *= scaley;
  948. OuterScaleChannel.Set_Key_Value(i, key_val);
  949. }
  950. }
  951. /***********************************************************************************************
  952. * RingRenderObjClass::Update_On_Visibilty -- Either starts or stops the animation based on vis*
  953. * *
  954. * INPUT: *
  955. * *
  956. * OUTPUT: *
  957. * *
  958. * WARNINGS: *
  959. * *
  960. * HISTORY: *
  961. * 4/04/00 pds : Created. *
  962. *=============================================================================================*/
  963. void RingRenderObjClass::Update_On_Visibilty(void)
  964. {
  965. // Simply start or stop the animation based on
  966. // the visibility state of the primitive.
  967. if (Is_Not_Hidden_At_All () && Is_Animating () == false) {
  968. Start_Animating ();
  969. } else if ((Is_Not_Hidden_At_All () == false) && Is_Animating ()) {
  970. Stop_Animating ();
  971. }
  972. return ;
  973. }
  974. /***********************************************************************************************
  975. * RingRenderObjClass::animate -- Update Current Display state *
  976. * *
  977. * INPUT: *
  978. * *
  979. * OUTPUT: *
  980. * *
  981. * WARNINGS: *
  982. * *
  983. * HISTORY: *
  984. * 3/07/00 jga : Created. *
  985. *=============================================================================================*/
  986. void RingRenderObjClass::animate()
  987. {
  988. if (Is_Animating ()) {
  989. if ( ColorChannel.Get_Key_Count () > 0 ||
  990. AlphaChannel.Get_Key_Count () > 0 ||
  991. InnerScaleChannel.Get_Key_Count () > 0 ||
  992. OuterScaleChannel.Get_Key_Count () > 0)
  993. {
  994. //
  995. // Convert from milliseconds to seconds and normalize the time
  996. //
  997. if (AnimDuration > 0) {
  998. float frametime = WW3D::Get_Frame_Time();
  999. frametime = (frametime * 0.001F) / AnimDuration;
  1000. anim_time += frametime;
  1001. } else {
  1002. anim_time = 1.0F;
  1003. }
  1004. WWASSERT (anim_time >= 0.0F);
  1005. if ((Flags & USE_ANIMATION_LOOP) && anim_time > 1.0F) {
  1006. anim_time -= 1.0F;
  1007. }
  1008. if (ColorChannel.Get_Key_Count () > 0) {
  1009. Color = ColorChannel.Evaluate (anim_time);
  1010. }
  1011. if (AlphaChannel.Get_Key_Count () > 0) {
  1012. Alpha = AlphaChannel.Evaluate (anim_time);
  1013. }
  1014. if (InnerScaleChannel.Get_Key_Count () > 0) {
  1015. InnerScale = InnerScaleChannel.Evaluate (anim_time);
  1016. }
  1017. if (OuterScaleChannel.Get_Key_Count () > 0) {
  1018. OuterScale = OuterScaleChannel.Evaluate (anim_time);
  1019. ObjSpaceExtent.X = OuterScale.X * OuterExtent.X;
  1020. ObjSpaceExtent.Y = OuterScale.Y * OuterExtent.Y;
  1021. ObjSpaceExtent.Z = 0;
  1022. Update_Cached_Bounding_Volumes ();
  1023. }
  1024. }
  1025. }
  1026. return ;
  1027. } // animate
  1028. /*
  1029. ** RingLoaderClass Implementation
  1030. */
  1031. PrototypeClass * RingLoaderClass::Load_W3D(ChunkLoadClass & cload)
  1032. {
  1033. RingPrototypeClass *prototype = W3DNEW RingPrototypeClass ();
  1034. prototype->Load (cload);
  1035. return prototype;
  1036. }
  1037. /*
  1038. ** RingPrototypeClass Implementation
  1039. */
  1040. RingPrototypeClass::RingPrototypeClass (void)
  1041. {
  1042. ::memset (&Definition, 0, sizeof (Definition));
  1043. return ;
  1044. }
  1045. RingPrototypeClass::RingPrototypeClass(RingRenderObjClass *ring)
  1046. {
  1047. ::memset (&Definition, 0, sizeof (Definition));
  1048. ::strcpy (Definition.Name, ring->Get_Name ());
  1049. Definition.AnimDuration = ring->AnimDuration;
  1050. Definition.Attributes = ring->Get_Flags ();
  1051. Definition.DefaultAlpha = ring->Get_Default_Alpha ();
  1052. Definition.DefaultInnerScale = ring->Get_Default_Inner_Scale ();
  1053. Definition.DefaultOuterScale = ring->Get_Default_Outer_Scale ();
  1054. Definition.TextureTileCount = ring->Get_Texture_Tiling ();
  1055. Definition.InnerExtent = ring->Get_Inner_Extent ();
  1056. Definition.OuterExtent = ring->Get_Outer_Extent ();
  1057. Vector3 def_color = ring->Get_Default_Color ();
  1058. W3dUtilityClass::Convert_Vector (def_color, &Definition.DefaultColor);
  1059. W3dUtilityClass::Convert_Vector (ring->Get_Box ().Center, &Definition.Center);
  1060. W3dUtilityClass::Convert_Vector (ring->Get_Box ().Extent, &Definition.Extent);
  1061. W3dUtilityClass::Convert_Shader (ring->RingShader, &Definition.Shader);
  1062. //
  1063. // Determine the texture name for this ring
  1064. //
  1065. if (ring->RingTexture != NULL) {
  1066. StringClass name = ring->RingTexture->Get_Full_Path();
  1067. const char *filename = ::strrchr (name, '\\');
  1068. if (filename != NULL) {
  1069. filename ++;
  1070. } else {
  1071. filename = name;
  1072. }
  1073. ::strcpy (Definition.TextureName, filename);
  1074. }
  1075. //
  1076. // Save the animateable channels
  1077. //
  1078. ColorChannel = ring->Peek_Color_Channel ();
  1079. AlphaChannel = ring->Peek_Alpha_Channel ();
  1080. InnerScaleChannel = ring->Peek_Inner_Scale_Channel ();
  1081. OuterScaleChannel = ring->Peek_Outer_Scale_Channel ();
  1082. return ;
  1083. }
  1084. RingPrototypeClass::~RingPrototypeClass (void)
  1085. {
  1086. return ;
  1087. }
  1088. const char * RingPrototypeClass::Get_Name(void) const
  1089. {
  1090. return Definition.Name;
  1091. }
  1092. int RingPrototypeClass::Get_Class_ID(void) const
  1093. {
  1094. return RenderObjClass::CLASSID_RING;
  1095. }
  1096. enum
  1097. {
  1098. CHUNKID_RING_DEF = 1,
  1099. CHUNKID_COLOR_CHANNEL,
  1100. CHUNKID_ALPHA_CHANNEL,
  1101. CHUNKID_INNER_SCALE_CHANNEL,
  1102. CHUNKID_OUTER_SCALE_CHANNEL
  1103. };
  1104. bool RingPrototypeClass::Load (ChunkLoadClass &cload)
  1105. {
  1106. ColorChannel.Reset ();
  1107. AlphaChannel.Reset ();
  1108. InnerScaleChannel.Reset ();
  1109. OuterScaleChannel.Reset ();
  1110. while (cload.Open_Chunk ()) {
  1111. switch (cload.Cur_Chunk_ID ()) {
  1112. case CHUNKID_RING_DEF:
  1113. cload.Read (&Definition, sizeof (Definition));
  1114. break;
  1115. case CHUNKID_COLOR_CHANNEL:
  1116. ColorChannel.Load (cload);
  1117. break;
  1118. case CHUNKID_ALPHA_CHANNEL:
  1119. AlphaChannel.Load (cload);
  1120. break;
  1121. case CHUNKID_INNER_SCALE_CHANNEL:
  1122. InnerScaleChannel.Load (cload);
  1123. break;
  1124. case CHUNKID_OUTER_SCALE_CHANNEL:
  1125. OuterScaleChannel.Load (cload);
  1126. break;
  1127. }
  1128. cload.Close_Chunk ();
  1129. }
  1130. return true;
  1131. }
  1132. bool RingPrototypeClass::Save (ChunkSaveClass &csave)
  1133. {
  1134. csave.Begin_Chunk (W3D_CHUNK_RING);
  1135. csave.Begin_Chunk (CHUNKID_RING_DEF);
  1136. csave.Write (&Definition, sizeof (Definition));
  1137. csave.End_Chunk ();
  1138. if (ColorChannel.Get_Key_Count () > 0) {
  1139. csave.Begin_Chunk (CHUNKID_COLOR_CHANNEL);
  1140. ColorChannel.Save (csave);
  1141. csave.End_Chunk ();
  1142. }
  1143. if (AlphaChannel.Get_Key_Count () > 0) {
  1144. csave.Begin_Chunk (CHUNKID_ALPHA_CHANNEL);
  1145. AlphaChannel.Save (csave);
  1146. csave.End_Chunk ();
  1147. }
  1148. if (InnerScaleChannel.Get_Key_Count () > 0) {
  1149. csave.Begin_Chunk (CHUNKID_INNER_SCALE_CHANNEL);
  1150. InnerScaleChannel.Save (csave);
  1151. csave.End_Chunk ();
  1152. }
  1153. if (OuterScaleChannel.Get_Key_Count () > 0) {
  1154. csave.Begin_Chunk (CHUNKID_OUTER_SCALE_CHANNEL);
  1155. OuterScaleChannel.Save (csave);
  1156. csave.End_Chunk ();
  1157. }
  1158. csave.End_Chunk ();
  1159. return true;
  1160. }
  1161. RenderObjClass * RingPrototypeClass::Create(void)
  1162. {
  1163. //
  1164. // Create the new render object
  1165. //
  1166. RingRenderObjClass *ring = W3DNEW RingRenderObjClass (Definition);
  1167. //
  1168. // Configure the ring
  1169. //
  1170. W3dUtilityClass::Convert_Shader (Definition.Shader, &ring->RingShader);
  1171. if (WW3DAssetManager::Get_Instance()->Get_Activate_Fog_On_Load()) {
  1172. ring->RingShader.Enable_Fog ("RingPrototypeClass");
  1173. ring->RingShader.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
  1174. }
  1175. W3dUtilityClass::Convert_Vector (Definition.DefaultColor, &ring->Color);
  1176. ring->InnerScale = Definition.DefaultInnerScale;
  1177. ring->OuterScale = Definition.DefaultOuterScale;
  1178. ring->Set_Animation_Duration (Definition.AnimDuration);
  1179. ring->Alpha = Definition.DefaultAlpha;
  1180. ring->Set_Flags (Definition.Attributes);
  1181. ring->Set_Inner_Extent (Definition.InnerExtent);
  1182. ring->Set_Outer_Extent (Definition.OuterExtent);
  1183. ring->Set_Texture_Tiling (Definition.TextureTileCount);
  1184. //
  1185. // Initialize the render object with the keyframe arrays
  1186. //
  1187. ring->Set_Color_Channel (ColorChannel);
  1188. ring->Set_Alpha_Channel (AlphaChannel);
  1189. ring->Set_Inner_Scale_Channel (InnerScaleChannel);
  1190. ring->Set_Outer_Scale_Channel (OuterScaleChannel);
  1191. return ring;
  1192. }
  1193. /*
  1194. ** Global instance of the box loader
  1195. */
  1196. RingLoaderClass _RingLoader;
  1197. //
  1198. // Vertices are ordered as such
  1199. // center, followed by outer ring
  1200. //
  1201. /***********************************************************************************************
  1202. * RingMeshClass::RingMeshClass -- Constructor *
  1203. * *
  1204. * INPUT: *
  1205. * *
  1206. * OUTPUT: *
  1207. * *
  1208. * WARNINGS: *
  1209. * *
  1210. * HISTORY: *
  1211. * 3/07/00 jga : Created. *
  1212. *=============================================================================================*/
  1213. RingMeshClass::RingMeshClass(float radius, int slices):
  1214. Radius(radius),
  1215. Slices(slices),
  1216. Vertex_ct(0), // 1 vertex minimum, for center
  1217. vtx(NULL),
  1218. orig_vtx(NULL),
  1219. vtx_normal(NULL),
  1220. vtx_uv(NULL),
  1221. face_ct(0),
  1222. tri_poly(NULL),
  1223. TileCount (5),
  1224. InnerScale (1.0F, 1.0F),
  1225. OuterScale (1.0F, 1.0F)
  1226. {
  1227. Generate(radius, slices);
  1228. }
  1229. /***********************************************************************************************
  1230. * RingMeshClass::RingMeshClass -- Constructor *
  1231. * *
  1232. * INPUT: *
  1233. * *
  1234. * OUTPUT: *
  1235. * *
  1236. * WARNINGS: *
  1237. * *
  1238. * HISTORY: *
  1239. * 3/07/00 jga : Created. *
  1240. *=============================================================================================*/
  1241. RingMeshClass::RingMeshClass(void):
  1242. Radius(0.0f),
  1243. Slices(0),
  1244. Vertex_ct(0), // 1 vertex minimum, for center
  1245. vtx(NULL),
  1246. orig_vtx(NULL),
  1247. vtx_normal(NULL),
  1248. vtx_uv(NULL),
  1249. face_ct(0),
  1250. tri_poly(NULL),
  1251. TileCount (5),
  1252. InnerScale (1.0F, 1.0F),
  1253. OuterScale (1.0F, 1.0F)
  1254. {
  1255. } // empty ringmesh Constructor
  1256. void RingMeshClass::Set_Tiling (int count)
  1257. {
  1258. if (TileCount != count) {
  1259. TileCount = count;
  1260. //
  1261. // Calculate the increment 'u' increment value (as in UV).
  1262. //
  1263. float u_inc = ((float)TileCount) / ((float)(Slices));
  1264. float u_value = 0.0F;
  1265. //
  1266. // Reassign the UVs
  1267. //
  1268. for (int index = 0; index < Vertex_ct; index += 2) {
  1269. vtx_uv[index].Set (u_value, 0.0F);
  1270. vtx_uv[index + 1].Set (u_value, 1.0F);
  1271. u_value += u_inc;
  1272. }
  1273. }
  1274. return ;
  1275. }
  1276. void RingMeshClass::Scale (const Vector2 &inner_scale, const Vector2 &outer_scale)
  1277. {
  1278. bool do_inner = (inner_scale != InnerScale);
  1279. bool do_outer = (outer_scale != OuterScale);
  1280. //
  1281. // Only scale the inner ring if necessary
  1282. //
  1283. if (do_inner) {
  1284. for (int index = 0; index < Vertex_ct; index += 2) {
  1285. vtx[index].X = orig_vtx[index].X * inner_scale.X;
  1286. vtx[index].Y = orig_vtx[index].Y * inner_scale.Y;
  1287. vtx[index].Z = 0;
  1288. }
  1289. InnerScale = inner_scale;
  1290. }
  1291. //
  1292. // Only scale the outer ring if necessary
  1293. //
  1294. if (do_outer) {
  1295. for (int index = 1; index < Vertex_ct; index += 2) {
  1296. vtx[index].X = orig_vtx[index].X * outer_scale.X;
  1297. vtx[index].Y = orig_vtx[index].Y * outer_scale.Y;
  1298. vtx[index].Z = 0;
  1299. }
  1300. OuterScale = outer_scale;
  1301. }
  1302. return ;
  1303. }
  1304. /***********************************************************************************************
  1305. * RingMeshClass::Generate - Create Ring Geometry *
  1306. * *
  1307. * INPUT: *
  1308. * *
  1309. * OUTPUT: *
  1310. * *
  1311. * WARNINGS: *
  1312. * *
  1313. * HISTORY: *
  1314. * 3/07/00 jga : Created. *
  1315. *=============================================================================================*/
  1316. void RingMeshClass::Generate(float radius, int slices)
  1317. {
  1318. Free ();
  1319. Slices = slices;
  1320. Radius = radius;
  1321. face_ct = (Slices * 2);
  1322. Vertex_ct = (Slices * 2) + 2;
  1323. vtx = W3DNEWARRAY Vector3[Vertex_ct];
  1324. orig_vtx = W3DNEWARRAY Vector2[Vertex_ct];
  1325. vtx_normal = W3DNEWARRAY Vector3[Vertex_ct];
  1326. vtx_uv = W3DNEWARRAY Vector2[Vertex_ct];
  1327. tri_poly = W3DNEWARRAY TriIndex[face_ct];
  1328. //
  1329. // Generate vertices, normals, and uv's
  1330. //
  1331. float angle_inc = DEG_TO_RADF (360) / ((float)Slices);
  1332. float u_inc = ((float)TileCount) / ((float)(Slices));
  1333. float u_value = 0.0F;
  1334. float angle = 0;
  1335. int index = 0;
  1336. for (index = 0; index < Vertex_ct; index += 2) {
  1337. float x_pos = -WWMath::Sin (angle);
  1338. float y_pos = WWMath::Cos (angle);
  1339. //
  1340. // Place the inner index
  1341. //
  1342. vtx[index].X = orig_vtx[index].X = x_pos;
  1343. vtx[index].Y = orig_vtx[index].Y = y_pos;
  1344. vtx[index].Z = 0;
  1345. //
  1346. // Place the outer index
  1347. //
  1348. vtx[index+1].X = orig_vtx[index+1].X = x_pos;
  1349. vtx[index+1].Y = orig_vtx[index+1].Y = y_pos;
  1350. vtx[index+1].Z = 0;
  1351. //
  1352. // Normals will just point straight up from the ring...
  1353. //
  1354. vtx_normal[index].Set (0, 0, 1);
  1355. vtx_normal[index + 1].Set (0, 0, 1);
  1356. //
  1357. // Assign the UVs
  1358. //
  1359. vtx_uv[index].Set (u_value, 0.0F);
  1360. vtx_uv[index + 1].Set (u_value, 1.0F);
  1361. u_value += u_inc;
  1362. angle += angle_inc;
  1363. }
  1364. //
  1365. // Make the triangle strip...
  1366. //
  1367. for (index = 0; index < face_ct; index ++) {
  1368. tri_poly[index].I = index;
  1369. tri_poly[index].J = index+1;
  1370. tri_poly[index].K = index+2;
  1371. }
  1372. return ;
  1373. }
  1374. /***********************************************************************************************
  1375. * RingMeshClass::~RingMeshClass -- Destructor *
  1376. * *
  1377. * INPUT: *
  1378. * *
  1379. * OUTPUT: *
  1380. * *
  1381. * WARNINGS: *
  1382. * *
  1383. * HISTORY: *
  1384. * 3/07/00 jga : Created. *
  1385. *=============================================================================================*/
  1386. RingMeshClass::~RingMeshClass(void)
  1387. {
  1388. Free();
  1389. }
  1390. /***********************************************************************************************
  1391. * RingMeshClass::Free - Release Memory, that the ring mesh is using *
  1392. * *
  1393. * INPUT: *
  1394. * *
  1395. * OUTPUT: *
  1396. * *
  1397. * WARNINGS: *
  1398. * *
  1399. * HISTORY: *
  1400. * 3/07/00 jga : Created. *
  1401. *=============================================================================================*/
  1402. void RingMeshClass::Free(void)
  1403. {
  1404. if (vtx) delete vtx;
  1405. if (orig_vtx) delete orig_vtx;
  1406. if (vtx_normal) delete vtx_normal;
  1407. if (vtx_uv) delete vtx_uv;
  1408. if (tri_poly) delete tri_poly;
  1409. vtx = NULL;
  1410. orig_vtx = NULL;
  1411. vtx_normal = NULL;
  1412. vtx_uv = NULL;
  1413. tri_poly = NULL;
  1414. } // Free
  1415. // EOF - ringobj.cpp