Commit 03307cf2 authored by Sreekanth Arikatla's avatar Sreekanth Arikatla
Browse files

Merge branch 'fixWindingOrderOfSurfMesh' into 'master'

ENH: Fix winding order of surface mesh to enforce consistency

See merge request !198
parents 7eff1f6c c680c6c2
......@@ -340,4 +340,117 @@ SurfaceMesh::getDefaultTCoords()
{
return m_defaultTCoords;
}
void
SurfaceMesh::flipNormals()
{
for (auto& tri : m_trianglesVertices)
{
auto temp = tri[0];
tri[0] = tri[1];
tri[1] = temp;
}
}
void
SurfaceMesh::correctWindingOrder()
{
// Enforce consistency in winding of a particular triangle with its neighbor (master)
auto enforceWindingConsistency =
[this](const size_t masterTriId, const size_t neighTriId)
{
const auto& masterTri = m_trianglesVertices[masterTriId];
auto& neighTri = m_trianglesVertices[neighTriId];
for (unsigned int l = 0; l < 3; ++l)
{
for (unsigned int k = 0; k < 3; ++k)
{
if (masterTri[k] == neighTri[l] && masterTri[(k + 1) % 3] == neighTri[(l + 1) % 3])
{
// Flip the order of neighbor triangle
auto tempId = neighTri[0];
neighTri[0] = neighTri[1];
neighTri[1] = tempId;
break;
}
}
}
};
// Search for triangle neighbors that share a common edge
auto getTriangleNeighbors =
[this](const size_t triID, int* neig)
{
const auto& currentTri = m_trianglesVertices[triID];
size_t currentId = 0;
int numNeigh = 0;
for (auto& tri : m_trianglesVertices)
{
if (triID == currentId)
{
currentId++;
continue;
}
int numCommon = 0;
for (int i = 0; i < 3; ++i)
{
if (currentTri[i] == tri[0] || currentTri[i] == tri[1] || currentTri[i] == tri[2])
{
numCommon++;
if (numCommon == 2)
{
neig[numNeigh] = (int)currentId;
numNeigh++;
if (numNeigh == 3)
{
return;
}
else
{
break;
}
}
}
}
currentId++;
}
};
// Start with a reference triangle and enforce the consistency of its neighbors
// Keep track of those neighbor triangles whose order is enforced but its neighbors not
// necessarily enforced (trianglesCorrected). Continue this until there is no
// triangle left in the list
std::vector<bool> trianglesCorrected(this->getNumTriangles(), false);
std::vector<size_t> correctedTriangles;
size_t currentTriangle = 0; // Start with triangle 0
correctedTriangles.push_back(currentTriangle);
trianglesCorrected[currentTriangle] = true;
do
{
currentTriangle = correctedTriangles[0];
int neighborTri[3] = {-1, -1, -1};
getTriangleNeighbors(currentTriangle, &neighborTri[0]);
for (int i = 0; i < 3; ++i)
{
if (neighborTri[i] >= 0 && !trianglesCorrected[neighborTri[i]])
{
enforceWindingConsistency(currentTriangle, neighborTri[i]);
correctedTriangles.push_back(neighborTri[i]);
trianglesCorrected[neighborTri[i]] = true;
}
}
correctedTriangles.erase(std::remove(correctedTriangles.begin(),
correctedTriangles.end(),
currentTriangle),
correctedTriangles.end());
}
while (correctedTriangles.size() > 0);
}
} // imstk
......@@ -151,6 +151,16 @@ public:
void setDefaultTCoords(std::string arrayName);
std::string getDefaultTCoords();
///
/// \brief Flip the normals for the whole mesh by reversing the winding order
///
void flipNormals();
///
/// \brief Enforces consistency in the winding order of the triangles
///
void correctWindingOrder();
protected:
std::vector<TriangleArray> m_trianglesVertices; ///> Triangle connectivity
......
......@@ -108,7 +108,7 @@ TetrahedralMesh::computeAttachedSurfaceMesh()
}
bool
TetrahedralMesh::extractSurfaceMesh(std::shared_ptr<SurfaceMesh> surfaceMesh)
TetrahedralMesh::extractSurfaceMesh(std::shared_ptr<SurfaceMesh> surfaceMesh, const bool enforceWindingConsistency /* = false*/)
{
if (!surfaceMesh)
{
......@@ -219,6 +219,11 @@ TetrahedralMesh::extractSurfaceMesh(std::shared_ptr<SurfaceMesh> surfaceMesh)
// Create and attach surface mesh
surfaceMesh->initialize(vertPositions, surfaceTri);
if (enforceWindingConsistency)
{
surfaceMesh->correctWindingOrder();
}
return true;
}
......
......@@ -86,7 +86,8 @@ public:
/// (a) Extracts the confirming triangular mesh from the tetrahedral mesh
/// (b) Checks and flips the triangle connectivity order if it is not consistent
/// (c) Renumbers the vertices
bool extractSurfaceMesh(std::shared_ptr<SurfaceMesh> surfaceMesh);
/// (d) optionally enforces the consistency of winding of resulting surface triangles
bool extractSurfaceMesh(std::shared_ptr<SurfaceMesh> surfaceMesh, const bool enforceWindingConsistency = false);
///
/// \brief compute the barycentric weights of a given point in 3D space for a given the tetrahedra
......
......@@ -1331,7 +1331,11 @@ void testPbdVolume()
LOG(WARNING) << "Dynamic pointer cast from imstk::Mesh to imstk::TetrahedralMesh failed!";
return;
}
volTetMesh->extractSurfaceMesh(surfMesh);
volTetMesh->extractSurfaceMesh(surfMesh, true);
auto material = std::make_shared<RenderMaterial>();
material->setDisplayMode(RenderMaterial::DisplayMode::WIREFRAME_SURFACE);
surfMesh->setRenderMaterial(material);
// d. Construct a map
......@@ -3422,7 +3426,7 @@ int main()
Test physics
------------------*/
testPbdVolume();
testPbdCloth();
//testPbdCloth();
//testPbdCollision();
//testPbdFluidBenchmarking();
//testPbdFluid();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment