|
3 | 3 | // LICENSE file in the root directory of this source tree. |
4 | 4 |
|
5 | 5 | #include "SemanticScene.h" |
| 6 | +#include <Magnum/EigenIntegration/GeometryIntegration.h> |
| 7 | +#include <Magnum/EigenIntegration/Integration.h> |
6 | 8 | #include "GibsonSemanticScene.h" |
7 | 9 | #include "Mp3dSemanticScene.h" |
8 | 10 | #include "ReplicaSemanticScene.h" |
@@ -145,22 +147,103 @@ bool SemanticScene:: |
145 | 147 | ESP_DEBUG(Mn::Debug::Flag::NoSpace) |
146 | 148 | << "Semantic Attributes : `" << semanticAttr->getHandle() << "` has " |
147 | 149 | << semanticAttr->getNumRegionInstances() << " regions defined."; |
148 | | - |
149 | | - } // if semantic attributes specifes region annotations |
150 | | - } // if semanticAttrs are not null |
| 150 | + // Build Semantic regions for each SemanticRegion attributes instance |
| 151 | + const auto regionInstances = semanticAttr->getRegionInstances(); |
| 152 | + for (const auto regionInstance : regionInstances) { |
| 153 | + auto regionPtr = SemanticRegion::create(); |
| 154 | + // Unique name |
| 155 | + regionPtr->name_ = regionInstance->getHandle(); |
| 156 | + // Build a category |
| 157 | + regionPtr->category_ = |
| 158 | + LoopRegionCategory::create(-1, regionInstance->getLabel()); |
| 159 | + // Set y heights |
| 160 | + regionPtr->extrusionHeight_ = regionInstance->getExtrusionHeight(); |
| 161 | + regionPtr->floorHeight_ = regionInstance->getFloorHeight(); |
| 162 | + // Set bbox |
| 163 | + const Mn::Vector3 min = regionInstance->getMinBounds(); |
| 164 | + const Mn::Vector3 max = regionInstance->getMaxBounds(); |
| 165 | + regionPtr->setBBox(min, max); |
| 166 | + // Set polyloop points and precalc polyloop edge vectors |
| 167 | + const std::vector<Mn::Vector3> loopPoints = |
| 168 | + regionInstance->getPolyLoop(); |
| 169 | + |
| 170 | + std::size_t numPts = loopPoints.size(); |
| 171 | + regionPtr->polyLoopPoints_ = std::vector<Mn::Vector2>(numPts); |
| 172 | + // Save points and edges |
| 173 | + for (std::size_t i = 0; i < numPts; ++i) { |
| 174 | + Mn::Vector2 pt = {loopPoints[i].x(), loopPoints[i].z()}; |
| 175 | + regionPtr->polyLoopPoints_[i] = pt; |
| 176 | + } |
| 177 | + } |
| 178 | + } else { // if semantic attributes specifes region annotations |
| 179 | + ESP_DEBUG(Mn::Debug::Flag::NoSpace) |
| 180 | + << "Semantic Attributes : `" << semanticAttr->getHandle() |
| 181 | + << "` does not have any regions defined."; |
| 182 | + } |
| 183 | + } else { |
| 184 | + ESP_DEBUG(Mn::Debug::Flag::NoSpace) << "Semantic attributes do not exist."; |
| 185 | + } // if semanticAttrs exist or not |
151 | 186 |
|
152 | 187 | return loadSuccess; |
153 | 188 |
|
154 | 189 | } // SemanticScene::loadSemanticSceneDescriptor |
155 | 190 |
|
| 191 | +bool SemanticRegion::contains(const Mn::Vector3& pt) const { |
| 192 | + auto checkPt = [&](float x, float x0, float x1, float y, float y0, |
| 193 | + float y1) -> bool { |
| 194 | + float interp = ((y - y0) / (y1 - y0)); |
| 195 | + return (y < y0) != (y < y1) && (x < x0 + interp * (x1 - x0)); |
| 196 | + }; |
| 197 | + |
| 198 | + // First check height |
| 199 | + if ((pt.y() < floorHeight_) || (pt.y() > (floorHeight_ + extrusionHeight_))) { |
| 200 | + return false; |
| 201 | + } |
| 202 | + |
| 203 | + // next check bbox |
| 204 | + if (!bbox_.contains(Mn::EigenIntegration::cast<vec3f>(pt))) { |
| 205 | + return false; |
| 206 | + } |
| 207 | + |
| 208 | + // Lastly, count casts across edges. |
| 209 | + int count = 0; |
| 210 | + int numPts = polyLoopPoints_.size(); |
| 211 | + for (int i = 0; i < numPts; ++i) { |
| 212 | + const auto stPt = polyLoopPoints_[i]; |
| 213 | + const auto endPt = polyLoopPoints_[(i + 1) % numPts]; |
| 214 | + if (stPt == endPt) { |
| 215 | + // Skip points that are equal. |
| 216 | + continue; |
| 217 | + } |
| 218 | + // If two consecutive y values are equal, rotate the cast by 90. |
| 219 | + bool checkCrossing = |
| 220 | + (endPt.y() == stPt.y() |
| 221 | + ? checkPt(pt.y(), stPt.y(), endPt.y(), pt.x(), stPt.x(), endPt.x()) |
| 222 | + : checkPt(pt.x(), stPt.x(), endPt.x(), pt.y(), stPt.y(), |
| 223 | + endPt.y())); |
| 224 | + if (checkCrossing) { |
| 225 | + ++count; |
| 226 | + } |
| 227 | + } |
| 228 | + |
| 229 | + // Want odd crossings for being inside |
| 230 | + return (count % 2 == 1); |
| 231 | +} // SemanticRegion::contains |
| 232 | + |
| 233 | +void SemanticRegion::setBBox(const Mn::Vector3& min, const Mn::Vector3& max) { |
| 234 | + bbox_ = box3f(Mn::EigenIntegration::cast<vec3f>(min), |
| 235 | + Mn::EigenIntegration::cast<vec3f>(max)); |
| 236 | +} // SemanticRegion::setBBox |
| 237 | + |
156 | 238 | namespace { |
157 | 239 | /** |
158 | | - * @brief Build an AABB for a given set of vertex indices in @p verts list, and |
159 | | - * return in a std::pair, along with the count of verts used to build the AABB. |
| 240 | + * @brief Build an AABB for a given set of vertex indices in @p verts list, |
| 241 | + * and return in a std::pair, along with the count of verts used to build the |
| 242 | + * AABB. |
160 | 243 | * @param colorInt Semantic Color of object |
161 | 244 | * @param verts The mesh's vertex buffer. |
162 | | - * @param setOfIDXs set of vertex IDXs in the vertex buffer being used to build |
163 | | - * the resultant AABB. |
| 245 | + * @param setOfIDXs set of vertex IDXs in the vertex buffer being used to |
| 246 | + * build the resultant AABB. |
164 | 247 | */ |
165 | 248 | CCSemanticObject::ptr buildCCSemanticObjForSetOfVerts( |
166 | 249 | uint32_t colorInt, |
@@ -189,8 +272,8 @@ CCSemanticObject::ptr buildCCSemanticObjForSetOfVerts( |
189 | 272 | } // buildCCSemanticObjForSetOfVerts |
190 | 273 |
|
191 | 274 | /** |
192 | | - * @brief build per-SSD object vector of known semantic IDs - doing this in case |
193 | | - * semanticIDs are not contiguous. |
| 275 | + * @brief build per-SSD object vector of known semantic IDs - doing this in |
| 276 | + * case semanticIDs are not contiguous. |
194 | 277 | */ |
195 | 278 |
|
196 | 279 | std::vector<int> getObjsIdxToIDMap( |
@@ -236,8 +319,8 @@ SemanticScene::buildCCBasedSemanticObjs( |
236 | 319 | } |
237 | 320 | } |
238 | 321 |
|
239 | | - // only map to semantic ID if semanticScene exists, otherwise return map with |
240 | | - // objects keyed by hex color |
| 322 | + // only map to semantic ID if semanticScene exists, otherwise return map |
| 323 | + // with objects keyed by hex color |
241 | 324 | if (!semanticScene) { |
242 | 325 | return semanticCCObjsByVertTag; |
243 | 326 | } |
@@ -432,8 +515,9 @@ std::vector<uint32_t> SemanticScene::buildSemanticOBBs( |
432 | 515 | // number of unique ssdObjs mappings. |
433 | 516 |
|
434 | 517 | for (int vertIdx = 0; vertIdx < vertSemanticIDs.size(); ++vertIdx) { |
435 | | - // semantic ID on vertex - valid values are 1->semanticIDToSSOBJidx.size(). |
436 | | - // Invalid/unknown semantic ids are > semanticIDToSSOBJidx.size() |
| 518 | + // semantic ID on vertex - valid values are |
| 519 | + // 1->semanticIDToSSOBJidx.size(). Invalid/unknown semantic ids are > |
| 520 | + // semanticIDToSSOBJidx.size() |
437 | 521 | const auto semanticID = vertSemanticIDs[vertIdx]; |
438 | 522 | if ((semanticID >= 0) && (semanticID < semanticIDToSSOBJidx.size())) { |
439 | 523 | const auto vert = vertices[vertIdx]; |
@@ -473,7 +557,8 @@ std::vector<uint32_t> SemanticScene::buildSemanticOBBs( |
473 | 557 | center = .5f * (vertMax[semanticID] + vertMin[semanticID]); |
474 | 558 | dims = vertMax[semanticID] - vertMin[semanticID]; |
475 | 559 | ESP_VERY_VERBOSE() << Cr::Utility::formatString( |
476 | | - "{} Semantic ID : {} : color : {} tag : {} present in {} verts | BB " |
| 560 | + "{} Semantic ID : {} : color : {} tag : {} present in {} verts | " |
| 561 | + "BB " |
477 | 562 | "Center [{} {} {}] Dims [{} {} {}]", |
478 | 563 | msgPrefix, semanticID, geo::getColorAsString(ssdObj.getColor()), |
479 | 564 | ssdObj.id(), vertCounts[semanticID], center.x(), center.y(), |
|
0 commit comments