Mesh Overlay.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. #define CC4_MSOV CC4('M','S','O','V')
  6. /******************************************************************************/
  7. static void SetBoxAndPlanes(Box &box, Memc<Plane> &planes, Matrix &matrix)
  8. {
  9. box.set(1)*=matrix;
  10. planes.del();
  11. Vec n;
  12. // x
  13. n=matrix.x; n.normalize();
  14. planes.New().set(matrix.pos+matrix.x, n);
  15. planes.New().set(matrix.pos-matrix.x, -n);
  16. // y
  17. n=matrix.y; n.normalize();
  18. planes.New().set(matrix.pos+matrix.y, n);
  19. planes.New().set(matrix.pos-matrix.y, -n);
  20. // z
  21. n=matrix.z; n.normalize();
  22. planes.New().set(matrix.pos+matrix.z, n);
  23. planes.New().set(matrix.pos-matrix.z, -n);
  24. }
  25. static void ClipMeshToPlanes(C Mesh &src, C Matrix *matrix, Mesh &dest, C Plane *clip_plane, Int clip_planes, C Box &box)
  26. {
  27. Mesh temp;
  28. // box test
  29. Vec corner[8]; src.ext.toCorners(corner); if(matrix)Transform(corner, *matrix, Elms(corner));
  30. Bool all_inside=true;
  31. REPD(p, clip_planes)
  32. {
  33. Bool inside=false,
  34. outside=false;
  35. REPAD(c, corner)
  36. {
  37. if(Dist(corner[c], clip_plane[p])<=0)inside=true;else outside=true;
  38. }
  39. if(!inside)goto finished; // if no vertexes are inside the plane then cancel
  40. if(outside)all_inside=false;
  41. }
  42. // create dest
  43. /*if(all_inside) can't be used because it may happen that we're operating on MeshRender
  44. {
  45. temp.create(src, flag_and);
  46. if(matrix)
  47. {
  48. temp.transform(*matrix).setBox();
  49. temp.lod_center=src.lod_center*(*matrix);
  50. }
  51. }else*/
  52. {
  53. Bool poly_cur=0;
  54. Flt scale=(matrix ? matrix->maxScale() : 1);
  55. Memc< Vec> poly[2];
  56. Memc< Memc<Vec> > polys;
  57. temp.copyParams(src);
  58. FREPD(l, src.lods()) // order is important
  59. {
  60. C MeshLod &src_lod=src.lod(l);
  61. REPA(src_lod)
  62. {
  63. // create 'polys' from MeshPart
  64. C MeshPart &part=src_lod.parts[i];
  65. Bool semi_transparent=false; if(part.material())if(part.material()->hasAlpha() || part.material()->technique==MTECH_FUR)semi_transparent=true;
  66. if( !semi_transparent) // don't apply overlays on semi-transparent parts (because it will look like floating in air)
  67. {
  68. if(part.base.is()) // MSHB
  69. {
  70. C Vec *pos=part.base.vtx.pos();
  71. REPA(part.base.tri) // TRI
  72. {
  73. VecI t=part.base.tri.ind(i);
  74. poly[poly_cur].New()=pos[t.x];
  75. poly[poly_cur].New()=pos[t.y];
  76. poly[poly_cur].New()=pos[t.z];
  77. if(matrix)REPAO(poly[poly_cur])*=*matrix;
  78. Box b; b.from(poly[poly_cur].data(), poly[poly_cur].elms());
  79. if(Cuts(b, box))
  80. {
  81. REPD(p, clip_planes)
  82. {
  83. ClipPoly(poly[poly_cur], clip_plane[p], poly[poly_cur^1]); poly_cur^=1;
  84. if(poly[poly_cur].elms()<=2)goto mshb_tri_done;
  85. }
  86. Swap(poly[poly_cur], polys.New());
  87. }
  88. mshb_tri_done:;
  89. poly[0].clear();
  90. poly[1].clear();
  91. }
  92. REPA(part.base.quad) // QUAD
  93. {
  94. VecI4 q=part.base.quad.ind(i);
  95. poly[poly_cur].New()=pos[q.x];
  96. poly[poly_cur].New()=pos[q.y];
  97. poly[poly_cur].New()=pos[q.z];
  98. poly[poly_cur].New()=pos[q.w];
  99. if(matrix)REPAO(poly[poly_cur])*=*matrix;
  100. Box b; b.from(poly[poly_cur].data(), poly[poly_cur].elms());
  101. if(Cuts(b, box))
  102. {
  103. REPD(p, clip_planes)
  104. {
  105. ClipPoly(poly[poly_cur], clip_plane[p], poly[poly_cur^1]); poly_cur^=1;
  106. if(poly[poly_cur].elms()<=2)goto mshb_quad_done;
  107. }
  108. Swap(poly[poly_cur], polys.New());
  109. }
  110. mshb_quad_done:;
  111. poly[0].clear();
  112. poly[1].clear();
  113. }
  114. }else
  115. if(part.render.is()) // MSHR
  116. {
  117. Int vtx_pos=part.render.vtxOfs(VTX_POS);
  118. if( vtx_pos>=0)
  119. if(C Byte *vtx=part.render.vtxLockRead())
  120. {
  121. vtx+=vtx_pos;
  122. if(CPtr ind=part.render.indLockRead())
  123. {
  124. if(part.render._ib.bit16()) // 16 BIT
  125. {
  126. VecUS *tri=(VecUS*)ind;
  127. REP(part.render.tris())
  128. {
  129. VecUS t=tri[i];
  130. poly[poly_cur].New()=*(Vec*)(vtx+t.x*part.render.vtxSize());
  131. poly[poly_cur].New()=*(Vec*)(vtx+t.y*part.render.vtxSize());
  132. poly[poly_cur].New()=*(Vec*)(vtx+t.z*part.render.vtxSize());
  133. if(matrix)REPAO(poly[poly_cur])*=*matrix;
  134. Box b; b.from(poly[poly_cur].data(), poly[poly_cur].elms());
  135. if(Cuts(b, box))
  136. {
  137. REPD(p, clip_planes)
  138. {
  139. ClipPoly(poly[poly_cur], clip_plane[p], poly[poly_cur^1]); poly_cur^=1;
  140. if(poly[poly_cur].elms()<=2)goto mshr_tri16_done;
  141. }
  142. Swap(poly[poly_cur], polys.New());
  143. }
  144. mshr_tri16_done:;
  145. poly[0].clear();
  146. poly[1].clear();
  147. }
  148. }
  149. else // 32 BIT
  150. {
  151. VecI *tri=(VecI*)ind;
  152. REP(part.render.tris())
  153. {
  154. VecI t=tri[i];
  155. poly[poly_cur].New()=*(Vec*)(vtx+t.x*part.render.vtxSize());
  156. poly[poly_cur].New()=*(Vec*)(vtx+t.y*part.render.vtxSize());
  157. poly[poly_cur].New()=*(Vec*)(vtx+t.z*part.render.vtxSize());
  158. if(matrix)REPAO(poly[poly_cur])*=*matrix;
  159. Box b; b.from(poly[poly_cur].data(), poly[poly_cur].elms());
  160. if(Cuts(b, box))
  161. {
  162. REPD(p, clip_planes)
  163. {
  164. ClipPoly(poly[poly_cur], clip_plane[p], poly[poly_cur^1]); poly_cur^=1;
  165. if(poly[poly_cur].elms()<=2)goto mshr_tri32_done;
  166. }
  167. Swap(poly[poly_cur], polys.New());
  168. }
  169. mshr_tri32_done:;
  170. poly[0].clear();
  171. poly[1].clear();
  172. }
  173. }
  174. part.render.indUnlock();
  175. }
  176. part.render.vtxUnlock();
  177. }
  178. }
  179. }
  180. }
  181. // create MeshBase from 'polys'
  182. if(polys.elms())
  183. {
  184. MeshBase mshb; Triangulate(polys, mshb, EPS, true);
  185. polys.clear();
  186. if(mshb.vtxs() && mshb.faces())
  187. {
  188. MeshLod &dest_lod=(temp.parts.elms() ? temp.newLod() : temp);
  189. dest_lod. copyParams(src_lod);
  190. dest_lod.scaleParams(scale );
  191. Swap(mshb, dest_lod.parts.New().base);
  192. }
  193. }
  194. }
  195. temp.setBox();
  196. temp.lod_center=src.lod_center; if(matrix)temp.lod_center*=*matrix;
  197. }
  198. finished:;
  199. Swap(dest, temp);
  200. }
  201. /******************************************************************************/
  202. void MeshOverlay::zero()
  203. {
  204. _lod_center.zero();
  205. _ext .zero();
  206. _matrix .identity();
  207. _shader=null;
  208. }
  209. MeshOverlay::MeshOverlay() {zero();}
  210. MeshOverlay& MeshOverlay::del()
  211. {
  212. _lods .del ();
  213. _material.clear();
  214. zero(); return T;
  215. }
  216. /******************************************************************************/
  217. Bool MeshOverlay::createStatic(C Mesh &mesh, C MaterialPtr &material, C Matrix &overlay_matrix, C Matrix *mesh_matrix)
  218. {
  219. del();
  220. if(mesh.is())
  221. {
  222. _matrix=overlay_matrix;
  223. Memc<Plane> planes;
  224. Box box ; SetBoxAndPlanes(box, planes, _matrix);
  225. Mesh temp ; ClipMeshToPlanes(mesh, mesh_matrix, temp, planes.data(), planes.elms(), box);
  226. if(temp.is())
  227. {
  228. T._lod_center= temp.lod_center;
  229. T._ext = temp.ext;
  230. T._lods.setNum(temp.lods());
  231. FREPD(l, temp.lods()) // order is important
  232. {
  233. MeshBase &mshb=temp.lod(l).parts[0].base;
  234. #if 0
  235. mshb.setNormals(); REPA(mshb.vtx)mshb.vtx.pos[i]+=mshb.vtx.nrm[i]*0.005f; // surface epsilon
  236. #endif
  237. #if 0
  238. mshb.include(VTX_TEX0); REPA(mshb.vtx)mshb.vtx.tex0[i]=_matrix.convert(mshb.vtx.pos[i]); // maybe it will require changing axis length when restored
  239. #endif
  240. _lods[l].dist2=temp.lod(l).dist2;
  241. _lods[l].mshr.create(mshb);
  242. }
  243. T.material(material);
  244. return true;
  245. }
  246. }
  247. return false;
  248. }
  249. Bool MeshOverlay::createAnimated(C Mesh &mesh, C MaterialPtr &material, C Matrix &overlay_matrix, C Matrix *mesh_matrix)
  250. {
  251. del();
  252. if(mesh.is())
  253. {
  254. if(!mesh_matrix)_matrix=overlay_matrix;else
  255. {
  256. mesh_matrix->inverse(_matrix);
  257. overlay_matrix.mul(_matrix, _matrix);
  258. }
  259. Memc<Plane> planes;
  260. Box box ; SetBoxAndPlanes(box, planes, _matrix);
  261. Mesh temp ; ClipMeshToPlanes(mesh, null, temp, planes.data(), planes.elms(), box);
  262. if(temp.is())
  263. {
  264. T._lod_center= temp.lod_center;
  265. T._ext = temp.ext;
  266. T._lods.setNum(temp.lods());
  267. FREPD(l, temp.lods()) // order is important
  268. {
  269. MeshBase &mshb=temp.lod(l).parts[0].base;
  270. #if 0
  271. mshb.setNormals(); REPA(mshb.vtx)mshb.vtx.pos[i]+=mshb.vtx.nrm[i]*0.005f; // surface epsilon
  272. #endif
  273. #if 0
  274. mshb.include(VTX_TEX0); REPA(mshb.vtx)mshb.vtx.tex0[i]=_matrix.convert(mshb.vtx.pos[i]); // maybe it will require changing axis length when restored
  275. #endif
  276. _lods[l].dist2=temp.lod(l).dist2;
  277. _lods[l].mshr.create(mshb);
  278. }
  279. T.material(material);
  280. return true;
  281. }
  282. }
  283. return false;
  284. }
  285. /******************************************************************************/
  286. void MeshOverlay::setShader()
  287. {
  288. _shader=null;
  289. if(_lods.elms() && _material && _material->base_0)_shader=ShaderFiles("Overlay")->get(TechNameOverlay(false, _material->base_1!=null));
  290. }
  291. MeshOverlay& MeshOverlay::material(C MaterialPtr &material)
  292. {
  293. T._material=material;
  294. setShader();
  295. return T;
  296. }
  297. #pragma pack(push, 4)
  298. struct GOverlayClass
  299. {
  300. Vec4 param;
  301. Matrix mtrx ;
  302. };
  303. #pragma pack(pop)
  304. void MeshOverlay::setParams(Flt alpha)C // this is called only inside 'draw' methods, so '_material' is assumed to be != null
  305. {
  306. GOverlayClass overlay_params;
  307. overlay_params.param.set(0.8f, alpha, 0, 0);
  308. overlay_params.mtrx=_matrix;
  309. Sh.h_OverlayParams->set(overlay_params);
  310. _material ->setBlend();
  311. D.depth(true);
  312. D.cull (true);
  313. //D.alpha(ALPHA_BLEND_FACTOR); not needed because ALPHA_BLEND_FACTOR is used everywhere in RM_OVERLAY
  314. /*D.depthWrite(false); not needed because false is used everywhere in RM_OVERLAY*/ Renderer.needDepthTest(); // !! 'needDepthTest' after 'depthWrite' !!
  315. }
  316. /******************************************************************************/
  317. C MeshRender& MeshOverlay::getDrawLod(C Matrix &matrix)C
  318. {
  319. if(_lods.elms()>1)
  320. {
  321. Flt dist2=GetLodDist2(_lod_center, matrix);
  322. REPA(_lods){C Lod &test=_lods[i]; if(dist2>=test.dist2)return test.mshr;}
  323. }
  324. return _lods[0].mshr;
  325. }
  326. C MeshRender& MeshOverlay::getDrawLod(C MatrixM &matrix)C
  327. {
  328. if(_lods.elms()>1)
  329. {
  330. Flt dist2=GetLodDist2(_lod_center, matrix);
  331. REPA(_lods){C Lod &test=_lods[i]; if(dist2>=test.dist2)return test.mshr;}
  332. }
  333. return _lods[0].mshr;
  334. }
  335. /******************************************************************************/
  336. void MeshOverlay::draw(Flt alpha)C
  337. {
  338. if(_shader)
  339. {
  340. setParams(alpha);
  341. _shader->begin(); C MeshRender &mshr=getDrawLod(ObjMatrix); mshr.set().drawFull();
  342. ShaderEnd();
  343. }
  344. }
  345. void MeshOverlay::draw(C MatrixM &matrix, Flt alpha)C
  346. {
  347. if(_shader)
  348. {
  349. SetOneMatrix(matrix);
  350. setParams(alpha);
  351. _shader->begin(); C MeshRender &mshr=getDrawLod(matrix); mshr.set().drawFull();
  352. ShaderEnd();
  353. }
  354. }
  355. void MeshOverlay::draw(C AnimatedSkeleton &anim_skel, Flt alpha)C
  356. {
  357. if(_shader)
  358. {
  359. anim_skel.setMatrix();
  360. setParams(alpha);
  361. _shader->begin(); C MeshRender &mshr=getDrawLod(anim_skel.matrix()); mshr.set(); mshr.draw();
  362. ShaderEnd();
  363. }
  364. }
  365. /******************************************************************************/
  366. Bool MeshOverlay::save(File &f, CChar *path)C
  367. {
  368. f.putMulti(Byte(0), Int(_lods.elms())); // version
  369. if(_lods.elms())
  370. {
  371. f.putMulti(_lod_center, _ext, _matrix);
  372. f.putAsset(_material.id());
  373. FREPA(_lods)
  374. {
  375. f<<_lods[i].dist2;
  376. if(!_lods[i].mshr.saveData(f))return false;
  377. }
  378. }
  379. return f.ok();
  380. }
  381. Bool MeshOverlay::load(File &f, CChar *path)
  382. {
  383. del(); switch(f.decUIntV()) // version
  384. {
  385. case 0:
  386. {
  387. _lods.setNum(f.getInt());
  388. if(_lods.elms())
  389. {
  390. f.getMulti(_lod_center, _ext, _matrix);
  391. _material.require(f.getAssetID(), path);
  392. FREPA(_lods)
  393. {
  394. f>>_lods[i].dist2;
  395. if(!_lods[i].mshr.loadData(f))goto error;
  396. }
  397. setShader();
  398. }
  399. if(f.ok())return true;
  400. }break;
  401. }
  402. error:
  403. del(); return false;
  404. }
  405. /******************************************************************************/
  406. }
  407. /******************************************************************************/