Skip to content

Commit d1dbf33

Browse files
committed
pick barycoords in selection
1 parent 77c45f0 commit d1dbf33

File tree

4 files changed

+52
-5
lines changed

4 files changed

+52
-5
lines changed

include/polyscope/elementary_geometry.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99

1010
namespace polyscope {
1111

12+
// Compute t \in [0,1] for a point along hte line from lineStart -- lineEnd
1213
float computeTValAlongLine(glm::vec3 queryP, glm::vec3 lineStart, glm::vec3 lineEnd);
1314

15+
// Project a point onto a plane. planeNormal must be unit
16+
glm::vec3 projectToPlane(glm::vec3 queryP, glm::vec3 planeNormal, glm::vec3 pointOnPlane);
17+
18+
// Compute the signed area of triangle ABC which lies in the plane give by normal
19+
float signedTriangleArea(glm::vec3 normal, glm::vec3 pA, glm::vec3 pB, glm::vec3 pC);
1420

1521
}

include/polyscope/surface_mesh.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ struct QuantityTypeHelper<SurfaceMesh> {
5252
};
5353

5454
struct SurfaceMeshPickResult {
55-
MeshElement elementType; // which kind of element did we click
56-
int64_t index; // index of the clicked element
55+
MeshElement elementType; // which kind of element did we click
56+
int64_t index; // index of the clicked element
57+
glm::vec3 baryCoords = glm::vec3{-1., -1., -1}; // coordinates in face, populated only for triangular face picks
5758
};
5859

5960
// === The grand surface mesh class

src/elementary_geometry.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,17 @@ float computeTValAlongLine(glm::vec3 queryP, glm::vec3 lineStart, glm::vec3 line
1919
return t;
2020
}
2121

22+
glm::vec3 projectToPlane(glm::vec3 queryP, glm::vec3 planeNormal, glm::vec3 pointOnPlane) {
23+
glm::vec3 pVec = queryP - pointOnPlane;
24+
glm::vec3 pVecOrtho = glm::dot(pVec, planeNormal) * planeNormal;
25+
return queryP - pVecOrtho;
26+
}
27+
28+
float signedTriangleArea(glm::vec3 normal, glm::vec3 pA, glm::vec3 pB, glm::vec3 pC) {
29+
glm::vec3 cross = glm::cross(pB - pA, pC - pA);
30+
float sign = glm::sign(glm::dot(normal, cross));
31+
float area = glm::length(cross) / 2.;
32+
return sign * area;
33+
}
34+
2235
} // namespace polyscope

src/surface_mesh.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
#include "polyscope/surface_mesh.h"
44

5-
#include "glm/fwd.hpp"
65
#include "polyscope/combining_hash_functions.h"
6+
#include "polyscope/elementary_geometry.h"
77
#include "polyscope/pick.h"
88
#include "polyscope/polyscope.h"
99
#include "polyscope/render/engine.h"
@@ -1170,6 +1170,11 @@ void SurfaceMesh::buildFaceInfoGui(const SurfaceMeshPickResult& result) {
11701170
size_t displayInd = fInd;
11711171
ImGui::TextUnformatted(("Face #" + std::to_string(displayInd)).c_str());
11721172

1173+
if (result.baryCoords != glm::vec3{-1., -1., -1.}) {
1174+
ImGui::Text("selected barycoords = <%.3f, %.3f, %.3f>", result.baryCoords.x, result.baryCoords.y,
1175+
result.baryCoords.z);
1176+
}
1177+
11731178
ImGui::Spacing();
11741179
ImGui::Spacing();
11751180
ImGui::Spacing();
@@ -1446,18 +1451,40 @@ SurfaceMeshPickResult SurfaceMesh::interpretPickResult(const PickResult& rawResu
14461451
result.index = rawResult.localIndex - facePickIndStart;
14471452

14481453
// TODO barycoords
1454+
size_t D = faceIndsStart[result.index + 1] - faceIndsStart[result.index];
1455+
if (D == 3) {
1456+
1457+
// gather values and project onto plane
1458+
size_t iStart = faceIndsStart[result.index];
1459+
uint32_t vA = faceIndsEntries[iStart];
1460+
uint32_t vB = faceIndsEntries[iStart + 1];
1461+
uint32_t vC = faceIndsEntries[iStart + 2];
1462+
glm::vec3 pA = vertexPositions.getValue(vA);
1463+
glm::vec3 pB = vertexPositions.getValue(vB);
1464+
glm::vec3 pC = vertexPositions.getValue(vC);
1465+
glm::vec3 normal = glm::normalize(glm::cross(pB - pA, pC - pA));
1466+
glm::vec3 x = projectToPlane(rawResult.position, normal, pA);
1467+
1468+
// compute barycentric coordinates as ratio of signed areas
1469+
float areaABC = signedTriangleArea(normal, pA, pB, pC);
1470+
float areaXBC = signedTriangleArea(normal, x, pB, pC);
1471+
float areaXCA = signedTriangleArea(normal, x, pC, pA);
1472+
float areaXAB = signedTriangleArea(normal, x, pA, pB);
1473+
glm::vec3 barycoord{areaXBC / areaABC, areaXCA / areaABC, areaXAB / areaABC};
1474+
result.baryCoords = barycoord;
1475+
}
1476+
14491477
} else if (rawResult.localIndex < halfedgePickIndStart) {
14501478
// Edge pick
14511479
result.elementType = MeshElement::EDGE;
14521480
result.index = rawResult.localIndex - edgePickIndStart;
14531481

1454-
// TODO tEdge
1482+
14551483
} else if (rawResult.localIndex < cornerPickIndStart) {
14561484
// Halfedge pick
14571485
result.elementType = MeshElement::HALFEDGE;
14581486
result.index = rawResult.localIndex - halfedgePickIndStart;
14591487

1460-
// TODO tEdge
14611488
} else if (rawResult.localIndex < cornerPickIndStart + nCorners()) {
14621489
// Corner pick
14631490
result.elementType = MeshElement::CORNER;

0 commit comments

Comments
 (0)