7 #include "imstkSurfaceMeshTextureProject.h" 8 #include "imstkLogger.h" 9 #include "imstkParallelUtils.h" 10 #include "imstkSurfaceMesh.h" 11 #include "imstkVecDataArray.h" 16 closestPointOnTriangle(
const Vec3d& p,
const Vec3d& a,
const Vec3d& b,
const Vec3d& c,
int& caseType)
18 const Vec3d ab = b - a;
19 const Vec3d ac = c - a;
20 const Vec3d ap = p - a;
22 const double d1 = ab.dot(ap);
23 const double d2 = ac.dot(ap);
24 if (d1 <= 0.0 && d2 <= 0.0)
31 const Vec3d bp = p - b;
32 const double d3 = ab.dot(bp);
33 const double d4 = ac.dot(bp);
34 if (d3 >= 0.0 && d4 <= d3)
40 const double vc = d1 * d4 - d3 * d2;
41 if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0)
44 double v = d1 / (d1 - d3);
49 const Vec3d cp = p - c;
50 const double d5 = ab.dot(cp);
51 const double d6 = ac.dot(cp);
52 if (d6 >= 0.0 && d5 <= d6)
59 const double vb = d5 * d2 - d1 * d6;
60 if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0)
63 double w = d2 / (d2 - d6);
68 const double va = d3 * d6 - d5 * d4;
69 if (va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0)
72 double w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
73 return b + w * (c - b);
77 const double denom = 1.0 / (va + vb + vc);
78 const double v = vb * denom;
79 const double w = vc * denom;
81 return a + ab * v + ac * w;
86 baryInterpolate(T v1, T v2, T v3, Vec3d uvw)
88 return v1 * uvw[0] + v2 * uvw[1] + v3 * uvw[2];
91 SurfaceMeshTextureProject::SurfaceMeshTextureProject()
94 setRequiredInputType<SurfaceMesh>(0);
95 setRequiredInputType<SurfaceMesh>(1);
98 setOutput(std::make_shared<SurfaceMesh>(), 0);
113 std::shared_ptr<SurfaceMesh>
122 std::shared_ptr<SurfaceMesh> inputSrcMesh = std::dynamic_pointer_cast<
SurfaceMesh>(
getInput(0));
123 std::shared_ptr<SurfaceMesh> inputDestMesh = std::dynamic_pointer_cast<
SurfaceMesh>(
getInput(1));
124 std::shared_ptr<SurfaceMesh> outputDestMesh = std::dynamic_pointer_cast<
SurfaceMesh>(
getOutput(0));
125 *outputDestMesh = *inputDestMesh->
clone();
127 if (inputSrcMesh ==
nullptr || inputDestMesh ==
nullptr)
129 LOG(WARNING) <<
"Missing input surface mesh";
133 std::shared_ptr<VecDataArray<double, 3>> srcVerticesPtr = inputSrcMesh->getVertexPositions();
135 std::shared_ptr<VecDataArray<int, 3>> srcCellsPtr = inputSrcMesh->getCells();
137 std::shared_ptr<VecDataArray<float, 2>> srcTCoordsPtr = inputSrcMesh->getVertexTCoords();
138 if (srcTCoordsPtr ==
nullptr)
140 LOG(WARNING) <<
"inputSrcMesh does not have texture coordinates";
145 std::shared_ptr<VecDataArray<double, 3>> destVerticesPtr = inputDestMesh->getVertexPositions();
147 auto outputDestTCoordsPtr = std::make_shared<VecDataArray<float, 2>>(destVertices.size());
148 outputDestMesh->setVertexTCoords(inputSrcMesh->getActiveVertexTCoords(), outputDestTCoordsPtr);
152 for (
int i = 0; i < destVertices.size(); i++)
154 const Vec3d& pos = destVertices[i];
155 double minDistSqr = IMSTK_DOUBLE_MAX;
156 int closestCellI = -1;
157 Vec3d closestPt = Vec3d::Zero();
160 for (
int j = 0; j < srcCells.size(); j++)
162 const Vec3i& cell = srcCells[j];
163 const Vec3d& a = srcVertices[cell[0]];
164 const Vec3d& b = srcVertices[cell[1]];
165 const Vec3d& c = srcVertices[cell[2]];
168 const Vec3d ptOnTri = closestPointOnTriangle(pos, a, b, c, caseType);
169 const double sqrDist = (ptOnTri - pos).squaredNorm();
170 if (sqrDist < minDistSqr)
172 minDistSqr = sqrDist;
179 const Vec3i& closestCell = srcCells[closestCellI];
180 const Vec2f& va = inputTexCoords[closestCell[0]];
181 const Vec2f& vb = inputTexCoords[closestCell[1]];
182 const Vec2f& vc = inputTexCoords[closestCell[2]];
183 const Vec3d& a = srcVertices[closestCell[0]];
184 const Vec3d& b = srcVertices[closestCell[1]];
185 const Vec3d& c = srcVertices[closestCell[2]];
186 const Vec3d uvw = baryCentric(closestPt, a, b, c);
187 const Vec2f val = uvw[0] * va + uvw[1] * vb + uvw[2] * vc;
188 outputTexCoords[i] = val;
std::shared_ptr< Geometry > getInput(size_t port=0) const
Returns input geometry given port, returns nullptr if doesn't exist.
void setDestMesh(std::shared_ptr< SurfaceMesh > destMesh)
The mesh to recieve the attribute.
void requestUpdate() override
Users can implement this for the logic to be run.
std::unique_ptr< SurfaceMesh > clone()
Polymorphic clone, hides the declaration in superclass return own type.
void setNumOutputPorts(const size_t numPorts)
Get/Set the amount of output ports.
std::shared_ptr< Geometry > getOutput(size_t port=0) const
Returns output geometry given port, returns nullptr if doesn't exist.
void setInput(std::shared_ptr< Geometry > inputGeometry, size_t port=0)
Set the input at the port.
Represents a set of triangles & vertices via an array of Vec3d double vertices & Vec3i integer indice...
void setSourceMesh(std::shared_ptr< SurfaceMesh > surfMesh)
The mesh with attribute to put on the other.
void setOutput(std::shared_ptr< Geometry > inputGeometry, const size_t port=0)
Set the output at the port.
void setNumInputPorts(const size_t numPorts)
Get/Set the amount of input ports.
std::shared_ptr< SurfaceMesh > getOutputMesh()
destMesh copy with the attribute