mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-10 06:00:51 +00:00
Support --element-hierarchy in .glb output
This commit is contained in:
@@ -867,8 +867,8 @@ int main(int argc, char** argv) {
|
|||||||
geometry_settings.get<ifcopenshell::geometry::settings::NoParallelMapping>().value = true;
|
geometry_settings.get<ifcopenshell::geometry::settings::NoParallelMapping>().value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (geometry_settings.get<ifcopenshell::geometry::settings::UseElementHierarchy>().get() && output_extension != DAE && output_extension != USD && output_extension != USDA && output_extension != USDC) {
|
if (geometry_settings.get<ifcopenshell::geometry::settings::UseElementHierarchy>().get() && output_extension != DAE && output_extension != USD && output_extension != USDA && output_extension != USDC && output_extension != GLB) {
|
||||||
cerr_ << "[Error] --use-element-hierarchy can be used only with .dae or .usd output.\n";
|
cerr_ << "[Error] --use-element-hierarchy can be used only with .dae or .usd or .glb output.\n";
|
||||||
/// @todo Lots of duplicate error-and-exit code.
|
/// @todo Lots of duplicate error-and-exit code.
|
||||||
write_log(!quiet);
|
write_log(!quiet);
|
||||||
print_usage();
|
print_usage();
|
||||||
|
|||||||
@@ -564,13 +564,19 @@ IfcGeom::Element* IfcGeom::Iterator::get()
|
|||||||
// We need to find all the parents
|
// We need to find all the parents
|
||||||
while (parent_object != NULL && hasParent && parent_object->parent_id() != -1) {
|
while (parent_object != NULL && hasParent && parent_object->parent_id() != -1) {
|
||||||
// Find the next parent
|
// Find the next parent
|
||||||
try {
|
auto pid = parent_object->parent_id();
|
||||||
parent_object = get_object(parent_object->parent_id());
|
auto ifc_product = ifc_file->instance_by_id(pid)->as<IfcUtil::IfcBaseEntity>();
|
||||||
} catch (const std::exception& e) {
|
if (ifc_product->declaration().name() == "IfcProject") {
|
||||||
Logger::Error(e);
|
hasParent = false;
|
||||||
hasParent = false;
|
} else {
|
||||||
}
|
try {
|
||||||
|
parent_object = get_object(pid);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
Logger::Error(e);
|
||||||
|
hasParent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add the previously found parent to the vector
|
// Add the previously found parent to the vector
|
||||||
if (hasParent) parents.insert(parents.begin(), parent_object);
|
if (hasParent) parents.insert(parents.begin(), parent_object);
|
||||||
|
|
||||||
|
|||||||
@@ -180,35 +180,108 @@ void GltfSerializer::write(const IfcGeom::TriangulationElement* o) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_array_.push_back(json_["nodes"].size());
|
size_t current_node_index = json_["nodes"].size();
|
||||||
|
auto current_leaf_index = current_node_index;
|
||||||
|
json_["nodes"].emplace_back();
|
||||||
|
node_indices_[o->product()] = current_node_index;
|
||||||
|
node_array_.push_back(current_node_index);
|
||||||
|
|
||||||
const auto& m = o->transformation().data()->ccomponents();
|
auto m = o->transformation().data()->ccomponents();
|
||||||
|
|
||||||
// @todo check
|
if (o->parents().empty()) {
|
||||||
std::array<double, 16> matrix_flat;
|
roots_.push_back(current_node_index);
|
||||||
if (settings_.get<ifcopenshell::geometry::settings::WriteGltfEcef>().get()) {
|
|
||||||
matrix_flat = {
|
|
||||||
m(0,0), m(1,0), m(2,0), m(3,0),
|
|
||||||
m(0,1), m(1,1), m(2,1), m(3,1),
|
|
||||||
m(0,2), m(1,2), m(2,2), m(3,2),
|
|
||||||
m(0,3), m(1,3), m(2,3), m(3,3)
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// nb: note that this contains the Y-UP transform as well.
|
|
||||||
matrix_flat = {
|
|
||||||
m(0,0), m(2,0), -m(1,0), m(3,0),
|
|
||||||
m(0,1), m(2,1), -m(1,1), m(3,1),
|
|
||||||
m(0,2), m(2,2), -m(1,2), m(3,2),
|
|
||||||
m(0,3), m(2,3), -m(1,3), m(3,3)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
if (!o->parents().empty()) {
|
||||||
|
// apply inverse of last parent -> overwrite product transform (m)
|
||||||
|
m = o->parents().back()->transformation().data()->ccomponents().inverse() * m;
|
||||||
|
|
||||||
|
for (auto it = o->parents().rbegin(); it != o->parents().rend(); ++it) {
|
||||||
|
const auto jt = it + 1;
|
||||||
|
const bool is_root = jt == o->parents().rend();
|
||||||
|
|
||||||
|
auto kt = node_indices_.find((*it)->product());
|
||||||
|
if (kt != node_indices_.end()) {
|
||||||
|
// parent already processed as part of other parent sequence
|
||||||
|
json_["nodes"][kt->second]["children"].push_back(current_node_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto mm = (*it)->transformation().data()->ccomponents();
|
||||||
|
if (!is_root) {
|
||||||
|
mm = (*jt)->transformation().data()->ccomponents().inverse() * mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
json parent_node = json::object();
|
||||||
|
|
||||||
|
std::array<double, 16> matrix_flat;
|
||||||
|
if (settings_.get<ifcopenshell::geometry::settings::WriteGltfEcef>().get() || !is_root) {
|
||||||
|
// y-up transform is only accounted for on root
|
||||||
|
matrix_flat = {
|
||||||
|
mm(0,0), mm(1,0), mm(2,0), mm(3,0),
|
||||||
|
mm(0,1), mm(1,1), mm(2,1), mm(3,1),
|
||||||
|
mm(0,2), mm(1,2), mm(2,2), mm(3,2),
|
||||||
|
mm(0,3), mm(1,3), mm(2,3), mm(3,3)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// nb: note that this contains the Y-UP transform.
|
||||||
|
matrix_flat = {
|
||||||
|
mm(0,0), mm(2,0), -mm(1,0), mm(3,0),
|
||||||
|
mm(0,1), mm(2,1), -mm(1,1), mm(3,1),
|
||||||
|
mm(0,2), mm(2,2), -mm(1,2), mm(3,2),
|
||||||
|
mm(0,3), mm(2,3), -mm(1,3), mm(3,3)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static const std::array<double, 16> identity_matrix = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
|
static const std::array<double, 16> identity_matrix = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
|
||||||
|
|
||||||
|
if (matrix_flat != identity_matrix) {
|
||||||
|
// glTF validator complains about identity matrices
|
||||||
|
parent_node["matrix"] = matrix_flat;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t new_node_index = json_["nodes"].size();
|
||||||
|
node_indices_[(*it)->product()] = new_node_index;
|
||||||
|
node_array_.push_back(new_node_index);
|
||||||
|
parent_node["name"] = object_id(o);
|
||||||
|
parent_node["children"] = json::array({current_node_index});
|
||||||
|
json_["nodes"].push_back(parent_node);
|
||||||
|
|
||||||
|
current_node_index = new_node_index;
|
||||||
|
|
||||||
|
if (is_root) {
|
||||||
|
roots_.push_back(current_node_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
json node;
|
json node;
|
||||||
if (matrix_flat != identity_matrix) {
|
{
|
||||||
// glTF validator complains about identity matrices
|
std::array<double, 16> matrix_flat;
|
||||||
node["matrix"] = matrix_flat;
|
if (settings_.get<ifcopenshell::geometry::settings::WriteGltfEcef>().get() || !o->parents().empty()) {
|
||||||
|
// y-up transform is only accounted for on root
|
||||||
|
matrix_flat = {
|
||||||
|
m(0,0), m(1,0), m(2,0), m(3,0),
|
||||||
|
m(0,1), m(1,1), m(2,1), m(3,1),
|
||||||
|
m(0,2), m(1,2), m(2,2), m(3,2),
|
||||||
|
m(0,3), m(1,3), m(2,3), m(3,3)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// nb: note that this contains the Y-UP transform.
|
||||||
|
matrix_flat = {
|
||||||
|
m(0,0), m(2,0), -m(1,0), m(3,0),
|
||||||
|
m(0,1), m(2,1), -m(1,1), m(3,1),
|
||||||
|
m(0,2), m(2,2), -m(1,2), m(3,2),
|
||||||
|
m(0,3), m(2,3), -m(1,3), m(3,3)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::array<double, 16> identity_matrix = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
|
||||||
|
|
||||||
|
if (matrix_flat != identity_matrix) {
|
||||||
|
// glTF validator complains about identity matrices
|
||||||
|
node["matrix"] = matrix_flat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
node["name"] = object_id(o);
|
node["name"] = object_id(o);
|
||||||
|
|
||||||
@@ -300,7 +373,7 @@ void GltfSerializer::write(const IfcGeom::TriangulationElement* o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
node["mesh"] = current_mesh_index;
|
node["mesh"] = current_mesh_index;
|
||||||
json_["nodes"].push_back(node);
|
json_["nodes"][current_leaf_index] = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint32_t>
|
template <uint32_t>
|
||||||
@@ -372,7 +445,9 @@ void GltfSerializer::finalize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
json scene_0;
|
json scene_0;
|
||||||
if (north_rotation_ || ecef_transform_) {
|
if (geometry_settings().get<ifcopenshell::geometry::settings::UseElementHierarchy>().get()) {
|
||||||
|
scene_0["nodes"] = roots_;
|
||||||
|
} else if (north_rotation_ || ecef_transform_) {
|
||||||
scene_0["nodes"] = std::array<size_t, 1>{json_["nodes"].size() - 1};
|
scene_0["nodes"] = std::array<size_t, 1>{json_["nodes"].size() - 1};
|
||||||
} else {
|
} else {
|
||||||
scene_0["nodes"] = node_array_;
|
scene_0["nodes"] = node_array_;
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ private:
|
|||||||
json json_, node_array_;
|
json json_, node_array_;
|
||||||
boost::optional<json> ecef_transform_, north_rotation_;
|
boost::optional<json> ecef_transform_, north_rotation_;
|
||||||
int bufferViewId;
|
int bufferViewId;
|
||||||
|
std::map<const IfcUtil::IfcBaseEntity*, size_t> node_indices_;
|
||||||
|
std::vector<size_t> roots_;
|
||||||
|
|
||||||
int writeMaterial(const ifcopenshell::geometry::taxonomy::style::ptr style);
|
int writeMaterial(const ifcopenshell::geometry::taxonomy::style::ptr style);
|
||||||
public:
|
public:
|
||||||
|
|||||||
Reference in New Issue
Block a user