Commit: 77bb17b6615b8a383d1968a94d7290d342df4007 Author: Jacques Lucke Date: Fri Jul 8 14:45:48 2022 +0200 Branches: temp-T97352-3d-texturing-seam-bleeding-b2 https://developer.blender.org/rB77bb17b6615b8a383d1968a94d7290d342df4007
Curves: support deforming curves on surface Curves that are attached to a surface can now follow the surface when it is modified using shape keys or modifiers (but not when the original surface is deformed in edit or sculpt mode). The surface is allowed to be changed in any way that keeps uv maps intact. So deformation is allowed, but also some topology changes like subdivision. The following features are added: * A new `Deform Curves on Surface` node, which deforms curves with attachment information based on the surface object and uv map set in the properties panel. * A new `Add Rest Position` checkbox in the shape keys panel. When checked, a new `rest_position` vector attribute is added to the mesh before shape keys and modifiers are applied. This is necessary to support proper deformation of the curves, but can also be used for other purposes. * The `Add > Curve > Empty Hair` operator now sets up a simple geometry nodes setup that deforms the hair. It also makes sure that the rest position attribute is added to the surface. * A new `Object (Attach Curves to Surface)` operator in the `Set Parent To` (ctrl+P) menu, which attaches existing curves to the surface and sets the surface object as parent. Limitations: * Sculpting the procedurally deformed curves will be implemented separately. * The `Deform Curves on Surface` node is not generic and can only be used for one specific purpose currently. We plan to generalize this more in the future by adding support by exposing more inputs and/or by turning it into a node group. Differential Revision: https://developer.blender.org/D14864 =================================================================== M release/scripts/startup/bl_ui/properties_data_mesh.py M release/scripts/startup/nodeitems_builtins.py M source/blender/blenkernel/BKE_mesh.h M source/blender/blenkernel/BKE_node.h M source/blender/blenkernel/intern/DerivedMesh.cc M source/blender/blenkernel/intern/mesh.cc M source/blender/blenkernel/intern/node.cc M source/blender/editors/curves/intern/curves_add.cc M source/blender/editors/curves/intern/curves_ops.cc M source/blender/editors/include/ED_curves.h M source/blender/editors/object/object_add.cc M source/blender/editors/object/object_relations.c M source/blender/makesdna/DNA_object_types.h M source/blender/makesrna/intern/rna_object.c M source/blender/modifiers/intern/MOD_nodes.cc M source/blender/nodes/NOD_geometry.h M source/blender/nodes/NOD_static_types.h M source/blender/nodes/geometry/CMakeLists.txt A source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc =================================================================== diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 0b043905713..2fc949f4aae 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -411,6 +411,8 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel): row.active = enable_edit_value row.prop(key, "eval_time") + layout.prop(ob, "add_rest_position_attribute") + class DATA_PT_uv_texture(MeshButtonsPanel, Panel): bl_label = "UV Maps" diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 3f49fb9fb58..e59c98163d7 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -73,6 +73,7 @@ def curve_node_items(context): yield NodeItem("GeometryNodeCurveLength") yield NodeItem("GeometryNodeCurveToMesh") yield NodeItem("GeometryNodeCurveToPoints") + yield NodeItem("GeometryNodeDeformCurvesWithSurface") yield NodeItem("GeometryNodeFillCurve") yield NodeItem("GeometryNodeFilletCurve") yield NodeItem("GeometryNodeResampleCurve") diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index ff4f4a8dc9e..366083fee7f 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -692,7 +692,8 @@ void BKE_mesh_calc_normals_split(struct Mesh *mesh); * to split geometry along sharp edges. */ void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh, - struct MLoopNorSpaceArray *r_lnors_spacearr); + struct MLoopNorSpaceArray *r_lnors_spacearr, + float (*r_corner_normals)[3]); /** * Higher level functions hiding most of the code needed around call to diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index e13ac3180ec..b7962ade312 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1501,6 +1501,7 @@ struct TexResult; #define GEO_NODE_MESH_TO_VOLUME 1164 #define GEO_NODE_UV_UNWRAP 1165 #define GEO_NODE_UV_PACK_ISLANDS 1166 +#define GEO_NODE_DEFORM_CURVES_ON_SURFACE 1167 /** \} */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index ffac89c15e6..c2ea01bcadf 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -66,6 +66,9 @@ # include "DNA_userdef_types.h" #endif +using blender::float3; +using blender::IndexRange; + /* very slow! enable for testing only! */ //#define USE_MODIFIER_VALIDATE @@ -814,6 +817,25 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* Clear errors before evaluation. */ BKE_modifiers_clear_errors(ob); + if (ob->modifier_flag & OB_MODIFIER_FLAG_ADD_REST_POSITION) { + if (mesh_final == nullptr) { + mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); + ASSERT_IS_VALID_MESH(mesh_final); + } + float3 *rest_positions = static_cast<float3 *>(CustomData_add_layer_named(&mesh_final->vdata, + CD_PROP_FLOAT3, + CD_DEFAULT, + nullptr, + mesh_final->totvert, + "rest_position")); + blender::threading::parallel_for( + IndexRange(mesh_final->totvert), 1024, [&](const IndexRange range) { + for (const int i : range) { + rest_positions[i] = mesh_final->mvert[i].co; + } + }); + } + /* Apply all leading deform modifiers. */ if (use_deform) { for (; md; md = md->next, md_datamask = md_datamask->next) { diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 98fa551590c..2a14370bf93 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1848,9 +1848,25 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh, BKE_mesh_tag_coords_changed(mesh); } -void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spacearr) +static float (*ensure_corner_normal_layer(Mesh &mesh))[3] { float(*r_loopnors)[3]; + if (CustomData_has_layer(&mesh.ldata, CD_NORMAL)) { + r_loopnors = (float(*)[3])CustomData_get_layer(&mesh.ldata, CD_NORMAL); + memset(r_loopnors, 0, sizeof(float[3]) * mesh.totloop); + } + else { + r_loopnors = (float(*)[3])CustomData_add_layer( + &mesh.ldata, CD_NORMAL, CD_CALLOC, nullptr, mesh.totloop); + CustomData_set_layer_flag(&mesh.ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + } + return r_loopnors; +} + +void BKE_mesh_calc_normals_split_ex(Mesh *mesh, + MLoopNorSpaceArray *r_lnors_spacearr, + float (*r_corner_normals)[3]) +{ short(*clnors)[2] = nullptr; /* Note that we enforce computing clnors when the clnor space array is requested by caller here. @@ -1860,16 +1876,6 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac ((mesh->flag & ME_AUTOSMOOTH) != 0); const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : (float)M_PI; - if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { - r_loopnors = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL); - memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop); - } - else { - r_loopnors = (float(*)[3])CustomData_add_layer( - &mesh->ldata, CD_NORMAL, CD_CALLOC, nullptr, mesh->totloop); - CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - } - /* may be nullptr */ clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); @@ -1879,7 +1885,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac mesh->medge, mesh->totedge, mesh->mloop, - r_loopnors, + r_corner_normals, mesh->totloop, mesh->mpoly, BKE_mesh_poly_normals_ensure(mesh), @@ -1895,7 +1901,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac void BKE_mesh_calc_normals_split(Mesh *mesh) { - BKE_mesh_calc_normals_split_ex(mesh, nullptr); + BKE_mesh_calc_normals_split_ex(mesh, nullptr, ensure_corner_normal_layer(*mesh)); } /* Split faces helper functions. */ @@ -2114,7 +2120,7 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) MLoopNorSpaceArray lnors_spacearr = {nullptr}; /* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */ - BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr); + BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr, ensure_corner_normal_layer(*mesh)); /* Stealing memarena from loop normals space array. */ MemArena *memarena = lnors_spacearr.mem; diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 5be912ffb2b..c6f140b9260 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -4749,6 +4749,7 @@ static void registerGeometryNodes() register_node_type_geo_curve_to_mesh(); register_node_type_geo_curve_to_points(); register_node_type_geo_curve_trim(); + register_node_type_geo_deform_curves_on_surface(); register_node_type_geo_delete_geometry(); register_node_type_geo_duplicate_elements(); register_node_type_geo_distribute_points_on_faces(); diff --git a/source/blender/editors/curves/intern/curves_add.cc b/source/blender/editors/curves/intern/curves_add.cc index 552ef1d96c8..79916253207 100644 --- a/source/blender/editors/curves/intern/curves_add.cc +++ b/source/blender/editors/curves/intern/curves_add.cc @@ -6,12 +6,96 @@ #include "BLI_rand.hh" +#include "BKE_context.h" #include "BKE_curves.hh" +#include "BKE_node.h" +#include "BKE_node_runtime.hh" #include "ED_curves.h" +#include "ED_node.h" +#include "ED_object.h" + +#include "DNA_modifier_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" namespace blender::ed::curves { +static bool has_surface_deformation_node(const bNodeTree &ntree) +{ + LISTBASE_FOREACH (const bNode *, node, &ntree.nodes) { + if (node->type == GEO_NODE_DEFORM_CURVES_ON_SURFACE) { + return true; + } + if (node->type == NODE_GROUP) { + if (node->id != nullptr) { + if (has_surface_deformation_node(*reinterpret_cast<const bNodeTree *>(node->id))) { + return true; + } + } + } + } + return false; +} + +static bool has_surface_deformation_node(const Object &curves_ob) +{ + LISTBASE_FOREACH (const ModifierData *, md, &curves_ob.modifiers) { + if (md->type != eModifierType_Nodes) { + continue; + } + const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md); + if (nmd->node_group == nullptr) { + continue; + } + if (has_surface_deformation_node(*nmd->node_group)) { + return true; + } + } + return false; +} + +void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob) +{ + if (has_surface_deformation_node(curves_ob)) { + return; + } + + Main *bmain = CTX_data_main(&C); + Scene *scene = CTX_data_scene(&C); + + ModifierData *md = ED_object_modifier_add( + nullptr, bmain, scene, &curves_ob, "Surface Deform", eModifierType_Nodes); + NodesModifierData &nmd = *reinterpret_cast<NodesModifierData *>(md); + nmd.node_group = ntreeAddTree(bmain, "Surface Deform", "GeometryNodeTree"); + + bNodeTree *ntree = nmd.node_group; + ntree @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs
