meshmdlio.cpp 109 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /VSS_Sync/ww3d2/meshmdlio.cpp $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 8/29/01 7:29p $*
  29. * *
  30. * $Revision:: 22 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * MeshModelClass::Load_W3D -- Load a mesh from a W3D file *
  35. * MeshModelClass::read_chunks -- read all of the chunks for a mesh *
  36. * MeshModelClass::read_vertices -- reads the vertex chunk *
  37. * MeshModelClass::read_texcoords -- read in the texture coordinates chunk *
  38. * MeshModelClass::read_vertex_normals -- reads a vertex normal chunk from the w3d file *
  39. * MeshModelClass::read_v3_materials -- Reads in version 3 materials. *
  40. * MeshModelClass::read_triangles -- read the triangles chunk *
  41. * MeshModelClass::read_per_tri_materials -- read the material indices for each triangle *
  42. * MeshModelClass::read_user_text -- read in the user text chunk *
  43. * MeshModelClass::read_vertex_colors -- read in the vertex colors chunk *
  44. * MeshModelClass::read_vertex_influences -- read in the vertex influences chunk *
  45. * MeshModelClass::read_vertex_shade_indices -- read the shade index chunk *
  46. * MeshModelClass::read_material_info -- read the material info chunk *
  47. * MeshModelClass::read_shaders -- read the shaders chunk *
  48. * MeshModelClass::read_vertex_materials -- read the vertex materials chunk *
  49. * MeshModelClass::read_textures -- read the textures chunk *
  50. * MeshModelClass::read_material_pass -- read a material pass chunk *
  51. * MeshModelClass::read_vertex_material_ids -- read the vmat ids for a pass *
  52. * MeshModelClass::read_shader_ids -- read the shader indexes for a pass *
  53. * MeshModelClass::read_dcg -- read the per-vertex diffuse color for a pass *
  54. * MeshModelClass::read_dig -- read the per-vertex diffuse illumination for a pass *
  55. * MeshModelClass::read_scg -- read the specular color for a pass *
  56. * MeshModelClass::read_texture_stage -- read texture stage chunks *
  57. * MeshModelClass::read_texture_ids -- read the texture ids for a pass,stage *
  58. * MeshModelClass::read_stage_texcoords -- read the texcoords for a pass,stage *
  59. * MeshModelClass::read_per_face_texcoord_ids -- read uv indices for given (pass,stage). *
  60. * MeshModelClass::read_prelit_material -- read prelit material chunks. *
  61. * MeshModelClass::read_aabtree -- loads the aabtree chunk *
  62. * MeshModelClass::Save -- Save this mesh model! *
  63. * MeshLoadContextClass::MeshLoadContextClass -- constructor for MeshLoadContextClass *
  64. * MeshLoadContextClass::~MeshLoadContextClass -- destructor *
  65. * MeshLoadContextClass::Get_Texcoord_Array -- returns the texture coordinates array *
  66. * MeshLoadContextClass::Add_Shader -- adds a shader to the array *
  67. * MeshLoadContextClass::Add_Vertex_Materail -- adds a vertex material *
  68. * MeshLoadContextClass::Add_Texture -- adds a texture *
  69. * MeshLoadContextClass::Add_Legacy_Material -- adds a legacy material *
  70. * MeshLoadContextClass::Peek_Legacy_Shader -- returns a legacy shader *
  71. * MeshLoadContextClass::Peek_Legacy_Vertex_Material -- returns a pointer to a legacy vmat *
  72. * MeshLoadContextClass::Peek_Legacy_Texture -- returns a pointer to a texture *
  73. * MeshSaveContextClass::MeshSaveContextClass -- constructor *
  74. * MeshSaveContextClass::~MeshSaveContextClass -- destructor *
  75. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  76. #include "meshmdl.h"
  77. #include "aabtree.h"
  78. #include "matinfo.h"
  79. #include "vertmaterial.h"
  80. #include "shader.h"
  81. #include "texture.h"
  82. #include "chunkio.h"
  83. #include "w3derr.h"
  84. #include "w3d_file.h"
  85. #include "w3d_util.h"
  86. #include "assetmgr.h"
  87. #include "simplevec.h"
  88. #include "realcrc.h"
  89. #include "dx8wrapper.h"
  90. #include <stdio.h>
  91. #ifdef _UNIX
  92. #include "osdep/osdep.h"
  93. #endif
  94. #define MESH_SINGLE_MATERIAL_HACK 0 // (gth) forces all multi-material meshes to use their first material only. (NOT RECOMMENDED, TESTING ONLY!)
  95. #define MESH_FORCE_STATIC_SORT_HACK 0 // (gth) forces all sorting meshes to use static sort level 1 instead.
  96. /**
  97. ** MeshLoadContextClass
  98. ** This class is just used as a temporary scratchpad while a mesh is being
  99. ** loaded. In some cases, a chunk will be encountered before I have a place
  100. ** to plug it into the mesh model, etc. It is also used to convert from the
  101. ** old material format to the new one (detecting duplicated materials in the
  102. ** process).
  103. **
  104. ** This object will hold refs to all of the unique material objects. These
  105. ** objects will later be transferred into the MaterialInfo for the mesh and it
  106. ** will own the refs for the mesh. The load context object is destroyed once
  107. ** loading is complete...
  108. */
  109. class MeshLoadContextClass : public W3DMPO
  110. {
  111. W3DMPO_GLUE(MeshLoadContextClass)
  112. private:
  113. MeshLoadContextClass(void);
  114. ~MeshLoadContextClass(void);
  115. W3dTexCoordStruct * Get_Texcoord_Array(void);
  116. int Add_Shader(ShaderClass shader);
  117. int Add_Vertex_Material(VertexMaterialClass * vmat);
  118. int Add_Texture(TextureClass* tex);
  119. ShaderClass Peek_Shader(int index) { return Shaders[index]; }
  120. VertexMaterialClass * Peek_Vertex_Material(int index) { return VertexMaterials[index]; }
  121. TextureClass * Peek_Texture(int index) { return Textures[index]; }
  122. int Shader_Count(void) { return Shaders.Count(); }
  123. int Vertex_Material_Count(void) { return VertexMaterials.Count(); }
  124. int Texture_Count(void) { return Textures.Count(); }
  125. /*
  126. ** Legacy material support.
  127. */
  128. void Add_Legacy_Material(ShaderClass shader,VertexMaterialClass * vmat,TextureClass * tex);
  129. ShaderClass Peek_Legacy_Shader(int legacy_material_index);
  130. VertexMaterialClass * Peek_Legacy_Vertex_Material(int legacy_material_index);
  131. TextureClass * Peek_Legacy_Texture(int legacy_material_index);
  132. /*
  133. ** Redundant UV detection support. The context provides a temporary buffer to
  134. ** load the uv coordinates into.
  135. */
  136. Vector2 * Get_Temporary_UV_Array(int elementcount);
  137. /*
  138. ** Currently, the only tool that creates DIG chunks is the lightmap tool. Since DX8 support
  139. ** for linking the emissive material color to an array seems poor, We're just going to multiply
  140. ** the DIG array into the DCG array (or make it the DCG array). Now, to properly support the
  141. ** "alternate material set", we have to know whether we've already encountered a DIG chunk so
  142. ** these flags provide that functionality.
  143. */
  144. void Notify_Loaded_DIG_Chunk(bool onoff = true) { LoadedDIG = onoff; }
  145. bool Already_Loaded_DIG(void) { return LoadedDIG; }
  146. private:
  147. struct LegacyMaterialClass
  148. {
  149. LegacyMaterialClass(void) : Name(NULL),VertexMaterialIdx(0),ShaderIdx(0),TextureIdx(0) { }
  150. ~LegacyMaterialClass(void) { if (Name) free(Name); }
  151. void Set_Name(const char * name) { if (Name) free(Name); Name = NULL; if (name) Name = strdup(name); }
  152. char * Name;
  153. int VertexMaterialIdx;
  154. int ShaderIdx;
  155. int TextureIdx;
  156. };
  157. W3dMeshHeader3Struct Header;
  158. W3dTexCoordStruct * TexCoords;
  159. W3dMaterialInfoStruct MatInfo;
  160. uint32 PrelitChunkID;
  161. int CurPass;
  162. int CurTexStage;
  163. DynamicVectorClass < LegacyMaterialClass * > LegacyMaterials;
  164. DynamicVectorClass < ShaderClass > Shaders;
  165. DynamicVectorClass < VertexMaterialClass * > VertexMaterials;
  166. DynamicVectorClass < unsigned long > VertexMaterialCrcs;
  167. DynamicVectorClass < TextureClass * > Textures;
  168. /*
  169. ** Alternate material data. Any alternate material data will be loaded into
  170. ** this MeshMatDescClass object. When loading is finished, an alternate MeshMatDescClass
  171. ** will be allocated in the mesh model. This MeshMatDescClass will be initialized to be
  172. ** identical to the default MeshMatDescClass and then any data contained in this
  173. ** MeshMatDescClass will replace the relevant arrays.
  174. */
  175. MeshMatDescClass AlternateMatDesc;
  176. SimpleVecClass<Vector2> TempUVArray;
  177. /*
  178. ** Record when we load the DIG chunk
  179. */
  180. bool LoadedDIG;
  181. friend class MeshClass;
  182. friend class MeshModelClass;
  183. };
  184. /*
  185. ** MeshSaveContextClass
  186. ** This class is used to pass information between the saving code in a mesh
  187. */
  188. class MeshSaveContextClass
  189. {
  190. public:
  191. MeshSaveContextClass(void);
  192. ~MeshSaveContextClass(void);
  193. int CurPass;
  194. int CurStage;
  195. MaterialCollectorClass Materials;
  196. };
  197. /***********************************************************************************************
  198. * MeshModelClass::Load_W3D -- Load a mesh from a W3D file *
  199. * *
  200. * INPUT: *
  201. * *
  202. * OUTPUT: *
  203. * *
  204. * WARNINGS: *
  205. * *
  206. * HISTORY: *
  207. * 2/16/99 GTH : Created. *
  208. *=============================================================================================*/
  209. WW3DErrorType MeshModelClass::Load_W3D(ChunkLoadClass & cload)
  210. {
  211. MeshLoadContextClass * context = NULL;
  212. /*
  213. ** Open the first chunk, it should be the mesh header
  214. */
  215. cload.Open_Chunk();
  216. if (cload.Cur_Chunk_ID() != W3D_CHUNK_MESH_HEADER3) {
  217. WWDEBUG_SAY(("Old format mesh mesh, no longer supported.\n"));
  218. goto Error;
  219. }
  220. context = W3DNEW MeshLoadContextClass;
  221. if (cload.Read(&(context->Header),sizeof(W3dMeshHeader3Struct)) != sizeof(W3dMeshHeader3Struct)) {
  222. goto Error;
  223. }
  224. cload.Close_Chunk();
  225. /*
  226. ** Process the header
  227. */
  228. char * tmpname;
  229. int namelen;
  230. Reset(context->Header.NumTris,context->Header.NumVertices,1);
  231. namelen = strlen(context->Header.ContainerName);
  232. namelen += strlen(context->Header.MeshName);
  233. namelen += 2;
  234. W3dAttributes = context->Header.Attributes;
  235. SortLevel = context->Header.SortLevel;
  236. tmpname = W3DNEWARRAY char[namelen];
  237. memset(tmpname,0,namelen);
  238. if (strlen(context->Header.ContainerName) > 0) {
  239. strcpy(tmpname,context->Header.ContainerName);
  240. strcat(tmpname,".");
  241. }
  242. strcat(tmpname,context->Header.MeshName);
  243. Set_Name(tmpname);
  244. delete[] tmpname;
  245. tmpname = NULL;
  246. context->AlternateMatDesc.Set_Vertex_Count(VertexCount);
  247. context->AlternateMatDesc.Set_Polygon_Count(PolyCount);
  248. /*
  249. ** Set Bounding Info
  250. */
  251. BoundBoxMin.Set(context->Header.Min.X,context->Header.Min.Y,context->Header.Min.Z);
  252. BoundBoxMax.Set(context->Header.Max.X,context->Header.Max.Y,context->Header.Max.Z);
  253. BoundSphereCenter.Set(context->Header.SphCenter.X,context->Header.SphCenter.Y,context->Header.SphCenter.Z);
  254. BoundSphereRadius = context->Header.SphRadius;
  255. /*
  256. ** Flags
  257. */
  258. if (context->Header.Version >= W3D_MAKE_VERSION(4,1)) {
  259. int geometry_type = context->Header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK;
  260. switch (geometry_type)
  261. {
  262. case W3D_MESH_FLAG_GEOMETRY_TYPE_NORMAL:
  263. break;
  264. case W3D_MESH_FLAG_GEOMETRY_TYPE_CAMERA_ALIGNED:
  265. Set_Flag(ALIGNED,true);
  266. break;
  267. case W3D_MESH_FLAG_GEOMETRY_TYPE_CAMERA_ORIENTED:
  268. Set_Flag(ORIENTED,true);
  269. break;
  270. case W3D_MESH_FLAG_GEOMETRY_TYPE_SKIN:
  271. Set_Flag(SKIN,true);
  272. Set_Flag(ALLOW_NPATCHES,true);
  273. break;
  274. }
  275. }
  276. if (context->Header.Attributes & W3D_MESH_FLAG_TWO_SIDED) {
  277. Set_Flag(TWO_SIDED,true);
  278. }
  279. if (context->Header.Attributes & W3D_MESH_FLAG_CAST_SHADOW) {
  280. Set_Flag(CAST_SHADOW,true);
  281. }
  282. if (context->Header.Attributes & W3D_MESH_FLAG_NPATCHABLE) {
  283. Set_Flag(ALLOW_NPATCHES,true);
  284. }
  285. // Configure the load sequence for prelighting.
  286. if (context->Header.Attributes & W3D_MESH_FLAG_PRELIT_MASK) {
  287. // Select from the available prelit materials based on current prelit lighting mode.
  288. // If the model does not have the current prelit mode, select the next highest quality
  289. // prelit material that is available.
  290. switch (WW3D::Get_Prelit_Mode()) {
  291. case WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE:
  292. if (context->Header.Attributes & W3D_MESH_FLAG_PRELIT_LIGHTMAP_MULTI_TEXTURE) {
  293. context->PrelitChunkID = W3D_CHUNK_PRELIT_LIGHTMAP_MULTI_TEXTURE;
  294. Set_Flag (PRELIT_LIGHTMAP_MULTI_TEXTURE, true);
  295. break;
  296. }
  297. // Else fall thru...
  298. case WW3D::PRELIT_MODE_LIGHTMAP_MULTI_PASS:
  299. if (context->Header.Attributes & W3D_MESH_FLAG_PRELIT_LIGHTMAP_MULTI_PASS) {
  300. context->PrelitChunkID = W3D_CHUNK_PRELIT_LIGHTMAP_MULTI_PASS;
  301. Set_Flag (PRELIT_LIGHTMAP_MULTI_PASS, true);
  302. break;
  303. }
  304. // Else fall thru...
  305. case WW3D::PRELIT_MODE_VERTEX:
  306. if (context->Header.Attributes & W3D_MESH_FLAG_PRELIT_VERTEX) {
  307. context->PrelitChunkID = W3D_CHUNK_PRELIT_VERTEX;
  308. Set_Flag (PRELIT_VERTEX, true);
  309. break;
  310. }
  311. // Else fall thru...
  312. default:
  313. // This prelighting option MUST be available if none of the others are available.
  314. WWASSERT (context->Header.Attributes & W3D_MESH_FLAG_PRELIT_UNLIT);
  315. context->PrelitChunkID = W3D_CHUNK_PRELIT_UNLIT;
  316. break;
  317. }
  318. } else {
  319. // For backwards compatibility, test for obsolete lightmap flag.
  320. if (context->Header.Attributes & OBSOLETE_W3D_MESH_FLAG_LIGHTMAPPED) {
  321. Set_Flag (PRELIT_LIGHTMAP_MULTI_PASS, true);
  322. }
  323. // Else this mesh has no prelighting.
  324. }
  325. read_chunks(cload,context);
  326. /*
  327. ** If this is a pre-3.0 mesh and it has vertex influences,
  328. ** fixup the bone indices to account for the new root node
  329. */
  330. if ((context->Header.Version < W3D_MAKE_VERSION(3,0)) && (Get_Flag(SKIN))) {
  331. uint16 * links = get_bone_links();
  332. WWASSERT(links);
  333. for (int bi = 0; bi < Get_Vertex_Count(); bi++) {
  334. links[bi] += 1;
  335. }
  336. }
  337. /*
  338. ** If this mesh is collideable and no AABTree was in the file, generate one now
  339. */
  340. if ( (((W3dAttributes & W3D_MESH_FLAG_COLLISION_TYPE_MASK) >> W3D_MESH_FLAG_COLLISION_TYPE_SHIFT) != 0) &&
  341. (CullTree == NULL))
  342. {
  343. Generate_Culling_Tree();
  344. }
  345. /*
  346. ** Transfer the materials into the MatInfo
  347. */
  348. install_materials(context);
  349. /*
  350. ** Delete the temporary LoadInfo object
  351. */
  352. delete context;
  353. /*
  354. ** Post-process the model: optimize passes, activate fog etc.
  355. */
  356. post_process();
  357. return WW3D_ERROR_OK;
  358. Error:
  359. return WW3D_ERROR_LOAD_FAILED;
  360. }
  361. /***********************************************************************************************
  362. * MeshModelClass::read_chunks -- read all of the chunks for a mesh *
  363. * *
  364. * INPUT: *
  365. * *
  366. * OUTPUT: *
  367. * *
  368. * WARNINGS: *
  369. * *
  370. * HISTORY: *
  371. * 2/16/99 GTH : Created. *
  372. *=============================================================================================*/
  373. WW3DErrorType MeshModelClass::read_chunks(ChunkLoadClass & cload,MeshLoadContextClass * context)
  374. {
  375. /*
  376. ** Read in the chunk header
  377. ** If there are no more chunks within the mesh chunk,
  378. ** we are done.
  379. */
  380. while (cload.Open_Chunk()) {
  381. /*
  382. ** Process the chunk
  383. */
  384. WW3DErrorType error = WW3D_ERROR_OK;
  385. switch (cload.Cur_Chunk_ID()) {
  386. case W3D_CHUNK_VERTICES:
  387. // call up to MeshGeometryClass
  388. error = read_vertices(cload);
  389. break;
  390. case W3D_CHUNK_SURRENDER_NORMALS:
  391. case W3D_CHUNK_VERTEX_NORMALS:
  392. // call up to MeshGeometryClass
  393. error = read_vertex_normals(cload);
  394. break;
  395. case W3D_CHUNK_TEXCOORDS:
  396. error = read_texcoords(cload,context);
  397. break;
  398. case O_W3D_CHUNK_MATERIALS:
  399. case O_W3D_CHUNK_MATERIALS2:
  400. WWDEBUG_SAY(( "Obsolete material chunk encountered in mesh: %s.%s\r\n", context->Header.ContainerName,context->Header.MeshName));
  401. WWASSERT(0);
  402. break;
  403. case W3D_CHUNK_MATERIALS3:
  404. WWDEBUG_SAY(( "Obsolete material chunk encountered in mesh: %s.%s\r\n", context->Header.ContainerName,context->Header.MeshName));
  405. error = read_v3_materials(cload,context);
  406. break;
  407. case O_W3D_CHUNK_SURRENDER_TRIANGLES:
  408. WWASSERT_PRINT( 0, "Obsolete Triangle Chunk Encountered!\r\n" );
  409. break;
  410. case W3D_CHUNK_TRIANGLES:
  411. // call up to MeshGeometryClass
  412. error = read_triangles(cload);
  413. break;
  414. case W3D_CHUNK_PER_TRI_MATERIALS:
  415. error = read_per_tri_materials(cload,context);
  416. break;
  417. case W3D_CHUNK_MESH_USER_TEXT:
  418. // call up to MeshGeometryClass
  419. error = read_user_text(cload);
  420. break;
  421. case W3D_CHUNK_VERTEX_COLORS:
  422. error = read_vertex_colors(cload,context);
  423. break;
  424. case W3D_CHUNK_VERTEX_INFLUENCES:
  425. // call up to MeshGeometryClass
  426. error = read_vertex_influences(cload);
  427. break;
  428. case W3D_CHUNK_VERTEX_SHADE_INDICES:
  429. // call up to MeshGeometryClass
  430. error = read_vertex_shade_indices(cload);
  431. break;
  432. case W3D_CHUNK_MATERIAL_INFO:
  433. error = read_material_info(cload,context);
  434. break;
  435. case W3D_CHUNK_SHADERS:
  436. error = read_shaders(cload,context);
  437. break;
  438. case W3D_CHUNK_VERTEX_MATERIALS:
  439. error = read_vertex_materials(cload,context);
  440. break;
  441. case W3D_CHUNK_TEXTURES:
  442. error = read_textures(cload,context);
  443. break;
  444. case W3D_CHUNK_MATERIAL_PASS:
  445. error = read_material_pass(cload,context);
  446. break;
  447. case W3D_CHUNK_DEFORM:
  448. WWDEBUG_SAY(("Obsolete deform chunk encountered in mesh: %s.%s\r\n", context->Header.ContainerName,context->Header.MeshName));
  449. break;
  450. case W3D_CHUNK_DAMAGE:
  451. WWDEBUG_SAY(("Obsolete damage chunk encountered in mesh: %s.%s\r\n", context->Header.ContainerName,context->Header.MeshName));
  452. break;
  453. case W3D_CHUNK_PRELIT_UNLIT:
  454. case W3D_CHUNK_PRELIT_VERTEX:
  455. case W3D_CHUNK_PRELIT_LIGHTMAP_MULTI_PASS:
  456. case W3D_CHUNK_PRELIT_LIGHTMAP_MULTI_TEXTURE:
  457. read_prelit_material (cload, context);
  458. break;
  459. case W3D_CHUNK_AABTREE:
  460. // call up to MeshGeometryClass
  461. read_aabtree(cload);
  462. break;
  463. default:
  464. break;
  465. }
  466. cload.Close_Chunk();
  467. if (error != WW3D_ERROR_OK) {
  468. return error;
  469. }
  470. }
  471. return WW3D_ERROR_OK;
  472. }
  473. /***********************************************************************************************
  474. * MeshModelClass::read_texcoords -- read in the texture coordinates chunk *
  475. * *
  476. * INPUT: *
  477. * *
  478. * OUTPUT: *
  479. * *
  480. * WARNINGS: *
  481. * *
  482. * HISTORY: *
  483. * 3/6/98 GTH : Created. *
  484. * 2/16/99 GTH : Moved into MeshModel *
  485. *=============================================================================================*/
  486. WW3DErrorType MeshModelClass::read_texcoords(ChunkLoadClass & cload,MeshLoadContextClass * context)
  487. {
  488. W3dTexCoordStruct texcoord;
  489. Vector2 * uvarray = 0;
  490. int elementcount = cload.Cur_Chunk_Length() / sizeof (W3dTexCoordStruct);
  491. uvarray = context->Get_Temporary_UV_Array(elementcount);
  492. if (uvarray != NULL) {
  493. /*
  494. ** Read the uv's into the first u-v pass array
  495. ** NOTE: this is an obsolete function. Texture coordinates are now
  496. ** loaded in the pass chunks
  497. */
  498. for (int i=0; i<VertexCount; i++) {
  499. if (cload.Read(&(texcoord),sizeof(W3dTexCoordStruct)) != sizeof(W3dTexCoordStruct)) {
  500. return WW3D_ERROR_LOAD_FAILED;
  501. }
  502. uvarray[i].Set(texcoord.U,1.0f - texcoord.V);
  503. }
  504. DefMatDesc->Install_UV_Array(context->CurPass,context->CurTexStage,uvarray,elementcount);
  505. }
  506. return WW3D_ERROR_OK;
  507. }
  508. /***********************************************************************************************
  509. * MeshModelClass::read_v3_materials -- Reads in version 3 materials. *
  510. * *
  511. * INPUT: *
  512. * *
  513. * OUTPUT: *
  514. * *
  515. * WARNINGS: *
  516. * *
  517. * HISTORY: *
  518. * 4/2/98 GTH : Created. *
  519. * 2/16/99 GTH : Moved into MeshModelClass *
  520. *=============================================================================================*/
  521. WW3DErrorType MeshModelClass::read_v3_materials(ChunkLoadClass & cload,MeshLoadContextClass * context)
  522. {
  523. for (unsigned int mi=0; mi<context->Header.NumMaterials; mi++) {
  524. /*
  525. ** First, we expect a W3D_CHUNK_MATERIAL3 to wrap the entire material
  526. */
  527. if (!cload.Open_Chunk()) goto Error;
  528. if (cload.Cur_Chunk_ID() != W3D_CHUNK_MATERIAL3) goto Error;
  529. /*
  530. ** Inside the MATERIAL3 will be the following:
  531. **
  532. ** W3D_MATERIAL3_NAME - name of the material
  533. ** W3D_MATERIAL3_INFO - equivalent to 1.40 vertex material parameters
  534. ** W3D_MATERIAL3_DC_MAP - diffuse color mapping
  535. ** W3D_MAP3_FILENAME - filename of the texture map
  536. ** W3D_MAP3_INFO - animation, etc information
  537. ** W3D_MATERIAL3_DI_MAP - diffuse illumination map
  538. ** W3D_MATERIAL3_SC_MAP - specular color map
  539. ** W3D_MATERIAL3_SI_MAP - specular illumination map
  540. */
  541. VertexMaterialClass * vmat = NULL;
  542. ShaderClass shader;
  543. TextureClass * tex = NULL;
  544. char name[256];
  545. /*
  546. ** Read the material name
  547. */
  548. if (!cload.Open_Chunk()) goto Error;
  549. if (cload.Cur_Chunk_ID() != W3D_CHUNK_MATERIAL3_NAME) goto Error;
  550. cload.Read(name,cload.Cur_Chunk_Length());
  551. if (!cload.Close_Chunk()) goto Error;
  552. /*
  553. ** Read the vertex material parameters
  554. */
  555. if (!cload.Open_Chunk()) goto Error;
  556. W3dMaterial3Struct mat;
  557. if (cload.Cur_Chunk_ID() != W3D_CHUNK_MATERIAL3_INFO) goto Error;
  558. if (cload.Read(&mat,sizeof(W3dMaterial3Struct)) != sizeof(W3dMaterial3Struct)) goto Error;
  559. vmat = W3DNEW VertexMaterialClass;
  560. vmat->Init_From_Material3(mat);
  561. vmat->Set_Name(name);
  562. shader.Init_From_Material3(mat);
  563. #if 0 // TODO... ummmm...
  564. if (MeshClass::Legacy_Meshes_Fogged) {
  565. shader.Set_Fog_Func( ShaderClass::FOG_ENABLE );
  566. } else {
  567. shader.Set_Fog_Func( ShaderClass::FOG_DISABLE );
  568. }
  569. #endif
  570. /*
  571. ** If this shader does alpha blending, the mesh must be sorted.
  572. */
  573. if (shader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO) {
  574. Set_Flag(MeshModelClass::SORT,true);
  575. }
  576. if (!cload.Close_Chunk()) goto Error;
  577. /*
  578. ** Look for the DC map and read it in
  579. */
  580. while (cload.Open_Chunk()) {
  581. if (cload.Cur_Chunk_ID() == W3D_CHUNK_MATERIAL3_DC_MAP) {
  582. /*
  583. ** Read in the texture filename
  584. */
  585. char filename[_MAX_FNAME + _MAX_EXT];
  586. if (!cload.Open_Chunk()) goto Error;
  587. if (cload.Cur_Chunk_ID() != W3D_CHUNK_MAP3_FILENAME) goto Error;
  588. if (cload.Cur_Chunk_Length() >= sizeof(filename)) goto Error;
  589. cload.Read(filename,cload.Cur_Chunk_Length());
  590. if (!cload.Close_Chunk()) goto Error;
  591. /*
  592. ** Read in the auxiliary map info
  593. */
  594. W3dMap3Struct mapinfo;
  595. if (!cload.Open_Chunk()) goto Error;
  596. if (cload.Cur_Chunk_ID() != W3D_CHUNK_MAP3_INFO) goto Error;
  597. if (cload.Read(&mapinfo,sizeof(W3dMap3Struct)) != sizeof(W3dMap3Struct)) goto Error;
  598. if (!cload.Close_Chunk()) goto Error;
  599. if ( mapinfo.FrameCount > 1 ) {
  600. WWDEBUG_SAY(("ERROR: Obsolete Animated Texture detected in model: %s\r\n",context->Header.MeshName));
  601. }
  602. tex = WW3DAssetManager::Get_Instance()->Get_Texture(filename);
  603. shader.Set_Texturing(ShaderClass::TEXTURING_ENABLE);
  604. } else if (cload.Cur_Chunk_ID() == W3D_CHUNK_MATERIAL3_SI_MAP) {
  605. Vector3 diffuse_color;
  606. vmat->Get_Diffuse( &diffuse_color);
  607. if ( diffuse_color == Vector3( 0,0,0 ) ) {
  608. /*
  609. ** Read in the texture filename
  610. */
  611. char filename[_MAX_FNAME + _MAX_EXT];
  612. if (!cload.Open_Chunk()) goto Error;
  613. if (cload.Cur_Chunk_ID() != W3D_CHUNK_MAP3_FILENAME) goto Error;
  614. if (cload.Cur_Chunk_Length() >= sizeof(filename)) goto Error;
  615. cload.Read(filename,cload.Cur_Chunk_Length());
  616. if (!cload.Close_Chunk()) goto Error;
  617. if (tex) tex->Release_Ref();
  618. /*
  619. ** Read in the auxiliary map info
  620. */
  621. W3dMap3Struct mapinfo;
  622. if (!cload.Open_Chunk()) goto Error;
  623. if (cload.Cur_Chunk_ID() != W3D_CHUNK_MAP3_INFO) goto Error;
  624. if (cload.Read(&mapinfo,sizeof(W3dMap3Struct)) != sizeof(W3dMap3Struct)) goto Error;
  625. if (!cload.Close_Chunk()) goto Error;
  626. if ( mapinfo.FrameCount > 1 ) {
  627. WWDEBUG_SAY(("ERROR: Obsolete Animated Texture detected in model: %s\r\n",context->Header.MeshName));
  628. }
  629. tex = WW3DAssetManager::Get_Instance()->Get_Texture(filename);
  630. shader.Set_Texturing(ShaderClass::TEXTURING_ENABLE);
  631. shader.Set_Dst_Blend_Func(ShaderClass::DSTBLEND_ONE);
  632. shader.Set_Src_Blend_Func(ShaderClass::SRCBLEND_ONE);
  633. shader.Set_Primary_Gradient(ShaderClass::GRADIENT_DISABLE);
  634. }
  635. }
  636. cload.Close_Chunk();
  637. }
  638. // If not texturing, move the diffuse color to ambient (simulating old behavior)
  639. if ( shader.Get_Texturing() == ShaderClass::TEXTURING_DISABLE ) {
  640. Vector3 color;
  641. vmat->Get_Diffuse( &color );
  642. vmat->Set_Ambient( color );
  643. vmat->Set_Diffuse( Vector3( 0, 0, 0 ) );
  644. }
  645. context->Add_Legacy_Material(shader,vmat,tex);
  646. vmat->Release_Ref();
  647. if (tex) tex->Release_Ref();
  648. vmat = NULL;
  649. tex = NULL;
  650. /*
  651. ** Close the W3D_CHUNK_MATERIAL3
  652. */
  653. cload.Close_Chunk();
  654. }
  655. /*
  656. ** Install the default materials to use in the absence of an array
  657. */
  658. if (context->Vertex_Material_Count() >= 1) {
  659. Set_Single_Material(context->Peek_Vertex_Material(0),0);
  660. }
  661. if (context->Texture_Count() >= 1) {
  662. Set_Single_Texture(context->Peek_Texture(0),0);
  663. }
  664. if (context->Shader_Count() >= 1) {
  665. Set_Single_Shader(context->Peek_Shader(0),0);
  666. }
  667. return WW3D_ERROR_OK;
  668. Error:
  669. return WW3D_ERROR_LOAD_FAILED;
  670. }
  671. /***********************************************************************************************
  672. * MeshModelClass::read_per_tri_materials -- read the material indices for each triangle *
  673. * *
  674. * INPUT: *
  675. * *
  676. * OUTPUT: *
  677. * *
  678. * WARNINGS: *
  679. * *
  680. * HISTORY: *
  681. * 4/7/98 GTH : Created. *
  682. *=============================================================================================*/
  683. WW3DErrorType MeshModelClass::read_per_tri_materials(ChunkLoadClass & cload,MeshLoadContextClass * context)
  684. {
  685. if (context->Header.NumMaterials == 1) return WW3D_ERROR_OK;
  686. Vector3i * polys = get_polys();
  687. bool multi_mtl = (context->Vertex_Material_Count() > 1);
  688. bool multi_tex = (context->Texture_Count() > 1);
  689. bool multi_shad = (context->Shader_Count() > 1);
  690. if (!multi_mtl) {
  691. Set_Single_Material(context->Peek_Legacy_Vertex_Material(0));
  692. }
  693. if (!multi_tex) {
  694. Set_Single_Texture(context->Peek_Legacy_Texture(0));
  695. }
  696. if (!multi_shad) {
  697. Set_Single_Shader(context->Peek_Legacy_Shader(0));
  698. }
  699. /*
  700. ** Read in each polygon's material id and assign pointer to the
  701. ** shader, texture, and vertex material as needed.
  702. */
  703. for (int i=0; i<Get_Polygon_Count(); i++) {
  704. // read in the mat id for this poly
  705. uint16 matid;
  706. if (cload.Read(&matid,sizeof(uint16)) != sizeof(uint16)) {
  707. return WW3D_ERROR_LOAD_FAILED;
  708. }
  709. if (multi_shad) {
  710. Set_Shader(i,context->Peek_Legacy_Shader(matid));
  711. }
  712. if (multi_tex) {
  713. Set_Texture(i,context->Peek_Legacy_Texture(matid));
  714. }
  715. if (multi_mtl) {
  716. Set_Material(polys[i].I,context->Peek_Legacy_Vertex_Material(matid));
  717. Set_Material(polys[i].J,context->Peek_Legacy_Vertex_Material(matid));
  718. Set_Material(polys[i].K,context->Peek_Legacy_Vertex_Material(matid));
  719. }
  720. }
  721. return WW3D_ERROR_OK;
  722. }
  723. /***********************************************************************************************
  724. * MeshModelClass::read_vertex_colors -- read in the vertex colors chunk *
  725. * *
  726. * INPUT: *
  727. * *
  728. * OUTPUT: *
  729. * *
  730. * WARNINGS: *
  731. * *
  732. * HISTORY: *
  733. * 10/28/1997 GH : Created. *
  734. * 2/16/99 GTH : Moved into MeshModelClass *
  735. *=============================================================================================*/
  736. WW3DErrorType MeshModelClass::read_vertex_colors(ChunkLoadClass & cload,MeshLoadContextClass * context)
  737. {
  738. /*
  739. ** The W3D file format supports arbitrary vertex color arrays for each pass; however since
  740. ** our conversion to hardware T&L, we only support two unique color arrays. So here is
  741. ** what is happening in this function:
  742. **
  743. ** 1 - If this is the first diffuse color array we've encountered, load the values
  744. ** 2 - Always set the DCG source for this pass to the array (vertex materials will be fixed later)
  745. **
  746. ** A side effect is that if two DCG chunks are encountered, only the first is used...
  747. */
  748. if (CurMatDesc->Has_Color_Array(0) == NULL) {
  749. W3dRGBStruct color;
  750. unsigned * dcg = Get_Color_Array(0,true);
  751. assert(dcg != NULL);
  752. for (int i=0; i<Get_Vertex_Count(); i++) {
  753. if (cload.Read(&color,sizeof(W3dRGBStruct)) != sizeof(W3dRGBStruct)) {
  754. return WW3D_ERROR_LOAD_FAILED;
  755. }
  756. Vector4 col;
  757. col.Set((float)color.R / 255.0f,(float)color.G / 255.0f,(float)color.B / 255.0f, 1.0f);
  758. dcg[i]=DX8Wrapper::Convert_Color(col);
  759. }
  760. }
  761. CurMatDesc->Set_DCG_Source(context->CurPass,VertexMaterialClass::COLOR1);
  762. return WW3D_ERROR_OK;
  763. }
  764. /***********************************************************************************************
  765. * MeshModelClass::read_material_info -- read the material info chunk *
  766. * *
  767. * INPUT: *
  768. * *
  769. * OUTPUT: *
  770. * *
  771. * WARNINGS: *
  772. * *
  773. * HISTORY: *
  774. * 2/16/99 GTH : Created. *
  775. *=============================================================================================*/
  776. WW3DErrorType MeshModelClass::read_material_info(ChunkLoadClass & cload,MeshLoadContextClass * context)
  777. {
  778. if (cload.Read(&(context->MatInfo),sizeof(W3dMaterialInfoStruct)) != sizeof(W3dMaterialInfoStruct)) {
  779. return WW3D_ERROR_LOAD_FAILED;
  780. }
  781. Set_Pass_Count(context->MatInfo.PassCount);
  782. return WW3D_ERROR_OK;
  783. }
  784. /***********************************************************************************************
  785. * MeshModelClass::read_shaders -- read the shaders chunk *
  786. * *
  787. * INPUT: *
  788. * *
  789. * OUTPUT: *
  790. * *
  791. * WARNINGS: *
  792. * *
  793. * HISTORY: *
  794. * 2/16/99 GTH : Created. *
  795. *=============================================================================================*/
  796. WW3DErrorType MeshModelClass::read_shaders(ChunkLoadClass & cload,MeshLoadContextClass * context)
  797. {
  798. W3dShaderStruct shader;
  799. for (unsigned int i=0; i<context->MatInfo.ShaderCount; i++) {
  800. if (cload.Read(&shader,sizeof(shader)) != sizeof(shader)) {
  801. return WW3D_ERROR_LOAD_FAILED;
  802. }
  803. ShaderClass newshader;
  804. W3dUtilityClass::Convert_Shader(shader,&newshader);
  805. int index = context->Add_Shader(newshader);
  806. WWASSERT(index == (int)i);
  807. }
  808. return WW3D_ERROR_OK;
  809. }
  810. /***********************************************************************************************
  811. * MeshModelClass::read_vertex_materials -- read the vertex materials chunk *
  812. * *
  813. * INPUT: *
  814. * *
  815. * OUTPUT: *
  816. * *
  817. * WARNINGS: *
  818. * *
  819. * HISTORY: *
  820. * 2/16/99 GTH : Created. *
  821. *=============================================================================================*/
  822. WW3DErrorType MeshModelClass::read_vertex_materials(ChunkLoadClass & cload,MeshLoadContextClass * context)
  823. {
  824. while (cload.Open_Chunk()) {
  825. WWASSERT(cload.Cur_Chunk_ID() == W3D_CHUNK_VERTEX_MATERIAL);
  826. VertexMaterialClass * vmat = NEW_REF(VertexMaterialClass,());
  827. WW3DErrorType error = vmat->Load_W3D(cload);
  828. if (error != WW3D_ERROR_OK) {
  829. return error;
  830. }
  831. context->Add_Vertex_Material(vmat);
  832. vmat->Release_Ref();
  833. cload.Close_Chunk();
  834. }
  835. return WW3D_ERROR_OK;
  836. }
  837. /***********************************************************************************************
  838. * MeshModelClass::read_textures -- read the textures chunk *
  839. * *
  840. * INPUT: *
  841. * *
  842. * OUTPUT: *
  843. * *
  844. * WARNINGS: *
  845. * *
  846. * HISTORY: *
  847. * 2/16/99 GTH : Created. *
  848. * 3/05/99 PDS : Broke the guts of this function into a util function in texture.cpp *
  849. *=============================================================================================*/
  850. WW3DErrorType MeshModelClass::read_textures(ChunkLoadClass & cload,MeshLoadContextClass * context)
  851. {
  852. // Keep reading textures until there are no more...
  853. for (TextureClass *newtex = ::Load_Texture (cload);
  854. newtex != NULL;
  855. newtex = ::Load_Texture (cload)) {
  856. // Add this texture to our contex and release our local hold on it
  857. context->Add_Texture(newtex);
  858. newtex->Release_Ref();
  859. }
  860. return WW3D_ERROR_OK;
  861. }
  862. /***********************************************************************************************
  863. * MeshModelClass::read_material_pass -- read a material pass chunk *
  864. * *
  865. * INPUT: *
  866. * *
  867. * OUTPUT: *
  868. * *
  869. * WARNINGS: *
  870. * *
  871. * HISTORY: *
  872. * 2/16/99 GTH : Created. *
  873. *=============================================================================================*/
  874. WW3DErrorType MeshModelClass::read_material_pass(ChunkLoadClass & cload,MeshLoadContextClass * context)
  875. {
  876. context->CurTexStage = 0;
  877. while (cload.Open_Chunk()) {
  878. WW3DErrorType error = WW3D_ERROR_OK;
  879. switch (cload.Cur_Chunk_ID()) {
  880. case W3D_CHUNK_VERTEX_MATERIAL_IDS:
  881. error = read_vertex_material_ids(cload,context);
  882. break;
  883. case W3D_CHUNK_SHADER_IDS:
  884. error = read_shader_ids(cload,context);
  885. break;
  886. case W3D_CHUNK_DCG:
  887. error = read_dcg(cload,context);
  888. break;
  889. case W3D_CHUNK_DIG:
  890. error = read_dig(cload,context);
  891. break;
  892. case W3D_CHUNK_SCG:
  893. error = read_scg(cload,context);
  894. break;
  895. case W3D_CHUNK_TEXTURE_STAGE:
  896. error = read_texture_stage(cload,context);
  897. break;
  898. };
  899. if (error != WW3D_ERROR_OK) {
  900. return error;
  901. }
  902. cload.Close_Chunk();
  903. }
  904. context->CurPass++;
  905. return WW3D_ERROR_OK;
  906. }
  907. /***********************************************************************************************
  908. * MeshModelClass::read_vertex_material_ids -- read the vmat ids for a pass *
  909. * *
  910. * INPUT: *
  911. * *
  912. * OUTPUT: *
  913. * *
  914. * WARNINGS: *
  915. * *
  916. * HISTORY: *
  917. * 2/16/99 GTH : Created. *
  918. * 9/1/2000 gth : Added alternate material desc support *
  919. *=============================================================================================*/
  920. WW3DErrorType MeshModelClass::read_vertex_material_ids(ChunkLoadClass & cload,MeshLoadContextClass * context)
  921. {
  922. /*
  923. ** Determine whether this chunk should be read into the default or alternate material description
  924. */
  925. MeshMatDescClass * matdesc = DefMatDesc;
  926. if (DefMatDesc->Has_Material_Data(context->CurPass)) {
  927. matdesc = &(context->AlternateMatDesc);
  928. }
  929. /*
  930. ** This chunk will either have a single index in it or an array of indices
  931. ** with the length equal to the vertex count.
  932. */
  933. uint32 vmat;
  934. #if (!MESH_SINGLE_MATERIAL_HACK)
  935. if (cload.Cur_Chunk_Length() == 1*sizeof(uint32)) {
  936. cload.Read(&vmat,sizeof(uint32));
  937. matdesc->Set_Single_Material(context->Peek_Vertex_Material(vmat),context->CurPass);
  938. } else {
  939. for (int i=0; i<Get_Vertex_Count(); i++) {
  940. cload.Read(&vmat,sizeof(uint32));
  941. matdesc->Set_Material(i,context->Peek_Vertex_Material(vmat),context->CurPass);
  942. }
  943. }
  944. #else
  945. #pragma message ("(gth) Hacking to make Generals behave as if all meshes have 1 material")
  946. cload.Read(&vmat,sizeof(uint32));
  947. matdesc->Set_Single_Material(context->Peek_Vertex_Material(vmat),context->CurPass);
  948. #endif //0
  949. return WW3D_ERROR_OK;
  950. }
  951. /***********************************************************************************************
  952. * MeshModelClass::read_shader_ids -- read the shader indexes for a pass *
  953. * *
  954. * INPUT: *
  955. * *
  956. * OUTPUT: *
  957. * *
  958. * WARNINGS: *
  959. * *
  960. * HISTORY: *
  961. * 2/16/99 GTH : Created. *
  962. * 9/1/2000 gth : Added alternate material desc support *
  963. *=============================================================================================*/
  964. WW3DErrorType MeshModelClass::read_shader_ids(ChunkLoadClass & cload,MeshLoadContextClass * context)
  965. {
  966. /*
  967. ** Determine whether this chunk should be read into the default or alternate material description
  968. */
  969. MeshMatDescClass * matdesc = DefMatDesc;
  970. if (DefMatDesc->Has_Shader_Data(context->CurPass)) {
  971. matdesc = &(context->AlternateMatDesc);
  972. }
  973. /*
  974. ** Read in the shader id's and plug in the appropriate shader
  975. */
  976. uint32 shaderid;
  977. #if (!MESH_SINGLE_MATERIAL_HACK)
  978. if (cload.Cur_Chunk_Length() == 1*sizeof(uint32)) {
  979. cload.Read(&shaderid,sizeof(shaderid));
  980. ShaderClass shader = context->Peek_Shader(shaderid);
  981. matdesc->Set_Single_Shader(shader,context->CurPass);
  982. // turn on sorting of pass 0 has non-zero dest blend (unless alpha testing on)
  983. if ( (context->CurPass == 0) &&
  984. (shader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO) &&
  985. (shader.Get_Alpha_Test() == ShaderClass::ALPHATEST_DISABLE) &&
  986. (SortLevel == SORT_LEVEL_NONE) )
  987. {
  988. #if (MESH_FORCE_STATIC_SORT_HACK)
  989. SortLevel = 1;
  990. #else
  991. Set_Flag(SORT,true);
  992. #endif
  993. }
  994. } else {
  995. for (int i=0; i<Get_Polygon_Count(); i++) {
  996. cload.Read(&shaderid,sizeof(uint32));
  997. ShaderClass shader = context->Peek_Shader(shaderid);
  998. matdesc->Set_Shader(i,shader,context->CurPass);
  999. // turn on sorting of pass 0 has non-zero dest blend (unless alpha testing on)
  1000. if ( (context->CurPass == 0) &&
  1001. (shader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO) &&
  1002. (shader.Get_Alpha_Test() == ShaderClass::ALPHATEST_DISABLE) &&
  1003. (SortLevel == SORT_LEVEL_NONE) )
  1004. {
  1005. #if (MESH_FORCE_STATIC_SORT_HACK)
  1006. SortLevel = 1;
  1007. #else
  1008. Set_Flag(SORT,true);
  1009. #endif
  1010. }
  1011. }
  1012. }
  1013. #else
  1014. #pragma message ("(gth) Hacking to make Generals behave as if all meshes have 1 material")
  1015. cload.Read(&shaderid,sizeof(shaderid));
  1016. ShaderClass shader = context->Peek_Shader(shaderid);
  1017. matdesc->Set_Single_Shader(shader,context->CurPass);
  1018. // turn on sorting of pass 0 has non-zero dest blend (unless alpha testing on)
  1019. if ( (context->CurPass == 0) &&
  1020. (shader.Get_Dst_Blend_Func() != ShaderClass::DSTBLEND_ZERO) &&
  1021. (shader.Get_Alpha_Test() == ShaderClass::ALPHATEST_DISABLE) &&
  1022. (SortLevel == SORT_LEVEL_NONE) )
  1023. {
  1024. #if (MESH_FORCE_STATIC_SORT_HACK)
  1025. SortLevel = 1;
  1026. #else
  1027. Set_Flag(SORT,true);
  1028. #endif
  1029. }
  1030. #endif //0
  1031. return WW3D_ERROR_OK;
  1032. }
  1033. /***********************************************************************************************
  1034. * MeshModelClass::read_dcg -- read the per-vertex diffuse color for a pass *
  1035. * *
  1036. * INPUT: *
  1037. * *
  1038. * OUTPUT: *
  1039. * *
  1040. * WARNINGS: *
  1041. * *
  1042. * HISTORY: *
  1043. * 2/16/99 GTH : Created. *
  1044. * 9/1/2000 gth : Added alternate material desc support *
  1045. * 2/9/2001 gth : converted to handle dx8 limitations *
  1046. *=============================================================================================*/
  1047. WW3DErrorType MeshModelClass::read_dcg(ChunkLoadClass & cload,MeshLoadContextClass * context)
  1048. {
  1049. /*
  1050. ** Determine whether this chunk should be read into the default or alternate material description
  1051. */
  1052. MeshMatDescClass * matdesc = DefMatDesc;
  1053. if (DefMatDesc->Get_DCG_Source(context->CurPass) != VertexMaterialClass::MATERIAL) {
  1054. matdesc = &(context->AlternateMatDesc);
  1055. }
  1056. /*
  1057. ** The W3D file format supports arbitrary vertex color arrays for each pass; however since
  1058. ** our conversion to hardware T&L, we only support two unique color arrays. So here is
  1059. ** what is happening in this function:
  1060. **
  1061. ** 1 - If this is the first diffuse color array we've encountered, load the values.
  1062. ** 2 - Otherwise, if we are in PRELIT_VERTEX mode, put the alpha from this array into the color array.
  1063. ** 3 - Always set the DCG source for this pass to the array.
  1064. **
  1065. ** Our tools *currently* will only generate two color arrays in the case where one of them
  1066. ** is being used for alpha and the other is used for precomputed vertex lighting... This will
  1067. ** break if our tools change. The file format isn't restricting you from defining something
  1068. ** we can't render right now...
  1069. */
  1070. if (matdesc->Has_Color_Array(0) == false) {
  1071. W3dRGBAStruct color;
  1072. unsigned * dcg = matdesc->Get_Color_Array(0);
  1073. for (int i=0; i<Get_Vertex_Count(); i++) {
  1074. cload.Read(&color,sizeof(color));
  1075. Vector4 col;
  1076. W3dUtilityClass::Convert_Color(color,&col);
  1077. dcg[i]=DX8Wrapper::Convert_Color(col);
  1078. }
  1079. } else if (context->PrelitChunkID==W3D_CHUNK_PRELIT_VERTEX) {
  1080. W3dRGBAStruct color;
  1081. unsigned * dcg = matdesc->Get_Color_Array(0);
  1082. for (int i=0; i<Get_Vertex_Count(); i++) {
  1083. cload.Read(&color,sizeof(color));
  1084. Vector4 col;
  1085. col=DX8Wrapper::Convert_Color(dcg[i]);
  1086. col.W = float(color.A)/255.0f;
  1087. dcg[i]=DX8Wrapper::Convert_Color(col);
  1088. }
  1089. }
  1090. matdesc->Set_DCG_Source(context->CurPass,VertexMaterialClass::COLOR1);
  1091. return WW3D_ERROR_OK;
  1092. }
  1093. /***********************************************************************************************
  1094. * MeshModelClass::read_dig -- read the per-vertex diffuse illumination for a pass *
  1095. * *
  1096. * INPUT: *
  1097. * *
  1098. * OUTPUT: *
  1099. * *
  1100. * WARNINGS: *
  1101. * *
  1102. * HISTORY: *
  1103. * 2/16/99 GTH : Created. *
  1104. * 9/1/2000 gth : Added alternate material desc support *
  1105. * 2/9/2001 gth : converted to handle dx8 limitations *
  1106. *=============================================================================================*/
  1107. WW3DErrorType MeshModelClass::read_dig(ChunkLoadClass & cload,MeshLoadContextClass * context)
  1108. {
  1109. /*
  1110. ** Determine whether this chunk should be read into the default or alternate material description
  1111. */
  1112. MeshMatDescClass * matdesc = DefMatDesc;
  1113. if (context->Already_Loaded_DIG()) {
  1114. matdesc = &(context->AlternateMatDesc);
  1115. }
  1116. context->Notify_Loaded_DIG_Chunk(true);
  1117. /*
  1118. ** It appears that there isn't wide support for having the emissive material color source
  1119. ** be a vertex color array so when there is a pre-existing color array, I'm just multiplying
  1120. ** the DIG values into it.
  1121. */
  1122. W3dRGBAStruct color;
  1123. if (matdesc->Has_Color_Array(0) == false) {
  1124. unsigned * dcg = matdesc->Get_Color_Array(0);
  1125. for (int i=0; i<Get_Vertex_Count(); i++) {
  1126. cload.Read(&color,sizeof(color));
  1127. Vector4 col;
  1128. col.X = float(color.R)/255.0f;
  1129. col.Y = float(color.G)/255.0f;
  1130. col.Z = float(color.B)/255.0f;
  1131. col.W = 1.0f;
  1132. dcg[i]=DX8Wrapper::Convert_Color(col);
  1133. }
  1134. } else {
  1135. unsigned * dcg = matdesc->Get_Color_Array(0);
  1136. for (int i=0; i<Get_Vertex_Count(); i++) {
  1137. cload.Read(&color,sizeof(color));
  1138. Vector4 col=DX8Wrapper::Convert_Color(dcg[i]);
  1139. col.X *= float(color.R)/255.0f;
  1140. col.Y *= float(color.G)/255.0f;
  1141. col.Z *= float(color.B)/255.0f;
  1142. dcg[i]=DX8Wrapper::Convert_Color(col);
  1143. }
  1144. }
  1145. matdesc->Set_DCG_Source(context->CurPass,VertexMaterialClass::COLOR1);
  1146. return WW3D_ERROR_OK;
  1147. }
  1148. /***********************************************************************************************
  1149. * MeshModelClass::read_scg -- read the specular color for a pass *
  1150. * *
  1151. * INPUT: *
  1152. * *
  1153. * OUTPUT: *
  1154. * *
  1155. * WARNINGS: *
  1156. * *
  1157. * HISTORY: *
  1158. * 2/16/99 GTH : Created. *
  1159. * 9/1/2000 gth : Added alternate material desc support *
  1160. * 2/9/2001 gth : new dx8 code no longer supports this chunk *
  1161. *=============================================================================================*/
  1162. WW3DErrorType MeshModelClass::read_scg(ChunkLoadClass & cload,MeshLoadContextClass * context)
  1163. {
  1164. return WW3D_ERROR_OK;
  1165. }
  1166. /***********************************************************************************************
  1167. * MeshModelClass::read_texture_stage -- read texture stage chunks *
  1168. * *
  1169. * INPUT: *
  1170. * *
  1171. * OUTPUT: *
  1172. * *
  1173. * WARNINGS: *
  1174. * *
  1175. * HISTORY: *
  1176. * 2/16/99 GTH : Created. *
  1177. *=============================================================================================*/
  1178. WW3DErrorType MeshModelClass::read_texture_stage(ChunkLoadClass & cload,MeshLoadContextClass * context)
  1179. {
  1180. while (cload.Open_Chunk()) {
  1181. WW3DErrorType error = WW3D_ERROR_OK;
  1182. switch(cload.Cur_Chunk_ID()) {
  1183. case W3D_CHUNK_TEXTURE_IDS:
  1184. error = read_texture_ids(cload,context);
  1185. break;
  1186. case W3D_CHUNK_STAGE_TEXCOORDS:
  1187. case W3D_CHUNK_TEXCOORDS:
  1188. error = read_stage_texcoords(cload,context);
  1189. break;
  1190. case W3D_CHUNK_PER_FACE_TEXCOORD_IDS:
  1191. error = read_per_face_texcoord_ids (cload, context);
  1192. break;
  1193. }
  1194. if (error != WW3D_ERROR_OK) {
  1195. return error;
  1196. }
  1197. cload.Close_Chunk();
  1198. }
  1199. context->CurTexStage++;
  1200. return WW3D_ERROR_OK;
  1201. }
  1202. /***********************************************************************************************
  1203. * MeshModelClass::read_texture_ids -- read the texture ids for a pass,stage *
  1204. * *
  1205. * INPUT: *
  1206. * *
  1207. * OUTPUT: *
  1208. * *
  1209. * WARNINGS: *
  1210. * *
  1211. * HISTORY: *
  1212. * 2/16/99 GTH : Created. *
  1213. * 9/1/2000 gth : Added alternate material desc support *
  1214. *=============================================================================================*/
  1215. WW3DErrorType MeshModelClass::read_texture_ids(ChunkLoadClass & cload,MeshLoadContextClass * context)
  1216. {
  1217. uint32 texid;
  1218. int pass = context->CurPass;
  1219. int stage = context->CurTexStage;
  1220. /*
  1221. ** Determine whether this chunk should be read into the default or alternate material description
  1222. */
  1223. MeshMatDescClass * matdesc = DefMatDesc;
  1224. if (DefMatDesc->Has_Texture_Data(pass,stage)) {
  1225. matdesc = &(context->AlternateMatDesc);
  1226. }
  1227. /*
  1228. ** Read in the texture(s) array
  1229. */
  1230. #if (!MESH_SINGLE_MATERIAL_HACK)
  1231. if (cload.Cur_Chunk_Length() == 1*sizeof(uint32)) {
  1232. cload.Read(&texid,sizeof(texid));
  1233. matdesc->Set_Single_Texture(context->Peek_Texture(texid),pass,stage);
  1234. } else {
  1235. for (int i=0; i<Get_Polygon_Count(); i++) {
  1236. cload.Read(&texid,sizeof(uint32));
  1237. if (texid != 0xffffffff) {
  1238. matdesc->Set_Texture(i,context->Peek_Texture(texid),pass,stage);
  1239. }
  1240. }
  1241. }
  1242. #else
  1243. #pragma message ("(gth) Hacking to make Generals behave as if all meshes have 1 material")
  1244. cload.Read(&texid,sizeof(texid));
  1245. matdesc->Set_Single_Texture(context->Peek_Texture(texid),pass,stage);
  1246. #endif
  1247. return WW3D_ERROR_OK;
  1248. }
  1249. /***********************************************************************************************
  1250. * MeshModelClass::read_stage_texcoords -- read the texcoords for a pass,stage *
  1251. * *
  1252. * INPUT: *
  1253. * *
  1254. * OUTPUT: *
  1255. * *
  1256. * WARNINGS: *
  1257. * *
  1258. * HISTORY: *
  1259. * 2/16/99 GTH : Created. *
  1260. * 7/14/99 IML : Lightmap support: calculate vertex count directly from chunk size. *
  1261. * 9/1/2000 gth : Added alternate material desc support *
  1262. *=============================================================================================*/
  1263. WW3DErrorType MeshModelClass::read_stage_texcoords(ChunkLoadClass & cload,MeshLoadContextClass * context)
  1264. {
  1265. unsigned elementcount;
  1266. Vector2 *uvs;
  1267. W3dTexCoordStruct texcoord;
  1268. /*
  1269. ** Determine whether this chunk should be read into the default or alternate material description
  1270. */
  1271. MeshMatDescClass * matdesc = DefMatDesc;
  1272. if (DefMatDesc->Has_UV(context->CurPass,context->CurTexStage)) {
  1273. matdesc = &(context->AlternateMatDesc);
  1274. }
  1275. /*
  1276. ** Read in the texture coordiantes
  1277. */
  1278. elementcount = cload.Cur_Chunk_Length() / sizeof (W3dTexCoordStruct);
  1279. uvs = context->Get_Temporary_UV_Array(elementcount);
  1280. if (uvs != NULL) {
  1281. for (unsigned i = 0; i < elementcount; i++) {
  1282. cload.Read (&texcoord, sizeof (texcoord));
  1283. uvs[i].X = texcoord.U;
  1284. uvs[i].Y = 1.0f - texcoord.V;
  1285. }
  1286. }
  1287. matdesc->Install_UV_Array(context->CurPass,context->CurTexStage,uvs,elementcount);
  1288. return (WW3D_ERROR_OK);
  1289. }
  1290. /***********************************************************************************************
  1291. * MeshModelClass::read_per_face_texcoord_ids -- read uv indices for given (pass,stage). *
  1292. * *
  1293. * INPUT: *
  1294. * *
  1295. * OUTPUT: *
  1296. * *
  1297. * WARNINGS: *
  1298. * *
  1299. * HISTORY: *
  1300. * 02/02/99 IML : Created. *
  1301. * 9/1/2000 gth : Added alternate material desc support *
  1302. *=============================================================================================*/
  1303. WW3DErrorType MeshModelClass::read_per_face_texcoord_ids (ChunkLoadClass &cload, MeshLoadContextClass *context)
  1304. {
  1305. unsigned size;
  1306. /*
  1307. ** Determine whether this chunk should be read into the default or alternate material description
  1308. */
  1309. // MeshMatDescClass * matdesc = DefMatDesc;
  1310. // if (DefMatDesc->Has_UVIndex(context->CurPass)) {
  1311. // matdesc = &(context->AlternateMatDesc);
  1312. // }
  1313. /*
  1314. ** Read in the texture coordiante indices
  1315. ** There must be polygon count vectors in this chunk.
  1316. */
  1317. size = sizeof (Vector3i) * Get_Polygon_Count();
  1318. if (cload.Cur_Chunk_Length() == size) {
  1319. // Vector3i *uvindices;
  1320. //
  1321. // uvindices = matdesc->Get_UVIndex_Array (context->CurPass, true);
  1322. // WWASSERT (uvindices != NULL);
  1323. //uvindices=W3DNEWARRAY Vector3i[Get_Polygon_Count()];
  1324. // cload.Read (uvindices, size);
  1325. //delete[] uvindices;
  1326. cload.Seek(size);
  1327. return (WW3D_ERROR_OK);
  1328. } else {
  1329. return (WW3D_ERROR_LOAD_FAILED);
  1330. }
  1331. }
  1332. /***********************************************************************************************
  1333. * MeshModelClass::read_prelit_material -- read prelit material chunks. *
  1334. * *
  1335. * INPUT: *
  1336. * *
  1337. * OUTPUT: *
  1338. * *
  1339. * WARNINGS: *
  1340. * *
  1341. * HISTORY: *
  1342. * 02/02/99 IML : Created. *
  1343. *=============================================================================================*/
  1344. WW3DErrorType MeshModelClass::read_prelit_material (ChunkLoadClass &cload, MeshLoadContextClass *context)
  1345. {
  1346. // If this chunk ID matches the selected prelit chunk ID then load it, otherwise skip it.
  1347. if (cload.Cur_Chunk_ID() == context->PrelitChunkID) {
  1348. // While there are chunks in the prelit material chunk wrapper...
  1349. while (cload.Open_Chunk()) {
  1350. WW3DErrorType error = WW3D_ERROR_OK;
  1351. switch (cload.Cur_Chunk_ID()) {
  1352. case W3D_CHUNK_MATERIAL_INFO:
  1353. error = read_material_info (cload,context);
  1354. break;
  1355. case W3D_CHUNK_VERTEX_MATERIALS:
  1356. error = read_vertex_materials (cload,context);
  1357. break;
  1358. case W3D_CHUNK_SHADERS:
  1359. error = read_shaders (cload,context);
  1360. break;
  1361. case W3D_CHUNK_TEXTURES:
  1362. error = read_textures (cload,context);
  1363. break;
  1364. case W3D_CHUNK_MATERIAL_PASS:
  1365. error = read_material_pass (cload,context);
  1366. break;
  1367. default:
  1368. // Unknown chunk.
  1369. break;
  1370. }
  1371. cload.Close_Chunk();
  1372. if (error != WW3D_ERROR_OK) return (error);
  1373. }
  1374. }
  1375. return (WW3D_ERROR_OK);
  1376. }
  1377. /***********************************************************************************************
  1378. * MeshModelClass::post_process -- post loading, perform any processing on this model. *
  1379. * *
  1380. * INPUT: *
  1381. * *
  1382. * OUTPUT: *
  1383. * *
  1384. * WARNINGS: *
  1385. * *
  1386. * HISTORY: *
  1387. * 05/02/00 IML : Created. *
  1388. * 7/13/2001 hy : Added static sort postprocessing *
  1389. *=============================================================================================*/
  1390. void MeshModelClass::post_process()
  1391. {
  1392. #if 0
  1393. // we want to allow this now due to usage of the static sort
  1394. // Ensure no sorting, multipass meshes (for they are abomination...)
  1395. if (DefMatDesc->Get_Pass_Count() > 1 && Get_Flag(SORT)) {
  1396. WWDEBUG_SAY(( "Turning SORT off for multipass mesh %s\n",Get_Name() ));
  1397. Set_Flag(SORT, false);
  1398. }
  1399. #endif
  1400. // turn off backface culling if the mesh is supposed to be two-sided
  1401. if (Get_Flag(MeshGeometryClass::TWO_SIDED)) {
  1402. DefMatDesc->Disable_Backface_Culling();
  1403. if (AlternateMatDesc != NULL) {
  1404. AlternateMatDesc->Disable_Backface_Culling();
  1405. }
  1406. }
  1407. // fog activation.
  1408. if (WW3DAssetManager::Get_Instance()->Get_Activate_Fog_On_Load()) {
  1409. post_process_fog();
  1410. }
  1411. // if the mesh is sorting, pick an appropriate static sort level
  1412. // if default isn't set
  1413. if (Get_Flag(SORT) && SortLevel==SORT_LEVEL_NONE && WW3D::Is_Munge_Sort_On_Load_Enabled()) {
  1414. compute_static_sort_levels();
  1415. }
  1416. }
  1417. void MeshModelClass::post_process_fog(void)
  1418. {
  1419. // If two pass...
  1420. if (DefMatDesc->Get_Pass_Count() == 2) {
  1421. // If single shader on both passes...
  1422. if (!DefMatDesc->ShaderArray[0] && !DefMatDesc->ShaderArray[1]) {
  1423. ShaderClass &shader0 = DefMatDesc->Shader [0];
  1424. ShaderClass &shader1 = DefMatDesc->Shader [1];
  1425. // Analyze the mesh to determine if it is the emissive map effect and if it is, fix it up appropriately.
  1426. bool emissive_map_effect = DefMatDesc->PassCount == 2 &&
  1427. shader0.Get_Texturing() == ShaderClass::TEXTURING_DISABLE &&
  1428. shader0.Get_Src_Blend_Func() == ShaderClass::SRCBLEND_ONE &&
  1429. shader0.Get_Dst_Blend_Func() == ShaderClass::DSTBLEND_ZERO &&
  1430. shader0.Get_Primary_Gradient() == ShaderClass::GRADIENT_MODULATE &&
  1431. shader0.Get_Secondary_Gradient() == ShaderClass::SECONDARY_GRADIENT_DISABLE &&
  1432. shader1.Get_Texturing() == ShaderClass::TEXTURING_ENABLE &&
  1433. shader1.Get_Src_Blend_Func() == ShaderClass::SRCBLEND_SRC_ALPHA &&
  1434. shader1.Get_Dst_Blend_Func() == ShaderClass::DSTBLEND_SRC_COLOR;
  1435. if (emissive_map_effect) {
  1436. // Change the shader/texture setting into an equivalent one which will enable setting fog
  1437. // correctly: Note that we are setting up pass 0 to have a texture now.
  1438. shader0.Set_Texturing(ShaderClass::TEXTURING_ENABLE);
  1439. shader1.Set_Dst_Blend_Func(ShaderClass::DSTBLEND_ONE);
  1440. shader0.Set_Fog_Func(ShaderClass::FOG_ENABLE);
  1441. shader1.Set_Fog_Func(ShaderClass::FOG_SCALE_FRAGMENT);
  1442. // Copy pass 1 texture/texture array to pass 0.
  1443. REF_PTR_SET (DefMatDesc->Texture[0][0], DefMatDesc->Texture [1][0]);
  1444. if (DefMatDesc->TextureArray [1][0]) {
  1445. if (!DefMatDesc->TextureArray [0][0]) {
  1446. DefMatDesc->TextureArray [0][0] = NEW_REF (TexBufferClass, (PolyCount, "MeshModelClass::DefMatDesc::TextureArray"));
  1447. for (int i = 0; i < PolyCount; i++) {
  1448. DefMatDesc->TextureArray [0][0]->Set_Element (i, DefMatDesc->TextureArray [1][0]->Peek_Element (i));
  1449. }
  1450. }
  1451. }
  1452. // Make pass 0 point to the same UV array as pass 1. If pass 1 has a vertex material
  1453. // array, we only take the first one for determining UV source. The UV source is
  1454. // used to set the UV source of all the vertex materials in pass 0.
  1455. int uv_source = 0;
  1456. if (DefMatDesc->MaterialArray[1]) {
  1457. uv_source = DefMatDesc->MaterialArray[1]->Peek_Element(0)->Get_UV_Source(0);
  1458. } else {
  1459. DefMatDesc->Material[1]->Get_UV_Source(0);
  1460. }
  1461. if (DefMatDesc->MaterialArray[0]) {
  1462. for (int i = 0; i < VertexCount; i++) {
  1463. DefMatDesc->MaterialArray[0]->Peek_Element(i)->Set_UV_Source(0, uv_source);
  1464. }
  1465. } else {
  1466. DefMatDesc->Material[0]->Set_UV_Source(0, uv_source);
  1467. }
  1468. return;
  1469. }
  1470. // Analyze the mesh to determine if it is the shiny mask effect and if it is, fix it up appropriately.
  1471. bool shiny_mask_effect = shader0.Get_Src_Blend_Func() == ShaderClass::SRCBLEND_ONE &&
  1472. shader0.Get_Dst_Blend_Func() == ShaderClass::DSTBLEND_ZERO &&
  1473. shader1.Get_Src_Blend_Func() == ShaderClass::SRCBLEND_ONE &&
  1474. (shader1.Get_Dst_Blend_Func() == ShaderClass::DSTBLEND_SRC_ALPHA ||
  1475. shader1.Get_Dst_Blend_Func() == ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA);
  1476. if (shiny_mask_effect) {
  1477. shader0.Set_Fog_Func(ShaderClass::FOG_SCALE_FRAGMENT);
  1478. shader1.Set_Fog_Func(ShaderClass::FOG_ENABLE);
  1479. return;
  1480. }
  1481. }
  1482. }
  1483. // Mesh is not one of the special two-pass combinations. Apply a per-pass generic fix-up.
  1484. for (int pass = 0; pass < DefMatDesc->PassCount; pass++) {
  1485. DefMatDesc->Shader [pass].Enable_Fog (Get_Name());
  1486. if (DefMatDesc->ShaderArray [pass]) {
  1487. for (int tri = 0; tri < DefMatDesc->ShaderArray [pass]->Get_Count(); tri++) {
  1488. DefMatDesc->ShaderArray [pass]->Get_Element (tri).Enable_Fog (Get_Name());
  1489. }
  1490. }
  1491. }
  1492. }
  1493. unsigned int MeshModelClass::get_sort_flags(int pass) const
  1494. {
  1495. unsigned int flags = 0;
  1496. ShaderClass::StaticSortCategoryType scat;
  1497. if (Has_Shader_Array(pass)) {
  1498. for (int tri = 0; tri < CurMatDesc->ShaderArray[pass]->Get_Count(); tri++) {
  1499. scat = CurMatDesc->ShaderArray[pass]->Get_Element(tri).Get_SS_Category();
  1500. flags |= (1 << scat);
  1501. }
  1502. } else {
  1503. scat = Get_Single_Shader(pass).Get_SS_Category();
  1504. flags |= (1 << scat);
  1505. }
  1506. return false;
  1507. }
  1508. unsigned int MeshModelClass::get_sort_flags(void) const
  1509. {
  1510. unsigned int flags = 0;
  1511. for (int pass = 0; pass < Get_Pass_Count(); pass++) {
  1512. flags |= get_sort_flags(pass);
  1513. }
  1514. return flags;
  1515. }
  1516. void MeshModelClass::compute_static_sort_levels(void)
  1517. {
  1518. enum StaticSortCategoryBitFieldType
  1519. {
  1520. SSCAT_OPAQUE_BF = (1 << ShaderClass::SSCAT_OPAQUE),
  1521. SSCAT_ALPHA_TEST_BF = (1 << ShaderClass::SSCAT_ALPHA_TEST),
  1522. SSCAT_ADDITIVE_BF = (1 << ShaderClass::SSCAT_ADDITIVE),
  1523. SSCAT_OTHER_BF = (1 << ShaderClass::SSCAT_OTHER)
  1524. };
  1525. if (get_sort_flags(0) == SSCAT_OPAQUE_BF) {
  1526. SortLevel = SORT_LEVEL_NONE;
  1527. return;
  1528. }
  1529. switch (get_sort_flags())
  1530. {
  1531. case (SSCAT_OPAQUE_BF | SSCAT_ALPHA_TEST_BF):
  1532. SortLevel = SORT_LEVEL_NONE;
  1533. break;
  1534. case SSCAT_ADDITIVE_BF:
  1535. SortLevel = SORT_LEVEL_BIN3;
  1536. break;
  1537. case (SSCAT_ADDITIVE_BF | SSCAT_ALPHA_TEST_BF):
  1538. SortLevel = SORT_LEVEL_BIN2;
  1539. break;
  1540. default:
  1541. SortLevel = SORT_LEVEL_BIN1;
  1542. break;
  1543. };
  1544. }
  1545. void MeshModelClass::install_materials(MeshLoadContextClass * context)
  1546. {
  1547. int i;
  1548. /*
  1549. ** If alternate material chunks were loaded, initialize the AlternateMatDesc
  1550. */
  1551. install_alternate_material_desc(context);
  1552. /*
  1553. ** Finish configuring the vertex materials and color arrays.
  1554. */
  1555. DefMatDesc->Post_Load_Process (true);
  1556. if (AlternateMatDesc != NULL) {
  1557. AlternateMatDesc->Post_Load_Process (true);
  1558. }
  1559. /*
  1560. ** transfer the refs to our textures into the MatInfo
  1561. */
  1562. for (i=0; i<context->Texture_Count(); i++) {
  1563. MatInfo->Add_Texture(context->Peek_Texture(i));
  1564. }
  1565. /*
  1566. ** transfer the refs to our vertex materials into the MatInfo
  1567. */
  1568. for (i=0; i<context->Vertex_Material_Count(); i++) {
  1569. MatInfo->Add_Vertex_Material(context->Peek_Vertex_Material(i));
  1570. }
  1571. }
  1572. void MeshModelClass::clone_materials(const MeshModelClass & srcmesh)
  1573. {
  1574. /*
  1575. ** Copy the material info and the materials within
  1576. */
  1577. REF_PTR_RELEASE(MatInfo);
  1578. MatInfo = NEW_REF( MaterialInfoClass,(*(srcmesh.MatInfo)));
  1579. /*
  1580. ** remap!
  1581. */
  1582. MaterialRemapperClass remapper(srcmesh.MatInfo, MatInfo);
  1583. remapper.Remap_Mesh(srcmesh.CurMatDesc, CurMatDesc);
  1584. }
  1585. void MeshModelClass::install_alternate_material_desc(MeshLoadContextClass * context)
  1586. {
  1587. if (context->AlternateMatDesc.Is_Empty() == false) {
  1588. WWASSERT(AlternateMatDesc == NULL);
  1589. AlternateMatDesc = W3DNEW MeshMatDescClass;
  1590. AlternateMatDesc->Init_Alternate(*DefMatDesc,context->AlternateMatDesc);
  1591. }
  1592. }
  1593. /***********************************************************************************************
  1594. * MeshLoadContextClass::MeshLoadContextClass -- constructor for MeshLoadContextClass *
  1595. * *
  1596. * INPUT: *
  1597. * *
  1598. * OUTPUT: *
  1599. * *
  1600. * WARNINGS: *
  1601. * *
  1602. * HISTORY: *
  1603. * 12/10/98 GTH : Created. *
  1604. *=============================================================================================*/
  1605. MeshLoadContextClass::MeshLoadContextClass(void)
  1606. {
  1607. memset(&Header,0,sizeof(Header));
  1608. memset(&MatInfo,0,sizeof(MatInfo));
  1609. PrelitChunkID = 0xffffffff;
  1610. CurPass = 0;
  1611. CurTexStage = 0;
  1612. TexCoords = NULL;
  1613. LoadedDIG = false;
  1614. }
  1615. /***********************************************************************************************
  1616. * MeshLoadContextClass::~MeshLoadContextClass -- destructor *
  1617. * *
  1618. * INPUT: *
  1619. * *
  1620. * OUTPUT: *
  1621. * *
  1622. * WARNINGS: *
  1623. * *
  1624. * HISTORY: *
  1625. * 12/10/98 GTH : Created. *
  1626. *=============================================================================================*/
  1627. MeshLoadContextClass::~MeshLoadContextClass(void)
  1628. {
  1629. int i;
  1630. if (TexCoords != NULL) {
  1631. delete TexCoords;
  1632. TexCoords = NULL;
  1633. }
  1634. for (i=0; i<Textures.Count(); i++) {
  1635. Textures[i]->Release_Ref();
  1636. }
  1637. for (i=0; i<VertexMaterials.Count(); i++) {
  1638. VertexMaterials[i]->Release_Ref();
  1639. }
  1640. for (i=0; i<LegacyMaterials.Count(); i++) {
  1641. delete LegacyMaterials[i];
  1642. }
  1643. }
  1644. /***********************************************************************************************
  1645. * MeshLoadContextClass::Get_Texcoord_Array -- returns the texture coordinates array *
  1646. * *
  1647. * This function mainly exists to support the obsolete version 3.0 w3d files *
  1648. * *
  1649. * INPUT: *
  1650. * *
  1651. * OUTPUT: *
  1652. * *
  1653. * WARNINGS: *
  1654. * *
  1655. * HISTORY: *
  1656. * 12/10/98 GTH : Created. *
  1657. *=============================================================================================*/
  1658. W3dTexCoordStruct * MeshLoadContextClass::Get_Texcoord_Array(void)
  1659. {
  1660. if (TexCoords == NULL) {
  1661. TexCoords = W3DNEWARRAY W3dTexCoordStruct[Header.NumVertices];
  1662. }
  1663. return TexCoords;
  1664. }
  1665. /***********************************************************************************************
  1666. * MeshLoadContextClass::Add_Shader -- adds a shader to the array *
  1667. * *
  1668. * INPUT: *
  1669. * *
  1670. * OUTPUT: *
  1671. * *
  1672. * WARNINGS: *
  1673. * *
  1674. * HISTORY: *
  1675. * 12/10/98 GTH : Created. *
  1676. *=============================================================================================*/
  1677. int MeshLoadContextClass::Add_Shader(ShaderClass shader)
  1678. {
  1679. int index = Shaders.Count();
  1680. Shaders.Add(shader);
  1681. return index;
  1682. }
  1683. /***********************************************************************************************
  1684. * MeshLoadContextClass::Add_Vertex_Materail -- adds a vertex material *
  1685. * *
  1686. * INPUT: *
  1687. * *
  1688. * OUTPUT: *
  1689. * *
  1690. * WARNINGS: *
  1691. * *
  1692. * HISTORY: *
  1693. * 12/10/98 GTH : Created. *
  1694. *=============================================================================================*/
  1695. int MeshLoadContextClass::Add_Vertex_Material(VertexMaterialClass * vmat)
  1696. {
  1697. WWASSERT(vmat != NULL);
  1698. vmat->Add_Ref();
  1699. int index = VertexMaterials.Count();
  1700. VertexMaterials.Add(vmat);
  1701. return index;
  1702. }
  1703. /***********************************************************************************************
  1704. * MeshLoadContextClass::Add_Texture -- adds a texture *
  1705. * *
  1706. * INPUT: *
  1707. * *
  1708. * OUTPUT: *
  1709. * *
  1710. * WARNINGS: *
  1711. * *
  1712. * HISTORY: *
  1713. * 12/10/98 GTH : Created. *
  1714. *=============================================================================================*/
  1715. int MeshLoadContextClass::Add_Texture(TextureClass * tex)
  1716. {
  1717. WWASSERT(tex != NULL);
  1718. tex->Add_Ref();
  1719. int index = Textures.Count();
  1720. Textures.Add(tex);
  1721. return index;
  1722. }
  1723. /***********************************************************************************************
  1724. * MeshLoadContextClass::Add_Legacy_Material -- adds a legacy material *
  1725. * *
  1726. * This function will check to see if the parameters of any of the parts of the material are *
  1727. * duplicated. Only unique shaders/vertexmaterials will be actually added. *
  1728. * *
  1729. * INPUT: *
  1730. * *
  1731. * OUTPUT: *
  1732. * *
  1733. * WARNINGS: *
  1734. * *
  1735. * HISTORY: *
  1736. * 12/10/98 GTH : Created. *
  1737. *=============================================================================================*/
  1738. void MeshLoadContextClass::Add_Legacy_Material(ShaderClass shader,VertexMaterialClass * vmat,TextureClass * tex)
  1739. {
  1740. // create a new legacy material
  1741. LegacyMaterialClass * mat = W3DNEW LegacyMaterialClass;
  1742. // add the shader if it is unique
  1743. for (int si=0; si<Shaders.Count(); si++) {
  1744. if (Shaders[si] == shader) break;
  1745. }
  1746. if (si == Shaders.Count()) {
  1747. mat->ShaderIdx = Add_Shader(shader);
  1748. } else {
  1749. mat->ShaderIdx = si;
  1750. }
  1751. // add the vertex material if it is unique
  1752. if (vmat == NULL) {
  1753. mat->VertexMaterialIdx = -1;
  1754. } else {
  1755. unsigned long crc = vmat->Get_CRC();
  1756. for (int vi=0; vi<VertexMaterialCrcs.Count(); vi++) {
  1757. if (VertexMaterialCrcs[vi] == crc) break;
  1758. }
  1759. if (vi == VertexMaterials.Count()) {
  1760. mat->VertexMaterialIdx = Add_Vertex_Material(vmat);
  1761. VertexMaterialCrcs.Add(crc);
  1762. WWASSERT(VertexMaterialCrcs.Count() == VertexMaterials.Count());
  1763. } else {
  1764. mat->VertexMaterialIdx = vi;
  1765. }
  1766. }
  1767. // add the texture if it is unique
  1768. if (tex == NULL) {
  1769. mat->TextureIdx = -1;
  1770. } else {
  1771. for (int ti=0; ti<Textures.Count(); ti++) {
  1772. if (Textures[ti] == tex) break;
  1773. if (stricmp(Textures[ti]->Get_Texture_Name(),tex->Get_Texture_Name()) == 0) break;
  1774. }
  1775. if (ti == Textures.Count()) {
  1776. mat->TextureIdx = Add_Texture(tex);
  1777. } else {
  1778. mat->TextureIdx = ti;
  1779. }
  1780. }
  1781. LegacyMaterials.Add(mat);
  1782. }
  1783. /***********************************************************************************************
  1784. * MeshLoadContextClass::Peek_Legacy_Shader -- returns a legacy shader *
  1785. * *
  1786. * This function does the re-indexing to go from the legacy shader index to the actual shader *
  1787. * index and then returns that shader *
  1788. * *
  1789. * INPUT: *
  1790. * *
  1791. * OUTPUT: *
  1792. * *
  1793. * WARNINGS: *
  1794. * *
  1795. * HISTORY: *
  1796. * 12/10/98 GTH : Created. *
  1797. *=============================================================================================*/
  1798. ShaderClass MeshLoadContextClass::Peek_Legacy_Shader(int legacy_material_index)
  1799. {
  1800. WWASSERT(legacy_material_index >= 0);
  1801. WWASSERT(legacy_material_index < LegacyMaterials.Count());
  1802. int si = LegacyMaterials[legacy_material_index]->ShaderIdx;
  1803. return Peek_Shader(si);
  1804. }
  1805. /***********************************************************************************************
  1806. * MeshLoadContextClass::Peek_Legacy_Vertex_Material -- returns a pointer to a legacy vertex ma*
  1807. * *
  1808. * INPUT: *
  1809. * *
  1810. * OUTPUT: *
  1811. * *
  1812. * WARNINGS: *
  1813. * *
  1814. * HISTORY: *
  1815. * 12/10/98 GTH : Created. *
  1816. *=============================================================================================*/
  1817. VertexMaterialClass * MeshLoadContextClass::Peek_Legacy_Vertex_Material(int legacy_material_index)
  1818. {
  1819. WWASSERT(legacy_material_index >= 0);
  1820. WWASSERT(legacy_material_index < LegacyMaterials.Count());
  1821. int vi = LegacyMaterials[legacy_material_index]->VertexMaterialIdx;
  1822. if (vi != -1) {
  1823. return Peek_Vertex_Material(vi);
  1824. } else {
  1825. return NULL;
  1826. }
  1827. }
  1828. /***********************************************************************************************
  1829. * MeshLoadContextClass::Peek_Legacy_Texture -- returns a pointer to a texture *
  1830. * *
  1831. * INPUT: *
  1832. * *
  1833. * OUTPUT: *
  1834. * *
  1835. * WARNINGS: *
  1836. * *
  1837. * HISTORY: *
  1838. * 12/10/98 GTH : Created. *
  1839. *=============================================================================================*/
  1840. TextureClass * MeshLoadContextClass::Peek_Legacy_Texture(int legacy_material_index)
  1841. {
  1842. WWASSERT(legacy_material_index >= 0);
  1843. WWASSERT(legacy_material_index < LegacyMaterials.Count());
  1844. int ti = LegacyMaterials[legacy_material_index]->TextureIdx;
  1845. if (ti != -1) {
  1846. return Peek_Texture(ti);
  1847. } else {
  1848. return NULL;
  1849. }
  1850. }
  1851. Vector2 * MeshLoadContextClass::Get_Temporary_UV_Array(int elementcount)
  1852. {
  1853. TempUVArray.Uninitialised_Grow(elementcount);
  1854. return &(TempUVArray[0]);
  1855. }
  1856. /***********************************************************************************************
  1857. * MeshSaveContextClass::MeshSaveContextClass -- constructor *
  1858. * *
  1859. * INPUT: *
  1860. * *
  1861. * OUTPUT: *
  1862. * *
  1863. * WARNINGS: *
  1864. * *
  1865. * HISTORY: *
  1866. *=============================================================================================*/
  1867. MeshSaveContextClass::MeshSaveContextClass(void) :
  1868. CurPass(0),
  1869. CurStage(0)
  1870. {
  1871. }
  1872. /***********************************************************************************************
  1873. * MeshSaveContextClass::~MeshSaveContextClass -- destructor *
  1874. * *
  1875. * INPUT: *
  1876. * *
  1877. * OUTPUT: *
  1878. * *
  1879. * WARNINGS: *
  1880. * *
  1881. * HISTORY: *
  1882. *=============================================================================================*/
  1883. MeshSaveContextClass::~MeshSaveContextClass(void)
  1884. {
  1885. }
  1886. #if 0 // MESH SAVING CODE HAS NOT BEEN MAINTAINED... Leaving here for future reference if we ever need it :-)
  1887. /***********************************************************************************************
  1888. * MeshModelClass::Save -- Save this mesh model! *
  1889. * *
  1890. * INPUT: *
  1891. * *
  1892. * OUTPUT: *
  1893. * *
  1894. * WARNINGS: *
  1895. * *
  1896. * HISTORY: *
  1897. * 2/16/99 GTH : Created. *
  1898. *=============================================================================================*/
  1899. WW3DErrorType MeshModelClass::Save_W3D(ChunkSaveClass & csave)
  1900. {
  1901. MeshSaveContextClass * context = W3DNEW MeshSaveContextClass;
  1902. context->Materials.Collect_Materials(this);
  1903. write_chunks(csave,context);
  1904. delete context;
  1905. return WW3D_ERROR_OK;
  1906. }
  1907. WW3DErrorType MeshModelClass::write_chunks(ChunkSaveClass & csave,MeshSaveContextClass * context)
  1908. {
  1909. // write the header
  1910. write_header(csave,context);
  1911. write_user_text(csave,context);
  1912. // write the geometry
  1913. write_triangles(csave,context);
  1914. write_vertices(csave,context);
  1915. write_vertex_normals(csave,context);
  1916. write_vertex_shade_indices(csave,context);
  1917. write_vertex_influences(csave,context);
  1918. //write_cull_tree(csave);
  1919. // material stuff
  1920. write_material_info(csave,context);
  1921. write_vertex_materials(csave,context);
  1922. write_shaders(csave,context);
  1923. write_textures(csave,context);
  1924. // passes
  1925. for (int i=0; i<Get_Pass_Count(); i++) {
  1926. context->CurPass = i;
  1927. write_material_pass(csave,context);
  1928. }
  1929. return WW3D_ERROR_OK;
  1930. }
  1931. WW3DErrorType MeshModelClass::write_header(ChunkSaveClass & csave,MeshSaveContextClass * /*context*/)
  1932. {
  1933. W3dMeshHeader3Struct header;
  1934. memset(&header,0,sizeof(header));
  1935. // Set names
  1936. if (MeshName) {
  1937. char * name = MeshName->Get_Array();
  1938. char * mesh_name = strchr(name,'.');
  1939. int hierarchy_name_len = 0;
  1940. if (mesh_name == NULL) {
  1941. mesh_name = name;
  1942. } else {
  1943. hierarchy_name_len = (int)mesh_name - (int)name;
  1944. mesh_name++;
  1945. }
  1946. assert( hierarchy_name_len <= W3D_NAME_LEN);
  1947. strncpy( header.MeshName, mesh_name, W3D_NAME_LEN);
  1948. strncpy( header.ContainerName, name, hierarchy_name_len);
  1949. } else {
  1950. sprintf(header.MeshName,"UnNamed");
  1951. }
  1952. header.Version = W3D_CURRENT_MESH_VERSION;
  1953. header.Attributes = W3dAttributes;
  1954. header.NumTris = Get_Polygon_Count();
  1955. header.NumVertices = Get_Vertex_Count();
  1956. header.NumMaterials = 0;
  1957. header.NumDamageStages = 0;
  1958. header.VertexChannels = W3D_VERTEX_CHANNEL_LOCATION;
  1959. if (Get_Flag(SKIN)) {
  1960. header.VertexChannels |= W3D_VERTEX_CHANNEL_BONEID;
  1961. }
  1962. header.FaceChannels = W3D_FACE_CHANNEL_FACE;
  1963. W3dUtilityClass::Convert_Vector(BoundBoxMin,&(header.Min));
  1964. W3dUtilityClass::Convert_Vector(BoundBoxMax,&(header.Max));
  1965. W3dUtilityClass::Convert_Vector(BoundSphereCenter,&header.SphCenter);
  1966. header.SphRadius = BoundSphereRadius;
  1967. csave.Begin_Chunk(W3D_CHUNK_MESH_HEADER3);
  1968. if (csave.Write(&header,sizeof(header)) != sizeof(header)) {
  1969. return WW3D_ERROR_SAVE_FAILED;
  1970. }
  1971. csave.End_Chunk();
  1972. return WW3D_ERROR_OK;
  1973. }
  1974. WW3DErrorType MeshModelClass::write_user_text(ChunkSaveClass & csave,MeshSaveContextClass * /*context*/)
  1975. {
  1976. if (UserText == NULL) return WW3D_ERROR_OK;
  1977. if (strlen(UserText->Get_Array()) < 1) return WW3D_ERROR_OK;
  1978. csave.Begin_Chunk(W3D_CHUNK_MESH_USER_TEXT);
  1979. csave.Write(UserText->Get_Array(),strlen(UserText->Get_Array()) + 1);
  1980. csave.End_Chunk();
  1981. return WW3D_ERROR_OK;
  1982. }
  1983. WW3DErrorType MeshModelClass::write_triangles(ChunkSaveClass & csave,MeshSaveContextClass * /*context*/)
  1984. {
  1985. if (!csave.Begin_Chunk(W3D_CHUNK_TRIANGLES)) {
  1986. return WW3D_ERROR_LOAD_FAILED;
  1987. }
  1988. Vector3i * poly_verts = Poly->Get_Array();
  1989. Vector4 * poly_eq = (PlaneEq ? PlaneEq->Get_Array() : NULL);
  1990. for (int i=0; i<Get_Polygon_Count(); i++) {
  1991. W3dTriStruct tri;
  1992. memset(&tri,0,sizeof(W3dTriStruct));
  1993. // convert each triangle into surrender format
  1994. tri.Vindex[0] = poly_verts[i].I;
  1995. tri.Vindex[1] = poly_verts[i].J;
  1996. tri.Vindex[2] = poly_verts[i].K;
  1997. if (poly_eq) {
  1998. tri.Attributes = 0;
  1999. tri.Normal.X = poly_eq[i].X;
  2000. tri.Normal.Y = poly_eq[i].Y;
  2001. tri.Normal.Z = poly_eq[i].Z;
  2002. tri.Dist = poly_eq[i].W;
  2003. } else {
  2004. Vector3 a,b,normal;
  2005. Vector3 * verts = Vertex->Get_Array();
  2006. const Vector3 & p0= verts[poly_verts[i][0]];
  2007. Vector3::Subtract(verts[poly_verts[i][1]],p0,&a);
  2008. Vector3::Subtract(verts[poly_verts[i][2]],p0,&b);
  2009. Vector3::Cross_Product(a,b,&normal);
  2010. normal.Normalize();
  2011. tri.Attributes = 0;
  2012. tri.Normal.X = normal.X;
  2013. tri.Normal.Y = normal.Y;
  2014. tri.Normal.Z = normal.Z;
  2015. tri.Dist = Vector3::Dot_Product(p0,normal);
  2016. }
  2017. if (csave.Write(&tri,sizeof(W3dTriStruct)) != sizeof(W3dTriStruct)) {
  2018. return WW3D_ERROR_SAVE_FAILED;
  2019. }
  2020. }
  2021. if (!csave.End_Chunk()) {
  2022. return WW3D_ERROR_SAVE_FAILED;
  2023. }
  2024. return WW3D_ERROR_OK;
  2025. }
  2026. WW3DErrorType MeshModelClass::write_vertices(ChunkSaveClass & csave,MeshSaveContextClass * /*context*/)
  2027. {
  2028. if (!csave.Begin_Chunk(W3D_CHUNK_VERTICES)) {
  2029. return WW3D_ERROR_SAVE_FAILED;
  2030. }
  2031. WWASSERT(Get_Vertex_Count() > 0);
  2032. Vector3 * verts = Vertex->Get_Array();
  2033. for (int i=0; i<Get_Vertex_Count(); i++) {
  2034. W3dVectorStruct vert;
  2035. vert.X = verts[i].X;
  2036. vert.Y = verts[i].Y;
  2037. vert.Z = verts[i].Z;
  2038. if (csave.Write(&(vert),sizeof(W3dVectorStruct)) != sizeof(W3dVectorStruct)) {
  2039. return WW3D_ERROR_SAVE_FAILED;
  2040. }
  2041. }
  2042. if (!csave.End_Chunk()) {
  2043. return WW3D_ERROR_SAVE_FAILED;
  2044. }
  2045. return WW3D_ERROR_OK;
  2046. }
  2047. WW3DErrorType MeshModelClass::write_vertex_normals(ChunkSaveClass & csave,MeshSaveContextClass * /*context*/)
  2048. {
  2049. WWASSERT( Get_Vertex_Count() > 0);
  2050. if (!csave.Begin_Chunk(W3D_CHUNK_VERTEX_NORMALS)) {
  2051. return WW3D_ERROR_SAVE_FAILED;
  2052. }
  2053. const Vector3 * verts = Get_Vertex_Normal_Array();
  2054. for (int i=0; i<Get_Vertex_Count(); i++) {
  2055. W3dVectorStruct vert;
  2056. vert.X = verts[i].X;
  2057. vert.Y = verts[i].Y;
  2058. vert.Z = verts[i].Z;
  2059. if (csave.Write(&(vert),sizeof(W3dVectorStruct)) != sizeof(W3dVectorStruct)) {
  2060. return WW3D_ERROR_SAVE_FAILED;
  2061. }
  2062. }
  2063. if (!csave.End_Chunk()) {
  2064. return WW3D_ERROR_SAVE_FAILED;
  2065. }
  2066. return WW3D_ERROR_OK;
  2067. }
  2068. WW3DErrorType MeshModelClass::write_vertex_shade_indices(ChunkSaveClass & csave,MeshSaveContextClass * /*context*/)
  2069. {
  2070. WWASSERT(Get_Vertex_Count() > 0);
  2071. if (VertexShadeIdx == NULL) return WW3D_ERROR_OK;
  2072. if (!csave.Begin_Chunk(W3D_CHUNK_VERTEX_SHADE_INDICES)) {
  2073. return WW3D_ERROR_SAVE_FAILED;
  2074. }
  2075. for (int i=0; i<Get_Vertex_Count(); i++) {
  2076. uint32 idx = VertexShadeIdx->Get_Array()[i];
  2077. if (csave.Write(&idx,sizeof(idx)) != sizeof(idx)) {
  2078. return WW3D_ERROR_SAVE_FAILED;
  2079. }
  2080. }
  2081. if (!csave.End_Chunk()) {
  2082. return WW3D_ERROR_SAVE_FAILED;
  2083. }
  2084. return WW3D_ERROR_OK;
  2085. }
  2086. WW3DErrorType MeshModelClass::write_vertex_influences(ChunkSaveClass & csave,MeshSaveContextClass * /*context*/)
  2087. {
  2088. WWASSERT(Get_Vertex_Count() > 0);
  2089. if (VertexBoneLink == NULL) return WW3D_ERROR_OK;
  2090. if (!csave.Begin_Chunk(W3D_CHUNK_VERTEX_INFLUENCES)) {
  2091. return WW3D_ERROR_SAVE_FAILED;
  2092. }
  2093. W3dVertInfStruct vinf;
  2094. memset(&vinf,0,sizeof(vinf));
  2095. for (int i=0; i<Get_Vertex_Count(); i++) {
  2096. vinf.BoneIdx = VertexBoneLink->Get_Array()[i];
  2097. if (csave.Write(&vinf,sizeof(vinf)) != sizeof(vinf)) {
  2098. return WW3D_ERROR_SAVE_FAILED;
  2099. }
  2100. }
  2101. if (!csave.End_Chunk()) {
  2102. return WW3D_ERROR_SAVE_FAILED;
  2103. }
  2104. return WW3D_ERROR_OK;
  2105. }
  2106. WW3DErrorType MeshModelClass::write_material_info(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2107. {
  2108. if (!csave.Begin_Chunk(W3D_CHUNK_MATERIAL_INFO)) {
  2109. return WW3D_ERROR_SAVE_FAILED;
  2110. }
  2111. W3dMaterialInfoStruct info;
  2112. memset(&info,0,sizeof(info));
  2113. info.PassCount = DefMatDesc->PassCount;
  2114. info.VertexMaterialCount = context->Materials.Get_Vertex_Material_Count();
  2115. info.TextureCount = context->Materials.Get_Texture_Count();
  2116. info.ShaderCount = context->Materials.Get_Shader_Count();
  2117. if (csave.Write(&info,sizeof(info)) != sizeof(info)) {
  2118. return WW3D_ERROR_SAVE_FAILED;
  2119. }
  2120. if (!csave.End_Chunk()) {
  2121. return WW3D_ERROR_SAVE_FAILED;
  2122. }
  2123. return WW3D_ERROR_OK;
  2124. }
  2125. WW3DErrorType MeshModelClass::write_shaders(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2126. {
  2127. if (context->Materials.Get_Shader_Count() <= 0) {
  2128. return WW3D_ERROR_OK;
  2129. }
  2130. if (!csave.Begin_Chunk(W3D_CHUNK_SHADERS)) return WW3D_ERROR_SAVE_FAILED;
  2131. for (int si=0; si<context->Materials.Get_Shader_Count(); si++) {
  2132. W3dShaderStruct file_shader;
  2133. ShaderClass shader = context->Materials.Peek_Shader(si);
  2134. W3dUtilityClass::Convert_Shader(shader,&file_shader);
  2135. if (csave.Write(&file_shader,sizeof(file_shader)) != sizeof(file_shader)) {
  2136. return WW3D_ERROR_SAVE_FAILED;
  2137. }
  2138. }
  2139. if (!csave.End_Chunk()) return WW3D_ERROR_SAVE_FAILED;
  2140. return WW3D_ERROR_OK;
  2141. }
  2142. WW3DErrorType MeshModelClass::write_vertex_materials(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2143. {
  2144. if (context->Materials.Get_Vertex_Material_Count() <= 0) return WW3D_ERROR_OK;
  2145. if (!csave.Begin_Chunk(W3D_CHUNK_VERTEX_MATERIALS)) return WW3D_ERROR_SAVE_FAILED;
  2146. for (int vi=0; vi<context->Materials.Get_Vertex_Material_Count(); vi++) {
  2147. csave.Begin_Chunk(W3D_CHUNK_VERTEX_MATERIAL);
  2148. VertexMaterialClass * vmat = context->Materials.Peek_Vertex_Material(vi);
  2149. vmat->Save_W3D(csave);
  2150. csave.End_Chunk();
  2151. }
  2152. if (!csave.End_Chunk()) return WW3D_ERROR_SAVE_FAILED;
  2153. return WW3D_ERROR_OK;
  2154. }
  2155. WW3DErrorType MeshModelClass::write_textures(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2156. {
  2157. if (context->Materials.Get_Texture_Count() <= 0) return WW3D_ERROR_OK;
  2158. if (!csave.Begin_Chunk(W3D_CHUNK_TEXTURES)) return WW3D_ERROR_SAVE_FAILED;
  2159. for (int ti=0; ti<context->Materials.Get_Texture_Count(); ti++) {
  2160. TextureClass * tex = context->Materials.Peek_Texture(ti);
  2161. Save_Texture(tex,csave);
  2162. }
  2163. if (!csave.End_Chunk()) return WW3D_ERROR_SAVE_FAILED;
  2164. return WW3D_ERROR_OK;
  2165. }
  2166. WW3DErrorType MeshModelClass::write_material_pass(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2167. {
  2168. context->CurStage = 0;
  2169. csave.Begin_Chunk(W3D_CHUNK_MATERIAL_PASS);
  2170. write_vertex_material_ids(csave,context);
  2171. write_shader_ids(csave,context);
  2172. write_dcg(csave,context);
  2173. write_dig(csave,context);
  2174. write_scg(csave,context);
  2175. write_texture_stage(csave,context);
  2176. write_texture_stage(csave,context);
  2177. csave.End_Chunk();
  2178. context->CurPass++;
  2179. return WW3D_ERROR_OK;
  2180. }
  2181. WW3DErrorType MeshModelClass::write_vertex_material_ids(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2182. {
  2183. // first check if all vertex material pointers are Null (is this legal?)
  2184. if ( (DefMatDesc->Material[context->CurPass] == NULL) &&
  2185. (DefMatDesc->MaterialArray[context->CurPass] == NULL)) return WW3D_ERROR_OK;
  2186. csave.Begin_Chunk(W3D_CHUNK_VERTEX_MATERIAL_IDS);
  2187. uint32 id = 0;
  2188. if (DefMatDesc->MaterialArray[context->CurPass] == NULL) {
  2189. id = context->Materials.Find_Vertex_Material(DefMatDesc->Material[context->CurPass]);
  2190. csave.Write(&id,sizeof(id));
  2191. } else {
  2192. VertexMaterialClass ** array = DefMatDesc->MaterialArray[context->CurPass]->Get_Array();
  2193. for (int vi=0; vi<Get_Vertex_Count(); vi++) {
  2194. id = context->Materials.Find_Vertex_Material(array[vi]);
  2195. csave.Write(&id,sizeof(id));
  2196. }
  2197. }
  2198. csave.End_Chunk();
  2199. return WW3D_ERROR_OK;
  2200. }
  2201. WW3DErrorType MeshModelClass::write_shader_ids(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2202. {
  2203. csave.Begin_Chunk(W3D_CHUNK_SHADER_IDS);
  2204. uint32 id = 0;
  2205. if (DefMatDesc->ShaderArray[context->CurPass] == NULL) {
  2206. id = context->Materials.Find_Shader(DefMatDesc->Shader[context->CurPass]);
  2207. csave.Write(&id,sizeof(id));
  2208. } else {
  2209. ShaderClass * array = DefMatDesc->ShaderArray[context->CurPass]->Get_Array();
  2210. for (int pi=0; pi<Get_Polygon_Count(); pi++) {
  2211. id = context->Materials.Find_Shader(array[pi]);
  2212. csave.Write(&id,sizeof(id));
  2213. }
  2214. }
  2215. csave.End_Chunk();
  2216. return WW3D_ERROR_OK;
  2217. }
  2218. WW3DErrorType MeshModelClass::write_scg(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2219. {
  2220. if (DefMatDesc->SCG[context->CurPass] == NULL) return WW3D_ERROR_OK;
  2221. csave.Begin_Chunk(W3D_CHUNK_SCG);
  2222. W3dRGBAStruct color;
  2223. Vector4 * color_array = DefMatDesc->SCG[context->CurPass]->Get_Array();
  2224. for (int vi=0; vi<Get_Vertex_Count(); vi++) {
  2225. W3dUtilityClass::Convert_Color(color_array[vi],&color);
  2226. csave.Write(&color,sizeof(color));
  2227. }
  2228. csave.End_Chunk();
  2229. return WW3D_ERROR_OK;
  2230. }
  2231. WW3DErrorType MeshModelClass::write_dig(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2232. {
  2233. if (DefMatDesc->DIG[context->CurPass] == NULL) return WW3D_ERROR_OK;
  2234. csave.Begin_Chunk(W3D_CHUNK_DIG);
  2235. W3dRGBStruct color;
  2236. Vector3 * color_array = DefMatDesc->DIG[context->CurPass]->Get_Array();
  2237. for (int vi=0; vi<Get_Vertex_Count(); vi++) {
  2238. W3dUtilityClass::Convert_Color(color_array[vi],&color);
  2239. csave.Write(&color,sizeof(color));
  2240. }
  2241. csave.End_Chunk();
  2242. return WW3D_ERROR_OK;
  2243. }
  2244. WW3DErrorType MeshModelClass::write_dcg(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2245. {
  2246. if (DefMatDesc->DCG[context->CurPass] == NULL) return WW3D_ERROR_OK;
  2247. csave.Begin_Chunk(W3D_CHUNK_DCG);
  2248. W3dRGBAStruct color;
  2249. Vector4 * color_array = DefMatDesc->DCG[context->CurPass]->Get_Array();
  2250. for (int vi=0; vi<Get_Vertex_Count(); vi++) {
  2251. W3dUtilityClass::Convert_Color(color_array[vi],&color);
  2252. csave.Write(&color,sizeof(color));
  2253. }
  2254. csave.End_Chunk();
  2255. return WW3D_ERROR_OK;
  2256. }
  2257. WW3DErrorType MeshModelClass::write_texture_stage(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2258. {
  2259. if ( (DefMatDesc->Texture[context->CurPass][context->CurStage] == NULL) &&
  2260. (DefMatDesc->TextureArray[context->CurPass][context->CurStage] == NULL)) return WW3D_ERROR_OK;
  2261. csave.Begin_Chunk(W3D_CHUNK_TEXTURE_STAGE);
  2262. write_texture_ids(csave,context);
  2263. write_stage_texcoords(csave,context);
  2264. csave.End_Chunk();
  2265. context->CurStage++;
  2266. return WW3D_ERROR_OK;
  2267. }
  2268. WW3DErrorType MeshModelClass::write_texture_ids(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2269. {
  2270. csave.Begin_Chunk(W3D_CHUNK_TEXTURE_IDS);
  2271. uint32 id = 0;
  2272. if (DefMatDesc->TextureArray[context->CurPass][context->CurStage] == NULL) {
  2273. id = context->Materials.Find_Texture(DefMatDesc->Texture[context->CurPass][context->CurStage]);
  2274. csave.Write(&id,sizeof(id));
  2275. } else {
  2276. srTextureIFace ** array = DefMatDesc->TextureArray[context->CurPass][context->CurStage]->Get_Array();
  2277. for (int pi=0; pi<Get_Polygon_Count(); pi++) {
  2278. id = context->Materials.Find_Texture(array[pi]);
  2279. csave.Write(&id,sizeof(id));
  2280. }
  2281. }
  2282. csave.End_Chunk();
  2283. return WW3D_ERROR_OK;
  2284. }
  2285. WW3DErrorType MeshModelClass::write_stage_texcoords(ChunkSaveClass & csave,MeshSaveContextClass * context)
  2286. {
  2287. if (DefMatDesc->UV[context->CurPass][context->CurStage] == NULL) return WW3D_ERROR_OK;
  2288. csave.Begin_Chunk(W3D_CHUNK_STAGE_TEXCOORDS);
  2289. W3dTexCoordStruct tex;
  2290. Vector2 * array = DefMatDesc->UV[context->CurPass][context->CurStage]->Get_Array();
  2291. for (int vi=0; vi<Get_Vertex_Count(); vi++) {
  2292. tex.U = array[vi].X;
  2293. tex.V = 1.0f - array[vi].Y;
  2294. csave.Write(&tex,sizeof(tex));
  2295. }
  2296. csave.End_Chunk();
  2297. return WW3D_ERROR_OK;
  2298. }
  2299. #endif // 0 (disabled mesh saving code)