diff options
| author | Anton Novoselov <[email protected]> | 2017-08-01 12:53:38 +0300 |
|---|---|---|
| committer | Anton Novoselov <[email protected]> | 2017-08-01 12:53:38 +0300 |
| commit | 236f03c0b9a4982328ed1201978f7f69d192d9b2 (patch) | |
| tree | e486f2fa39dba203563895541e92c60ed3e25759 /sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp | |
| parent | Added screens to welcome page (diff) | |
| download | blast-236f03c0b9a4982328ed1201978f7f69d192d9b2.tar.xz blast-236f03c0b9a4982328ed1201978f7f69d192d9b2.zip | |
Blast 1.1 release (windows / linux)
see docs/release_notes.txt for details
Diffstat (limited to 'sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp')
| -rw-r--r-- | sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp | 946 |
1 files changed, 48 insertions, 898 deletions
diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp index 0b7187f..cc2442c 100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp @@ -1,12 +1,30 @@ -/* -* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. -* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, related documentation -* and any modifications thereto. Any use, reproduction, disclosure or -* distribution of this software and related documentation without an express -* license agreement from NVIDIA CORPORATION is strictly prohibited. -*/ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2016-2017 NVIDIA Corporation. All rights reserved. + // This warning arises when using some stl containers with older versions of VC // c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1826): warning C4702: unreachable code @@ -24,13 +42,11 @@ #include <set> #include "NvBlastExtAuthoringBooleanTool.h" #include <queue> -#include "NvBlastExtAuthoringPerlinNoise.h" #include <NvBlastAssert.h> using physx::PxVec3; using physx::PxVec2; -#define VEC_COMPARISON_OFFSET 1e-5f #define TWO_VERTICES_THRESHOLD 1e-7 namespace Nv @@ -38,40 +54,6 @@ namespace Nv namespace Blast { -bool VrtComp::operator()(const Vertex& a, const Vertex& b) const -{ - if (a.p.x + VEC_COMPARISON_OFFSET < b.p.x) return true; - if (a.p.x - VEC_COMPARISON_OFFSET > b.p.x) return false; - if (a.p.y + VEC_COMPARISON_OFFSET < b.p.y) return true; - if (a.p.y - VEC_COMPARISON_OFFSET > b.p.y) return false; - if (a.p.z + VEC_COMPARISON_OFFSET < b.p.z) return true; - if (a.p.z - VEC_COMPARISON_OFFSET > b.p.z) return false; - - if (a.n.x + 1e-3 < b.n.x) return true; - if (a.n.x - 1e-3 > b.n.x) return false; - if (a.n.y + 1e-3 < b.n.y) return true; - if (a.n.y - 1e-3 > b.n.y) return false; - if (a.n.z + 1e-3 < b.n.z) return true; - if (a.n.z - 1e-3 > b.n.z) return false; - - - if (a.uv[0].x + 1e-3 < b.uv[0].x) return true; - if (a.uv[0].x - 1e-3 > b.uv[0].x) return false; - if (a.uv[0].y + 1e-3 < b.uv[0].y) return true; - return false; -} - -bool VrtPositionComparator::operator()(const PxVec3& a, const PxVec3& b) const -{ - if (a.x + VEC_COMPARISON_OFFSET < b.x) return true; - if (a.x - VEC_COMPARISON_OFFSET > b.x) return false; - if (a.y + VEC_COMPARISON_OFFSET < b.y) return true; - if (a.y - VEC_COMPARISON_OFFSET > b.y) return false; - if (a.z + VEC_COMPARISON_OFFSET < b.z) return true; - if (a.z - VEC_COMPARISON_OFFSET > b.z) return false; - return false; -} - NV_FORCE_INLINE bool compareTwoVertices(const PxVec3& a, const PxVec3& b) { return std::abs(b.x - a.x) < TWO_VERTICES_THRESHOLD && std::abs(b.y - a.y) < TWO_VERTICES_THRESHOLD && std::abs(b.z - a.z) < TWO_VERTICES_THRESHOLD; @@ -100,7 +82,7 @@ inline bool pointInside(PxVec2 a, PxVec2 b, PxVec2 c, PxVec2 pnt) (v1 <= 0.0f && v2 <= 0.0f && v3 <= 0.0f); } -void ChunkPostProcessor::triangulatePolygonWithEarClipping(std::vector<uint32_t>& inputPolygon, Vertex* vert, ProjectionDirections dir) +void Triangulator::triangulatePolygonWithEarClipping(std::vector<uint32_t>& inputPolygon, Vertex* vert, ProjectionDirections dir) { // return; //for (uint32_t i = 0; i < inputPolygon.size(); ++i) @@ -144,10 +126,6 @@ void ChunkPostProcessor::triangulatePolygonWithEarClipping(std::vector<uint32_t> } if (good) { - addEdgeTr(Edge(inputPolygon[curr], inputPolygon[prev])); - addEdgeTr(Edge(inputPolygon[next], inputPolygon[prev])); - addEdgeTr(Edge(inputPolygon[curr], inputPolygon[next])); - mBaseMeshTriangles.push_back(TriangleIndexed(inputPolygon[curr], inputPolygon[prev], inputPolygon[next])); vCount--; inputPolygon.erase(inputPolygon.begin() + curr); @@ -321,7 +299,7 @@ int32_t unitePolygons(std::vector<uint32_t>& externalLoop, std::vector<uint32_t> return 0; } -void ChunkPostProcessor::buildPolygonAndTriangulate(std::vector<Edge>& edges, Vertex* vertices, int32_t userData) +void Triangulator::buildPolygonAndTriangulate(std::vector<Edge>& edges, Vertex* vertices, int32_t userData, int32_t materialId, int32_t smoothingGroup) { std::vector<std::vector<uint32_t> > serializedLoops; @@ -439,7 +417,7 @@ void ChunkPostProcessor::buildPolygonAndTriangulate(std::vector<Edge>& edges, Ve int32_t baseLoop = loopsInfo[extPoly].index; for (uint32_t intPoly = 0; intPoly < loopsInfo.size(); ++intPoly) { - if (loopsInfo[intPoly].area > 0 || loopsInfo[intPoly].used || abs(loopsInfo[intPoly].area) > loopsInfo[extPoly].area) + if (loopsInfo[intPoly].area > 0 || loopsInfo[intPoly].used || std::abs(loopsInfo[intPoly].area) > loopsInfo[extPoly].area) { continue; } @@ -454,11 +432,13 @@ void ChunkPostProcessor::buildPolygonAndTriangulate(std::vector<Edge>& edges, Ve } for (uint32_t i = oldSize; i < mBaseMeshTriangles.size(); ++i) { - mBaseMeshTriangles[i].userInfo = userData; + mBaseMeshTriangles[i].userData = userData; + mBaseMeshTriangles[i].materialId = materialId; + mBaseMeshTriangles[i].smoothingGroup = smoothingGroup; } } -NV_FORCE_INLINE int32_t ChunkPostProcessor::addVerticeIfNotExist(Vertex& p) +NV_FORCE_INLINE int32_t Triangulator::addVerticeIfNotExist(const Vertex& p) { auto it = mVertMap.find(p); if (it == mVertMap.end()) @@ -473,7 +453,7 @@ NV_FORCE_INLINE int32_t ChunkPostProcessor::addVerticeIfNotExist(Vertex& p) } } -NV_FORCE_INLINE void ChunkPostProcessor::addEdgeIfValid(EdgeWithParent& ed) +NV_FORCE_INLINE void Triangulator::addEdgeIfValid(EdgeWithParent& ed) { if (ed.s == ed.e) return; @@ -497,14 +477,14 @@ NV_FORCE_INLINE void ChunkPostProcessor::addEdgeIfValid(EdgeWithParent& ed) -void ChunkPostProcessor::prepare(Mesh* mesh) +void Triangulator::prepare(const Mesh* mesh) { - Edge* ed = mesh->getEdges(); - Vertex* vr = mesh->getVertices(); + const Edge* ed = mesh->getEdges(); + const Vertex* vr = mesh->getVertices(); mBaseMapping.resize(mesh->getVerticesCount()); for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) { - Facet* fc = mesh->getFacet(i); + const Facet* fc = mesh->getFacet(i); for (uint32_t j = fc->firstEdgeNumber; j < fc->firstEdgeNumber + fc->edgesCount; ++j) { int32_t a = addVerticeIfNotExist(vr[ed[j].s]); @@ -527,29 +507,17 @@ void ChunkPostProcessor::prepare(Mesh* mesh) } -void ChunkPostProcessor::reset() +void Triangulator::reset() { - isTesselated = false; mVertices.clear(); mBaseMeshEdges.clear(); mVertMap.clear(); mEdgeMap.clear(); - mTrMeshEdgeMap.clear(); - mTrMeshEdges.clear(); - mTrMeshEdToTr.clear(); mBaseMeshTriangles.clear(); - mEdgeFlag.clear(); - mVertexValence.clear(); - mRestrictionFlag.clear(); - mVerticesDistances.clear(); - mVerticesNormalsSmoothed.clear(); - mBaseMeshResultTriangles.clear(); - mTesselatedMeshResultTriangles.clear(); - mTesselatedMeshTriangles.clear(); } -void ChunkPostProcessor::triangulate(Mesh* mesh) +void Triangulator::triangulate(const Mesh* mesh) { reset(); if (mesh == nullptr || !mesh->isValid()) @@ -569,17 +537,16 @@ void ChunkPostProcessor::triangulate(Mesh* mesh) { if (temp.empty() == false) { - buildPolygonAndTriangulate(temp, &mVertices[0], mesh->getFacet(fP)->userData); + buildPolygonAndTriangulate(temp, mVertices.data(), mesh->getFacet(fP)->userData, mesh->getFacet(fP)->materialId, mesh->getFacet(fP)->smoothingGroup); } temp.clear(); fP = mBaseMeshEdges[i].parent; } temp.push_back(Edge(mBaseMeshEdges[i].s, mBaseMeshEdges[i].e)); } - buildPolygonAndTriangulate(temp, &mVertices[0], mesh->getFacet(fP)->userData); + buildPolygonAndTriangulate(temp, mVertices.data(), mesh->getFacet(fP)->userData, mesh->getFacet(fP)->materialId, mesh->getFacet(fP)->smoothingGroup); /* Build final triangles */ - mBaseMeshResultTriangles.clear(); for (uint32_t i = 0; i < mBaseMeshTriangles.size(); ++i) { @@ -588,683 +555,19 @@ void ChunkPostProcessor::triangulate(Mesh* mesh) continue; } mBaseMeshResultTriangles.push_back(Triangle(mVertices[mBaseMeshTriangles[i].ea], mVertices[mBaseMeshTriangles[i].eb], mVertices[mBaseMeshTriangles[i].ec])); - mBaseMeshResultTriangles.back().userInfo = mBaseMeshTriangles[i].userInfo; - } - - computePositionedMapping(); -} - -void ChunkPostProcessor::prebuildTesselatedTriangles() -{ - mTesselatedMeshResultTriangles.clear(); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - mTesselatedMeshResultTriangles.push_back(Triangle(mVertices[mTesselatedMeshTriangles[i].ea], mVertices[mTesselatedMeshTriangles[i].eb], mVertices[mTesselatedMeshTriangles[i].ec])); - mTesselatedMeshResultTriangles.back().userInfo = mTesselatedMeshTriangles[i].userInfo; - } - -} - - -int32_t ChunkPostProcessor::addEdgeTr(const Edge& e) -{ - Edge ed = e; - if (ed.e < ed.s) std::swap(ed.s, ed.e); - auto it = mTrMeshEdgeMap.find(ed); - if (it == mTrMeshEdgeMap.end()) - { - mTrMeshEdToTr.push_back(EdgeToTriangles()); - mTrMeshEdgeMap[ed] = (int)mTrMeshEdToTr.size() - 1; - mTrMeshEdges.push_back(ed); - mEdgeFlag.push_back(INTERNAL_EDGE); - return (int32_t)mTrMeshEdToTr.size() - 1; - } - else - { - return it->second; - } -} - -int32_t ChunkPostProcessor::findEdge(const Edge& e) -{ - Edge ed = e; - if (ed.e < ed.s) std::swap(ed.s, ed.e); - auto it = mTrMeshEdgeMap.find(ed); - if (it == mTrMeshEdgeMap.end()) - { - return -1; - } - return it->second; -} - -void ChunkPostProcessor::updateEdgeTriangleInfo() -{ - mTrMeshEdToTr.clear(); - mTrMeshEdToTr.resize(mTrMeshEdges.size()); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.ea == NOT_VALID_VERTEX) - continue; - int32_t ed = addEdgeTr(Edge(tr.ea, tr.eb)); - mTrMeshEdToTr[ed].add(i); - ed = addEdgeTr(Edge(tr.ea, tr.ec)); - mTrMeshEdToTr[ed].add(i); - ed = addEdgeTr(Edge(tr.ec, tr.eb)); - mTrMeshEdToTr[ed].add(i); - } -} - -void ChunkPostProcessor::updateVertEdgeInfo() -{ - mVertexToTriangleMap.clear(); - mVertexToTriangleMap.resize(mVertices.size()); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.ea == NOT_VALID_VERTEX) continue; - mVertexToTriangleMap[tr.ea].push_back(i); - mVertexToTriangleMap[tr.eb].push_back(i); - mVertexToTriangleMap[tr.ec].push_back(i); - } - mVertexValence.clear(); - mVertexValence.resize(mVertices.size(), 0); - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mTrMeshEdToTr[i].c != 0) - { - mVertexValence[mTrMeshEdges[i].s]++; - mVertexValence[mTrMeshEdges[i].e]++; - } - } -} - - -void ChunkPostProcessor::collapseEdge(int32_t id) -{ - Edge cEdge = mTrMeshEdges[id]; - uint32_t from = cEdge.s; - uint32_t to = cEdge.e; - - - if (mRestrictionFlag[from] && mRestrictionFlag[to]) - { - return; - } - - if (mVertexValence[from] > mVertexValence[to]) - { - std::swap(from, to); - } - - if (mRestrictionFlag[from]) - { - std::swap(from, to); - } - - std::set<int32_t> connectedToBegin; - std::set<int32_t> connectedToEnd; - std::set<int32_t> neighboorTriangles; - - int32_t trWithEdge[2] = {-1, -1}; - int32_t cntr = 0; - for (uint32_t i = 0; i < mVertexToTriangleMap[from].size(); ++i) - { - if (mTesselatedMeshTriangles[mVertexToTriangleMap[from][i]].ea == NOT_VALID_VERTEX) - continue; - if (neighboorTriangles.insert(mVertexToTriangleMap[from][i]).second && mTesselatedMeshTriangles[mVertexToTriangleMap[from][i]].isContainEdge(from, to)) - { - trWithEdge[cntr] = mVertexToTriangleMap[from][i]; - cntr++; - } - } - for (uint32_t i = 0; i < mVertexToTriangleMap[to].size(); ++i) - { - if (mTesselatedMeshTriangles[mVertexToTriangleMap[to][i]].ea == NOT_VALID_VERTEX) - continue; - if (neighboorTriangles.insert(mVertexToTriangleMap[to][i]).second && mTesselatedMeshTriangles[mVertexToTriangleMap[to][i]].isContainEdge(from, to)) - { - trWithEdge[cntr] = mVertexToTriangleMap[to][i]; - cntr++; - } - } - - if (cntr == 0) - { - return; - } - if (cntr > 2) - { - return; - } - - for (uint32_t i: neighboorTriangles) - { - if (mTesselatedMeshTriangles[i].ea == from || mTesselatedMeshTriangles[i].eb == from || mTesselatedMeshTriangles[i].ec == from) - { - if (mTesselatedMeshTriangles[i].ea != to && mTesselatedMeshTriangles[i].ea != from) - connectedToBegin.insert(mTesselatedMeshTriangles[i].ea); - if (mTesselatedMeshTriangles[i].eb != to && mTesselatedMeshTriangles[i].eb != from) - connectedToBegin.insert(mTesselatedMeshTriangles[i].eb); - if (mTesselatedMeshTriangles[i].ec != to && mTesselatedMeshTriangles[i].ec != from) - connectedToBegin.insert(mTesselatedMeshTriangles[i].ec); - } - - if (mTesselatedMeshTriangles[i].ea == to || mTesselatedMeshTriangles[i].eb == to || mTesselatedMeshTriangles[i].ec == to) - { - if (mTesselatedMeshTriangles[i].ea != to && mTesselatedMeshTriangles[i].ea != from) - connectedToEnd.insert(mTesselatedMeshTriangles[i].ea); - if (mTesselatedMeshTriangles[i].eb != to && mTesselatedMeshTriangles[i].eb != from) - connectedToEnd.insert(mTesselatedMeshTriangles[i].eb); - if (mTesselatedMeshTriangles[i].ec != to && mTesselatedMeshTriangles[i].ec != from) - connectedToEnd.insert(mTesselatedMeshTriangles[i].ec); - } - } - bool canBeCollapsed = true; - for (auto it = connectedToBegin.begin(); it != connectedToBegin.end(); ++it) - { - uint32_t currV = *it; - if (connectedToEnd.find(currV) == connectedToEnd.end()) - continue; - bool found = false; - for (int32_t tr : neighboorTriangles) - { - if ((mTesselatedMeshTriangles[tr].ea == from || mTesselatedMeshTriangles[tr].eb == from || mTesselatedMeshTriangles[tr].ec == from) && - (mTesselatedMeshTriangles[tr].ea == to || mTesselatedMeshTriangles[tr].eb == to || mTesselatedMeshTriangles[tr].ec == to) && - (mTesselatedMeshTriangles[tr].ea == currV || mTesselatedMeshTriangles[tr].eb == currV || mTesselatedMeshTriangles[tr].ec == currV)) - { - found = true; - break; - } - } - if (!found) - { - canBeCollapsed = false; - break; - } - } - - if (canBeCollapsed) - { - for (int32_t i : neighboorTriangles) - { - if (trWithEdge[0] == i) continue; - if (cntr == 2 && trWithEdge[1] == i) continue; - TriangleIndexed tr = mTesselatedMeshTriangles[i]; - PxVec3 oldNormal = (mVertices[tr.eb].p - mVertices[tr.ea].p).cross(mVertices[tr.ec].p - mVertices[tr.ea].p); - - if (tr.ea == from) - { - tr.ea = to; - } - else - if (tr.eb == from) - { - tr.eb = to; - } - else - if (tr.ec == from) - { - tr.ec = to; - } - PxVec3 newNormal = (mVertices[tr.eb].p - mVertices[tr.ea].p).cross(mVertices[tr.ec].p - mVertices[tr.ea].p); - if (newNormal.magnitude() < 1e-8f) - { - canBeCollapsed = false; - break; - } - if (oldNormal.dot(newNormal) < 0) - { - canBeCollapsed = false; - break; - } - } - } - - if (canBeCollapsed) - { - mTesselatedMeshTriangles[trWithEdge[0]].ea = NOT_VALID_VERTEX; - if (cntr == 2)mTesselatedMeshTriangles[trWithEdge[1]].ea = NOT_VALID_VERTEX; - - for (int32_t i : neighboorTriangles) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - continue; - if (mTesselatedMeshTriangles[i].ea == from) - { - mTesselatedMeshTriangles[i].ea = to; - mVertexToTriangleMap[from].clear(); - mVertexToTriangleMap[to].push_back(i); - } - else - if (mTesselatedMeshTriangles[i].eb == from) - { - mTesselatedMeshTriangles[i].eb = to; - mVertexToTriangleMap[from].clear(); - mVertexToTriangleMap[to].push_back(i); - } - else - if (mTesselatedMeshTriangles[i].ec == from) - { - mTesselatedMeshTriangles[i].ec = to; - mVertexToTriangleMap[from].clear(); - mVertexToTriangleMap[to].push_back(i); - } - } - } -} - - -void ChunkPostProcessor::divideEdge(int32_t id) -{ - - if (mTrMeshEdToTr[id].c == 0 ) - { - return; - } - - Edge cEdge = mTrMeshEdges[id]; - EdgeFlag snapRestriction = mEdgeFlag[id]; - Vertex middle; - uint32_t nv = NOT_VALID_VERTEX; - for (int32_t t = 0; t < mTrMeshEdToTr[id].c; ++t) - { - int32_t oldTriangleIndex = mTrMeshEdToTr[id].tr[t]; - TriangleIndexed tr = mTesselatedMeshTriangles[mTrMeshEdToTr[id].tr[t]]; - - if (tr.ea == NOT_VALID_VERTEX) - { - continue; - } - - uint32_t pbf[3]; - pbf[0] = tr.ea; - pbf[1] = tr.eb; - pbf[2] = tr.ec; - for (int32_t p = 0; p < 3; ++p) - { - int32_t pnx = (p + 1) % 3; - int32_t opp = (p + 2) % 3; - - if ((pbf[p] == cEdge.s && pbf[pnx] == cEdge.e) || (pbf[p] == cEdge.e && pbf[pnx] == cEdge.s)) - { - if (nv == NOT_VALID_VERTEX) - { - middle.p = (mVertices[pbf[p]].p + mVertices[pbf[pnx]].p) * 0.5f; - middle.n = (mVertices[pbf[p]].n + mVertices[pbf[pnx]].n) * 0.5f; - middle.uv[0] = (mVertices[pbf[p]].uv[0] + mVertices[pbf[pnx]].uv[0]) * 0.5f; - - nv = (uint32_t)mVertices.size(); - mVertices.push_back(middle); - } - if (nv < mRestrictionFlag.size()) - { - mRestrictionFlag[nv] = ((snapRestriction == EXTERNAL_BORDER_EDGE) || (snapRestriction == INTERNAL_BORDER_EDGE)); - } - else - { - mRestrictionFlag.push_back((snapRestriction == EXTERNAL_BORDER_EDGE) || (snapRestriction == INTERNAL_BORDER_EDGE)); - } - - uint32_t ind1 = addEdgeTr(Edge(pbf[p], nv)); - uint32_t ind2 = addEdgeTr(Edge(nv, pbf[pnx])); - uint32_t ind3 = addEdgeTr(Edge(nv, pbf[opp])); - - - mEdgeFlag[ind1] = snapRestriction; - mEdgeFlag[ind2] = snapRestriction; - mEdgeFlag[ind3] = INTERNAL_EDGE; - - mTrMeshEdToTr[ind1].add(mTrMeshEdToTr[id].tr[t]); - int32_t userInfo = mTesselatedMeshTriangles[mTrMeshEdToTr[id].tr[t]].userInfo; - mTesselatedMeshTriangles[mTrMeshEdToTr[id].tr[t]] = TriangleIndexed(pbf[p], nv, pbf[opp]); - mTesselatedMeshTriangles[mTrMeshEdToTr[id].tr[t]].userInfo = userInfo; - mTrMeshEdToTr[ind2].add((int32_t)mTesselatedMeshTriangles.size()); - mTrMeshEdToTr[ind3].add((int32_t)mTrMeshEdToTr[id].tr[t]); - mTrMeshEdToTr[ind3].add((int32_t)mTesselatedMeshTriangles.size()); - mTesselatedMeshTriangles.push_back(TriangleIndexed(nv,pbf[pnx], pbf[opp])); - mTesselatedMeshTriangles.back().userInfo = userInfo; - int32_t ed1 = findEdge(Edge(pbf[pnx], pbf[opp])); - mTrMeshEdToTr[ed1].replace(oldTriangleIndex, (int32_t)mTesselatedMeshTriangles.size() - 1); - break; - } - } - } -} - + mBaseMeshResultTriangles.back().userData = mBaseMeshTriangles[i].userData; + mBaseMeshResultTriangles.back().materialId = mBaseMeshTriangles[i].materialId; + mBaseMeshResultTriangles.back().smoothingGroup = mBaseMeshTriangles[i].smoothingGroup; -NV_FORCE_INLINE void markEdge(int32_t ui, int32_t ed, std::vector<ChunkPostProcessor::EdgeFlag>& shortMarkup, std::vector<int32_t>& lastOwner) -{ - if (shortMarkup[ed] == ChunkPostProcessor::NONE) - { - if (ui == 0) - { - shortMarkup[ed] = ChunkPostProcessor::EXTERNAL_EDGE; - } - else - { - shortMarkup[ed] = ChunkPostProcessor::INTERNAL_EDGE; - } - lastOwner[ed] = ui; } - else - { - if (ui != 0) - { - if (shortMarkup[ed] == ChunkPostProcessor::EXTERNAL_EDGE) - { - shortMarkup[ed] = ChunkPostProcessor::EXTERNAL_BORDER_EDGE; - } - if ((shortMarkup[ed] == ChunkPostProcessor::INTERNAL_EDGE) && ui != lastOwner[ed]) - { - shortMarkup[ed] = ChunkPostProcessor::INTERNAL_BORDER_EDGE; - } - } - else - { - if (shortMarkup[ed] != ChunkPostProcessor::EXTERNAL_EDGE) - { - shortMarkup[ed] = ChunkPostProcessor::EXTERNAL_BORDER_EDGE; - } - } - } -} - -float falloffFunction(float x, float mx) -{ - float t = (x) / (mx + 1e-6f); - t = std::min(1.0f, t); - return t * t; -} - -void ChunkPostProcessor::recalcNoiseDirs() -{ - /** - Compute normals direction to apply noise - */ - mVerticesNormalsSmoothed.resize(mVertices.size(), PxVec3(0, 0, 0)); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.userInfo == 0) continue; - - if (tr.userInfo < 0) - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]] += mVertices[tr.ea].n.getNormalized(); - else - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]] -= mVertices[tr.ea].n.getNormalized(); - - if (tr.userInfo < 0) - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]] += mVertices[tr.eb].n.getNormalized(); - else - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]] -= mVertices[tr.eb].n.getNormalized(); - - if (tr.userInfo < 0) - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]] += mVertices[tr.ec].n.getNormalized(); - else - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]] -= mVertices[tr.ec].n.getNormalized(); - - } - for (uint32_t i = 0; i < mVerticesNormalsSmoothed.size(); ++i) - { - - mVerticesNormalsSmoothed[i] = mVerticesNormalsSmoothed[mPositionMappedVrt[i]]; - mVerticesNormalsSmoothed[i].normalize(); - } -} - - - -void ChunkPostProcessor::applyNoise(SimplexNoise& noise, float falloff, int32_t relaxIterations, float relaxFactor) -{ - NVBLAST_ASSERT(isTesselated); - if (isTesselated == false) - { - return; - } - mRestrictionFlag.clear(); - mRestrictionFlag.resize(mVertices.size(), false); - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mTrMeshEdToTr[i].c != 0) - { - if (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == EXTERNAL_BORDER_EDGE) - { - mRestrictionFlag[mTrMeshEdges[i].e] = true; - mRestrictionFlag[mTrMeshEdges[i].s] = true; - } - } - } - std::vector<Vertex> localVertices = mVertices; - - recalcNoiseDirs(); - - relax(relaxIterations, relaxFactor, localVertices); - - - /** - Apply noise - */ - for (uint32_t i = 0; i < localVertices.size(); ++i) - { - - if (!mRestrictionFlag[i]) - { - - float d = noise.sample(localVertices[i].p); - localVertices[i].p += (falloffFunction(mVerticesDistances[i], falloff)) * mVerticesNormalsSmoothed[i] * d; - } - } - - - /* Recalculate smoothed normals*/ - mVerticesNormalsSmoothed.assign(mVerticesNormalsSmoothed.size(), PxVec3(0, 0, 0)); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.userInfo == 0) continue; - - Triangle pTr(localVertices[tr.ea], localVertices[tr.eb], localVertices[tr.ec]); - PxVec3 nrm = pTr.getNormal().getNormalized(); - - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]] += nrm; - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]] += nrm; - mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]] += nrm; - } - for (uint32_t i = 0; i < mVerticesNormalsSmoothed.size(); ++i) - { - mVerticesNormalsSmoothed[i] = mVerticesNormalsSmoothed[mPositionMappedVrt[i]]; - mVerticesNormalsSmoothed[i].normalize(); - } - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - TriangleIndexed& tr = mTesselatedMeshTriangles[i]; - if (tr.userInfo == 0) continue; - - localVertices[tr.ea].n = mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ea]]; - localVertices[tr.eb].n = mVerticesNormalsSmoothed[mPositionMappedVrt[tr.eb]]; - localVertices[tr.ec].n = mVerticesNormalsSmoothed[mPositionMappedVrt[tr.ec]]; - } - - mTesselatedMeshResultTriangles.clear(); - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].ea == NOT_VALID_VERTEX) - { - continue; - } - mTesselatedMeshResultTriangles.push_back(Triangle(localVertices[mTesselatedMeshTriangles[i].ea], localVertices[mTesselatedMeshTriangles[i].eb], localVertices[mTesselatedMeshTriangles[i].ec])); - mTesselatedMeshResultTriangles.back().userInfo = mTesselatedMeshTriangles[i].userInfo; - } - - -} - - -void ChunkPostProcessor::computePositionedMapping() -{ - std::map<PxVec3, int32_t, VrtPositionComparator> mPosMap; - mPositionMappedVrt.clear(); - mPositionMappedVrt.resize(mVertices.size()); - - for (uint32_t i = 0; i < mVertices.size(); ++i) - { - auto it = mPosMap.find(mVertices[i].p); - - if (it == mPosMap.end()) - { - mPosMap[mVertices[i].p] = i; - mPositionMappedVrt[i] = i; - } - else - { - mPositionMappedVrt[i] = it->second; - } - } -} - -void ChunkPostProcessor::computeFalloffAndNormals() -{ - // Map newly created vertices according to positions - computePositionedMapping(); - - mGeometryGraph.resize(mVertices.size()); - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mTrMeshEdToTr[i].c == 0) - { - continue; - } - int32_t v1 = mPositionMappedVrt[mTrMeshEdges[i].s]; - int32_t v2 = mPositionMappedVrt[mTrMeshEdges[i].e]; - - if (std::find(mGeometryGraph[v1].begin(), mGeometryGraph[v1].end(), v2) == mGeometryGraph[v1].end()) - mGeometryGraph[v1].push_back(v2); - if (std::find(mGeometryGraph[v2].begin(), mGeometryGraph[v2].end(), v1) == mGeometryGraph[v2].end()) - mGeometryGraph[v2].push_back(v1); - } - mVerticesDistances.clear(); - mVerticesDistances.resize(mVertices.size(), 10000.0f); - - std::queue<int32_t> que; - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mTrMeshEdToTr[i].c != 0 && (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == EXTERNAL_BORDER_EDGE)) - { - int32_t v1 = mPositionMappedVrt[mTrMeshEdges[i].s]; - int32_t v2 = mPositionMappedVrt[mTrMeshEdges[i].e]; - mVerticesDistances[v1] = 0.0f; - mVerticesDistances[v2] = 0.0f; - que.push(v1); - que.push(v2); - } - } - while (!que.empty()) - { - int32_t curr = que.front(); - que.pop(); - - for (uint32_t i = 0; i < mGeometryGraph[curr].size(); ++i) - { - int32_t to = mGeometryGraph[curr][i]; - float d = mVerticesDistances[curr] + 0.1f;// (mVertices[to].p - mVertices[curr].p).magnitudeSquared(); - if (d < mVerticesDistances[to]) - { - mVerticesDistances[to] = d; - que.push(to); - } - } - } - - for (uint32_t i = 0; i < mVerticesDistances.size(); ++i) - { - int32_t from = mPositionMappedVrt[i]; - mVerticesDistances[i] = mVerticesDistances[from]; - } -} - -bool edgeOverlapTest(PxVec3& as, PxVec3& ae, PxVec3& bs, PxVec3& be) -{ - //return false; - if (std::max(std::min(as.x, ae.x), std::min(bs.x, be.x)) > std::min(std::max(as.x, ae.x), std::max(bs.x, be.x))) return false; - if (std::max(std::min(as.y, ae.y), std::min(bs.y, be.y)) > std::min(std::max(as.y, ae.y), std::max(bs.y, be.y))) return false; - if (std::max(std::min(as.z, ae.z), std::min(bs.z, be.z)) > std::min(std::max(as.z, ae.z), std::max(bs.z, be.z))) return false; - - return ((bs - as).cross(ae - as)).magnitudeSquared() < 1e-12f && ((be - as).cross(ae - as)).magnitudeSquared() < 1e-12f; } -void ChunkPostProcessor::relax(int32_t iteration, float factor, std::vector<Vertex>& vertices) +void Triangulator::computePositionedMapping() { - std::vector<PxVec3> verticesTemp(vertices.size()); - std::vector<PxVec3> normalsTemp(vertices.size()); - for (int32_t iter = 0; iter < iteration; ++iter) - { - for (uint32_t i = 0; i < vertices.size(); ++i) - { - if (mRestrictionFlag[i]) - { - continue; - } - PxVec3 cps = vertices[i].p; - PxVec3 cns = mVerticesNormalsSmoothed[i]; - PxVec3 averaged(0, 0, 0); - PxVec3 averagedNormal(0, 0, 0); - - for (uint32_t p = 0; p < mGeometryGraph[mPositionMappedVrt[i]].size(); ++p) - { - int32_t to = mGeometryGraph[mPositionMappedVrt[i]][p]; - averaged += vertices[to].p; - averagedNormal += mVerticesNormalsSmoothed[to]; - - } - averaged *= (1.0f / mGeometryGraph[mPositionMappedVrt[i]].size()); - averagedNormal *= (1.0f / mGeometryGraph[mPositionMappedVrt[i]].size()); - verticesTemp[i] = cps + (averaged - cps) * factor; - normalsTemp[i] = cns * (1.0f - factor) + averagedNormal * factor; - } - for (uint32_t i = 0; i < vertices.size(); ++i) - { - if (mRestrictionFlag[i]) - { - continue; - } - vertices[i].p = verticesTemp[i]; - mVerticesNormalsSmoothed[i] = normalsTemp[i].getNormalized(); - - } - } - -} - -void ChunkPostProcessor::prebuildEdgeFlagArray() -{ - mRestrictionFlag.clear(); - mRestrictionFlag.resize(mVertices.size()); - mEdgeFlag.clear(); - mEdgeFlag.resize(mTrMeshEdges.size(), NONE); - std::map<PxVec3, int32_t, VrtPositionComparator> mPosMap; mPositionMappedVrt.clear(); - mPositionMappedVrt.resize(mVertices.size(), 0); + mPositionMappedVrt.resize(mVertices.size()); for (uint32_t i = 0; i < mVertices.size(); ++i) { @@ -1280,159 +583,6 @@ void ChunkPostProcessor::prebuildEdgeFlagArray() mPositionMappedVrt[i] = it->second; } } - - std::map<Edge, int32_t> mPositionEdgeMap; - std::vector<int32_t> mPositionBasedEdges(mTrMeshEdges.size()); - - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - Edge tmp = Edge(mPositionMappedVrt[mTrMeshEdges[i].s], mPositionMappedVrt[mTrMeshEdges[i].e]); - if (tmp.e < tmp.s) std::swap(tmp.e, tmp.s); - auto it = mPositionEdgeMap.find(tmp); - if (it == mPositionEdgeMap.end()) - { - mPositionEdgeMap[tmp] = i; - mPositionBasedEdges[i] = i; - } - else - { - mPositionBasedEdges[i] = it->second; - } - } - - std::vector<EdgeFlag> shortMarkup(mTrMeshEdges.size(), NONE); - std::vector<int32_t> lastOwner(mTrMeshEdges.size(), 0); - - std::vector<std::vector<int32_t> > edgeOverlap(mTrMeshEdges.size()); - for (auto it1 = mPositionEdgeMap.begin(); it1 != mPositionEdgeMap.end(); ++it1) - { - auto it2 = it1; - it2++; - for (; it2 != mPositionEdgeMap.end(); ++it2) - { - Edge& ed1 = mTrMeshEdges[it1->second]; - Edge& ed2 = mTrMeshEdges[it2->second]; - - if (edgeOverlapTest(mVertices[ed1.s].p, mVertices[ed1.e].p, mVertices[ed2.s].p, mVertices[ed2.e].p)) - { - edgeOverlap[it1->second].push_back(it2->second); - } - } - } - - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - int32_t ui = mTesselatedMeshTriangles[i].userInfo; - int32_t ed = mPositionBasedEdges[findEdge(Edge(mTesselatedMeshTriangles[i].ea, mTesselatedMeshTriangles[i].eb))]; - - - markEdge(ui, ed, shortMarkup, lastOwner); - for (uint32_t ov = 0; ov < edgeOverlap[ed].size(); ++ov) - { - markEdge(ui, edgeOverlap[ed][ov], shortMarkup, lastOwner); - } - - ed = mPositionBasedEdges[findEdge(Edge(mTesselatedMeshTriangles[i].ea, mTesselatedMeshTriangles[i].ec))]; - markEdge(ui, ed, shortMarkup, lastOwner); - for (uint32_t ov = 0; ov < edgeOverlap[ed].size(); ++ov) - { - markEdge(ui, edgeOverlap[ed][ov], shortMarkup, lastOwner); - } - - ed = mPositionBasedEdges[findEdge(Edge(mTesselatedMeshTriangles[i].eb, mTesselatedMeshTriangles[i].ec))]; - markEdge(ui, ed, shortMarkup, lastOwner); - for (uint32_t ov = 0; ov < edgeOverlap[ed].size(); ++ov) - { - markEdge(ui, edgeOverlap[ed][ov], shortMarkup, lastOwner); - } - - } - - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - mEdgeFlag[i] = shortMarkup[mPositionBasedEdges[i]]; - } - - for (uint32_t i = 0; i < mTesselatedMeshTriangles.size(); ++i) - { - if (mTesselatedMeshTriangles[i].userInfo != 0) continue; - - int32_t ed = findEdge(Edge(mTesselatedMeshTriangles[i].ea, mTesselatedMeshTriangles[i].eb)); - mEdgeFlag[ed] = EXTERNAL_EDGE; - ed = findEdge(Edge(mTesselatedMeshTriangles[i].ec, mTesselatedMeshTriangles[i].eb)); - mEdgeFlag[ed] = EXTERNAL_EDGE; - ed = findEdge(Edge(mTesselatedMeshTriangles[i].ea, mTesselatedMeshTriangles[i].ec)); - mEdgeFlag[ed] = EXTERNAL_EDGE; - } -} - - - -void ChunkPostProcessor::tesselateInternalSurface(float maxLenIn) -{ - mTesselatedMeshTriangles = mBaseMeshTriangles; - if (mTesselatedMeshTriangles.empty()) - { - return; - } - - updateEdgeTriangleInfo(); - prebuildEdgeFlagArray(); - mRestrictionFlag.resize(mVertices.size(), 0); - for (uint32_t i = 0; i < mTrMeshEdges.size(); ++i) - { - if (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == EXTERNAL_BORDER_EDGE || mEdgeFlag[i] == INTERNAL_BORDER_EDGE) - { - mRestrictionFlag[mTrMeshEdges[i].s] = 1; - mRestrictionFlag[mTrMeshEdges[i].e] = 1; - } - } - - - float maxLen = std::max(0.1f, maxLenIn); - while (maxLen > maxLenIn) - { - float mlSq = maxLen * maxLen; - float minD = maxLen * 0.5f; - minD = minD * minD; - - for (int32_t iter = 0; iter < 15; ++iter) - { - updateVertEdgeInfo(); - uint32_t oldSize = (uint32_t)mTrMeshEdges.size(); - for (uint32_t i = 0; i < oldSize; ++i) - { - if (mEdgeFlag[i] == EXTERNAL_EDGE || mEdgeFlag[i] == INTERNAL_BORDER_EDGE) - { - continue; - } - if ((mVertices[mTrMeshEdges[i].s].p - mVertices[mTrMeshEdges[i].e].p).magnitudeSquared() < minD) - { - collapseEdge(i); - } - } - - oldSize = (uint32_t)mTrMeshEdges.size(); - updateEdgeTriangleInfo(); - for (uint32_t i = 0; i < oldSize; ++i) - { - if (mEdgeFlag[i] == EXTERNAL_EDGE) - { - continue; - } - if ((mVertices[mTrMeshEdges[i].s].p - mVertices[mTrMeshEdges[i].e].p).magnitudeSquared() > mlSq) - { - divideEdge(i); - } - } - } - maxLen *= 0.3; - maxLen = std::max(maxLen, maxLenIn); - } - computeFalloffAndNormals(); - prebuildTesselatedTriangles(); - isTesselated = true; } } // namespace Blast |