diff options
author | Fabian Schempp <fabianschempp@googlemail.com> | 2021-08-17 23:32:46 +0300 |
---|---|---|
committer | Fabian Schempp <fabianschempp@googlemail.com> | 2021-08-17 23:32:46 +0300 |
commit | 7649b8446278cb3db4409267afd90b39fef6de2b (patch) | |
tree | a6703d9825e9f3e3e20c97d0cd8b3b3aa016c114 /source/blender | |
parent | 809dce5bdeeb193a160b2961bf069eab76c2ce01 (diff) | |
parent | ec0ebcdcc49da24fd91b7fae0eda87903f1a8cb2 (diff) |
Merge branch 'soc-2021-porting-modifiers-to-nodes-decimate' into soc-2021-porting-modifiers-to-nodes
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_node.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.cc | 3 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh.c | 74 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh.h | 6 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operator_api.h | 3 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate_dissolve.c | 16 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_node_types.h | 23 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_nodetree.c | 52 | ||||
-rw-r--r-- | source/blender/nodes/CMakeLists.txt | 3 | ||||
-rw-r--r-- | source/blender/nodes/NOD_geometry.h | 3 | ||||
-rw-r--r-- | source/blender/nodes/NOD_static_types.h | 3 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_collapse.cc | 122 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_dissolve.cc | 137 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_unsubdivide.cc | 87 |
14 files changed, 535 insertions, 1 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index caa7ab6de0a..14448bd7c85 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1477,7 +1477,9 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_CURVE_SET_HANDLES 1072 #define GEO_NODE_CURVE_SPLINE_TYPE 1073 #define GEO_NODE_CURVE_SELECT_HANDLES 1074 - +#define GEO_NODE_COLLAPSE 1075 +#define GEO_NODE_UNSUBDIVIDE 1076 +#define GEO_NODE_DISSOLVE 1077 /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index bd22f049a8b..8a8fb7561b6 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -5136,6 +5136,7 @@ static void registerGeometryNodes() register_node_type_geo_attribute_vector_rotate(); register_node_type_geo_boolean(); register_node_type_geo_bounding_box(); + register_node_type_geo_collapse(); register_node_type_geo_collection_info(); register_node_type_geo_convex_hull(); register_node_type_geo_curve_endpoints(); @@ -5156,6 +5157,7 @@ static void registerGeometryNodes() register_node_type_geo_curve_to_points(); register_node_type_geo_curve_trim(); register_node_type_geo_delete_geometry(); + register_node_type_geo_dissolve(); register_node_type_geo_edge_split(); register_node_type_geo_input_material(); register_node_type_geo_is_viewport(); @@ -5189,6 +5191,7 @@ static void registerGeometryNodes() register_node_type_geo_switch(); register_node_type_geo_transform(); register_node_type_geo_triangulate(); + register_node_type_geo_unsubdivide(); register_node_type_geo_viewer(); register_node_type_geo_volume_to_mesh(); } diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index b2958a9e744..ef89451a587 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -1446,4 +1446,78 @@ void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm, } } +/** + * Use to select bmesh vertex data based on an array of bool. + */ +void BM_select_vertices(BMesh *bm, const bool *mask) +{ + BMIter iter; + BMVert *v; + int i; + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + BM_elem_flag_set(v, BM_ELEM_SELECT, mask[i]); + } +} + +/** + * Use to select bmesh edge data based on an array of bool. + */ +void BM_select_edges(BMesh *bm, const bool *mask) +{ + BMIter iter; + BMEdge *e; + int i; + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + BM_elem_flag_set(e, BM_ELEM_SELECT, mask[i]); + } +} + +/** + * Use to select bmesh face data based on an array of bool. + */ +void BM_select_faces(BMesh *bm, const bool *mask) +{ + BMIter iter; + BMFace *f; + int i; + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { + BM_elem_flag_set(f, BM_ELEM_SELECT, mask[i]); + } +} + +void BM_tag_vertices(BMesh *bm, const bool *mask) +{ + BMIter iter; + BMVert *v; + int i; + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + BM_elem_flag_set(v, BM_ELEM_TAG, mask[i]); + } +} + +/** + * Use to temporary tag bmesh edge data based on an array of bool. + */ +void BM_tag_edges(BMesh *bm, const bool *mask) +{ + BMIter iter; + BMEdge *e; + int i; + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + BM_elem_flag_set(e, BM_ELEM_TAG, mask[i]); + } +} + +/** + * Use to temporary tag bmesh face data based on an array of bool. + */ +void BM_tag_faces(BMesh *bm, const bool *mask) +{ + BMIter iter; + BMFace *f; + int i; + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { + BM_elem_flag_set(f, BM_ELEM_TAG, mask[i]); + } +} /** \} */ diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index bd0504b038a..5928da51d1e 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -134,3 +134,9 @@ void BM_mesh_vert_coords_apply(BMesh *bm, const float (*vert_coords)[3]); void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm, const float (*vert_coords)[3], const float mat[4][4]); +void BM_select_vertices(BMesh *bm, const bool *mask); +void BM_select_edges(BMesh *bm, const bool *mask); +void BM_select_faces(BMesh *bm, const bool *mask); +void BM_tag_vertices(BMesh *bm, const bool *mask); +void BM_tag_edges(BMesh *bm, const bool *mask); +void BM_tag_faces(BMesh *bm, const bool *mask);
\ No newline at end of file diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 0f9488bd091..06f82e21c9c 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -428,6 +428,9 @@ typedef enum { BMO_DELIM_SEAM = 1 << 2, BMO_DELIM_SHARP = 1 << 3, BMO_DELIM_UV = 1 << 4, + BMO_DELIM_EDGE_SELECTION_INVSE = 1 << 5, + BMO_DELIM_EDGE_SELECTION = 1 << 6, + BMO_DELIM_FACE_SELECTION = 1 << 7, } BMO_Delimit; void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index d8a586acee5..349b89d4340 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -104,6 +104,22 @@ static bool bm_edge_is_delimiter(const BMEdge *e, BLI_assert(BM_edge_is_manifold(e)); if (delimit != 0) { + if (delimit & BMO_DELIM_EDGE_SELECTION_INVSE) { + if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) { + return true; + } + } + if (delimit & BMO_DELIM_EDGE_SELECTION) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + return true; + } + } + if (delimit & BMO_DELIM_FACE_SELECTION) { + if (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) != + BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG)) { + return true; + } + } if (delimit & BMO_DELIM_SEAM) { if (BM_elem_flag_test(e, BM_ELEM_SEAM)) { return true; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index fd794ed1b21..65016674436 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1437,6 +1437,16 @@ typedef struct NodeGeometryRaycast { char _pad[1]; } NodeGeometryRaycast; +typedef struct NodeGeometryCollapse { + /* GeometryNodeCollapseSymmetryAxis. */ + int8_t symmetry_axis; +} NodeGeometryCollapse; + +typedef struct NodeGeometryDissolve { + /* GeometryNodeDissolveDelimiter */ + int8_t selection_type; +} NodeGeometryDissolve; + /* script node mode */ #define NODE_SCRIPT_INTERNAL 0 #define NODE_SCRIPT_EXTERNAL 1 @@ -2008,6 +2018,19 @@ typedef enum GeometryNodeRaycastMapMode { GEO_NODE_RAYCAST_NEAREST = 1, } GeometryNodeRaycastMapMode; +typedef enum GeometryNodeCollapseSymmetryAxis { + GEO_NODE_COLLAPSE_SYMMETRY_AXIS_NONE = -1, + GEO_NODE_COLLAPSE_SYMMETRY_AXIS_X = 0, + GEO_NODE_COLLAPSE_SYMMETRY_AXIS_Y = 1, + GEO_NODE_COLLAPSE_SYMMETRY_AXIS_Z = 2, +} GeometryNodeCollapseSymmetryAxis; + +typedef enum GeometryNodeDissolveDelimiter { + GEO_NODE_DISSOLVE_DELIMITTER_UNSELECTED = 0, + GEO_NODE_DISSOLVE_DELIMITTER_LIMIT = 1, + GEO_NODE_DISSOLVE_DELIMITTER_SELECTION_BORDER = 2, +} GeometryNodeDissolveDelimiter; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 7d5fffcc6c9..0b144b7f5bc 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -10094,6 +10094,58 @@ static void def_geo_curve_resample(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_collapse(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem symmetry_axis_items[] = { + {GEO_NODE_COLLAPSE_SYMMETRY_AXIS_NONE, "NONE", 0, "None", "No Symmetry is applied"}, + {GEO_NODE_COLLAPSE_SYMMETRY_AXIS_X, "X", 0, "X", "Symmetry is applied on X axis"}, + {GEO_NODE_COLLAPSE_SYMMETRY_AXIS_Y, "Y", 0, "Y", "Symmetry is applied on Y axis"}, + {GEO_NODE_COLLAPSE_SYMMETRY_AXIS_Z, "Z", 0, "Z", "Symmetry is applied on Z axis"}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_struct_sdna_from(srna, "NodeGeometryCollapse", "storage"); + + prop = RNA_def_property(srna, "symmetry_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, symmetry_axis_items); + RNA_def_property_ui_text( + prop, "Symmetry", "Set if and on what axis symmetry is applied by the operation"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + +static void def_geo_dissolve(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem delimiter_items[] = { + {GEO_NODE_DISSOLVE_DELIMITTER_UNSELECTED, + "SELECTION", + 0, + "Selection", + "Only dissolve selected"}, + {GEO_NODE_DISSOLVE_DELIMITTER_LIMIT, + "LIMIT", + 0, + "Limit", + "Only dissolve unselected. Use especially for attributes on edge domain e.g. crease"}, + {GEO_NODE_DISSOLVE_DELIMITTER_SELECTION_BORDER, + "BORDER", + 0, + "Border as Limit", + "Use border of selection as delimiter"}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_struct_sdna_from(srna, "NodeGeometryDissolve", "storage"); + + prop = RNA_def_property(srna, "selection_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, delimiter_items); + RNA_def_property_ui_text(prop, "Selection", "Define how selection is applied"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + static void def_geo_curve_subdivide(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 46fb9f54bfe..d8041b646f2 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -161,6 +161,7 @@ set(SRC geometry/nodes/node_geo_attribute_vector_rotate.cc geometry/nodes/node_geo_boolean.cc geometry/nodes/node_geo_bounding_box.cc + geometry/nodes/node_geo_collapse.cc geometry/nodes/node_geo_collection_info.cc geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_convex_hull.cc @@ -183,6 +184,7 @@ set(SRC geometry/nodes/node_geo_curve_to_points.cc geometry/nodes/node_geo_curve_trim.cc geometry/nodes/node_geo_delete_geometry.cc + geometry/nodes/node_geo_dissolve.cc geometry/nodes/node_geo_edge_split.cc geometry/nodes/node_geo_input_material.cc geometry/nodes/node_geo_is_viewport.cc @@ -214,6 +216,7 @@ set(SRC geometry/nodes/node_geo_switch.cc geometry/nodes/node_geo_transform.cc geometry/nodes/node_geo_triangulate.cc + geometry/nodes/node_geo_unsubdivide.cc geometry/nodes/node_geo_viewer.cc geometry/nodes/node_geo_volume_to_mesh.cc geometry/node_geometry_exec.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 856d787c8d0..176c3eac289 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -49,6 +49,7 @@ void register_node_type_geo_attribute_vector_math(void); void register_node_type_geo_attribute_vector_rotate(void); void register_node_type_geo_boolean(void); void register_node_type_geo_bounding_box(void); +void register_node_type_geo_collapse(void); void register_node_type_geo_collection_info(void); void register_node_type_geo_convex_hull(void); void register_node_type_geo_curve_endpoints(void); @@ -69,6 +70,7 @@ void register_node_type_geo_curve_to_mesh(void); void register_node_type_geo_curve_to_points(void); void register_node_type_geo_curve_trim(void); void register_node_type_geo_delete_geometry(void); +void register_node_type_geo_dissolve(void); void register_node_type_geo_edge_split(void); void register_node_type_geo_input_material(void); void register_node_type_geo_is_viewport(void); @@ -102,6 +104,7 @@ void register_node_type_geo_subdivision_surface(void); void register_node_type_geo_switch(void); void register_node_type_geo_transform(void); void register_node_type_geo_triangulate(void); +void register_node_type_geo_unsubdivide(void); void register_node_type_geo_viewer(void); void register_node_type_geo_volume_to_mesh(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 4da8648173d..40a0d60fc51 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -289,6 +289,7 @@ DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_VECTOR_MATH, def_geo_attribute_vector_m DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_VECTOR_ROTATE, def_geo_attribute_vector_rotate, "ATTRIBUTE_VECTOR_ROTATE", AttributeVectorRotate, "Attribute Vector Rotate", "") DefNode(GeometryNode, GEO_NODE_BOOLEAN, def_geo_boolean, "BOOLEAN", Boolean, "Boolean", "") DefNode(GeometryNode, GEO_NODE_BOUNDING_BOX, 0, "BOUNDING_BOX", BoundBox, "Bounding Box", "") +DefNode(GeometryNode, GEO_NODE_COLLAPSE, def_geo_collapse, "COLLAPSE", Collapse, "Collapse", "") DefNode(GeometryNode, GEO_NODE_COLLECTION_INFO, def_geo_collection_info, "COLLECTION_INFO", CollectionInfo, "Collection Info", "") DefNode(GeometryNode, GEO_NODE_CONVEX_HULL, 0, "CONVEX_HULL", ConvexHull, "Convex Hull", "") DefNode(GeometryNode, GEO_NODE_CURVE_ENDPOINTS, 0, "CURVE_ENDPOINTS", CurveEndpoints, "Curve Endpoints", "") @@ -310,6 +311,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, " DefNode(GeometryNode, GEO_NODE_CURVE_TO_POINTS, def_geo_curve_to_points, "CURVE_TO_POINTS", CurveToPoints, "Curve to Points", "") DefNode(GeometryNode, GEO_NODE_CURVE_TRIM, def_geo_curve_trim, "CURVE_TRIM", CurveTrim, "Curve Trim", "") DefNode(GeometryNode, GEO_NODE_DELETE_GEOMETRY, 0, "DELETE_GEOMETRY", DeleteGeometry, "Delete Geometry", "") +DefNode(GeometryNode, GEO_NODE_DISSOLVE, def_geo_dissolve, "DISSOLVE", Dissolve, "Dissolve", "") DefNode(GeometryNode, GEO_NODE_EDGE_SPLIT, 0, "EDGE_SPLIT", EdgeSplit, "Edge Split", "") DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL, def_geo_input_material, "INPUT_MATERIAL", InputMaterial, "Material", "") DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "") @@ -341,6 +343,7 @@ DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, def_geo_subdivision_surface, DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "") DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "") DefNode(GeometryNode, GEO_NODE_TRIANGULATE, def_geo_triangulate, "TRIANGULATE", Triangulate, "Triangulate", "") +DefNode(GeometryNode, GEO_NODE_UNSUBDIVIDE, 0, "UNSUBDIVIDE", Unsubdivide, "Unsubdivide", "") DefNode(GeometryNode, GEO_NODE_VIEWER, 0, "VIEWER", Viewer, "Viewer", "") DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "") diff --git a/source/blender/nodes/geometry/nodes/node_geo_collapse.cc b/source/blender/nodes/geometry/nodes/node_geo_collapse.cc new file mode 100644 index 00000000000..c13ab362f17 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_collapse.cc @@ -0,0 +1,122 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BKE_mesh.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "bmesh.h" +#include "bmesh_tools.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_collapse_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_FLOAT, N_("Factor"), 1.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, PROP_FACTOR}, + {SOCK_STRING, N_("Selection")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_collapse_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_collapse_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + uiItemR(layout, ptr, "symmetry_axis", 0, nullptr, ICON_NONE); +} + +static void geo_node_collapse_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryCollapse *node_storage = (NodeGeometryCollapse *)MEM_callocN( + sizeof(NodeGeometryCollapse), __func__); + + node->storage = node_storage; + node_storage->symmetry_axis = GEO_NODE_COLLAPSE_SYMMETRY_AXIS_NONE; +} + +namespace blender::nodes { + +static Mesh *collapse_mesh(const float factor, + const VArray<float> &selection, + const bool triangulate, + const int symmetry_axis, + const Mesh *mesh) +{ + const BMeshCreateParams bmesh_create_params = {0}; + const BMeshFromMeshParams bmesh_from_mesh_params = { + true, 0, 0, 0, {CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX}}; + BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params); + + const float symmetry_eps = 0.00002f; + Array<float> mask(selection.size()); + selection.materialize(mask); + + BM_mesh_decimate_collapse( + bm, factor, mask.data(), 1.0f, triangulate, symmetry_axis, symmetry_eps); + Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); + BM_mesh_free(bm); + + result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + return result; +} + +static void geo_node_collapse_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + const float factor = params.extract_input<float>("Factor"); + + if (factor < 1.0f && geometry_set.has_mesh()) { + MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); + + const float default_factor = 1.0f; + GVArray_Typed<float> selection_attribute = params.get_input_attribute<float>( + "Selection", mesh_component, ATTR_DOMAIN_POINT, default_factor); + // VArray<float> selection(selection_attribute.to); + const Mesh *input_mesh = mesh_component.get_for_read(); + + const bNode &node = params.node(); + const NodeGeometryCollapse &node_storage = *(NodeGeometryCollapse *)node.storage; + Mesh *result = collapse_mesh( + factor, selection_attribute, false, node_storage.symmetry_axis, input_mesh); + geometry_set.replace_mesh(result); + } + + params.set_output("Geometry", std::move(geometry_set)); +} +} // namespace blender::nodes + +void register_node_type_geo_collapse() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_COLLAPSE, "Collapse", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_collapse_in, geo_node_collapse_out); + node_type_storage( + &ntype, "NodeGeometryCollapse", node_free_standard_storage, node_copy_standard_storage); + node_type_init(&ntype, geo_node_collapse_init); + ntype.geometry_node_execute = blender::nodes::geo_node_collapse_exec; + ntype.draw_buttons = geo_node_collapse_layout; + ntype.width = 180; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_dissolve.cc b/source/blender/nodes/geometry/nodes/node_geo_dissolve.cc new file mode 100644 index 00000000000..3d41fa80e75 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_dissolve.cc @@ -0,0 +1,137 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BKE_mesh.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "bmesh.h" +#include "bmesh_tools.h" +#include "math.h" +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_dissolve_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_FLOAT, N_("Angle"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, M_PI, PROP_ANGLE}, + {SOCK_BOOLEAN, N_("All Boundaries"), false}, + {SOCK_STRING, N_("Selection")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_dissolve_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_dissolve_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + uiItemR(layout, ptr, "selection_type", 0, nullptr, ICON_NONE); +} + +static void geo_node_dissolve_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryDissolve *node_storage = (NodeGeometryDissolve *)MEM_callocN( + sizeof(NodeGeometryDissolve), __func__); + + node->storage = node_storage; + node_storage->selection_type = GEO_NODE_DISSOLVE_DELIMITTER_UNSELECTED; +} + +namespace blender::nodes { +static Mesh *dissolve_mesh(const float angle, + const bool all_boundaries, + const int delimiter, + const Span<bool> selection, + const Mesh *mesh) +{ + const BMeshCreateParams bmesh_create_params = {0}; + const BMeshFromMeshParams bmesh_from_mesh_params = { + true, 0, 0, 0, {CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX}}; + BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params); + if (delimiter & BMO_DELIM_FACE_SELECTION) { + BM_tag_faces(bm, selection.data()); + } + else { + BM_select_edges(bm, selection.data()); + } + + BM_mesh_decimate_dissolve(bm, angle, all_boundaries, (BMO_Delimit)delimiter); + + Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); + BM_mesh_free(bm); + result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + return result; +} + +static void geo_node_dissolve_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + const float angle = params.extract_input<float>("Angle"); + + if (angle > 0.0f && geometry_set.has_mesh()) { + const MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); + const Mesh *input_mesh = mesh_component.get_for_read(); + + const bool all_boundaries = params.extract_input<bool>("All Boundaries"); + const bNode &node = params.node(); + const NodeGeometryDissolve &node_storage = *(NodeGeometryDissolve *)node.storage; + + bool default_selection = false; + AttributeDomain selection_domain = ATTR_DOMAIN_FACE; + BMO_Delimit delimiter = BMO_DELIM_FACE_SELECTION; + + if (node_storage.selection_type == GEO_NODE_DISSOLVE_DELIMITTER_UNSELECTED) { + selection_domain = ATTR_DOMAIN_EDGE; + delimiter = BMO_DELIM_EDGE_SELECTION_INVSE; + } + else if (node_storage.selection_type == GEO_NODE_DISSOLVE_DELIMITTER_LIMIT) { + selection_domain = ATTR_DOMAIN_EDGE; + delimiter = BMO_DELIM_EDGE_SELECTION; + default_selection = true; + }; + + GVArray_Typed<bool> selection_attribute = params.get_input_attribute<bool>( + "Selection", mesh_component, selection_domain, default_selection); + VArray_Span<bool> selection{selection_attribute}; + + Mesh *result = dissolve_mesh(angle, all_boundaries, delimiter, selection, input_mesh); + geometry_set.replace_mesh(result); + } + + params.set_output("Geometry", std::move(geometry_set)); +} +} // namespace blender::nodes + +void register_node_type_geo_dissolve() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_DISSOLVE, "Dissolve", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_dissolve_in, geo_node_dissolve_out); + node_type_storage( + &ntype, "NodeGeometryDissolve", node_free_standard_storage, node_copy_standard_storage); + node_type_init(&ntype, geo_node_dissolve_init); + ntype.geometry_node_execute = blender::nodes::geo_node_dissolve_exec; + ntype.draw_buttons = geo_node_dissolve_layout; + ntype.width = 165; + nodeRegisterType(&ntype); +}
\ No newline at end of file diff --git a/source/blender/nodes/geometry/nodes/node_geo_unsubdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_unsubdivide.cc new file mode 100644 index 00000000000..7f0fc66ff28 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_unsubdivide.cc @@ -0,0 +1,87 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BKE_mesh.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "bmesh.h" +#include "bmesh_tools.h" +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_unsubdivide_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_INT, N_("Iterations"), 1, 0, 0, 0, 0, 10}, + {SOCK_STRING, N_("Selection")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_unsubdivide_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +namespace blender::nodes { + +static Mesh *unsubdivide_mesh(const int iterations, const Array<bool> &selection, const Mesh *mesh) +{ + const BMeshCreateParams bmesh_create_params = {0}; + const BMeshFromMeshParams bmesh_from_mesh_params = { + true, 0, 0, 0, {CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX}}; + BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params); + BM_tag_vertices(bm, selection.data()); + BM_mesh_decimate_unsubdivide_ex(bm, iterations, true); + + Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); + BM_mesh_free(bm); + result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + + return result; +} + +static void geo_node_unsubdivide_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + const int iterations = params.extract_input<int>("Iterations"); + if (iterations > 0 && geometry_set.has_mesh()) { + const MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); + const Mesh *input_mesh = mesh_component.get_for_read(); + + const bool default_selection = true; + GVArray_Typed<bool> selection_attribute = params.get_input_attribute<bool>( + "Selection", mesh_component, ATTR_DOMAIN_POINT, default_selection); + VArray_Span<bool> selection{selection_attribute}; + + Mesh *result = unsubdivide_mesh(iterations, selection, input_mesh); + if (result != input_mesh) { + geometry_set.replace_mesh(result); + } + } + params.set_output("Geometry", std::move(geometry_set)); +} +} // namespace blender::nodes + +void register_node_type_geo_unsubdivide() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_UNSUBDIVIDE, "Unsubdivide", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_unsubdivide_in, geo_node_unsubdivide_out); + ntype.geometry_node_execute = blender::nodes::geo_node_unsubdivide_exec; + ntype.width = 165; + nodeRegisterType(&ntype); +} |