Mesh IO.cpp 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. #define CC4_MSHB CC4('M','S','H','B')
  6. #define CC4_MSHR CC4('M','S','H','R')
  7. #define CC4_MSHP CC4('M','S','H','P')
  8. #define CC4_MSHL CC4('M','S','H','L')
  9. #define CC4_MESH CC4('M','E','S','H')
  10. #define CC4_MSHG CC4('M','S','H','G')
  11. /******************************************************************************/
  12. XMaterial::XMaterial()
  13. {
  14. cull =true;
  15. flip_normal_y=false;
  16. technique =MTECH_DEFAULT;
  17. color =1;
  18. ambient =0;
  19. specular =0;
  20. sss =0;
  21. glow =0;
  22. rough =1;
  23. bump =0.03f;
  24. tex_scale =1.0f;
  25. det_scale =4;
  26. det_power =0.3f;
  27. reflection =0.2f;
  28. }
  29. void XMaterial::del()
  30. {
  31. T=XMaterial();
  32. }
  33. void XMaterial::createFrom(C Material &src)
  34. {
  35. cull =src.cull;
  36. technique =src.technique;
  37. color =src.color;
  38. ambient =src.ambient;
  39. specular =src.specular;
  40. sss =src.sss;
  41. glow =src.glow;
  42. rough =src.rough;
  43. bump =src.bump;
  44. tex_scale =src.tex_scale;
  45. det_scale =src.det_scale;
  46. det_power =src.det_power;
  47. reflection =src.reflect;
  48. color_map=src. base_0.name();
  49. normal_map=src. base_1.name();
  50. detail_color_map=src. detail_map.name();
  51. reflection_map=src.reflection_map.name();
  52. light_map=src. light_map.name();
  53. }
  54. void XMaterial::copyParamsTo(Material &mtrl)C
  55. {
  56. mtrl.cull =cull;
  57. mtrl.technique=technique;
  58. mtrl.color =color;
  59. mtrl.ambient =ambient;
  60. mtrl.specular =specular.max();
  61. mtrl.sss =sss;
  62. mtrl.glow =glow;
  63. mtrl.rough =rough;
  64. mtrl.bump =bump;
  65. mtrl.tex_scale=tex_scale;
  66. mtrl.det_scale=det_scale;
  67. mtrl.det_power=det_power;
  68. mtrl.reflect =reflection;
  69. mtrl.validate();
  70. }
  71. static void FixPath(Str &name, Str &path)
  72. {
  73. if(name.is() && !FExistSystem(name))
  74. {
  75. Str test;
  76. if(!FullPath(name)) // relative
  77. {
  78. test=NormalizePath(path+name);
  79. if(FExistSystem(test)){name=test; return;}
  80. }
  81. test=path+GetBase(name); // skip the path and leave only file name
  82. if(FExistSystem(test)){name=test; return;}
  83. //name.clear(); don't clear but leave as it was
  84. }
  85. }
  86. void XMaterial::fixPath(Str path)
  87. {
  88. path.tailSlash(true);
  89. FixPath( color_map, path);
  90. FixPath( alpha_map, path);
  91. FixPath( light_map, path);
  92. FixPath( bump_map, path);
  93. FixPath( normal_map, path);
  94. FixPath( specular_map, path);
  95. FixPath( reflection_map, path);
  96. FixPath( detail_color_map, path);
  97. FixPath( detail_bump_map, path);
  98. FixPath( detail_normal_map, path);
  99. FixPath(detail_specular_map, path);
  100. }
  101. Bool XMaterial::save(File &f)C
  102. {
  103. f.cmpUIntV(0); // version
  104. f<<cull<<flip_normal_y<<technique<<color<<ambient<<specular
  105. <<name<<color_map<<alpha_map<<bump_map<<glow_map<<light_map<<normal_map<<specular_map<<reflection_map<<detail_color_map<<detail_bump_map<<detail_normal_map<<detail_specular_map;
  106. return f.ok();
  107. }
  108. Bool XMaterial::load(File &f)
  109. {
  110. switch(f.decUIntV()) // version
  111. {
  112. case 0:
  113. {
  114. f>>cull>>flip_normal_y>>technique>>color>>ambient>>specular
  115. >>name>>color_map>>alpha_map>>bump_map>>glow_map>>light_map>>normal_map>>specular_map>>reflection_map>>detail_color_map>>detail_bump_map>>detail_normal_map>>detail_specular_map;
  116. if(f.ok())return true;
  117. }break;
  118. }
  119. del(); return false;
  120. }
  121. /******************************************************************************/
  122. // MSHB
  123. /******************************************************************************/
  124. Bool MeshBase::saveData(File &f)C
  125. {
  126. f.cmpUIntV(3); // version
  127. UInt flag =T.flag (); f.putUInt (flag );
  128. Int vtxs =T.vtxs (); f.cmpUIntV(vtxs );
  129. Int edges=T.edges(); f.cmpUIntV(edges);
  130. Int tris =T.tris (); f.cmpUIntV(tris );
  131. Int quads=T.quads(); f.cmpUIntV(quads);
  132. if(flag&VTX_POS )f.putN(vtx.pos (), vtxs);
  133. if(flag&VTX_NRM )f.putN(vtx.nrm (), vtxs);
  134. if(flag&VTX_TAN )f.putN(vtx.tan (), vtxs);
  135. if(flag&VTX_BIN )f.putN(vtx.bin (), vtxs);
  136. if(flag&VTX_HLP )f.putN(vtx.hlp (), vtxs);
  137. if(flag&VTX_TEX0 )f.putN(vtx.tex0 (), vtxs);
  138. if(flag&VTX_TEX1 )f.putN(vtx.tex1 (), vtxs);
  139. if(flag&VTX_TEX2 )f.putN(vtx.tex2 (), vtxs);
  140. if(flag&VTX_MATRIX )f.putN(vtx.matrix (), vtxs);
  141. if(flag&VTX_BLEND )f.putN(vtx.blend (), vtxs);
  142. if(flag&VTX_SIZE )f.putN(vtx.size (), vtxs);
  143. if(flag&VTX_MATERIAL)f.putN(vtx.material(), vtxs);
  144. if(flag&VTX_COLOR )f.putN(vtx.color (), vtxs);
  145. if(flag&VTX_FLAG )f.putN(vtx.flag (), vtxs);
  146. if(flag&EDGE_NRM)f.putN(edge.nrm(), edges);
  147. if(flag& TRI_NRM)f.putN(tri .nrm(), tris );
  148. if(flag&QUAD_NRM)f.putN(quad.nrm(), quads);
  149. if(flag&EDGE_FLAG)f.putN(edge.flag(), edges);
  150. if(flag& TRI_FLAG)f.putN(tri .flag(), tris );
  151. if(flag&QUAD_FLAG)f.putN(quad.flag(), quads);
  152. if(flag&EDGE_ID)f.putN(edge.id(), edges);
  153. if(flag& TRI_ID)f.putN(tri .id(), tris );
  154. if(flag&QUAD_ID)f.putN(quad.id(), quads);
  155. if(flag&EDGE_IND )IndSave(f, edge.ind (), edges*2, vtxs);
  156. if(flag& TRI_IND )IndSave(f, tri .ind (), tris *3, vtxs);
  157. if(flag&QUAD_IND )IndSave(f, quad.ind (), quads*4, vtxs);
  158. if(flag&EDGE_ADJ_FACE)IndSave(f, edge.adjFace(), edges*2); // can't use size reduction for adjacent faces because they can contain -1 and SIGN_BIT
  159. if(flag& TRI_ADJ_FACE)IndSave(f, tri .adjFace(), tris *3); // can't use size reduction for adjacent faces because they can contain -1 and SIGN_BIT
  160. if(flag&QUAD_ADJ_FACE)IndSave(f, quad.adjFace(), quads*4); // can't use size reduction for adjacent faces because they can contain -1 and SIGN_BIT
  161. if(flag& TRI_ADJ_EDGE)IndSave(f, tri .adjEdge(), tris *3); // can't use size reduction for adjacent edges because they can contain -1
  162. if(flag&QUAD_ADJ_EDGE)IndSave(f, quad.adjEdge(), quads*4); // can't use size reduction for adjacent edges because they can contain -1
  163. return f.ok();
  164. }
  165. /******************************************************************************/
  166. Bool MeshBase::loadData(File &f)
  167. {
  168. switch(f.decUIntV()) // version
  169. {
  170. case 3:
  171. {
  172. UInt flag =f.getUInt ();
  173. Int vtxs =f.decUIntV(),
  174. edges=f.decUIntV(),
  175. tris =f.decUIntV(),
  176. quads=f.decUIntV();
  177. create(vtxs, edges, tris, quads, flag);
  178. if(flag&VTX_POS )f.getN(vtx.pos (), vtxs);
  179. if(flag&VTX_NRM )f.getN(vtx.nrm (), vtxs);
  180. if(flag&VTX_TAN )f.getN(vtx.tan (), vtxs);
  181. if(flag&VTX_BIN )f.getN(vtx.bin (), vtxs);
  182. if(flag&VTX_HLP )f.getN(vtx.hlp (), vtxs);
  183. if(flag&VTX_TEX0 )f.getN(vtx.tex0 (), vtxs);
  184. if(flag&VTX_TEX1 )f.getN(vtx.tex1 (), vtxs);
  185. if(flag&VTX_TEX2 )f.getN(vtx.tex2 (), vtxs);
  186. if(flag&VTX_MATRIX )f.getN(vtx.matrix (), vtxs);
  187. if(flag&VTX_BLEND )f.getN(vtx.blend (), vtxs);
  188. if(flag&VTX_SIZE )f.getN(vtx.size (), vtxs);
  189. if(flag&VTX_MATERIAL)f.getN(vtx.material(), vtxs);
  190. if(flag&VTX_COLOR )f.getN(vtx.color (), vtxs);
  191. if(flag&VTX_FLAG )f.getN(vtx.flag (), vtxs);
  192. if(flag&EDGE_NRM)f.getN(edge.nrm(), edges);
  193. if(flag& TRI_NRM)f.getN(tri .nrm(), tris );
  194. if(flag&QUAD_NRM)f.getN(quad.nrm(), quads);
  195. if(flag&EDGE_FLAG)f.getN(edge.flag(), edges);
  196. if(flag& TRI_FLAG)f.getN(tri .flag(), tris );
  197. if(flag&QUAD_FLAG)f.getN(quad.flag(), quads);
  198. if(flag&EDGE_ID)f.getN(edge.id(), edges);
  199. if(flag& TRI_ID)f.getN(tri .id(), tris );
  200. if(flag&QUAD_ID)f.getN(quad.id(), quads);
  201. if(flag&EDGE_IND )IndLoad(f, edge.ind (), edges*2);
  202. if(flag& TRI_IND )IndLoad(f, tri .ind (), tris *3);
  203. if(flag&QUAD_IND )IndLoad(f, quad.ind (), quads*4);
  204. if(flag&EDGE_ADJ_FACE)IndLoad(f, edge.adjFace(), edges*2);
  205. if(flag& TRI_ADJ_FACE)IndLoad(f, tri .adjFace(), tris *3);
  206. if(flag&QUAD_ADJ_FACE)IndLoad(f, quad.adjFace(), quads*4);
  207. if(flag& TRI_ADJ_EDGE)IndLoad(f, tri .adjEdge(), tris *3);
  208. if(flag&QUAD_ADJ_EDGE)IndLoad(f, quad.adjEdge(), quads*4);
  209. if(f.ok())return true;
  210. }break;
  211. case 2:
  212. {
  213. UInt flag =f.getUInt();
  214. Int vtxs =f.getInt (),
  215. edges=f.getInt (),
  216. tris =f.getInt (),
  217. quads=f.getInt ();
  218. create(vtxs, edges, tris, quads, flag&~ID_ALL);
  219. if(flag&VTX_POS )f.getN(vtx.pos (), vtxs);
  220. if(flag&VTX_NRM )f.getN(vtx.nrm (), vtxs);
  221. if(flag&VTX_TAN )f.getN(vtx.tan (), vtxs);
  222. if(flag&VTX_BIN )f.getN(vtx.bin (), vtxs);
  223. if(flag&VTX_HLP )f.getN(vtx.hlp (), vtxs);
  224. if(flag&VTX_TEX0 )f.getN(vtx.tex0 (), vtxs);
  225. if(flag&VTX_TEX1 )f.getN(vtx.tex1 (), vtxs);
  226. if(flag&VTX_TEX2 )f.getN(vtx.tex2 (), vtxs);
  227. if(flag&VTX_MATRIX )f.getN(vtx.matrix (), vtxs);
  228. if(flag&VTX_BLEND )f.getN(vtx.blend (), vtxs);
  229. if(flag&VTX_SIZE )f.getN(vtx.size (), vtxs);
  230. if(flag&VTX_MATERIAL)f.getN(vtx.material(), vtxs);
  231. if(flag&VTX_COLOR )f.getN(vtx.color (), vtxs);
  232. if(flag&VTX_FLAG )f.getN(vtx.flag (), vtxs);
  233. if(flag&EDGE_NRM)f.getN(edge.nrm(), edges);
  234. if(flag& TRI_NRM)f.getN(tri .nrm(), tris );
  235. if(flag&QUAD_NRM)f.getN(quad.nrm(), quads);
  236. if(flag&EDGE_FLAG)f.getN(edge.flag(), edges);
  237. if(flag& TRI_FLAG)f.getN(tri .flag(), tris );
  238. if(flag&QUAD_FLAG)f.getN(quad.flag(), quads);
  239. if(flag&EDGE_ID)f.skip(SIZE(VecI2)*edges);
  240. if(flag& TRI_ID)f.skip(SIZE(VecI2)*tris );
  241. if(flag&QUAD_ID)f.skip(SIZE(VecI2)*quads);
  242. if(flag&EDGE_IND )IndLoad(f, edge.ind (), edges*2);
  243. if(flag& TRI_IND )IndLoad(f, tri .ind (), tris *3);
  244. if(flag&QUAD_IND )IndLoad(f, quad.ind (), quads*4);
  245. if(flag&EDGE_ADJ_FACE)IndLoad(f, edge.adjFace(), edges*2);
  246. if(flag& TRI_ADJ_FACE)IndLoad(f, tri .adjFace(), tris *3);
  247. if(flag&QUAD_ADJ_FACE)IndLoad(f, quad.adjFace(), quads*4);
  248. if(flag& TRI_ADJ_EDGE)IndLoad(f, tri .adjEdge(), tris *3);
  249. if(flag&QUAD_ADJ_EDGE)IndLoad(f, quad.adjEdge(), quads*4);
  250. if(f.ok())return true;
  251. }break;
  252. case 1:
  253. {
  254. UInt flag =f.getUInt();
  255. Int vtxs =f.getInt (),
  256. edges=f.getInt (),
  257. tris =f.getInt (),
  258. quads=f.getInt ();
  259. create(vtxs, edges, tris, quads, flag&~ID_ALL);
  260. if(flag&VTX_POS )f.getN(vtx.pos (), vtxs);
  261. if(flag&VTX_NRM )f.getN(vtx.nrm (), vtxs);
  262. if(flag&VTX_TAN )f.getN(vtx.tan (), vtxs);
  263. if(flag&VTX_BIN )f.getN(vtx.bin (), vtxs);
  264. if(flag&VTX_HLP )f.getN(vtx.hlp (), vtxs);
  265. if(flag&VTX_TEX0 )f.getN(vtx.tex0 (), vtxs);
  266. if(flag&VTX_TEX1 )f.getN(vtx.tex1 (), vtxs);
  267. if(flag&VTX_TEX2 )f.getN(vtx.tex2 (), vtxs);
  268. if(flag&VTX_MATRIX )f.getN(vtx.matrix (), vtxs);
  269. if(flag&VTX_BLEND )f.getN(vtx.blend (), vtxs); if(vtx.blend())REP(vtxs){Flt f=(Flt&)vtx.blend(i); Byte b=RoundPos(f*255); vtx.blend(i).set(b, 255-b, 0, 0);}
  270. if(flag&VTX_SIZE )f.getN(vtx.size (), vtxs);
  271. if(flag&VTX_MATERIAL)f.getN(vtx.material(), vtxs);
  272. if(flag&VTX_COLOR )f.getN(vtx.color (), vtxs);
  273. if(flag&VTX_FLAG )f.getN(vtx.flag (), vtxs);
  274. if(flag&EDGE_NRM)f.getN(edge.nrm(), edges);
  275. if(flag& TRI_NRM)f.getN(tri .nrm(), tris );
  276. if(flag&QUAD_NRM)f.getN(quad.nrm(), quads);
  277. if(flag&EDGE_FLAG)f.getN(edge.flag(), edges);
  278. if(flag& TRI_FLAG)f.getN(tri .flag(), tris );
  279. if(flag&QUAD_FLAG)f.getN(quad.flag(), quads);
  280. if(flag&EDGE_ID)f.skip(SIZE(VecI2)*edges);
  281. if(flag& TRI_ID)f.skip(SIZE(VecI2)*tris );
  282. if(flag&QUAD_ID)f.skip(SIZE(VecI2)*quads);
  283. if(flag&EDGE_IND )IndLoad(f, edge.ind (), edges*2);
  284. if(flag& TRI_IND )IndLoad(f, tri .ind (), tris *3);
  285. if(flag&QUAD_IND )IndLoad(f, quad.ind (), quads*4);
  286. if(flag&EDGE_ADJ_FACE)IndLoad(f, edge.adjFace(), edges*2);
  287. if(flag& TRI_ADJ_FACE)IndLoad(f, tri .adjFace(), tris *3);
  288. if(flag&QUAD_ADJ_FACE)IndLoad(f, quad.adjFace(), quads*4);
  289. if(flag& TRI_ADJ_EDGE)IndLoad(f, tri .adjEdge(), tris *3);
  290. if(flag&QUAD_ADJ_EDGE)IndLoad(f, quad.adjEdge(), quads*4);
  291. if(f.ok())return true;
  292. }break;
  293. case 0:
  294. {
  295. f.getByte(); // part of old U16 version byte
  296. UInt flag =f.getUInt();
  297. Int vtxs =f.getInt (),
  298. edges=f.getInt (),
  299. tris =f.getInt (),
  300. quads=f.getInt ();
  301. create(vtxs, edges, tris, quads, flag&~ID_ALL);
  302. if(flag&VTX_POS )f.getN(vtx.pos (), vtxs);
  303. if(flag&VTX_NRM )f.getN(vtx.nrm (), vtxs);
  304. if(flag&VTX_TAN )f.getN(vtx.tan (), vtxs);
  305. if(flag&VTX_BIN )f.getN(vtx.bin (), vtxs);
  306. if(flag&VTX_HLP )f.getN(vtx.hlp (), vtxs);
  307. if(flag&VTX_TEX0 )f.getN(vtx.tex0 (), vtxs);
  308. if(flag&VTX_TEX1 )f.getN(vtx.tex1 (), vtxs);
  309. if(flag&VTX_TEX2 )f.getN(vtx.tex2 (), vtxs);
  310. if(flag&VTX_MATRIX )f.getN(vtx.matrix (), vtxs);
  311. if(flag&VTX_BLEND )f.getN(vtx.blend (), vtxs); if(vtx.blend())REP(vtxs){Flt f=(Flt&)vtx.blend(i); Byte b=RoundPos(f*255); vtx.blend(i).set(b, 255-b, 0, 0);}
  312. if(flag&VTX_SIZE )f.getN(vtx.size (), vtxs);
  313. if(flag&VTX_MATERIAL)f.getN(vtx.material(), vtxs);
  314. if(flag&VTX_COLOR )f.getN(vtx.color (), vtxs); if(vtx.color())REP(vtxs)Swap(vtx.color(i).r, vtx.color(i).b); // convert BGRA -> RGBA
  315. if(flag&VTX_FLAG )f.getN(vtx.flag (), vtxs);
  316. if(flag&EDGE_NRM)f.getN(edge.nrm(), edges);
  317. if(flag& TRI_NRM)f.getN(tri .nrm(), tris );
  318. if(flag&QUAD_NRM)f.getN(quad.nrm(), quads);
  319. if(flag&EDGE_FLAG)f.getN(edge.flag(), edges);
  320. if(flag& TRI_FLAG)f.getN(tri .flag(), tris );
  321. if(flag&QUAD_FLAG)f.getN(quad.flag(), quads);
  322. if(flag&EDGE_ID)f.skip(SIZE(VecI2)*edges);
  323. if(flag& TRI_ID)f.skip(SIZE(VecI2)*tris );
  324. if(flag&QUAD_ID)f.skip(SIZE(VecI2)*quads);
  325. if(flag&EDGE_IND )IndLoad(f, edge.ind (), edges*2);
  326. if(flag& TRI_IND )IndLoad(f, tri .ind (), tris *3);
  327. if(flag&QUAD_IND )IndLoad(f, quad.ind (), quads*4);
  328. if(flag&EDGE_ADJ_FACE)IndLoad(f, edge.adjFace(), edges*2);
  329. if(flag& TRI_ADJ_FACE)IndLoad(f, tri .adjFace(), tris *3);
  330. if(flag&QUAD_ADJ_FACE)IndLoad(f, quad.adjFace(), quads*4);
  331. if(flag& TRI_ADJ_EDGE)IndLoad(f, tri .adjEdge(), tris *3);
  332. if(flag&QUAD_ADJ_EDGE)IndLoad(f, quad.adjEdge(), quads*4);
  333. if(f.ok())return true;
  334. }break;
  335. }
  336. del(); return false;
  337. }
  338. /******************************************************************************/
  339. Bool MeshBase::save(File &f)C
  340. {
  341. f.putUInt(CC4_MSHB);
  342. return saveData(f);
  343. }
  344. Bool MeshBase::load(File &f, CChar *path)
  345. {
  346. switch(f.getUInt())
  347. {
  348. case CC4_MSHB: return loadData(f);
  349. case CC4_MESH:
  350. {
  351. Mesh mesh; if(mesh.loadData(f, path))
  352. {
  353. create(mesh);
  354. return true;
  355. }
  356. }break;
  357. }
  358. del(); return false;
  359. }
  360. /******************************************************************************/
  361. Bool MeshBase::save(C Str &name)C
  362. {
  363. File f; if(f.writeTry(name)){if(save(f) && f.flush())return true; f.del(); FDelFile(name);}
  364. return false;
  365. }
  366. Bool MeshBase::load(C Str &name)
  367. {
  368. File f; if(f.readTry(name))return load(f, _GetPath(name));
  369. del(); return false;
  370. }
  371. /******************************************************************************/
  372. // MSHR
  373. /******************************************************************************/
  374. Bool MeshRender::saveData(File &f)C
  375. {
  376. f.cmpUIntV(5); // version
  377. if(_vb.save(f))
  378. if(_ib.save(f))
  379. {
  380. if(_vb._vtx_num || _ib._ind_num)
  381. {
  382. f.putMulti(_storage, _flag, _bone_splits).putN(_bone_split, _bone_splits);
  383. }
  384. return f.ok();
  385. }
  386. return false;
  387. }
  388. static void Fix(MeshRender &m, Bool color, Bool bone_weight)
  389. {
  390. Int col_ofs=(color ? m.vtxOfs(VTX_COLOR) : -1),
  391. blend_ofs=(bone_weight ? m.vtxOfs(VTX_BLEND) : -1);
  392. if( col_ofs>=0 || blend_ofs>=0)if(Byte *vtx=m.vtxLock())
  393. {
  394. REP(m._vb.vtxs())
  395. {
  396. if( col_ofs>=0){Color &c=*(Color*)(vtx+ col_ofs); Swap(c.r, c.b);}
  397. if(blend_ofs>=0){VecB4 &b=*(VecB4*)(vtx+blend_ofs); Flt f=(Flt&)b; Byte i=RoundPos(f*255); b.set(i, 255-i, 0, 0);}
  398. vtx+=m._vb._vtx_size;
  399. }
  400. m.vtxUnlock();
  401. }
  402. }
  403. Bool MeshRender::loadData(File &f)
  404. {
  405. del(); switch(f.decUIntV()) // version
  406. {
  407. case 5:
  408. {
  409. if(_vb.load(f))
  410. if(_ib.load(f))
  411. {
  412. if(_vb._vtx_num || _ib._ind_num)
  413. {
  414. f.getMulti(_storage, _flag, _bone_splits);
  415. f.getN(Alloc(_bone_split, _bone_splits), _bone_splits); // !! keep as a separate command because if f.get().get() are merged then 'Alloc' may be called before the first get !!
  416. _tris=_ib._ind_num/3;
  417. adjustToPlatform();
  418. if(!setVF())goto error; // !! call at the end (when have VB IB and flag/storage) !!
  419. }
  420. //if(App.flag&APP_AUTO_FREE_MESH_OPEN_GL_ES_DATA)freeOpenGLESData(); don't free here because skinning information may be needed for Mesh-Skeleton link (in Mesh.loadData)
  421. if(f.ok())return true;
  422. }
  423. }break;
  424. case 4:
  425. {
  426. if(_vb.load(f))
  427. if(_ib.load(f))
  428. {
  429. if(_vb._vtx_num || _ib._ind_num)
  430. {
  431. f>>_storage>>_flag>>_bone_splits; f.getN(Alloc(_bone_split, _bone_splits), _bone_splits);
  432. _tris=_ib._ind_num/3;
  433. adjustToPlatform();
  434. if(!setVF())goto error; // !! call at the end (when have VB IB and flag/storage) !!
  435. Fix(T, false, true);
  436. }
  437. //if(App.flag&APP_AUTO_FREE_MESH_OPEN_GL_ES_DATA)freeOpenGLESData(); don't free here because skinning information may be needed for Mesh-Skeleton link (in Mesh.loadData)
  438. if(f.ok())return true;
  439. }
  440. }break;
  441. case 3:
  442. {
  443. if(_vb.load(f))
  444. if(_ib.load(f))
  445. {
  446. if(_vb._vtx_num || _ib._ind_num)
  447. {
  448. Bool compress, dx10; f>>compress>>dx10; _storage=(compress?MSHR_COMPRESS:0)|(dx10?MSHR_SIGNED:MSHR_BONE_SPLIT);
  449. f>>_flag>>_bone_splits; f.getN(Alloc(_bone_split, _bone_splits), _bone_splits);
  450. _tris=_ib._ind_num/3;
  451. adjustToPlatform();
  452. if(!setVF())goto error; // !! call at the end (when have VB IB and flag/storage) !!
  453. Fix(T, true, true);
  454. }
  455. //if(App.flag&APP_AUTO_FREE_MESH_OPEN_GL_ES_DATA)freeOpenGLESData(); don't free here because skinning information may be needed for Mesh-Skeleton link (in Mesh.loadData)
  456. if(f.ok())return true;
  457. }
  458. }break;
  459. case 2:
  460. {
  461. if(_vb.load(f))
  462. if(_ib.load(f))
  463. {
  464. if(_vb._vtx_num || _ib._ind_num)
  465. {
  466. Bool compress; f>>compress; _storage=MSHR_BONE_SPLIT|(compress?MSHR_COMPRESS:0);
  467. f>>_flag>>_bone_splits; f.getN(Alloc(_bone_split, _bone_splits), _bone_splits);
  468. _tris=_ib._ind_num/3;
  469. adjustToPlatform();
  470. if(!setVF())goto error; // !! call at the end (when have VB IB and flag/storage) !!
  471. Fix(T, true, true);
  472. }
  473. //if(App.flag&APP_AUTO_FREE_MESH_OPEN_GL_ES_DATA)freeOpenGLESData(); don't free here because skinning information may be needed for Mesh-Skeleton link (in Mesh.loadData)
  474. if(f.ok())return true;
  475. }
  476. }break;
  477. case 1:
  478. {
  479. Int vtxs, tris; f>>vtxs>>tris;
  480. if( vtxs && tris)
  481. {
  482. Bool bit16 =!f.getBool();
  483. Int vtx_size = f.getInt ();
  484. Int tri_ind_size= f.getInt ();
  485. Int bone_splits = f.getInt ();
  486. UInt flag = f.getUInt();
  487. if(_vb.createNum(vtx_size, vtxs ))
  488. if(_ib.create (tris*3 , bit16))
  489. {
  490. T._storage=MSHR_BONE_SPLIT;
  491. T._tris =tris;
  492. T._flag =flag;
  493. if(!f.getN(Alloc(_bone_split, T._bone_splits=bone_splits), bone_splits))goto error;
  494. Ptr data=vtxLock(LOCK_WRITE); if(!f.get (data, vtxs*vtxSize() ))goto error; vtxUnlock();
  495. data=indLock(LOCK_WRITE); if(!f.get (data, tris*tri_ind_size))goto error; indUnlock();
  496. if(!setVF())goto error; // !! call at the end (when have VB IB and flag/storage) !!
  497. Fix(T, true, true);
  498. MeshBase mshb(T); create(mshb, ~0, false);
  499. //if(App.flag&APP_AUTO_FREE_MESH_OPEN_GL_ES_DATA)freeOpenGLESData(); don't free here because skinning information may be needed for Mesh-Skeleton link (in Mesh::loadData)
  500. if(f.ok())return true;
  501. }
  502. }else if(f.ok())return true;
  503. }break;
  504. case 0:
  505. {
  506. f.getByte(); // old ver
  507. Int vtxs, tris; f>>vtxs>>tris;
  508. if( vtxs && tris)
  509. {
  510. Bool bit16 =!f.getBool();
  511. Int vtx_size = f.getInt ();
  512. Int tri_ind_size= f.getInt ();
  513. UInt flag = f.getUInt();
  514. if(_vb.createNum(vtx_size, vtxs ))
  515. if(_ib.create (tris*3 , bit16))
  516. {
  517. T._storage=0;
  518. T._tris =tris;
  519. T._flag =flag;
  520. Ptr data=vtxLock(LOCK_WRITE); if(!f.get(data, vtxs*vtxSize() ))goto error; vtxUnlock();
  521. data=indLock(LOCK_WRITE); if(!f.get(data, tris*tri_ind_size))goto error; indUnlock();
  522. if(!setVF())goto error; // !! call at the end (when have VB IB and flag/storage) !!
  523. Fix(T, true, true);
  524. MeshBase mshb(T); create(mshb, ~0, false);
  525. //if(App.flag&APP_AUTO_FREE_MESH_OPEN_GL_ES_DATA)freeOpenGLESData(); don't free here because skinning information may be needed for Mesh-Skeleton link (in Mesh.loadData)
  526. if(f.ok())return true;
  527. }
  528. }else if(f.ok())return true;
  529. }break;
  530. }
  531. error:
  532. del(); return false;
  533. }
  534. Bool MeshRender::save(File &f)C
  535. {
  536. f.putUInt(CC4_MSHR);
  537. return saveData(f);
  538. }
  539. Bool MeshRender::load(File &f)
  540. {
  541. if(f.getUInt()==CC4_MSHR)return loadData(f);
  542. del(); return false;
  543. }
  544. Bool MeshRender::save(C Str &name)C
  545. {
  546. File f; if(f.writeTry(name)){if(save(f) && f.flush())return true; f.del(); FDelFile(name);}
  547. return false;
  548. }
  549. Bool MeshRender::load(C Str &name)
  550. {
  551. File f; if(f.readTry(name))return load(f);
  552. del(); return false;
  553. }
  554. /******************************************************************************/
  555. // MESH PART
  556. /******************************************************************************/
  557. Bool MeshPart::saveData(File &f, CChar *path)C
  558. {
  559. f.cmpUIntV(7);
  560. f.putStr(name).putMulti(part_flag, _vtx_heightmap, _draw_mask, _draw_mask_enum_id);
  561. f.putAsset(_materials[0].id());
  562. f.putAsset(_materials[1].id());
  563. f.putAsset(_materials[2].id());
  564. if(_variation .save (f, path))
  565. if(_variations.save (f, path))
  566. if( base .saveData(f))
  567. if( render .saveData(f))
  568. return f.ok();
  569. return false;
  570. }
  571. static void SetOldFlag(MeshPart &part, Byte flag)
  572. {
  573. if(flag&0x1)part.part_flag|=MSHP_NO_PHYS_BODY;
  574. //if(flag&0x2)floor
  575. if(flag&0x4)part.part_flag|=MSHP_HIDDEN;
  576. }
  577. Bool MeshPart::loadData(File &f, CChar *path)
  578. {
  579. del(); switch(f.decUIntV()) // version
  580. {
  581. case 7:
  582. {
  583. f.getStr(name).getMulti(part_flag, _vtx_heightmap, _draw_mask, _draw_mask_enum_id);
  584. _materials[0].require(f.getAssetID(), path);
  585. _materials[1].require(f.getAssetID(), path);
  586. _materials[2].require(f.getAssetID(), path);
  587. if(_variation .load(f, path))
  588. if(_variations.load(f, path))
  589. if( base .loadData(f))
  590. if( render .loadData(f))
  591. if(f.ok()){setUMM().setShader(0); return true;}
  592. }break;
  593. case 6:
  594. {
  595. f._getStr2(name).getMulti(part_flag, _vtx_heightmap, _draw_mask, _draw_mask_enum_id);
  596. _materials[0].require(f.getAssetID(), path);
  597. _materials[1].require(f.getAssetID(), path);
  598. _materials[2].require(f.getAssetID(), path);
  599. if(_variation .load(f, path))
  600. if(_variations.load(f, path))
  601. if( base .loadData(f))
  602. if( render .loadData(f))
  603. if(f.ok()){setUMM().setShader(0); return true;}
  604. }break;
  605. case 5:
  606. {
  607. f>>name; f.getMulti(part_flag, _vtx_heightmap, _draw_mask, _draw_mask_enum_id);
  608. _materials[0].require(f.getAssetID(), path);
  609. _materials[1].require(f.getAssetID(), path);
  610. _materials[2].require(f.getAssetID(), path);
  611. if(_variation .load(f, path))
  612. if(_variations.load(f, path))
  613. if( base .loadData(f))
  614. if( render .loadData(f))
  615. if(f.ok()){setUMM().setShader(0); return true;}
  616. }break;
  617. case 4:
  618. {
  619. f>>name; f.getMulti(part_flag, _vtx_heightmap, _draw_mask, _draw_mask_enum_id);
  620. _variation.material .require(f._getStr(), path);
  621. _materials[0].require(f._getStr(), path);
  622. _materials[1].require(f._getStr(), path);
  623. _materials[2].require(f._getStr(), path);
  624. if(base .loadData(f))
  625. if(render.loadData(f))
  626. if(f.ok()){setUMM().setShader(0); return true;}
  627. }break;
  628. case 3:
  629. {
  630. f>>name; f.skip(1); SetOldFlag(T, f.getByte()); f>>_vtx_heightmap;
  631. _variation.material .require(f._getStr(), path);
  632. _materials[0].require(f._getStr(), path);
  633. _materials[1].require(f._getStr(), path);
  634. _materials[2].require(f._getStr(), path);
  635. if(base .loadData(f))
  636. if(render.loadData(f))
  637. if(f.ok()){setUMM().setShader(0); return true;}
  638. }break;
  639. case 2:
  640. {
  641. f>>name; f.skip(1); SetOldFlag(T, f.getByte()); f.skip(1); f>>_vtx_heightmap; f.skip(20);
  642. _variation.material .require(f._getStr(), path);
  643. _materials[0].require(f._getStr(), path);
  644. _materials[1].require(f._getStr(), path);
  645. _materials[2].require(f._getStr(), path);
  646. if(base .loadData(f))
  647. if(render.loadData(f))
  648. if(f.ok()){setUMM().setShader(0); return true;}
  649. }break;
  650. case 1:
  651. {
  652. f>>name; f.skip(1); SetOldFlag(T, f.getByte()); f.skip(20);
  653. _variation.material .require(f._getStr(), path);
  654. _materials[0].require(f._getStr(), path);
  655. _materials[1].require(f._getStr(), path);
  656. _materials[2].require(f._getStr(), path);
  657. if(base .loadData(f))
  658. if(render.loadData(f))
  659. if(f.ok()){setUMM().setShader(0); return true;}
  660. }break;
  661. case 0:
  662. {
  663. Char8 name[16]; f>>name; f.skip(1); SetOldFlag(T, f.getByte()); f.skip(20); Set(T.name, name);
  664. _variation.material .require(f._getStr8(), path);
  665. _materials[0].require(f._getStr8(), path);
  666. _materials[1].require(f._getStr8(), path);
  667. _materials[2].require(f._getStr8(), path);
  668. if(base .loadData(f))
  669. if(render.loadData(f))
  670. if(f.ok()){setUMM().setShader(0); return true;}
  671. }break;
  672. }
  673. del(); return false;
  674. }
  675. Bool MeshPart::loadOld(File &f, CChar *path)
  676. {
  677. del();
  678. Char8 name[16]; f>>name; f.skip(1); SetOldFlag(T, f.getByte()); Set(T.name, name);
  679. _variation.material .require(f._getStr8(), path);
  680. _materials[0].require(f._getStr8(), path);
  681. _materials[1].require(f._getStr8(), path);
  682. _materials[2].require(f._getStr8(), path);
  683. if(base .loadData(f))
  684. if(render.loadData(f))
  685. if(f.ok()){setUMM().setShader(0); return true;}
  686. del(); return false;
  687. }
  688. Bool MeshPart::loadOld0(File &f, CChar *path)
  689. {
  690. del();
  691. Char8 name[16], material[80];
  692. f>>name; f.skip(1); SetOldFlag(T, f.getByte()); f>>material;
  693. Set(T.name, name); _variation.material.require(material, path);
  694. if(base .loadData(f))
  695. if(render.loadData(f))
  696. if(f.ok()){setUMM().setShader(0); return true;}
  697. del(); return false;
  698. }
  699. Bool MeshPart::save(File &f, CChar *path)C { f.putUInt( CC4_MSHP); return saveData(f, path); }
  700. Bool MeshPart::load(File &f, CChar *path) {if(f.getUInt()==CC4_MSHP) return loadData(f, path); del(); return false;}
  701. /******************************************************************************/
  702. // MSHL
  703. /******************************************************************************/
  704. Bool MeshLod::saveData(File &f, CChar *path)C
  705. {
  706. f.putMulti(Byte(0), Int(parts.elms()), dist2); // version
  707. FREPA(T)if(!parts[i].saveData(f, path))return false;
  708. return f.ok();
  709. }
  710. Bool MeshLod::loadData(File &f, CChar *path)
  711. {
  712. switch(f.decUIntV()) // version
  713. {
  714. case 0:
  715. {
  716. create(f.getInt());
  717. f>>dist2;
  718. FREPA(T)if(!parts[i].loadData(f, path))goto error;
  719. if(f.ok())return true;
  720. }break;
  721. }
  722. error:
  723. del(); return false;
  724. }
  725. Bool MeshLod::loadOld(File &f, CChar *path)
  726. {
  727. create(f.getInt());
  728. FREPA(T)if(!parts[i].loadOld(f, path))goto error;
  729. if(f.ok())return true;
  730. error:
  731. del(); return false;
  732. }
  733. Bool MeshLod::save(File &f, CChar *path)C { f.putUInt( CC4_MSHL); return saveData(f); }
  734. Bool MeshLod::load(File &f, CChar *path) {if(f.getUInt()==CC4_MSHL) return loadData(f); del(); return false;}
  735. /******************************************************************************/
  736. // MESH
  737. /******************************************************************************/
  738. Bool Mesh::saveData(File &f, CChar *path)C
  739. {
  740. f.putMulti(Byte(8), ext, lod_center); // version
  741. if(_bone_map .save(f))
  742. if(_variations.save(f))
  743. {
  744. f.cmpUIntV(_lods.elms()); FREP(lods())if(!lod(i).saveData(f, path))return false;
  745. f.putAsset(Enums .id(drawGroupEnum())); // save after LOD's, so when loading and setting 'drawGroupEnum' it can operate on LOD's
  746. f.putAsset(Skeletons.id(skeleton ())); // save after LOD's, so when loading and setting 'skeleton' it can operate on LOD's
  747. return f.ok();
  748. }
  749. return false;
  750. }
  751. Bool Mesh::loadData(File &f, CChar *path)
  752. {
  753. Box box; del(); switch(f.decUIntV()) // version
  754. {
  755. case 8:
  756. {
  757. f.getMulti(ext, lod_center);
  758. if(!_bone_map .load(f))goto error;
  759. if(!_variations.load(f))goto error;
  760. _lods.setNum(f.decUIntV()); FREP(lods())if(!lod(i).loadData(f, path))goto error;
  761. drawGroupEnum(Enums (f.getAssetID(), path), false);
  762. skeleton (Skeletons(f.getAssetID(), path));
  763. }break;
  764. case 7:
  765. {
  766. f.getMulti(box, lod_center); ext=box;
  767. _lods.setNum(f.decUIntV()); FREP(lods())if(!lod(i).loadData(f, path))goto error;
  768. if(!_bone_map .load(f))goto error;
  769. if(!_variations.load(f))goto error;
  770. skeleton (Skeletons(f.getAssetID(), path));
  771. drawGroupEnum(Enums (f.getAssetID(), path), false);
  772. }break;
  773. case 6:
  774. {
  775. f.getMulti(box, lod_center); ext=box;
  776. _lods.setNum(f.decUIntV()); FREP(lods())if(!lod(i).loadData(f, path))goto error;
  777. if(!_bone_map .loadOld1(f))goto error;
  778. if(!_variations.load (f))goto error;
  779. skeleton (Skeletons(f.getAssetID(), path));
  780. drawGroupEnum(Enums (f.getAssetID(), path), false);
  781. }break;
  782. case 5:
  783. {
  784. f.getMulti(box, lod_center); ext=box;
  785. _lods.setNum(f.getByte()); FREP(lods())if(!lod(i).loadData(f, path))goto error;
  786. if(!_bone_map.loadOld(f))goto error;
  787. skeleton (Skeletons(f._getStr(), path));
  788. drawGroupEnum(Enums (f._getStr(), path), false);
  789. }break;
  790. case 4:
  791. {
  792. f>>box>>lod_center; ext=box;
  793. _lods.setNum(f.getByte()); FREP(lods())if(!lod(i).loadData(f, path))goto error;
  794. if(!_bone_map.loadOld(f))goto error;
  795. skeleton(Skeletons(f._getStr(), path));
  796. }break;
  797. case 3:
  798. {
  799. f>>box>>lod_center; ext=box;
  800. _lods.setNum(f.getByte()); FREP(lods())if(!lod(i).loadData(f, path))goto error;
  801. }break;
  802. case 2:
  803. {
  804. f.getByte();
  805. f>>box; ext=box; lod_center=ext.pos;
  806. _lods.setNum(f.getByte()); FREP(lods())if(!lod(i).loadData(f, path))goto error;
  807. }break;
  808. case 1:
  809. {
  810. f.getByte();
  811. f>>box; ext=box; lod_center=ext.pos;
  812. _lods.setNum(f.getByte()); FREP(lods())if(!lod(i).loadOld(f, path))goto error;
  813. }break;
  814. case 0:
  815. {
  816. f.getByte();
  817. create(f.getInt());
  818. f>>box; ext=box; lod_center=ext.pos;
  819. FREPA(parts)if(!parts[i].loadOld0(f))goto error;
  820. }break;
  821. default: goto error;
  822. }
  823. if(f.ok())
  824. {
  825. if(App.flag&APP_AUTO_FREE_MESH_OPEN_GL_ES_DATA)freeOpenGLESData();
  826. REPAO(_lods).setShader(i+1); // by default all shaders were set with lod_index=0, so now reset them with correct index
  827. return true;
  828. }
  829. error:;
  830. del(); return false;
  831. }
  832. /******************************************************************************/
  833. Bool Mesh::save(File &f, CChar *path)C
  834. {
  835. f.putUInt(CC4_MESH);
  836. return saveData(f, path);
  837. }
  838. Bool Mesh::load(File &f, CChar *path)
  839. {
  840. switch(f.getUInt()) // type of mesh
  841. {
  842. case CC4_MESH: return loadData(f, path);
  843. case CC4_MSHB: if(create(1).parts[0].base.loadData(f))
  844. {
  845. setBox();
  846. return true;
  847. }break;
  848. case CC4_MSHR: if(create(1).parts[0].render.loadData(f))
  849. {
  850. setBox();
  851. return true;
  852. }break;
  853. case CC4_MSHL: if(del().MeshLod::loadData(f, path))
  854. {
  855. setBox();
  856. return true;
  857. }break;
  858. case CC4_MSHG:
  859. {
  860. MeshGroup mshg; if(mshg.loadData(f, path))
  861. {
  862. create(mshg);
  863. return true;
  864. }
  865. }break;
  866. }
  867. del(); return false;
  868. }
  869. Bool Mesh::save(C Str &name)C
  870. {
  871. File f; if(f.writeTry(name)){if(save(f, _GetPath(name)) && f.flush())return true; f.del(); FDelFile(name);}
  872. return false;
  873. }
  874. Bool Mesh::load(C Str &name)
  875. {
  876. File f; if(f.readTry(name))return load(f, _GetPath(name));
  877. del(); return false;
  878. }
  879. /******************************************************************************/
  880. // MESH GROUP
  881. /******************************************************************************/
  882. Bool MeshGroup::saveData(File &f, CChar *path)C
  883. {
  884. f.putMulti(Byte(3), ext); // version
  885. f.cmpUIntV(meshes.elms()); FREPA(T)if(!meshes[i].saveData(f, path))return false;
  886. return f.ok();
  887. }
  888. /******************************************************************************/
  889. Bool MeshGroup::loadData(File &f, CChar *path)
  890. {
  891. Box box; switch(f.decUIntV()) // version
  892. {
  893. case 3:
  894. {
  895. f>>ext;
  896. meshes.setNum(f.decUIntV()); FREPA(T)if(!meshes[i].loadData(f, path))goto error;
  897. if(f.ok())return true;
  898. }break;
  899. case 2:
  900. {
  901. f>>box; ext=box;
  902. meshes.setNum(f.decUIntV()); FREPA(T)if(!meshes[i].loadData(f, path))goto error;
  903. if(f.ok())return true;
  904. }break;
  905. case 1:
  906. {
  907. f>>box; ext=box;
  908. meshes.setNum(f.decUIntV()); FREPA(T)
  909. {
  910. Mesh &mesh=meshes[i];
  911. if(f.decUIntV()==0)if(mesh.loadData(f, path))
  912. {
  913. mesh.variationKeep(mesh.variationFind(f.getUInt()));
  914. continue;
  915. }
  916. goto error;
  917. }
  918. if(f.ok())return true;
  919. }break;
  920. case 0:
  921. {
  922. f.getByte(); // old U16 version part
  923. meshes.setNum(f.getInt());
  924. f>>box; ext=box;
  925. FREPA(T)if(!meshes[i].loadData(f, path))goto error;
  926. if(f.ok())return true;
  927. }break;
  928. }
  929. error:
  930. del(); return false;
  931. }
  932. /******************************************************************************/
  933. Bool MeshGroup::save(File &f, CChar *path)C
  934. {
  935. f.putUInt(CC4_MSHG);
  936. return saveData(f, path);
  937. }
  938. Bool MeshGroup::load(File &f, CChar *path)
  939. {
  940. switch(f.getUInt())
  941. {
  942. case CC4_MSHG: return loadData(f, path);
  943. case CC4_MESH: if(del().meshes.New().loadData(f, path))
  944. {
  945. ext=meshes[0].ext;
  946. return true;
  947. }break;
  948. }
  949. del(); return false;
  950. }
  951. Bool MeshGroup::loadAdd(File &f, CChar *path)
  952. {
  953. if(!meshes.elms())return load(f, path);
  954. MeshGroup mshg; if(mshg.load(f, path))
  955. {
  956. if(mshg.meshes.elms())
  957. {
  958. ext|=mshg.ext;
  959. Int start=meshes.addNum(mshg.meshes.elms());
  960. FREPA(mshg)Swap(meshes[start+i], mshg.meshes[i]);
  961. }
  962. return true;
  963. }
  964. return false;
  965. }
  966. Bool MeshGroup::save(C Str &name)C
  967. {
  968. File f; if(f.writeTry(name)){if(save(f, _GetPath(name)) && f.flush())return true; f.del(); FDelFile(name);}
  969. return false;
  970. }
  971. Bool MeshGroup::load(C Str &name)
  972. {
  973. File f; if(f.readTry(name))return load(f, _GetPath(name));
  974. del(); return false;
  975. }
  976. /******************************************************************************/
  977. // MSHB TXT
  978. /******************************************************************************
  979. Bool MeshBase::saveTxt(FileText &f)C
  980. {
  981. Int temp=PrecisionFlt; PrecisionFlt=9;
  982. if(vtxs ())f.put("vtxs = ", vtxs ());
  983. if(edges())f.put("edges = ", edges());
  984. if(tris ())f.put("tris = ", tris ());
  985. if(quads())f.put("quads = ", quads());
  986. if(vtx.pos ()){f.putLine("VTX_POS" ); f++; FREPA(vtx)f.put(S, vtx.pos (i)); f--;}
  987. if(vtx.nrm ()){f.putLine("VTX_NRM" ); f++; FREPA(vtx)f.put(S, vtx.nrm (i)); f--;}
  988. if(vtx.tan ()){f.putLine("VTX_TAN" ); f++; FREPA(vtx)f.put(S, vtx.tan (i)); f--;}
  989. if(vtx.bin ()){f.putLine("VTX_BIN" ); f++; FREPA(vtx)f.put(S, vtx.bin (i)); f--;}
  990. if(vtx.hlp ()){f.putLine("VTX_HLP" ); f++; FREPA(vtx)f.put(S, vtx.hlp (i)); f--;}
  991. if(vtx.tex0 ()){f.putLine("VTX_TEX0" ); f++; FREPA(vtx)f.put(S, vtx.tex0 (i)); f--;}
  992. if(vtx.tex1 ()){f.putLine("VTX_TEX1" ); f++; FREPA(vtx)f.put(S, vtx.tex1 (i)); f--;}
  993. if(vtx.tex2 ()){f.putLine("VTX_TEX2" ); f++; FREPA(vtx)f.put(S, vtx.tex2 (i)); f--;}
  994. if(vtx.matrix ()){f.putLine("VTX_MATRIX" ); f++; FREPA(vtx)f.put(S, vtx.matrix (i)); f--;}
  995. if(vtx.blend ()){f.putLine("VTX_BLEND" ); f++; FREPA(vtx)f.put(S, vtx.blend (i)); f--;}
  996. if(vtx.size ()){f.putLine("VTX_SIZE" ); f++; FREPA(vtx)f.put(S, vtx.size (i)); f--;}
  997. if(vtx.material()){f.putLine("VTX_MATERIAL"); f++; FREPA(vtx)f.put(S, vtx.material(i)); f--;}
  998. if(vtx.color ()){f.putLine("VTX_COLOR" ); f++; FREPA(vtx)f.put(S, vtx.color (i)); f--;}
  999. if(vtx.flag ()){f.putLine("VTX_FLAG" ); f++; FREPA(vtx)f.put(S, vtx.flag (i)); f--;}
  1000. if(edge.ind ()){f.putLine("EDGE_IND" ); f++; FREPA(edge)f.put(S, edge.ind (i)); f--;}
  1001. if(edge.nrm ()){f.putLine("EDGE_NRM" ); f++; FREPA(edge)f.put(S, edge.nrm (i)); f--;}
  1002. if(edge.flag()){f.putLine("EDGE_FLAG"); f++; FREPA(edge)f.put(S, edge.flag(i)); f--;}
  1003. if(edge.id ()){f.putLine("EDGE_ID" ); f++; FREPA(edge)f.put(S, edge.id (i)); f--;}
  1004. if(tri.ind ()){f.putLine("TRI_IND" ); f++; FREPA(tri)f.put(S, tri.ind (i)); f--;}
  1005. if(tri.nrm ()){f.putLine("TRI_NRM" ); f++; FREPA(tri)f.put(S, tri.nrm (i)); f--;}
  1006. if(tri.flag()){f.putLine("TRI_FLAG"); f++; FREPA(tri)f.put(S, tri.flag(i)); f--;}
  1007. if(tri.id ()){f.putLine("TRI_ID" ); f++; FREPA(tri)f.put(S, tri.id (i)); f--;}
  1008. if(quad.ind ()){f.putLine("QUAD_IND" ); f++; FREPA(quad)f.put(S, quad.ind (i)); f--;}
  1009. if(quad.nrm ()){f.putLine("QUAD_NRM" ); f++; FREPA(quad)f.put(S, quad.nrm (i)); f--;}
  1010. if(quad.flag()){f.putLine("QUAD_FLAG"); f++; FREPA(quad)f.put(S, quad.flag(i)); f--;}
  1011. if(quad.id ()){f.putLine("QUAD_ID" ); f++; FREPA(quad)f.put(S, quad.id (i)); f--;}
  1012. PrecisionFlt=temp;
  1013. return true;
  1014. }
  1015. Bool MeshBase::loadTxt(FileText &f)
  1016. {
  1017. del(); for(; f.level(); )
  1018. {
  1019. if(f.cur("vtxs" )){exclude( VTX_ALL); f.get(vtx ._elms);}else
  1020. if(f.cur("edges")){exclude(EDGE_ALL); f.get(edge._elms);}else
  1021. if(f.cur("tris" )){exclude( TRI_ALL); f.get(tri ._elms);}else
  1022. if(f.cur("quads")){exclude(QUAD_ALL); f.get(quad._elms);}else
  1023. if(f.cur("VTX_POS" ) && f.getIn()){include(VTX_POS ); FREPA(vtx)f.get(vtx.pos (i)); f.getOut();}else
  1024. if(f.cur("VTX_NRM" ) && f.getIn()){include(VTX_NRM ); FREPA(vtx)f.get(vtx.nrm (i)); f.getOut();}else
  1025. if(f.cur("VTX_TAN" ) && f.getIn()){include(VTX_TAN ); FREPA(vtx)f.get(vtx.tan (i)); f.getOut();}else
  1026. if(f.cur("VTX_BIN" ) && f.getIn()){include(VTX_BIN ); FREPA(vtx)f.get(vtx.bin (i)); f.getOut();}else
  1027. if(f.cur("VTX_HLP" ) && f.getIn()){include(VTX_HLP ); FREPA(vtx)f.get(vtx.hlp (i)); f.getOut();}else
  1028. if(f.cur("VTX_TEX0" ) && f.getIn()){include(VTX_TEX0 ); FREPA(vtx)f.get(vtx.tex0 (i)); f.getOut();}else
  1029. if(f.cur("VTX_TEX1" ) && f.getIn()){include(VTX_TEX1 ); FREPA(vtx)f.get(vtx.tex1 (i)); f.getOut();}else
  1030. if(f.cur("VTX_TEX2" ) && f.getIn()){include(VTX_TEX2 ); FREPA(vtx)f.get(vtx.tex2 (i)); f.getOut();}else
  1031. if(f.cur("VTX_MATRIX" ) && f.getIn()){include(VTX_MATRIX ); FREPA(vtx)f.get(vtx.matrix (i)); f.getOut();}else
  1032. if(f.cur("VTX_BLEND" ) && f.getIn()){include(VTX_BLEND ); FREPA(vtx)f.get(vtx.blend (i)); f.getOut();}else
  1033. if(f.cur("VTX_SIZE" ) && f.getIn()){include(VTX_SIZE ); FREPA(vtx)f.get(vtx.size (i)); f.getOut();}else
  1034. if(f.cur("VTX_MATERIAL") && f.getIn()){include(VTX_MATERIAL); FREPA(vtx)f.get(vtx.material(i)); f.getOut();}else
  1035. if(f.cur("VTX_COLOR" ) && f.getIn()){include(VTX_COLOR ); FREPA(vtx)f.get(vtx.color (i)); f.getOut();}else
  1036. if(f.cur("VTX_FLAG" ) && f.getIn()){include(VTX_FLAG ); FREPA(vtx)f.get(vtx.flag (i)); f.getOut();}else
  1037. if(f.cur("EDGE_IND") && f.getIn()){include(EDGE_IND); FREPA(edge)f.get(edge.ind(i)); f.getOut();}else
  1038. if(f.cur("EDGE_NRM") && f.getIn()){include(EDGE_NRM); FREPA(edge)f.get(edge.nrm(i)); f.getOut();}else
  1039. if(f.cur("EDGE_ID" ) && f.getIn()){include(EDGE_ID ); FREPA(edge)f.get(edge.id (i)); f.getOut();}else
  1040. if(f.cur("TRI_IND") && f.getIn()){include(TRI_IND); FREPA(tri)f.get(tri.ind(i)); f.getOut();}else
  1041. if(f.cur("TRI_NRM") && f.getIn()){include(TRI_NRM); FREPA(tri)f.get(tri.nrm(i)); f.getOut();}else
  1042. if(f.cur("TRI_ID" ) && f.getIn()){include(TRI_ID ); FREPA(tri)f.get(tri.id (i)); f.getOut();}else
  1043. if(f.cur("QUAD_IND") && f.getIn()){include(QUAD_IND); FREPA(quad)f.get(quad.ind(i)); f.getOut();}else
  1044. if(f.cur("QUAD_NRM") && f.getIn()){include(QUAD_NRM); FREPA(quad)f.get(quad.nrm(i)); f.getOut();}else
  1045. if(f.cur("QUAD_ID" ) && f.getIn()){include(QUAD_ID ); FREPA(quad)f.get(quad.id (i)); f.getOut();}else
  1046. if(f.cur("EDGE_FLAG") && f.getIn()){include(EDGE_FLAG); FREPA(edge)edge.flag(i)=f.getUInt(); f.getOut();}else
  1047. if(f.cur( "TRI_FLAG") && f.getIn()){include( TRI_FLAG); FREPA(tri )tri .flag(i)=f.getUInt(); f.getOut();}else
  1048. if(f.cur("QUAD_FLAG") && f.getIn()){include(QUAD_FLAG); FREPA(quad)quad.flag(i)=f.getUInt(); f.getOut();}
  1049. }
  1050. return false;
  1051. }
  1052. Bool MeshBase::saveTxt(C Str &name)C
  1053. {
  1054. FileText f; if(f.write(name))
  1055. {
  1056. f.putLine("MeshBase");
  1057. f++;
  1058. Bool ok=saveTxt(f);
  1059. f--;
  1060. return ok;
  1061. }
  1062. return false;
  1063. }
  1064. Bool MeshBase::loadTxt(C Str &name)
  1065. {
  1066. FileText f; if(f.read(name))for(; f.level(); )if(f.cur("MeshBase") && f.getIn())return loadTxt(f);
  1067. del(); return false;
  1068. }
  1069. /******************************************************************************/
  1070. // MSHP TXT
  1071. /******************************************************************************
  1072. Bool MeshPart::saveTxt(FileText &f, CChar *path)C
  1073. {
  1074. f.putName("name = ", name);
  1075. f.put ("flag = ", flag);
  1076. if(_material[0])f.putName("material[0] = ", _material[0].name(path));
  1077. if(_material[1])f.putName("material[1] = ", _material[1].name(path));
  1078. if(_material[2])f.putName("material[2] = ", _material[2].name(path));
  1079. if(_material[3])f.putName("material[3] = ", _material[3].name(path));
  1080. f.putLine("MeshBase");
  1081. f++;
  1082. Bool ok=base.saveTxt(f);
  1083. f--;
  1084. return ok;
  1085. }
  1086. Bool MeshPart::loadTxt(FileText &f, CChar *path)
  1087. {
  1088. del();
  1089. for(; f.level(); )
  1090. {
  1091. if(f.cur("name"))Set(name, f.getName());else
  1092. if(f.cur("flag")) flag= f.getInt () ;else
  1093. if(f.cur("material[0]") || f.cur("material"))_material[0].require(f.getName(), path);else
  1094. if(f.cur("material[1]") )_material[1].require(f.getName(), path);else
  1095. if(f.cur("material[2]") )_material[2].require(f.getName(), path);else
  1096. if(f.cur("material[3]") )_material[3].require(f.getName(), path);else
  1097. if(f.cur("MeshBase") && f.getIn())base.loadTxt(f);
  1098. }
  1099. setUMM().setShader(0);
  1100. return true;
  1101. }
  1102. /******************************************************************************/
  1103. // MESH TXT
  1104. /******************************************************************************
  1105. void Mesh::saveTxt(FileText &f, CChar *path)C
  1106. {
  1107. f.put("parts = ", parts.elms());
  1108. f.put("box = ", box );
  1109. f.put("lod_center = ", lod_center );
  1110. FREPA(parts)
  1111. {
  1112. f.putLine("MeshPart");
  1113. f++;
  1114. parts[i].saveTxt(f, path);
  1115. f--;
  1116. }
  1117. }
  1118. /******************************************************************************
  1119. void Mesh::loadTxt(FileText &f, CChar *path)
  1120. {
  1121. del();
  1122. Bool is_box =false,
  1123. is_lod_center=false;
  1124. for(; f.level(); )
  1125. {
  1126. if(f.cur("box" )){f.get(box ); is_box =true;}else
  1127. if(f.cur("lod_center")){f.get(lod_center); is_lod_center=true;}else
  1128. if(f.cur("MeshPart" ) && f.getIn())parts.New().loadTxt(f, path);
  1129. }
  1130. if(!is_box )setBox();
  1131. if(!is_lod_center)lod_center=box.center();
  1132. }
  1133. /******************************************************************************
  1134. Bool Mesh::saveTxt(C Str &name)C
  1135. {
  1136. FileText f; if(f.write(name))
  1137. {
  1138. f.putLine("Mesh");
  1139. f++;
  1140. saveTxt(f, _GetPath(name));
  1141. f--;
  1142. return true;
  1143. }
  1144. return false;
  1145. }
  1146. /******************************************************************************
  1147. Bool Mesh::loadTxt(C Str &name)
  1148. {
  1149. FileText f; if(f.read(name))for(; f.level(); )if(f.cur("Mesh") && f.getIn())
  1150. {
  1151. loadTxt(f, _GetPath(name));
  1152. return true;
  1153. }
  1154. del(); return false;
  1155. }
  1156. /******************************************************************************/
  1157. // MSHG TXT
  1158. /******************************************************************************
  1159. void MeshGroup::saveTxt(FileText &f, CChar *path)C
  1160. {
  1161. f.put("meshes = ", meshes.elms());
  1162. f.put("box = ", box );
  1163. FREPA(T)
  1164. {
  1165. f.putLine("Mesh");
  1166. f++;
  1167. meshes[i].saveTxt(f, path);
  1168. f--;
  1169. }
  1170. }
  1171. /******************************************************************************
  1172. void MeshGroup::loadTxt(FileText &f, CChar *path)
  1173. {
  1174. del();
  1175. for(; f.level(); )
  1176. {
  1177. if(f.cur("Mesh") && f.getIn())meshes.New().loadTxt(f, path);
  1178. }
  1179. setBox(false);
  1180. }
  1181. /******************************************************************************
  1182. Bool MeshGroup::saveTxt(C Str &name)C
  1183. {
  1184. FileText f; if(f.write(name))
  1185. {
  1186. f.putLine("MeshGroup");
  1187. f++;
  1188. saveTxt(f, _GetPath(name));
  1189. f--;
  1190. return true;
  1191. }
  1192. return false;
  1193. }
  1194. /******************************************************************************
  1195. Bool MeshGroup::loadTxt(C Str &name)
  1196. {
  1197. FileText f; if(f.read(name))for(; f.level(); )if(f.cur("MeshGroup") && f.getIn())
  1198. {
  1199. loadTxt(f, _GetPath(name));
  1200. return true;
  1201. }
  1202. del(); return false;
  1203. }
  1204. /******************************************************************************/
  1205. void MeshBase ::operator=(C Str &name) {if(!load(name))Exit(MLT(S+"Can't load mesh \""+name+"\"", PL,S+u"Nie można wczytać modelu \""+name+"\""));}
  1206. void MeshRender::operator=(C Str &name) {if(!load(name))Exit(MLT(S+"Can't load mesh \""+name+"\"", PL,S+u"Nie można wczytać modelu \""+name+"\""));}
  1207. void Mesh ::operator=(C Str &name) {if(!load(name))Exit(MLT(S+"Can't load mesh \""+name+"\"", PL,S+u"Nie można wczytać modelu \""+name+"\""));}
  1208. void MeshGroup ::operator=(C Str &name) {if(!load(name))Exit(MLT(S+"Can't load mesh \""+name+"\"", PL,S+u"Nie można wczytać modelu \""+name+"\""));}
  1209. /******************************************************************************/
  1210. // IMPORT
  1211. /******************************************************************************/
  1212. Bool Import(C Str &name, Mesh *mesh, Skeleton *skeleton, MemPtr<XAnimation> animations, MemPtr<XMaterial> materials, MemPtr<Int> part_material_index, MemPtr<Str> bone_names, Bool all_nodes_as_bones)
  1213. {
  1214. if(mesh )mesh ->del();
  1215. if(skeleton)skeleton->del();
  1216. animations .clear();
  1217. materials .clear();
  1218. part_material_index.clear();
  1219. bone_names .clear();
  1220. Str ext=GetExt(name);
  1221. if(ext=="fbx" )return ImportFBX(name, mesh, skeleton, animations, materials, part_material_index, bone_names, all_nodes_as_bones);
  1222. if(ext=="obj" )return ImportOBJ(name, mesh, materials, part_material_index);
  1223. if(ext=="mesh" || ext=="mshb" || ext=="mshr" || ext=="mshg")
  1224. {
  1225. if(mesh && mesh->load(name))
  1226. {
  1227. if(mesh->skeleton())if(CChar *skel_name=Skeletons.name(mesh->skeleton())){mesh->skeleton()->load(skel_name); mesh->skeleton(mesh->skeleton());} // because Import is used to load/reload, and because Skeleton is cached, then force reload skeleton from file, because it's possible that skel file was changed, however due to caching it will not be reloaded
  1228. if(skeleton && mesh->skeleton())*skeleton=*mesh->skeleton();
  1229. if(materials || part_material_index)
  1230. {
  1231. Memt<Material*> mesh_mtrls;
  1232. FREPD(l, mesh->lods()) // gather all materials
  1233. {
  1234. C MeshLod &lod=mesh->lod(l);
  1235. FREPA(lod)if(Material *m=lod.parts[i].material()())mesh_mtrls.include(m);
  1236. }
  1237. if(materials)FREPA(mesh_mtrls) // create 'XMaterial's
  1238. {
  1239. XMaterial &xm=materials.New();
  1240. xm.createFrom(*mesh_mtrls[i]);
  1241. xm.name=GetBaseNoExt(Materials.name(mesh_mtrls[i]));
  1242. }
  1243. if(part_material_index)FREPD(l, mesh->lods()) // set 'part_material_index'
  1244. {
  1245. C MeshLod &lod=mesh->lod(l);
  1246. FREPA(lod)part_material_index.add(mesh_mtrls.find(lod.parts[i].material()()));
  1247. }
  1248. }
  1249. return true;
  1250. }
  1251. }else
  1252. if(ext=="skel"){if(skeleton)return skeleton->load(name);}else
  1253. if(ext=="anim"){if(animations && animations.New().anim.load(name)){animations.last().name=GetBaseNoExt(name); return true;}}else
  1254. if(ext=="mtrl")
  1255. {
  1256. Material mtrl; if(materials)if(mtrl.load(name))
  1257. {
  1258. XMaterial &m=materials.New();
  1259. m.createFrom(mtrl);
  1260. m.name=GetBaseNoExt(name);
  1261. return true;
  1262. }
  1263. }else
  1264. if(ext=="dae")
  1265. {
  1266. if(ImportDAE(name, mesh, skeleton, animations ? &animations.New() : null, materials, part_material_index))
  1267. {
  1268. if(animations.elms() && !animations.first().anim.is())animations.clear();
  1269. return true;
  1270. }
  1271. }else
  1272. if(ext=="b3d")
  1273. {
  1274. if(ImportB3D(name, mesh, skeleton, animations ? &animations.New() : null, materials, part_material_index))
  1275. {
  1276. if(animations.elms() && !animations.first().anim.is())animations.clear();
  1277. return true;
  1278. }
  1279. }else
  1280. if(ext=="ms3d")
  1281. {
  1282. if(ImportMS3D(name, mesh, skeleton, animations ? &animations.New() : null, materials, part_material_index))
  1283. {
  1284. if(animations.elms() && !animations.first().anim.is())animations.clear();
  1285. return true;
  1286. }
  1287. }else
  1288. if(ext=="bvh")
  1289. {
  1290. if(ImportBVH(name, skeleton, animations ? &animations.New() : null))
  1291. {
  1292. if(animations.elms() && !animations.first().anim.is())animations.clear();
  1293. return true;
  1294. }
  1295. }else
  1296. if(ext=="ase" ){return ImportASE(name, mesh, materials, part_material_index);}else
  1297. if(ext=="3ds" ){return Import3DS(name, mesh, materials, part_material_index);}else
  1298. if(ext=="psk" ){return ImportPSK(name, mesh, skeleton, materials, part_material_index);}else
  1299. if(ext=="psa" ){return ImportPSA(name, skeleton, animations );}else
  1300. if(ext=="ascii"){return ImportXPS(name, mesh, skeleton, materials, part_material_index);}
  1301. return false;
  1302. }
  1303. /******************************************************************************
  1304. void RemoveNubBones(Mesh *mesh, Skeleton &skeleton, C MemPtr<Animation*> &animations)
  1305. {
  1306. Memt<Byte, 256> old_to_new;
  1307. REPA(skeleton.bones)
  1308. {
  1309. SkelBone &bone=skeleton.bones[i]; if(Ends(bone.name, "Nub") && !bone.children_num)
  1310. {
  1311. // remove animation bones
  1312. REPAD(a, animations)
  1313. if(Animation *anim=animations[a])
  1314. REPA(anim->bones)
  1315. if(Equal(anim->bones[a].name, bone.name))anim->bones.remove(a, true);
  1316. // remove skeleton bone
  1317. if(skeleton.removeBone(i, old_to_new))
  1318. {
  1319. // adjust mesh vertex skinning
  1320. if(mesh)mesh->boneRemap(old_to_new);
  1321. }
  1322. }
  1323. }
  1324. }
  1325. /******************************************************************************/
  1326. void CleanMesh(Mesh &mesh)
  1327. {
  1328. REPD(l, mesh.lods())
  1329. {
  1330. MeshLod &lod=mesh.lod(l);
  1331. REPA(lod)
  1332. {
  1333. MeshPart &part=lod.parts[i];
  1334. MeshBase &base=part.base;
  1335. if(base.vtx.color())REPA(base.vtx)
  1336. {
  1337. C Color &c=base.vtx.color(i);
  1338. if(c.r<253 || c.g<253 || c.b<253)goto valid_color;
  1339. }
  1340. base.exclude(VTX_COLOR);
  1341. valid_color:;
  1342. }
  1343. }
  1344. }
  1345. /******************************************************************************/
  1346. void ShutMesh() {Meshes.del();}
  1347. /******************************************************************************/
  1348. }
  1349. /******************************************************************************/