Skip to content

Commit e941b92

Browse files
cdtwiggfacebook-github-bot
authored andcommitted
Handle polygon fields in mesh subset operations
Summary: reduceMeshInternal (used by reduceMeshByFaces, reduceMeshByVertices, and reduceMeshComponents) didn't handle the polyFaces/polyFaceSizes/polyTexcoordFaces fields. After a mesh subset operation, the polygon data would be stale. Add remapPolyFaces helper to filter and remap polygon data during mesh reduction, using the same active-vertex logic as triangulated faces. Also add verticesToPolys, polysToVertices conversion functions and reduceMeshByPolys for selecting mesh subsets by polygon. Differential Revision: D94579400
1 parent 88cc0e7 commit e941b92

File tree

3 files changed

+381
-3
lines changed

3 files changed

+381
-3
lines changed

momentum/character/character_utility.cpp

Lines changed: 178 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,47 @@ std::vector<Eigen::Vector3i> remapFaces(
845845
return remappedFaces;
846846
}
847847

848+
template <typename T>
849+
void remapPolyFaces(
850+
MeshT<T>& newMesh,
851+
const MeshT<T>& mesh,
852+
const std::vector<bool>& activeVertices,
853+
const std::vector<size_t>& reverseVertexMapping,
854+
const std::vector<size_t>& reverseTexcoordMapping) {
855+
if (mesh.polyFaces.empty()) {
856+
return;
857+
}
858+
859+
uint32_t offset = 0;
860+
for (const auto polySize : mesh.polyFaceSizes) {
861+
// Check if all vertices of this polygon are active
862+
bool allActive = true;
863+
for (uint32_t i = 0; i < polySize; ++i) {
864+
const auto vtx = mesh.polyFaces[offset + i];
865+
if (vtx >= activeVertices.size() || !activeVertices[vtx]) {
866+
allActive = false;
867+
break;
868+
}
869+
}
870+
871+
if (allActive) {
872+
newMesh.polyFaceSizes.push_back(polySize);
873+
for (uint32_t i = 0; i < polySize; ++i) {
874+
newMesh.polyFaces.push_back(
875+
static_cast<uint32_t>(reverseVertexMapping[mesh.polyFaces[offset + i]]));
876+
}
877+
if (!mesh.polyTexcoordFaces.empty()) {
878+
for (uint32_t i = 0; i < polySize; ++i) {
879+
newMesh.polyTexcoordFaces.push_back(
880+
static_cast<uint32_t>(reverseTexcoordMapping[mesh.polyTexcoordFaces[offset + i]]));
881+
}
882+
}
883+
}
884+
885+
offset += polySize;
886+
}
887+
}
888+
848889
std::vector<std::vector<int32_t>> remapLines(
849890
const std::vector<std::vector<int32_t>>& lines,
850891
const std::vector<size_t>& mapping) {
@@ -923,6 +964,50 @@ std::vector<bool> facesToVertices(
923964
return activeVertices;
924965
}
925966

967+
std::vector<bool> verticesToPolys(
968+
const std::vector<uint32_t>& polyFaces,
969+
const std::vector<uint32_t>& polyFaceSizes,
970+
const std::vector<bool>& activeVertices) {
971+
std::vector<bool> activePolys(polyFaceSizes.size(), false);
972+
uint32_t offset = 0;
973+
for (size_t polyIdx = 0; polyIdx < polyFaceSizes.size(); ++polyIdx) {
974+
const auto polySize = polyFaceSizes[polyIdx];
975+
bool allActive = true;
976+
for (uint32_t i = 0; i < polySize; ++i) {
977+
const auto vtx = polyFaces[offset + i];
978+
if (vtx >= activeVertices.size() || !activeVertices[vtx]) {
979+
allActive = false;
980+
break;
981+
}
982+
}
983+
activePolys[polyIdx] = allActive;
984+
offset += polySize;
985+
}
986+
return activePolys;
987+
}
988+
989+
std::vector<bool> polysToVertices(
990+
const std::vector<uint32_t>& polyFaces,
991+
const std::vector<uint32_t>& polyFaceSizes,
992+
const std::vector<bool>& activePolys,
993+
size_t vertexCount) {
994+
std::vector<bool> activeVertices(vertexCount, false);
995+
uint32_t offset = 0;
996+
for (size_t polyIdx = 0; polyIdx < polyFaceSizes.size(); ++polyIdx) {
997+
const auto polySize = polyFaceSizes[polyIdx];
998+
if (activePolys[polyIdx]) {
999+
for (uint32_t i = 0; i < polySize; ++i) {
1000+
const auto vtx = polyFaces[offset + i];
1001+
if (vtx < vertexCount) {
1002+
activeVertices[vtx] = true;
1003+
}
1004+
}
1005+
}
1006+
offset += polySize;
1007+
}
1008+
return activeVertices;
1009+
}
1010+
9261011
// Internal mesh reduction function used by both reduceMeshComponents and
9271012
// the public reduceMeshByFaces/reduceMeshByVertices for Mesh.
9281013
template <typename T>
@@ -954,22 +1039,26 @@ MeshT<T> reduceMeshInternal(
9541039
newMesh.lines = remapLines(mesh.lines, reverseVertexMapping);
9551040
}
9561041

1042+
std::vector<size_t> reverseTextureVertexMapping;
9571043
if (!mesh.texcoord_faces.empty() && !mesh.texcoords.empty()) {
9581044
std::vector<bool> activeTextureTriangles = activeFaces;
9591045
activeTextureTriangles.resize(mesh.texcoord_faces.size(), false);
9601046

9611047
const std::vector<bool> activeTextureVertices =
9621048
facesToVertices(mesh.texcoord_faces, activeTextureTriangles, mesh.texcoords.size());
9631049

964-
auto [forwardTextureVertexMapping, reverseTextureVertexMapping] =
965-
createIndexMapping(activeTextureVertices);
1050+
auto [forwardTextureVertexMapping, revTexMapping] = createIndexMapping(activeTextureVertices);
1051+
reverseTextureVertexMapping = std::move(revTexMapping);
9661052

9671053
newMesh.texcoords = selectVertices(mesh.texcoords, forwardTextureVertexMapping);
9681054
newMesh.texcoord_faces =
9691055
remapFaces(mesh.texcoord_faces, reverseTextureVertexMapping, activeTextureTriangles);
9701056
newMesh.texcoord_lines = remapLines(mesh.texcoord_lines, reverseTextureVertexMapping);
9711057
}
9721058

1059+
// Remap polygon face data
1060+
remapPolyFaces(newMesh, mesh, activeVertices, reverseVertexMapping, reverseTextureVertexMapping);
1061+
9731062
return newMesh;
9741063
}
9751064

