@@ -1085,66 +1085,77 @@ void ResourceManager::computeGeneralMeshAreaAndVolume(
10851085 // Determine that all edges have exactly 2 sides ->
10861086 // idxAra describes exactly 2 pairs of the same idxs, a->b and b->a
10871087 std::unordered_map<uint64_t , int > edgeCount;
1088- std::unordered_map<uint64_t , int > altEdgeCount ;
1088+ std::unordered_map<uint64_t , int > revEdgeCount ;
10891089 scene::DrawableMeshTopology meshTopology =
10901090 scene::DrawableMeshTopology::ClosedManifold;
10911091 for (uint32_t idx = 0 ; idx < numIdxs; idx += 3 ) {
1092+ // First edge index, encoded in 64bit
10921093 uint64_t vals[] = {uint64_t (idxAra[idx]), uint64_t (idxAra[idx + 1 ]),
10931094 uint64_t (idxAra[idx + 2 ])};
10941095 uint64_t shift_vals[] = {vals[0 ] << 32 , vals[1 ] << 32 , vals[2 ] << 32 };
10951096 // for each edge in poly
10961097 for (uint32_t i = 0 ; i < 3 ; ++i) {
1098+ // Second edge index
10971099 uint32_t next_i = (i + 1 ) % 3 ;
1100+ // Encode directed edge vert idxs in single unsigned long
10981101 auto res =
10991102 edgeCount.emplace (std::make_pair (shift_vals[i] + vals[next_i], 0 ));
1103+ // Check if duplicate already exists - if so then non-manifold
11001104 if (!res.second ) {
1105+ // Keep count of dupes
11011106 res.first ->second += 1 ;
11021107 // Duplicate edge with same orientation
11031108 meshTopology = scene::DrawableMeshTopology::NonManifold;
11041109 }
1105- // Alt edge placement - verify the alternate edge is present
1106- altEdgeCount .emplace (std::make_pair (shift_vals[next_i] + vals[i], 0 ));
1110+ // Reverse edge placement - verify the reverse edge is present
1111+ revEdgeCount .emplace (std::make_pair (shift_vals[next_i] + vals[i], 0 ));
11071112 }
11081113 }
11091114 // If still closed manifold then check that every edge has an alt edge
11101115 // present
11111116 if (meshTopology == scene::DrawableMeshTopology::ClosedManifold) {
11121117 for (const auto entry : edgeCount) {
1113- altEdgeCount .erase (entry.first );
1118+ revEdgeCount .erase (entry.first );
11141119 }
1115- if (altEdgeCount .size () > 0 ) {
1120+ if (revEdgeCount .size () > 0 ) {
11161121 meshTopology = scene::DrawableMeshTopology::OpenManifold;
11171122 }
11181123 }
11191124
1120- // Surface area of the mesh : .5 * ba.cross(bc)
1125+ // Surface area of the mesh M_a : sum(Tri_abc) ( | .5 * ba.cross(bc)| )
11211126 double ttlSurfaceArea = 0.0 ;
1122- // Volume of the mesh : 1/6 * (OA.dot(ba.cross(bc)))
1127+ // Volume of the mesh M_v = sum(Tri_abc)( 1/3 (area_abc) h_O
1128+ // = sum(Tri_abc)(1/3 * (bO.dot(.5 * (ba.cross(bc)))))
11231129 // Where O is a distant vertex
11241130 // Only applicable on closed manifold meshes (i.e. all edges have exactly
11251131 // 2 faces)
11261132 double ttlVolume = 0 .0f ;
11271133 if (meshTopology == scene::DrawableMeshTopology::ClosedManifold) {
11281134 Mn::Vector3 origin{};
11291135 for (uint32_t idx = 0 ; idx < numIdxs; idx += 3 ) {
1130- const auto aVert = posArray[idxAra[idx + 1 ]];
1131- Mn::Vector3 aVec = posArray[idxAra[idx]] - aVert;
1132- Mn::Vector3 bVec = posArray[idxAra[idx + 2 ]] - aVert;
1133- Mn::Vector3 areaNormVec = 0.5 * Mn::Math::cross (aVec, bVec);
1134- double surfArea = areaNormVec.length ();
1136+ const auto bVert = posArray[idxAra[idx + 1 ]];
1137+ Mn::Vector3 baVec = posArray[idxAra[idx]] - bVert;
1138+ Mn::Vector3 bcVec = posArray[idxAra[idx + 2 ]] - bVert;
1139+ // Magnitude is 2x tri_abc area, direction is orthogonal to tri_abc
1140+ // ("height" dir)
1141+ Mn::Vector3 areaOrthoVec = 0.5 * Mn::Math::cross (baVec, bcVec);
1142+ double surfArea = areaOrthoVec.length ();
11351143 ttlSurfaceArea += surfArea;
1136- Mn::Vector3 c = origin - aVert;
1137- double signedVol = (Mn::Math::dot (c, areaNormVec)) / 3.0 ;
1144+ Mn::Vector3 bO = origin - bVert;
1145+ // Project along "height" direction
1146+ double signedVol = (Mn::Math::dot (bO, areaOrthoVec)) / 3.0 ;
11381147 ttlVolume += signedVol;
11391148 }
11401149 } else {
11411150 // Open or non-manifold meshes won't have an accurate volume calc
11421151 for (uint32_t idx = 0 ; idx < numIdxs; idx += 3 ) {
1143- const auto aVert = posArray[idxAra[idx + 1 ]];
1144- Mn::Vector3 aVec = posArray[idxAra[idx]] - aVert;
1145- Mn::Vector3 bVec = posArray[idxAra[idx + 2 ]] - aVert;
1146- Mn::Vector3 areaNormVec = 0.5 * Mn::Math::cross (aVec, bVec);
1147- double surfArea = areaNormVec.length ();
1152+ const auto bVert = posArray[idxAra[idx + 1 ]];
1153+ Mn::Vector3 baVec = posArray[idxAra[idx]] - bVert;
1154+ Mn::Vector3 bcVec = posArray[idxAra[idx + 2 ]] - bVert;
1155+ // Magnitude is 2x tri_abc area, direction is orthogonal to tri_abc
1156+ // ("height" dir)
1157+ Mn::Vector3 areaOrthoVec = 0.5 * Mn::Math::cross (baVec, bcVec);
1158+ double surfArea = areaOrthoVec.length ();
11481159 ttlSurfaceArea += surfArea;
11491160 }
11501161 }
0 commit comments