diff options
Diffstat (limited to 'source/blender/modifiers/intern')
-rw-r--r-- | source/blender/modifiers/intern/MOD_boolean.cc | 5 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_mask.cc | 37 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes.cc | 93 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes_evaluator.cc | 35 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_skin.c | 63 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_surface.c | 16 |
6 files changed, 198 insertions, 51 deletions
diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc index 9b8782737c3..4b9b24e4e47 100644 --- a/source/blender/modifiers/intern/MOD_boolean.cc +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -283,11 +283,10 @@ static void BMD_mesh_intersection(BMesh *bm, /* main bmesh intersection setup */ /* create tessface & intersect */ const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); - int tottri; BMLoop *(*looptris)[3] = (BMLoop * (*)[3]) MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__); - BM_mesh_calc_tessellation_beauty(bm, looptris, &tottri); + BM_mesh_calc_tessellation_beauty(bm, looptris); /* postpone this until after tessellating * so we can use the original normals before the vertex are moved */ @@ -364,7 +363,7 @@ static void BMD_mesh_intersection(BMesh *bm, BM_mesh_intersect(bm, looptris, - tottri, + looptris_tot, bm_face_isect_pair, nullptr, false, diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 812bfe3b375..a77f6cfe8ba 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -69,6 +69,19 @@ using blender::MutableSpan; using blender::Span; using blender::Vector; +/* For delete geometry node. */ +void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span<int> vertex_map); +void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + Span<int> vertex_map, + Span<int> edge_map); +void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + Span<int> vertex_map, + Span<int> edge_map, + Span<int> masked_poly_indices, + Span<int> new_loop_starts); + static void initData(ModifierData *md) { MaskModifierData *mmd = (MaskModifierData *)md; @@ -237,9 +250,7 @@ static void computed_masked_polygons(const Mesh *mesh, *r_num_masked_loops = num_masked_loops; } -static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span<int> vertex_map) +void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span<int> vertex_map) { BLI_assert(src_mesh.totvert == vertex_map.size()); for (const int i_src : vertex_map.index_range()) { @@ -256,10 +267,10 @@ static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, } } -static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span<int> vertex_map, - Span<int> edge_map) +void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + Span<int> vertex_map, + Span<int> edge_map) { BLI_assert(src_mesh.totvert == vertex_map.size()); BLI_assert(src_mesh.totedge == edge_map.size()); @@ -279,12 +290,12 @@ static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, } } -static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span<int> vertex_map, - Span<int> edge_map, - Span<int> masked_poly_indices, - Span<int> new_loop_starts) +void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + Span<int> vertex_map, + Span<int> edge_map, + Span<int> masked_poly_indices, + Span<int> new_loop_starts) { for (const int i_dst : masked_poly_indices.index_range()) { const int i_src = masked_poly_indices[i_dst]; diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 37a21a3c14b..8fa80025790 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -36,6 +36,7 @@ #include "DNA_collection_types.h" #include "DNA_defaults.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -123,6 +124,18 @@ static void addIdsUsedBySocket(const ListBase *sockets, Set<ID *> &ids) ids.add(&collection->id); } } + else if (socket->type == SOCK_MATERIAL) { + Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value; + if (material != nullptr) { + ids.add(&material->id); + } + } + else if (socket->type == SOCK_TEXTURE) { + Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value; + if (texture != nullptr) { + ids.add(&texture->id); + } + } } } @@ -179,7 +192,7 @@ static void add_object_relation(const ModifierUpdateDepsgraphContext *ctx, Objec if (object.type == OB_EMPTY && object.instance_collection != nullptr) { add_collection_relation(ctx, *object.instance_collection); } - else if (ELEM(object.type, OB_MESH, OB_POINTCLOUD, OB_VOLUME, OB_CURVE)) { + else if (DEG_object_has_geometry_component(&object)) { DEG_add_object_relation(ctx->node, &object, DEG_OB_COMP_GEOMETRY, "Nodes Modifier"); DEG_add_customdata_mask(ctx->node, &object, &dependency_data_mask); } @@ -197,18 +210,28 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte find_used_ids_from_settings(nmd->settings, used_ids); find_used_ids_from_nodes(*nmd->node_group, used_ids); for (ID *id : used_ids) { - if (GS(id->name) == ID_OB) { - Object *object = reinterpret_cast<Object *>(id); - add_object_relation(ctx, *object); - } - if (GS(id->name) == ID_GR) { - Collection *collection = reinterpret_cast<Collection *>(id); - add_collection_relation(ctx, *collection); + switch ((ID_Type)GS(id->name)) { + case ID_OB: { + Object *object = reinterpret_cast<Object *>(id); + add_object_relation(ctx, *object); + break; + } + case ID_GR: { + Collection *collection = reinterpret_cast<Collection *>(id); + add_collection_relation(ctx, *collection); + break; + } + case ID_TE: { + DEG_add_generic_id_relation(ctx->node, id, "Nodes Modifier"); + } + default: { + /* Purposefully don't add relations for materials. While there are material sockets, + * the pointers are only passed around as handles rather than dereferenced. */ + break; + } } } } - - /* TODO: Add dependency for adding and removing objects in collections. */ } static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) @@ -560,6 +583,48 @@ static const SocketPropertyType *get_socket_property_type(const bNodeSocket &bso }; return &collection_type; } + case SOCK_TEXTURE: { + static const SocketPropertyType collection_type = { + [](const bNodeSocket &socket, const char *name) { + bNodeSocketValueTexture *value = (bNodeSocketValueTexture *)socket.default_value; + IDPropertyTemplate idprop = {0}; + idprop.id = (ID *)value->value; + return IDP_New(IDP_ID, &idprop, name); + }, + nullptr, + nullptr, + nullptr, + nullptr, + [](const IDProperty &property) { return property.type == IDP_ID; }, + [](const IDProperty &property, void *r_value) { + ID *id = IDP_Id(&property); + Tex *texture = (id && GS(id->name) == ID_TE) ? (Tex *)id : nullptr; + *(Tex **)r_value = texture; + }, + }; + return &collection_type; + } + case SOCK_MATERIAL: { + static const SocketPropertyType collection_type = { + [](const bNodeSocket &socket, const char *name) { + bNodeSocketValueMaterial *value = (bNodeSocketValueMaterial *)socket.default_value; + IDPropertyTemplate idprop = {0}; + idprop.id = (ID *)value->value; + return IDP_New(IDP_ID, &idprop, name); + }, + nullptr, + nullptr, + nullptr, + nullptr, + [](const IDProperty &property) { return property.type == IDP_ID; }, + [](const IDProperty &property, void *r_value) { + ID *id = IDP_Id(&property); + Material *material = (id && GS(id->name) == ID_MA) ? (Material *)id : nullptr; + *(Material **)r_value = material; + }, + }; + return &collection_type; + } default: { return nullptr; } @@ -1087,6 +1152,14 @@ static void draw_property_for_socket(uiLayout *layout, ICON_OUTLINER_COLLECTION); break; } + case SOCK_MATERIAL: { + uiItemPointerR(layout, md_ptr, rna_path, bmain_ptr, "materials", socket.name, ICON_MATERIAL); + break; + } + case SOCK_TEXTURE: { + uiItemPointerR(layout, md_ptr, rna_path, bmain_ptr, "textures", socket.name, ICON_TEXTURE); + break; + } default: uiItemR(layout, md_ptr, rna_path, 0, socket.name, ICON_NONE); } diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index ac5249b40a2..10ef2f4d8eb 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -175,7 +175,7 @@ enum class NodeScheduleState { struct NodeState { /** - * Needs to be locked when any data in this state is accessed that is not explicitely marked as + * Needs to be locked when any data in this state is accessed that is not explicitly marked as * otherwise. */ std::mutex mutex; @@ -192,12 +192,12 @@ struct NodeState { MutableSpan<OutputState> outputs; /** - * Nodes that don't support lazyness have some special handling the first time they are executed. + * Nodes that don't support laziness have some special handling the first time they are executed. */ bool non_lazy_node_is_initialized = false; /** - * Used to check that nodes that don't support lazyness do not run more than once. + * Used to check that nodes that don't support laziness do not run more than once. */ bool has_been_executed = false; @@ -309,9 +309,9 @@ static const CPPType *get_socket_cpp_type(const SocketRef &socket) return nodes::socket_cpp_type_get(*socket.typeinfo()); } -static bool node_supports_lazyness(const DNode node) +static bool node_supports_laziness(const DNode node) { - return node->typeinfo()->geometry_node_execute_supports_lazyness; + return node->typeinfo()->geometry_node_execute_supports_laziness; } /** Implements the callbacks that might be called when a node is executed. */ @@ -380,7 +380,8 @@ class GeometryNodesEvaluator { void execute() { - task_pool_ = BLI_task_pool_create(this, TASK_PRIORITY_HIGH); + /* Disable threading until T88598 is resolved. */ + task_pool_ = BLI_task_pool_create_no_threads(this); this->create_states_for_reachable_nodes(); this->forward_group_inputs(); @@ -644,10 +645,10 @@ class GeometryNodesEvaluator { if (!this->prepare_node_outputs_for_execution(locked_node)) { return false; } - /* Initialize nodes that don't support lazyness. This is done after at least one output is + /* Initialize nodes that don't support laziness. This is done after at least one output is * required and before we check that all required inputs are provided. This reduces the * number of "round-trips" through the task pool by one for most nodes. */ - if (!node_state.non_lazy_node_is_initialized && !node_supports_lazyness(node)) { + if (!node_state.non_lazy_node_is_initialized && !node_supports_laziness(node)) { this->initialize_non_lazy_node(locked_node); node_state.non_lazy_node_is_initialized = true; } @@ -722,7 +723,7 @@ class GeometryNodesEvaluator { /* Ignore unavailable/non-data sockets. */ continue; } - /* Nodes that don't support lazyness require all inputs. */ + /* Nodes that don't support laziness require all inputs. */ const DInputSocket input_socket = locked_node.node.input(i); this->set_input_required(locked_node, input_socket); } @@ -789,8 +790,8 @@ class GeometryNodesEvaluator { const bNode &bnode = *node->bnode(); if (node_state.has_been_executed) { - if (!node_supports_lazyness(node)) { - /* Nodes that don't support lazyness must not be executed more than once. */ + if (!node_supports_laziness(node)) { + /* Nodes that don't support laziness must not be executed more than once. */ BLI_assert_unreachable(); } } @@ -923,12 +924,12 @@ class GeometryNodesEvaluator { return; } - const bool supports_lazyness = node_supports_lazyness(locked_node.node); + const bool supports_laziness = node_supports_laziness(locked_node.node); /* Iterating over sockets instead of the states directly, because that makes it easier to * figure out which socket is missing when one of the asserts is hit. */ for (const OutputSocketRef *socket_ref : locked_node.node->outputs()) { OutputState &output_state = locked_node.node_state.outputs[socket_ref->index()]; - if (supports_lazyness) { + if (supports_laziness) { /* Expected that at least all required sockets have been computed. If more outputs become * required later, the node will be executed again. */ if (output_state.output_usage_for_execution == ValueUsage::Required) { @@ -1025,7 +1026,7 @@ class GeometryNodesEvaluator { /* Get all origin sockets, because we have to tag those as required as well. */ Vector<DSocket> origin_sockets; input_socket.foreach_origin_socket( - [&, this](const DSocket origin_socket) { origin_sockets.append(origin_socket); }); + [&](const DSocket origin_socket) { origin_sockets.append(origin_socket); }); if (origin_sockets.is_empty()) { /* If there are no origin sockets, just load the value from the socket directly. */ @@ -1078,7 +1079,7 @@ class GeometryNodesEvaluator { } /* Notify origin nodes that might want to set its inputs as unused as well. */ - socket.foreach_origin_socket([&, this](const DSocket origin_socket) { + socket.foreach_origin_socket([&](const DSocket origin_socket) { if (origin_socket->is_input()) { /* Values from these sockets are loaded directly from the sockets, so there is no node to * notify. */ @@ -1511,7 +1512,7 @@ void NodeParamsProvider::set_output(StringRef identifier, GMutablePointer value) bool NodeParamsProvider::lazy_require_input(StringRef identifier) { - BLI_assert(node_supports_lazyness(this->dnode)); + BLI_assert(node_supports_laziness(this->dnode)); const DInputSocket socket = get_input_by_identifier(this->dnode, identifier); BLI_assert(socket); @@ -1547,7 +1548,7 @@ bool NodeParamsProvider::output_is_required(StringRef identifier) const bool NodeParamsProvider::lazy_output_is_required(StringRef identifier) const { - BLI_assert(node_supports_lazyness(this->dnode)); + BLI_assert(node_supports_laziness(this->dnode)); const DOutputSocket socket = get_output_by_identifier(this->dnode, identifier); BLI_assert(socket); diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index e2d18cf1790..58d70ef3a4a 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -90,6 +90,46 @@ #include "bmesh.h" +/* -------------------------------------------------------------------- */ +/** \name Generic BMesh Utilities + * \{ */ + +static void vert_face_normal_mark_set(BMVert *v) +{ + BMIter iter; + BMFace *f; + BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { + f->no[0] = FLT_MAX; + } +} + +static void vert_face_normal_mark_update(BMVert *v) +{ + BMIter iter; + BMFace *f; + BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { + if (f->no[0] == FLT_MAX) { + BM_face_normal_update(f); + } + } +} + +/** + * Recalculate the normals of all faces connected to `verts`. + */ +static void vert_array_face_normal_update(BMVert **verts, int verts_len) +{ + for (int i = 0; i < verts_len; i++) { + vert_face_normal_mark_set(verts[i]); + } + + for (int i = 0; i < verts_len; i++) { + vert_face_normal_mark_update(verts[i]); + } +} + +/** \} */ + typedef struct { float mat[3][3]; /* Vert that edge is pointing away from, no relation to @@ -1352,13 +1392,25 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f split_face = collapse_face_corners(bm, split_face, 4, vert_buf); } - /* Done with dynamic array, split_face must now be a quad */ - BLI_array_free(vert_buf); + /* `split_face` should now be a quad. */ BLI_assert(split_face->len == 4); + + /* Account for the highly unlikely case that it's not a quad. */ if (split_face->len != 4) { + /* Reuse `vert_buf` for updating normals. */ + BLI_array_clear(vert_buf); + BLI_array_grow_items(vert_buf, split_face->len); + + BM_iter_as_array(bm, BM_FACES_OF_VERT, split_face, (void **)vert_buf, split_face->len); + + vert_array_face_normal_update(vert_buf, split_face->len); + BLI_array_free(vert_buf); return; } + /* Done with dynamic array. */ + BLI_array_free(vert_buf); + /* Get split face's verts */ // BM_iter_as_array(bm, BM_VERTS_OF_FACE, split_face, (void **)verts, 4); BM_face_as_array_vert_quad(split_face, verts); @@ -1373,6 +1425,8 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f } BMO_op_exec(bm, &op); BMO_op_finish(bm, &op); + + vert_array_face_normal_update(frame->verts, 4); } /* If the frame has some vertices that are inside the hull (detached) @@ -1731,6 +1785,11 @@ static void skin_smooth_hulls(BMesh *bm, /* Done with original coordinates */ BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, skey); + + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BM_face_normal_update(f); + } } /* Returns true if all hulls are successfully built, false otherwise */ diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index d2c011a21d3..bfd4cd81803 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -184,13 +184,17 @@ static void deformVerts(ModifierData *md, surmd->cfra = cfra; - surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh"); + const bool has_poly = surmd->mesh->totpoly > 0; + const bool has_edge = surmd->mesh->totedge > 0; + if (has_poly || has_edge) { + surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh"); - if (surmd->mesh->totpoly) { - BKE_bvhtree_from_mesh_get(surmd->bvhtree, surmd->mesh, BVHTREE_FROM_LOOPTRI, 2); - } - else { - BKE_bvhtree_from_mesh_get(surmd->bvhtree, surmd->mesh, BVHTREE_FROM_EDGES, 2); + if (has_poly) { + BKE_bvhtree_from_mesh_get(surmd->bvhtree, surmd->mesh, BVHTREE_FROM_LOOPTRI, 2); + } + else if (has_edge) { + BKE_bvhtree_from_mesh_get(surmd->bvhtree, surmd->mesh, BVHTREE_FROM_EDGES, 2); + } } } } |