@@ -1082,66 +1082,77 @@ void ResourceManager::computeGeneralMeshAreaAndVolume(
1082
1082
// Determine that all edges have exactly 2 sides ->
1083
1083
// idxAra describes exactly 2 pairs of the same idxs, a->b and b->a
1084
1084
std::unordered_map<uint64_t , int > edgeCount;
1085
- std::unordered_map<uint64_t , int > altEdgeCount ;
1085
+ std::unordered_map<uint64_t , int > revEdgeCount ;
1086
1086
scene::DrawableMeshTopology meshTopology =
1087
1087
scene::DrawableMeshTopology::ClosedManifold;
1088
1088
for (uint32_t idx = 0 ; idx < numIdxs; idx += 3 ) {
1089
+ // First edge index, encoded in 64bit
1089
1090
uint64_t vals[] = {uint64_t (idxAra[idx]), uint64_t (idxAra[idx + 1 ]),
1090
1091
uint64_t (idxAra[idx + 2 ])};
1091
1092
uint64_t shift_vals[] = {vals[0 ] << 32 , vals[1 ] << 32 , vals[2 ] << 32 };
1092
1093
// for each edge in poly
1093
1094
for (uint32_t i = 0 ; i < 3 ; ++i) {
1095
+ // Second edge index
1094
1096
uint32_t next_i = (i + 1 ) % 3 ;
1097
+ // Encode directed edge vert idxs in single unsigned long
1095
1098
auto res =
1096
1099
edgeCount.emplace (std::make_pair (shift_vals[i] + vals[next_i], 0 ));
1100
+ // Check if duplicate already exists - if so then non-manifold
1097
1101
if (!res.second ) {
1102
+ // Keep count of dupes
1098
1103
res.first ->second += 1 ;
1099
1104
// Duplicate edge with same orientation
1100
1105
meshTopology = scene::DrawableMeshTopology::NonManifold;
1101
1106
}
1102
- // Alt edge placement - verify the alternate edge is present
1103
- altEdgeCount .emplace (std::make_pair (shift_vals[next_i] + vals[i], 0 ));
1107
+ // Reverse edge placement - verify the reverse edge is present
1108
+ revEdgeCount .emplace (std::make_pair (shift_vals[next_i] + vals[i], 0 ));
1104
1109
}
1105
1110
}
1106
1111
// If still closed manifold then check that every edge has an alt edge
1107
1112
// present
1108
1113
if (meshTopology == scene::DrawableMeshTopology::ClosedManifold) {
1109
1114
for (const auto entry : edgeCount) {
1110
- altEdgeCount .erase (entry.first );
1115
+ revEdgeCount .erase (entry.first );
1111
1116
}
1112
- if (altEdgeCount .size () > 0 ) {
1117
+ if (revEdgeCount .size () > 0 ) {
1113
1118
meshTopology = scene::DrawableMeshTopology::OpenManifold;
1114
1119
}
1115
1120
}
1116
1121
1117
- // Surface area of the mesh : .5 * ba.cross(bc)
1122
+ // Surface area of the mesh M_a : sum(Tri_abc) ( | .5 * ba.cross(bc)| )
1118
1123
double ttlSurfaceArea = 0.0 ;
1119
- // Volume of the mesh : 1/6 * (OA.dot(ba.cross(bc)))
1124
+ // Volume of the mesh M_v = sum(Tri_abc)( 1/3 (area_abc) h_O
1125
+ // = sum(Tri_abc)(1/3 * (bO.dot(.5 * (ba.cross(bc)))))
1120
1126
// Where O is a distant vertex
1121
1127
// Only applicable on closed manifold meshes (i.e. all edges have exactly
1122
1128
// 2 faces)
1123
1129
double ttlVolume = 0 .0f ;
1124
1130
if (meshTopology == scene::DrawableMeshTopology::ClosedManifold) {
1125
1131
Mn::Vector3 origin{};
1126
1132
for (uint32_t idx = 0 ; idx < numIdxs; idx += 3 ) {
1127
- const auto aVert = posArray[idxAra[idx + 1 ]];
1128
- Mn::Vector3 aVec = posArray[idxAra[idx]] - aVert;
1129
- Mn::Vector3 bVec = posArray[idxAra[idx + 2 ]] - aVert;
1130
- Mn::Vector3 areaNormVec = 0.5 * Mn::Math::cross (aVec, bVec);
1131
- double surfArea = areaNormVec.length ();
1133
+ const auto bVert = posArray[idxAra[idx + 1 ]];
1134
+ Mn::Vector3 baVec = posArray[idxAra[idx]] - bVert;
1135
+ Mn::Vector3 bcVec = posArray[idxAra[idx + 2 ]] - bVert;
1136
+ // Magnitude is 2x tri_abc area, direction is orthogonal to tri_abc
1137
+ // ("height" dir)
1138
+ Mn::Vector3 areaOrthoVec = 0.5 * Mn::Math::cross (baVec, bcVec);
1139
+ double surfArea = areaOrthoVec.length ();
1132
1140
ttlSurfaceArea += surfArea;
1133
- Mn::Vector3 c = origin - aVert;
1134
- double signedVol = (Mn::Math::dot (c, areaNormVec)) / 3.0 ;
1141
+ Mn::Vector3 bO = origin - bVert;
1142
+ // Project along "height" direction
1143
+ double signedVol = (Mn::Math::dot (bO, areaOrthoVec)) / 3.0 ;
1135
1144
ttlVolume += signedVol;
1136
1145
}
1137
1146
} else {
1138
1147
// Open or non-manifold meshes won't have an accurate volume calc
1139
1148
for (uint32_t idx = 0 ; idx < numIdxs; idx += 3 ) {
1140
- const auto aVert = posArray[idxAra[idx + 1 ]];
1141
- Mn::Vector3 aVec = posArray[idxAra[idx]] - aVert;
1142
- Mn::Vector3 bVec = posArray[idxAra[idx + 2 ]] - aVert;
1143
- Mn::Vector3 areaNormVec = 0.5 * Mn::Math::cross (aVec, bVec);
1144
- double surfArea = areaNormVec.length ();
1149
+ const auto bVert = posArray[idxAra[idx + 1 ]];
1150
+ Mn::Vector3 baVec = posArray[idxAra[idx]] - bVert;
1151
+ Mn::Vector3 bcVec = posArray[idxAra[idx + 2 ]] - bVert;
1152
+ // Magnitude is 2x tri_abc area, direction is orthogonal to tri_abc
1153
+ // ("height" dir)
1154
+ Mn::Vector3 areaOrthoVec = 0.5 * Mn::Math::cross (baVec, bcVec);
1155
+ double surfArea = areaOrthoVec.length ();
1145
1156
ttlSurfaceArea += surfArea;
1146
1157
}
1147
1158
}
0 commit comments