w3dmtl.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Max2W3d *
  23. * *
  24. * $Archive:: /Commando/Code/Tools/max2w3d/w3dmtl.cpp $*
  25. * *
  26. * $Author:: Greg_h $*
  27. * *
  28. * $Modtime:: 8/22/01 7:47a $*
  29. * *
  30. * $Revision:: 32 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "w3dmtl.h"
  36. #include <Max.h>
  37. #include <StdMat.h>
  38. #include "gamemtl.h"
  39. #include "realcrc.h"
  40. static W3dRGBStruct Color_To_W3d(Color & c)
  41. {
  42. W3dRGBStruct wc;
  43. wc.R = (c.r * 255.0f);
  44. wc.G = (c.g * 255.0f);
  45. wc.B = (c.b * 255.0f);
  46. wc.pad = 0;
  47. return wc;
  48. }
  49. /*
  50. Implementation of W3dMapClass
  51. */
  52. W3dMapClass::W3dMapClass(const W3dMapClass & that)
  53. {
  54. Set_Filename(that.Filename);
  55. if (that.AnimInfo) {
  56. Set_Anim_Info(that.AnimInfo);
  57. }
  58. }
  59. W3dMapClass & W3dMapClass::operator = (const W3dMapClass & that)
  60. {
  61. if (this != &that) {
  62. Set_Filename(that.Filename);
  63. Set_Anim_Info(that.AnimInfo);
  64. }
  65. return *this;
  66. }
  67. W3dMapClass::~W3dMapClass(void)
  68. {
  69. if (Filename) free(Filename);
  70. if (AnimInfo) delete AnimInfo;
  71. }
  72. void W3dMapClass::Reset(void)
  73. {
  74. if (Filename) free(Filename);
  75. if (AnimInfo) delete AnimInfo;
  76. Filename = NULL;
  77. AnimInfo = NULL;
  78. }
  79. void W3dMapClass::Set_Filename(const char * fullpath)
  80. {
  81. if (Filename) {
  82. free(Filename);
  83. }
  84. if (fullpath) {
  85. char name[_MAX_FNAME];
  86. char exten[_MAX_EXT];
  87. char fname[_MAX_FNAME+_MAX_EXT+2];
  88. _splitpath(fullpath,NULL,NULL,name,exten);
  89. _makepath(fname,NULL,NULL,name,exten);
  90. //strupr(fname); (gth) need to preserve case since unix/PS2 is case sensitive...
  91. Filename = strdup(fname);
  92. } else {
  93. Filename = NULL;
  94. }
  95. }
  96. void W3dMapClass::Set_Anim_Info(const W3dTextureInfoStruct * info)
  97. {
  98. if (info == NULL) {
  99. if (AnimInfo) {
  100. delete AnimInfo;
  101. AnimInfo = NULL;
  102. return;
  103. }
  104. } else {
  105. if (AnimInfo == NULL) {
  106. AnimInfo = new W3dTextureInfoStruct;
  107. }
  108. *AnimInfo = *info;
  109. }
  110. }
  111. void W3dMapClass::Set_Anim_Info(int framecount,float framerate)
  112. {
  113. if (AnimInfo == NULL) {
  114. AnimInfo = new W3dTextureInfoStruct;
  115. }
  116. AnimInfo->FrameCount = framecount;
  117. AnimInfo->FrameRate = framerate;
  118. }
  119. /*
  120. Implementation of W3dMaterialClass
  121. */
  122. W3dMaterialClass::W3dMaterialClass(void)
  123. {
  124. PassCount = 0;
  125. SortLevel = SORT_LEVEL_NONE;
  126. for (int pass = 0; pass < MAX_PASSES; pass++) {
  127. Materials[pass] = NULL;
  128. W3d_Shader_Reset(&(Shaders[pass]));
  129. for (int stage = 0; stage < MAX_STAGES; stage++) {
  130. Textures[pass][stage] = NULL;
  131. MapChannel[pass][stage] = 1;
  132. MapperArgs[pass][stage] = NULL;
  133. }
  134. }
  135. }
  136. W3dMaterialClass::~W3dMaterialClass(void)
  137. {
  138. Free();
  139. }
  140. void W3dMaterialClass::Free(void)
  141. {
  142. for (int pass = 0; pass < MAX_PASSES; pass++) {
  143. if (Materials[pass]) {
  144. delete Materials[pass];
  145. Materials[pass] = NULL;
  146. }
  147. for (int stage = 0; stage < MAX_STAGES; stage++) {
  148. if (Textures[pass][stage]) {
  149. delete Textures[pass][stage];
  150. Textures[pass][stage] = NULL;
  151. }
  152. if (MapperArgs[pass][stage]) {
  153. delete [] MapperArgs[pass][stage];
  154. MapperArgs[pass][stage] = NULL;
  155. }
  156. }
  157. }
  158. }
  159. void W3dMaterialClass::Reset(void)
  160. {
  161. Free();
  162. SortLevel = SORT_LEVEL_NONE;
  163. for (int pass=0; pass < MAX_PASSES; pass++) {
  164. W3d_Shader_Reset(&(Shaders[pass]));
  165. for (int stage=0; stage < MAX_STAGES; stage++) {
  166. MapChannel[pass][stage] = 1;
  167. }
  168. }
  169. }
  170. void W3dMaterialClass::Set_Surface_Type(unsigned int type)
  171. {
  172. SurfaceType = type;
  173. }
  174. void W3dMaterialClass::Set_Sort_Level(int level)
  175. {
  176. assert(level <= MAX_SORT_LEVEL);
  177. SortLevel = level;
  178. }
  179. void W3dMaterialClass::Set_Pass_Count(int count)
  180. {
  181. assert(count >= 0);
  182. assert(count < MAX_PASSES);
  183. PassCount = count;
  184. }
  185. void W3dMaterialClass::Set_Vertex_Material(const W3dVertexMaterialStruct & vmat,int pass)
  186. {
  187. assert(pass >= 0);
  188. assert(pass < PassCount);
  189. if (Materials[pass] == NULL) {
  190. Materials[pass] = new W3dVertexMaterialStruct;
  191. }
  192. *(Materials[pass]) = vmat;
  193. }
  194. void W3dMaterialClass::Set_Mapper_Args(const char *args_buffer, int pass, int stage)
  195. {
  196. assert(pass >= 0);
  197. assert(pass < PassCount);
  198. assert(stage >= 0);
  199. assert(stage < MAX_STAGES);
  200. if (MapperArgs[pass][stage] != NULL) {
  201. delete [] MapperArgs[pass][stage];
  202. MapperArgs[pass][stage] = NULL;
  203. }
  204. if (args_buffer) {
  205. int len = strlen(args_buffer);
  206. MapperArgs[pass][stage] = new char [len + 1];
  207. strcpy(MapperArgs[pass][stage], args_buffer);
  208. }
  209. }
  210. void W3dMaterialClass::Set_Shader(const W3dShaderStruct & shader,int pass)
  211. {
  212. assert(pass >= 0);
  213. assert(pass < PassCount);
  214. Shaders[pass] = shader;
  215. }
  216. void W3dMaterialClass::Set_Texture(const W3dMapClass & map,int pass,int stage)
  217. {
  218. assert(pass >= 0);
  219. assert(pass < PassCount);
  220. if (Textures[pass][stage] == NULL) {
  221. Textures[pass][stage] = new W3dMapClass;
  222. }
  223. *(Textures[pass][stage]) = map;
  224. }
  225. void W3dMaterialClass::Set_Map_Channel(int pass,int stage,int channel)
  226. {
  227. assert(pass >= 0);
  228. assert(pass < PassCount);
  229. MapChannel[pass][stage] = channel;
  230. }
  231. unsigned int W3dMaterialClass::Get_Surface_Type(void) const
  232. {
  233. return SurfaceType;
  234. }
  235. int W3dMaterialClass::Get_Sort_Level(void) const
  236. {
  237. return SortLevel;
  238. }
  239. int W3dMaterialClass::Get_Pass_Count(void) const
  240. {
  241. return PassCount;
  242. }
  243. W3dVertexMaterialStruct * W3dMaterialClass::Get_Vertex_Material(int pass ) const
  244. {
  245. assert(pass >= 0);
  246. assert(pass < PassCount);
  247. return Materials[pass];
  248. }
  249. const char * W3dMaterialClass::Get_Mapper_Args(int pass, int stage) const
  250. {
  251. assert(pass >= 0);
  252. assert(pass < PassCount);
  253. assert(stage >= 0);
  254. assert(stage < MAX_STAGES);
  255. return MapperArgs[pass][stage];
  256. }
  257. W3dShaderStruct W3dMaterialClass::Get_Shader(int pass) const
  258. {
  259. assert(pass >= 0);
  260. assert(pass < PassCount);
  261. return Shaders[pass];
  262. }
  263. W3dMapClass * W3dMaterialClass::Get_Texture(int pass,int stage) const
  264. {
  265. assert(pass >= 0);
  266. assert(pass < PassCount);
  267. assert(stage >= 0);
  268. assert(stage < MAX_STAGES);
  269. return Textures[pass][stage];
  270. }
  271. int W3dMaterialClass::Get_Map_Channel(int pass,int stage) const
  272. {
  273. assert(pass >= 0);
  274. assert(pass < PassCount);
  275. assert(stage >= 0);
  276. assert(stage < MAX_STAGES);
  277. return MapChannel[pass][stage];
  278. }
  279. void W3dMaterialClass::Init(Mtl * mtl, char *materialColorTexture)
  280. {
  281. bool ps2_mat = false;
  282. Reset();
  283. if (mtl->ClassID() == PS2GameMaterialClassID)
  284. {
  285. ps2_mat = true;
  286. }
  287. if ((mtl->ClassID() == GameMaterialClassID) || ps2_mat) {
  288. Init((GameMtl*)mtl, materialColorTexture); ///@todo: Fix this for substituted textures.
  289. return;
  290. }
  291. Texmap * tmap;
  292. PassCount = 1;
  293. tmap = mtl->GetSubTexmap(ID_RL);
  294. if (tmap && tmap->ClassID() == Class_ID(BMTEX_CLASS_ID,0)) {
  295. PassCount++;
  296. }
  297. W3dVertexMaterialStruct mat;
  298. W3dShaderStruct shader;
  299. W3dMapClass tex;
  300. /*
  301. ** Setting up the diffuse color pass
  302. */
  303. W3d_Shader_Reset(&shader);
  304. mat.Attributes = 0;
  305. mat.Emissive.R = mat.Emissive.G = mat.Emissive.B = 0; //(uint8)(255 .0f * mtl->GetSelfIllum());
  306. Color diffuse = mtl->GetDiffuse();
  307. mat.Diffuse.R = (uint8)(diffuse.r * 255.0f);
  308. mat.Diffuse.G = (uint8)(diffuse.g * 255.0f);
  309. mat.Diffuse.B = (uint8)(diffuse.b * 255.0f);
  310. mat.Ambient = mat.Diffuse;
  311. Color specular = mtl->GetSpecular();
  312. mat.Specular.R = (uint8)(specular.r * 255.0f);
  313. mat.Specular.G = (uint8)(specular.g * 255.0f);
  314. mat.Specular.B = (uint8)(specular.b * 255.0f);
  315. mat.Shininess = mtl->GetShininess();
  316. mat.Opacity = 1.0f - mtl->GetXParency();
  317. mat.Translucency = 0.0f;
  318. tmap = mtl->GetSubTexmap(ID_DI);
  319. if (tmap && tmap->ClassID() == Class_ID(BMTEX_CLASS_ID,0)) {
  320. char * tname = ((BitmapTex *)tmap)->GetMapName();
  321. if (tname) {
  322. tex.Set_Filename(tname);
  323. mat.Diffuse.R = mat.Diffuse.G = mat.Diffuse.B = 255;
  324. W3d_Shader_Set_Texturing(&shader,W3DSHADER_TEXTURING_ENABLE);
  325. Set_Texture(tex,0,0);
  326. }
  327. }
  328. if (materialColorTexture && !mtl->GetSubTexmap(ID_DI) && !mtl->GetSubTexmap(ID_RL))
  329. { //no textures on material, substitute textures to improve rendering speed.
  330. tex.Set_Filename(materialColorTexture); ///@todo: Fix this to procedural name/path
  331. W3d_Shader_Set_Texturing(&shader,W3DSHADER_TEXTURING_ENABLE);
  332. //This texture will hold solid pixels of material color, don't need any filtering.
  333. // W3dTextureInfoStruct texinfo;
  334. // memset(&texinfo,0,sizeof(texinfo));
  335. // texinfo.Attributes = texinfo.Attributes | /*W3DTEXTURE_NO_LOD|*/W3DTEXTURE_CLAMP_U | W3DTEXTURE_CLAMP_V;
  336. // tex.Set_Anim_Info(&texinfo);
  337. Set_Texture(tex,0,0);
  338. }
  339. if (mat.Opacity != 1.0f) {
  340. W3d_Shader_Set_Dest_Blend_Func(&shader,W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_ALPHA);
  341. W3d_Shader_Set_Src_Blend_Func(&shader,W3DSHADER_SRCBLENDFUNC_SRC_ALPHA);
  342. }
  343. Set_Vertex_Material(mat,0);
  344. Set_Shader(shader,0);
  345. /*
  346. ** Setting up the reflection pass (envmap)
  347. */
  348. if (PassCount == 2) {
  349. W3d_Shader_Reset(&shader);
  350. if (ps2_mat)
  351. {
  352. W3d_Shader_Set_Pri_Gradient(&shader,PSS_PRIGRADIENT_MODULATE);
  353. }
  354. else
  355. {
  356. W3d_Shader_Set_Pri_Gradient(&shader,W3DSHADER_PRIGRADIENT_MODULATE);
  357. }
  358. W3d_Shader_Set_Sec_Gradient(&shader,W3DSHADER_SECGRADIENT_DISABLE);
  359. W3d_Shader_Set_Depth_Mask(&shader,W3DSHADER_DEPTHMASK_WRITE_DISABLE);
  360. W3d_Shader_Set_Dest_Blend_Func(&shader,W3DSHADER_DESTBLENDFUNC_ONE);
  361. W3d_Shader_Set_Src_Blend_Func(&shader,W3DSHADER_SRCBLENDFUNC_ONE);
  362. W3d_Shader_Set_Texturing(&shader,W3DSHADER_TEXTURING_ENABLE);
  363. // PS2 specific paramaters.
  364. W3d_Shader_Set_PS2_Param_A(&shader, PSS_SRC);
  365. W3d_Shader_Set_PS2_Param_B(&shader, PSS_ZERO);
  366. W3d_Shader_Set_PS2_Param_B(&shader, PSS_ONE);
  367. W3d_Shader_Set_PS2_Param_B(&shader, PSS_DEST);
  368. W3d_Vertex_Material_Reset(&mat);
  369. mat.Diffuse.R = mat.Diffuse.G = mat.Diffuse.B = 128;
  370. mat.Attributes &= W3DVERTMAT_STAGE0_MAPPING_MASK;
  371. mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_ENVIRONMENT;
  372. tmap = mtl->GetSubTexmap(ID_RL);
  373. if (tmap && tmap->ClassID() == Class_ID(BMTEX_CLASS_ID,0)) {
  374. char * tname = ((BitmapTex *)tmap)->GetMapName();
  375. if (tname) {
  376. tex.Set_Filename(tname);
  377. Set_Texture(tex,1);
  378. }
  379. }
  380. Set_Vertex_Material(mat,1);
  381. Set_Shader(shader,1);
  382. }
  383. }
  384. void W3dMaterialClass::Init(GameMtl * gamemtl, char *materialColorTexture)
  385. {
  386. Reset();
  387. PassCount = gamemtl->Get_Pass_Count();
  388. Set_Surface_Type (gamemtl->Get_Surface_Type ());
  389. Set_Sort_Level(gamemtl->Get_Sort_Level());
  390. for (int pass=0;pass<gamemtl->Get_Pass_Count(); pass++) {
  391. /*
  392. ** set up the shader
  393. */
  394. W3dShaderStruct shader;
  395. W3d_Shader_Reset(&shader);
  396. shader.DepthCompare = gamemtl->Get_Depth_Compare(pass);
  397. shader.DepthMask = gamemtl->Get_Depth_Mask(pass);
  398. shader.AlphaTest = gamemtl->Get_Alpha_Test(pass);
  399. shader.DestBlend = gamemtl->Get_Dest_Blend(pass);
  400. shader.PriGradient = gamemtl->Get_Pri_Gradient(pass);
  401. shader.SecGradient = gamemtl->Get_Sec_Gradient(pass);
  402. shader.SrcBlend = gamemtl->Get_Src_Blend(pass);
  403. shader.DetailColorFunc = gamemtl->Get_Detail_Color_Func(pass);
  404. shader.DetailAlphaFunc = gamemtl->Get_Detail_Alpha_Func(pass);
  405. shader.Texturing = W3DSHADER_TEXTURING_DISABLE;
  406. shader.PostDetailColorFunc = gamemtl->Get_Detail_Color_Func(pass); // (gth) set up the post-detail options
  407. shader.PostDetailAlphaFunc = gamemtl->Get_Detail_Alpha_Func(pass);
  408. // PS2 specific paramaters.
  409. W3d_Shader_Set_PS2_Param_A(&shader, gamemtl->Get_PS2_Shader_Param_A(pass));
  410. W3d_Shader_Set_PS2_Param_B(&shader, gamemtl->Get_PS2_Shader_Param_B(pass));
  411. W3d_Shader_Set_PS2_Param_C(&shader, gamemtl->Get_PS2_Shader_Param_C(pass));
  412. W3d_Shader_Set_PS2_Param_D(&shader, gamemtl->Get_PS2_Shader_Param_D(pass));
  413. /*
  414. ** set up the vertex material
  415. */
  416. W3dVertexMaterialStruct mat;
  417. mat.Attributes = 0;
  418. if (gamemtl->Get_Copy_Specular_To_Diffuse(pass)) {
  419. mat.Attributes |= W3DVERTMAT_COPY_SPECULAR_TO_DIFFUSE;
  420. }
  421. // mapping type for stage 0
  422. switch(gamemtl->Get_Mapping_Type(pass, 0))
  423. {
  424. case GAMEMTL_MAPPING_UV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_UV; break;
  425. case GAMEMTL_MAPPING_ENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_ENVIRONMENT; break;
  426. case GAMEMTL_MAPPING_CHEAP_ENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_CHEAP_ENVIRONMENT; break;
  427. case GAMEMTL_MAPPING_SCREEN: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_SCREEN; break;
  428. case GAMEMTL_MAPPING_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_LINEAR_OFFSET; break;
  429. case GAMEMTL_MAPPING_SILHOUETTE: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_SILHOUETTE; break;
  430. case GAMEMTL_MAPPING_SCALE: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_SCALE; break;
  431. case GAMEMTL_MAPPING_GRID: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_GRID; break;
  432. case GAMEMTL_MAPPING_ROTATE: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_ROTATE; break;
  433. case GAMEMTL_MAPPING_SINE_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_SINE_LINEAR_OFFSET; break;
  434. case GAMEMTL_MAPPING_STEP_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_STEP_LINEAR_OFFSET; break;
  435. case GAMEMTL_MAPPING_ZIGZAG_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_ZIGZAG_LINEAR_OFFSET; break;
  436. case GAMEMTL_MAPPING_WS_CLASSIC_ENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_WS_CLASSIC_ENV; break;
  437. case GAMEMTL_MAPPING_WS_ENVIRONMENT: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_WS_ENVIRONMENT; break;
  438. case GAMEMTL_MAPPING_GRID_CLASSIC_ENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_GRID_CLASSIC_ENV; break;
  439. case GAMEMTL_MAPPING_GRID_ENVIRONMENT: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_GRID_ENVIRONMENT; break;
  440. case GAMEMTL_MAPPING_RANDOM: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_RANDOM; break;
  441. case GAMEMTL_MAPPING_EDGE: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_EDGE; break;
  442. case GAMEMTL_MAPPING_BUMPENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_BUMPENV; break;
  443. };
  444. // mapping type for stage 1
  445. switch(gamemtl->Get_Mapping_Type(pass, 1))
  446. {
  447. case GAMEMTL_MAPPING_UV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_UV; break;
  448. case GAMEMTL_MAPPING_ENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_ENVIRONMENT; break;
  449. case GAMEMTL_MAPPING_CHEAP_ENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_CHEAP_ENVIRONMENT; break;
  450. case GAMEMTL_MAPPING_SCREEN: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_SCREEN; break;
  451. case GAMEMTL_MAPPING_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_LINEAR_OFFSET; break;
  452. case GAMEMTL_MAPPING_SILHOUETTE: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_SILHOUETTE; break;
  453. case GAMEMTL_MAPPING_SCALE: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_SCALE; break;
  454. case GAMEMTL_MAPPING_GRID: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_GRID; break;
  455. case GAMEMTL_MAPPING_ROTATE: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_ROTATE; break;
  456. case GAMEMTL_MAPPING_SINE_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_SINE_LINEAR_OFFSET; break;
  457. case GAMEMTL_MAPPING_STEP_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_STEP_LINEAR_OFFSET; break;
  458. case GAMEMTL_MAPPING_ZIGZAG_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_ZIGZAG_LINEAR_OFFSET; break;
  459. case GAMEMTL_MAPPING_WS_CLASSIC_ENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_WS_CLASSIC_ENV; break;
  460. case GAMEMTL_MAPPING_WS_ENVIRONMENT: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_WS_ENVIRONMENT; break;
  461. case GAMEMTL_MAPPING_GRID_CLASSIC_ENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_GRID_CLASSIC_ENV; break;
  462. case GAMEMTL_MAPPING_GRID_ENVIRONMENT: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_GRID_ENVIRONMENT; break;
  463. case GAMEMTL_MAPPING_RANDOM: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_RANDOM; break;
  464. case GAMEMTL_MAPPING_EDGE: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_EDGE; break;
  465. case GAMEMTL_MAPPING_BUMPENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_BUMPENV; break;
  466. };
  467. switch(gamemtl->Get_PSX_Translucency(pass))
  468. {
  469. case GAMEMTL_PSX_TRANS_NONE: mat.Attributes |= W3DVERTMAT_PSX_TRANS_NONE; break;
  470. case GAMEMTL_PSX_TRANS_100: mat.Attributes |= W3DVERTMAT_PSX_TRANS_100; break;
  471. case GAMEMTL_PSX_TRANS_50: mat.Attributes |= W3DVERTMAT_PSX_TRANS_50; break;
  472. case GAMEMTL_PSX_TRANS_25: mat.Attributes |= W3DVERTMAT_PSX_TRANS_25; break;
  473. case GAMEMTL_PSX_TRANS_MINUS_100:mat.Attributes |= W3DVERTMAT_PSX_TRANS_MINUS_100; break;
  474. };
  475. if (!gamemtl->Get_PSX_Lighting(pass)) {
  476. mat.Attributes |= W3DVERTMAT_PSX_NO_RT_LIGHTING;
  477. }
  478. mat.Ambient = Color_To_W3d(gamemtl->Get_Ambient(pass,0));
  479. mat.Diffuse = Color_To_W3d(gamemtl->Get_Diffuse(pass,0));
  480. mat.Specular = Color_To_W3d(gamemtl->Get_Specular(pass,0));
  481. mat.Emissive = Color_To_W3d(gamemtl->Get_Emissive(pass,0));
  482. mat.Shininess = gamemtl->Get_Shininess(pass,0);
  483. mat.Opacity = gamemtl->Get_Opacity(pass,0);
  484. mat.Translucency = gamemtl->Get_Translucency(pass,0);
  485. /*
  486. ** install the two textures if present
  487. */
  488. W3dMapClass w3dmap;
  489. BitmapTex * tex = NULL;
  490. for (int stage=0; stage < MAX_STAGES; stage++) {
  491. if (gamemtl->Get_Texture_Enable(pass,stage) && gamemtl->Get_Texture(pass,stage)) {
  492. w3dmap.Reset();
  493. // get the filename for the w3dmap texture
  494. tex = (BitmapTex *)gamemtl->Get_Texture(pass,stage);
  495. assert(tex->GetMapName());
  496. w3dmap.Set_Filename(tex->GetMapName());
  497. // get the animation and flags for the w3dmap texture
  498. W3dTextureInfoStruct texinfo;
  499. memset(&texinfo,0,sizeof(texinfo));
  500. texinfo.AnimType = gamemtl->Get_Texture_Anim_Type(pass,stage);
  501. if (gamemtl->Get_Texture_Publish(pass,stage)) {
  502. texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_PUBLISH;
  503. }
  504. if (gamemtl->Get_Texture_No_LOD(pass,stage)) {
  505. texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_NO_LOD;
  506. }
  507. if (gamemtl->Get_Texture_Clamp_U(pass,stage)) {
  508. texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_CLAMP_U;
  509. }
  510. if (gamemtl->Get_Texture_Clamp_V(pass,stage)) {
  511. texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_CLAMP_V;
  512. }
  513. if (gamemtl->Get_Texture_Alpha_Bitmap(pass,stage)) {
  514. texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_ALPHA_BITMAP;
  515. }
  516. texinfo.Attributes = texinfo.Attributes | (
  517. (gamemtl->Get_Texture_Hint(pass,stage) << W3DTEXTURE_HINT_SHIFT)
  518. & W3DTEXTURE_HINT_MASK);
  519. // If the shader indicates bump-environment mapping mark this texture as a bumpmap.
  520. if ((stage == 0) && (gamemtl->Get_Pri_Gradient (pass) == W3DSHADER_PRIGRADIENT_BUMPENVMAP)) {
  521. texinfo.Attributes |= W3DTEXTURE_TYPE_BUMPMAP;
  522. }
  523. texinfo.FrameCount = gamemtl->Get_Texture_Frame_Count(pass,stage);
  524. texinfo.FrameRate = gamemtl->Get_Texture_Frame_Rate(pass,stage);
  525. if ((texinfo.FrameCount > 1) || (texinfo.Attributes != 0)) {
  526. w3dmap.Set_Anim_Info(&texinfo);
  527. }
  528. // plug it in and turn on texturing in the shader
  529. Set_Texture(w3dmap,pass,stage);
  530. shader.Texturing = W3DSHADER_TEXTURING_ENABLE;
  531. // copy over the mapping channel
  532. Set_Map_Channel(pass,stage,gamemtl->Get_Map_Channel(pass,stage));
  533. // copy over the mapper args
  534. Set_Mapper_Args(gamemtl->Get_Mapping_Arg_Buffer(pass, stage), pass, stage);
  535. } else {
  536. if (materialColorTexture)
  537. { //no textures on material, substitute textures to improve rendering speed.
  538. w3dmap.Reset();
  539. w3dmap.Set_Filename(materialColorTexture);
  540. // plug it in and turn on texturing in the shader
  541. Set_Texture(w3dmap,pass,stage);
  542. shader.Texturing = W3DSHADER_TEXTURING_ENABLE;
  543. }
  544. break; // break out of the loop (and dont put in stage 1 if stage 0 is missing...)
  545. }
  546. }
  547. Set_Shader(shader,pass);
  548. Set_Vertex_Material(mat,pass);
  549. }
  550. }
  551. bool W3dMaterialClass::Is_Multi_Pass_Transparent(void) const
  552. {
  553. return ((PassCount >= 2) && (Get_Shader(0).DestBlend != W3DSHADER_DESTBLENDFUNC_ZERO));
  554. }
  555. /*
  556. Implementation of W3dMaterialDescClass::VertClass
  557. */
  558. W3dMaterialDescClass::VertMatClass::VertMatClass(void) :
  559. PassIndex(-1),
  560. Crc(0),
  561. Name(NULL)
  562. {
  563. for (int stage=0; stage < W3dMaterialClass::MAX_STAGES; ++stage) {
  564. MapperArgs[stage] = NULL;
  565. }
  566. }
  567. W3dMaterialDescClass::VertMatClass::~VertMatClass(void)
  568. {
  569. if (Name) free(Name);
  570. for (int stage=0; stage < W3dMaterialClass::MAX_STAGES; ++stage) {
  571. if (MapperArgs[stage]) {
  572. delete [] (MapperArgs[stage]);
  573. MapperArgs[stage] = NULL;
  574. }
  575. }
  576. }
  577. W3dMaterialDescClass::VertMatClass &
  578. W3dMaterialDescClass::VertMatClass::operator = (const VertMatClass & that)
  579. {
  580. if (this != &that) {
  581. Material = that.Material;
  582. PassIndex = that.PassIndex;
  583. Crc = that.Crc;
  584. Set_Name(that.Name);
  585. for (int stage=0; stage < W3dMaterialClass::MAX_STAGES; stage++) {
  586. Set_Mapper_Args(that.MapperArgs[stage], stage);
  587. }
  588. }
  589. return *this;
  590. }
  591. bool W3dMaterialDescClass::VertMatClass::operator != (const VertMatClass & that)
  592. {
  593. return !(*this == that);
  594. }
  595. bool W3dMaterialDescClass::VertMatClass::operator == (const VertMatClass & that)
  596. {
  597. assert(0); return false;
  598. }
  599. void W3dMaterialDescClass::VertMatClass::Set_Name(const char * name)
  600. {
  601. if (Name) free(Name);
  602. if (name) {
  603. Name = strdup(name);
  604. } else {
  605. Name = NULL;
  606. }
  607. }
  608. void W3dMaterialDescClass::VertMatClass::Set_Mapper_Args(const char * args, int stage)
  609. {
  610. if (MapperArgs[stage]) {
  611. delete [] (MapperArgs[stage]);
  612. MapperArgs[stage] = NULL;
  613. }
  614. if (args) {
  615. int len = strlen(args);
  616. MapperArgs[stage] = new char [len + 1];
  617. strcpy(MapperArgs[stage], args);
  618. } else {
  619. MapperArgs[stage] = NULL;
  620. }
  621. }
  622. /*
  623. Implementation of W3dMaterialDescClass
  624. */
  625. W3dMaterialDescClass::MaterialRemapClass::MaterialRemapClass(void)
  626. {
  627. PassCount = -1;
  628. for (int pass=0; pass<W3dMaterialClass::MAX_PASSES; pass++) {
  629. VertexMaterialIdx[pass] = -1;
  630. ShaderIdx[pass] = -1;
  631. for (int stage=0; stage<W3dMaterialClass::MAX_STAGES; stage++) {
  632. TextureIdx[pass][stage] = -1;
  633. }
  634. }
  635. }
  636. bool W3dMaterialDescClass::MaterialRemapClass::operator != (const MaterialRemapClass & that)
  637. {
  638. return !(*this == that);
  639. }
  640. bool W3dMaterialDescClass::MaterialRemapClass::operator == (const MaterialRemapClass & that)
  641. {
  642. for (int pass=0; pass<W3dMaterialClass::MAX_PASSES; pass++) {
  643. if (VertexMaterialIdx[pass] != that.VertexMaterialIdx[pass]) return false;
  644. if (ShaderIdx[pass] != that.ShaderIdx[pass]) return false;
  645. for (int stage=0; stage<W3dMaterialClass::MAX_STAGES; stage++) {
  646. if (TextureIdx[pass][stage] != that.TextureIdx[pass][stage]) return false;
  647. }
  648. }
  649. return true;
  650. }
  651. W3dMaterialDescClass::W3dMaterialDescClass(void)
  652. {
  653. Reset();
  654. }
  655. W3dMaterialDescClass::~W3dMaterialDescClass(void)
  656. {
  657. }
  658. void W3dMaterialDescClass::Reset(void)
  659. {
  660. PassCount = -1;
  661. SortLevel = -1;
  662. MaterialRemaps.Clear();
  663. Shaders.Clear();
  664. VertexMaterials.Clear();
  665. Textures.Clear();
  666. }
  667. W3dMaterialDescClass::ErrorType W3dMaterialDescClass::Add_Material(const W3dMaterialClass & mat,const char * name)
  668. {
  669. /*
  670. ** If passes hasn't been set yet, set it.
  671. */
  672. if (PassCount == -1) {
  673. PassCount = mat.Get_Pass_Count();
  674. }
  675. /*
  676. ** Same for sort level.
  677. */
  678. if (SortLevel == -1) {
  679. SortLevel = mat.Get_Sort_Level();
  680. }
  681. /*
  682. ** Verify that this material uses the same number of passes that any
  683. ** other materials we have use.
  684. */
  685. if (mat.Get_Pass_Count() != PassCount) {
  686. return INCONSISTENT_PASSES;
  687. }
  688. if (mat.Is_Multi_Pass_Transparent()) {
  689. char msg[100];
  690. sprintf(msg,"Enable Multipass-Transparency?");
  691. HWND window=GetForegroundWindow();
  692. if (IDYES!=MessageBox(window,msg,"Confirmation",MB_YESNO|MB_ICONINFORMATION|MB_TASKMODAL))
  693. return MULTIPASS_TRANSPARENT;
  694. }
  695. /*
  696. ** Verify that this material uses the same sort level as all other
  697. ** materials used on this mesh.
  698. */
  699. if (mat.Get_Sort_Level() != SortLevel) {
  700. return INCONSISTENT_SORT_LEVEL;
  701. }
  702. /*
  703. ** Ok, lets re-index this material and store the unique parts
  704. */
  705. MaterialRemapClass remap;
  706. for (int pass=0; pass<PassCount; pass++) {
  707. remap.VertexMaterialIdx[pass] = Add_Vertex_Material(
  708. mat.Get_Vertex_Material(pass),mat.Get_Mapper_Args(pass, 0),mat.Get_Mapper_Args(pass, 1),pass,name);
  709. remap.ShaderIdx[pass] = Add_Shader(mat.Get_Shader(pass),pass);
  710. for (int stage=0; stage<W3dMaterialClass::MAX_STAGES; stage++) {
  711. remap.TextureIdx[pass][stage] = Add_Texture(mat.Get_Texture(pass,stage),pass,stage);
  712. remap.MapChannel[pass][stage] = mat.Get_Map_Channel(pass,stage);
  713. }
  714. }
  715. MaterialRemaps.Add(remap);
  716. return OK;
  717. }
  718. int W3dMaterialDescClass::Material_Count(void)
  719. {
  720. return MaterialRemaps.Count();
  721. }
  722. int W3dMaterialDescClass::Pass_Count(void)
  723. {
  724. return PassCount;
  725. }
  726. int W3dMaterialDescClass::Vertex_Material_Count(void)
  727. {
  728. return VertexMaterials.Count();
  729. }
  730. int W3dMaterialDescClass::Shader_Count(void)
  731. {
  732. return Shaders.Count();
  733. }
  734. int W3dMaterialDescClass::Texture_Count(void)
  735. {
  736. return Textures.Count();
  737. }
  738. int W3dMaterialDescClass::Get_Sort_Level(void)
  739. {
  740. return SortLevel;
  741. }
  742. W3dVertexMaterialStruct * W3dMaterialDescClass::Get_Vertex_Material(int vmat_index)
  743. {
  744. assert(vmat_index >= 0);
  745. assert(vmat_index < VertexMaterials.Count());
  746. return &(VertexMaterials[vmat_index].Material);
  747. }
  748. const char * W3dMaterialDescClass::Get_Mapper_Args(int vmat_index, int stage)
  749. {
  750. assert(vmat_index >= 0);
  751. assert(vmat_index < VertexMaterials.Count());
  752. assert(stage >= 0);
  753. assert(stage < W3dMaterialClass::MAX_STAGES);
  754. return VertexMaterials[vmat_index].MapperArgs[stage];
  755. }
  756. W3dShaderStruct * W3dMaterialDescClass::Get_Shader(int shader_index)
  757. {
  758. assert(shader_index >= 0);
  759. assert(shader_index < Shaders.Count());
  760. return &(Shaders[shader_index].Shader);
  761. }
  762. W3dMapClass * W3dMaterialDescClass::Get_Texture(int texture_index)
  763. {
  764. assert(texture_index >= 0);
  765. assert(texture_index < Textures.Count());
  766. return &(Textures[texture_index].Map);
  767. }
  768. int W3dMaterialDescClass::Get_Vertex_Material_Index(int mat_index,int pass)
  769. {
  770. assert(mat_index >= 0);
  771. assert(mat_index < MaterialRemaps.Count());
  772. assert(pass >= 0);
  773. assert(pass < PassCount);
  774. return MaterialRemaps[mat_index].VertexMaterialIdx[pass];
  775. }
  776. int W3dMaterialDescClass::Get_Shader_Index(int mat_index,int pass)
  777. {
  778. assert(mat_index >= 0);
  779. assert(mat_index < MaterialRemaps.Count());
  780. assert(pass >= 0);
  781. assert(pass < PassCount);
  782. return MaterialRemaps[mat_index].ShaderIdx[pass];
  783. }
  784. int W3dMaterialDescClass::Get_Texture_Index(int mat_index,int pass,int stage)
  785. {
  786. assert(mat_index >= 0);
  787. assert(mat_index < MaterialRemaps.Count());
  788. assert(pass >= 0);
  789. assert(pass < PassCount);
  790. assert(stage >= 0);
  791. assert(stage < W3dMaterialClass::MAX_STAGES);
  792. return MaterialRemaps[mat_index].TextureIdx[pass][stage];
  793. }
  794. W3dVertexMaterialStruct * W3dMaterialDescClass::Get_Vertex_Material(int mat_index,int pass)
  795. {
  796. int index = Get_Vertex_Material_Index(mat_index,pass);
  797. if (index == -1) {
  798. return NULL;
  799. } else {
  800. return Get_Vertex_Material(index);
  801. }
  802. }
  803. const char * W3dMaterialDescClass::Get_Mapper_Args(int mat_index,int pass,int stage)
  804. {
  805. int index = Get_Vertex_Material_Index(mat_index,pass);
  806. if (index == -1) {
  807. return NULL;
  808. } else {
  809. return Get_Mapper_Args(index,stage);
  810. }
  811. }
  812. W3dShaderStruct * W3dMaterialDescClass::Get_Shader(int mat_index,int pass)
  813. {
  814. int index = Get_Shader_Index(mat_index,pass);
  815. if (index == -1) {
  816. return NULL;
  817. } else {
  818. return Get_Shader(index);
  819. }
  820. }
  821. W3dMapClass * W3dMaterialDescClass::Get_Texture(int mat_index,int pass,int stage)
  822. {
  823. int index = Get_Texture_Index(mat_index,pass,stage);
  824. if (index == -1) {
  825. return NULL;
  826. } else {
  827. return Get_Texture(index);
  828. }
  829. }
  830. int W3dMaterialDescClass::Get_Map_Channel(int mat_index,int pass,int stage)
  831. {
  832. return MaterialRemaps[mat_index].MapChannel[pass][stage];
  833. }
  834. const char * W3dMaterialDescClass::Get_Vertex_Material_Name(int mat_index,int pass)
  835. {
  836. int index = Get_Vertex_Material_Index(mat_index,pass);
  837. if (index == -1) {
  838. return NULL;
  839. } else {
  840. return VertexMaterials[index].Name;
  841. }
  842. }
  843. const char * W3dMaterialDescClass::Get_Vertex_Material_Name(int vmat_index)
  844. {
  845. return VertexMaterials[vmat_index].Name;
  846. }
  847. bool W3dMaterialDescClass::Stage_Needs_Texture_Coordinates(int pass,int stage)
  848. {
  849. for (int mi=0; mi<MaterialRemaps.Count();mi++) {
  850. W3dShaderStruct * shader = Get_Shader(mi,pass);
  851. if (shader) {
  852. if (stage == 0) {
  853. if (W3d_Shader_Get_Texturing(shader) == W3DSHADER_TEXTURING_ENABLE) return true;
  854. }
  855. if (stage == 1) {
  856. if ((W3d_Shader_Get_Detail_Color_Func(shader) != W3DSHADER_DETAILCOLORFUNC_DISABLE) ||
  857. (W3d_Shader_Get_Detail_Alpha_Func(shader) != W3DSHADER_DETAILALPHAFUNC_DISABLE)) {
  858. return true;
  859. }
  860. }
  861. }
  862. }
  863. return false;
  864. }
  865. bool W3dMaterialDescClass::Pass_Uses_Vertex_Alpha(int pass)
  866. {
  867. /*
  868. ** Only the last alpha pass gets vertex alpha
  869. */
  870. int max_alpha_pass = -1;
  871. for (int pi=0; pi<Pass_Count(); pi++) {
  872. if (Pass_Uses_Alpha(pi)) {
  873. max_alpha_pass = pi;
  874. }
  875. }
  876. return (max_alpha_pass == pass);
  877. }
  878. bool W3dMaterialDescClass::Pass_Uses_Alpha(int pass)
  879. {
  880. for (int mi=0; mi<MaterialRemaps.Count(); mi++) {
  881. W3dShaderStruct * shader = Get_Shader(mi,pass);
  882. int dst_blend = W3d_Shader_Get_Dest_Blend_Func(shader);
  883. int src_blend = W3d_Shader_Get_Src_Blend_Func(shader);
  884. int alpha_test = W3d_Shader_Get_Alpha_Test(shader);
  885. if ( (dst_blend == W3DSHADER_DESTBLENDFUNC_SRC_ALPHA) ||
  886. (dst_blend == W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_ALPHA) ||
  887. (src_blend == W3DSHADER_SRCBLENDFUNC_SRC_ALPHA) ||
  888. (src_blend == W3DSHADER_SRCBLENDFUNC_ONE_MINUS_SRC_ALPHA) ||
  889. (alpha_test != 0) )
  890. {
  891. return true;
  892. }
  893. }
  894. return false;
  895. }
  896. int W3dMaterialDescClass::Add_Vertex_Material(W3dVertexMaterialStruct * vmat,
  897. const char *mapper_args0,const char *mapper_args1,int pass,const char * name)
  898. {
  899. if (vmat == NULL) {
  900. return -1;
  901. }
  902. int crc = Compute_Crc(*vmat, mapper_args0, mapper_args1);
  903. for (int vi=0; vi<VertexMaterials.Count(); vi++) {
  904. if ((crc == VertexMaterials[vi].Crc) && (pass == VertexMaterials[vi].PassIndex)) {
  905. break;
  906. }
  907. }
  908. if (vi == VertexMaterials.Count()) {
  909. VertMatClass vm;
  910. vm.Material = *vmat;
  911. vm.Crc = crc;
  912. vm.PassIndex = pass;
  913. vm.Set_Name(name);
  914. vm.Set_Mapper_Args(mapper_args0, 0);
  915. vm.Set_Mapper_Args(mapper_args1, 1);
  916. VertexMaterials.Add(vm);
  917. }
  918. return vi;
  919. }
  920. int W3dMaterialDescClass::Add_Shader(const W3dShaderStruct & shader,int pass)
  921. {
  922. int crc = Compute_Crc(shader);
  923. for (int si=0; si<Shaders.Count(); si++) {
  924. if (crc == Shaders[si].Crc) break;
  925. }
  926. if (si == Shaders.Count()) {
  927. ShadeClass s;
  928. s.Shader = shader;
  929. s.Crc = crc;
  930. Shaders.Add(s);
  931. }
  932. return si;
  933. }
  934. int W3dMaterialDescClass::Add_Texture(W3dMapClass * map,int pass,int stage)
  935. {
  936. if ((map == NULL) || (map->Filename == NULL)) {
  937. return -1;
  938. }
  939. int crc = Compute_Crc(*map);
  940. for (int ti=0; ti<Textures.Count(); ti++) {
  941. if (crc == Textures[ti].Crc) {
  942. break;
  943. }
  944. }
  945. if (ti == Textures.Count()) {
  946. TexClass tex;
  947. tex.Map = *map;
  948. tex.Crc = crc;
  949. Textures.Add(tex);
  950. }
  951. return ti;
  952. }
  953. unsigned long W3dMaterialDescClass::Compute_Crc(const W3dVertexMaterialStruct & vmat,
  954. const char *mapper_args0,
  955. const char *mapper_args1)
  956. {
  957. unsigned long crc = 0;
  958. crc = CRC_Memory((const unsigned char *)&vmat.Attributes,sizeof(vmat.Attributes),crc);
  959. crc = CRC_Memory((const unsigned char *)&vmat.Ambient,sizeof(vmat.Ambient),crc);
  960. crc = CRC_Memory((const unsigned char *)&vmat.Diffuse,sizeof(vmat.Diffuse),crc);
  961. crc = CRC_Memory((const unsigned char *)&vmat.Specular,sizeof(vmat.Specular),crc);
  962. crc = CRC_Memory((const unsigned char *)&vmat.Emissive,sizeof(vmat.Emissive),crc);
  963. crc = CRC_Memory((const unsigned char *)&vmat.Shininess,sizeof(vmat.Shininess),crc);
  964. crc = CRC_Memory((const unsigned char *)&vmat.Opacity,sizeof(vmat.Opacity),crc);
  965. crc = CRC_Memory((const unsigned char *)&vmat.Translucency,sizeof(vmat.Translucency),crc);
  966. // Add mapper args string to crc. We are stripping out spaces, tabs, and
  967. // leading/trailing newlines before computing the CRC so two strings will
  968. // only differ if they have visible differences.
  969. crc = Add_String_To_Crc(mapper_args0, crc);
  970. crc = Add_String_To_Crc(mapper_args1, crc);
  971. return crc;
  972. }
  973. unsigned long W3dMaterialDescClass::Compute_Crc(const W3dShaderStruct & shader)
  974. {
  975. unsigned long crc = 0;
  976. crc = CRC_Memory((const unsigned char *)&shader,sizeof(shader),crc);
  977. return crc;
  978. }
  979. unsigned long W3dMaterialDescClass::Compute_Crc(const W3dMapClass & map)
  980. {
  981. unsigned long crc = 0;
  982. if (map.AnimInfo != NULL) {
  983. crc = CRC_Memory((const unsigned char *)&map.AnimInfo->Attributes,sizeof(map.AnimInfo->Attributes),crc);
  984. crc = CRC_Memory((const unsigned char *)&map.AnimInfo->AnimType,sizeof(map.AnimInfo->AnimType),crc);
  985. crc = CRC_Memory((const unsigned char *)&map.AnimInfo->FrameCount,sizeof(map.AnimInfo->FrameCount),crc);
  986. crc = CRC_Memory((const unsigned char *)&map.AnimInfo->FrameRate,sizeof(map.AnimInfo->FrameRate),crc);
  987. }
  988. crc = CRC_Stringi(map.Filename, crc);
  989. return crc;
  990. }
  991. unsigned long W3dMaterialDescClass::Add_String_To_Crc(const char *str, unsigned long in_crc)
  992. {
  993. unsigned long out_crc = in_crc;
  994. if (str) {
  995. int len = strlen(str);
  996. char *temp = new char[len + 1];
  997. const char *p_in = str;
  998. // skip leading spaces, tabs, newlines
  999. for (; *p_in == ' ' || *p_in == '\t' || *p_in == '\r' || *p_in == '\n'; p_in++);
  1000. // copy string, skipping spaces and tabs
  1001. char * p_out = temp;
  1002. int count = 0;
  1003. for (; *p_in; p_in++) {
  1004. for (; *p_in == ' ' || *p_in == '\t'; p_in++);
  1005. if (!(*p_in)) break;
  1006. *p_out = *p_in;
  1007. p_out++;
  1008. count++;
  1009. }
  1010. *p_out = 0;
  1011. // Erase any trailing newlines:
  1012. if (count) {
  1013. // p_out now points to the ending null - make it point to the
  1014. // character before it (the last character of the string proper)
  1015. p_out--;
  1016. for (; *p_out == '\r' || *p_out == '\n'; p_out--) {
  1017. *p_out = '\000';
  1018. count--;
  1019. }
  1020. }
  1021. out_crc = CRC_Memory((const unsigned char *)temp,count,in_crc);
  1022. delete [] temp;
  1023. }
  1024. return out_crc;
  1025. }