@@ -1185,6 +1274,61 @@ std::vector<bool> facesToVertices(const MeshT<T>& mesh, const std::vector<bool>&
11851274
return facesToVertices(mesh.faces, activeFaces, mesh.vertices.size());
11861275
}
11871276

1277+
template <typename T>
1278+
std::vector<bool> verticesToPolys(const MeshT<T>& mesh, const std::vector<bool>& activeVertices) {
1279+
MT_CHECK(
1280+
activeVertices.size() == mesh.vertices.size(),
1281+
"Active vertices size ({}) does not match mesh vertex count ({})",
1282+
activeVertices.size(),
1283+
mesh.vertices.size());
1284+
1285+
return verticesToPolys(mesh.polyFaces, mesh.polyFaceSizes, activeVertices);
1286+
}
1287+
1288+
template <typename T>
1289+
std::vector<bool> polysToVertices(const MeshT<T>& mesh, const std::vector<bool>& activePolys) {
1290+
MT_CHECK(
1291+
activePolys.size() == mesh.polyFaceSizes.size(),
1292+
"Active polys size ({}) does not match polygon count ({})",
1293+
activePolys.size(),
1294+
mesh.polyFaceSizes.size());
1295+
1296+
return polysToVertices(mesh.polyFaces, mesh.polyFaceSizes, activePolys, mesh.vertices.size());
1297+
}
1298+
1299+
template <typename T>
1300+
MeshT<T> reduceMeshByPolys(const MeshT<T>& mesh, const std::vector<bool>& activePolys) {
1301+
MT_CHECK(
1302+
activePolys.size() == mesh.polyFaceSizes.size(),
1303+
"Active polys size ({}) does not match polygon count ({})",
1304+
activePolys.size(),
1305+
mesh.polyFaceSizes.size());
1306+
1307+
// Convert polygon selection to vertex selection, then to face selection
1308+
const auto activeVertices = polysToVertices(mesh, activePolys);
1309+
const auto activeFaces = verticesToFaces(mesh, activeVertices);
1310+
1311+
return reduceMeshInternal(mesh, activeVertices, activeFaces);
1312+
}
1313+
1314+
template <typename T>
1315+
CharacterT<T> reduceMeshByPolys(
1316+
const CharacterT<T>& character,
1317+
const std::vector<bool>& activePolys) {
1318+
MT_CHECK(character.mesh, "Cannot reduce mesh: character has no mesh");
1319+
MT_CHECK(
1320+
activePolys.size() == character.mesh->polyFaceSizes.size(),
1321+
"Active polys size ({}) does not match polygon count ({})",
1322+
activePolys.size(),
1323+
character.mesh->polyFaceSizes.size());
1324+
1325+
// Convert polygon selection to vertex selection, then to face selection
1326+
const auto activeVertices = polysToVertices(*character.mesh, activePolys);
1327+
const auto activeFaces = verticesToFaces(*character.mesh, activeVertices);
1328+
1329+
return reduceMeshComponents(character, activeVertices, activeFaces);
1330+
}
1331+
11881332
// Explicit instantiations for commonly used types
11891333
template CharacterT<float> reduceMeshByVertices<float>(
11901334
const CharacterT<float>& character,
@@ -1234,4 +1378,36 @@ template std::vector<bool> facesToVertices<double>(
12341378
const MeshT<double>& mesh,
12351379
const std::vector<bool>& activeFaces);
12361380

1381+
template std::vector<bool> verticesToPolys<float>(
1382+
const MeshT<float>& mesh,
1383+
const std::vector<bool>& activeVertices);
1384+
1385+
template std::vector<bool> verticesToPolys<double>(
1386+
const MeshT<double>& mesh,
1387+
const std::vector<bool>& activeVertices);
1388+
1389+
template std::vector<bool> polysToVertices<float>(
1390+
const MeshT<float>& mesh,
1391+
const std::vector<bool>& activePolys);
1392+
1393+
template std::vector<bool> polysToVertices<double>(
1394+
const MeshT<double>& mesh,
1395+
const std::vector<bool>& activePolys);
1396+
1397+
template MeshT<float> reduceMeshByPolys<float>(
1398+
const MeshT<float>& mesh,
1399+
const std::vector<bool>& activePolys);
1400+
1401+
template MeshT<double> reduceMeshByPolys<double>(
1402+
const MeshT<double>& mesh,
1403+
const std::vector<bool>& activePolys);
1404+
1405+
template CharacterT<float> reduceMeshByPolys<float>(
1406+
const CharacterT<float>& character,
1407+
const std::vector<bool>& activePolys);
1408+
1409+
template CharacterT<double> reduceMeshByPolys<double>(
1410+
const CharacterT<double>& character,
1411+
const std::vector<bool>& activePolys);
1412+
12371413
} // namespace momentum

