in src/esp/scene/Mp3dSemanticScene.cpp [105:292]
bool SemanticScene::buildMp3dHouse(std::ifstream& ifs,
SemanticScene& scene,
const quatf& rotation) {
const bool hasWorldRotation = !rotation.isApprox(quatf::Identity());
auto getVec3f = [&](const std::vector<std::string>& tokens, int offset,
bool applyRotation = true) -> vec3f {
const float x = std::stof(tokens[offset]);
const float y = std::stof(tokens[offset + 1]);
const float z = std::stof(tokens[offset + 2]);
vec3f p = vec3f(x, y, z);
if (applyRotation && hasWorldRotation) {
p = rotation * p;
}
return p;
};
auto getBBox = [&](const std::vector<std::string>& tokens,
int offset) -> box3f {
// Get the bounding box without rotating as rotating min/max is odd
box3f sceneBox{getVec3f(tokens, offset, /*applyRotation=*/false),
getVec3f(tokens, offset + 3, /*applyRotation=*/false)};
if (!hasWorldRotation)
return sceneBox;
// Apply the rotation to center/sizes
const vec3f worldCenter = rotation * sceneBox.center();
const vec3f worldHalfSizes =
(rotation * sceneBox.sizes()).array().abs().matrix() / 2.0f;
// Then remake the box with min/max computed from rotated center/size
return box3f{(worldCenter - worldHalfSizes).eval(),
(worldCenter + worldHalfSizes).eval()};
};
auto getOBB = [&](const std::vector<std::string>& tokens, int offset) {
const vec3f center = getVec3f(tokens, offset);
// Don't need to apply rotation here, it'll already be added in by getVec3f
mat3f boxRotation;
boxRotation.col(0) << getVec3f(tokens, offset + 3);
boxRotation.col(1) << getVec3f(tokens, offset + 6);
boxRotation.col(2) << boxRotation.col(0).cross(boxRotation.col(1));
// Don't apply the world rotation here, that'll get added by boxRotation
const vec3f radius = getVec3f(tokens, offset + 9, /*applyRotation=*/false);
return geo::OBB(center, 2 * radius, quatf(boxRotation));
};
scene.categories_.clear();
scene.levels_.clear();
scene.regions_.clear();
scene.objects_.clear();
std::string line;
while (std::getline(ifs, line)) {
if (line.empty()) {
continue;
}
const std::vector<std::string> tokens =
Cr::Utility::String::splitWithoutEmptyParts(line, ' ');
switch (line[0]) {
case 'H': { // house
// H name label #images #panoramas #vertices #surfaces #segments
// #objects #categories #regions #portals #levels 0 0 0 0 0
// xlo ylo zlo xhi yhi zhi 0 0 0 0 0
scene.name_ = tokens[1];
scene.label_ = tokens[2];
scene.elementCounts_["images"] = std::stoi(tokens[3]);
scene.elementCounts_["panoramas"] = std::stoi(tokens[4]);
scene.elementCounts_["vertices"] = std::stoi(tokens[5]);
scene.elementCounts_["surfaces"] = std::stoi(tokens[6]);
scene.elementCounts_["segments"] = std::stoi(tokens[7]);
scene.elementCounts_["objects"] = std::stoi(tokens[8]);
scene.elementCounts_["categories"] = std::stoi(tokens[9]);
scene.elementCounts_["regions"] = std::stoi(tokens[10]);
scene.elementCounts_["portals"] = std::stoi(tokens[11]);
scene.elementCounts_["levels"] = std::stoi(tokens[12]);
scene.bbox_ = getBBox(tokens, 18);
break;
}
case 'L': { // level
// L level_index #regions label px py pz xlo ylo zlo xhi yhi zhi 0 0
// 0 0 0
scene.levels_.emplace_back(SemanticLevel::create());
auto& level = scene.levels_.back();
level->index_ = std::stoi(tokens[1]);
// NOTE tokens[2] is number of regions in level which we don't need
level->labelCode_ = tokens[3];
level->position_ = getVec3f(tokens, 4);
level->bbox_ = getBBox(tokens, 7);
break;
}
case 'R': { // region
// R region_index level_index 0 0 label px py pz xlo ylo zlo xhi yhi
// zhi height 0 0 0 0
scene.regions_.emplace_back(SemanticRegion::create());
auto& region = scene.regions_.back();
region->index_ = std::stoi(tokens[1]);
region->parentIndex_ = std::stoi(tokens[2]);
region->category_ = std::make_shared<Mp3dRegionCategory>(tokens[5][0]);
region->position_ = getVec3f(tokens, 6);
region->bbox_ = getBBox(tokens, 9);
if (region->parentIndex_ >= 0) {
region->level_ = scene.levels_[region->parentIndex_];
region->level_->regions_.push_back(region);
}
break;
}
// NOLINTNEXTLINE(bugprone-branch-clone)
case 'P': { // portal or panorama
// P portal_index region0_index region1_index label xlo ylo zlo xhi
// yhi zhi 0 0 0 0
// P name panorama_index region_index 0 px py pz 0 0 0 0 0
break;
}
// NOLINTNEXTLINE(bugprone-branch-clone)
case 'S': { // surface
// S surface_index region_index 0 label px py pz nx ny nz xlo ylo
// zlo
// xhi yhi zhi 0 0 0 0 0
break;
}
// NOLINTNEXTLINE(bugprone-branch-clone)
case 'V': { // vertex
// V vertex_index surface_index label px py pz nx ny nz 0 0 0
break;
}
// NOLINTNEXTLINE(bugprone-branch-clone)
case 'I': { // image
// I image_index panorama_index name camera_index yaw_index e00 e01
// e02 e03 e10 e11 e12 e13 e20 e21 e22 e23 e30 e31 e32 e33 i00 i01
// i02 i10 i11 i12 i20 i21 i22 width height px py pz 0 0 0 0 0
break;
}
case 'C': { // category
// C category_index category_mapping_index category_mapping_name
// mpcat40_index mpcat40_name 0 0 0 0 0
scene.categories_.emplace_back(std::make_shared<Mp3dObjectCategory>());
auto& category =
static_cast<Mp3dObjectCategory&>(*scene.categories_.back());
category.index_ = std::stoi(tokens[1]);
category.categoryMappingIndex_ = std::stoi(tokens[2]);
std::string catName = tokens[3];
std::replace(catName.begin(), catName.end(), '#', ' ');
category.categoryMappingName_ = catName;
category.mpcat40Index_ = std::stoi(tokens[4]);
category.mpcat40Name_ = tokens[5];
break;
}
case 'O': { // object
// O object_index region_index category_index px py pz a0x a0y a0z
// a1x a1y a1z r0 r1 r2 0 0 0 0 0 0 0 0
scene.objects_.emplace_back(SemanticObject::create());
auto& object = scene.objects_.back();
object->index_ = std::stoi(tokens[1]);
object->parentIndex_ = std::stoi(tokens[2]);
int categoryIndex = std::stoi(tokens[3]);
if (categoryIndex < 0) { // no category
object->category_ = std::make_shared<Mp3dObjectCategory>();
} else {
object->category_ = scene.categories_[categoryIndex];
}
object->obb_ = getOBB(tokens, 4);
if (object->parentIndex_ >= 0) {
object->region_ = scene.regions_[object->parentIndex_];
object->region_->objects_.push_back(object);
}
break;
}
case 'E': { // segment
// E segment_index object_index id area px py pz xlo ylo zlo xhi yhi
// zhi 0 0 0 0 0
const int objectIndex = std::stoi(tokens[2]);
const int segmentId = std::stoi(tokens[3]);
// NOTE: segmentId = regionIndex * 1000000 + segmentId
scene.segmentToObjectIndex_[segmentId] = objectIndex;
break;
}
default: {
break;
}
}
}
return true;
} // SemanticScene::buildMp3dHouse