| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- /******************************************************************************/
- #include "stdafx.h"
- namespace EE{
- /******************************************************************************/
- #define CC4_MSOV CC4('M','S','O','V')
- /******************************************************************************/
- static void SetBoxAndPlanes(Box &box, Memc<Plane> &planes, Matrix &matrix)
- {
- box.set(1)*=matrix;
- planes.del();
- Vec n;
- // x
- n=matrix.x; n.normalize();
- planes.New().set(matrix.pos+matrix.x, n);
- planes.New().set(matrix.pos-matrix.x, -n);
- // y
- n=matrix.y; n.normalize();
- planes.New().set(matrix.pos+matrix.y, n);
- planes.New().set(matrix.pos-matrix.y, -n);
- // z
- n=matrix.z; n.normalize();
- planes.New().set(matrix.pos+matrix.z, n);
- planes.New().set(matrix.pos-matrix.z, -n);
- }
- static void ClipMeshToPlanes(C Mesh &src, C Matrix *matrix, Mesh &dest, C Plane *clip_plane, Int clip_planes, C Box &box)
- {
- Mesh temp;
- // box test
- Vec corner[8]; src.ext.toCorners(corner); if(matrix)Transform(corner, *matrix, Elms(corner));
- Bool all_inside=true;
- REPD(p, clip_planes)
- {
- Bool inside=false,
- outside=false;
- REPAD(c, corner)
- {
- if(Dist(corner[c], clip_plane[p])<=0)inside=true;else outside=true;
- }
- if(!inside)goto finished; // if no vertexes are inside the plane then cancel
- if(outside)all_inside=false;
- }
- // create dest
- /*if(all_inside) can't be used because it may happen that we're operating on MeshRender
- {
- temp.create(src, flag_and);
- if(matrix)
- {
- temp.transform(*matrix).setBox();
- temp.lod_center=src.lod_center*(*matrix);
- }
- }else*/
- {
- Bool poly_cur=0;
- Flt scale=(matrix ? matrix->maxScale() : 1);
- Memc< Vec> poly[2];
- Memc< Memc<Vec> > polys;
- temp.copyParams(src);
- FREPD(l, src.lods()) // order is important
- {
- C MeshLod &src_lod=src.lod(l);
- REPA(src_lod)
- {
- // create 'polys' from MeshPart
- C MeshPart &part=src_lod.parts[i];
-
- Bool semi_transparent=false; if(part.material())if(part.material()->hasAlpha() || part.material()->technique==MTECH_FUR)semi_transparent=true;
- if( !semi_transparent) // don't apply overlays on semi-transparent parts (because it will look like floating in air)
- {
- if(part.base.is()) // MSHB
- {
- C Vec *pos=part.base.vtx.pos();
- REPA(part.base.tri) // TRI
- {
- VecI t=part.base.tri.ind(i);
- poly[poly_cur].New()=pos[t.x];
- poly[poly_cur].New()=pos[t.y];
- poly[poly_cur].New()=pos[t.z];
- if(matrix)REPAO(poly[poly_cur])*=*matrix;
- Box b; b.from(poly[poly_cur].data(), poly[poly_cur].elms());
- if(Cuts(b, box))
- {
- REPD(p, clip_planes)
- {
- ClipPoly(poly[poly_cur], clip_plane[p], poly[poly_cur^1]); poly_cur^=1;
- if(poly[poly_cur].elms()<=2)goto mshb_tri_done;
- }
- Swap(poly[poly_cur], polys.New());
- }
- mshb_tri_done:;
- poly[0].clear();
- poly[1].clear();
- }
- REPA(part.base.quad) // QUAD
- {
- VecI4 q=part.base.quad.ind(i);
- poly[poly_cur].New()=pos[q.x];
- poly[poly_cur].New()=pos[q.y];
- poly[poly_cur].New()=pos[q.z];
- poly[poly_cur].New()=pos[q.w];
- if(matrix)REPAO(poly[poly_cur])*=*matrix;
- Box b; b.from(poly[poly_cur].data(), poly[poly_cur].elms());
- if(Cuts(b, box))
- {
- REPD(p, clip_planes)
- {
- ClipPoly(poly[poly_cur], clip_plane[p], poly[poly_cur^1]); poly_cur^=1;
- if(poly[poly_cur].elms()<=2)goto mshb_quad_done;
- }
- Swap(poly[poly_cur], polys.New());
- }
- mshb_quad_done:;
- poly[0].clear();
- poly[1].clear();
- }
- }else
- if(part.render.is()) // MSHR
- {
- Int vtx_pos=part.render.vtxOfs(VTX_POS);
- if( vtx_pos>=0)
- if(C Byte *vtx=part.render.vtxLockRead())
- {
- vtx+=vtx_pos;
- if(CPtr ind=part.render.indLockRead())
- {
- if(part.render._ib.bit16()) // 16 BIT
- {
- VecUS *tri=(VecUS*)ind;
- REP(part.render.tris())
- {
- VecUS t=tri[i];
- poly[poly_cur].New()=*(Vec*)(vtx+t.x*part.render.vtxSize());
- poly[poly_cur].New()=*(Vec*)(vtx+t.y*part.render.vtxSize());
- poly[poly_cur].New()=*(Vec*)(vtx+t.z*part.render.vtxSize());
- if(matrix)REPAO(poly[poly_cur])*=*matrix;
- Box b; b.from(poly[poly_cur].data(), poly[poly_cur].elms());
- if(Cuts(b, box))
- {
- REPD(p, clip_planes)
- {
- ClipPoly(poly[poly_cur], clip_plane[p], poly[poly_cur^1]); poly_cur^=1;
- if(poly[poly_cur].elms()<=2)goto mshr_tri16_done;
- }
- Swap(poly[poly_cur], polys.New());
- }
- mshr_tri16_done:;
- poly[0].clear();
- poly[1].clear();
- }
- }
- else // 32 BIT
- {
- VecI *tri=(VecI*)ind;
- REP(part.render.tris())
- {
- VecI t=tri[i];
- poly[poly_cur].New()=*(Vec*)(vtx+t.x*part.render.vtxSize());
- poly[poly_cur].New()=*(Vec*)(vtx+t.y*part.render.vtxSize());
- poly[poly_cur].New()=*(Vec*)(vtx+t.z*part.render.vtxSize());
- if(matrix)REPAO(poly[poly_cur])*=*matrix;
- Box b; b.from(poly[poly_cur].data(), poly[poly_cur].elms());
- if(Cuts(b, box))
- {
- REPD(p, clip_planes)
- {
- ClipPoly(poly[poly_cur], clip_plane[p], poly[poly_cur^1]); poly_cur^=1;
- if(poly[poly_cur].elms()<=2)goto mshr_tri32_done;
- }
- Swap(poly[poly_cur], polys.New());
- }
- mshr_tri32_done:;
- poly[0].clear();
- poly[1].clear();
- }
- }
- part.render.indUnlock();
- }
- part.render.vtxUnlock();
- }
- }
- }
- }
- // create MeshBase from 'polys'
- if(polys.elms())
- {
- MeshBase mshb; Triangulate(polys, mshb, EPS, true);
- polys.clear();
- if(mshb.vtxs() && mshb.faces())
- {
- MeshLod &dest_lod=(temp.parts.elms() ? temp.newLod() : temp);
- dest_lod. copyParams(src_lod);
- dest_lod.scaleParams(scale );
- Swap(mshb, dest_lod.parts.New().base);
- }
- }
- }
- temp.setBox();
- temp.lod_center=src.lod_center; if(matrix)temp.lod_center*=*matrix;
- }
- finished:;
- Swap(dest, temp);
- }
- /******************************************************************************/
- void MeshOverlay::zero()
- {
- _lod_center.zero();
- _ext .zero();
- _matrix .identity();
- _shader=null;
- }
- MeshOverlay::MeshOverlay() {zero();}
- MeshOverlay& MeshOverlay::del()
- {
- _lods .del ();
- _material.clear();
- zero(); return T;
- }
- /******************************************************************************/
- Bool MeshOverlay::createStatic(C Mesh &mesh, C MaterialPtr &material, C Matrix &overlay_matrix, C Matrix *mesh_matrix)
- {
- del();
- if(mesh.is())
- {
- _matrix=overlay_matrix;
- Memc<Plane> planes;
- Box box ; SetBoxAndPlanes(box, planes, _matrix);
- Mesh temp ; ClipMeshToPlanes(mesh, mesh_matrix, temp, planes.data(), planes.elms(), box);
- if(temp.is())
- {
- T._lod_center= temp.lod_center;
- T._ext = temp.ext;
- T._lods.setNum(temp.lods());
- FREPD(l, temp.lods()) // order is important
- {
- MeshBase &mshb=temp.lod(l).parts[0].base;
- #if 0
- mshb.setNormals(); REPA(mshb.vtx)mshb.vtx.pos[i]+=mshb.vtx.nrm[i]*0.005f; // surface epsilon
- #endif
- #if 0
- 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
- #endif
- _lods[l].dist2=temp.lod(l).dist2;
- _lods[l].mshr.create(mshb);
- }
- T.material(material);
- return true;
- }
- }
- return false;
- }
- Bool MeshOverlay::createAnimated(C Mesh &mesh, C MaterialPtr &material, C Matrix &overlay_matrix, C Matrix *mesh_matrix)
- {
- del();
- if(mesh.is())
- {
- if(!mesh_matrix)_matrix=overlay_matrix;else
- {
- mesh_matrix->inverse(_matrix);
- overlay_matrix.mul(_matrix, _matrix);
- }
- Memc<Plane> planes;
- Box box ; SetBoxAndPlanes(box, planes, _matrix);
- Mesh temp ; ClipMeshToPlanes(mesh, null, temp, planes.data(), planes.elms(), box);
- if(temp.is())
- {
- T._lod_center= temp.lod_center;
- T._ext = temp.ext;
- T._lods.setNum(temp.lods());
- FREPD(l, temp.lods()) // order is important
- {
- MeshBase &mshb=temp.lod(l).parts[0].base;
- #if 0
- mshb.setNormals(); REPA(mshb.vtx)mshb.vtx.pos[i]+=mshb.vtx.nrm[i]*0.005f; // surface epsilon
- #endif
- #if 0
- 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
- #endif
- _lods[l].dist2=temp.lod(l).dist2;
- _lods[l].mshr.create(mshb);
- }
- T.material(material);
- return true;
- }
- }
- return false;
- }
- /******************************************************************************/
- void MeshOverlay::setShader()
- {
- _shader=null;
- if(_lods.elms() && _material && _material->base_0)_shader=ShaderFiles("Overlay")->get(TechNameOverlay(false, _material->base_1!=null));
- }
- MeshOverlay& MeshOverlay::material(C MaterialPtr &material)
- {
- T._material=material;
- setShader();
- return T;
- }
- #pragma pack(push, 4)
- struct GOverlayClass
- {
- Vec4 param;
- Matrix mtrx ;
- };
- #pragma pack(pop)
- void MeshOverlay::setParams(Flt alpha)C // this is called only inside 'draw' methods, so '_material' is assumed to be != null
- {
- GOverlayClass overlay_params;
- overlay_params.param.set(0.8f, alpha, 0, 0);
- overlay_params.mtrx=_matrix;
- Sh.h_OverlayParams->set(overlay_params);
- _material ->setBlend();
- D.depth(true);
- D.cull (true);
- //D.alpha(ALPHA_BLEND_FACTOR); not needed because ALPHA_BLEND_FACTOR is used everywhere in RM_OVERLAY
- /*D.depthWrite(false); not needed because false is used everywhere in RM_OVERLAY*/ Renderer.needDepthTest(); // !! 'needDepthTest' after 'depthWrite' !!
- }
- /******************************************************************************/
- C MeshRender& MeshOverlay::getDrawLod(C Matrix &matrix)C
- {
- if(_lods.elms()>1)
- {
- Flt dist2=GetLodDist2(_lod_center, matrix);
- REPA(_lods){C Lod &test=_lods[i]; if(dist2>=test.dist2)return test.mshr;}
- }
- return _lods[0].mshr;
- }
- C MeshRender& MeshOverlay::getDrawLod(C MatrixM &matrix)C
- {
- if(_lods.elms()>1)
- {
- Flt dist2=GetLodDist2(_lod_center, matrix);
- REPA(_lods){C Lod &test=_lods[i]; if(dist2>=test.dist2)return test.mshr;}
- }
- return _lods[0].mshr;
- }
- /******************************************************************************/
- void MeshOverlay::draw(Flt alpha)C
- {
- if(_shader)
- {
- setParams(alpha);
- _shader->begin(); C MeshRender &mshr=getDrawLod(ObjMatrix); mshr.set().drawFull();
- ShaderEnd();
- }
- }
- void MeshOverlay::draw(C MatrixM &matrix, Flt alpha)C
- {
- if(_shader)
- {
- SetOneMatrix(matrix);
- setParams(alpha);
- _shader->begin(); C MeshRender &mshr=getDrawLod(matrix); mshr.set().drawFull();
- ShaderEnd();
- }
- }
- void MeshOverlay::draw(C AnimatedSkeleton &anim_skel, Flt alpha)C
- {
- if(_shader)
- {
- anim_skel.setMatrix();
- setParams(alpha);
- _shader->begin(); C MeshRender &mshr=getDrawLod(anim_skel.matrix()); mshr.set(); mshr.draw();
- ShaderEnd();
- }
- }
- /******************************************************************************/
- Bool MeshOverlay::save(File &f, CChar *path)C
- {
- f.putMulti(Byte(0), Int(_lods.elms())); // version
- if(_lods.elms())
- {
- f.putMulti(_lod_center, _ext, _matrix);
- f.putAsset(_material.id());
- FREPA(_lods)
- {
- f<<_lods[i].dist2;
- if(!_lods[i].mshr.saveData(f))return false;
- }
- }
- return f.ok();
- }
- Bool MeshOverlay::load(File &f, CChar *path)
- {
- del(); switch(f.decUIntV()) // version
- {
- case 0:
- {
- _lods.setNum(f.getInt());
- if(_lods.elms())
- {
- f.getMulti(_lod_center, _ext, _matrix);
- _material.require(f.getAssetID(), path);
- FREPA(_lods)
- {
- f>>_lods[i].dist2;
- if(!_lods[i].mshr.loadData(f))goto error;
- }
- setShader();
- }
- if(f.ok())return true;
- }break;
- }
- error:
- del(); return false;
- }
- /******************************************************************************/
- }
- /******************************************************************************/
|