momentum/character/character_utility.h

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,60 @@ template <typename T>
145145

146146
/// Converts face selection to vertex selection
147147
///
148-
/// @param[in] character Character containing the mesh
148+
/// @param[in] mesh The mesh containing the faces
149149
/// @param[in] activeFaces Boolean vector indicating which faces are active
150150
/// @return Boolean vector indicating which vertices are used by active faces
151151
template <typename T>
152152
[[nodiscard]] std::vector<bool> facesToVertices(
153153
const MeshT<T>& mesh,
154154
const std::vector<bool>& activeFaces);
155155

156+
/// Converts vertex selection to polygon selection
157+
///
158+
/// A polygon is active if all its vertices are active.
159+
///
160+
/// @param[in] mesh The mesh containing the polygon data
161+
/// @param[in] activeVertices Boolean vector indicating which vertices are active
162+
/// @return Boolean vector indicating which polygons only contain active vertices
163+
template <typename T>
164+
[[nodiscard]] std::vector<bool> verticesToPolys(
165+
const MeshT<T>& mesh,
166+
const std::vector<bool>& activeVertices);
167+
168+
/// Converts polygon selection to vertex selection
169+
///
170+
/// @param[in] mesh The mesh containing the polygon data
171+
/// @param[in] activePolys Boolean vector indicating which polygons are active
172+
/// @return Boolean vector indicating which vertices are used by active polygons
173+
template <typename T>
174+
[[nodiscard]] std::vector<bool> polysToVertices(
175+
const MeshT<T>& mesh,
176+
const std::vector<bool>& activePolys);
177+
178+
/// Reduces a standalone mesh to only include the specified polygons and associated vertices.
179+
///
180+
/// Converts polygon selection to vertex selection and face selection, then reduces the mesh.
181+
/// Both triangulated faces and polygon data are filtered and remapped.
182+
///
183+
/// @param[in] mesh The mesh to reduce
184+
/// @param[in] activePolys Boolean vector indicating which polygons to keep
185+
/// @return A new mesh containing only the specified polygons and their referenced vertices
186+
template <typename T>
187+
[[nodiscard]] MeshT<T> reduceMeshByPolys(
188+
const MeshT<T>& mesh,
189+
const std::vector<bool>& activePolys);
190+
191+
/// Reduces the mesh to only include the specified polygons and associated vertices
192+
///
193+
/// Converts polygon selection to vertex selection and face selection, then reduces the mesh.
194+
/// Both triangulated faces and polygon data are filtered and remapped.
195+
///
196+
/// @param[in] character Character to be reduced
197+
/// @param[in] activePolys Boolean vector indicating which polygons to keep
198+
/// @return A new character with mesh reduced to the specified polygons
199+
template <typename T>
200+
[[nodiscard]] CharacterT<T> reduceMeshByPolys(
201+
const CharacterT<T>& character,
202+
const std::vector<bool>& activePolys);
203+
156204
} // namespace momentum

0 commit comments

Comments
 (0)