diff options
author | Hans Goudey <h.goudey@me.com> | 2022-09-28 07:04:21 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-09-28 07:04:21 +0300 |
commit | c4b7ffa6f50c9680059fd221b5d7391fae6e6f29 (patch) | |
tree | 431834a347a5cab1347ff92eb7290a8cebe04079 /source/blender/nodes | |
parent | 0f36ad24b5031f78664a935a3c483751e173e308 (diff) | |
parent | 788f3d72cf89c0301721a5eb2a72da07058dfa24 (diff) |
Merge branch 'master' into refactor-mesh-position-generic
Diffstat (limited to 'source/blender/nodes')
93 files changed, 1464 insertions, 1119 deletions
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 7c2cec873c0..4ead6326295 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -61,6 +61,7 @@ void register_node_type_geo_field_at_index(void); void register_node_type_geo_flip_faces(void); void register_node_type_geo_geometry_to_instance(void); void register_node_type_geo_image_texture(void); +void register_node_type_geo_input_control_point_neighbors(void); void register_node_type_geo_input_curve_handles(void); void register_node_type_geo_input_curve_tilt(void); void register_node_type_geo_input_id(void); @@ -118,6 +119,9 @@ void register_node_type_geo_raycast(void); void register_node_type_geo_realize_instances(void); void register_node_type_geo_remove_attribute(void); void register_node_type_geo_rotate_instances(void); +void register_node_type_geo_sample_index(void); +void register_node_type_geo_sample_nearest_surface(void); +void register_node_type_geo_sample_nearest(void); void register_node_type_geo_scale_elements(void); void register_node_type_geo_scale_instances(void); void register_node_type_geo_select_by_handle_type(void); @@ -140,7 +144,6 @@ void register_node_type_geo_string_join(void); void register_node_type_geo_string_to_curves(void); void register_node_type_geo_subdivision_surface(void); void register_node_type_geo_switch(void); -void register_node_type_geo_transfer_attribute(void); void register_node_type_geo_transform(void); void register_node_type_geo_translate_instances(void); void register_node_type_geo_triangulate(void); diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh index 42755b2e8dd..13f8af4ddf5 100644 --- a/source/blender/nodes/NOD_node_declaration.hh +++ b/source/blender/nodes/NOD_node_declaration.hh @@ -65,6 +65,8 @@ struct FieldInferencingInterface { Vector<OutputFieldDependency> outputs; }; +using ImplicitInputValueFn = std::function<void(const bNode &node, void *r_value)>; + /** * Describes a single input or output socket. This is subclassed for different socket types. */ @@ -103,6 +105,10 @@ class SocketDeclaration { /** Utility method to make the socket available if there is a straightforward way to do so. */ std::function<void(bNode &)> make_available_fn_; + /** Some input sockets can have non-trivial values in the case when they are unlinked. This + * callback computes the default input of a values in geometry nodes when nothing is linked. */ + std::unique_ptr<ImplicitInputValueFn> implicit_input_fn_; + friend NodeDeclarationBuilder; template<typename SocketDecl> friend class SocketDeclarationBuilder; @@ -140,6 +146,11 @@ class SocketDeclaration { bool compositor_skip_realization() const; bool compositor_expects_single_value() const; + const ImplicitInputValueFn *implicit_input_fn() const + { + return implicit_input_fn_.get(); + } + protected: void set_common_flags(bNodeSocket &socket) const; bool matches_common_data(const bNodeSocket &socket) const; @@ -225,10 +236,11 @@ class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder { } /** The input supports a field and is a field by default when nothing is connected. */ - Self &implicit_field() + Self &implicit_field(ImplicitInputValueFn fn) { this->hide_value(); decl_->input_field_type_ = InputSocketFieldType::Implicit; + decl_->implicit_input_fn_ = std::make_unique<ImplicitInputValueFn>(std::move(fn)); return *(Self *)this; } @@ -348,6 +360,13 @@ class NodeDeclarationBuilder { eNodeSocketInOut in_out); }; +namespace implicit_field_inputs { +void position(const bNode &node, void *r_value); +void normal(const bNode &node, void *r_value); +void index(const bNode &node, void *r_value); +void id_or_index(const bNode &node, void *r_value); +} // namespace implicit_field_inputs + /* -------------------------------------------------------------------- */ /** \name #OutputFieldDependency Inline Methods * \{ */ diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 4b055962b58..574a8dcab96 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -319,6 +319,7 @@ DefNode(GeometryNode, GEO_NODE_FLIP_FACES, 0, "FLIP_FACES", FlipFaces, "Flip Fac DefNode(GeometryNode, GEO_NODE_GEOMETRY_TO_INSTANCE, 0, "GEOMETRY_TO_INSTANCE", GeometryToInstance, "Geometry to Instance", "Convert each input geometry into an instance, which can be much faster than the Join Geometry node when the inputs are large") DefNode(GeometryNode, GEO_NODE_IMAGE_TEXTURE, def_geo_image_texture, "IMAGE_TEXTURE", ImageTexture, "Image Texture", "Sample values from an image texture") DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_HANDLES, 0, "INPUT_CURVE_HANDLES",InputCurveHandlePositions,"Curve Handle Positions", "Retrieve the position of each Bézier control point's handles") +DefNode(GeometryNode, GEO_NODE_INPUT_CONTROL_POINT_NEIGHBORS, 0, "INPUT_CONTROL_POINT_NEIGHBORS", InputControlPointNeighbors, "Control Point Neighbors", "Offset a control point index within its curve") DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_TILT, 0, "INPUT_CURVE_TILT", InputCurveTilt, "Curve Tilt", "Retrieve the angle at each control point used to twist the curve's normal around its tangent") DefNode(GeometryNode, GEO_NODE_INPUT_ID, 0, "INPUT_ID", InputID, "ID", "Retrieve a stable random identifier value from the \"id\" attribute on the point domain, or the index if the attribute does not exist") DefNode(GeometryNode, GEO_NODE_INPUT_INDEX, 0, "INDEX", InputIndex, "Index", "Retrieve an integer value indicating the position of each element in the list, starting at zero") @@ -378,6 +379,9 @@ DefNode(GeometryNode, GEO_NODE_RESAMPLE_CURVE, def_geo_curve_resample, "RESAMPLE DefNode(GeometryNode, GEO_NODE_REVERSE_CURVE, 0, "REVERSE_CURVE", ReverseCurve, "Reverse Curve", "Swap the start and end of splines") DefNode(GeometryNode, GEO_NODE_ROTATE_INSTANCES, 0, "ROTATE_INSTANCES", RotateInstances, "Rotate Instances", "Rotate geometry instances in local or global space") DefNode(GeometryNode, GEO_NODE_SAMPLE_CURVE, def_geo_curve_sample, "SAMPLE_CURVE", SampleCurve, "Sample Curve", "Retrieve data from a point on a curve at a certain distance from its start") +DefNode(GeometryNode, GEO_NODE_SAMPLE_INDEX, def_geo_sample_index, "SAMPLE_INDEX", SampleIndex, "Sample Index", "Retrieve values from specific geometry elements") +DefNode(GeometryNode, GEO_NODE_SAMPLE_NEAREST_SURFACE, def_geo_sample_nearest_surface, "SAMPLE_NEAREST_SURFACE", SampleNearestSurface, "Sample Nearest Surface", "Calculate the interpolated value of a mesh attribute on the closest point of its surface") +DefNode(GeometryNode, GEO_NODE_SAMPLE_NEAREST, def_geo_sample_nearest, "SAMPLE_NEAREST", SampleNearest, "Sample Nearest", "Find the element of a geometry closest to a position") DefNode(GeometryNode, GEO_NODE_SCALE_ELEMENTS, def_geo_scale_elements, "SCALE_ELEMENTS", ScaleElements, "Scale Elements", "Scale groups of connected edges and faces") DefNode(GeometryNode, GEO_NODE_SCALE_INSTANCES, 0, "SCALE_INSTANCES", ScaleInstances, "Scale Instances", "Scale geometry instances in local or global space") DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS",SeparateComponents, "Separate Components","Split a geometry into a separate output for each type of data in the geometry") @@ -402,7 +406,6 @@ DefNode(GeometryNode, GEO_NODE_SUBDIVIDE_CURVE, 0, "SUBDIVIDE_CURVE", SubdivideC DefNode(GeometryNode, GEO_NODE_SUBDIVIDE_MESH, 0, "SUBDIVIDE_MESH", SubdivideMesh, "Subdivide Mesh", "Divide mesh faces into smaller ones without changing the shape or volume, using linear interpolation to place the new vertices") DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, def_geo_subdivision_surface, "SUBDIVISION_SURFACE",SubdivisionSurface, "Subdivision Surface","Divide mesh faces to form a smooth surface, using the Catmull-Clark subdivision method") DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "Switch between two inputs") -DefNode(GeometryNode, GEO_NODE_TRANSFER_ATTRIBUTE, def_geo_transfer_attribute, "ATTRIBUTE_TRANSFER", AttributeTransfer, "Transfer Attribute", "Retrieve values from a source geometry and provides them as a field by interpolating them with the context geometry") DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "Translate, rotate or scale the geometry") DefNode(GeometryNode, GEO_NODE_TRANSLATE_INSTANCES, 0, "TRANSLATE_INSTANCES",TranslateInstances, "Translate Instances","Move top-level geometry instances in local or global space") DefNode(GeometryNode, GEO_NODE_TRIANGULATE, def_geo_triangulate, "TRIANGULATE", Triangulate, "Triangulate", "Convert all faces in a mesh to triangular faces") diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.cc b/source/blender/nodes/composite/nodes/node_composite_blur.cc index 630f18361e3..af7dca32c0d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_blur.cc +++ b/source/blender/nodes/composite/nodes/node_composite_blur.cc @@ -346,7 +346,7 @@ class BlurOperation : public NodeOperation { Domain domain = compute_domain(); if (get_extend_bounds()) { - domain.size.x += static_cast<int>(math::ceil(compute_blur_radius().x)) * 2; + domain.size.x += int(math::ceil(compute_blur_radius().x)) * 2; } /* We allocate an output image of a transposed size, that is, with a height equivalent to the diff --git a/source/blender/nodes/composite/nodes/node_composite_curves.cc b/source/blender/nodes/composite/nodes/node_composite_curves.cc index bf45e219730..70bd4d17007 100644 --- a/source/blender/nodes/composite/nodes/node_composite_curves.cc +++ b/source/blender/nodes/composite/nodes/node_composite_curves.cc @@ -80,8 +80,7 @@ class TimeCurveOperation : public NodeOperation { if (get_start_time() == get_end_time()) { return 0.0f; } - return static_cast<float>(frame_number - get_start_time()) / - static_cast<float>(get_end_time() - get_start_time()); + return float(frame_number - get_start_time()) / float(get_end_time() - get_start_time()); } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_dilate.cc b/source/blender/nodes/composite/nodes/node_composite_dilate.cc index 551dfacb276..0cf0c5cc80b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_dilate.cc +++ b/source/blender/nodes/composite/nodes/node_composite_dilate.cc @@ -393,7 +393,7 @@ class DilateErodeOperation : public NodeOperation { /* See the discussion in the implementation for more information. */ int get_morphological_distance_threshold_radius() { - return static_cast<int>(math::ceil(get_inset())) + math::abs(get_distance()); + return int(math::ceil(get_inset())) + math::abs(get_distance()); } /* ---------------------------------------- diff --git a/source/blender/nodes/composite/nodes/node_composite_image.cc b/source/blender/nodes/composite/nodes/node_composite_image.cc index 4d1eff0b940..4b73c1a62fb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.cc +++ b/source/blender/nodes/composite/nodes/node_composite_image.cc @@ -685,7 +685,7 @@ const char *node_cmp_rlayers_sock_to_pass(int sock_index) } const char *name = cmp_node_rlayers_out[sock_index].name; /* Exception for alpha, which is derived from Combined. */ - return (STREQ(name, "Alpha")) ? RE_PASSNAME_COMBINED : name; + return STREQ(name, "Alpha") ? RE_PASSNAME_COMBINED : name; } namespace blender::nodes::node_composite_render_layer_cc { @@ -851,7 +851,7 @@ class RenderLayerOperation : public NodeOperation { /* Other output passes are not supported for now, so allocate them as invalid. */ for (const bNodeSocket *output : this->node()->output_sockets()) { - if (!STREQ(output->identifier, "Image") && !STREQ(output->identifier, "Alpha")) { + if (!STR_ELEM(output->identifier, "Image", "Alpha")) { get_result(output->identifier).allocate_invalid(); } } diff --git a/source/blender/nodes/composite/nodes/node_composite_scene_time.cc b/source/blender/nodes/composite/nodes/node_composite_scene_time.cc index 1f5317378bb..3a7e7dc78bd 100644 --- a/source/blender/nodes/composite/nodes/node_composite_scene_time.cc +++ b/source/blender/nodes/composite/nodes/node_composite_scene_time.cc @@ -38,7 +38,7 @@ class SceneTimeOperation : public NodeOperation { { Result &result = get_result("Frame"); result.allocate_single_value(); - result.set_float_value(static_cast<float>(context().get_frame_number())); + result.set_float_value(float(context().get_frame_number())); } }; diff --git a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc index aad2f532d20..452768208c5 100644 --- a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc +++ b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc @@ -43,13 +43,13 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode) { static auto exec_preset = fn::CustomMF_presets::AllSpanOrSingle(); static fn::CustomMF_SI_SO<float, int> round_fn{ - "Round", [](float a) { return (int)round(a); }, exec_preset}; + "Round", [](float a) { return int(round(a)); }, exec_preset}; static fn::CustomMF_SI_SO<float, int> floor_fn{ - "Floor", [](float a) { return (int)floor(a); }, exec_preset}; + "Floor", [](float a) { return int(floor(a)); }, exec_preset}; static fn::CustomMF_SI_SO<float, int> ceil_fn{ - "Ceiling", [](float a) { return (int)ceil(a); }, exec_preset}; + "Ceiling", [](float a) { return int(ceil(a)); }, exec_preset}; static fn::CustomMF_SI_SO<float, int> trunc_fn{ - "Truncate", [](float a) { return (int)trunc(a); }, exec_preset}; + "Truncate", [](float a) { return int(trunc(a)); }, exec_preset}; switch (static_cast<FloatToIntRoundingMode>(bnode.custom1)) { case FN_NODE_FLOAT_TO_INT_ROUND: diff --git a/source/blender/nodes/function/nodes/node_fn_random_value.cc b/source/blender/nodes/function/nodes/node_fn_random_value.cc index 360695299cb..341a3fbfa75 100644 --- a/source/blender/nodes/function/nodes/node_fn_random_value.cc +++ b/source/blender/nodes/function/nodes/node_fn_random_value.cc @@ -33,7 +33,7 @@ static void fn_node_random_value_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR) .supports_field() .make_available([](bNode &node) { node_storage(node).data_type = CD_PROP_BOOL; }); - b.add_input<decl::Int>(N_("ID")).implicit_field(); + b.add_input<decl::Int>(N_("ID")).implicit_field(implicit_field_inputs::id_or_index); b.add_input<decl::Int>(N_("Seed")).default_value(0).min(-10000).max(10000).supports_field(); b.add_output<decl::Vector>(N_("Value")).dependent_field(); diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index f15152fe1c4..b80e87e80ac 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -71,6 +71,7 @@ set(SRC nodes/node_geo_flip_faces.cc nodes/node_geo_geometry_to_instance.cc nodes/node_geo_image_texture.cc + nodes/node_geo_input_control_point_neighbors.cc nodes/node_geo_input_curve_handles.cc nodes/node_geo_input_curve_tilt.cc nodes/node_geo_input_id.cc @@ -128,6 +129,9 @@ set(SRC nodes/node_geo_realize_instances.cc nodes/node_geo_remove_attribute.cc nodes/node_geo_rotate_instances.cc + nodes/node_geo_sample_index.cc + nodes/node_geo_sample_nearest_surface.cc + nodes/node_geo_sample_nearest.cc nodes/node_geo_scale_elements.cc nodes/node_geo_scale_instances.cc nodes/node_geo_separate_components.cc @@ -149,7 +153,6 @@ set(SRC nodes/node_geo_string_to_curves.cc nodes/node_geo_subdivision_surface.cc nodes/node_geo_switch.cc - nodes/node_geo_transfer_attribute.cc nodes/node_geo_transform.cc nodes/node_geo_translate_instances.cc nodes/node_geo_triangulate.cc diff --git a/source/blender/nodes/geometry/node_geometry_tree.cc b/source/blender/nodes/geometry/node_geometry_tree.cc index 1a12d2c49e6..61a416765a3 100644 --- a/source/blender/nodes/geometry/node_geometry_tree.cc +++ b/source/blender/nodes/geometry/node_geometry_tree.cc @@ -48,7 +48,7 @@ static void geometry_node_tree_get_from_context(const bContext *C, } if (md->type == eModifierType_Nodes) { - NodesModifierData *nmd = (NodesModifierData *)md; + const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md); if (nmd->node_group != nullptr) { *r_from = &ob->id; *r_id = &ob->id; diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc index 8f673d2264e..3192459b8b5 100644 --- a/source/blender/nodes/geometry/node_geometry_util.cc +++ b/source/blender/nodes/geometry/node_geometry_util.cc @@ -36,7 +36,7 @@ std::optional<eCustomDataType> node_data_type_to_custom_data_type(const eNodeSoc std::optional<eCustomDataType> node_socket_to_custom_data_type(const bNodeSocket &socket) { - return node_data_type_to_custom_data_type(static_cast<eNodeSocketDatatype>(socket.type)); + return node_data_type_to_custom_data_type(eNodeSocketDatatype(socket.type)); } } // namespace blender::nodes diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 4db4d8bb097..5aeb68b3fdc 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -24,6 +24,8 @@ #include "node_util.h" +struct BVHTreeFromMesh; + void geo_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass); bool geo_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree, @@ -78,6 +80,13 @@ void separate_geometry(GeometrySet &geometry_set, const Field<bool> &selection_field, bool &r_is_error); +void get_closest_in_bvhtree(BVHTreeFromMesh &tree_data, + const VArray<float3> &positions, + const IndexMask mask, + const MutableSpan<int> r_indices, + const MutableSpan<float> r_distances_sq, + const MutableSpan<float3> r_positions); + std::optional<eCustomDataType> node_data_type_to_custom_data_type(eNodeSocketDatatype type); std::optional<eCustomDataType> node_socket_to_custom_data_type(const bNodeSocket &socket); diff --git a/source/blender/nodes/geometry/nodes/node_geo_accumulate_field.cc b/source/blender/nodes/geometry/nodes/node_geo_accumulate_field.cc index 13a9cdc8600..4ad6efebfa8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_accumulate_field.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_accumulate_field.cc @@ -87,13 +87,13 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { const NodeAccumulateField &storage = node_storage(*node); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); + const eCustomDataType data_type = eCustomDataType(storage.data_type); - bNodeSocket *sock_in_vector = (bNodeSocket *)node->inputs.first; + bNodeSocket *sock_in_vector = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *sock_in_float = sock_in_vector->next; bNodeSocket *sock_in_int = sock_in_float->next; - bNodeSocket *sock_out_vector = (bNodeSocket *)node->outputs.first; + bNodeSocket *sock_out_vector = static_cast<bNodeSocket *>(node->outputs.first); bNodeSocket *sock_out_float = sock_out_vector->next; bNodeSocket *sock_out_int = sock_out_float->next; @@ -373,8 +373,8 @@ template<typename T> std::string identifier_suffix() static void node_geo_exec(GeoNodeExecParams params) { const NodeAccumulateField &storage = node_storage(params.node()); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); - const eAttrDomain source_domain = static_cast<eAttrDomain>(storage.domain); + const eCustomDataType data_type = eCustomDataType(storage.data_type); + const eAttrDomain source_domain = eAttrDomain(storage.domain); Field<int> group_index_field = params.extract_input<Field<int>>("Group Index"); attribute_math::convert_to_static_type(data_type, [&](auto dummy) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc index 8c11288efdd..c9df66f1eea 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc @@ -50,9 +50,9 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { const NodeGeometryAttributeCapture &storage = node_storage(*node); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); + const eCustomDataType data_type = eCustomDataType(storage.data_type); - bNodeSocket *socket_value_geometry = (bNodeSocket *)node->inputs.first; + bNodeSocket *socket_value_geometry = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *socket_value_vector = socket_value_geometry->next; bNodeSocket *socket_value_float = socket_value_vector->next; bNodeSocket *socket_value_color4f = socket_value_float->next; @@ -65,7 +65,7 @@ static void node_update(bNodeTree *ntree, bNode *node) nodeSetSocketAvailability(ntree, socket_value_boolean, data_type == CD_PROP_BOOL); nodeSetSocketAvailability(ntree, socket_value_int32, data_type == CD_PROP_INT32); - bNodeSocket *out_socket_value_geometry = (bNodeSocket *)node->outputs.first; + bNodeSocket *out_socket_value_geometry = static_cast<bNodeSocket *>(node->outputs.first); bNodeSocket *out_socket_value_vector = out_socket_value_geometry->next; bNodeSocket *out_socket_value_float = out_socket_value_vector->next; bNodeSocket *out_socket_value_color4f = out_socket_value_float->next; @@ -165,8 +165,8 @@ static void node_geo_exec(GeoNodeExecParams params) } const NodeGeometryAttributeCapture &storage = node_storage(params.node()); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); - const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); + const eCustomDataType data_type = eCustomDataType(storage.data_type); + const eAttrDomain domain = eAttrDomain(storage.domain); const std::string output_identifier = "Attribute" + identifier_suffix(data_type); diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_domain_size.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_domain_size.cc index f6ea6073459..a59236235a5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_domain_size.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_domain_size.cc @@ -42,7 +42,7 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { - bNodeSocket *point_socket = (bNodeSocket *)node->outputs.first; + bNodeSocket *point_socket = static_cast<bNodeSocket *>(node->outputs.first); bNodeSocket *edge_socket = point_socket->next; bNodeSocket *face_socket = edge_socket->next; bNodeSocket *face_corner_socket = face_socket->next; diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc index af0007c2fa4..0ab0081b9cf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc @@ -54,12 +54,12 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { - bNodeSocket *socket_geo = (bNodeSocket *)node->inputs.first; + bNodeSocket *socket_geo = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *socket_selection = socket_geo->next; bNodeSocket *socket_float_attr = socket_selection->next; bNodeSocket *socket_float3_attr = socket_float_attr->next; - bNodeSocket *socket_float_mean = (bNodeSocket *)node->outputs.first; + bNodeSocket *socket_float_mean = static_cast<bNodeSocket *>(node->outputs.first); bNodeSocket *socket_float_median = socket_float_mean->next; bNodeSocket *socket_float_sum = socket_float_median->next; bNodeSocket *socket_float_min = socket_float_sum->next; @@ -77,7 +77,7 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *socket_vector_std = socket_vector_range->next; bNodeSocket *socket_vector_variance = socket_vector_std->next; - const eCustomDataType data_type = static_cast<eCustomDataType>(node->custom1); + const eCustomDataType data_type = eCustomDataType(node->custom1); nodeSetSocketAvailability(ntree, socket_float_attr, data_type == CD_PROP_FLOAT); nodeSetSocketAvailability(ntree, socket_float_mean, data_type == CD_PROP_FLOAT); @@ -184,8 +184,8 @@ static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.get_input<GeometrySet>("Geometry"); const bNode &node = params.node(); - const eCustomDataType data_type = static_cast<eCustomDataType>(node.custom1); - const eAttrDomain domain = static_cast<eAttrDomain>(node.custom2); + const eCustomDataType data_type = eCustomDataType(node.custom1); + const eAttrDomain domain = eAttrDomain(node.custom2); Vector<const GeometryComponent *> components = geometry_set.get_components_for_read(); const Field<bool> selection_field = params.get_input<Field<bool>>("Selection"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc index c8c58945bce..341f58f176b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc @@ -37,7 +37,7 @@ static void node_update(bNodeTree *ntree, bNode *node) { GeometryNodeBooleanOperation operation = (GeometryNodeBooleanOperation)node->custom1; - bNodeSocket *geometry_1_socket = (bNodeSocket *)node->inputs.first; + bNodeSocket *geometry_1_socket = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *geometry_2_socket = geometry_1_socket->next; switch (operation) { @@ -148,7 +148,8 @@ static void node_geo_exec(GeoNodeExecParams params) } MEM_SAFE_FREE(result->mat); - result->mat = (Material **)MEM_malloc_arrayN(materials.size(), sizeof(Material *), __func__); + result->mat = static_cast<Material **>( + MEM_malloc_arrayN(materials.size(), sizeof(Material *), __func__)); result->totcol = materials.size(); MutableSpan(result->mat, result->totcol).copy_from(materials); diff --git a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc index 54a061993a3..f4e8788cb8d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc @@ -57,8 +57,8 @@ static void node_geo_exec(GeoNodeExecParams params) return; } const Object *self_object = params.self_object(); - const bool is_recursive = BKE_collection_has_object_recursive_instanced(collection, - (Object *)self_object); + const bool is_recursive = BKE_collection_has_object_recursive_instanced( + collection, const_cast<Object *>(self_object)); if (is_recursive) { params.error_message_add(NodeWarningType::Error, "Collection contains current object"); params.set_default_remaining_outputs(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc index 10859c4c4af..9f07c33785a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc @@ -55,7 +55,7 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords) # if 0 /* Disabled because it only works for meshes, not predictable enough. */ /* Copy custom data on vertices, like vertex groups etc. */ if (mesh && original_index < mesh->totvert) { - CustomData_copy_data(&mesh->vdata, &result->vdata, (int)original_index, (int)i, 1); + CustomData_copy_data(&mesh->vdata, &result->vdata, int(original_index), int(i), 1); } # endif } @@ -78,7 +78,7 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords) int v_to; plConvexHullGetLoop(hull, i, &v_from, &v_to); - mloop_src[i].v = (uint)v_from; + mloop_src[i].v = uint(v_from); /* Add edges for ascending order loops only. */ if (v_from < v_to) { MEdge &edge = edges[edge_index]; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc index 8640215153b..811f6981635 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc @@ -85,7 +85,7 @@ static Mesh *cdt_to_mesh(const meshintersect::CDT_result<double> &result) MutableSpan<MLoop> loops = mesh->loops_for_write(); for (const int i : IndexRange(result.vert.size())) { - positions[i] = float3((float)result.vert[i].x, (float)result.vert[i].y, 0.0f); + positions[i] = float3(float(result.vert[i].x), float(result.vert[i].y), 0.0f); } for (const int i : IndexRange(result.edge.size())) { edges[i].v1 = result.edge[i].first; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc index 4586bb24464..50863b2031a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc @@ -48,7 +48,7 @@ static void node_update(bNodeTree *ntree, bNode *node) { const NodeGeometryCurveFillet &storage = node_storage(*node); const GeometryNodeCurveFilletMode mode = (GeometryNodeCurveFilletMode)storage.mode; - bNodeSocket *poly_socket = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *poly_socket = static_cast<bNodeSocket *>(node->inputs.first)->next; nodeSetSocketAvailability(ntree, poly_socket, mode == GEO_NODE_CURVE_FILLET_POLY); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc index b34b22e995d..b1c3bbfb81e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc @@ -97,7 +97,7 @@ class HandleTypeFieldInput final : public bke::CurvesFieldInput { uint64_t hash() const override { - return get_default_hash_2((int)mode_, (int)type_); + return get_default_hash_2(int(mode_), int(type_)); } bool is_equal_to(const fn::FieldNode &other) const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_arc.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_arc.cc index ba8c9a893c2..85a8ccc3192 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_arc.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_arc.cc @@ -106,7 +106,7 @@ static void node_update(bNodeTree *ntree, bNode *node) const NodeGeometryCurvePrimitiveArc &storage = node_storage(*node); const GeometryNodeCurvePrimitiveArcMode mode = (GeometryNodeCurvePrimitiveArcMode)storage.mode; - bNodeSocket *start_socket = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *start_socket = static_cast<bNodeSocket *>(node->inputs.first)->next; bNodeSocket *middle_socket = start_socket->next; bNodeSocket *end_socket = middle_socket->next; @@ -116,7 +116,7 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *offset_angle_socket = sweep_angle_socket->next; - bNodeSocket *center_out_socket = ((bNodeSocket *)node->outputs.first)->next; + bNodeSocket *center_out_socket = static_cast<bNodeSocket *>(node->outputs.first)->next; bNodeSocket *normal_out_socket = center_out_socket->next; bNodeSocket *radius_out_socket = normal_out_socket->next; @@ -151,7 +151,7 @@ static bool colinear_f3_f3_f3(const float3 p1, const float3 p2, const float3 p3) { const float3 a = math::normalize(p2 - p1); const float3 b = math::normalize(p3 - p1); - return (ELEM(a, b, b * -1.0f)); + return ELEM(a, b, b * -1.0f); } static Curves *create_arc_curve_from_points(const int resolution, diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc index c33ba3e2a4c..12df6f76a28 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc @@ -75,12 +75,12 @@ static void node_update(bNodeTree *ntree, bNode *node) const GeometryNodeCurvePrimitiveCircleMode mode = (GeometryNodeCurvePrimitiveCircleMode) storage.mode; - bNodeSocket *start_socket = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *start_socket = static_cast<bNodeSocket *>(node->inputs.first)->next; bNodeSocket *middle_socket = start_socket->next; bNodeSocket *end_socket = middle_socket->next; bNodeSocket *radius_socket = end_socket->next; - bNodeSocket *center_socket = ((bNodeSocket *)node->outputs.first)->next; + bNodeSocket *center_socket = static_cast<bNodeSocket *>(node->outputs.first)->next; nodeSetSocketAvailability( ntree, start_socket, mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS); @@ -98,7 +98,7 @@ static bool colinear_f3_f3_f3(const float3 p1, const float3 p2, const float3 p3) { const float3 a = math::normalize(p2 - p1); const float3 b = math::normalize(p3 - p1); - return (ELEM(a, b, b * -1.0f)); + return ELEM(a, b, b * -1.0f); } static Curves *create_point_circle_curve( @@ -144,7 +144,7 @@ static Curves *create_point_circle_curve( /* Get the radius from the center-point to p1. */ const float r = math::distance(p1, center); - const float theta_step = ((2 * M_PI) / (float)resolution); + const float theta_step = ((2 * M_PI) / float(resolution)); for (const int i : IndexRange(resolution)) { /* Formula for a circle around a point and 2 unit vectors perpendicular diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc index 4cfa606d8eb..9f098674fe5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc @@ -57,7 +57,7 @@ static void node_update(bNodeTree *ntree, bNode *node) const NodeGeometryCurvePrimitiveLine &storage = node_storage(*node); const GeometryNodeCurvePrimitiveLineMode mode = (GeometryNodeCurvePrimitiveLineMode)storage.mode; - bNodeSocket *p2_socket = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *p2_socket = static_cast<bNodeSocket *>(node->inputs.first)->next; bNodeSocket *direction_socket = p2_socket->next; bNodeSocket *length_socket = direction_socket->next; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc index fec4e31701f..9536917077e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc @@ -83,10 +83,9 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { const NodeGeometryCurvePrimitiveQuad &storage = node_storage(*node); - GeometryNodeCurvePrimitiveQuadMode mode = static_cast<GeometryNodeCurvePrimitiveQuadMode>( - storage.mode); + GeometryNodeCurvePrimitiveQuadMode mode = GeometryNodeCurvePrimitiveQuadMode(storage.mode); - bNodeSocket *width = ((bNodeSocket *)node->inputs.first); + bNodeSocket *width = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *height = width->next; bNodeSocket *bottom = height->next; bNodeSocket *top = bottom->next; @@ -140,7 +139,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) search_link_ops_for_declarations(params, declaration.outputs()); } else if (params.node_tree().typeinfo->validate_link( - static_cast<eNodeSocketDatatype>(params.other_socket().type), SOCK_FLOAT)) { + eNodeSocketDatatype(params.other_socket().type), SOCK_FLOAT)) { params.add_item(IFACE_("Width"), SocketSearchOp{"Width", GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE}); params.add_item(IFACE_("Height"), diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc index 4aaf57d57cb..66284fe77db 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc @@ -43,9 +43,9 @@ static Curves *create_spiral_curve(const float rotations, const bool direction) { const int totalpoints = std::max(int(resolution * rotations), 1); - const float delta_radius = (end_radius - start_radius) / (float)totalpoints; - const float delta_height = height / (float)totalpoints; - const float delta_theta = (M_PI * 2 * rotations) / (float)totalpoints * + const float delta_radius = (end_radius - start_radius) / float(totalpoints); + const float delta_height = height / float(totalpoints); + const float delta_theta = (M_PI * 2 * rotations) / float(totalpoints) * (direction ? 1.0f : -1.0f); Curves *curves_id = bke::curves_new_nomain_single(totalpoints + 1, CURVE_TYPE_POLY); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc index 41eafe2a741..db71371d464 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc @@ -44,7 +44,7 @@ static void node_update(bNodeTree *ntree, bNode *node) const NodeGeometryCurveResample &storage = node_storage(*node); const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)storage.mode; - bNodeSocket *count_socket = ((bNodeSocket *)node->inputs.first)->next->next; + bNodeSocket *count_socket = static_cast<bNodeSocket *>(node->inputs.first)->next->next; bNodeSocket *length_socket = count_socket->next; nodeSetSocketAvailability(ntree, count_socket, mode == GEO_NODE_CURVE_RESAMPLE_COUNT); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc index e80b600a740..186c00ddda0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc @@ -52,7 +52,7 @@ static void node_update(bNodeTree *ntree, bNode *node) const NodeGeometryCurveSample &storage = node_storage(*node); const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)storage.mode; - bNodeSocket *factor = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *factor = static_cast<bNodeSocket *>(node->inputs.first)->next; bNodeSocket *length = factor->next; nodeSetSocketAvailability(ntree, factor, mode == GEO_NODE_CURVE_SAMPLE_FACTOR); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc index 919d0056bca..5a1d2461c72 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc @@ -29,6 +29,8 @@ static void node_geo_exec(GeoNodeExecParams params) GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); Field<int> cuts_field = params.extract_input<Field<int>>("Cuts"); + GeometryComponentEditData::remember_deformed_curve_positions_if_necessary(geometry_set); + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { if (!geometry_set.has_curves()) { return; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc index 799a65ec3d1..e05d80bd722 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc @@ -58,7 +58,7 @@ static void node_update(bNodeTree *ntree, bNode *node) const NodeGeometryCurveToPoints &storage = node_storage(*node); const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)storage.mode; - bNodeSocket *count_socket = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *count_socket = static_cast<bNodeSocket *>(node->inputs.first)->next; bNodeSocket *length_socket = count_socket->next; nodeSetSocketAvailability(ntree, count_socket, mode == GEO_NODE_CURVE_RESAMPLE_COUNT); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc index 1576b573058..a5a82557a4f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc @@ -64,7 +64,7 @@ static void node_update(bNodeTree *ntree, bNode *node) const NodeGeometryCurveTrim &storage = node_storage(*node); const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)storage.mode; - bNodeSocket *start_fac = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *start_fac = static_cast<bNodeSocket *>(node->inputs.first)->next; bNodeSocket *end_fac = start_fac->next; bNodeSocket *start_len = end_fac->next; bNodeSocket *end_len = start_len->next; @@ -95,8 +95,8 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) search_link_ops_for_declarations(params, declaration.inputs().take_front(1)); if (params.in_out() == SOCK_IN) { - if (params.node_tree().typeinfo->validate_link( - static_cast<eNodeSocketDatatype>(params.other_socket().type), SOCK_FLOAT)) { + if (params.node_tree().typeinfo->validate_link(eNodeSocketDatatype(params.other_socket().type), + SOCK_FLOAT)) { params.add_item(IFACE_("Start (Factor)"), SocketSearchOp{"Start", GEO_NODE_CURVE_SAMPLE_FACTOR}); params.add_item(IFACE_("End (Factor)"), SocketSearchOp{"End", GEO_NODE_CURVE_SAMPLE_FACTOR}); diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc index 380f884e992..7cdb7cc55f4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc @@ -312,10 +312,8 @@ static void node_geo_exec(GeoNodeExecParams params) ATTR_DOMAIN_POINT); const Span<float2> surface_uv_coords = curves.surface_uv_coords(); - const Span<MLoopTri> looptris_orig{BKE_mesh_runtime_looptri_ensure(surface_mesh_orig), - BKE_mesh_runtime_looptri_len(surface_mesh_orig)}; - const Span<MLoopTri> looptris_eval{BKE_mesh_runtime_looptri_ensure(surface_mesh_eval), - BKE_mesh_runtime_looptri_len(surface_mesh_eval)}; + const Span<MLoopTri> looptris_orig = surface_mesh_orig->looptris(); + const Span<MLoopTri> looptris_eval = surface_mesh_eval->looptris(); const ReverseUVSampler reverse_uv_sampler_orig{uv_map_orig, looptris_orig}; const ReverseUVSampler reverse_uv_sampler_eval{uv_map_eval, looptris_eval}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index 6fe65f38172..3ed7bd9edb4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -1145,7 +1145,7 @@ static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { const bNode *node = static_cast<bNode *>(ptr->data); const NodeGeometryDeleteGeometry &storage = node_storage(*node); - const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); + const eAttrDomain domain = eAttrDomain(storage.domain); uiItemR(layout, ptr, "domain", 0, "", ICON_NONE); /* Only show the mode when it is relevant. */ @@ -1174,7 +1174,7 @@ static void node_geo_exec(GeoNodeExecParams params) params.extract_input<Field<bool>>("Selection")); const NodeGeometryDeleteGeometry &storage = node_storage(params.node()); - const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); + const eAttrDomain domain = eAttrDomain(storage.domain); const GeometryNodeDeleteGeometryMode mode = (GeometryNodeDeleteGeometryMode)storage.mode; if (domain == ATTR_DOMAIN_INSTANCE) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc index a0bd28218cc..9910ccb84fa 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc @@ -65,10 +65,10 @@ static void node_distribute_points_in_volume_init(bNodeTree *UNUSED(ntree), bNod static void node_distribute_points_in_volume_update(bNodeTree *ntree, bNode *node) { const NodeGeometryDistributePointsInVolume &storage = node_storage(*node); - GeometryNodeDistributePointsInVolumeMode mode = - static_cast<GeometryNodeDistributePointsInVolumeMode>(storage.mode); + GeometryNodeDistributePointsInVolumeMode mode = GeometryNodeDistributePointsInVolumeMode( + storage.mode); - bNodeSocket *sock_density = ((bNodeSocket *)(node->inputs.first))->next; + bNodeSocket *sock_density = static_cast<bNodeSocket *>(node->inputs.first)->next; bNodeSocket *sock_seed = sock_density->next; bNodeSocket *sock_spacing = sock_seed->next; bNodeSocket *sock_threshold = sock_spacing->next; @@ -99,7 +99,7 @@ class PositionsVDBWrapper { void add(const openvdb::Vec3R &pos) { - vector_.append((float3((float)pos[0], (float)pos[1], (float)pos[2]) + offset_fix_)); + vector_.append(float3(float(pos[0]), float(pos[1]), float(pos[2])) + offset_fix_); } }; @@ -117,9 +117,9 @@ static void point_scatter_density_random(const openvdb::FloatGrid &grid, Vector<float3> &r_positions) { /* Offset points by half a voxel so that grid points are aligned with world grid points. */ - const float3 offset_fix = {0.5f * (float)grid.voxelSize().x(), - 0.5f * (float)grid.voxelSize().y(), - 0.5f * (float)grid.voxelSize().z()}; + const float3 offset_fix = {0.5f * float(grid.voxelSize().x()), + 0.5f * float(grid.voxelSize().y()), + 0.5f * float(grid.voxelSize().z())}; /* Setup and call into OpenVDB's point scatter API. */ PositionsVDBWrapper vdb_position_wrapper = PositionsVDBWrapper(r_positions, offset_fix); RNGType random_generator(seed); @@ -133,9 +133,9 @@ static void point_scatter_density_grid(const openvdb::FloatGrid &grid, Vector<float3> &r_positions) { const openvdb::Vec3d half_voxel(0.5, 0.5, 0.5); - const openvdb::Vec3d voxel_spacing((double)spacing.x / grid.voxelSize().x(), - (double)spacing.y / grid.voxelSize().y(), - (double)spacing.z / grid.voxelSize().z()); + const openvdb::Vec3d voxel_spacing(double(spacing.x) / grid.voxelSize().x(), + double(spacing.y) / grid.voxelSize().y(), + double(spacing.z) / grid.voxelSize().z()); /* Abort if spacing is zero. */ const double min_spacing = std::min(voxel_spacing.x(), @@ -170,7 +170,7 @@ static void point_scatter_density_grid(const openvdb::FloatGrid &grid, /* Transform with grid matrix and add point. */ const openvdb::Vec3d idx_pos(x, y, z); const openvdb::Vec3d local_pos = grid.indexToWorld(idx_pos + half_voxel); - r_positions.append({(float)local_pos.x(), (float)local_pos.y(), (float)local_pos.z()}); + r_positions.append({float(local_pos.x()), float(local_pos.y()), float(local_pos.z())}); } } } @@ -185,8 +185,8 @@ static void geo_node_distribute_points_in_volume_exec(GeoNodeExecParams params) GeometrySet geometry_set = params.extract_input<GeometrySet>("Volume"); const NodeGeometryDistributePointsInVolume &storage = node_storage(params.node()); - const GeometryNodeDistributePointsInVolumeMode mode = - static_cast<GeometryNodeDistributePointsInVolumeMode>(storage.mode); + const GeometryNodeDistributePointsInVolumeMode mode = GeometryNodeDistributePointsInVolumeMode( + storage.mode); float density; int seed; diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 11c55b262c1..e49311d07d7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -69,8 +69,8 @@ static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) static void node_point_distribute_points_on_faces_update(bNodeTree *ntree, bNode *node) { - bNodeSocket *sock_distance_min = (bNodeSocket *)BLI_findlink(&node->inputs, 2); - bNodeSocket *sock_density_max = (bNodeSocket *)sock_distance_min->next; + bNodeSocket *sock_distance_min = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2)); + bNodeSocket *sock_density_max = static_cast<bNodeSocket *>(sock_distance_min->next); bNodeSocket *sock_density = sock_density_max->next; bNodeSocket *sock_density_factor = sock_density->next; nodeSetSocketAvailability(ntree, @@ -107,8 +107,7 @@ static void sample_mesh_surface(const Mesh &mesh, { const Span<float3> positions = mesh.positions(); const Span<MLoop> loops = mesh.loops(); - const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), - BKE_mesh_runtime_looptri_len(&mesh)}; + const Span<MLoopTri> looptris = mesh.looptris(); for (const int looptri_index : looptris.index_range()) { const MLoopTri &looptri = looptris[looptri_index]; @@ -204,8 +203,7 @@ BLI_NOINLINE static void update_elimination_mask_based_on_density_factors( const Span<int> looptri_indices, const MutableSpan<bool> elimination_mask) { - const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), - BKE_mesh_runtime_looptri_len(&mesh)}; + const Span<MLoopTri> looptris = mesh.looptris(); for (const int i : bary_coords.index_range()) { if (elimination_mask[i]) { continue; @@ -352,8 +350,7 @@ BLI_NOINLINE static void compute_attribute_outputs(const Mesh &mesh, const Span<float3> positions = mesh.positions(); const Span<MLoop> loops = mesh.loops(); - const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), - BKE_mesh_runtime_looptri_len(&mesh)}; + const Span<MLoopTri> looptris = mesh.looptris(); for (const int i : bary_coords.index_range()) { const int looptri_index = looptri_indices[i]; @@ -514,8 +511,8 @@ static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh"); - const GeometryNodeDistributePointsOnFacesMode method = - static_cast<GeometryNodeDistributePointsOnFacesMode>(params.node().custom1); + const GeometryNodeDistributePointsOnFacesMode method = GeometryNodeDistributePointsOnFacesMode( + params.node().custom1); const int seed = params.get_input<int>("Seed") * 5383843; const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index bd50da06f91..50e86b2df8d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -24,7 +24,10 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>("Mesh").supported_type(GEO_COMPONENT_TYPE_MESH); b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value(); - b.add_input<decl::Vector>(N_("Offset")).subtype(PROP_TRANSLATION).implicit_field().hide_value(); + b.add_input<decl::Vector>(N_("Offset")) + .subtype(PROP_TRANSLATION) + .implicit_field(implicit_field_inputs::normal) + .hide_value(); b.add_input<decl::Float>(N_("Offset Scale")).default_value(1.0f).supports_field(); b.add_input<decl::Bool>(N_("Individual")).default_value(true); b.add_output<decl::Geometry>("Mesh"); @@ -49,9 +52,9 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { const NodeGeometryExtrudeMesh &storage = node_storage(*node); - const GeometryNodeExtrudeMeshMode mode = static_cast<GeometryNodeExtrudeMeshMode>(storage.mode); + const GeometryNodeExtrudeMeshMode mode = GeometryNodeExtrudeMeshMode(storage.mode); - bNodeSocket *individual_socket = (bNodeSocket *)node->inputs.last; + bNodeSocket *individual_socket = static_cast<bNodeSocket *>(node->inputs.last); nodeSetSocketAvailability(ntree, individual_socket, mode == GEO_NODE_EXTRUDE_MESH_FACES); } @@ -1320,7 +1323,7 @@ static void node_geo_exec(GeoNodeExecParams params) Field<float3> offset_field = params.extract_input<Field<float3>>("Offset"); Field<float> scale_field = params.extract_input<Field<float>>("Offset Scale"); const NodeGeometryExtrudeMesh &storage = node_storage(params.node()); - GeometryNodeExtrudeMeshMode mode = static_cast<GeometryNodeExtrudeMeshMode>(storage.mode); + GeometryNodeExtrudeMeshMode mode = GeometryNodeExtrudeMeshMode(storage.mode); /* Create a combined field from the offset and the scale so the field evaluator * can take care of the multiplication and to simplify each extrude function. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_field_at_index.cc b/source/blender/nodes/geometry/nodes/node_geo_field_at_index.cc index c8df5785fed..4d7e4b00c5a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_field_at_index.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_field_at_index.cc @@ -44,7 +44,7 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { - const eCustomDataType data_type = static_cast<eCustomDataType>(node->custom2); + const eCustomDataType data_type = eCustomDataType(node->custom2); bNodeSocket *sock_index = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *sock_in_float = sock_index->next; @@ -128,7 +128,7 @@ class FieldAtIndex final : public bke::GeometryFieldInput { threading::parallel_for(mask.index_range(), 1024, [&](const IndexRange range) { for (const int i : mask.slice(range)) { const int index = indices[i]; - if (index >= 0 && index < src_values.size()) { + if (src_values.index_range().contains(index)) { dst_array[i] = src_values[index]; } else { @@ -165,8 +165,8 @@ static StringRefNull identifier_suffix(eCustomDataType data_type) static void node_geo_exec(GeoNodeExecParams params) { const bNode &node = params.node(); - const eAttrDomain domain = static_cast<eAttrDomain>(node.custom1); - const eCustomDataType data_type = static_cast<eCustomDataType>(node.custom2); + const eAttrDomain domain = eAttrDomain(node.custom1); + const eCustomDataType data_type = eCustomDataType(node.custom2); Field<int> index_field = params.extract_input<Field<int>>("Index"); attribute_math::convert_to_static_type(data_type, [&](auto dummy) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc index 33802d00d2b..1dd48f437bd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc @@ -24,8 +24,8 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Image>(N_("Image")).hide_label(); b.add_input<decl::Vector>(N_("Vector")) - .implicit_field() - .description(("Texture coordinates from 0 to 1")); + .implicit_field(implicit_field_inputs::position) + .description("Texture coordinates from 0 to 1"); b.add_input<decl::Int>(N_("Frame")).min(0).max(MAXFRAMEF); b.add_output<decl::Color>(N_("Color")).no_muted_links().dependent_field(); b.add_output<decl::Float>(N_("Alpha")).no_muted_links().dependent_field(); @@ -122,9 +122,9 @@ class ImageFieldsFunction : public fn::MultiFunction { static float frac(const float x, int *ix) { - const int i = (int)x - ((x < 0.0f) ? 1 : 0); + const int i = int(x) - ((x < 0.0f) ? 1 : 0); *ix = i; - return x - (float)i; + return x - float(i); } static float4 image_cubic_texture_lookup(const ImBuf *ibuf, @@ -135,8 +135,8 @@ class ImageFieldsFunction : public fn::MultiFunction { const int width = ibuf->x; const int height = ibuf->y; int pix, piy, nix, niy; - const float tx = frac(px * (float)width - 0.5f, &pix); - const float ty = frac(py * (float)height - 0.5f, &piy); + const float tx = frac(px * float(width) - 0.5f, &pix); + const float ty = frac(py * float(height) - 0.5f, &piy); int ppix, ppiy, nnix, nniy; switch (extension) { @@ -215,8 +215,8 @@ class ImageFieldsFunction : public fn::MultiFunction { const int width = ibuf->x; const int height = ibuf->y; int pix, piy, nix, niy; - const float nfx = frac(px * (float)width - 0.5f, &pix); - const float nfy = frac(py * (float)height - 0.5f, &piy); + const float nfx = frac(px * float(width) - 0.5f, &pix); + const float nfy = frac(py * float(height) - 0.5f, &piy); switch (extension) { case SHD_IMAGE_EXTENSION_CLIP: { @@ -257,8 +257,8 @@ class ImageFieldsFunction : public fn::MultiFunction { const int width = ibuf->x; const int height = ibuf->y; int ix, iy; - const float tx = frac(px * (float)width, &ix); - const float ty = frac(py * (float)height, &iy); + const float tx = frac(px * float(width), &ix); + const float ty = frac(py * float(height), &iy); switch (extension) { case SHD_IMAGE_EXTENSION_REPEAT: { @@ -292,7 +292,7 @@ class ImageFieldsFunction : public fn::MultiFunction { 1, "Color"); MutableSpan<float> r_alpha = params.uninitialized_single_output_if_required<float>(2, "Alpha"); - MutableSpan<float4> color_data{(float4 *)r_color.data(), r_color.size()}; + MutableSpan<float4> color_data{reinterpret_cast<float4 *>(r_color.data()), r_color.size()}; /* Sample image texture. */ switch (interpolation_) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_control_point_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_control_point_neighbors.cc new file mode 100644 index 00000000000..b5d0c8cdd74 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_input_control_point_neighbors.cc @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_task.hh" + +#include "BKE_curves.hh" + +#include "node_geometry_util.hh" + +namespace blender::nodes::node_geo_input_control_point_neighbors_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Int>(N_("Point Index")) + .implicit_field(implicit_field_inputs::index) + .hide_value() + .description( + N_("The index of the control point to evaluate. Defaults to the current index")); + b.add_input<decl::Int>(N_("Offset")) + .dependent_field() + .description(N_("The number of control points along the curve to traverse")); + b.add_output<decl::Bool>(N_("Is Valid Offset")) + .field_source() + .description(N_("Outputs true if the evaluated control point plus the offset " + "is a valid index of the original curve")); + b.add_output<decl::Int>(N_("Point Index")) + .field_source() + .description(N_("The index of the control point plus the offset within the entire " + "curves data-block")); +} + +static int apply_offset_in_cyclic_range(const IndexRange range, + const int start_index, + const int offset) +{ + BLI_assert(range.contains(start_index)); + const int start_in_range = start_index - range.first(); + const int offset_in_range = start_in_range + offset; + const int mod_offset = offset_in_range % range.size(); + if (mod_offset >= 0) { + return range[mod_offset]; + } + return range.last(-(mod_offset + 1)); +} + +static Array<int> build_parent_curves(const bke::CurvesGeometry &curves) +{ + Array<int> parent_curves(curves.points_num()); + for (const int i : curves.curves_range()) { + parent_curves.as_mutable_span().slice(curves.points_for_curve(i)).fill(i); + } + return parent_curves; +} + +class ControlPointNeighborFieldInput final : public bke::CurvesFieldInput { + private: + const Field<int> index_; + const Field<int> offset_; + + public: + ControlPointNeighborFieldInput(Field<int> index, Field<int> offset) + : CurvesFieldInput(CPPType::get<int>(), "Control Point Neighbors"), + index_(std::move(index)), + offset_(std::move(offset)) + { + category_ = Category::Generated; + } + + GVArray get_varray_for_context(const bke::CurvesGeometry &curves, + const eAttrDomain domain, + const IndexMask mask) const final + { + const VArray<bool> cyclic = curves.cyclic(); + const Array<int> parent_curves = build_parent_curves(curves); + + const bke::CurvesFieldContext context{curves, domain}; + fn::FieldEvaluator evaluator{context, &mask}; + evaluator.add(index_); + evaluator.add(offset_); + evaluator.evaluate(); + const VArray<int> indices = evaluator.get_evaluated<int>(0); + const VArray<int> offsets = evaluator.get_evaluated<int>(1); + + Array<int> output(mask.min_array_size()); + for (const int i_selection : mask) { + const int i_point = std::clamp(indices[i_selection], 0, curves.points_num() - 1); + const int i_curve = parent_curves[i_point]; + const IndexRange curve_points = curves.points_for_curve(i_curve); + const int offset_point = i_point + offsets[i_point]; + + if (cyclic[i_curve]) { + output[i_selection] = apply_offset_in_cyclic_range( + curve_points, i_point, offsets[i_selection]); + continue; + } + output[i_selection] = std::clamp(offset_point, 0, curves.points_num() - 1); + } + + return VArray<int>::ForContainer(std::move(output)); + } +}; + +class OffsetValidFieldInput final : public bke::CurvesFieldInput { + private: + const Field<int> index_; + const Field<int> offset_; + + public: + OffsetValidFieldInput(Field<int> index, Field<int> offset) + : CurvesFieldInput(CPPType::get<bool>(), "Offset Valid"), + index_(std::move(index)), + offset_(std::move(offset)) + { + category_ = Category::Generated; + } + + GVArray get_varray_for_context(const bke::CurvesGeometry &curves, + const eAttrDomain domain, + const IndexMask mask) const final + { + const VArray<bool> cyclic = curves.cyclic(); + const Array<int> parent_curves = build_parent_curves(curves); + + const bke::CurvesFieldContext context{curves, domain}; + fn::FieldEvaluator evaluator{context, &mask}; + evaluator.add(index_); + evaluator.add(offset_); + evaluator.evaluate(); + const VArray<int> indices = evaluator.get_evaluated<int>(0); + const VArray<int> offsets = evaluator.get_evaluated<int>(1); + + Array<bool> output(mask.min_array_size()); + for (const int i_selection : mask) { + const int i_point = indices[i_selection]; + if (!curves.points_range().contains(i_point)) { + output[i_selection] = false; + continue; + } + + const int i_curve = parent_curves[i_point]; + const IndexRange curve_points = curves.points_for_curve(i_curve); + if (cyclic[i_curve]) { + output[i_selection] = true; + continue; + } + output[i_selection] = curve_points.contains(i_point + offsets[i_selection]); + }; + return VArray<bool>::ForContainer(std::move(output)); + } +}; + +static void node_geo_exec(GeoNodeExecParams params) +{ + Field<int> index = params.extract_input<Field<int>>("Point Index"); + Field<int> offset = params.extract_input<Field<int>>("Offset"); + + if (params.output_is_required("Point Index")) { + Field<int> curve_point_field{std::make_shared<ControlPointNeighborFieldInput>(index, offset)}; + params.set_output("Point Index", std::move(curve_point_field)); + } + if (params.output_is_required("Is Valid Offset")) { + Field<bool> valid_field{std::make_shared<OffsetValidFieldInput>(index, offset)}; + params.set_output("Is Valid Offset", std::move(valid_field)); + } +} + +} // namespace blender::nodes::node_geo_input_control_point_neighbors_cc + +void register_node_type_geo_input_control_point_neighbors() +{ + namespace file_ns = blender::nodes::node_geo_input_control_point_neighbors_cc; + static bNodeType ntype; + geo_node_type_base( + &ntype, GEO_NODE_INPUT_CONTROL_POINT_NEIGHBORS, "Control Point Neighbors", NODE_CLASS_INPUT); + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.declare = file_ns::node_declare; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_material.cc b/source/blender/nodes/geometry/nodes/node_geo_input_material.cc index 19882c4966d..6f3c6d23bd2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_material.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_material.cc @@ -19,7 +19,7 @@ static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) static void node_geo_exec(GeoNodeExecParams params) { - Material *material = (Material *)params.node().id; + Material *material = reinterpret_cast<Material *>(params.node().id); params.set_output("Material", material); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc index 1686701bc3f..cac7dade79d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc @@ -40,7 +40,8 @@ class PlanarFieldInput final : public bke::MeshFieldInput { const Span<float3> positions = mesh.positions(); const Span<MPoly> polys = mesh.polys(); const Span<MLoop> loops = mesh.loops(); - const Span<float3> poly_normals{(float3 *)BKE_mesh_poly_normals_ensure(&mesh), mesh.totpoly}; + const Span<float3> poly_normals{ + reinterpret_cast<const float3 *>(BKE_mesh_poly_normals_ensure(&mesh)), mesh.totpoly}; bke::MeshFieldContext context{mesh, ATTR_DOMAIN_FACE}; fn::FieldEvaluator evaluator{context, polys.size()}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc index da09d3650e3..8973c1db319 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc @@ -37,9 +37,9 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { const NodeGeometryInputNamedAttribute &storage = node_storage(*node); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); + const eCustomDataType data_type = eCustomDataType(storage.data_type); - bNodeSocket *socket_vector = (bNodeSocket *)node->outputs.first; + bNodeSocket *socket_vector = static_cast<bNodeSocket *>(node->outputs.first); bNodeSocket *socket_float = socket_vector->next; bNodeSocket *socket_color4f = socket_float->next; bNodeSocket *socket_boolean = socket_color4f->next; @@ -59,7 +59,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) if (params.in_out() == SOCK_OUT) { const std::optional<eCustomDataType> type = node_data_type_to_custom_data_type( - static_cast<eNodeSocketDatatype>(params.other_socket().type)); + eNodeSocketDatatype(params.other_socket().type)); if (type && *type != CD_PROP_STRING) { /* The input and output sockets have the same name. */ params.add_item(IFACE_("Attribute"), [type](LinkSearchOpParams ¶ms) { @@ -74,7 +74,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) static void node_geo_exec(GeoNodeExecParams params) { const NodeGeometryInputNamedAttribute &storage = node_storage(params.node()); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); + const eCustomDataType data_type = eCustomDataType(storage.data_type); const std::string name = params.extract_input<std::string>("Name"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_scene_time.cc b/source/blender/nodes/geometry/nodes/node_geo_input_scene_time.cc index 0222ccbbd02..74d10c286a0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_scene_time.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_scene_time.cc @@ -18,7 +18,7 @@ static void node_exec(GeoNodeExecParams params) { const Scene *scene = DEG_get_input_scene(params.depsgraph()); const float scene_ctime = BKE_scene_ctime_get(scene); - const double frame_rate = (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base); + const double frame_rate = (double(scene->r.frs_sec) / double(scene->r.frs_sec_base)); params.set_output("Seconds", float(scene_ctime / frame_rate)); params.set_output("Frame", scene_ctime); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index d54d082311f..c6f214e72ac 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -25,7 +25,7 @@ static void node_declare(NodeDeclarationBuilder &b) .description(N_("Choose instances from the \"Instance\" input at each point instead of " "instancing the entire geometry")); b.add_input<decl::Int>(N_("Instance Index")) - .implicit_field() + .implicit_field(implicit_field_inputs::id_or_index) .description(N_( "Index of the instance that used for each point. This is only used when Pick Instances " "is on. By default the point index is used")); diff --git a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc index ec2f1b00e6c..d4072a05e5f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc @@ -13,7 +13,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>(N_("Instances")).only_instances(); b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field(); - b.add_input<decl::Vector>(N_("Position")).implicit_field(); + b.add_input<decl::Vector>(N_("Position")).implicit_field(implicit_field_inputs::position); b.add_input<decl::Float>(N_("Radius")) .default_value(0.05f) .min(0.0f) diff --git a/source/blender/nodes/geometry/nodes/node_geo_interpolate_domain.cc b/source/blender/nodes/geometry/nodes/node_geo_interpolate_domain.cc index 8e38ef14aba..df1427ac5b9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_interpolate_domain.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_interpolate_domain.cc @@ -42,7 +42,7 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { - const eCustomDataType data_type = static_cast<eCustomDataType>(node->custom2); + const eCustomDataType data_type = eCustomDataType(node->custom2); bNodeSocket *sock_in_float = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *sock_in_int = sock_in_float->next; @@ -135,8 +135,8 @@ static StringRefNull identifier_suffix(eCustomDataType data_type) static void node_geo_exec(GeoNodeExecParams params) { const bNode &node = params.node(); - const eAttrDomain domain = static_cast<eAttrDomain>(node.custom1); - const eCustomDataType data_type = static_cast<eCustomDataType>(node.custom2); + const eAttrDomain domain = eAttrDomain(node.custom1); + const eCustomDataType data_type = eCustomDataType(node.custom2); attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc index a636c559157..400bc30d7a7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc @@ -115,7 +115,7 @@ static Mesh *create_circle_mesh(const float radius, MutableSpan<MLoop> loops = mesh->loops_for_write(); /* Assign vertex coordinates. */ - const float angle_delta = 2.0f * (M_PI / static_cast<float>(verts_num)); + const float angle_delta = 2.0f * (M_PI / float(verts_num)); for (const int i : IndexRange(verts_num)) { const float angle = i * angle_delta; positions[i] = float3(std::cos(angle) * radius, std::sin(angle) * radius, 0.0f); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc index e2f8f18501a..ea579396164 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc @@ -258,7 +258,7 @@ int ConeConfig::calculate_total_corners() static void calculate_cone_verts(const MutableSpan<float3> positions, const ConeConfig &config) { Array<float2> circle(config.circle_segments); - const float angle_delta = 2.0f * (M_PI / static_cast<float>(config.circle_segments)); + const float angle_delta = 2.0f * (M_PI / float(config.circle_segments)); float angle = 0.0f; for (const int i : IndexRange(config.circle_segments)) { circle[i].x = std::cos(angle); @@ -275,8 +275,7 @@ static void calculate_cone_verts(const MutableSpan<float3> positions, const Cone /* Top fill including the outer edge of the fill. */ if (!config.top_is_point) { - const float top_fill_radius_delta = config.radius_top / - static_cast<float>(config.fill_segments); + const float top_fill_radius_delta = config.radius_top / float(config.fill_segments); for (const int i : IndexRange(config.fill_segments)) { const float top_fill_radius = top_fill_radius_delta * (i + 1); for (const int j : IndexRange(config.circle_segments)) { @@ -289,8 +288,8 @@ static void calculate_cone_verts(const MutableSpan<float3> positions, const Cone /* Rings along the side. */ const float side_radius_delta = (config.radius_bottom - config.radius_top) / - static_cast<float>(config.side_segments); - const float height_delta = 2.0f * config.height / static_cast<float>(config.side_segments); + float(config.side_segments); + const float height_delta = 2.0f * config.height / float(config.side_segments); for (const int i : IndexRange(config.side_segments - 1)) { const float ring_radius = config.radius_top + (side_radius_delta * (i + 1)); const float ring_height = config.height - (height_delta * (i + 1)); @@ -303,8 +302,7 @@ static void calculate_cone_verts(const MutableSpan<float3> positions, const Cone /* Bottom fill including the outer edge of the fill. */ if (!config.bottom_is_point) { - const float bottom_fill_radius_delta = config.radius_bottom / - static_cast<float>(config.fill_segments); + const float bottom_fill_radius_delta = config.radius_bottom / float(config.fill_segments); for (const int i : IndexRange(config.fill_segments)) { const float bottom_fill_radius = config.radius_bottom - (i * bottom_fill_radius_delta); for (const int j : IndexRange(config.circle_segments)) { @@ -544,7 +542,7 @@ static void calculate_cone_uvs(Mesh *mesh, const ConeConfig &config) Array<float2> circle(config.circle_segments); float angle = 0.0f; - const float angle_delta = 2.0f * M_PI / static_cast<float>(config.circle_segments); + const float angle_delta = 2.0f * M_PI / float(config.circle_segments); for (const int i : IndexRange(config.circle_segments)) { circle[i].x = std::cos(angle) * 0.225f; circle[i].y = std::sin(angle) * 0.225f; @@ -556,9 +554,8 @@ static void calculate_cone_uvs(Mesh *mesh, const ConeConfig &config) /* Left circle of the UV representing the top fill or top cone tip. */ if (config.top_is_point || config.fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE) { const float2 center_left(0.25f, 0.25f); - const float radius_factor_delta = 1.0f / (config.top_is_point ? - static_cast<float>(config.side_segments) : - static_cast<float>(config.fill_segments)); + const float radius_factor_delta = 1.0f / (config.top_is_point ? float(config.side_segments) : + float(config.fill_segments)); const int left_circle_segment_count = config.top_is_point ? config.side_segments : config.fill_segments; @@ -595,8 +592,8 @@ static void calculate_cone_uvs(Mesh *mesh, const ConeConfig &config) if (!config.top_is_point && !config.bottom_is_point) { /* Mesh is a truncated cone or cylinder. The sides are unwrapped into a rectangle. */ const float bottom = (config.fill_type == GEO_NODE_MESH_CIRCLE_FILL_NONE) ? 0.0f : 0.5f; - const float x_delta = 1.0f / static_cast<float>(config.circle_segments); - const float y_delta = (1.0f - bottom) / static_cast<float>(config.side_segments); + const float x_delta = 1.0f / float(config.circle_segments); + const float y_delta = (1.0f - bottom) / float(config.side_segments); for (const int i : IndexRange(config.side_segments)) { for (const int j : IndexRange(config.circle_segments)) { @@ -612,8 +609,8 @@ static void calculate_cone_uvs(Mesh *mesh, const ConeConfig &config) if (config.bottom_is_point || config.fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE) { const float2 center_right(0.75f, 0.25f); const float radius_factor_delta = 1.0f / (config.bottom_is_point ? - static_cast<float>(config.side_segments) : - static_cast<float>(config.fill_segments)); + float(config.side_segments) : + float(config.fill_segments)); const int right_circle_segment_count = config.bottom_is_point ? config.side_segments : config.fill_segments; @@ -679,7 +676,7 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top, if (config.height == 0.0f) { return create_vertex_mesh(); } - const float z_delta = -2.0f * config.height / static_cast<float>(config.side_segments); + const float z_delta = -2.0f * config.height / float(config.side_segments); const float3 start(0.0f, 0.0f, config.height); const float3 delta(0.0f, 0.0f, z_delta); return create_line_mesh(start, delta, config.tot_verts); @@ -757,7 +754,7 @@ static void node_init(bNodeTree *UNUSED(ntree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { - bNodeSocket *vertices_socket = (bNodeSocket *)node->inputs.first; + bNodeSocket *vertices_socket = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *rings_socket = vertices_socket->next; bNodeSocket *fill_subdiv_socket = rings_socket->next; diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc index 301d46e586f..587999f3d00 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc @@ -66,7 +66,7 @@ static void node_init(bNodeTree *UNUSED(ntree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { - bNodeSocket *vertices_socket = (bNodeSocket *)node->inputs.first; + bNodeSocket *vertices_socket = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *rings_socket = vertices_socket->next; bNodeSocket *fill_subdiv_socket = rings_socket->next; diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc index aa9a2e9013f..8287c6a6714 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc @@ -47,7 +47,7 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions, const float radius) BMeshToMeshParams params{}; params.calc_object_remap = false; - Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr); + Mesh *mesh = reinterpret_cast<Mesh *>(BKE_id_new_nomain(ID_ME, nullptr)); BKE_id_material_eval_ensure_default_slot(&mesh->id); BM_mesh_bm_to_me(nullptr, bm, mesh, ¶ms); BM_mesh_free(bm); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc index b2b82c5dc16..4045b6223dc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc @@ -65,7 +65,7 @@ static void node_init(bNodeTree *UNUSED(ntree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { - bNodeSocket *count_socket = (bNodeSocket *)node->inputs.first; + bNodeSocket *count_socket = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *resolution_socket = count_socket->next; bNodeSocket *start_socket = resolution_socket->next; bNodeSocket *end_and_offset_socket = start_socket->next; @@ -97,7 +97,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) return; } else if (params.node_tree().typeinfo->validate_link( - static_cast<eNodeSocketDatatype>(params.other_socket().type), SOCK_FLOAT)) { + eNodeSocketDatatype(params.other_socket().type), SOCK_FLOAT)) { params.add_item(IFACE_("Count"), [](LinkSearchOpParams ¶ms) { bNode &node = params.add_node("GeometryNodeMeshLine"); node_storage(node).mode = GEO_NODE_MESH_LINE_MODE_OFFSET; @@ -153,7 +153,7 @@ static void node_geo_exec(GeoNodeExecParams params) mesh = create_line_mesh(start, float3(0), count); } else { - const float3 delta = total_delta / (float)(count - 1); + const float3 delta = total_delta / float(count - 1); mesh = create_line_mesh(start, delta, count); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index e493e4556a4..6db4c82d5cf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -266,16 +266,16 @@ BLI_NOINLINE static void calculate_sphere_uvs(Mesh *mesh, const float segments, const float segments_inv = 1.0f / segments; for (const int i_segment : IndexRange(segments)) { - const float segment = static_cast<float>(i_segment); + const float segment = float(i_segment); uvs[loop_index++] = float2((segment + 0.5f) * segments_inv, 0.0f); uvs[loop_index++] = float2(segment * segments_inv, dy); uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, dy); } for (const int i_ring : IndexRange(1, rings - 2)) { - const float ring = static_cast<float>(i_ring); + const float ring = float(i_ring); for (const int i_segment : IndexRange(segments)) { - const float segment = static_cast<float>(i_segment); + const float segment = float(i_segment); uvs[loop_index++] = float2(segment * segments_inv, ring / rings); uvs[loop_index++] = float2(segment * segments_inv, (ring + 1.0f) / rings); uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, (ring + 1.0f) / rings); @@ -284,7 +284,7 @@ BLI_NOINLINE static void calculate_sphere_uvs(Mesh *mesh, const float segments, } for (const int i_segment : IndexRange(segments)) { - const float segment = static_cast<float>(i_segment); + const float segment = float(i_segment); uvs[loop_index++] = float2((segment + 0.5f) * segments_inv, 1.0f); uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, 1.0f - dy); uvs[loop_index++] = float2(segment * segments_inv, 1.0f - dy); @@ -309,7 +309,8 @@ static Mesh *create_uv_sphere_mesh(const float radius, const int segments, const threading::parallel_invoke( 1024 < segments * rings, [&]() { - MutableSpan vert_normals{(float3 *)BKE_mesh_vertex_normals_for_write(mesh), mesh->totvert}; + MutableSpan vert_normals{ + reinterpret_cast<float3 *>(BKE_mesh_vertex_normals_for_write(mesh)), mesh->totvert}; calculate_sphere_vertex_data(positions, vert_normals, radius, segments, rings); BKE_mesh_vertex_normals_clear_dirty(mesh); }, diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc index ce06ccbda75..ceb87c59b8e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc @@ -24,7 +24,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH); b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value(); - b.add_input<decl::Vector>(N_("Position")).implicit_field(); + b.add_input<decl::Vector>(N_("Position")).implicit_field(implicit_field_inputs::position); b.add_input<decl::Float>(N_("Radius")) .default_value(0.05f) .min(0.0f) diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc index f6fa5c99013..de04f0561e5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc @@ -59,24 +59,22 @@ static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) static void node_init(bNodeTree *UNUSED(tree), bNode *node) { - NodeGeometryMeshToVolume *data = (NodeGeometryMeshToVolume *)MEM_callocN( - sizeof(NodeGeometryMeshToVolume), __func__); + NodeGeometryMeshToVolume *data = MEM_cnew<NodeGeometryMeshToVolume>(__func__); data->resolution_mode = MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT; node->storage = data; } static void node_update(bNodeTree *ntree, bNode *node) { - NodeGeometryMeshToVolume *data = (NodeGeometryMeshToVolume *)node->storage; + NodeGeometryMeshToVolume &data = node_storage(*node); bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size"); bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount"); nodeSetSocketAvailability(ntree, voxel_amount_socket, - data->resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT); - nodeSetSocketAvailability(ntree, - voxel_size_socket, - data->resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE); + data.resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT); + nodeSetSocketAvailability( + ntree, voxel_size_socket, data.resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE); } #ifdef WITH_OPENVDB @@ -126,7 +124,7 @@ static Volume *create_volume_from_mesh(const Mesh &mesh, GeoNodeExecParams ¶ exterior_band_width, mesh_to_volume_space_transform); - Volume *volume = (Volume *)BKE_id_new_nomain(ID_VO, nullptr); + Volume *volume = reinterpret_cast<Volume *>(BKE_id_new_nomain(ID_VO, nullptr)); BKE_volume_init_grids(volume); /* Convert mesh to grid and add to volume. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc index 0990eebb903..ec9a40f8cf8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc @@ -83,7 +83,7 @@ struct ParticleList { size_t size() const { - return (size_t)positions.size(); + return size_t(positions.size()); } void getPos(size_t n, openvdb::Vec3R &xyz) const @@ -215,7 +215,7 @@ static void initialize_volume_component_from_points(GeoNodeExecParams ¶ms, return; } - Volume *volume = (Volume *)BKE_id_new_nomain(ID_VO, nullptr); + Volume *volume = reinterpret_cast<Volume *>(BKE_id_new_nomain(ID_VO, nullptr)); BKE_volume_init_grids(volume); const float density = params.get_input<float>("Density"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_proximity.cc index d5233ee35a4..f453c7cb47a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_proximity.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_proximity.cc @@ -22,7 +22,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input<decl::Geometry>(N_("Target")) .only_realized_data() .supported_type({GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD}); - b.add_input<decl::Vector>(N_("Source Position")).implicit_field(); + b.add_input<decl::Vector>(N_("Source Position")).implicit_field(implicit_field_inputs::position); b.add_output<decl::Vector>(N_("Position")).dependent_field(); b.add_output<decl::Float>(N_("Distance")).dependent_field(); } @@ -211,8 +211,7 @@ static void node_geo_exec(GeoNodeExecParams params) Field<float3> position_field = params.extract_input<Field<float3>>("Source Position"); auto proximity_fn = std::make_unique<ProximityFunction>( - std::move(geometry_set_target), - static_cast<GeometryNodeProximityTargetType>(storage.target_element)); + std::move(geometry_set_target), GeometryNodeProximityTargetType(storage.target_element)); auto proximity_op = std::make_shared<FieldOperation>( FieldOperation(std::move(proximity_fn), {std::move(position_field)})); diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc index f657b128c51..118d6c2f6c7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc @@ -31,7 +31,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input<decl::Bool>(N_("Attribute"), "Attribute_003").hide_value().supports_field(); b.add_input<decl::Int>(N_("Attribute"), "Attribute_004").hide_value().supports_field(); - b.add_input<decl::Vector>(N_("Source Position")).implicit_field(); + b.add_input<decl::Vector>(N_("Source Position")).implicit_field(implicit_field_inputs::position); b.add_input<decl::Vector>(N_("Ray Direction")) .default_value({0.0f, 0.0f, -1.0f}) .supports_field(); @@ -70,9 +70,9 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { const NodeGeometryRaycast &storage = node_storage(*node); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); + const eCustomDataType data_type = eCustomDataType(storage.data_type); - bNodeSocket *socket_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 1); + bNodeSocket *socket_vector = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1)); bNodeSocket *socket_float = socket_vector->next; bNodeSocket *socket_color4f = socket_float->next; bNodeSocket *socket_boolean = socket_color4f->next; @@ -84,7 +84,7 @@ static void node_update(bNodeTree *ntree, bNode *node) nodeSetSocketAvailability(ntree, socket_boolean, data_type == CD_PROP_BOOL); nodeSetSocketAvailability(ntree, socket_int32, data_type == CD_PROP_INT32); - bNodeSocket *out_socket_vector = (bNodeSocket *)BLI_findlink(&node->outputs, 4); + bNodeSocket *out_socket_vector = static_cast<bNodeSocket *>(BLI_findlink(&node->outputs, 4)); bNodeSocket *out_socket_float = out_socket_vector->next; bNodeSocket *out_socket_color4f = out_socket_float->next; bNodeSocket *out_socket_boolean = out_socket_color4f->next; @@ -386,8 +386,8 @@ static void node_geo_exec(GeoNodeExecParams params) { GeometrySet target = params.extract_input<GeometrySet>("Target Geometry"); const NodeGeometryRaycast &storage = node_storage(params.node()); - const GeometryNodeRaycastMapMode mapping = (GeometryNodeRaycastMapMode)storage.mapping; - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); + const GeometryNodeRaycastMapMode mapping = GeometryNodeRaycastMapMode(storage.mapping); + const eCustomDataType data_type = eCustomDataType(storage.data_type); if (target.is_empty()) { params.set_default_remaining_outputs(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc new file mode 100644 index 00000000000..bfaf9b70f13 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc @@ -0,0 +1,337 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_task.hh" + +#include "BKE_attribute_math.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "NOD_socket_search_link.hh" + +#include "node_geometry_util.hh" + +namespace blender::nodes::node_geo_sample_index_cc { + +NODE_STORAGE_FUNCS(NodeGeometrySampleIndex); + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>(N_("Geometry")) + .supported_type({GEO_COMPONENT_TYPE_MESH, + GEO_COMPONENT_TYPE_POINT_CLOUD, + GEO_COMPONENT_TYPE_CURVE, + GEO_COMPONENT_TYPE_INSTANCES}); + + b.add_input<decl::Float>(N_("Value"), "Value_Float").hide_value().supports_field(); + b.add_input<decl::Int>(N_("Value"), "Value_Int").hide_value().supports_field(); + b.add_input<decl::Vector>(N_("Value"), "Value_Vector").hide_value().supports_field(); + b.add_input<decl::Color>(N_("Value"), "Value_Color").hide_value().supports_field(); + b.add_input<decl::Bool>(N_("Value"), "Value_Bool").hide_value().supports_field(); + b.add_input<decl::Int>(N_("Index")) + .supports_field() + .description(N_("Which element to retrieve a value from on the geometry")); + + b.add_output<decl::Float>(N_("Value"), "Value_Float").dependent_field({6}); + b.add_output<decl::Int>(N_("Value"), "Value_Int").dependent_field({6}); + b.add_output<decl::Vector>(N_("Value"), "Value_Vector").dependent_field({6}); + b.add_output<decl::Color>(N_("Value"), "Value_Color").dependent_field({6}); + b.add_output<decl::Bool>(N_("Value"), "Value_Bool").dependent_field({6}); +} + +static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "domain", 0, "", ICON_NONE); + uiItemR(layout, ptr, "clamp", 0, nullptr, ICON_NONE); +} + +static void node_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometrySampleIndex *data = MEM_cnew<NodeGeometrySampleIndex>(__func__); + data->data_type = CD_PROP_FLOAT; + data->domain = ATTR_DOMAIN_POINT; + data->clamp = 0; + node->storage = data; +} + +static void node_update(bNodeTree *ntree, bNode *node) +{ + const eCustomDataType data_type = eCustomDataType(node_storage(*node).data_type); + + bNodeSocket *in_socket_geometry = static_cast<bNodeSocket *>(node->inputs.first); + bNodeSocket *in_socket_float = in_socket_geometry->next; + bNodeSocket *in_socket_int32 = in_socket_float->next; + bNodeSocket *in_socket_vector = in_socket_int32->next; + bNodeSocket *in_socket_color4f = in_socket_vector->next; + bNodeSocket *in_socket_bool = in_socket_color4f->next; + + nodeSetSocketAvailability(ntree, in_socket_vector, data_type == CD_PROP_FLOAT3); + nodeSetSocketAvailability(ntree, in_socket_float, data_type == CD_PROP_FLOAT); + nodeSetSocketAvailability(ntree, in_socket_color4f, data_type == CD_PROP_COLOR); + nodeSetSocketAvailability(ntree, in_socket_bool, data_type == CD_PROP_BOOL); + nodeSetSocketAvailability(ntree, in_socket_int32, data_type == CD_PROP_INT32); + + bNodeSocket *out_socket_float = static_cast<bNodeSocket *>(node->outputs.first); + bNodeSocket *out_socket_int32 = out_socket_float->next; + bNodeSocket *out_socket_vector = out_socket_int32->next; + bNodeSocket *out_socket_color4f = out_socket_vector->next; + bNodeSocket *out_socket_bool = out_socket_color4f->next; + + nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3); + nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT); + nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR); + nodeSetSocketAvailability(ntree, out_socket_bool, data_type == CD_PROP_BOOL); + nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32); +} + +static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) +{ + const NodeDeclaration &declaration = *params.node_type().fixed_declaration; + search_link_ops_for_declarations(params, declaration.inputs().take_back(1)); + search_link_ops_for_declarations(params, declaration.inputs().take_front(1)); + + const std::optional<eCustomDataType> type = node_data_type_to_custom_data_type( + (eNodeSocketDatatype)params.other_socket().type); + if (type && *type != CD_PROP_STRING) { + /* The input and output sockets have the same name. */ + params.add_item(IFACE_("Value"), [type](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("GeometryNodeSampleIndex"); + node_storage(node).data_type = *type; + params.update_and_connect_available_socket(node, "Value"); + }); + } +} + +static bool component_is_available(const GeometrySet &geometry, + const GeometryComponentType type, + const eAttrDomain domain) +{ + if (!geometry.has(type)) { + return false; + } + const GeometryComponent &component = *geometry.get_component_for_read(type); + if (component.is_empty()) { + return false; + } + return component.attribute_domain_size(domain) != 0; +} + +static const GeometryComponent *find_source_component(const GeometrySet &geometry, + const eAttrDomain domain) +{ + /* Choose the other component based on a consistent order, rather than some more complicated + * heuristic. This is the same order visible in the spreadsheet and used in the ray-cast node. */ + static const Array<GeometryComponentType> supported_types = {GEO_COMPONENT_TYPE_MESH, + GEO_COMPONENT_TYPE_POINT_CLOUD, + GEO_COMPONENT_TYPE_CURVE, + GEO_COMPONENT_TYPE_INSTANCES}; + for (const GeometryComponentType src_type : supported_types) { + if (component_is_available(geometry, src_type, domain)) { + return geometry.get_component_for_read(src_type); + } + } + + return nullptr; +} + +template<typename T> +void copy_with_indices(const VArray<T> &src, + const VArray<int> &indices, + const IndexMask mask, + MutableSpan<T> dst) +{ + const IndexRange src_range = src.index_range(); + devirtualize_varray2(src, indices, [&](const auto src, const auto indices) { + threading::parallel_for(mask.index_range(), 4096, [&](IndexRange range) { + for (const int i : mask.slice(range)) { + const int index = indices[i]; + if (src_range.contains(index)) { + dst[i] = src[index]; + } + else { + dst[i] = {}; + } + } + }); + }); +} + +template<typename T> +void copy_with_clamped_indices(const VArray<T> &src, + const VArray<int> &indices, + const IndexMask mask, + MutableSpan<T> dst) +{ + const int last_index = src.index_range().last(); + devirtualize_varray2(src, indices, [&](const auto src, const auto indices) { + threading::parallel_for(mask.index_range(), 4096, [&](IndexRange range) { + for (const int i : mask.slice(range)) { + const int index = indices[i]; + dst[i] = src[std::clamp(index, 0, last_index)]; + } + }); + }); +} + +/** + * The index-based transfer theoretically does not need realized data when there is only one + * instance geometry set in the source. A future optimization could be removing that limitation + * internally. + */ +class SampleIndexFunction : public fn::MultiFunction { + GeometrySet src_geometry_; + GField src_field_; + eAttrDomain domain_; + bool clamp_; + + fn::MFSignature signature_; + + std::optional<bke::GeometryFieldContext> geometry_context_; + std::unique_ptr<FieldEvaluator> evaluator_; + const GVArray *src_data_ = nullptr; + + public: + SampleIndexFunction(GeometrySet geometry, + GField src_field, + const eAttrDomain domain, + const bool clamp) + : src_geometry_(std::move(geometry)), + src_field_(std::move(src_field)), + domain_(domain), + clamp_(clamp) + { + src_geometry_.ensure_owns_direct_data(); + + signature_ = this->create_signature(); + this->set_signature(&signature_); + + this->evaluate_field(); + } + + fn::MFSignature create_signature() + { + fn::MFSignatureBuilder signature{"Sample Index"}; + signature.single_input<int>("Index"); + signature.single_output("Value", src_field_.cpp_type()); + return signature.build(); + } + + void evaluate_field() + { + const GeometryComponent *component = find_source_component(src_geometry_, domain_); + if (component == nullptr) { + return; + } + const int domain_num = component->attribute_domain_size(domain_); + geometry_context_.emplace(bke::GeometryFieldContext(*component, domain_)); + evaluator_ = std::make_unique<FieldEvaluator>(*geometry_context_, domain_num); + evaluator_->add(src_field_); + evaluator_->evaluate(); + src_data_ = &evaluator_->get_evaluated(0); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + const VArray<int> &indices = params.readonly_single_input<int>(0, "Index"); + GMutableSpan dst = params.uninitialized_single_output(1, "Value"); + + const CPPType &type = dst.type(); + if (src_data_ == nullptr) { + type.value_initialize_indices(dst.data(), mask); + return; + } + + attribute_math::convert_to_static_type(type, [&](auto dummy) { + using T = decltype(dummy); + if (clamp_) { + copy_with_clamped_indices(src_data_->typed<T>(), indices, mask, dst.typed<T>()); + } + else { + copy_with_indices(src_data_->typed<T>(), indices, mask, dst.typed<T>()); + } + }); + } +}; + +static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustomDataType data_type) +{ + switch (data_type) { + case CD_PROP_FLOAT: + return params.extract_input<Field<float>>("Value_Float"); + case CD_PROP_FLOAT3: + return params.extract_input<Field<float3>>("Value_Vector"); + case CD_PROP_COLOR: + return params.extract_input<Field<ColorGeometry4f>>("Value_Color"); + case CD_PROP_BOOL: + return params.extract_input<Field<bool>>("Value_Bool"); + case CD_PROP_INT32: + return params.extract_input<Field<int>>("Value_Int"); + default: + BLI_assert_unreachable(); + } + return {}; +} + +static void output_attribute_field(GeoNodeExecParams ¶ms, GField field) +{ + switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) { + case CD_PROP_FLOAT: { + params.set_output("Value_Float", Field<float>(field)); + break; + } + case CD_PROP_FLOAT3: { + params.set_output("Value_Vector", Field<float3>(field)); + break; + } + case CD_PROP_COLOR: { + params.set_output("Value_Color", Field<ColorGeometry4f>(field)); + break; + } + case CD_PROP_BOOL: { + params.set_output("Value_Bool", Field<bool>(field)); + break; + } + case CD_PROP_INT32: { + params.set_output("Value_Int", Field<int>(field)); + break; + } + default: + break; + } +} + +static void node_geo_exec(GeoNodeExecParams params) +{ + GeometrySet geometry = params.extract_input<GeometrySet>("Geometry"); + const NodeGeometrySampleIndex &storage = node_storage(params.node()); + const eCustomDataType data_type = eCustomDataType(storage.data_type); + const eAttrDomain domain = eAttrDomain(storage.domain); + + auto fn = std::make_shared<SampleIndexFunction>(std::move(geometry), + get_input_attribute_field(params, data_type), + domain, + bool(storage.clamp)); + auto op = FieldOperation::Create(std::move(fn), {params.extract_input<Field<int>>("Index")}); + output_attribute_field(params, GField(std::move(op))); +} + +} // namespace blender::nodes::node_geo_sample_index_cc + +void register_node_type_geo_sample_index() +{ + namespace file_ns = blender::nodes::node_geo_sample_index_cc; + + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_SAMPLE_INDEX, "Sample Index", NODE_CLASS_GEOMETRY); + node_type_init(&ntype, file_ns::node_init); + node_type_update(&ntype, file_ns::node_update); + ntype.declare = file_ns::node_declare; + node_type_storage( + &ntype, "NodeGeometrySampleIndex", node_free_standard_storage, node_copy_standard_storage); + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.draw_buttons = file_ns::node_layout; + ntype.gather_link_search_ops = file_ns::node_gather_link_searches; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc new file mode 100644 index 00000000000..95f7c7add3a --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc @@ -0,0 +1,344 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_task.hh" + +#include "DNA_pointcloud_types.h" + +#include "BKE_bvhutils.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +namespace blender::nodes { + +void get_closest_in_bvhtree(BVHTreeFromMesh &tree_data, + const VArray<float3> &positions, + const IndexMask mask, + const MutableSpan<int> r_indices, + const MutableSpan<float> r_distances_sq, + const MutableSpan<float3> r_positions) +{ + BLI_assert(positions.size() >= r_indices.size()); + BLI_assert(positions.size() >= r_distances_sq.size()); + BLI_assert(positions.size() >= r_positions.size()); + + for (const int i : mask) { + BVHTreeNearest nearest; + nearest.dist_sq = FLT_MAX; + const float3 position = positions[i]; + BLI_bvhtree_find_nearest( + tree_data.tree, position, &nearest, tree_data.nearest_callback, &tree_data); + if (!r_indices.is_empty()) { + r_indices[i] = nearest.index; + } + if (!r_distances_sq.is_empty()) { + r_distances_sq[i] = nearest.dist_sq; + } + if (!r_positions.is_empty()) { + r_positions[i] = nearest.co; + } + } +} + +} // namespace blender::nodes + +namespace blender::nodes::node_geo_sample_nearest_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>(N_("Geometry")) + .supported_type({GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD}); + b.add_input<decl::Vector>(N_("Sample Position")).implicit_field(implicit_field_inputs::position); + b.add_output<decl::Int>(N_("Index")).dependent_field({1}); +} + +static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "domain", 0, "", ICON_NONE); +} + +static void node_init(bNodeTree *UNUSED(tree), bNode *node) +{ + node->custom1 = CD_PROP_FLOAT; + node->custom2 = ATTR_DOMAIN_POINT; +} + +static void get_closest_pointcloud_points(const PointCloud &pointcloud, + const VArray<float3> &positions, + const IndexMask mask, + const MutableSpan<int> r_indices, + const MutableSpan<float> r_distances_sq) +{ + BLI_assert(positions.size() >= r_indices.size()); + BLI_assert(pointcloud.totpoint > 0); + + BVHTreeFromPointCloud tree_data; + BKE_bvhtree_from_pointcloud_get(&tree_data, &pointcloud, 2); + + for (const int i : mask) { + BVHTreeNearest nearest; + nearest.dist_sq = FLT_MAX; + const float3 position = positions[i]; + BLI_bvhtree_find_nearest( + tree_data.tree, position, &nearest, tree_data.nearest_callback, &tree_data); + r_indices[i] = nearest.index; + if (!r_distances_sq.is_empty()) { + r_distances_sq[i] = nearest.dist_sq; + } + } + + free_bvhtree_from_pointcloud(&tree_data); +} + +static void get_closest_mesh_points(const Mesh &mesh, + const VArray<float3> &positions, + const IndexMask mask, + const MutableSpan<int> r_point_indices, + const MutableSpan<float> r_distances_sq, + const MutableSpan<float3> r_positions) +{ + BLI_assert(mesh.totvert > 0); + BVHTreeFromMesh tree_data; + BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_VERTS, 2); + get_closest_in_bvhtree(tree_data, positions, mask, r_point_indices, r_distances_sq, r_positions); + free_bvhtree_from_mesh(&tree_data); +} + +static void get_closest_mesh_edges(const Mesh &mesh, + const VArray<float3> &positions, + const IndexMask mask, + const MutableSpan<int> r_edge_indices, + const MutableSpan<float> r_distances_sq, + const MutableSpan<float3> r_positions) +{ + BLI_assert(mesh.totedge > 0); + BVHTreeFromMesh tree_data; + BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_EDGES, 2); + get_closest_in_bvhtree(tree_data, positions, mask, r_edge_indices, r_distances_sq, r_positions); + free_bvhtree_from_mesh(&tree_data); +} + +static void get_closest_mesh_looptris(const Mesh &mesh, + const VArray<float3> &positions, + const IndexMask mask, + const MutableSpan<int> r_looptri_indices, + const MutableSpan<float> r_distances_sq, + const MutableSpan<float3> r_positions) +{ + BLI_assert(mesh.totpoly > 0); + BVHTreeFromMesh tree_data; + BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_LOOPTRI, 2); + get_closest_in_bvhtree( + tree_data, positions, mask, r_looptri_indices, r_distances_sq, r_positions); + free_bvhtree_from_mesh(&tree_data); +} + +static void get_closest_mesh_polys(const Mesh &mesh, + const VArray<float3> &positions, + const IndexMask mask, + const MutableSpan<int> r_poly_indices, + const MutableSpan<float> r_distances_sq, + const MutableSpan<float3> r_positions) +{ + BLI_assert(mesh.totpoly > 0); + + Array<int> looptri_indices(positions.size()); + get_closest_mesh_looptris(mesh, positions, mask, looptri_indices, r_distances_sq, r_positions); + + const Span<MLoopTri> looptris = mesh.looptris(); + + for (const int i : mask) { + const MLoopTri &looptri = looptris[looptri_indices[i]]; + r_poly_indices[i] = looptri.poly; + } +} + +/* The closest corner is defined to be the closest corner on the closest face. */ +static void get_closest_mesh_corners(const Mesh &mesh, + const VArray<float3> &positions, + const IndexMask mask, + const MutableSpan<int> r_corner_indices, + const MutableSpan<float> r_distances_sq, + const MutableSpan<float3> r_positions) +{ + const Span<MVert> verts = mesh.verts(); + const Span<MPoly> polys = mesh.polys(); + const Span<MLoop> loops = mesh.loops(); + + BLI_assert(mesh.totloop > 0); + Array<int> poly_indices(positions.size()); + get_closest_mesh_polys(mesh, positions, mask, poly_indices, {}, {}); + + for (const int i : mask) { + const float3 position = positions[i]; + const int poly_index = poly_indices[i]; + const MPoly &poly = polys[poly_index]; + + /* Find the closest vertex in the polygon. */ + float min_distance_sq = FLT_MAX; + const MVert *closest_mvert; + int closest_loop_index = 0; + for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + const MLoop &loop = loops[loop_index]; + const int vertex_index = loop.v; + const MVert &mvert = verts[vertex_index]; + const float distance_sq = math::distance_squared(position, float3(mvert.co)); + if (distance_sq < min_distance_sq) { + min_distance_sq = distance_sq; + closest_loop_index = loop_index; + closest_mvert = &mvert; + } + } + if (!r_corner_indices.is_empty()) { + r_corner_indices[i] = closest_loop_index; + } + if (!r_positions.is_empty()) { + r_positions[i] = closest_mvert->co; + } + if (!r_distances_sq.is_empty()) { + r_distances_sq[i] = min_distance_sq; + } + } +} + +static bool component_is_available(const GeometrySet &geometry, + const GeometryComponentType type, + const eAttrDomain domain) +{ + if (!geometry.has(type)) { + return false; + } + const GeometryComponent &component = *geometry.get_component_for_read(type); + if (component.is_empty()) { + return false; + } + return component.attribute_domain_size(domain) != 0; +} + +static const GeometryComponent *find_source_component(const GeometrySet &geometry, + const eAttrDomain domain) +{ + /* Choose the other component based on a consistent order, rather than some more complicated + * heuristic. This is the same order visible in the spreadsheet and used in the ray-cast node. */ + static const Array<GeometryComponentType> supported_types = {GEO_COMPONENT_TYPE_MESH, + GEO_COMPONENT_TYPE_POINT_CLOUD, + GEO_COMPONENT_TYPE_CURVE, + GEO_COMPONENT_TYPE_INSTANCES}; + for (const GeometryComponentType src_type : supported_types) { + if (component_is_available(geometry, src_type, domain)) { + return geometry.get_component_for_read(src_type); + } + } + + return nullptr; +} + +class SampleNearestFunction : public fn::MultiFunction { + GeometrySet source_; + eAttrDomain domain_; + + const GeometryComponent *src_component_; + + fn::MFSignature signature_; + + public: + SampleNearestFunction(GeometrySet geometry, eAttrDomain domain) + : source_(std::move(geometry)), domain_(domain) + { + source_.ensure_owns_direct_data(); + signature_ = this->create_signature(); + this->set_signature(&signature_); + + this->src_component_ = find_source_component(source_, domain_); + } + + fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Sample Nearest"}; + signature.single_input<float3>("Position"); + signature.single_output<int>("Index"); + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + const VArray<float3> &positions = params.readonly_single_input<float3>(0, "Position"); + MutableSpan<int> indices = params.uninitialized_single_output<int>(1, "Index"); + if (!src_component_) { + indices.fill_indices(mask, 0); + return; + } + + switch (src_component_->type()) { + case GEO_COMPONENT_TYPE_MESH: { + const MeshComponent &component = *static_cast<const MeshComponent *>(src_component_); + const Mesh &mesh = *component.get_for_read(); + Array<float> distances(mask.min_array_size()); + switch (domain_) { + case ATTR_DOMAIN_POINT: + get_closest_mesh_points(mesh, positions, mask, indices, distances, {}); + break; + case ATTR_DOMAIN_EDGE: + get_closest_mesh_edges(mesh, positions, mask, indices, distances, {}); + break; + case ATTR_DOMAIN_FACE: + get_closest_mesh_polys(mesh, positions, mask, indices, distances, {}); + break; + case ATTR_DOMAIN_CORNER: + get_closest_mesh_corners(mesh, positions, mask, indices, distances, {}); + break; + default: + break; + } + break; + } + case GEO_COMPONENT_TYPE_POINT_CLOUD: { + const PointCloudComponent &component = *static_cast<const PointCloudComponent *>( + src_component_); + const PointCloud &points = *component.get_for_read(); + Array<float> distances(mask.min_array_size()); + get_closest_pointcloud_points(points, positions, mask, indices, distances); + break; + } + default: + break; + } + } +}; + +static void node_geo_exec(GeoNodeExecParams params) +{ + GeometrySet geometry = params.extract_input<GeometrySet>("Geometry"); + const eAttrDomain domain = eAttrDomain(params.node().custom2); + if (geometry.has_curves() && !geometry.has_mesh() && !geometry.has_pointcloud()) { + params.error_message_add(NodeWarningType::Error, + TIP_("The source geometry must contain a mesh or a point cloud")); + params.set_default_remaining_outputs(); + return; + } + + Field<float3> positions = params.extract_input<Field<float3>>("Sample Position"); + auto fn = std::make_shared<SampleNearestFunction>(std::move(geometry), domain); + auto op = FieldOperation::Create(std::move(fn), {std::move(positions)}); + params.set_output<Field<int>>("Index", Field<int>(std::move(op))); +} + +} // namespace blender::nodes::node_geo_sample_nearest_cc + +void register_node_type_geo_sample_nearest() +{ + namespace file_ns = blender::nodes::node_geo_sample_nearest_cc; + + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_SAMPLE_NEAREST, "Sample Nearest", NODE_CLASS_GEOMETRY); + node_type_init(&ntype, file_ns::node_init); + ntype.declare = file_ns::node_declare; + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.draw_buttons = file_ns::node_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc new file mode 100644 index 00000000000..f3c182cd97a --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc @@ -0,0 +1,280 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_generic_array.hh" +#include "BLI_kdopbvh.h" +#include "BLI_task.hh" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_pointcloud_types.h" + +#include "BKE_attribute_math.hh" +#include "BKE_bvhutils.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_mesh_sample.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "NOD_socket_search_link.hh" + +#include "node_geometry_util.hh" + +namespace blender::nodes::node_geo_sample_nearest_surface_cc { + +using namespace blender::bke::mesh_surface_sample; + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH); + + b.add_input<decl::Float>(N_("Value"), "Value_Float").hide_value().supports_field(); + b.add_input<decl::Int>(N_("Value"), "Value_Int").hide_value().supports_field(); + b.add_input<decl::Vector>(N_("Value"), "Value_Vector").hide_value().supports_field(); + b.add_input<decl::Color>(N_("Value"), "Value_Color").hide_value().supports_field(); + b.add_input<decl::Bool>(N_("Value"), "Value_Bool").hide_value().supports_field(); + + b.add_input<decl::Vector>(N_("Sample Position")).implicit_field(implicit_field_inputs::position); + + b.add_output<decl::Float>(N_("Value"), "Value_Float").dependent_field({6}); + b.add_output<decl::Int>(N_("Value"), "Value_Int").dependent_field({6}); + b.add_output<decl::Vector>(N_("Value"), "Value_Vector").dependent_field({6}); + b.add_output<decl::Color>(N_("Value"), "Value_Color").dependent_field({6}); + b.add_output<decl::Bool>(N_("Value"), "Value_Bool").dependent_field({6}); +} + +static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); +} + +static void node_init(bNodeTree *UNUSED(tree), bNode *node) +{ + node->custom1 = CD_PROP_FLOAT; +} + +static void node_update(bNodeTree *ntree, bNode *node) +{ + const eCustomDataType data_type = eCustomDataType(node->custom1); + + bNodeSocket *in_socket_mesh = static_cast<bNodeSocket *>(node->inputs.first); + bNodeSocket *in_socket_float = in_socket_mesh->next; + bNodeSocket *in_socket_int32 = in_socket_float->next; + bNodeSocket *in_socket_vector = in_socket_int32->next; + bNodeSocket *in_socket_color4f = in_socket_vector->next; + bNodeSocket *in_socket_bool = in_socket_color4f->next; + + nodeSetSocketAvailability(ntree, in_socket_vector, data_type == CD_PROP_FLOAT3); + nodeSetSocketAvailability(ntree, in_socket_float, data_type == CD_PROP_FLOAT); + nodeSetSocketAvailability(ntree, in_socket_color4f, data_type == CD_PROP_COLOR); + nodeSetSocketAvailability(ntree, in_socket_bool, data_type == CD_PROP_BOOL); + nodeSetSocketAvailability(ntree, in_socket_int32, data_type == CD_PROP_INT32); + + bNodeSocket *out_socket_float = static_cast<bNodeSocket *>(node->outputs.first); + bNodeSocket *out_socket_int32 = out_socket_float->next; + bNodeSocket *out_socket_vector = out_socket_int32->next; + bNodeSocket *out_socket_color4f = out_socket_vector->next; + bNodeSocket *out_socket_bool = out_socket_color4f->next; + + nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3); + nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT); + nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR); + nodeSetSocketAvailability(ntree, out_socket_bool, data_type == CD_PROP_BOOL); + nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32); +} + +static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) +{ + const NodeDeclaration &declaration = *params.node_type().fixed_declaration; + search_link_ops_for_declarations(params, declaration.inputs().take_back(2)); + search_link_ops_for_declarations(params, declaration.inputs().take_front(1)); + + const std::optional<eCustomDataType> type = node_data_type_to_custom_data_type( + (eNodeSocketDatatype)params.other_socket().type); + if (type && *type != CD_PROP_STRING) { + /* The input and output sockets have the same name. */ + params.add_item(IFACE_("Value"), [type](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("GeometryNodeSampleNearestSurface"); + node.custom1 = *type; + params.update_and_connect_available_socket(node, "Value"); + }); + } +} + +static void get_closest_mesh_looptris(const Mesh &mesh, + const VArray<float3> &positions, + const IndexMask mask, + const MutableSpan<int> r_looptri_indices, + const MutableSpan<float> r_distances_sq, + const MutableSpan<float3> r_positions) +{ + BLI_assert(mesh.totpoly > 0); + BVHTreeFromMesh tree_data; + BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_LOOPTRI, 2); + get_closest_in_bvhtree( + tree_data, positions, mask, r_looptri_indices, r_distances_sq, r_positions); + free_bvhtree_from_mesh(&tree_data); +} + +/** + * \note Multi-threading for this function is provided by the field evaluator. Since the #call + * function could be called many times, calculate the data from the source geometry once and store + * it for later. + */ +class SampleNearestSurfaceFunction : public fn::MultiFunction { + GeometrySet source_; + GField src_field_; + + /** + * This function is meant to sample the surface of a mesh rather than take the value from + * individual elements, so use the most complex domain, ensuring no information is lost. In the + * future, it should be possible to use the most complex domain required by the field inputs, to + * simplify sampling and avoid domain conversions. + */ + eAttrDomain domain_ = ATTR_DOMAIN_CORNER; + + fn::MFSignature signature_; + + std::optional<bke::MeshFieldContext> source_context_; + std::unique_ptr<FieldEvaluator> source_evaluator_; + const GVArray *source_data_; + + public: + SampleNearestSurfaceFunction(GeometrySet geometry, GField src_field) + : source_(std::move(geometry)), src_field_(std::move(src_field)) + { + source_.ensure_owns_direct_data(); + signature_ = this->create_signature(); + this->set_signature(&signature_); + this->evaluate_source_field(); + } + + fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Sample Nearest Surface"}; + signature.single_input<float3>("Position"); + signature.single_output("Value", src_field_.cpp_type()); + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + const VArray<float3> &positions = params.readonly_single_input<float3>(0, "Position"); + GMutableSpan dst = params.uninitialized_single_output_if_required(1, "Value"); + + const MeshComponent &mesh_component = *source_.get_component_for_read<MeshComponent>(); + BLI_assert(mesh_component.has_mesh()); + const Mesh &mesh = *mesh_component.get_for_read(); + BLI_assert(mesh.totpoly > 0); + + /* Find closest points on the mesh surface. */ + Array<int> looptri_indices(mask.min_array_size()); + Array<float3> sampled_positions(mask.min_array_size()); + get_closest_mesh_looptris(mesh, positions, mask, looptri_indices, {}, sampled_positions); + + MeshAttributeInterpolator interp(&mesh, mask, sampled_positions, looptri_indices); + interp.sample_data(*source_data_, domain_, eAttributeMapMode::INTERPOLATED, dst); + } + + private: + void evaluate_source_field() + { + const Mesh &mesh = *source_.get_mesh_for_read(); + source_context_.emplace(bke::MeshFieldContext{mesh, domain_}); + const int domain_size = mesh.attributes().domain_size(domain_); + source_evaluator_ = std::make_unique<FieldEvaluator>(*source_context_, domain_size); + source_evaluator_->add(src_field_); + source_evaluator_->evaluate(); + source_data_ = &source_evaluator_->get_evaluated(0); + } +}; + +static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustomDataType data_type) +{ + switch (data_type) { + case CD_PROP_FLOAT: + return params.extract_input<Field<float>>("Value_Float"); + case CD_PROP_FLOAT3: + return params.extract_input<Field<float3>>("Value_Vector"); + case CD_PROP_COLOR: + return params.extract_input<Field<ColorGeometry4f>>("Value_Color"); + case CD_PROP_BOOL: + return params.extract_input<Field<bool>>("Value_Bool"); + case CD_PROP_INT32: + return params.extract_input<Field<int>>("Value_Int"); + default: + BLI_assert_unreachable(); + } + return {}; +} + +static void output_attribute_field(GeoNodeExecParams ¶ms, GField field) +{ + switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) { + case CD_PROP_FLOAT: { + params.set_output("Value_Float", Field<float>(field)); + break; + } + case CD_PROP_FLOAT3: { + params.set_output("Value_Vector", Field<float3>(field)); + break; + } + case CD_PROP_COLOR: { + params.set_output("Value_Color", Field<ColorGeometry4f>(field)); + break; + } + case CD_PROP_BOOL: { + params.set_output("Value_Bool", Field<bool>(field)); + break; + } + case CD_PROP_INT32: { + params.set_output("Value_Int", Field<int>(field)); + break; + } + default: + break; + } +} + +static void node_geo_exec(GeoNodeExecParams params) +{ + GeometrySet geometry = params.extract_input<GeometrySet>("Mesh"); + const eCustomDataType data_type = eCustomDataType(params.node().custom1); + const Mesh *mesh = geometry.get_mesh_for_read(); + if (mesh == nullptr) { + params.set_default_remaining_outputs(); + return; + } + if (mesh->totpoly == 0 && mesh->totvert != 0) { + params.error_message_add(NodeWarningType::Error, TIP_("The source mesh must have faces")); + params.set_default_remaining_outputs(); + return; + } + + Field<float3> positions = params.extract_input<Field<float3>>("Sample Position"); + GField field = get_input_attribute_field(params, data_type); + auto fn = std::make_shared<SampleNearestSurfaceFunction>(std::move(geometry), std::move(field)); + auto op = FieldOperation::Create(std::move(fn), {std::move(positions)}); + output_attribute_field(params, GField(std::move(op))); +} + +} // namespace blender::nodes::node_geo_sample_nearest_surface_cc + +void register_node_type_geo_sample_nearest_surface() +{ + namespace file_ns = blender::nodes::node_geo_sample_nearest_surface_cc; + + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_SAMPLE_NEAREST_SURFACE, "Sample Nearest Surface", NODE_CLASS_GEOMETRY); + node_type_init(&ntype, file_ns::node_init); + node_type_update(&ntype, file_ns::node_update); + ntype.declare = file_ns::node_declare; + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.draw_buttons = file_ns::node_layout; + ntype.gather_link_search_ops = file_ns::node_gather_link_searches; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc index 20a951e65f3..3416e63f682 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc @@ -25,7 +25,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input<decl::Float>(N_("Scale"), "Scale").default_value(1.0f).min(0.0f).supports_field(); b.add_input<decl::Vector>(N_("Center")) .subtype(PROP_TRANSLATION) - .implicit_field() + .implicit_field(implicit_field_inputs::position) .description(N_("Origin of the scaling for each element. If multiple elements are " "connected, their center is averaged")); b.add_input<decl::Vector>(N_("Axis")) @@ -56,8 +56,7 @@ static void node_update(bNodeTree *ntree, bNode *node) bNodeSocket *center_socket = scale_float_socket->next; bNodeSocket *axis_socket = center_socket->next; - const GeometryNodeScaleElementsMode mode = static_cast<GeometryNodeScaleElementsMode>( - node->custom2); + const GeometryNodeScaleElementsMode mode = GeometryNodeScaleElementsMode(node->custom2); const bool use_single_axis = mode == GEO_NODE_SCALE_ELEMENTS_SINGLE_AXIS; nodeSetSocketAvailability(ntree, axis_socket, use_single_axis); @@ -399,9 +398,8 @@ static void scale_edges_on_axis(Mesh &mesh, const AxisScaleFields &fields) static void node_geo_exec(GeoNodeExecParams params) { const bNode &node = params.node(); - const eAttrDomain domain = static_cast<eAttrDomain>(node.custom1); - const GeometryNodeScaleElementsMode scale_mode = static_cast<GeometryNodeScaleElementsMode>( - node.custom2); + const eAttrDomain domain = eAttrDomain(node.custom1); + const GeometryNodeScaleElementsMode scale_mode = GeometryNodeScaleElementsMode(node.custom2); GeometrySet geometry = params.extract_input<GeometrySet>("Geometry"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc index d785694f253..f40ad62a5e4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc @@ -43,7 +43,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); const NodeGeometrySeparateGeometry &storage = node_storage(params.node()); - const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); + const eAttrDomain domain = eAttrDomain(storage.domain); auto separate_geometry_maybe_recursively = [&](GeometrySet &geometry_set, const Field<bool> &selection) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc index e529ddddabe..5610edf7e4c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc @@ -17,7 +17,11 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE); b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field(); - b.add_input<decl::Vector>(N_("Position")).implicit_field(); + b.add_input<decl::Vector>(N_("Position")).implicit_field([](const bNode &node, void *r_value) { + const StringRef side = node_storage(node).mode == GEO_NODE_CURVE_HANDLE_LEFT ? "handle_left" : + "handle_right"; + new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>(side)); + }); b.add_input<decl::Vector>(N_("Offset")).default_value(float3(0.0f, 0.0f, 0.0f)).supports_field(); b.add_output<decl::Geometry>(N_("Curve")); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc index 5864401223b..e308371b1c2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc @@ -8,7 +8,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>(N_("Geometry")); b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field(); - b.add_input<decl::Int>(N_("ID")).implicit_field(); + b.add_input<decl::Int>(N_("ID")).implicit_field(implicit_field_inputs::index); b.add_output<decl::Geometry>(N_("Geometry")); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc index 61bf48449d8..50739b83a61 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc @@ -18,7 +18,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>(N_("Geometry")); b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field(); - b.add_input<decl::Vector>(N_("Position")).implicit_field(); + b.add_input<decl::Vector>(N_("Position")).implicit_field(implicit_field_inputs::position); b.add_input<decl::Vector>(N_("Offset")).supports_field().subtype(PROP_TRANSLATION); b.add_output<decl::Geometry>(N_("Geometry")); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc index 37e55602fb0..d0b770aadad 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc @@ -49,9 +49,9 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node) static void node_update(bNodeTree *ntree, bNode *node) { const NodeGeometryStoreNamedAttribute &storage = node_storage(*node); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); + const eCustomDataType data_type = eCustomDataType(storage.data_type); - bNodeSocket *socket_geometry = (bNodeSocket *)node->inputs.first; + bNodeSocket *socket_geometry = static_cast<bNodeSocket *>(node->inputs.first); bNodeSocket *socket_name = socket_geometry->next; bNodeSocket *socket_vector = socket_name->next; bNodeSocket *socket_float = socket_vector->next; @@ -75,7 +75,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) if (params.in_out() == SOCK_IN) { const std::optional<eCustomDataType> type = node_data_type_to_custom_data_type( - static_cast<eNodeSocketDatatype>(params.other_socket().type)); + eNodeSocketDatatype(params.other_socket().type)); if (type && *type != CD_PROP_STRING) { /* The input and output sockets have the same name. */ params.add_item(IFACE_("Value"), [type](LinkSearchOpParams ¶ms) { @@ -155,8 +155,8 @@ static void node_geo_exec(GeoNodeExecParams params) params.used_named_attribute(name, NamedAttributeUsage::Write); const NodeGeometryStoreNamedAttribute &storage = node_storage(params.node()); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); - const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); + const eCustomDataType data_type = eCustomDataType(storage.data_type); + const eAttrDomain domain = eAttrDomain(storage.domain); GField field; switch (data_type) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc index afd7db6604d..e8913f80916 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc @@ -85,7 +85,7 @@ static void node_init(bNodeTree *UNUSED(ntree), bNode *node) data->align_y = GEO_NODE_STRING_TO_CURVES_ALIGN_Y_TOP_BASELINE; data->pivot_mode = GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_LEFT; node->storage = data; - node->id = (ID *)BKE_vfont_builtin_get(); + node->id = reinterpret_cast<ID *>(BKE_vfont_builtin_get()); } static void node_update(bNodeTree *ntree, bNode *node) @@ -93,11 +93,11 @@ static void node_update(bNodeTree *ntree, bNode *node) const NodeGeometryStringToCurves &storage = node_storage(*node); const GeometryNodeStringToCurvesOverflowMode overflow = (GeometryNodeStringToCurvesOverflowMode) storage.overflow; - bNodeSocket *socket_remainder = ((bNodeSocket *)node->outputs.first)->next; + bNodeSocket *socket_remainder = static_cast<bNodeSocket *>(node->outputs.first)->next; nodeSetSocketAvailability( ntree, socket_remainder, overflow == GEO_NODE_STRING_TO_CURVES_MODE_TRUNCATE); - bNodeSocket *height_socket = (bNodeSocket *)node->inputs.last; + bNodeSocket *height_socket = static_cast<bNodeSocket *>(node->inputs.last); nodeSetSocketAvailability( ntree, height_socket, overflow != GEO_NODE_STRING_TO_CURVES_MODE_OVERFLOW); } @@ -203,7 +203,7 @@ static std::optional<TextLayout> get_text_layout(GeoNodeExecParams ¶ms) cu.linedist = line_spacing; cu.vfont = vfont; cu.overflow = overflow; - cu.tb = (TextBox *)MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), __func__); + cu.tb = static_cast<TextBox *>(MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), __func__)); cu.tb->w = textbox_w; cu.tb->h = textbox_h; cu.totbox = 1; @@ -213,8 +213,8 @@ static std::optional<TextLayout> get_text_layout(GeoNodeExecParams ¶ms) cu.len = len_bytes; cu.pos = len_chars; /* The reason for the additional character here is unknown, but reflects other code elsewhere. */ - cu.str = (char *)MEM_mallocN(len_bytes + sizeof(char32_t), __func__); - cu.strinfo = (CharInfo *)MEM_callocN((len_chars + 1) * sizeof(CharInfo), __func__); + cu.str = static_cast<char *>(MEM_mallocN(len_bytes + sizeof(char32_t), __func__)); + cu.strinfo = static_cast<CharInfo *>(MEM_callocN((len_chars + 1) * sizeof(CharInfo), __func__)); BLI_strncpy(cu.str, layout.text.c_str(), len_bytes + 1); struct CharTrans *chartransdata = nullptr; @@ -226,7 +226,7 @@ static std::optional<TextLayout> get_text_layout(GeoNodeExecParams ¶ms) nullptr, &cu, FO_DUPLI, nullptr, &r_text, &text_len, &text_free, &chartransdata); if (text_free) { - MEM_freeN((void *)r_text); + MEM_freeN(const_cast<char32_t *>(r_text)); } Span<CharInfo> info{cu.strinfo, text_len}; @@ -272,7 +272,7 @@ static Map<int, int> create_curve_instances(GeoNodeExecParams ¶ms, TextLayout &layout, InstancesComponent &instances) { - VFont *vfont = (VFont *)params.node().id; + VFont *vfont = reinterpret_cast<VFont *>(params.node().id); Map<int, int> handles; bool pivot_required = params.output_is_required("Pivot Point"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_switch.cc b/source/blender/nodes/geometry/nodes/node_geo_switch.cc index ddc87e3dac4..6dc30af4fb6 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_switch.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_switch.cc @@ -89,8 +89,8 @@ static void node_update(bNodeTree *ntree, bNode *node) { const NodeSwitch &storage = node_storage(*node); int index = 0; - bNodeSocket *field_switch = (bNodeSocket *)node->inputs.first; - bNodeSocket *non_field_switch = (bNodeSocket *)field_switch->next; + bNodeSocket *field_switch = static_cast<bNodeSocket *>(node->inputs.first); + bNodeSocket *non_field_switch = static_cast<bNodeSocket *>(field_switch->next); const bool fields_type = ELEM( storage.input_type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA, SOCK_STRING); @@ -222,7 +222,7 @@ template<typename T> void switch_no_fields(GeoNodeExecParams ¶ms, const Stri static void node_geo_exec(GeoNodeExecParams params) { const NodeSwitch &storage = node_storage(params.node()); - const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.input_type); + const eNodeSocketDatatype data_type = eNodeSocketDatatype(storage.input_type); switch (data_type) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc deleted file mode 100644 index 81f1155a96c..00000000000 --- a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc +++ /dev/null @@ -1,829 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "BLI_generic_array.hh" -#include "BLI_kdopbvh.h" -#include "BLI_task.hh" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_pointcloud_types.h" - -#include "BKE_attribute_math.hh" -#include "BKE_bvhutils.h" -#include "BKE_mesh.h" -#include "BKE_mesh_runtime.h" -#include "BKE_mesh_sample.hh" - -#include "UI_interface.h" -#include "UI_resources.h" - -#include "NOD_socket_search_link.hh" - -#include "node_geometry_util.hh" - -namespace blender::nodes::node_geo_transfer_attribute_cc { - -using namespace blender::bke::mesh_surface_sample; - -NODE_STORAGE_FUNCS(NodeGeometryTransferAttribute) - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input<decl::Geometry>(N_("Source")) - .supported_type({GEO_COMPONENT_TYPE_MESH, - GEO_COMPONENT_TYPE_POINT_CLOUD, - GEO_COMPONENT_TYPE_CURVE, - GEO_COMPONENT_TYPE_INSTANCES}); - - b.add_input<decl::Vector>(N_("Attribute")).hide_value().supports_field(); - b.add_input<decl::Float>(N_("Attribute"), "Attribute_001").hide_value().supports_field(); - b.add_input<decl::Color>(N_("Attribute"), "Attribute_002").hide_value().supports_field(); - b.add_input<decl::Bool>(N_("Attribute"), "Attribute_003").hide_value().supports_field(); - b.add_input<decl::Int>(N_("Attribute"), "Attribute_004").hide_value().supports_field(); - - b.add_input<decl::Vector>(N_("Source Position")) - .implicit_field() - .make_available([](bNode &node) { - node_storage(node).mode = GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED; - }); - b.add_input<decl::Int>(N_("Index")).implicit_field().make_available([](bNode &node) { - node_storage(node).mode = GEO_NODE_ATTRIBUTE_TRANSFER_INDEX; - }); - - b.add_output<decl::Vector>(N_("Attribute")).dependent_field({6, 7}); - b.add_output<decl::Float>(N_("Attribute"), "Attribute_001").dependent_field({6, 7}); - b.add_output<decl::Color>(N_("Attribute"), "Attribute_002").dependent_field({6, 7}); - b.add_output<decl::Bool>(N_("Attribute"), "Attribute_003").dependent_field({6, 7}); - b.add_output<decl::Int>(N_("Attribute"), "Attribute_004").dependent_field({6, 7}); -} - -static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - const bNode &node = *static_cast<const bNode *>(ptr->data); - const NodeGeometryTransferAttribute &storage = node_storage(node); - const GeometryNodeAttributeTransferMode mapping = (GeometryNodeAttributeTransferMode) - storage.mode; - - uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE); - if (mapping != GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED) { - uiItemR(layout, ptr, "domain", 0, "", ICON_NONE); - } -} - -static void node_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeGeometryTransferAttribute *data = MEM_cnew<NodeGeometryTransferAttribute>(__func__); - data->data_type = CD_PROP_FLOAT; - data->mode = GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED; - node->storage = data; -} - -static void node_update(bNodeTree *ntree, bNode *node) -{ - const NodeGeometryTransferAttribute &storage = node_storage(*node); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); - const GeometryNodeAttributeTransferMode mapping = (GeometryNodeAttributeTransferMode) - storage.mode; - - bNodeSocket *socket_geometry = (bNodeSocket *)node->inputs.first; - bNodeSocket *socket_vector = socket_geometry->next; - bNodeSocket *socket_float = socket_vector->next; - bNodeSocket *socket_color4f = socket_float->next; - bNodeSocket *socket_boolean = socket_color4f->next; - bNodeSocket *socket_int32 = socket_boolean->next; - - bNodeSocket *socket_positions = socket_int32->next; - bNodeSocket *socket_indices = socket_positions->next; - - nodeSetSocketAvailability(ntree, socket_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, socket_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, socket_color4f, data_type == CD_PROP_COLOR); - nodeSetSocketAvailability(ntree, socket_boolean, data_type == CD_PROP_BOOL); - nodeSetSocketAvailability(ntree, socket_int32, data_type == CD_PROP_INT32); - - nodeSetSocketAvailability(ntree, socket_positions, mapping != GEO_NODE_ATTRIBUTE_TRANSFER_INDEX); - nodeSetSocketAvailability(ntree, socket_indices, mapping == GEO_NODE_ATTRIBUTE_TRANSFER_INDEX); - - bNodeSocket *out_socket_vector = (bNodeSocket *)node->outputs.first; - bNodeSocket *out_socket_float = out_socket_vector->next; - bNodeSocket *out_socket_color4f = out_socket_float->next; - bNodeSocket *out_socket_boolean = out_socket_color4f->next; - bNodeSocket *out_socket_int32 = out_socket_boolean->next; - - nodeSetSocketAvailability(ntree, out_socket_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(ntree, out_socket_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(ntree, out_socket_color4f, data_type == CD_PROP_COLOR); - nodeSetSocketAvailability(ntree, out_socket_boolean, data_type == CD_PROP_BOOL); - nodeSetSocketAvailability(ntree, out_socket_int32, data_type == CD_PROP_INT32); -} - -static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) -{ - const NodeDeclaration &declaration = *params.node_type().fixed_declaration; - search_link_ops_for_declarations(params, declaration.inputs().take_back(2)); - search_link_ops_for_declarations(params, declaration.inputs().take_front(1)); - - const std::optional<eCustomDataType> type = node_data_type_to_custom_data_type( - (eNodeSocketDatatype)params.other_socket().type); - if (type && *type != CD_PROP_STRING) { - /* The input and output sockets have the same name. */ - params.add_item(IFACE_("Attribute"), [type](LinkSearchOpParams ¶ms) { - bNode &node = params.add_node("GeometryNodeAttributeTransfer"); - node_storage(node).data_type = *type; - params.update_and_connect_available_socket(node, "Attribute"); - }); - } -} - -static void get_closest_in_bvhtree(BVHTreeFromMesh &tree_data, - const VArray<float3> &positions, - const IndexMask mask, - const MutableSpan<int> r_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(positions.size() >= r_indices.size()); - BLI_assert(positions.size() >= r_distances_sq.size()); - BLI_assert(positions.size() >= r_positions.size()); - - for (const int i : mask) { - BVHTreeNearest nearest; - nearest.dist_sq = FLT_MAX; - const float3 position = positions[i]; - BLI_bvhtree_find_nearest( - tree_data.tree, position, &nearest, tree_data.nearest_callback, &tree_data); - if (!r_indices.is_empty()) { - r_indices[i] = nearest.index; - } - if (!r_distances_sq.is_empty()) { - r_distances_sq[i] = nearest.dist_sq; - } - if (!r_positions.is_empty()) { - r_positions[i] = nearest.co; - } - } -} - -static void get_closest_pointcloud_points(const PointCloud &pointcloud, - const VArray<float3> &positions, - const IndexMask mask, - const MutableSpan<int> r_indices, - const MutableSpan<float> r_distances_sq) -{ - BLI_assert(positions.size() >= r_indices.size()); - BLI_assert(pointcloud.totpoint > 0); - - BVHTreeFromPointCloud tree_data; - BKE_bvhtree_from_pointcloud_get(&tree_data, &pointcloud, 2); - - for (const int i : mask) { - BVHTreeNearest nearest; - nearest.dist_sq = FLT_MAX; - const float3 position = positions[i]; - BLI_bvhtree_find_nearest( - tree_data.tree, position, &nearest, tree_data.nearest_callback, &tree_data); - r_indices[i] = nearest.index; - if (!r_distances_sq.is_empty()) { - r_distances_sq[i] = nearest.dist_sq; - } - } - - free_bvhtree_from_pointcloud(&tree_data); -} - -static void get_closest_mesh_points(const Mesh &mesh, - const VArray<float3> &positions, - const IndexMask mask, - const MutableSpan<int> r_point_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(mesh.totvert > 0); - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_VERTS, 2); - get_closest_in_bvhtree(tree_data, positions, mask, r_point_indices, r_distances_sq, r_positions); - free_bvhtree_from_mesh(&tree_data); -} - -static void get_closest_mesh_edges(const Mesh &mesh, - const VArray<float3> &positions, - const IndexMask mask, - const MutableSpan<int> r_edge_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(mesh.totedge > 0); - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_EDGES, 2); - get_closest_in_bvhtree(tree_data, positions, mask, r_edge_indices, r_distances_sq, r_positions); - free_bvhtree_from_mesh(&tree_data); -} - -static void get_closest_mesh_looptris(const Mesh &mesh, - const VArray<float3> &positions, - const IndexMask mask, - const MutableSpan<int> r_looptri_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(mesh.totpoly > 0); - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_LOOPTRI, 2); - get_closest_in_bvhtree( - tree_data, positions, mask, r_looptri_indices, r_distances_sq, r_positions); - free_bvhtree_from_mesh(&tree_data); -} - -static void get_closest_mesh_polys(const Mesh &mesh, - const VArray<float3> &positions, - const IndexMask mask, - const MutableSpan<int> r_poly_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - BLI_assert(mesh.totpoly > 0); - - Array<int> looptri_indices(positions.size()); - get_closest_mesh_looptris(mesh, positions, mask, looptri_indices, r_distances_sq, r_positions); - - const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), - BKE_mesh_runtime_looptri_len(&mesh)}; - - for (const int i : mask) { - const MLoopTri &looptri = looptris[looptri_indices[i]]; - r_poly_indices[i] = looptri.poly; - } -} - -/* The closest corner is defined to be the closest corner on the closest face. */ -static void get_closest_mesh_corners(const Mesh &mesh, - const VArray<float3> &positions, - const IndexMask mask, - const MutableSpan<int> r_corner_indices, - const MutableSpan<float> r_distances_sq, - const MutableSpan<float3> r_positions) -{ - const Span<float3> mesh_positions = mesh.positions(); - const Span<MPoly> polys = mesh.polys(); - const Span<MLoop> loops = mesh.loops(); - - BLI_assert(mesh.totloop > 0); - Array<int> poly_indices(positions.size()); - get_closest_mesh_polys(mesh, positions, mask, poly_indices, {}, {}); - - for (const int i : mask) { - const float3 position = positions[i]; - const int poly_index = poly_indices[i]; - const MPoly &poly = polys[poly_index]; - - /* Find the closest vertex in the polygon. */ - float min_distance_sq = FLT_MAX; - int closest_vert; - int closest_loop_index = 0; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = loops[loop_index]; - const int vertex_index = loop.v; - const float distance_sq = math::distance_squared(position, mesh_positions[vertex_index]); - if (distance_sq < min_distance_sq) { - min_distance_sq = distance_sq; - closest_loop_index = loop_index; - closest_vert = vertex_index; - } - } - if (!r_corner_indices.is_empty()) { - r_corner_indices[i] = closest_loop_index; - } - if (!r_positions.is_empty()) { - r_positions[i] = mesh_positions[closest_vert]; - } - if (!r_distances_sq.is_empty()) { - r_distances_sq[i] = min_distance_sq; - } - } -} - -template<typename T> -void copy_with_indices(const VArray<T> &src, - const IndexMask mask, - const Span<int> indices, - const MutableSpan<T> dst) -{ - if (src.is_empty()) { - return; - } - for (const int i : mask) { - dst[i] = src[indices[i]]; - } -} - -template<typename T> -void copy_with_indices_clamped(const VArray<T> &src, - const IndexMask mask, - const VArray<int> &indices, - const MutableSpan<T> dst) -{ - if (src.is_empty()) { - return; - } - const int max_index = src.size() - 1; - threading::parallel_for(mask.index_range(), 4096, [&](IndexRange range) { - for (const int i : range) { - const int index = mask[i]; - dst[index] = src[std::clamp(indices[index], 0, max_index)]; - } - }); -} - -template<typename T> -void copy_with_indices_and_comparison(const VArray<T> &src_1, - const VArray<T> &src_2, - const Span<float> distances_1, - const Span<float> distances_2, - const IndexMask mask, - const Span<int> indices_1, - const Span<int> indices_2, - const MutableSpan<T> dst) -{ - if (src_1.is_empty() || src_2.is_empty()) { - return; - } - for (const int i : mask) { - if (distances_1[i] < distances_2[i]) { - dst[i] = src_1[indices_1[i]]; - } - else { - dst[i] = src_2[indices_2[i]]; - } - } -} - -static bool component_is_available(const GeometrySet &geometry, - const GeometryComponentType type, - const eAttrDomain domain) -{ - if (!geometry.has(type)) { - return false; - } - const GeometryComponent &component = *geometry.get_component_for_read(type); - if (component.is_empty()) { - return false; - } - return component.attribute_domain_size(domain) != 0; -} - -/** - * \note Multi-threading for this function is provided by the field evaluator. Since the #call - * function could be called many times, calculate the data from the source geometry once and store - * it for later. - */ -class NearestInterpolatedTransferFunction : public fn::MultiFunction { - GeometrySet source_; - GField src_field_; - - /** - * This function is meant to sample the surface of a mesh rather than take the value from - * individual elements, so use the most complex domain, ensuring no information is lost. In the - * future, it should be possible to use the most complex domain required by the field inputs, to - * simplify sampling and avoid domain conversions. - */ - eAttrDomain domain_ = ATTR_DOMAIN_CORNER; - - fn::MFSignature signature_; - - std::optional<bke::MeshFieldContext> source_context_; - std::unique_ptr<FieldEvaluator> source_evaluator_; - const GVArray *source_data_; - - public: - NearestInterpolatedTransferFunction(GeometrySet geometry, GField src_field) - : source_(std::move(geometry)), src_field_(std::move(src_field)) - { - source_.ensure_owns_direct_data(); - signature_ = this->create_signature(); - this->set_signature(&signature_); - this->evaluate_source_field(); - } - - fn::MFSignature create_signature() - { - blender::fn::MFSignatureBuilder signature{"Attribute Transfer Nearest Interpolated"}; - signature.single_input<float3>("Position"); - signature.single_output("Attribute", src_field_.cpp_type()); - return signature.build(); - } - - void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override - { - const VArray<float3> &positions = params.readonly_single_input<float3>(0, "Position"); - GMutableSpan dst = params.uninitialized_single_output_if_required(1, "Attribute"); - - const MeshComponent &mesh_component = *source_.get_component_for_read<MeshComponent>(); - BLI_assert(mesh_component.has_mesh()); - const Mesh &mesh = *mesh_component.get_for_read(); - BLI_assert(mesh.totpoly > 0); - - /* Find closest points on the mesh surface. */ - Array<int> looptri_indices(mask.min_array_size()); - Array<float3> sampled_positions(mask.min_array_size()); - get_closest_mesh_looptris(mesh, positions, mask, looptri_indices, {}, sampled_positions); - - MeshAttributeInterpolator interp(&mesh, mask, sampled_positions, looptri_indices); - interp.sample_data(*source_data_, domain_, eAttributeMapMode::INTERPOLATED, dst); - } - - private: - void evaluate_source_field() - { - const Mesh &mesh = *source_.get_mesh_for_read(); - source_context_.emplace(bke::MeshFieldContext{mesh, domain_}); - const int domain_size = mesh.attributes().domain_size(domain_); - source_evaluator_ = std::make_unique<FieldEvaluator>(*source_context_, domain_size); - source_evaluator_->add(src_field_); - source_evaluator_->evaluate(); - source_data_ = &source_evaluator_->get_evaluated(0); - } -}; - -/** - * \note Multi-threading for this function is provided by the field evaluator. Since the #call - * function could be called many times, calculate the data from the source geometry once and store - * it for later. - */ -class NearestTransferFunction : public fn::MultiFunction { - GeometrySet source_; - GField src_field_; - eAttrDomain domain_; - - fn::MFSignature signature_; - - bool use_mesh_; - bool use_points_; - - /* Store data from the source as a virtual array, since we may only access a few indices. */ - std::optional<bke::MeshFieldContext> mesh_context_; - std::unique_ptr<FieldEvaluator> mesh_evaluator_; - const GVArray *mesh_data_; - - std::optional<bke::PointCloudFieldContext> point_context_; - std::unique_ptr<FieldEvaluator> point_evaluator_; - const GVArray *point_data_; - - public: - NearestTransferFunction(GeometrySet geometry, GField src_field, eAttrDomain domain) - : source_(std::move(geometry)), src_field_(std::move(src_field)), domain_(domain) - { - source_.ensure_owns_direct_data(); - signature_ = this->create_signature(); - this->set_signature(&signature_); - - this->use_mesh_ = component_is_available(source_, GEO_COMPONENT_TYPE_MESH, domain_); - this->use_points_ = component_is_available(source_, GEO_COMPONENT_TYPE_POINT_CLOUD, domain_); - - this->evaluate_source_field(); - } - - fn::MFSignature create_signature() - { - blender::fn::MFSignatureBuilder signature{"Attribute Transfer Nearest"}; - signature.single_input<float3>("Position"); - signature.single_output("Attribute", src_field_.cpp_type()); - return signature.build(); - } - - void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override - { - const VArray<float3> &positions = params.readonly_single_input<float3>(0, "Position"); - GMutableSpan dst = params.uninitialized_single_output_if_required(1, "Attribute"); - - if (!use_mesh_ && !use_points_) { - dst.type().value_initialize_indices(dst.data(), mask); - return; - } - - const Mesh *mesh = use_mesh_ ? source_.get_mesh_for_read() : nullptr; - const PointCloud *pointcloud = use_points_ ? source_.get_pointcloud_for_read() : nullptr; - - const int tot_samples = mask.min_array_size(); - - Array<int> point_indices; - Array<float> point_distances; - - /* Depending on where what domain the source attribute lives, these indices are either vertex, - * corner, edge or polygon indices. */ - Array<int> mesh_indices; - Array<float> mesh_distances; - - /* If there is a point cloud, find the closest points. */ - if (use_points_) { - point_indices.reinitialize(tot_samples); - if (use_mesh_) { - point_distances.reinitialize(tot_samples); - } - get_closest_pointcloud_points(*pointcloud, positions, mask, point_indices, point_distances); - } - - /* If there is a mesh, find the closest mesh elements. */ - if (use_mesh_) { - mesh_indices.reinitialize(tot_samples); - if (use_points_) { - mesh_distances.reinitialize(tot_samples); - } - switch (domain_) { - case ATTR_DOMAIN_POINT: { - get_closest_mesh_points(*mesh, positions, mask, mesh_indices, mesh_distances, {}); - break; - } - case ATTR_DOMAIN_EDGE: { - get_closest_mesh_edges(*mesh, positions, mask, mesh_indices, mesh_distances, {}); - break; - } - case ATTR_DOMAIN_FACE: { - get_closest_mesh_polys(*mesh, positions, mask, mesh_indices, mesh_distances, {}); - break; - } - case ATTR_DOMAIN_CORNER: { - get_closest_mesh_corners(*mesh, positions, mask, mesh_indices, mesh_distances, {}); - break; - } - default: { - break; - } - } - } - - attribute_math::convert_to_static_type(dst.type(), [&](auto dummy) { - using T = decltype(dummy); - if (use_mesh_ && use_points_) { - VArray<T> src_mesh = mesh_data_->typed<T>(); - VArray<T> src_point = point_data_->typed<T>(); - copy_with_indices_and_comparison(src_mesh, - src_point, - mesh_distances, - point_distances, - mask, - mesh_indices, - point_indices, - dst.typed<T>()); - } - else if (use_points_) { - VArray<T> src_point = point_data_->typed<T>(); - copy_with_indices(src_point, mask, point_indices, dst.typed<T>()); - } - else if (use_mesh_) { - VArray<T> src_mesh = mesh_data_->typed<T>(); - copy_with_indices(src_mesh, mask, mesh_indices, dst.typed<T>()); - } - }); - } - - private: - void evaluate_source_field() - { - if (use_mesh_) { - const Mesh &mesh = *source_.get_mesh_for_read(); - const int domain_size = mesh.attributes().domain_size(domain_); - mesh_context_.emplace(bke::MeshFieldContext(mesh, domain_)); - mesh_evaluator_ = std::make_unique<FieldEvaluator>(*mesh_context_, domain_size); - mesh_evaluator_->add(src_field_); - mesh_evaluator_->evaluate(); - mesh_data_ = &mesh_evaluator_->get_evaluated(0); - } - - if (use_points_) { - const PointCloud &points = *source_.get_pointcloud_for_read(); - point_context_.emplace(bke::PointCloudFieldContext(points)); - point_evaluator_ = std::make_unique<FieldEvaluator>(*point_context_, points.totpoint); - point_evaluator_->add(src_field_); - point_evaluator_->evaluate(); - point_data_ = &point_evaluator_->get_evaluated(0); - } - } -}; - -static const GeometryComponent *find_source_component(const GeometrySet &geometry, - const eAttrDomain domain) -{ - /* Choose the other component based on a consistent order, rather than some more complicated - * heuristic. This is the same order visible in the spreadsheet and used in the ray-cast node. */ - static const Array<GeometryComponentType> supported_types = {GEO_COMPONENT_TYPE_MESH, - GEO_COMPONENT_TYPE_POINT_CLOUD, - GEO_COMPONENT_TYPE_CURVE, - GEO_COMPONENT_TYPE_INSTANCES}; - for (const GeometryComponentType src_type : supported_types) { - if (component_is_available(geometry, src_type, domain)) { - return geometry.get_component_for_read(src_type); - } - } - - return nullptr; -} - -/** - * The index-based transfer theoretically does not need realized data when there is only one - * instance geometry set in the source. A future optimization could be removing that limitation - * internally. - */ -class IndexTransferFunction : public fn::MultiFunction { - GeometrySet src_geometry_; - GField src_field_; - eAttrDomain domain_; - - fn::MFSignature signature_; - - std::optional<bke::GeometryFieldContext> geometry_context_; - std::unique_ptr<FieldEvaluator> evaluator_; - const GVArray *src_data_ = nullptr; - - public: - IndexTransferFunction(GeometrySet geometry, GField src_field, const eAttrDomain domain) - : src_geometry_(std::move(geometry)), src_field_(std::move(src_field)), domain_(domain) - { - src_geometry_.ensure_owns_direct_data(); - - signature_ = this->create_signature(); - this->set_signature(&signature_); - - this->evaluate_field(); - } - - fn::MFSignature create_signature() - { - fn::MFSignatureBuilder signature{"Attribute Transfer Index"}; - signature.single_input<int>("Index"); - signature.single_output("Attribute", src_field_.cpp_type()); - return signature.build(); - } - - void evaluate_field() - { - const GeometryComponent *component = find_source_component(src_geometry_, domain_); - if (component == nullptr) { - return; - } - const int domain_num = component->attribute_domain_size(domain_); - geometry_context_.emplace(bke::GeometryFieldContext(*component, domain_)); - evaluator_ = std::make_unique<FieldEvaluator>(*geometry_context_, domain_num); - evaluator_->add(src_field_); - evaluator_->evaluate(); - src_data_ = &evaluator_->get_evaluated(0); - } - - void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override - { - const VArray<int> &indices = params.readonly_single_input<int>(0, "Index"); - GMutableSpan dst = params.uninitialized_single_output(1, "Attribute"); - - const CPPType &type = dst.type(); - if (src_data_ == nullptr) { - type.value_initialize_indices(dst.data(), mask); - return; - } - - attribute_math::convert_to_static_type(type, [&](auto dummy) { - using T = decltype(dummy); - copy_with_indices_clamped(src_data_->typed<T>(), mask, indices, dst.typed<T>()); - }); - } -}; - -static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustomDataType data_type) -{ - switch (data_type) { - case CD_PROP_FLOAT: - return params.extract_input<Field<float>>("Attribute_001"); - case CD_PROP_FLOAT3: - return params.extract_input<Field<float3>>("Attribute"); - case CD_PROP_COLOR: - return params.extract_input<Field<ColorGeometry4f>>("Attribute_002"); - case CD_PROP_BOOL: - return params.extract_input<Field<bool>>("Attribute_003"); - case CD_PROP_INT32: - return params.extract_input<Field<int>>("Attribute_004"); - default: - BLI_assert_unreachable(); - } - return {}; -} - -static void output_attribute_field(GeoNodeExecParams ¶ms, GField field) -{ - switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) { - case CD_PROP_FLOAT: { - params.set_output("Attribute_001", Field<float>(field)); - break; - } - case CD_PROP_FLOAT3: { - params.set_output("Attribute", Field<float3>(field)); - break; - } - case CD_PROP_COLOR: { - params.set_output("Attribute_002", Field<ColorGeometry4f>(field)); - break; - } - case CD_PROP_BOOL: { - params.set_output("Attribute_003", Field<bool>(field)); - break; - } - case CD_PROP_INT32: { - params.set_output("Attribute_004", Field<int>(field)); - break; - } - default: - break; - } -} - -static void node_geo_exec(GeoNodeExecParams params) -{ - GeometrySet geometry = params.extract_input<GeometrySet>("Source"); - const NodeGeometryTransferAttribute &storage = node_storage(params.node()); - const GeometryNodeAttributeTransferMode mapping = (GeometryNodeAttributeTransferMode) - storage.mode; - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); - const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); - - GField field = get_input_attribute_field(params, data_type); - - auto return_default = [&]() { - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { - using T = decltype(dummy); - output_attribute_field(params, fn::make_constant_field<T>(T())); - }); - }; - - GField output_field; - switch (mapping) { - case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED: { - const Mesh *mesh = geometry.get_mesh_for_read(); - if (mesh == nullptr) { - if (!geometry.is_empty()) { - params.error_message_add(NodeWarningType::Error, - TIP_("The source geometry must contain a mesh")); - } - return return_default(); - } - if (mesh->totpoly == 0) { - /* Don't add a warning for empty meshes. */ - if (mesh->totvert != 0) { - params.error_message_add(NodeWarningType::Error, - TIP_("The source mesh must have faces")); - } - return return_default(); - } - auto fn = std::make_unique<NearestInterpolatedTransferFunction>(std::move(geometry), - std::move(field)); - auto op = std::make_shared<FieldOperation>( - FieldOperation(std::move(fn), {params.extract_input<Field<float3>>("Source Position")})); - output_field = GField(std::move(op)); - break; - } - case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST: { - if (geometry.has_curves() && !geometry.has_mesh() && !geometry.has_pointcloud()) { - params.error_message_add(NodeWarningType::Error, - TIP_("The source geometry must contain a mesh or a point cloud")); - return return_default(); - } - auto fn = std::make_unique<NearestTransferFunction>( - std::move(geometry), std::move(field), domain); - auto op = std::make_shared<FieldOperation>( - FieldOperation(std::move(fn), {params.extract_input<Field<float3>>("Source Position")})); - output_field = GField(std::move(op)); - break; - } - case GEO_NODE_ATTRIBUTE_TRANSFER_INDEX: { - Field<int> indices = params.extract_input<Field<int>>("Index"); - auto fn = std::make_unique<IndexTransferFunction>( - std::move(geometry), std::move(field), domain); - auto op = std::make_shared<FieldOperation>( - FieldOperation(std::move(fn), {std::move(indices)})); - output_field = GField(std::move(op)); - break; - } - } - - output_attribute_field(params, std::move(output_field)); -} - -} // namespace blender::nodes::node_geo_transfer_attribute_cc - -void register_node_type_geo_transfer_attribute() -{ - namespace file_ns = blender::nodes::node_geo_transfer_attribute_cc; - - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_TRANSFER_ATTRIBUTE, "Transfer Attribute", NODE_CLASS_ATTRIBUTE); - node_type_init(&ntype, file_ns::node_init); - node_type_update(&ntype, file_ns::node_update); - node_type_storage(&ntype, - "NodeGeometryTransferAttribute", - node_free_standard_storage, - node_copy_standard_storage); - ntype.declare = file_ns::node_declare; - ntype.geometry_node_execute = file_ns::node_geo_exec; - ntype.draw_buttons = file_ns::node_layout; - ntype.gather_link_search_ops = file_ns::node_gather_link_searches; - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc index 57487059437..04fe7641899 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc @@ -68,10 +68,8 @@ static void node_geo_exec(GeoNodeExecParams params) Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); const int min_vertices = std::max(params.extract_input<int>("Minimum Vertices"), 4); - GeometryNodeTriangulateQuads quad_method = static_cast<GeometryNodeTriangulateQuads>( - params.node().custom1); - GeometryNodeTriangulateNGons ngon_method = static_cast<GeometryNodeTriangulateNGons>( - params.node().custom2); + GeometryNodeTriangulateQuads quad_method = GeometryNodeTriangulateQuads(params.node().custom1); + GeometryNodeTriangulateNGons ngon_method = GeometryNodeTriangulateNGons(params.node().custom2); geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { if (!geometry_set.has_mesh()) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc index 6979693e215..2c8a70901f8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc @@ -61,7 +61,7 @@ static eNodeSocketDatatype custom_data_type_to_socket_type(const eCustomDataType static void node_update(bNodeTree *ntree, bNode *node) { const NodeGeometryViewer &storage = node_storage(*node); - const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); + const eCustomDataType data_type = eCustomDataType(storage.data_type); const eNodeSocketDatatype socket_type = custom_data_type_to_socket_type(data_type); LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc index c102b91acb1..4018f85fc94 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc @@ -75,8 +75,7 @@ class Grid3DFieldContext : public FieldContext { int64_t points_num() const { - return static_cast<int64_t>(resolution_.x) * static_cast<int64_t>(resolution_.y) * - static_cast<int64_t>(resolution_.z); + return int64_t(resolution_.x) * int64_t(resolution_.y) * int64_t(resolution_.z); } GVArray get_varray_for_input(const FieldInput &field_input, @@ -169,7 +168,7 @@ static void node_geo_exec(GeoNodeExecParams params) grid->transform().postTranslate( openvdb::math::Vec3<float>(bounds_min.x, bounds_min.y, bounds_min.z)); - Volume *volume = (Volume *)BKE_id_new_nomain(ID_VO, nullptr); + Volume *volume = reinterpret_cast<Volume *>(BKE_id_new_nomain(ID_VO, nullptr)); BKE_volume_init_grids(volume); BKE_volume_grid_add_vdb(*volume, "density", std::move(grid)); diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index cb296cdd93f..7a78547b10b 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -535,6 +535,12 @@ class LazyFunctionForViewerNode : public LazyFunction { { GeoNodesLFUserData *user_data = dynamic_cast<GeoNodesLFUserData *>(context.user_data); BLI_assert(user_data != nullptr); + if (user_data->modifier_data == nullptr) { + return; + } + if (user_data->modifier_data->eval_log == nullptr) { + return; + } GeometrySet geometry = params.extract_input<GeometrySet>(0); @@ -1188,70 +1194,27 @@ struct GeometryNodesLazyFunctionGraphBuilder { bool try_add_implicit_input(const bNodeSocket &input_bsocket, lf::InputSocket &input_lf_socket) { const bNode &bnode = input_bsocket.owner_node(); - const NodeDeclaration *node_declaration = bnode.declaration(); - if (node_declaration == nullptr) { + const SocketDeclaration *socket_decl = input_bsocket.runtime->declaration; + if (socket_decl == nullptr) { return false; } - const SocketDeclaration &socket_declaration = - *node_declaration->inputs()[input_bsocket.index()]; - if (socket_declaration.input_field_type() != InputSocketFieldType::Implicit) { + if (socket_decl->input_field_type() != InputSocketFieldType::Implicit) { return false; } - const CPPType &type = input_lf_socket.type(); - std::function<void(void *)> init_fn = this->get_implicit_input_init_function(bnode, - input_bsocket); - if (!init_fn) { + const ImplicitInputValueFn *implicit_input_fn = socket_decl->implicit_input_fn(); + if (implicit_input_fn == nullptr) { return false; } - + std::function<void(void *)> init_fn = [&bnode, implicit_input_fn](void *r_value) { + (*implicit_input_fn)(bnode, r_value); + }; + const CPPType &type = input_lf_socket.type(); auto lazy_function = std::make_unique<LazyFunctionForImplicitInput>(type, std::move(init_fn)); lf::Node &lf_node = lf_graph_->add_function(*lazy_function); lf_graph_info_->functions.append(std::move(lazy_function)); lf_graph_->add_link(lf_node.output(0), input_lf_socket); return true; } - - std::function<void(void *)> get_implicit_input_init_function(const bNode &bnode, - const bNodeSocket &bsocket) - { - const bNodeSocketType &socket_type = *bsocket.typeinfo; - if (socket_type.type == SOCK_VECTOR) { - if (bnode.type == GEO_NODE_SET_CURVE_HANDLES) { - StringRef side = ((NodeGeometrySetCurveHandlePositions *)bnode.storage)->mode == - GEO_NODE_CURVE_HANDLE_LEFT ? - "handle_left" : - "handle_right"; - return [side](void *r_value) { - new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>(side)); - }; - } - else if (bnode.type == GEO_NODE_EXTRUDE_MESH) { - return [](void *r_value) { - new (r_value) - ValueOrField<float3>(Field<float3>(std::make_shared<bke::NormalFieldInput>())); - }; - } - else { - return [](void *r_value) { - new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>("position")); - }; - } - } - else if (socket_type.type == SOCK_INT) { - if (ELEM(bnode.type, FN_NODE_RANDOM_VALUE, GEO_NODE_INSTANCE_ON_POINTS)) { - return [](void *r_value) { - new (r_value) - ValueOrField<int>(Field<int>(std::make_shared<bke::IDAttributeFieldInput>())); - }; - } - else { - return [](void *r_value) { - new (r_value) ValueOrField<int>(Field<int>(std::make_shared<fn::IndexFieldInput>())); - }; - } - } - return {}; - } }; const GeometryNodesLazyFunctionGraphInfo *ensure_geometry_nodes_lazy_function_graph( diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index 110573c9119..aadf69f10c5 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -35,8 +35,8 @@ FieldInfoLog::FieldInfoLog(const GField &field) : type(field.cpp_type()) std::sort( field_inputs.begin(), field_inputs.end(), [](const FieldInput &a, const FieldInput &b) { - const int index_a = (int)a.category(); - const int index_b = (int)b.category(); + const int index_a = int(a.category()); + const int index_b = int(b.category()); if (index_a == index_b) { return a.socket_inspection_name().size() < b.socket_inspection_name().size(); } diff --git a/source/blender/nodes/intern/node_common.cc b/source/blender/nodes/intern/node_common.cc index 1f085375329..022ea3313e2 100644 --- a/source/blender/nodes/intern/node_common.cc +++ b/source/blender/nodes/intern/node_common.cc @@ -221,7 +221,7 @@ void node_group_update(struct bNodeTree *ntree, struct bNode *node) if (node->id == nullptr) { nodeRemoveAllSockets(ntree, node); } - else if ((ID_IS_LINKED(node->id) && (node->id->tag & LIB_TAG_MISSING))) { + else if (ID_IS_LINKED(node->id) && (node->id->tag & LIB_TAG_MISSING)) { /* Missing data-block, leave sockets unchanged so that when it comes back * the links remain valid. */ } diff --git a/source/blender/nodes/intern/node_declaration.cc b/source/blender/nodes/intern/node_declaration.cc index 2cd9c6000c0..f323d035668 100644 --- a/source/blender/nodes/intern/node_declaration.cc +++ b/source/blender/nodes/intern/node_declaration.cc @@ -2,6 +2,7 @@ #include "NOD_node_declaration.hh" +#include "BKE_geometry_fields.hh" #include "BKE_node.h" namespace blender::nodes { @@ -81,4 +82,30 @@ bool SocketDeclaration::matches_common_data(const bNodeSocket &socket) const return true; } +namespace implicit_field_inputs { + +void position(const bNode & /*node*/, void *r_value) +{ + new (r_value) fn::ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>("position")); +} + +void normal(const bNode & /*node*/, void *r_value) +{ + new (r_value) + fn::ValueOrField<float3>(fn::Field<float3>(std::make_shared<bke::NormalFieldInput>())); +} + +void index(const bNode & /*node*/, void *r_value) +{ + new (r_value) fn::ValueOrField<int>(fn::Field<int>(std::make_shared<fn::IndexFieldInput>())); +} + +void id_or_index(const bNode & /*node*/, void *r_value) +{ + new (r_value) + fn::ValueOrField<int>(fn::Field<int>(std::make_shared<bke::IDAttributeFieldInput>())); +} + +} // namespace implicit_field_inputs + } // namespace blender::nodes diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index 098f766589d..79ce9b76e82 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -59,14 +59,14 @@ struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, } case SOCK_INT: { bNodeSocketValueInt *dval = (bNodeSocketValueInt *)sock->default_value; - dval->value = (int)stemp->val1; - dval->min = (int)stemp->min; - dval->max = (int)stemp->max; + dval->value = int(stemp->val1); + dval->min = int(stemp->min); + dval->max = int(stemp->max); break; } case SOCK_BOOLEAN: { bNodeSocketValueBoolean *dval = (bNodeSocketValueBoolean *)sock->default_value; - dval->value = (int)stemp->val1; + dval->value = int(stemp->val1); break; } case SOCK_VECTOR: { diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc index a6d2e954a0c..2edcd160345 100644 --- a/source/blender/nodes/shader/node_shader_tree.cc +++ b/source/blender/nodes/shader/node_shader_tree.cc @@ -300,7 +300,7 @@ static bool ntree_shader_expand_socket_default(bNodeTree *localtree, BLI_assert(value_socket != nullptr); src_int = static_cast<bNodeSocketValueInt *>(socket->default_value); dst_float = static_cast<bNodeSocketValueFloat *>(value_socket->default_value); - dst_float->value = (float)(src_int->value); + dst_float->value = float(src_int->value); break; case SOCK_FLOAT: value_node = nodeAddStaticNode(nullptr, localtree, SH_NODE_VALUE); @@ -563,7 +563,7 @@ static bNode *ntree_shader_copy_branch(bNodeTree *ntree, void (*callback)(bNode *node, int user_data), int user_data) { - /* Init tmp flag. */ + /* Initialize `tmp_flag`. */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { node->tmp_flag = -1; } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc index a0579372a15..766c926916a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc @@ -44,7 +44,7 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR); b.add_input<decl::Float>(N_("IOR")).default_value(1.55f).min(0.0f).max(1000.0f); b.add_input<decl::Float>(N_("Offset")) - .default_value(2.0f * ((float)M_PI) / 180.0f) + .default_value(2.0f * float(M_PI) / 180.0f) .min(-M_PI_2) .max(M_PI_2) .subtype(PROP_ANGLE); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc b/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc index a1c51a440d0..5a7ec408433 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc @@ -13,7 +13,10 @@ namespace blender::nodes::node_shader_tex_brick_cc { static void sh_node_tex_brick_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).min(-10000.0f).max(10000.0f).implicit_field(); + b.add_input<decl::Vector>(N_("Vector")) + .min(-10000.0f) + .max(10000.0f) + .implicit_field(implicit_field_inputs::position); b.add_input<decl::Color>(N_("Color1")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); b.add_input<decl::Color>(N_("Color2")).default_value({0.2f, 0.2f, 0.2f, 1.0f}); b.add_input<decl::Color>(N_("Mortar")).default_value({0.0f, 0.0f, 0.0f, 1.0f}).no_muted_links(); @@ -147,7 +150,7 @@ class BrickFunction : public fn::MultiFunction { n = (n + 1013) & 0x7fffffff; n = (n >> 13) ^ n; const uint nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; - return 0.5f * ((float)nn / 1073741824.0f); + return 0.5f * (float(nn) / 1073741824.0f); } static float smoothstepf(const float f) @@ -169,14 +172,14 @@ class BrickFunction : public fn::MultiFunction { { float offset = 0.0f; - const int rownum = (int)floorf(p.y / row_height); + const int rownum = int(floorf(p.y / row_height)); if (offset_frequency && squash_frequency) { brick_width *= (rownum % squash_frequency) ? 1.0f : squash_amount; offset = (rownum % offset_frequency) ? 0.0f : (brick_width * offset_amount); } - const int bricknum = (int)floorf((p.x + offset) / brick_width); + const int bricknum = int(floorf((p.x + offset) / brick_width)); const float x = (p.x + offset) - brick_width * bricknum; const float y = p.y - row_height * rownum; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc b/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc index b0e5639c893..fc231d79417 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc @@ -8,7 +8,10 @@ namespace blender::nodes::node_shader_tex_checker_cc { static void sh_node_tex_checker_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).min(-10000.0f).max(10000.0f).implicit_field(); + b.add_input<decl::Vector>(N_("Vector")) + .min(-10000.0f) + .max(10000.0f) + .implicit_field(implicit_field_inputs::position); b.add_input<decl::Color>(N_("Color1")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); b.add_input<decl::Color>(N_("Color2")).default_value({0.2f, 0.2f, 0.2f, 1.0f}); b.add_input<decl::Float>(N_("Scale")) @@ -77,9 +80,9 @@ class NodeTexChecker : public fn::MultiFunction { /* Avoid precision issues on unit coordinates. */ const float3 p = (vector[i] * scale[i] + 0.000001f) * 0.999999f; - const int xi = abs((int)(floorf(p.x))); - const int yi = abs((int)(floorf(p.y))); - const int zi = abs((int)(floorf(p.z))); + const int xi = abs(int(floorf(p.x))); + const int yi = abs(int(floorf(p.y))); + const int zi = abs(int(floorf(p.z))); r_fac[i] = ((xi % 2 == yi % 2) == (zi % 2)) ? 1.0f : 0.0f; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc index 37c72ec1f17..bc7837040b7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc @@ -11,7 +11,9 @@ namespace blender::nodes::node_shader_tex_gradient_cc { static void sh_node_tex_gradient_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).hide_value().implicit_field(); + b.add_input<decl::Vector>(N_("Vector")) + .hide_value() + .implicit_field(implicit_field_inputs::position); b.add_output<decl::Color>(N_("Color")).no_muted_links(); b.add_output<decl::Float>(N_("Fac")).no_muted_links(); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc index c9588949761..e70539fcf25 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc @@ -8,7 +8,7 @@ namespace blender::nodes::node_shader_tex_image_cc { static void sh_node_tex_image_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).implicit_field(); + b.add_input<decl::Vector>(N_("Vector")).implicit_field(implicit_field_inputs::position); b.add_output<decl::Color>(N_("Color")).no_muted_links(); b.add_output<decl::Float>(N_("Alpha")).no_muted_links(); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc b/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc index 205d3b89016..86c96cfe70b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc @@ -11,7 +11,7 @@ namespace blender::nodes::node_shader_tex_magic_cc { static void sh_node_tex_magic_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).implicit_field(); + b.add_input<decl::Vector>(N_("Vector")).implicit_field(implicit_field_inputs::position); b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); b.add_input<decl::Float>(N_("Distortion")).min(-1000.0f).max(1000.0f).default_value(1.0f); b.add_output<decl::Color>(N_("Color")).no_muted_links(); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc index a2241c2327f..86a79a3f213 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc @@ -15,7 +15,9 @@ NODE_STORAGE_FUNCS(NodeTexMusgrave) static void sh_node_tex_musgrave_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).hide_value().implicit_field(); + b.add_input<decl::Vector>(N_("Vector")) + .hide_value() + .implicit_field(implicit_field_inputs::position); b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f).make_available([](bNode &node) { /* Default to 1 instead of 4, because it is much faster. */ node_storage(node).dimensions = 1; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc index 87fb1aeac29..eabe1fa774f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc @@ -15,7 +15,7 @@ NODE_STORAGE_FUNCS(NodeTexNoise) static void sh_node_tex_noise_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).implicit_field(); + b.add_input<decl::Vector>(N_("Vector")).implicit_field(implicit_field_inputs::position); b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f).make_available([](bNode &node) { /* Default to 1 instead of 4, because it is much faster. */ node_storage(node).dimensions = 1; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.cc b/source/blender/nodes/shader/nodes/node_shader_tex_sky.cc index 97b7f2616ae..23fb4052c7e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.cc @@ -189,12 +189,12 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat, /* Pass sky_state->configs[3][9] as 3*(vec4+vec4)+vec3 */ float config_x07[8], config_y07[8], config_z07[8], config_xyz8[3]; for (int i = 0; i < 8; ++i) { - config_x07[i] = (float)sky_state->configs[0][i]; - config_y07[i] = (float)sky_state->configs[1][i]; - config_z07[i] = (float)sky_state->configs[2][i]; + config_x07[i] = float(sky_state->configs[0][i]); + config_y07[i] = float(sky_state->configs[1][i]); + config_z07[i] = float(sky_state->configs[2][i]); } for (int i = 0; i < 3; ++i) { - config_xyz8[i] = (float)sky_state->configs[i][8]; + config_xyz8[i] = float(sky_state->configs[i][8]); } float radiance[3]; for (int i = 0; i < 3; i++) { diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc index fc6a5ef72b6..723cf9322f8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc @@ -15,7 +15,9 @@ NODE_STORAGE_FUNCS(NodeTexVoronoi) static void sh_node_tex_voronoi_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).hide_value().implicit_field(); + b.add_input<decl::Vector>(N_("Vector")) + .hide_value() + .implicit_field(implicit_field_inputs::position); b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f).make_available([](bNode &node) { /* Default to 1 instead of 4, because it is much faster. */ node_storage(node).dimensions = 1; @@ -173,7 +175,7 @@ static void node_shader_update_tex_voronoi(bNodeTree *ntree, bNode *node) outWSock, storage.feature != SHD_VORONOI_DISTANCE_TO_EDGE && storage.feature != SHD_VORONOI_N_SPHERE_RADIUS && - (ELEM(storage.dimensions, 1, 4))); + ELEM(storage.dimensions, 1, 4)); nodeSetSocketAvailability(ntree, outRadiusSock, storage.feature == SHD_VORONOI_N_SPHERE_RADIUS); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc index 8475101dbaf..d86b2d820ab 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc @@ -13,7 +13,7 @@ namespace blender::nodes::node_shader_tex_wave_cc { static void sh_node_tex_wave_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).implicit_field(); + b.add_input<decl::Vector>(N_("Vector")).implicit_field(implicit_field_inputs::position); b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); b.add_input<decl::Float>(N_("Distortion")).min(-1000.0f).max(1000.0f).default_value(0.0f); b.add_input<decl::Float>(N_("Detail")).min(0.0f).max(15.0f).default_value(2.0f); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc index 64075a903ab..d7f985d73fa 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc @@ -13,7 +13,10 @@ namespace blender::nodes::node_shader_tex_white_noise_cc { static void sh_node_tex_white_noise_declare(NodeDeclarationBuilder &b) { b.is_function_node(); - b.add_input<decl::Vector>(N_("Vector")).min(-10000.0f).max(10000.0f).implicit_field(); + b.add_input<decl::Vector>(N_("Vector")) + .min(-10000.0f) + .max(10000.0f) + .implicit_field(implicit_field_inputs::position); b.add_input<decl::Float>(N_("W")).min(-10000.0f).max(10000.0f).make_available([](bNode &node) { /* Default to 1 instead of 4, because it is faster. */ node.custom1 = 1; @@ -177,7 +180,7 @@ class WhiteNoiseFunction : public fn::MultiFunction { static void sh_node_noise_build_multi_function(NodeMultiFunctionBuilder &builder) { const bNode &node = builder.node(); - builder.construct_and_set_matching_fn<WhiteNoiseFunction>((int)node.custom1); + builder.construct_and_set_matching_fn<WhiteNoiseFunction>(int(node.custom1)); } } // namespace blender::nodes::node_shader_tex_white_noise_cc |