// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include #include #include "nel/pacs/collision_mesh_build.h" #include "nel/pacs/local_retriever.h" #include "nel/pacs/exterior_mesh.h" #include "mouline.h" #include "build_surfaces.h" using namespace std; using namespace NLMISC; using namespace NLPACS; /* // a reference on an edge struct CEdgeKey { uint32 V0; uint32 V1; CEdgeKey() {} CEdgeKey(uint32 v0, uint32 v1) : V0(v0), V1(v1) {} bool operator() (const CEdgeKey &a, const CEdgeKey &b) { return a.V0 < b.V0 || (a.V0 == b.V0 && a.V1 < b.V1); } }; // the info on an edge struct CEdgeInfo { sint32 Left, LeftEdge; sint32 Right, RightEdge; CEdgeInfo(sint32 left=-1, sint32 leftEdge=-1, sint32 right=-1, sint32 rightEdge=-1) : Left(left), LeftEdge(leftEdge), Right(right), RightEdge(rightEdge) {} }; typedef map TLinkRelloc; typedef TLinkRelloc::iterator ItTLinkRelloc; // void linkMesh(CCollisionMeshBuild &cmb, bool linkInterior) { uint i, j; TLinkRelloc relloc; // check each edge of each face for (i=0; i= CCollisionFace::InteriorSurfaceFirst && !linkInterior) continue; for (j=0; j<3; ++j) { cmb.Faces[i].Edge[j] = -1; uint edge = (j+2)%3; uint32 va = cmb.Faces[i].V[j], vb = cmb.Faces[i].V[(j+1)%3]; ItTLinkRelloc it; if ((it = relloc.find(CEdgeKey(va, vb))) != relloc.end()) { // in this case, the left triangle of the edge has already been found. // should throw an error nlerror("On face %d, edge %d: left side of edge (%d,%d) already linked to face %d", i, edge, va, vb, (*it).second.Left); } else if ((it = relloc.find(CEdgeKey(vb, va))) != relloc.end()) { // in this case, we must check the right face has been set yet if ((*it).second.Right != -1) { nlerror("On face %d, edge %d: right side of edge (%d,%d) already linked to face %d", i, edge, vb, va, (*it).second.Right); } (*it).second.Right = i; (*it).second.RightEdge = edge; } else { // if the edge wasn't present yet, create it and set it up. relloc.insert(make_pair(CEdgeKey(va, vb), CEdgeInfo(i, edge, -1, -1))); } } } // for each checked edge, update the edge info inside the faces ItTLinkRelloc it; for (it=relloc.begin(); it!=relloc.end(); ++it) { sint32 left, leftEdge; sint32 right, rightEdge; // get the link info on the edge left = (*it).second.Left; leftEdge = (*it).second.LeftEdge; right = (*it).second.Right; rightEdge = (*it).second.RightEdge; // update both faces if (left != -1) cmb.Faces[left].Edge[leftEdge] = right; if (right != -1) cmb.Faces[right].Edge[rightEdge] = left; } } */ void buildExteriorMesh(CCollisionMeshBuild &cmb, CExteriorMesh &em) { uint startFace = 0; vector edges; uint i; for (i=0; i loop; while (true) { if (cmb.Faces[current].EdgeFlags[nextEdge]) { // if reaches the end of the border, then quits. break; } else if (next == -1) { // if the next edge belongs to the border, then go on the same element cmb.Faces[current].EdgeFlags[nextEdge] = true; /// \todo get the real edge link sint link = (cmb.Faces[current].Visibility[nextEdge]) ? -1 : 0; //(numLink++); //edges.push_back(CExteriorMesh::CEdge(cmb.Vertices[cmb.Faces[current].V[pivot]], link)); loop.push_back(CExteriorMesh::CEdge(cmb.Vertices[cmb.Faces[current].V[pivot]], link)); pivot = (pivot+1)%3; nextEdge = (nextEdge+1)%3; next = cmb.Faces[current].Edge[nextEdge]; } else { // if the next element is inside the surface, then go to the next element for (oedge=0; oedge<3 && cmb.Faces[next].Edge[oedge]!=current; ++oedge) ; nlassert(oedge != 3); current = next; pivot = (oedge+2)%3; nextEdge = (oedge+1)%3; next = cmb.Faces[current].Edge[nextEdge]; } } // mark the end of a ext mesh block // this way, collisions won't be checked in the pacs engine if (loop.size() >= 3) { uint n = (uint)loop.size(); while (loop.front().Link >= 0 && loop.back().Link >= 0 && n > 0) { loop.push_back(loop.front()); loop.erase(loop.begin()); --n; } } loop.push_back(loop.front()); loop.back().Link = -2; edges.insert(edges.end(), loop.begin(), loop.end()); //edges.push_back(edges[firstEdge]); //edges.back().Link = -2; } bool previousWasLink = false; sint previousLink = -1; for (i=0; i= 0) { if (!previousWasLink) ++previousLink; edges[i].Link = previousLink; previousWasLink = true; } else { previousWasLink = false; } } em.setEdges(edges); } // void linkExteriorToInterior(CLocalRetriever &lr) { CExteriorMesh em = lr.getExteriorMesh(); vector edges = em.getEdges(); vector links; const vector &chains = lr.getChains(); const vector &ochains = lr.getFullOrderedChains(); const vector &bchains = lr.getBorderChains(); { uint i; nlinfo("Border chains (to be linked) for this retriever:"); for (i=0; i= (sint)links.size()) links.resize(edges[startedge].Link+1); // if the link already exists, warning if (links[edges[startedge].Link].BorderChainId != 0xFFFF || links[edges[startedge].Link].ChainId != 0xFFFF || links[edges[startedge].Link].SurfaceId != 0xFFFF) { nlwarning("in linkInteriorToExterior():"); nlwarning("link %d already set!!", edges[startedge].Link); } // setup the link links[edges[startedge].Link] = link; } // em.setEdges(edges); em.setLinks(links); lr.setExteriorMesh(em); } // void computeRetriever(CCollisionMeshBuild &cmb, CLocalRetriever &lr, CVector &translation, bool useCmbTrivialTranslation) { // set the retriever lr.setType(CLocalRetriever::Interior); // if should use the own cmb bbox, then compute it if (useCmbTrivialTranslation) { translation = cmb.computeTrivialTranslation(); // snap the translation vector to a meter wide grid translation.x = (float)ceil(translation.x); translation.y = (float)ceil(translation.y); translation.z = 0.0f; } uint i, j; for (i=0; i errors; cmb.link(false, errors); cmb.link(true, errors); if (!errors.empty()) { nlwarning("Edge issues reported !!"); uint i; for (i=0; i