Skip to content

Commit

Permalink
Push some warnings for CSG non manifold and other errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
fire committed Dec 13, 2024
1 parent aa8d9b8 commit 0dd5082
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 15 deletions.
61 changes: 46 additions & 15 deletions modules/csg/csg_shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,13 +335,13 @@ static String _export_meshgl_as_json(const manifold::MeshGL64 &p_mesh) {
}
#endif // DEV_ENABLED

static void _pack_manifold(
static manifold::Manifold::Error _pack_manifold(
const CSGBrush *const p_mesh_merge,
manifold::Manifold &r_manifold,
HashMap<int32_t, Ref<Material>> &p_mesh_materials,
CSGShape3D *p_csg_shape) {
ERR_FAIL_NULL_MSG(p_mesh_merge, "p_mesh_merge is null");
ERR_FAIL_NULL_MSG(p_csg_shape, "p_shape is null");
ERR_FAIL_NULL_V_MSG(p_mesh_merge, manifold::Manifold::Error::InvalidConstruction, "p_mesh_merge is null");
ERR_FAIL_NULL_V_MSG(p_csg_shape, manifold::Manifold::Error::InvalidConstruction, "p_shape is null");
HashMap<uint32_t, Vector<CSGBrush::Face>> faces_by_material;
for (int face_i = 0; face_i < p_mesh_merge->faces.size(); face_i++) {
const CSGBrush::Face &face = p_mesh_merge->faces[face_i];
Expand Down Expand Up @@ -394,22 +394,14 @@ static void _pack_manifold(
// runIndex needs an explicit end value.
mesh.runIndex.push_back(mesh.triVerts.size());
mesh.tolerance = 2 * FLT_EPSILON;
ERR_FAIL_COND_MSG(mesh.vertProperties.size() % mesh.numProp != 0, "Invalid vertex properties size.");
ERR_FAIL_COND_V_MSG(mesh.vertProperties.size() % mesh.numProp != 0, manifold::Manifold::Error::PropertiesWrongLength, "Invalid vertex properties size.");
mesh.Merge();
#ifdef DEV_ENABLED
print_verbose(_export_meshgl_as_json(mesh));
#endif // DEV_ENABLED
r_manifold = manifold::Manifold(mesh);
manifold::Manifold::Error error = r_manifold.Status();
if (error == manifold::Manifold::Error::NoError) {
return;
}
if (p_csg_shape->get_owner()) {
NodePath path = p_csg_shape->get_owner()->get_path_to(p_csg_shape, true);
print_error(vformat("CSGShape3D manifold creation from mesh failed at %s: %s.", path, manifold_error_to_string(error)));
} else {
print_error(vformat("CSGShape3D manifold creation from mesh failed at .: %s.", manifold_error_to_string(error)));
}
return error;
}

struct ManifoldOperation {
Expand Down Expand Up @@ -442,7 +434,36 @@ CSGBrush *CSGShape3D::_get_brush() {
CSGBrush *n = _build_brush();
HashMap<int32_t, Ref<Material>> mesh_materials;
manifold::Manifold root_manifold;
_pack_manifold(n, root_manifold, mesh_materials, this);
manifold::Manifold::Error manifold_error = _pack_manifold(n, root_manifold, mesh_materials, this);
if (is_root_shape()) {
warnings.clear();
for (int i = 0; i < get_child_count(); i++) {
CSGShape3D *child = Object::cast_to<CSGShape3D>(get_child(i));
if (child) {
child->warnings.clear();
}
}
}
const String manifold_error_message_template = "%s: The CSGShape3D could not be created due to this error, resulting in an empty shape. "
"This typically occurs because the mesh is not manifold. "
"A manifold mesh forms a solid object without gaps, holes, or loose edges.\n"
"For a mesh to be manifold, every edge of every triangle must contain the same two vertices (by index) as exactly one other triangle edge, "
"and the start and end vertices must switch places between these two edges. The Godot Engine triangle vertices must appear in clockwise order "
"when viewed from the outside of the manifold.";
if (manifold_error != manifold::Manifold::Error::NoError) {
String error_message = vformat(manifold_error_message_template, manifold_error_to_string(manifold_error));
if (!warnings.has(error_message)) {
warnings.push_back(error_message);
}
for (int i = 0; i < get_child_count(); i++) {
CSGShape3D *child = Object::cast_to<CSGShape3D>(get_child(i));
if (child) {
if (!child->warnings.has(error_message)) {
child->warnings.push_back(error_message);
}
}
}
}
manifold::OpType current_op = ManifoldOperation::convert_csg_op(get_operation());
std::vector<manifold::Manifold> manifolds;
manifolds.push_back(root_manifold);
Expand All @@ -458,7 +479,13 @@ CSGBrush *CSGShape3D::_get_brush() {
CSGBrush transformed_brush;
transformed_brush.copy_from(*child_brush, child->get_transform());
manifold::Manifold child_manifold;
_pack_manifold(&transformed_brush, child_manifold, mesh_materials, child);
manifold::Manifold::Error child_manifold_error = _pack_manifold(&transformed_brush, child_manifold, mesh_materials, child);
if (child_manifold_error != manifold::Manifold::Error::NoError) {
String error_message = vformat(manifold_error_message_template, manifold_error_to_string(child_manifold_error));
if (!child->warnings.has(error_message)) {
child->warnings.push_back(error_message);
}
}
manifold::OpType child_operation = ManifoldOperation::convert_csg_op(child->get_operation());
if (child_operation != current_op) {
manifold::Manifold result = manifold::Manifold::BatchBoolean(manifolds, current_op);
Expand Down Expand Up @@ -939,6 +966,10 @@ Array CSGShape3D::get_meshes() const {
return Array();
}

PackedStringArray CSGShape3D::get_configuration_warnings() const {
return warnings;
}

void CSGShape3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_shape"), &CSGShape3D::_update_shape);
ClassDB::bind_method(D_METHOD("is_root_shape"), &CSGShape3D::is_root_shape);
Expand Down
2 changes: 2 additions & 0 deletions modules/csg/csg_shape.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ class CSGShape3D : public GeometryInstance3D {
void _notification(int p_what);
virtual CSGBrush *_build_brush() = 0;
void _make_dirty(bool p_parent_removing = false);
PackedStringArray warnings;
PackedStringArray get_configuration_warnings() const override;

static void _bind_methods();

Expand Down

0 comments on commit 0dd5082

Please sign in to comment.