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