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