Commit 3662ebfb authored by Sreekanth Arikatla's avatar Sreekanth Arikatla
Browse files

WIP: Extracts surface mesh from TetrahedralMesh

Adds surface mesh extraction from tetrahedral mesh
TODO: code style check and test
parent 7728413f
......@@ -118,4 +118,13 @@ Mesh::computeBoundingBox(Vec3d& min, Vec3d& max, const double percent) const
max = max + range*(percent / 100);
}
}
void
Mesh::clear()
{
m_initialVerticesPositions.clear();
m_verticesPositions.clear();
m_verticesDisplacements.clear();
}
}
......@@ -49,6 +49,10 @@ public:
void computeBoundingBox(Vec3d& min, Vec3d& max, const double percent = 0.0) const;
///
/// \brief Clear all the mesh data
///
virtual void clear();
protected:
Mesh(GeometryType type) : Geometry(type, WORLD_ORIGIN, Quatd()) {}
......
......@@ -22,7 +22,24 @@
#include "imstkSurfaceMesh.h"
namespace imstk {
void
void SurfaceMesh::initialize(const std::vector<Vec3d>& vertices,
const std::vector<TriangleArray>& triangles,
const std::vector<Vec2f>& texCoords,
const bool computDerivedData)
{
this->clear();
setInitialVerticesPositions(vertices);
setInitialVerticesPositions(vertices);
setTrianglesVertices(triangles);
setTextureCoordinates(texCoords);
computeVerticesNormals();
computeTrianglesNormals();
computeVerticesTangents();
}
void
SurfaceMesh::computeVerticesNeighborTriangles()
{
m_verticesNeighborTriangles.resize(m_verticesPositions.size());
......@@ -261,4 +278,18 @@ SurfaceMesh::getVolume() const
return 0.0;
}
void
SurfaceMesh::clear()
{
m_trianglesVertices.clear();
m_textureCoordinates.clear();
m_verticesNeighborTriangles.clear();
m_verticesNeighborVertices.clear();
m_trianglesNormals.clear();
m_verticesNormals.clear();
m_verticesTangents.clear();
Mesh::clear();
}
}
......@@ -39,6 +39,15 @@ public:
~SurfaceMesh() = default;
///
/// \brief Initializes the rest of the data structures gives vertex positions and
/// triangle connectivity
///
void initialize(const std::vector<Vec3d>& vertices,
const std::vector<TriangleArray>& triangles,
const std::vector<Vec2f>& texCoords = std::vector<Vec2f>(),
const bool computDerivedData = false);
void computeVerticesNeighborTriangles();
void computeVerticesNeighborVertices();
void computeTrianglesNormals();
......@@ -63,6 +72,10 @@ public:
double getVolume() const;
///
/// \brief Clear all the mesh data
///
void clear();
protected:
std::vector<TriangleArray> m_trianglesVertices;
......
......@@ -127,9 +127,174 @@ TetrahedralMesh::computeTetrahedronBoundingBox(const size_t& tetId, Vec3d& min,
max[2] = *std::max_element(arrayz.begin(), arrayz.end());
}
bool TetrahedralMesh::extractSurfaceMesh(std::shared_ptr<TetrahedralMesh> tetMesh,
std::shared_ptr<SurfaceMesh> surfaceMesh)
// TODO: Test pending
bool
TetrahedralMesh::extractSurfaceMesh(std::shared_ptr<SurfaceMesh> surfaceMesh)
{
if (surfaceMesh)
{
LOG(WARNING) << "Cannot extract SurfaceMesh: The surface mesh provided is not instantiated!";
return false;
}
const SurfaceMesh::TriangleArray facePattern[4] = { { 0, 1, 2 }, { 0, 1, 3}, {0, 2, 3}, {1, 2, 3} };
// Find number of common vertices
auto getNumCommonVerts = [](const TetraArray& array1, const TetraArray& array2, SurfaceMesh::TriangleArray& commonFace) -> int
{
int numCommonVerts = 0;
SurfaceMesh::TriangleArray tmpFace;
for (size_t i = 0; i < 4; ++i)
{
if (array1[i] == array2[0] || array1[i] == array2[1] || array1[i] == array2[2] || array1[i] == array2[3])
{
tmpFace.at(numCommonVerts) = i;
numCommonVerts++;
}
}
if (numCommonVerts == 3)
{
commonFace = tmpFace;
}
return numCommonVerts;
};
// Find the common face
auto findCommonFace = [facePattern](const TetraArray& tetVertArray, const SurfaceMesh::TriangleArray& triVertArray) -> int
{
for (size_t i; i < 4; ++i)
{
auto vertId = tetVertArray[i];
if (vertId != triVertArray[0] && vertId != triVertArray[1] && vertId != triVertArray[2])
{
for (size_t j; j < 4; ++j)
{
if (i != facePattern[j][0] && i != facePattern[j][1] && i != facePattern[j][2])
{
return j;
}
}
}
}
};
// Find and store the tetrahedral faces that are unique
std::vector<SurfaceMesh::TriangleArray> surfaceTri;
std::vector<int> surfaceTriTet;
std::vector<int> tetRemainingVert;
auto vertArray = this->getTetrahedraVertices();
SurfaceMesh::TriangleArray possibleFaces[4];
SurfaceMesh::TriangleArray commonFace;
bool foundFaces[4];
for (size_t tetId; tetId < this->getNumTetrahedra(); ++tetId)
{
auto tetVertArray = vertArray.at(tetId);
foundFaces[0] = foundFaces[1] = foundFaces[2] = foundFaces[3] = false;
for (size_t tetIdInner; tetIdInner < this->getNumTetrahedra(); ++tetIdInner)
{
auto tetVertArrayInner = vertArray.at(tetIdInner);
// check if there is common face
if (getNumCommonVerts(tetVertArray, tetVertArrayInner, commonFace) == 3)
{
foundFaces[findCommonFace(tetVertArray, commonFace)] = true;
}
// break if all the faces are already found
if (foundFaces[0] && foundFaces[1] && foundFaces[2] && foundFaces[3])
{
break;
}
}
// break if all the faces are already found
if (foundFaces[0] && foundFaces[1] && foundFaces[2] && foundFaces[3])
{
break;
}
else
{
for (size_t faceId = 0; faceId < 4; ++faceId)
{
possibleFaces[faceId] = SurfaceMesh::TriangleArray{ {
tetVertArray[facePattern[faceId].at(0)],
tetVertArray[facePattern[faceId].at(1)],
tetVertArray[facePattern[faceId].at(2)] } };
if (foundFaces[faceId] == false)
{
surfaceTri.push_back(possibleFaces[faceId]);
surfaceTriTet.push_back(tetId);
tetRemainingVert.push_back(3 - faceId);
}
}
}
}
// Arrange the surface triangle faces found in order
Vec3d v0, v1, v2;
Vec3d centroid;
Vec3d normal;
for (size_t faceId = 0; faceId < surfaceTri.size(); ++faceId)
{
v0 = this->getVertexPosition(surfaceTri.at(faceId)[0]);
v1 = this->getVertexPosition(surfaceTri.at(faceId)[1]);
v2 = this->getVertexPosition(surfaceTri.at(faceId)[2]);
centroid = (v0 + v1 + v2) / 3;
normal = ((v0 - v1).cross(v0 - v2));
normal.normalize();
if (normal.dot(centroid - this->getVertexPosition(tetRemainingVert.at(faceId))) > 0)
{
// swap
int tmpIndex = surfaceTri[faceId][3];
surfaceTri[faceId][3] = surfaceTri[faceId][2];
surfaceTri[faceId][3] = tmpIndex;
}
}
// Renumber the vertices
std::list<int> uniqueVertIdList;
for (auto &face : surfaceTri)
{
uniqueVertIdList.push_back(face[0]);
uniqueVertIdList.push_back(face[1]);
uniqueVertIdList.push_back(face[2]);
}
uniqueVertIdList.unique();
int vertId;
std::list<int>::iterator it;
std::vector<Vec3d> vertPositions;
for (vertId, it = uniqueVertIdList.begin(); it != uniqueVertIdList.end(); ++vertId, it++)
{
vertPositions.push_back(this->getVertexPosition(*it));
for (auto &face : surfaceTri)
{
for (size_t i = 0; i < 4; ++i)
{
if (face[i] == *it)
{
face[i] = vertId;
}
}
}
}
// add vertices and triangles
surfaceMesh->initialize(vertPositions, surfaceTri);
return true;
}
void
TetrahedralMesh::clear()
{
m_tetrahedraVertices.clear();
Mesh::clear();
}
}
......@@ -23,6 +23,7 @@
#define imstkTetrahedralMesh_h
#include <set>
#include <list>
#include "imstkVolumetricMesh.h"
......@@ -78,9 +79,12 @@ public:
///
/// \brief Extract the confirming triangular mesh from the tetrahedral mesh
///
static bool extractSurfaceMesh(std::shared_ptr<TetrahedralMesh> tetMesh,
std::shared_ptr<SurfaceMesh> surfaceMesh);
bool extractSurfaceMesh(std::shared_ptr<SurfaceMesh> surfaceMesh);
///
/// \brief Clear all the mesh data
///
void clear();
protected:
std::vector<TetraArray> m_tetrahedraVertices; ///< vertices of the tetrahedra
......
Markdown is supported
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