Skip to content

Commit

Permalink
Add the ability to lock faces.
Browse files Browse the repository at this point in the history
A CSG brush property to lock faces that defaults to off.

Useful to avoid high levels of mesh simplification.
  • Loading branch information
fire committed Jan 30, 2025
1 parent 71d80b2 commit 839c592
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
1 change: 1 addition & 0 deletions modules/csg/csg.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct CSGBrush {

Vector<Face> faces;
Vector<Ref<Material>> materials;
bool lock_faces = false;

inline void _regen_face_aabbs() {
for (int i = 0; i < faces.size(); i++) {
Expand Down
56 changes: 56 additions & 0 deletions modules/csg/csg_shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ enum ManifoldProperty {
MANIFOLD_PROPERTY_SMOOTH_GROUP,
MANIFOLD_PROPERTY_UV_X_0,
MANIFOLD_PROPERTY_UV_Y_0,
MANIFOLD_PROPERTY_FACE_LOCK,
MANIFOLD_PROPERTY_MAX
};

Expand Down Expand Up @@ -339,6 +340,38 @@ static String _export_meshgl_as_json(const manifold::MeshGL64 &p_mesh) {
}
#endif // DEV_ENABLED

// Yes, Manifold removes extra triangles from coplanar faces. There are several ways to make them stay - probably the easiest is adding any kind of extra vertex property.
//
// TODO: Adding any kind of extra vertex property to lock the faces.

// struct CSGBrush {
// struct Face {
// Vector3 vertices[3];
// Vector2 uvs[3];
// AABB aabb;
// bool smooth = false;
// bool invert = false;
// int material = 0;
// };

// Vector<Face> faces;
// Vector<Ref<Material>> materials;
// bool lock_faces = false;

// inline void _regen_face_aabbs() {
// for (int i = 0; i < faces.size(); i++) {
// faces.write[i].aabb = AABB();
// faces.write[i].aabb.position = faces[i].vertices[0];
// faces.write[i].aabb.expand_to(faces[i].vertices[1]);
// faces.write[i].aabb.expand_to(faces[i].vertices[2]);
// }
// }

// // Create a brush from faces.
// void build_from_faces(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials, const Vector<bool> &p_invert_faces);
// void copy_from(const CSGBrush &p_brush, const Transform3D &p_xform);
// };

static void _pack_manifold(
const CSGBrush *const p_mesh_merge,
manifold::Manifold &r_manifold,
Expand All @@ -347,6 +380,7 @@ static void _pack_manifold(
ERR_FAIL_NULL_MSG(p_mesh_merge, "p_mesh_merge is null");
ERR_FAIL_NULL_MSG(p_csg_shape, "p_shape is null");
HashMap<uint32_t, Vector<CSGBrush::Face>> faces_by_material;
bool lock_faces = p_mesh_merge->lock_faces;
for (int face_i = 0; face_i < p_mesh_merge->faces.size(); face_i++) {
const CSGBrush::Face &face = p_mesh_merge->faces[face_i];
faces_by_material[face.material].push_back(face);
Expand All @@ -373,6 +407,7 @@ static void _pack_manifold(
}

p_mesh_materials.insert(reserved_id, material);
int face_i = 0;
for (const CSGBrush::Face &face : faces) {
for (int32_t tri_order_i = 0; tri_order_i < 3; tri_order_i++) {
constexpr int32_t order[3] = { 0, 2, 1 };
Expand All @@ -392,7 +427,13 @@ static void _pack_manifold(
vert[MANIFOLD_PROPERTY_UV_Y_0] = face.uvs[i].y;
vert[MANIFOLD_PROPERTY_SMOOTH_GROUP] = face.smooth ? 1.0f : 0.0f;
vert[MANIFOLD_PROPERTY_INVERT] = face.invert ? 1.0f : 0.0f;
if (lock_faces) {
vert[MANIFOLD_PROPERTY_FACE_LOCK] = face_i;
} else {
vert[MANIFOLD_PROPERTY_FACE_LOCK] = 0.0f;
}
}
face_i++;
}
}
// runIndex needs an explicit end value.
Expand Down Expand Up @@ -996,6 +1037,10 @@ void CSGShape3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("bake_static_mesh"), &CSGShape3D::bake_static_mesh);
ClassDB::bind_method(D_METHOD("bake_collision_shape"), &CSGShape3D::bake_collision_shape);

ClassDB::bind_method(D_METHOD("set_lock_faces", "lock"), &CSGShape3D::set_lock_faces);
ClassDB::bind_method(D_METHOD("set_lock_faces"), &CSGShape3D::get_lock_faces);

ADD_PROPERTY(PropertyInfo(Variant::BOOL, "lock_faces"), "set_lock_faces", "get_lock_faces");
ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation");
#ifndef DISABLE_DEPRECATED
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_RANGE, "0.000001,1,0.000001,suffix:m", PROPERTY_USAGE_NONE), "set_snap", "get_snap");
Expand Down Expand Up @@ -2784,3 +2829,14 @@ CSGPolygon3D::CSGPolygon3D() {
path_joined = false;
path = nullptr;
}
void CSGShape3D::set_lock_faces(bool p_lock) {
if (brush) {
brush->lock_faces = p_lock;
}
}
bool CSGShape3D::get_lock_faces() const {
if (brush) {
return brush->lock_faces;
}
return false;
}
3 changes: 3 additions & 0 deletions modules/csg/csg_shape.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ class CSGShape3D : public GeometryInstance3D {
public:
Array get_meshes() const;

void set_lock_faces(bool p_lock);
bool get_lock_faces() const;

void set_operation(Operation p_operation);
Operation get_operation() const;

Expand Down

0 comments on commit 839c592

Please sign in to comment.