3030
3131#include " csg_shape.h"
3232
33+ #ifdef DEV_ENABLED
34+ #include " core/io/json.h"
35+ #endif // DEV_ENABLED
3336#include " core/math/geometry_2d.h"
3437
3538#include < manifold/manifold.h>
@@ -142,6 +145,7 @@ bool CSGShape3D::is_root_shape() const {
142145 return !parent_shape;
143146}
144147
148+ #ifndef DISABLE_DEPRECATED
145149void CSGShape3D::set_snap (float p_snap) {
146150 if (snap == p_snap) {
147151 return ;
@@ -154,6 +158,7 @@ void CSGShape3D::set_snap(float p_snap) {
154158float CSGShape3D::get_snap () const {
155159 return snap;
156160}
161+ #endif // DISABLE_DEPRECATED
157162
158163void CSGShape3D::_make_dirty (bool p_parent_removing) {
159164 if ((p_parent_removing || is_root_shape ()) && !dirty) {
@@ -232,21 +237,118 @@ static void _unpack_manifold(
232237 r_mesh_merge->_regen_face_aabbs ();
233238}
234239
240+ // Errors matching `thirdparty/manifold/include/manifold/manifold.h`.
241+ static String manifold_error_to_string (const manifold::Manifold::Error &p_error) {
242+ switch (p_error) {
243+ case manifold::Manifold::Error::NoError:
244+ return " No Error" ;
245+ case manifold::Manifold::Error::NonFiniteVertex:
246+ return " Non Finite Vertex" ;
247+ case manifold::Manifold::Error::NotManifold:
248+ return " Not Manifold" ;
249+ case manifold::Manifold::Error::VertexOutOfBounds:
250+ return " Vertex Out Of Bounds" ;
251+ case manifold::Manifold::Error::PropertiesWrongLength:
252+ return " Properties Wrong Length" ;
253+ case manifold::Manifold::Error::MissingPositionProperties:
254+ return " Missing Position Properties" ;
255+ case manifold::Manifold::Error::MergeVectorsDifferentLengths:
256+ return " Merge Vectors Different Lengths" ;
257+ case manifold::Manifold::Error::MergeIndexOutOfBounds:
258+ return " Merge Index Out Of Bounds" ;
259+ case manifold::Manifold::Error::TransformWrongLength:
260+ return " Transform Wrong Length" ;
261+ case manifold::Manifold::Error::RunIndexWrongLength:
262+ return " Run Index Wrong Length" ;
263+ case manifold::Manifold::Error::FaceIDWrongLength:
264+ return " Face ID Wrong Length" ;
265+ case manifold::Manifold::Error::InvalidConstruction:
266+ return " Invalid Construction" ;
267+ default :
268+ return " Unknown Error" ;
269+ }
270+ }
271+
272+ #ifdef DEV_ENABLED
273+ static String _export_meshgl_as_json (const manifold::MeshGL64 &p_mesh) {
274+ Dictionary mesh_dict;
275+ mesh_dict[" numProp" ] = p_mesh.numProp ;
276+
277+ Array vert_properties;
278+ for (const double &val : p_mesh.vertProperties ) {
279+ vert_properties.append (val);
280+ }
281+ mesh_dict[" vertProperties" ] = vert_properties;
282+
283+ Array tri_verts;
284+ for (const uint64_t &val : p_mesh.triVerts ) {
285+ tri_verts.append (val);
286+ }
287+ mesh_dict[" triVerts" ] = tri_verts;
288+
289+ Array merge_from_vert;
290+ for (const uint64_t &val : p_mesh.mergeFromVert ) {
291+ merge_from_vert.append (val);
292+ }
293+ mesh_dict[" mergeFromVert" ] = merge_from_vert;
294+
295+ Array merge_to_vert;
296+ for (const uint64_t &val : p_mesh.mergeToVert ) {
297+ merge_to_vert.append (val);
298+ }
299+ mesh_dict[" mergeToVert" ] = merge_to_vert;
300+
301+ Array run_index;
302+ for (const uint64_t &val : p_mesh.runIndex ) {
303+ run_index.append (val);
304+ }
305+ mesh_dict[" runIndex" ] = run_index;
306+
307+ Array run_original_id;
308+ for (const uint32_t &val : p_mesh.runOriginalID ) {
309+ run_original_id.append (val);
310+ }
311+ mesh_dict[" runOriginalID" ] = run_original_id;
312+
313+ Array run_transform;
314+ for (const double &val : p_mesh.runTransform ) {
315+ run_transform.append (val);
316+ }
317+ mesh_dict[" runTransform" ] = run_transform;
318+
319+ Array face_id;
320+ for (const uint64_t &val : p_mesh.faceID ) {
321+ face_id.append (val);
322+ }
323+ mesh_dict[" faceID" ] = face_id;
324+
325+ Array halfedge_tangent;
326+ for (const double &val : p_mesh.halfedgeTangent ) {
327+ halfedge_tangent.append (val);
328+ }
329+ mesh_dict[" halfedgeTangent" ] = halfedge_tangent;
330+
331+ mesh_dict[" tolerance" ] = p_mesh.tolerance ;
332+
333+ String json_string = JSON::stringify (mesh_dict);
334+ return json_string;
335+ }
336+ #endif // DEV_ENABLED
337+
235338static void _pack_manifold (
236339 const CSGBrush *const p_mesh_merge,
237340 manifold::Manifold &r_manifold,
238341 HashMap<int32_t , Ref<Material>> &p_mesh_materials,
239- float p_snap ) {
342+ CSGShape3D *p_csg_shape ) {
240343 ERR_FAIL_NULL_MSG (p_mesh_merge, " p_mesh_merge is null" );
241-
344+ ERR_FAIL_NULL_MSG (p_csg_shape, " p_shape is null " );
242345 HashMap<uint32_t , Vector<CSGBrush::Face>> faces_by_material;
243346 for (int face_i = 0 ; face_i < p_mesh_merge->faces .size (); face_i++) {
244347 const CSGBrush::Face &face = p_mesh_merge->faces [face_i];
245348 faces_by_material[face.material ].push_back (face);
246349 }
247350
248351 manifold::MeshGL64 mesh;
249- mesh.tolerance = p_snap;
250352 mesh.numProp = MANIFOLD_PROPERTY_MAX;
251353 mesh.runOriginalID .reserve (faces_by_material.size ());
252354 mesh.runIndex .reserve (faces_by_material.size () + 1 );
@@ -291,12 +393,22 @@ static void _pack_manifold(
291393 }
292394 // runIndex needs an explicit end value.
293395 mesh.runIndex .push_back (mesh.triVerts .size ());
396+ mesh.tolerance = 2 * FLT_EPSILON;
294397 ERR_FAIL_COND_MSG (mesh.vertProperties .size () % mesh.numProp != 0 , " Invalid vertex properties size." );
295398 mesh.Merge ();
399+ #ifdef DEV_ENABLED
400+ print_verbose (_export_meshgl_as_json (mesh));
401+ #endif // DEV_ENABLED
296402 r_manifold = manifold::Manifold (mesh);
297- manifold::Manifold::Error err = r_manifold.Status ();
298- if (err != manifold::Manifold::Error::NoError) {
299- print_error (String (" Manifold creation from mesh failed:" + itos ((int )err)));
403+ manifold::Manifold::Error error = r_manifold.Status ();
404+ if (error == manifold::Manifold::Error::NoError) {
405+ return ;
406+ }
407+ if (p_csg_shape->get_owner ()) {
408+ NodePath path = p_csg_shape->get_owner ()->get_path_to (p_csg_shape, true );
409+ print_error (vformat (" CSGShape3D manifold creation from mesh failed at %s: %s." , path, manifold_error_to_string (error)));
410+ } else {
411+ print_error (vformat (" CSGShape3D manifold creation from mesh failed at .: %s." , manifold_error_to_string (error)));
300412 }
301413}
302414
@@ -330,7 +442,7 @@ CSGBrush *CSGShape3D::_get_brush() {
330442 CSGBrush *n = _build_brush ();
331443 HashMap<int32_t , Ref<Material>> mesh_materials;
332444 manifold::Manifold root_manifold;
333- _pack_manifold (n, root_manifold, mesh_materials, get_snap () );
445+ _pack_manifold (n, root_manifold, mesh_materials, this );
334446 manifold::OpType current_op = ManifoldOperation::convert_csg_op (get_operation ());
335447 std::vector<manifold::Manifold> manifolds;
336448 manifolds.push_back (root_manifold);
@@ -346,7 +458,7 @@ CSGBrush *CSGShape3D::_get_brush() {
346458 CSGBrush transformed_brush;
347459 transformed_brush.copy_from (*child_brush, child->get_transform ());
348460 manifold::Manifold child_manifold;
349- _pack_manifold (&transformed_brush, child_manifold, mesh_materials, get_snap () );
461+ _pack_manifold (&transformed_brush, child_manifold, mesh_materials, child );
350462 manifold::OpType child_operation = ManifoldOperation::convert_csg_op (child->get_operation ());
351463 if (child_operation != current_op) {
352464 manifold::Manifold result = manifold::Manifold::BatchBoolean (manifolds, current_op);
@@ -834,8 +946,10 @@ void CSGShape3D::_bind_methods() {
834946 ClassDB::bind_method (D_METHOD (" set_operation" , " operation" ), &CSGShape3D::set_operation);
835947 ClassDB::bind_method (D_METHOD (" get_operation" ), &CSGShape3D::get_operation);
836948
949+ #ifndef DISABLE_DEPRECATED
837950 ClassDB::bind_method (D_METHOD (" set_snap" , " snap" ), &CSGShape3D::set_snap);
838951 ClassDB::bind_method (D_METHOD (" get_snap" ), &CSGShape3D::get_snap);
952+ #endif // DISABLE_DEPRECATED
839953
840954 ClassDB::bind_method (D_METHOD (" set_use_collision" , " operation" ), &CSGShape3D::set_use_collision);
841955 ClassDB::bind_method (D_METHOD (" is_using_collision" ), &CSGShape3D::is_using_collision);
@@ -864,7 +978,9 @@ void CSGShape3D::_bind_methods() {
864978 ClassDB::bind_method (D_METHOD (" bake_collision_shape" ), &CSGShape3D::bake_collision_shape);
865979
866980 ADD_PROPERTY (PropertyInfo (Variant::INT, " operation" , PROPERTY_HINT_ENUM, " Union,Intersection,Subtraction" ), " set_operation" , " get_operation" );
867- ADD_PROPERTY (PropertyInfo (Variant::FLOAT, " snap" , PROPERTY_HINT_RANGE, " 0.000001,1,0.000001,suffix:m" ), " set_snap" , " get_snap" );
981+ #ifndef DISABLE_DEPRECATED
982+ ADD_PROPERTY (PropertyInfo (Variant::FLOAT, " snap" , PROPERTY_HINT_RANGE, " 0.000001,1,0.000001,suffix:m" , PROPERTY_USAGE_NONE), " set_snap" , " get_snap" );
983+ #endif // DISABLE_DEPRECATED
868984 ADD_PROPERTY (PropertyInfo (Variant::BOOL, " calculate_tangents" ), " set_calculate_tangents" , " is_calculating_tangents" );
869985
870986 ADD_GROUP (" Collision" , " collision_" );
0 commit comments