@@ -1058,37 +1058,86 @@ void ResourceManager::computeGeneralMeshAreaAndVolume(
10581058 meshData->positions3DAsArray (0 );
10591059 Mn::MeshTools::transformPointsInPlace (absTransforms[iEntry], posArray);
10601060
1061+ // Getting the view properly relies on having the appropriate type of the
1062+ // loaded data
1063+ // const auto idxView = meshData->indices<std::uint32_t>();
1064+ const auto idxAra = meshData->indicesAsArray ();
1065+ // # of indices
1066+ uint32_t numIdxs = meshData->indexCount ();
1067+ // Assuming no duplicate vertices with different idxs
1068+ // Determine that all edges have exactly 2 sides ->
1069+ // idxAra describes exactly 2 pairs of the same idxs, a->b and b->a
1070+ std::unordered_map<uint64_t , int > edgeCount;
1071+ std::unordered_map<uint64_t , int > altEdgeCount;
1072+ scene::DrawableMeshTopology meshTopology =
1073+ scene::DrawableMeshTopology::ClosedManifold;
1074+ for (uint32_t idx = 0 ; idx < numIdxs; idx += 3 ) {
1075+ uint64_t vals[] = {uint64_t (idxAra[idx]), uint64_t (idxAra[idx + 1 ]),
1076+ uint64_t (idxAra[idx + 2 ])};
1077+ uint64_t shift_vals[] = {vals[0 ] << 32 , vals[1 ] << 32 , vals[2 ] << 32 };
1078+ // for each edge in poly
1079+ for (uint32_t i = 0 ; i < 3 ; ++i) {
1080+ uint32_t next_i = (i + 1 ) % 3 ;
1081+ auto res =
1082+ edgeCount.emplace (std::make_pair (shift_vals[i] + vals[next_i], 0 ));
1083+ if (!res.second ) {
1084+ res.first ->second += 1 ;
1085+ // Duplicate edge with same orientation
1086+ meshTopology = scene::DrawableMeshTopology::NonManifold;
1087+ }
1088+ // Alt edge placement - verify the alternate edge is present
1089+ altEdgeCount.emplace (std::make_pair (shift_vals[next_i] + vals[i], 0 ));
1090+ }
1091+ }
1092+ // If still closed manifold then check that every edge has an alt edge
1093+ // present
1094+ if (meshTopology == scene::DrawableMeshTopology::ClosedManifold) {
1095+ for (const auto entry : edgeCount) {
1096+ altEdgeCount.erase (entry.first );
1097+ }
1098+ if (altEdgeCount.size () > 0 ) {
1099+ meshTopology = scene::DrawableMeshTopology::OpenManifold;
1100+ }
1101+ }
1102+
1103+ // locate the scene node which contains the current drawable
1104+ scene::SceneNode& node = staticDrawableInfo[iEntry].node ;
10611105 // Surface area of the mesh : .5 * ba.cross(bc)
10621106 double ttlSurfaceArea = 0.0 ;
1063-
10641107 // Volume of the mesh : 1/6 * (OA.dot(ba.cross(bc)))
10651108 // Where O is a distant vertex
1109+ // Only applicable on closed manifold meshes (i.e. all edges have exactly
1110+ // 2 faces)
10661111 double ttlVolume = 0 .0f ;
1067-
1068- // locate the scene node which contains the current drawable
1069- scene::SceneNode& node = staticDrawableInfo[iEntry].node ;
1070- // # of indices
1071- int numIdxs = meshData->indexCount ();
1072-
1073- // const auto idxView = meshData->indices<std::uint32_t>();
1074- const auto idxView = meshData->indicesAsArray ();
1075- Mn::Vector3 distPt{1000 , 1000 , 1000 };
1076- for (uint32_t rawIdx = 0 ; rawIdx < numIdxs; rawIdx += 3 ) {
1077- const auto aVert = posArray[idxView[rawIdx + 1 ]];
1078- Mn::Vector3 a = posArray[idxView[rawIdx]] - aVert;
1079- Mn::Vector3 b = posArray[idxView[rawIdx + 2 ]] - aVert;
1080- Mn::Vector3 areaNorm = 0.5 * Mn::Math::cross (a, b);
1081- double surfArea = areaNorm.length ();
1082- ttlSurfaceArea += surfArea;
1083- Mn::Vector3 c = distPt - aVert;
1084- double signedVol = (Mn::Math::dot (c, areaNorm)) / 3.0 ;
1085- ttlVolume += signedVol;
1112+ if (meshTopology == scene::DrawableMeshTopology::ClosedManifold) {
1113+ Mn::Vector3 origin{};
1114+ for (uint32_t idx = 0 ; idx < numIdxs; idx += 3 ) {
1115+ const auto aVert = posArray[idxAra[idx + 1 ]];
1116+ Mn::Vector3 aVec = posArray[idxAra[idx]] - aVert;
1117+ Mn::Vector3 bVec = posArray[idxAra[idx + 2 ]] - aVert;
1118+ Mn::Vector3 areaNormVec = 0.5 * Mn::Math::cross (aVec, bVec);
1119+ double surfArea = areaNormVec.length ();
1120+ ttlSurfaceArea += surfArea;
1121+ Mn::Vector3 c = origin - aVert;
1122+ double signedVol = (Mn::Math::dot (c, areaNormVec)) / 3.0 ;
1123+ ttlVolume += signedVol;
1124+ }
1125+ } else {
1126+ // Open or non-manifold meshes won't have an accurate volume calc
1127+ for (uint32_t idx = 0 ; idx < numIdxs; idx += 3 ) {
1128+ const auto aVert = posArray[idxAra[idx + 1 ]];
1129+ Mn::Vector3 aVec = posArray[idxAra[idx]] - aVert;
1130+ Mn::Vector3 bVec = posArray[idxAra[idx + 2 ]] - aVert;
1131+ Mn::Vector3 areaNormVec = 0.5 * Mn::Math::cross (aVec, bVec);
1132+ double surfArea = areaNormVec.length ();
1133+ ttlSurfaceArea += surfArea;
1134+ }
10861135 }
1087-
10881136 // set the node's volume and surface area
10891137 node.setMeshVolume (ttlVolume);
10901138 node.setMeshSurfaceArea (ttlSurfaceArea);
1091-
1139+ // Set whether the mesh is manifold and/or closed/watertight
1140+ node.setMeshTopology (meshTopology);
10921141 } // iEntry
10931142
10941143} // ResourceManager::computeGeneralMeshVolume
@@ -3196,9 +3245,9 @@ void ResourceManager::addComponent(
31963245 drawableConfig); // instance skinning data
31973246
31983247 // compute the bounding box for the mesh we are adding
3199- if (computeAbsoluteAABBs) {
3200- staticDrawableInfo.emplace_back (StaticDrawableInfo{node, meshID});
3201- }
3248+ // if (computeAbsoluteAABBs) {
3249+ staticDrawableInfo.emplace_back (StaticDrawableInfo{node, meshID});
3250+ // }
32023251 BaseMesh* meshBB = meshes_.at (meshID).get ();
32033252 node.setMeshBB (computeMeshBB (meshBB));
32043253 }
0 commit comments