mesh.cpp 79 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604
  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. /* $Header: /Commando/Code/ww3d2/mesh.cpp 69 1/19/02 1:01p Greg_h $ */
  19. /***********************************************************************************************
  20. *** Confidential - Westwood Studios ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Commando / G 3D engine *
  24. * *
  25. * File Name : MESH.CPP *
  26. * *
  27. * Programmer : Greg Hjelstrom *
  28. * *
  29. * Start Date : 06/11/97 *
  30. * *
  31. * Last Update : June 12, 1997 [GH] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * MeshClass::MeshClass -- Constructor for MeshClass *
  36. * MeshClass::MeshClass -- Copy Constructor for MeshClass *
  37. * MeshClass::operator == -- assignment operator for MeshClass *
  38. * MeshClass::~MeshClass -- destructor *
  39. * MeshClass::Contains -- Determines whether mesh contains a (worldspace) point. *
  40. * MeshClass::Free -- Releases all memory/assets in use by this mesh *
  41. * MeshClass::Clone -- Creates a clone of this mesh *
  42. * MeshClass::Get_Name -- returns the name of the mesh *
  43. * MeshClass::Set_Name -- sets the name of this mesh *
  44. * MeshClass::Get_W3D_Flags -- access to the W3D flags *
  45. * MeshClass::Get_User_Text -- access to the text buffer *
  46. * MeshClass::Scale -- Scales the mesh *
  47. * MeshClass::Scale -- Scales the mesh *
  48. * MeshClass::Init -- Init the mesh from a MeshBuilder object *
  49. * MeshClass::Load -- creates a mesh out of a mesh chunk in a .w3d file *
  50. * MeshClass::Cast_Ray -- compute a ray intersection with this mesh *
  51. * MeshClass::Cast_AABox -- cast an AABox against this mesh *
  52. * MeshClass::Cast_OBBox -- Cast an obbox against this mesh *
  53. * MeshClass::Intersect_AABox -- test for intersection with given AABox *
  54. * MeshClass::Intersect_OBBox -- test for intersection with the given OBBox *
  55. * MeshClass::Generate_Culling_Tree -- Generates a hierarchical culling tree for the mesh *
  56. * MeshClass::Direct_Load -- read the w3d file directly into this mesh object *
  57. * MeshClass::read_chunks -- read all of the chunks from the .wtm file *
  58. * MeshClass::read_vertices -- reads the vertex chunk *
  59. * MeshClass::read_texcoords -- read in the texture coordinates chunk *
  60. * MeshClass::install_texture_coordinates -- installs the given u-v's in each channel that is*
  61. * MeshClass::read_vertex_normals -- reads a surrender normal chunk from the wtm file *
  62. * MeshClass::read_v3_materials -- Reads in version 3 materials. *
  63. * MeshClass::read_map -- Reads definition of a texture map from the file *
  64. * MeshClass::read_triangles -- read the triangles chunk *
  65. * MeshClass::read_per_tri_materials -- read the material indices for each triangle *
  66. * MeshClass::read_user_text -- read in the user text chunk *
  67. * MeshClass::read_vertex_colors -- read in the vertex colors chunk *
  68. * MeshClass::read_vertex_influences -- read in the vertex influences chunk *
  69. * MeshClass::Get_Material_Info -- returns a pointer to the material info *
  70. * MeshClass::Create_Decal -- creates a decal on this mesh *
  71. * MeshClass::Delete_Decal -- removes a decal from this mesh *
  72. * MeshClass::Get_Num_Polys -- returns the number of polys (tris) in this mesh *
  73. * MeshClass::Render -- renders this mesh *
  74. * MeshClass::Special_Render -- special render function for meshes *
  75. * MeshClass::update_skin -- deforms the mesh *
  76. * MeshClass::clone_materials -- clone the materials for this mesh *
  77. * MeshClass::install_materials -- transfers the materials into the mesh *
  78. * MeshClass::Get_Model -- user access to the mesh model *
  79. * MeshClass::Get_Obj_Space_Bounding_Sphere -- returns obj-space bounding sphere *
  80. * MeshClass::Get_Obj_Space_Bounding_Box -- returns the obj-space bounding box *
  81. * MeshClass::Get_Deformed_Vertices -- Gets the deformed vertices for a skin *
  82. * MeshClass::Get_Deformed_Vertices -- Gets the deformed vertices for a skin *
  83. * MeshClass::Render_Material_Pass -- Render a procedural material pass for this mesh *
  84. * MeshClass::Replace_VertexMaterial -- Replaces existing vertex material with a new one. Wi *
  85. * MeshClass::Make_Unique -- Makes mesh unique in the renderer, but still shares system ram *
  86. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  87. #include "mesh.h"
  88. #include <assert.h>
  89. #include <string.h>
  90. #include "w3d_file.h"
  91. #include "assetmgr.h"
  92. #include "w3derr.h"
  93. #include "wwdebug.h"
  94. #include "vertmaterial.h"
  95. #include "shader.h"
  96. #include "matinfo.h"
  97. #include "htree.h"
  98. #include "meshbuild.h"
  99. #include "tri.h"
  100. #include "aaplane.h"
  101. #include "aabtree.h"
  102. #include "chunkio.h"
  103. #include "w3d_util.h"
  104. #include "meshmdl.h"
  105. #include "meshgeometry.h"
  106. #include "ww3d.h"
  107. #include "camera.h"
  108. #include "texture.h"
  109. #include "rinfo.h"
  110. #include "coltest.h"
  111. #include "inttest.h"
  112. #include "decalmsh.h"
  113. #include "decalsys.h"
  114. #include "dx8polygonrenderer.h"
  115. #include "dx8indexbuffer.h"
  116. #include "dx8renderer.h"
  117. #include "visrasterizer.h"
  118. #include "wwmemlog.h"
  119. #include "dx8rendererdebugger.h"
  120. #include <stdio.h>
  121. #include <wwprofile.h>
  122. static unsigned MeshDebugIdCount;
  123. bool MeshClass::Legacy_Meshes_Fogged = true;
  124. static SimpleDynVecClass<uint32> temp_apt;
  125. /*
  126. ** This #define causes the collision code to always recompute the triangle normals rather
  127. ** than using the ones in the model.
  128. ** TODO: ensure that the models have unit normals and start re-using them again or write
  129. ** collision code to handle non-unit normals!
  130. */
  131. #if (OPTIMIZE_PLANEEQ_RAM)
  132. #define COMPUTE_NORMALS
  133. #endif
  134. /*
  135. ** Temporary storage used during decal creation
  136. */
  137. static DynamicVectorClass<Vector3> _TempVertexBuffer;
  138. /***********************************************************************************************
  139. * MeshClass::MeshClass -- Constructor for MeshClass *
  140. * *
  141. * Initializes an empty mesh class *
  142. * *
  143. * INPUT: *
  144. * *
  145. * OUTPUT: *
  146. * *
  147. * WARNINGS: *
  148. * *
  149. * HISTORY: *
  150. * 1/6/98 GTH : Created. *
  151. *=============================================================================================*/
  152. MeshClass::MeshClass(void) :
  153. Model(NULL),
  154. DecalMesh(NULL),
  155. LightEnvironment(NULL),
  156. BaseVertexOffset(0),
  157. NextVisibleSkin(NULL),
  158. IsDisabledByDebugger(false),
  159. MeshDebugId(MeshDebugIdCount++),
  160. m_alphaOverride(1.0f),
  161. m_materialPassAlphaOverride(1.0f),
  162. m_materialPassEmissiveOverride(1.0f)
  163. {
  164. }
  165. /***********************************************************************************************
  166. * MeshClass::MeshClass -- Copy Constructor for MeshClass *
  167. * *
  168. * Creates a mesh which is a copy of the given mesh *
  169. * *
  170. * INPUT: *
  171. * *
  172. * OUTPUT: *
  173. * *
  174. * WARNINGS: *
  175. * *
  176. * HISTORY: *
  177. *=============================================================================================*/
  178. MeshClass::MeshClass(const MeshClass & that) :
  179. RenderObjClass(that),
  180. Model(NULL),
  181. DecalMesh(NULL),
  182. LightEnvironment(NULL),
  183. BaseVertexOffset(that.BaseVertexOffset),
  184. NextVisibleSkin(NULL),
  185. IsDisabledByDebugger(false),
  186. MeshDebugId(MeshDebugIdCount++),
  187. m_alphaOverride(1.0f),
  188. m_materialPassAlphaOverride(1.0f),
  189. m_materialPassEmissiveOverride(1.0f)
  190. {
  191. REF_PTR_SET(Model,that.Model); // mesh instances share models by default
  192. }
  193. /***********************************************************************************************
  194. * operator == -- assignment operator for MeshClass *
  195. * *
  196. * INPUT: *
  197. * *
  198. * OUTPUT: *
  199. * *
  200. * WARNINGS: *
  201. * *
  202. * HISTORY: *
  203. * 1/6/98 GTH : Created. *
  204. *=============================================================================================*/
  205. MeshClass & MeshClass::operator = (const MeshClass & that)
  206. {
  207. if (this != &that) {
  208. RenderObjClass::operator = (that);
  209. REF_PTR_SET(Model,that.Model); // mesh instances share models by default
  210. BaseVertexOffset = that.BaseVertexOffset;
  211. // just dont copy the decals or light environment
  212. REF_PTR_RELEASE(DecalMesh);
  213. LightEnvironment = NULL;
  214. }
  215. return * this;
  216. }
  217. /***********************************************************************************************
  218. * MeshClass::~MeshClass -- destructor *
  219. * *
  220. * INPUT: *
  221. * *
  222. * OUTPUT: *
  223. * *
  224. * WARNINGS: *
  225. * *
  226. * HISTORY: *
  227. * 1/6/98 GTH : Created. *
  228. *=============================================================================================*/
  229. MeshClass::~MeshClass(void)
  230. {
  231. Free();
  232. }
  233. /***********************************************************************************************
  234. * MeshClass::Contains -- Determines whether mesh contains a (worldspace) point. *
  235. * *
  236. * INPUT: *
  237. * *
  238. * OUTPUT: *
  239. * *
  240. * WARNINGS: Assumes mesh is a closed manifold - results are undefined otherwise *
  241. * This function will NOT work for skins *
  242. * *
  243. * HISTORY: *
  244. * 8/30/00 NH : Created. *
  245. *=============================================================================================*/
  246. bool MeshClass::Contains(const Vector3 &point)
  247. {
  248. // Transform point to object space and pass on to model
  249. Vector3 obj_point;
  250. Matrix3D::Inverse_Transform_Vector(Transform, point, &obj_point);
  251. return Model->Contains(obj_point);
  252. }
  253. /***********************************************************************************************
  254. * MeshClass::Free -- Releases all memory/assets in use by this mesh *
  255. * *
  256. * INPUT: *
  257. * *
  258. * OUTPUT: *
  259. * *
  260. * WARNINGS: *
  261. * *
  262. * HISTORY: *
  263. * 1/6/98 GTH : Created. *
  264. *=============================================================================================*/
  265. void MeshClass::Free(void)
  266. {
  267. REF_PTR_RELEASE(Model);
  268. REF_PTR_RELEASE(DecalMesh);
  269. }
  270. /***********************************************************************************************
  271. * MeshClass::Clone -- Creates a clone of this mesh *
  272. * *
  273. * INPUT: *
  274. * *
  275. * OUTPUT: *
  276. * *
  277. * WARNINGS: *
  278. * *
  279. * HISTORY: *
  280. * 1/6/98 GTH : Created. *
  281. *=============================================================================================*/
  282. RenderObjClass * MeshClass::Clone(void) const
  283. {
  284. return NEW_REF( MeshClass, (*this));
  285. }
  286. /***********************************************************************************************
  287. * MeshClass::Get_Name -- returns the name of the mesh *
  288. * *
  289. * INPUT: *
  290. * *
  291. * OUTPUT: *
  292. * *
  293. * WARNINGS: *
  294. * *
  295. * HISTORY: *
  296. * 5/15/98 GTH : Created. *
  297. *=============================================================================================*/
  298. const char * MeshClass::Get_Name(void) const
  299. {
  300. return Model->Get_Name();
  301. }
  302. /***********************************************************************************************
  303. * MeshClass::Set_Name -- sets the name of this mesh *
  304. * *
  305. * INPUT: *
  306. * *
  307. * OUTPUT: *
  308. * *
  309. * WARNINGS: *
  310. * *
  311. * HISTORY: *
  312. * 3/9/99 GTH : Created. *
  313. *=============================================================================================*/
  314. void MeshClass::Set_Name(const char * name)
  315. {
  316. Model->Set_Name(name);
  317. }
  318. /***********************************************************************************************
  319. * MeshClass::Get_W3D_Flags -- access to the W3D flags *
  320. * *
  321. * INPUT: *
  322. * *
  323. * OUTPUT: *
  324. * *
  325. * WARNINGS: *
  326. * *
  327. * HISTORY: *
  328. * 5/15/98 GTH : Created. *
  329. *=============================================================================================*/
  330. uint32 MeshClass::Get_W3D_Flags(void)
  331. {
  332. return Model->W3dAttributes;
  333. }
  334. /***********************************************************************************************
  335. * MeshClass::Get_User_Text -- access to the text buffer *
  336. * *
  337. * INPUT: *
  338. * *
  339. * OUTPUT: *
  340. * *
  341. * WARNINGS: *
  342. * *
  343. * HISTORY: *
  344. * 5/15/98 GTH : Created. *
  345. *=============================================================================================*/
  346. const char * MeshClass::Get_User_Text(void) const
  347. {
  348. return Model->Get_User_Text();
  349. }
  350. /***********************************************************************************************
  351. * MeshClass::Get_Material_Info -- returns a pointer to the material info *
  352. * *
  353. * INPUT: *
  354. * *
  355. * OUTPUT: *
  356. * *
  357. * WARNINGS: *
  358. * *
  359. * HISTORY: *
  360. * 5/20/98 GTH : Created. *
  361. *=============================================================================================*/
  362. MaterialInfoClass * MeshClass::Get_Material_Info(void)
  363. {
  364. if (Model) {
  365. if (Model->MatInfo) {
  366. Model->MatInfo->Add_Ref();
  367. return Model->MatInfo;
  368. }
  369. }
  370. return NULL;
  371. }
  372. /***********************************************************************************************
  373. * MeshClass::Get_Model -- user access to the mesh model *
  374. * *
  375. * INPUT: *
  376. * *
  377. * OUTPUT: *
  378. * *
  379. * WARNINGS: *
  380. * *
  381. * HISTORY: *
  382. * 2/4/99 GTH : Created. *
  383. *=============================================================================================*/
  384. MeshModelClass * MeshClass::Get_Model(void)
  385. {
  386. if (Model != NULL) {
  387. Model->Add_Ref();
  388. }
  389. return Model;
  390. }
  391. /***********************************************************************************************
  392. * MeshClass::Scale -- Scales the mesh *
  393. * *
  394. * INPUT: *
  395. * *
  396. * OUTPUT: *
  397. * *
  398. * WARNINGS: *
  399. * *
  400. * HISTORY: *
  401. *=============================================================================================*/
  402. void MeshClass::Scale(float scale)
  403. {
  404. if (scale==1.0f) return;
  405. Vector3 sc;
  406. sc.X = sc.Y = sc.Z = scale;
  407. Make_Unique();
  408. Model->Make_Geometry_Unique();
  409. Model->Scale(sc);
  410. Invalidate_Cached_Bounding_Volumes();
  411. // Now update the object space bounding volumes of this object's container:
  412. RenderObjClass *container = Get_Container();
  413. if (container) container->Update_Obj_Space_Bounding_Volumes();
  414. }
  415. /***********************************************************************************************
  416. * MeshClass::Scale -- Scales the mesh *
  417. * *
  418. * INPUT: *
  419. * *
  420. * OUTPUT: *
  421. * *
  422. * WARNINGS: *
  423. * *
  424. * HISTORY: *
  425. * 1/6/98 GTH : Created. *
  426. * 12/8/98 GTH : Modified the box scaling to use the non-uniform parameters *
  427. *=============================================================================================*/
  428. void MeshClass::Scale(float scalex, float scaley, float scalez)
  429. {
  430. // scale the surrender mesh model
  431. Vector3 sc;
  432. sc.X = scalex;
  433. sc.Y = scaley;
  434. sc.Z = scalez;
  435. Make_Unique();
  436. Model->Make_Geometry_Unique();
  437. Model->Scale(sc);
  438. Invalidate_Cached_Bounding_Volumes();
  439. // Now update the object space bounding volumes of this object's container:
  440. RenderObjClass *container = Get_Container();
  441. if (container) container->Update_Obj_Space_Bounding_Volumes();
  442. }
  443. /***********************************************************************************************
  444. * MeshClass::Get_Deformed_Vertices -- Gets the deformed vertices for a skin *
  445. * *
  446. * INPUT: *
  447. * *
  448. * OUTPUT: *
  449. * *
  450. * WARNINGS: *
  451. * *
  452. * HISTORY: *
  453. * 3/4/2001 gth : Created. *
  454. *=============================================================================================*/
  455. void MeshClass::Get_Deformed_Vertices(Vector3 *dst_vert, Vector3 *dst_norm)
  456. {
  457. WWASSERT(Model->Get_Flag(MeshGeometryClass::SKIN));
  458. Model->get_deformed_vertices(dst_vert,dst_norm,Container->Get_HTree());
  459. }
  460. /***********************************************************************************************
  461. * MeshClass::Get_Deformed_Vertices -- Gets the deformed vertices for a skin *
  462. * *
  463. * INPUT: *
  464. * *
  465. * OUTPUT: *
  466. * *
  467. * WARNINGS: *
  468. * *
  469. * HISTORY: *
  470. * 3/4/2001 gth : Created. *
  471. *=============================================================================================*/
  472. void MeshClass::Get_Deformed_Vertices(Vector3 *dst_vert)
  473. {
  474. WWASSERT(Model->Get_Flag(MeshGeometryClass::SKIN));
  475. WWASSERT(Container != NULL);
  476. WWASSERT(Container->Get_HTree() != NULL);
  477. Model->get_deformed_vertices(dst_vert,Container->Get_HTree());
  478. }
  479. /***********************************************************************************************
  480. * MeshClass::Create_Decal -- creates a decal on this mesh *
  481. * *
  482. * INPUT: *
  483. * *
  484. * OUTPUT: *
  485. * *
  486. * WARNINGS: *
  487. * *
  488. * HISTORY: *
  489. * 1/26/00 gth : Created. *
  490. *=============================================================================================*/
  491. void MeshClass::Create_Decal(DecalGeneratorClass * generator)
  492. {
  493. WWMEMLOG(MEM_GEOMETRY);
  494. if (WW3D::Are_Decals_Enabled() == false) {
  495. return;
  496. }
  497. if (Is_Translucent() && (generator->Is_Applied_To_Translucent_Meshes() == false)) {
  498. return;
  499. }
  500. if (!Model->Get_Flag(MeshGeometryClass::SKIN)) {
  501. // Rigid mesh
  502. Matrix3D modeltm_inv;
  503. OBBoxClass localbox;
  504. Get_Transform().Get_Orthogonal_Inverse(modeltm_inv);
  505. OBBoxClass::Transform(modeltm_inv, generator->Get_Bounding_Volume(), &localbox);
  506. // generate apt, if it is not empty, add a decal.
  507. temp_apt.Delete_All(false); // reset contents
  508. Model->Generate_Rigid_APT(localbox, temp_apt);
  509. if (temp_apt.Count() > 0) {
  510. if (DecalMesh == NULL) {
  511. DecalMesh = NEW_REF(RigidDecalMeshClass, (this, generator->Peek_Decal_System()));
  512. }
  513. DecalMesh->Create_Decal(generator, localbox, temp_apt);
  514. }
  515. } else {
  516. WWDEBUG_SAY(("PERFORMANCE WARNING: Decal being applied to a SKIN mesh!\r\n"));
  517. // Skin
  518. // The deformed worldspace vertices are used both for the APT and in Create_Decal() to
  519. // generate the texture coordinates.
  520. int vertex_count = Model->Get_Vertex_Count();
  521. if (_TempVertexBuffer.Count() < vertex_count) _TempVertexBuffer.Resize(vertex_count);
  522. Vector3 *dst_vert = &(_TempVertexBuffer[0]);
  523. Get_Deformed_Vertices(dst_vert);
  524. // generate apt, if it is not empty, add a decal.
  525. temp_apt.Delete_All(false);
  526. OBBoxClass worldbox = generator->Get_Bounding_Volume();
  527. // We compare the worldspace box vs. the worldspace vertices
  528. Model->Generate_Skin_APT(worldbox, temp_apt, dst_vert);
  529. // if it is not empty, add a decal
  530. if (temp_apt.Count() > 0) {
  531. if (DecalMesh == NULL) {
  532. DecalMesh = NEW_REF(SkinDecalMeshClass, (this, generator->Peek_Decal_System()));
  533. }
  534. DecalMesh->Create_Decal(generator, worldbox, temp_apt, &_TempVertexBuffer);
  535. }
  536. }
  537. }
  538. /***********************************************************************************************
  539. * MeshClass::Delete_Decal -- removes a decal from this mesh *
  540. * *
  541. * INPUT: *
  542. * *
  543. * OUTPUT: *
  544. * *
  545. * WARNINGS: *
  546. * *
  547. * HISTORY: *
  548. * 1/26/00 gth : Created. *
  549. *=============================================================================================*/
  550. void MeshClass::Delete_Decal(uint32 decal_id)
  551. {
  552. if (DecalMesh != NULL) {
  553. DecalMesh->Delete_Decal(decal_id);
  554. }
  555. }
  556. /***********************************************************************************************
  557. * MeshClass::Get_Num_Polys -- returns the number of polys (tris) in this mesh *
  558. * *
  559. * INPUT: *
  560. * *
  561. * OUTPUT: *
  562. * *
  563. * WARNINGS: *
  564. * *
  565. * HISTORY: *
  566. * 1/6/98 GTH : Created. *
  567. *=============================================================================================*/
  568. int MeshClass::Get_Num_Polys(void) const
  569. {
  570. if (Model) {
  571. int num_passes=Model->Get_Pass_Count();
  572. WWASSERT(num_passes>0);
  573. int poly_count=Model->Get_Polygon_Count();
  574. return num_passes*poly_count;
  575. } else {
  576. return 0;
  577. }
  578. }
  579. /***********************************************************************************************
  580. * MeshClass::Render -- renders this mesh *
  581. * *
  582. * INPUT: *
  583. * *
  584. * OUTPUT: *
  585. * *
  586. * WARNINGS: *
  587. * *
  588. * HISTORY: *
  589. * 12/10/98 GTH : Created. *
  590. *=============================================================================================*/
  591. void MeshClass::Render(RenderInfoClass & rinfo)
  592. {
  593. WWPROFILE("Mesh::Render");
  594. if (Is_Not_Hidden_At_All() == false) {
  595. return;
  596. }
  597. // If static sort lists are enabled and this mesh has a sort level, put it on the list instead
  598. // of rendering it.
  599. unsigned int sort_level = (unsigned int)Model->Get_Sort_Level();
  600. if (WW3D::Are_Static_Sort_Lists_Enabled() && sort_level != SORT_LEVEL_NONE) {
  601. Set_Lighting_Environment(rinfo.light_environment);
  602. //Add custom alpha
  603. m_alphaOverride = rinfo.alphaOverride;
  604. m_materialPassAlphaOverride = rinfo.materialPassAlphaOverride;
  605. m_materialPassEmissiveOverride = rinfo.materialPassEmissiveOverride;
  606. WW3D::Add_To_Static_Sort_List(this, sort_level);
  607. } else {
  608. /* Commented out since we set lighting environment only on visible meshes below. -MW
  609. ** Plug in the lighting environment unless we arrived here as part of the static
  610. ** sorting system being flushed
  611. */
  612. // if (WW3D::Are_Static_Sort_Lists_Enabled()) {
  613. // Set_Lighting_Environment(rinfo.light_environment);
  614. // }
  615. const FrustumClass & frustum=rinfo.Camera.Get_Frustum();
  616. if ( Model->Get_Flag(MeshGeometryClass::SKIN) ||
  617. CollisionMath::Overlap_Test(frustum,Get_Bounding_Box())!=CollisionMath::OUTSIDE )
  618. {
  619. bool rendered_something = false;
  620. /*
  621. ** If this mesh model has never been rendered, we need to generate the DX8 datastructures
  622. */
  623. if (Model->PolygonRendererList.Is_Empty()) {
  624. Model->Register_For_Rendering();
  625. WWASSERT(!Model->PolygonRendererList.Is_Empty());
  626. }
  627. /*
  628. ** Plug in lighting
  629. */
  630. if (sort_level == SORT_LEVEL_NONE) //sorting ones get their environment set above.
  631. { Set_Lighting_Environment(rinfo.light_environment);
  632. //Add custom alpha
  633. m_alphaOverride = rinfo.alphaOverride;
  634. m_materialPassAlphaOverride = rinfo.materialPassAlphaOverride;
  635. m_materialPassEmissiveOverride = rinfo.materialPassEmissiveOverride;
  636. }
  637. /*
  638. ** Process texture reductions:
  639. */
  640. // Model->Process_Texture_Reduction();
  641. /*
  642. ** Look up the FVF container that this mesh is in
  643. */
  644. DX8FVFCategoryContainer * fvf_container = Model->PolygonRendererList.Peek_Head()->Get_Texture_Category()->Get_Container();
  645. /*
  646. ** Check if we should render the base passes. One special case here: if
  647. ** the mesh is translucent (alpha) and the base passes are disabled but we
  648. ** are rendering a shadow, we go ahead and render the base pass. This is an ugly way
  649. ** to get our tree shadows and other alpha textured shadows to work.
  650. */
  651. bool render_base_passes = ((rinfo.Current_Override_Flags() & RenderInfoClass::RINFO_OVERRIDE_ADDITIONAL_PASSES_ONLY) == 0);
  652. bool is_alpha = (Model->Get_Single_Shader().Get_Alpha_Test() == ShaderClass::ALPHATEST_ENABLE) ||
  653. (Model->Get_Single_Shader().Get_Src_Blend_Func() == ShaderClass::SRCBLEND_SRC_ALPHA);
  654. if ( (rinfo.Current_Override_Flags() & RenderInfoClass::RINFO_OVERRIDE_SHADOW_RENDERING) &&
  655. (is_alpha == true))
  656. {
  657. render_base_passes = true;
  658. }
  659. if (render_base_passes) {
  660. /*
  661. ** Link each polygon renderer for this mesh into the visible list
  662. */
  663. DX8PolygonRendererListIterator it(&(Model->PolygonRendererList));
  664. while (!it.Is_Done()) {
  665. DX8PolygonRendererClass* polygon_renderer=it.Peek_Obj();
  666. polygon_renderer->Get_Texture_Category()->Add_Render_Task(polygon_renderer,this);
  667. it.Next();
  668. }
  669. rendered_something = true;
  670. }
  671. /*
  672. ** If the rendering context specifies procedural material passes, register them
  673. ** for rendering
  674. */
  675. for (int i=0; i<rinfo.Additional_Pass_Count(); i++) {
  676. MaterialPassClass * matpass = rinfo.Peek_Additional_Pass(i);
  677. if ((!Is_Translucent()) || (matpass->Is_Enabled_On_Translucent_Meshes())) {
  678. /*
  679. ** If the base pass for this mesh has been disabled, we have to make sure
  680. ** the procedural material pass is rendered after everything else has rendered
  681. */
  682. if (rinfo.Current_Override_Flags() & RenderInfoClass::RINFO_OVERRIDE_ADDITIONAL_PASSES_ONLY) {
  683. fvf_container->Add_Delayed_Visible_Material_Pass(matpass, this);
  684. } else {
  685. fvf_container->Add_Visible_Material_Pass(matpass,this);
  686. }
  687. rendered_something = true;
  688. }
  689. }
  690. /*
  691. ** If we rendered any base or procedural passes and this is a skin, we need
  692. ** to tell the mesh rendering system to process this skin
  693. */
  694. if (rendered_something && Model->Get_Flag(MeshGeometryClass::SKIN)) {
  695. //WWASSERT(dynamic_cast<DX8SkinFVFCategoryContainer *>(fvf_container) != NULL);
  696. static_cast<DX8SkinFVFCategoryContainer*>(fvf_container)->Add_Visible_Skin(this);
  697. }
  698. /*
  699. ** If we have a decal mesh, link it into the mesh rendering system
  700. */
  701. if ( (DecalMesh != NULL) &&
  702. ((rinfo.Current_Override_Flags() & RenderInfoClass::RINFO_OVERRIDE_ADDITIONAL_PASSES_ONLY) == 0))
  703. {
  704. const SphereClass & ws_sphere = Get_Bounding_Sphere();
  705. Vector3 cam_space_sphere_center;
  706. rinfo.Camera.Transform_To_View_Space(cam_space_sphere_center,ws_sphere.Center);
  707. if (-cam_space_sphere_center.Z - ws_sphere.Radius < WW3D::Get_Decal_Rejection_Distance()) {
  708. TheDX8MeshRenderer.Add_To_Render_List(DecalMesh);
  709. }
  710. }
  711. DX8RendererDebugger::Add_Mesh(this);
  712. }
  713. }
  714. }
  715. /***********************************************************************************************
  716. * MeshClass::Render_Material_Pass -- Render a procedural material pass for this mesh *
  717. * *
  718. * INPUT: *
  719. * *
  720. * OUTPUT: *
  721. * *
  722. * WARNINGS: *
  723. * *
  724. * HISTORY: *
  725. * 3/4/2001 gth : Created. *
  726. *=============================================================================================*/
  727. void MeshClass::Render_Material_Pass(MaterialPassClass * pass,IndexBufferClass * ib)
  728. {
  729. //Added to allow dynamic opacity on additional render passed
  730. //without having to create a new material pass per object instance. -MW
  731. float oldOpacity=-1.0f;
  732. Vector3 oldEmissive(-1,-1,-1);
  733. if (LightEnvironment != NULL) {
  734. DX8Wrapper::Set_Light_Environment(LightEnvironment);
  735. }
  736. if (Model->Get_Flag(MeshModelClass::SKIN)) {
  737. /*
  738. ** In the case of skin meshes, we need to render our polys with the identity transform
  739. */
  740. if (m_materialPassAlphaOverride != 1.0f)
  741. { VertexMaterialClass *mat=pass->Peek_Material();
  742. if (mat)
  743. {
  744. oldOpacity=mat->Get_Opacity();
  745. mat->Set_Opacity(m_materialPassAlphaOverride);
  746. }
  747. }
  748. if (m_materialPassEmissiveOverride != 1.0f)
  749. { VertexMaterialClass *mat=pass->Peek_Material();
  750. if (mat)
  751. {
  752. mat->Get_Emissive(&oldEmissive);
  753. mat->Set_Emissive(m_materialPassEmissiveOverride*oldEmissive);
  754. }
  755. }
  756. pass->Install_Materials();
  757. DX8Wrapper::Set_Index_Buffer(ib,0);
  758. SNAPSHOT_SAY(("Set_World_Identity\n"));
  759. DX8Wrapper::Set_World_Identity();
  760. DX8PolygonRendererListIterator it(&Model->PolygonRendererList);
  761. while (!it.Is_Done()) {
  762. if (it.Peek_Obj()->Get_Pass() == 0)
  763. it.Peek_Obj()->Render(BaseVertexOffset);
  764. it.Next();
  765. }
  766. if (oldOpacity >= 0)
  767. { //opacity was modified for this mesh instance, so need to restore the material setting which may be shared
  768. //among other instances.
  769. pass->Peek_Material()->Set_Opacity(oldOpacity);
  770. }
  771. if (oldEmissive.X >= 0)
  772. { //emissive was modified for this mesh instance, so need to restore the material setting which may be shared
  773. //among other instances.
  774. pass->Peek_Material()->Set_Emissive(oldEmissive);
  775. }
  776. //MW: Need uninstall custom materials in case they leave D3D in unknown state
  777. pass->UnInstall_Materials();
  778. } else if ((pass->Get_Cull_Volume() != NULL) && (MaterialPassClass::Is_Per_Polygon_Culling_Enabled())) {
  779. /*
  780. ** Generate the APT
  781. */
  782. temp_apt.Delete_All(false);
  783. Matrix3D modeltminv;
  784. Get_Transform().Get_Orthogonal_Inverse(modeltminv);
  785. OBBoxClass localbox;
  786. OBBoxClass::Transform(modeltminv,*(pass->Get_Cull_Volume()),&localbox);
  787. Vector3 view_dir;
  788. localbox.Basis.Get_Z_Vector(&view_dir);
  789. view_dir = -view_dir;
  790. if (Model->Has_Cull_Tree()) {
  791. Model->Generate_Rigid_APT(localbox,view_dir,temp_apt);
  792. } else {
  793. Model->Generate_Rigid_APT(view_dir,temp_apt);
  794. }
  795. if (temp_apt.Count() > 0) {
  796. int buftype = BUFFER_TYPE_DYNAMIC_DX8;
  797. if (Model->Get_Flag(MeshGeometryClass::SORT) && WW3D::Is_Sorting_Enabled()) {
  798. buftype = BUFFER_TYPE_DYNAMIC_SORTING;
  799. }
  800. /*
  801. ** Spew triangles in the APT into the dynamic index buffer
  802. */
  803. int min_v = Model->Get_Vertex_Count();
  804. int max_v = 0;
  805. DynamicIBAccessClass dynamic_ib(buftype,temp_apt.Count() * 3);
  806. {
  807. DynamicIBAccessClass::WriteLockClass lock(&dynamic_ib);
  808. unsigned short * indices = lock.Get_Index_Array();
  809. const TriIndex * polys = Model->Get_Polygon_Array();
  810. try {
  811. for (int i=0; i < temp_apt.Count(); i++)
  812. {
  813. unsigned v0 = polys[temp_apt[i]].I;
  814. unsigned v1 = polys[temp_apt[i]].J;
  815. unsigned v2 = polys[temp_apt[i]].K;
  816. indices[i*3 + 0] = (unsigned short)v0;
  817. indices[i*3 + 1] = (unsigned short)v1;
  818. indices[i*3 + 2] = (unsigned short)v2;
  819. min_v = WWMath::Min(v0,min_v);
  820. min_v = WWMath::Min(v1,min_v);
  821. min_v = WWMath::Min(v2,min_v);
  822. max_v = WWMath::Max(v0,max_v);
  823. max_v = WWMath::Max(v1,max_v);
  824. max_v = WWMath::Max(v2,max_v);
  825. }
  826. IndexBufferExceptionFunc();
  827. } catch(...) {
  828. IndexBufferExceptionFunc();
  829. }
  830. }
  831. /*
  832. ** Render
  833. */
  834. int vertex_offset = Model->PolygonRendererList.Peek_Head()->Get_Vertex_Offset();
  835. pass->Install_Materials();
  836. DX8Wrapper::Set_Transform(D3DTS_WORLD,Get_Transform());
  837. DX8Wrapper::Set_Index_Buffer(dynamic_ib,vertex_offset);
  838. DX8Wrapper::Draw_Triangles(
  839. 0,
  840. temp_apt.Count(),
  841. min_v,
  842. max_v-min_v+1);
  843. //MW: Need uninstall custom materials in case they leave D3D in unknown state
  844. pass->UnInstall_Materials();
  845. }
  846. } else {
  847. /*
  848. ** Normal mesh case, render polys with this mesh's transform
  849. */
  850. if (m_materialPassAlphaOverride != 1.0f)
  851. { VertexMaterialClass *mat=pass->Peek_Material();
  852. if (mat)
  853. {
  854. oldOpacity=mat->Get_Opacity();
  855. mat->Set_Opacity(m_materialPassAlphaOverride);
  856. }
  857. }
  858. if (m_materialPassEmissiveOverride != 1.0f)
  859. { VertexMaterialClass *mat=pass->Peek_Material();
  860. if (mat)
  861. {
  862. mat->Get_Emissive(&oldEmissive);
  863. mat->Set_Emissive(m_materialPassEmissiveOverride*oldEmissive);
  864. }
  865. }
  866. pass->Install_Materials();
  867. DX8Wrapper::Set_Index_Buffer(ib,0);
  868. SNAPSHOT_SAY(("Set_World_Transform\n"));
  869. DX8Wrapper::Set_Transform(D3DTS_WORLD,Transform);
  870. DX8PolygonRendererListIterator it(&Model->PolygonRendererList);
  871. while (!it.Is_Done()) {
  872. if (it.Peek_Obj()->Get_Pass() == 0)
  873. it.Peek_Obj()->Render(BaseVertexOffset);
  874. it.Next();
  875. }
  876. if (oldOpacity >= 0)
  877. { //opacity was modified for this mesh instance, so need to restore the material setting which may be shared
  878. //among other instances.
  879. pass->Peek_Material()->Set_Opacity(oldOpacity);
  880. }
  881. if (oldEmissive.X >= 0)
  882. { //emissive was modified for this mesh instance, so need to restore the material setting which may be shared
  883. //among other instances.
  884. pass->Peek_Material()->Set_Emissive(oldEmissive);
  885. }
  886. //MW: Need uninstall custom materials in case they leave D3D in unknown state
  887. pass->UnInstall_Materials();
  888. }
  889. }
  890. /***********************************************************************************************
  891. * MeshClass::Special_Render -- special render function for meshes *
  892. * *
  893. * INPUT: *
  894. * *
  895. * OUTPUT: *
  896. * *
  897. * WARNINGS: *
  898. * *
  899. * HISTORY: *
  900. * 12/10/98 GTH : Created. *
  901. *=============================================================================================*/
  902. void MeshClass::Special_Render(SpecialRenderInfoClass & rinfo)
  903. {
  904. if ((Is_Not_Hidden_At_All() == false) && (rinfo.RenderType != SpecialRenderInfoClass::RENDER_SHADOW)) {
  905. return;
  906. }
  907. if (rinfo.RenderType == SpecialRenderInfoClass::RENDER_VIS) {
  908. WWASSERT(rinfo.VisRasterizer != NULL);
  909. rinfo.VisRasterizer->Enable_Two_Sided_Rendering(!!Model->Get_Flag(MeshGeometryClass::TWO_SIDED));
  910. if (Model->Get_Flag(MeshModelClass::SKIN) == 0) {
  911. rinfo.VisRasterizer->Set_Model_Transform(Transform);
  912. rinfo.VisRasterizer->Render_Triangles( Model->Get_Vertex_Array(),
  913. Model->Get_Vertex_Count(),
  914. Model->Get_Polygon_Array(),
  915. Model->Get_Polygon_Count(),
  916. Get_Bounding_Box() );
  917. } else {
  918. int vertex_count = Model->Get_Vertex_Count();
  919. if (_TempVertexBuffer.Count() < vertex_count) _TempVertexBuffer.Resize(vertex_count);
  920. Vector3 *dst_vert = &(_TempVertexBuffer[0]);
  921. Get_Deformed_Vertices(dst_vert);
  922. rinfo.VisRasterizer->Set_Model_Transform(Matrix3D::Identity);
  923. rinfo.VisRasterizer->Render_Triangles( dst_vert,
  924. Model->Get_Vertex_Count(),
  925. Model->Get_Polygon_Array(),
  926. Model->Get_Polygon_Count(),
  927. Get_Bounding_Box() );
  928. }
  929. rinfo.VisRasterizer->Enable_Two_Sided_Rendering(false);
  930. }
  931. if (rinfo.RenderType == SpecialRenderInfoClass::RENDER_SHADOW) {
  932. const HTreeClass * htree = NULL;
  933. if (Container!=NULL) {
  934. htree = Container->Get_HTree();
  935. }
  936. Model->Shadow_Render(rinfo,Transform,htree);
  937. }
  938. }
  939. void MeshClass::Replace_Texture(TextureClass* texture,TextureClass* new_texture)
  940. {
  941. Model->Replace_Texture(texture,new_texture);
  942. }
  943. /***********************************************************************************************
  944. * MeshClass::Replace_VertexMaterial -- Replaces existing vertex material with a new one. Will *
  945. * *
  946. * *
  947. * *
  948. * *
  949. * INPUT: *
  950. * *
  951. * OUTPUT: *
  952. * *
  953. * WARNINGS: *
  954. * *
  955. * HISTORY: *
  956. * 4/2/2001 hy : Created. *
  957. *=============================================================================================*/
  958. void MeshClass::Replace_VertexMaterial(VertexMaterialClass* vmat,VertexMaterialClass* new_vmat)
  959. {
  960. Model->Replace_VertexMaterial(vmat,new_vmat);
  961. }
  962. /***********************************************************************************************
  963. * MeshClass::Make_Unique -- Makes mesh unique in the renderer, but still shares system ram ge *
  964. * *
  965. * *
  966. * *
  967. * *
  968. * INPUT: *
  969. * *
  970. * OUTPUT: *
  971. * *
  972. * WARNINGS: *
  973. * *
  974. * HISTORY: *
  975. * 4/2/2001 hy : Created. *
  976. *=============================================================================================*/
  977. void MeshClass::Make_Unique(bool force_meshmdl_clone)
  978. {
  979. // Usually we will not clone the mesh model if it is already unique - force_meshmdl_clone will
  980. // force it to be cloned in any case. This is used in some special situations, for example if we
  981. // want to change this mesh and it may have already been rendered, we need to clone the mesh
  982. // model regardless of whether there is another mesh using it.
  983. if (Model->Num_Refs()==1 && !force_meshmdl_clone) return;
  984. MeshModelClass *newmesh=NEW_REF(MeshModelClass,(*Model));
  985. REF_PTR_SET(Model,newmesh);
  986. REF_PTR_RELEASE(newmesh);
  987. }
  988. /***********************************************************************************************
  989. * MeshClass::Load -- creates a mesh out of a mesh chunk in a .w3d file *
  990. * *
  991. * INPUT: *
  992. * *
  993. * OUTPUT: *
  994. * *
  995. * WARNINGS: *
  996. * *
  997. * HISTORY: *
  998. * 06/12/1997 GH : Created. *
  999. *=============================================================================================*/
  1000. WW3DErrorType MeshClass::Load_W3D(ChunkLoadClass & cload)
  1001. {
  1002. Vector3 boxmin,boxmax;
  1003. /*
  1004. ** Make sure this mesh is "empty"
  1005. */
  1006. Free();
  1007. /*
  1008. ** Create empty MaterialInfo and Model
  1009. */
  1010. Model = NEW_REF(MeshModelClass,());
  1011. if (Model == NULL) {
  1012. WWDEBUG_SAY(("MeshClass::Load - Failed to allocate model\r\n"));
  1013. return WW3D_ERROR_LOAD_FAILED;
  1014. }
  1015. /*
  1016. ** Create and read in the model...
  1017. */
  1018. if (Model->Load_W3D(cload) != WW3D_ERROR_OK) {
  1019. Free();
  1020. return WW3D_ERROR_LOAD_FAILED;
  1021. }
  1022. /*
  1023. ** Pull interesting stuff out of the w3d attributes bits
  1024. */
  1025. int col_bits = (Model->W3dAttributes & W3D_MESH_FLAG_COLLISION_TYPE_MASK) >> W3D_MESH_FLAG_COLLISION_TYPE_SHIFT;
  1026. Set_Collision_Type( col_bits << 1 );
  1027. Set_Hidden(Model->W3dAttributes & W3D_MESH_FLAG_HIDDEN);
  1028. /*
  1029. ** Indicate whether this mesh is translucent. The mesh is considered translucent
  1030. ** if sorting has been enabled (alpha blending on pass 0) or if pass0 contains alpha-test.
  1031. ** This flag is mainly being used by visibility preprocessing code in Renegade.
  1032. */
  1033. int is_translucent = Model->Get_Flag(MeshModelClass::SORT);
  1034. int is_alpha = 0; //keep track of alpha pieces that require sorting (including static sort lists).
  1035. int is_additive = 0;
  1036. if (Model->Has_Shader_Array(0)) {
  1037. for (int i=0; i<Model->Get_Polygon_Count(); i++) {
  1038. ShaderClass shader = Model->Get_Shader(i,0);
  1039. is_translucent |= (shader.Get_Alpha_Test() == ShaderClass::ALPHATEST_ENABLE);
  1040. is_alpha |= (shader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO ||
  1041. shader.Get_Src_Blend_Func() != ShaderClass::SRCBLEND_ONE) && (shader.Get_Alpha_Test() != ShaderClass::ALPHATEST_ENABLE);
  1042. is_additive |= (shader.Get_Dst_Blend_Func() == ShaderClass::DSTBLEND_ONE &&
  1043. shader.Get_Src_Blend_Func() == ShaderClass::SRCBLEND_ONE);
  1044. }
  1045. } else {
  1046. ShaderClass shader = Model->Get_Single_Shader(0);
  1047. is_translucent |= (shader.Get_Alpha_Test() == ShaderClass::ALPHATEST_ENABLE);
  1048. is_alpha |= (shader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO ||
  1049. shader.Get_Src_Blend_Func() != ShaderClass::SRCBLEND_ONE) && (shader.Get_Alpha_Test() != ShaderClass::ALPHATEST_ENABLE);
  1050. is_additive |= (shader.Get_Dst_Blend_Func() == ShaderClass::DSTBLEND_ONE &&
  1051. shader.Get_Src_Blend_Func() == ShaderClass::SRCBLEND_ONE);
  1052. }
  1053. Set_Translucent(is_translucent);
  1054. Set_Alpha(is_alpha);
  1055. Set_Additive(is_additive);
  1056. return WW3D_ERROR_OK;
  1057. }
  1058. /***********************************************************************************************
  1059. * MeshClass::Cast_Ray -- compute a ray intersection with this mesh *
  1060. * *
  1061. * INPUT: *
  1062. * *
  1063. * OUTPUT: *
  1064. * *
  1065. * WARNINGS: *
  1066. * *
  1067. * HISTORY: *
  1068. * 6/17/98 GTH : Created. *
  1069. *=============================================================================================*/
  1070. bool MeshClass::Cast_Ray(RayCollisionTestClass & raytest)
  1071. {
  1072. if ((Get_Collision_Type() & raytest.CollisionType) == 0) return false;
  1073. //Modified for 'Generals' so we could select trees but filter out headlight beams, etc. -MW
  1074. if (raytest.CheckTranslucent && Is_Alpha()!=0)
  1075. return false;
  1076. if (Is_Hidden() && !raytest.CheckHidden) return false;
  1077. if (Is_Animation_Hidden()) return false;
  1078. if (raytest.Result->StartBad) return false;
  1079. Matrix3D world_to_obj;
  1080. Matrix3D world=Get_Transform();
  1081. // if aligned or oriented rotate the mesh so that it's aligned to the ray
  1082. if (Model->Get_Flag(MeshModelClass::ALIGNED)) {
  1083. Vector3 mesh_position;
  1084. world.Get_Translation(&mesh_position);
  1085. world.Obj_Look_At(mesh_position,mesh_position - raytest.Ray.Get_Dir(),0.0f);
  1086. } else if (Model->Get_Flag(MeshModelClass::ORIENTED)) {
  1087. Vector3 mesh_position;
  1088. world.Get_Translation(&mesh_position);
  1089. world.Obj_Look_At(mesh_position,raytest.Ray.Get_P0(),0.0f);
  1090. }
  1091. world.Get_Inverse(world_to_obj);
  1092. RayCollisionTestClass objray(raytest,world_to_obj);
  1093. WWASSERT(Model);
  1094. bool hit = Model->Cast_Ray(objray);
  1095. // transform result back into original coordinate system
  1096. if (hit) {
  1097. raytest.CollidedRenderObj = this;
  1098. Matrix3D::Rotate_Vector(world,raytest.Result->Normal, &(raytest.Result->Normal));
  1099. if (raytest.Result->ComputeContactPoint) {
  1100. Matrix3D::Transform_Vector(world,raytest.Result->ContactPoint, &(raytest.Result->ContactPoint));
  1101. }
  1102. }
  1103. return hit;
  1104. }
  1105. /***********************************************************************************************
  1106. * MeshClass::Cast_AABox -- cast an AABox against this mesh *
  1107. * *
  1108. * INPUT: *
  1109. * *
  1110. * OUTPUT: *
  1111. * *
  1112. * WARNINGS: *
  1113. * *
  1114. * HISTORY: *
  1115. * 6/17/98 GTH : Created. *
  1116. *=============================================================================================*/
  1117. bool MeshClass::Cast_AABox(AABoxCollisionTestClass & boxtest)
  1118. {
  1119. if ((Get_Collision_Type() & boxtest.CollisionType) == 0) return false;
  1120. if (boxtest.Result->StartBad) return false;
  1121. WWASSERT(Model);
  1122. // This function analyses the tranform to call optimized functions in certain cases
  1123. bool hit = Model->Cast_World_Space_AABox(boxtest, Get_Transform());
  1124. if (hit) {
  1125. boxtest.CollidedRenderObj = this;
  1126. }
  1127. return hit;
  1128. }
  1129. /***********************************************************************************************
  1130. * Cast_OBBox -- Cast an obbox against this mesh *
  1131. * *
  1132. * INPUT: *
  1133. * *
  1134. * OUTPUT: *
  1135. * *
  1136. * WARNINGS: *
  1137. * *
  1138. * HISTORY: *
  1139. * 6/17/98 GTH : Created. *
  1140. *=============================================================================================*/
  1141. bool MeshClass::Cast_OBBox(OBBoxCollisionTestClass & boxtest)
  1142. {
  1143. if ((Get_Collision_Type() & boxtest.CollisionType) == 0) return false;
  1144. if (boxtest.Result->StartBad) return false;
  1145. /*
  1146. ** transform into the local coordinate system of the mesh.
  1147. */
  1148. const Matrix3D & tm = Get_Transform();
  1149. Matrix3D world_to_obj;
  1150. tm.Get_Orthogonal_Inverse(world_to_obj);
  1151. OBBoxCollisionTestClass localtest(boxtest,world_to_obj);
  1152. WWASSERT(Model);
  1153. bool hit = Model->Cast_OBBox(localtest);
  1154. /*
  1155. ** If we hit, transform the result of the test back to the original coordinate system.
  1156. */
  1157. if (hit) {
  1158. boxtest.CollidedRenderObj = this;
  1159. Matrix3D::Rotate_Vector(tm,boxtest.Result->Normal, &(boxtest.Result->Normal));
  1160. if (boxtest.Result->ComputeContactPoint) {
  1161. Matrix3D::Transform_Vector(tm,boxtest.Result->ContactPoint, &(boxtest.Result->ContactPoint));
  1162. }
  1163. }
  1164. return hit;
  1165. }
  1166. /***********************************************************************************************
  1167. * MeshClass::Intersect_AABox -- test for intersection with given AABox *
  1168. * *
  1169. * The AAbox given is assumed to be in world space. Since meshes aren't generally in world *
  1170. * space, the test must be transformed into our local coordinate system (which turns it into *
  1171. * an OBBox...) *
  1172. * *
  1173. * INPUT: *
  1174. * *
  1175. * OUTPUT: *
  1176. * *
  1177. * WARNINGS: *
  1178. * *
  1179. * HISTORY: *
  1180. * 1/19/00 gth : Created. *
  1181. *=============================================================================================*/
  1182. bool MeshClass::Intersect_AABox(AABoxIntersectionTestClass & boxtest)
  1183. {
  1184. if ((Get_Collision_Type() & boxtest.CollisionType) == 0) return false;
  1185. Matrix3D inv_tm;
  1186. Get_Transform().Get_Orthogonal_Inverse(inv_tm);
  1187. OBBoxIntersectionTestClass local_test(boxtest,inv_tm);
  1188. WWASSERT(Model);
  1189. return Model->Intersect_OBBox(local_test);
  1190. }
  1191. /***********************************************************************************************
  1192. * MeshClass::Intersect_OBBox -- test for intersection with the given OBBox *
  1193. * *
  1194. * The given OBBox is assumed to be in world space so we need to transform it into the mesh's *
  1195. * local coordinate system. *
  1196. * *
  1197. * INPUT: *
  1198. * *
  1199. * OUTPUT: *
  1200. * *
  1201. * WARNINGS: *
  1202. * *
  1203. * HISTORY: *
  1204. * 1/19/00 gth : Created. *
  1205. *=============================================================================================*/
  1206. bool MeshClass::Intersect_OBBox(OBBoxIntersectionTestClass & boxtest)
  1207. {
  1208. if ((Get_Collision_Type() & boxtest.CollisionType) == 0) return false;
  1209. Matrix3D inv_tm;
  1210. Get_Transform().Get_Orthogonal_Inverse(inv_tm);
  1211. OBBoxIntersectionTestClass local_test(boxtest,inv_tm);
  1212. WWASSERT(Model);
  1213. return Model->Intersect_OBBox(local_test);
  1214. }
  1215. /***********************************************************************************************
  1216. * MeshClass::Get_Obj_Space_Bounding_Sphere -- returns obj-space bounding sphere *
  1217. * *
  1218. * INPUT: *
  1219. * *
  1220. * OUTPUT: *
  1221. * *
  1222. * WARNINGS: *
  1223. * *
  1224. * HISTORY: *
  1225. * 1/19/00 gth : Created. *
  1226. *=============================================================================================*/
  1227. void MeshClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
  1228. {
  1229. if (Model) {
  1230. Model->Get_Bounding_Sphere(&sphere);
  1231. } else {
  1232. sphere.Center.Set(0,0,0);
  1233. sphere.Radius = 1.0f;
  1234. }
  1235. }
  1236. /***********************************************************************************************
  1237. * MeshClass::Get_Obj_Space_Bounding_Box -- returns the obj-space bounding box *
  1238. * *
  1239. * INPUT: *
  1240. * *
  1241. * OUTPUT: *
  1242. * *
  1243. * WARNINGS: *
  1244. * *
  1245. * HISTORY: *
  1246. * 1/19/00 gth : Created. *
  1247. *=============================================================================================*/
  1248. void MeshClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
  1249. {
  1250. if (Model) {
  1251. Model->Get_Bounding_Box(&box);
  1252. } else {
  1253. box.Init(Vector3(0,0,0),Vector3(1,1,1));
  1254. }
  1255. }
  1256. /***********************************************************************************************
  1257. * MeshClass::Generate_Culling_Tree -- Generates a hierarchical culling tree for the mesh *
  1258. * *
  1259. * INPUT: *
  1260. * *
  1261. * OUTPUT: *
  1262. * *
  1263. * WARNINGS: *
  1264. * *
  1265. * HISTORY: *
  1266. * 6/18/98 GTH : Created. *
  1267. *=============================================================================================*/
  1268. void MeshClass::Generate_Culling_Tree(void)
  1269. {
  1270. Model->Generate_Culling_Tree();
  1271. }
  1272. /***********************************************************************************************
  1273. * MeshClass::Add_Dependencies_To_List -- Add dependent files to the list. *
  1274. * *
  1275. * INPUT: *
  1276. * *
  1277. * OUTPUT: *
  1278. * *
  1279. * WARNINGS: *
  1280. * *
  1281. * HISTORY: *
  1282. * 3/18/99 PDS : Created. *
  1283. *=============================================================================================*/
  1284. void MeshClass::Add_Dependencies_To_List
  1285. (
  1286. DynamicVectorClass<StringClass> &file_list,
  1287. bool textures_only
  1288. )
  1289. {
  1290. //
  1291. // Get a pointer to this mesh's material information object
  1292. //
  1293. MaterialInfoClass *material = Get_Material_Info ();
  1294. if (material != NULL) {
  1295. //
  1296. // Loop through all the textures and add their filenames to our list
  1297. //
  1298. for (int index = 0; index < material->Texture_Count (); index ++) {
  1299. //
  1300. // Add this texture's filename to the list
  1301. //
  1302. TextureClass *texture = material->Peek_Texture (index);
  1303. if (texture != NULL) {
  1304. file_list.Add (texture->Get_Full_Path ());
  1305. }
  1306. }
  1307. //
  1308. // Release our hold on the material information object
  1309. //
  1310. material->Release_Ref ();
  1311. }
  1312. RenderObjClass::Add_Dependencies_To_List (file_list, textures_only);
  1313. return ;
  1314. }
  1315. /***********************************************************************************************
  1316. * MeshClass::Update_Cached_Bounding_Volumes -- default collision sphere. *
  1317. * *
  1318. * INPUT: *
  1319. * *
  1320. * OUTPUT: *
  1321. * *
  1322. * WARNINGS: *
  1323. * *
  1324. * HISTORY: *
  1325. * 5/14/2001 NH : Created. *
  1326. *=============================================================================================*/
  1327. void MeshClass::Update_Cached_Bounding_Volumes(void) const
  1328. {
  1329. Get_Obj_Space_Bounding_Sphere(CachedBoundingSphere);
  1330. #ifdef ALLOW_TEMPORARIES
  1331. CachedBoundingSphere.Center = Get_Transform() * CachedBoundingSphere.Center;
  1332. #else
  1333. Get_Transform().mulVector3(CachedBoundingSphere.Center);
  1334. #endif
  1335. // If we are camera-aligned or -oriented, we don't know which way we are facing at this point,
  1336. // so the box we return needs to contain the sphere. Otherewise do the normal computation.
  1337. if (Model->Get_Flag(MeshModelClass::ALIGNED) || Model->Get_Flag(MeshModelClass::ORIENTED)) {
  1338. CachedBoundingBox.Center = CachedBoundingSphere.Center;
  1339. CachedBoundingBox.Extent.Set(CachedBoundingSphere.Radius, CachedBoundingSphere.Radius, CachedBoundingSphere.Radius);
  1340. } else {
  1341. Get_Obj_Space_Bounding_Box(CachedBoundingBox);
  1342. CachedBoundingBox.Transform(Get_Transform());
  1343. }
  1344. Validate_Cached_Bounding_Volumes();
  1345. }
  1346. // This utility function recurses throughout the subobjects of a renderobject, and for each
  1347. // MeshClass it finds it sets the given MeshModel flag on its model. This is useful for stuff
  1348. // like making a RenderObjects' polys sort.
  1349. void Set_MeshModel_Flag(RenderObjClass *robj, int flag, int onoff)
  1350. {
  1351. if (robj->Class_ID() == RenderObjClass::CLASSID_MESH) {
  1352. // Set flag on model (the assumption is that meshes don't have subobjects)
  1353. MeshClass *mesh = (MeshClass *)robj;
  1354. MeshModelClass *model = mesh->Get_Model();
  1355. model->Set_Flag((MeshModelClass::FlagsType)flag, onoff != 0);
  1356. model->Release_Ref();
  1357. } else {
  1358. // Recurse to subobjects (if any)
  1359. int num_obj = robj->Get_Num_Sub_Objects();
  1360. RenderObjClass *sub_obj;
  1361. for (int i = 0; i < num_obj; i++) {
  1362. sub_obj = robj->Get_Sub_Object(i);
  1363. if (sub_obj) {
  1364. Set_MeshModel_Flag(sub_obj, flag, onoff);
  1365. sub_obj->Release_Ref();
  1366. }
  1367. }
  1368. }
  1369. }
  1370. int MeshClass::Get_Sort_Level(void) const
  1371. {
  1372. if (Model) {
  1373. return (Model->Get_Sort_Level());
  1374. }
  1375. return(SORT_LEVEL_NONE);
  1376. }
  1377. void MeshClass::Set_Sort_Level(int level)
  1378. {
  1379. if (Model) {
  1380. Model->Set_Sort_Level(level);
  1381. }
  1382. }
  1383. int MeshClass::Get_Draw_Call_Count(void) const
  1384. {
  1385. if (Model != NULL) {
  1386. // Prefer to return the number of polygon renderers
  1387. int prcount = Model->PolygonRendererList.Count();
  1388. if (prcount > 0) {
  1389. return prcount;
  1390. }
  1391. // Otherwise if we have textures, return the number of textures (e.g. dont have prs when sorting)
  1392. if ((Model->MatInfo != NULL) && (Model->MatInfo->Texture_Count() > 0)) {
  1393. return Model->MatInfo->Texture_Count();
  1394. }
  1395. // Otherwise, return 1
  1396. return 1;
  1397. } else {
  1398. return 0;
  1399. }
  1400. }