diff options
Diffstat (limited to 'source/blender/blenkernel')
36 files changed, 998 insertions, 480 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 4274ca97fd1..da1e45ababd 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -141,14 +141,6 @@ struct DerivedMesh { void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *r_loop); void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly); - /** Return a copy of all verts/edges/faces from the derived mesh - * it is the caller's responsibility to free the returned pointer - */ - struct MVert *(*dupVertArray)(DerivedMesh *dm); - struct MEdge *(*dupEdgeArray)(DerivedMesh *dm); - struct MLoop *(*dupLoopArray)(DerivedMesh *dm); - struct MPoly *(*dupPolyArray)(DerivedMesh *dm); - /** Return a pointer to the entire array of vert/edge/face custom data * from the derived mesh (this gives a pointer to the actual data, not * a copy) @@ -254,11 +246,6 @@ void DM_copy_vert_data(struct DerivedMesh *source, int count); /** - * Sets up mpolys for a DM based on face iterators in source. - */ -void DM_DupPolys(DerivedMesh *source, DerivedMesh *target); - -/** * Ensure the array is large enough. * * \note This function must always be thread-protected by caller. diff --git a/source/blender/blenkernel/BKE_attribute.hh b/source/blender/blenkernel/BKE_attribute.hh index 4aa6c133e9e..fbdacee139c 100644 --- a/source/blender/blenkernel/BKE_attribute.hh +++ b/source/blender/blenkernel/BKE_attribute.hh @@ -553,6 +553,11 @@ class MutableAttributeAccessor : public AttributeAccessor { GAttributeWriter lookup_for_write(const AttributeIDRef &attribute_id); /** + * Same as above, but returns a type that makes it easier to work with the attribute as a span. + */ + GSpanAttributeWriter lookup_for_write_span(const AttributeIDRef &attribute_id); + + /** * Get a writable attribute or non if it does not exist. * Make sure to call #finish after changes are done. */ @@ -569,6 +574,19 @@ class MutableAttributeAccessor : public AttributeAccessor { } /** + * Same as above, but returns a type that makes it easier to work with the attribute as a span. + */ + template<typename T> + SpanAttributeWriter<T> lookup_for_write_span(const AttributeIDRef &attribute_id) + { + AttributeWriter<T> attribute = this->lookup_for_write<T>(attribute_id); + if (attribute) { + return SpanAttributeWriter<T>{std::move(attribute), true}; + } + return {}; + } + + /** * Create a new attribute. * \return True, when a new attribute has been created. False, when it's not possible to create * this attribute or there is already an attribute with that id. @@ -692,6 +710,19 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer( eAttrDomainMask domain_mask, const Set<std::string> &skip = {}); +/** + * Copy attributes for the domain based on the elementwise mask. + * + * \param mask_indices: Indexed elements to copy from the source data-block. + * \param domain: Attribute domain to transfer. + * \param skip: Named attributes to ignore/skip. + */ +void copy_attribute_domain(AttributeAccessor src_attributes, + MutableAttributeAccessor dst_attributes, + IndexMask selection, + eAttrDomain domain, + const Set<std::string> &skip = {}); + bool allow_procedural_attribute_access(StringRef attribute_name); extern const char *no_procedural_access_message; diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 3c929857c14..2d1aca7c3c8 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -25,10 +25,6 @@ struct Mesh; * data to not overwrite the original. */ struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh); -/* Copies the given DerivedMesh with verts, faces & edges stored as - * custom element data. */ -struct DerivedMesh *CDDM_copy(struct DerivedMesh *source); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_compute_contexts.hh b/source/blender/blenkernel/BKE_compute_contexts.hh new file mode 100644 index 00000000000..a8f0022f49b --- /dev/null +++ b/source/blender/blenkernel/BKE_compute_contexts.hh @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** + * This file implements some specific compute contexts for concepts in Blender. + */ + +#include "BLI_compute_context.hh" + +namespace blender::bke { + +class ModifierComputeContext : public ComputeContext { + private: + static constexpr const char *s_static_type = "MODIFIER"; + + /** + * Use modifier name instead of something like `session_uuid` for now because: + * - It's more obvious that the name matches between the original and evaluated object. + * - We might want that the context hash is consistent between sessions in the future. + */ + std::string modifier_name_; + + public: + ModifierComputeContext(const ComputeContext *parent, std::string modifier_name); + + private: + void print_current_in_line(std::ostream &stream) const override; +}; + +class NodeGroupComputeContext : public ComputeContext { + private: + static constexpr const char *s_static_type = "NODE_GROUP"; + + std::string node_name_; + + public: + NodeGroupComputeContext(const ComputeContext *parent, std::string node_name); + + StringRefNull node_name() const; + + private: + void print_current_in_line(std::ostream &stream) const override; +}; + +} // namespace blender::bke diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h index 56049ecf405..b2024f09278 100644 --- a/source/blender/blenkernel/BKE_cryptomatte.h +++ b/source/blender/blenkernel/BKE_cryptomatte.h @@ -25,6 +25,8 @@ struct CryptomatteSession *BKE_cryptomatte_init(void); struct CryptomatteSession *BKE_cryptomatte_init_from_render_result( const struct RenderResult *render_result); struct CryptomatteSession *BKE_cryptomatte_init_from_scene(const struct Scene *scene); +struct CryptomatteSession *BKE_cryptomatte_init_from_view_layer( + const struct ViewLayer *view_layer); void BKE_cryptomatte_free(struct CryptomatteSession *session); void BKE_cryptomatte_add_layer(struct CryptomatteSession *session, const char *layer_name); diff --git a/source/blender/blenkernel/BKE_cryptomatte.hh b/source/blender/blenkernel/BKE_cryptomatte.hh index cd3f8dc9f58..dd08f7b5c4f 100644 --- a/source/blender/blenkernel/BKE_cryptomatte.hh +++ b/source/blender/blenkernel/BKE_cryptomatte.hh @@ -12,6 +12,7 @@ #include "BKE_cryptomatte.h" +#include "BLI_hash_mm3.h" #include "BLI_map.hh" #include "BLI_string_ref.hh" @@ -54,10 +55,14 @@ struct CryptomatteHash { uint32_t hash; CryptomatteHash(uint32_t hash); - CryptomatteHash(const char *name, int name_len); - static CryptomatteHash from_hex_encoded(blender::StringRef hex_encoded); + CryptomatteHash(const char *name, int name_len) + { + hash = BLI_hash_mm3((const unsigned char *)name, name_len, 0); + } + static CryptomatteHash from_hex_encoded(blender::StringRef hex_encoded); std::string hex_encoded() const; + /** * Convert a cryptomatte hash to a float. * @@ -70,7 +75,20 @@ struct CryptomatteHash { * * Note that this conversion assumes to be running on a L-endian system. */ - float float_encoded() const; + float float_encoded() const + { + uint32_t mantissa = hash & ((1 << 23) - 1); + uint32_t exponent = (hash >> 23) & ((1 << 8) - 1); + exponent = MAX2(exponent, (uint32_t)1); + exponent = MIN2(exponent, (uint32_t)254); + exponent = exponent << 23; + uint32_t sign = (hash >> 31); + sign = sign << 31; + uint32_t float_bits = sign | exponent | mantissa; + float f; + memcpy(&f, &float_bits, sizeof(uint32_t)); + return f; + } }; struct CryptomatteLayer { @@ -107,6 +125,8 @@ struct CryptomatteStampDataCallbackData { const blender::Vector<std::string> &BKE_cryptomatte_layer_names_get( const CryptomatteSession &session); +CryptomatteLayer *BKE_cryptomatte_layer_get(CryptomatteSession &session, + const StringRef layer_name); struct CryptomatteSessionDeleter { void operator()(CryptomatteSession *session) diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh index 4b0fc293b54..9f150c13d6e 100644 --- a/source/blender/blenkernel/BKE_curves.hh +++ b/source/blender/blenkernel/BKE_curves.hh @@ -22,6 +22,7 @@ #include "BLI_virtual_array.hh" #include "BKE_attribute.hh" +#include "BKE_attribute_math.hh" namespace blender::bke { @@ -162,6 +163,11 @@ class CurvesGeometry : public ::CurvesGeometry { IndexRange curves_range() const; /** + * Number of control points in the indexed curve. + */ + int points_num_for_curve(const int index) const; + + /** * The index of the first point in every curve. The size of this span is one larger than the * number of curves. Consider using #points_for_curve rather than using the offsets directly. */ @@ -532,6 +538,16 @@ bool segment_is_vector(Span<int8_t> handle_types_left, int segment_index); /** + * True if the Bezier curve contains polygonal segments of HandleType::BEZIER_HANDLE_VECTOR. + * + * \param num_curve_points: Number of points in the curve. + * \param evaluated_size: Number of evaluated points in the curve. + * \param cyclic: If curve is cyclic. + * \param resolution: Curve resolution. + */ +bool has_vector_handles(int num_curve_points, int64_t evaluated_size, bool cyclic, int resolution); + +/** * Return true if the curve's last cyclic segment has a vector type. * This only makes a difference in the shape of cyclic curves. */ @@ -693,6 +709,36 @@ void interpolate_to_evaluated(const GSpan src, const Span<int> evaluated_offsets, GMutableSpan dst); +void calculate_basis(const float parameter, float r_weights[4]); + +/** + * Interpolate the control point values for the given parameter on the piecewise segment. + * \param a: Value associated with the first control point influencing the segment. + * \param d: Value associated with the fourth control point. + * \param parameter: Parameter in range [0, 1] to compute the interpolation for. + */ +template<typename T> +T interpolate(const T &a, const T &b, const T &c, const T &d, const float parameter) +{ + float n[4]; + calculate_basis(parameter, n); + /* TODO: Use DefaultMixer or other generic mixing in the basis evaluation function to simplify + * supporting more types. */ + if constexpr (!is_same_any_v<T, float, float2, float3, float4, int8_t, int, int64_t>) { + T return_value; + attribute_math::DefaultMixer<T> mixer({&return_value, 1}); + mixer.mix_in(0, a, n[0] * 0.5f); + mixer.mix_in(0, b, n[1] * 0.5f); + mixer.mix_in(0, c, n[2] * 0.5f); + mixer.mix_in(0, d, n[3] * 0.5f); + mixer.finalize(); + return return_value; + } + else { + return 0.5f * (a * n[0] + b * n[1] + c * n[2] + d * n[3]); + } +} + } // namespace catmull_rom /** \} */ @@ -807,6 +853,16 @@ inline IndexRange CurvesGeometry::curves_range() const return IndexRange(this->curves_num()); } +inline int CurvesGeometry::points_num_for_curve(const int index) const +{ + BLI_assert(this->curve_num > 0); + BLI_assert(this->curve_num > index); + BLI_assert(this->curve_offsets != nullptr); + const int offset = this->curve_offsets[index]; + const int offset_next = this->curve_offsets[index + 1]; + return offset_next - offset; +} + inline bool CurvesGeometry::is_single_type(const CurveType type) const { return this->curve_type_counts()[type] == this->curves_num(); @@ -833,6 +889,7 @@ inline IndexRange CurvesGeometry::points_for_curve(const int index) const { /* Offsets are not allocated when there are no curves. */ BLI_assert(this->curve_num > 0); + BLI_assert(this->curve_num > index); BLI_assert(this->curve_offsets != nullptr); const int offset = this->curve_offsets[index]; const int offset_next = this->curve_offsets[index + 1]; @@ -905,11 +962,13 @@ inline float CurvesGeometry::evaluated_length_total_for_curve(const int curve_in /** \} */ +namespace curves { + /* -------------------------------------------------------------------- */ /** \name Bezier Inline Methods * \{ */ -namespace curves::bezier { +namespace bezier { inline bool point_is_sharp(const Span<int8_t> handle_types_left, const Span<int8_t> handle_types_right, @@ -929,14 +988,24 @@ inline bool segment_is_vector(const int8_t left, const int8_t right) return segment_is_vector(HandleType(left), HandleType(right)); } +inline bool has_vector_handles(const int num_curve_points, + const int64_t evaluated_size, + const bool cyclic, + const int resolution) +{ + return evaluated_size - !cyclic != (int64_t)segments_num(num_curve_points, cyclic) * resolution; +} + inline float3 calculate_vector_handle(const float3 &point, const float3 &next_point) { return math::interpolate(point, next_point, 1.0f / 3.0f); } +} // namespace bezier + /** \} */ -} // namespace curves::bezier +} // namespace curves struct CurvesSurfaceTransforms { float4x4 curves_to_world; diff --git a/source/blender/blenkernel/BKE_curves_utils.hh b/source/blender/blenkernel/BKE_curves_utils.hh index 0fbd33002e1..5579ab5654a 100644 --- a/source/blender/blenkernel/BKE_curves_utils.hh +++ b/source/blender/blenkernel/BKE_curves_utils.hh @@ -11,9 +11,301 @@ #include "BLI_function_ref.hh" #include "BLI_generic_pointer.hh" +#include "BLI_index_range.hh" namespace blender::bke::curves { +/* -------------------------------------------------------------------- + * Utility structs. + */ + +/** + * Reference to a piecewise segment on a spline curve. + */ +struct CurveSegment { + /** + * Index of the previous control/evaluated point on the curve. First point on the segment. + */ + int index; + /** + * Index of the next control/evaluated point on the curve. Last point on the curve segment. + * Should be 0 for looped segments. + */ + int next_index; +}; + +/** + * Reference to a point on a piecewise curve (spline). + * + * Tracks indices of the neighbouring control/evaluated point pair associated with the segment + * in which the point resides. Referenced point within the segment is defined by a + * normalized parameter in the range [0, 1]. + */ +struct CurvePoint : public CurveSegment { + /** + * Normalized parameter in the range [0, 1] defining the point on the piecewise segment. + * Note that the curve point representation is not unique at segment endpoints. + */ + float parameter; + + /** + * True if the parameter is an integer and references a control/evaluated point. + */ + inline bool is_controlpoint() const; + + /* + * Compare if the points are equal. + */ + inline bool operator==(const CurvePoint &other) const; + inline bool operator!=(const CurvePoint &other) const; + + /** + * Compare if 'this' point comes before 'other'. Loop segment for cyclical curves counts + * as the first (least) segment. + */ + inline bool operator<(const CurvePoint &other) const; +}; + +/** + * Cyclical index range. Iterates the interval [start, end). + */ +class IndexRangeCyclic { + /* Index to the start and end of the iterated range. + */ + int64_t start_ = 0; + int64_t end_ = 0; + /* Index for the start and end of the entire iterable range which contains the iterated range + * (e.g. the point range for an indiviudal spline/curve within the entire Curves point domain). + */ + int64_t range_start_ = 0; + int64_t range_end_ = 0; + /* Number of times the range end is passed when the range is iterated. + */ + int64_t cycles_ = 0; + + constexpr IndexRangeCyclic(int64_t begin, + int64_t end, + int64_t iterable_range_start, + int64_t iterable_range_end, + int64_t cycles) + : start_(begin), + end_(end), + range_start_(iterable_range_start), + range_end_(iterable_range_end), + cycles_(cycles) + { + } + + public: + constexpr IndexRangeCyclic() = default; + ~IndexRangeCyclic() = default; + + constexpr IndexRangeCyclic(int64_t start, int64_t end, IndexRange iterable_range, int64_t cycles) + : start_(start), + end_(end), + range_start_(iterable_range.first()), + range_end_(iterable_range.one_after_last()), + cycles_(cycles) + { + } + + /** + * Create an iterator over the cyclical interval [start_index, end_index). + */ + constexpr IndexRangeCyclic(int64_t start, int64_t end, IndexRange iterable_range) + : start_(start), + end_(end == iterable_range.one_after_last() ? iterable_range.first() : end), + range_start_(iterable_range.first()), + range_end_(iterable_range.one_after_last()), + cycles_(end < start) + { + } + + /** + * Increment the range by adding the given number of indices to the beginning of the range. + */ + constexpr IndexRangeCyclic push_forward(int n) + { + BLI_assert(n >= 0); + int64_t nstart = start_ - n; + int64_t cycles = cycles_; + if (nstart < range_start_) { + + cycles += (int64_t)(n / (range_end_ - range_start_)) + (end_ < nstart) - (end_ < start_); + } + return {nstart, end_, range_start_, range_end_, cycles}; + } + /** + * Increment the range by adding the given number of indices to the end of the range. + */ + constexpr IndexRangeCyclic push_backward(int n) + { + BLI_assert(n >= 0); + int64_t new_end = end_ + n; + int64_t cycles = cycles_; + if (range_end_ <= new_end) { + cycles += (int64_t)(n / (range_end_ - range_start_)) + (new_end < start_) - (end_ < start_); + } + return {start_, new_end, range_start_, range_end_, cycles}; + } + + /** + * Get the index range for the curve buffer. + */ + constexpr IndexRange curve_range() const + { + return IndexRange(range_start_, total_size()); + } + + /** + * Range between the first element up to the end of the range. + */ + constexpr IndexRange range_before_loop() const + { + return IndexRange(start_, size_before_loop()); + } + + /** + * Range between the first element in the iterable range up to the last element in the range. + */ + constexpr IndexRange range_after_loop() const + { + return IndexRange(range_start_, size_after_loop()); + } + + /** + * Size of the entire iterable range. + */ + constexpr int64_t total_size() const + { + return range_end_ - range_start_; + } + + /** + * Number of elements between the first element in the range up to the last element in the curve. + */ + constexpr int64_t size_before_loop() const + { + return range_end_ - start_; + } + + /** + * Number of elements between the first element in the iterable range up to the last element in + * the range. + */ + constexpr int64_t size_after_loop() const + { + return end_ - range_start_; + } + + /** + * Get number of elements iterated by the cyclical index range. + */ + constexpr int64_t size() const + { + if (cycles_ > 0) { + return size_before_loop() + end_ + (cycles_ - 1) * (range_end_ - range_start_); + } + else { + return end_ - start_; + } + } + + /** + * Return the number of times the iterator will cycle before ending. + */ + constexpr int64_t cycles() const + { + return cycles_; + } + + constexpr int64_t first() const + { + return start_; + } + + constexpr int64_t one_after_last() const + { + return end_; + } + + struct CyclicIterator; /* Forward declaration */ + + constexpr CyclicIterator begin() const + { + return CyclicIterator(range_start_, range_end_, start_, 0); + } + + constexpr CyclicIterator end() const + { + return CyclicIterator(range_start_, range_end_, end_, cycles_); + } + + struct CyclicIterator { + int64_t index_, begin_, end_, cycles_; + + constexpr CyclicIterator(int64_t range_begin, int64_t range_end, int64_t index, int64_t cycles) + : index_(index), begin_(range_begin), end_(range_end), cycles_(cycles) + { + BLI_assert(range_begin <= index && index <= range_end); + } + + constexpr CyclicIterator(const CyclicIterator ©) + : index_(copy.index_), begin_(copy.begin_), end_(copy.end_), cycles_(copy.cycles_) + { + } + ~CyclicIterator() = default; + + constexpr CyclicIterator &operator=(const CyclicIterator ©) + { + if (this == ©) { + return *this; + } + index_ = copy.index_; + begin_ = copy.begin_; + end_ = copy.end_; + cycles_ = copy.cycles_; + return *this; + } + constexpr CyclicIterator &operator++() + { + index_++; + if (index_ == end_) { + index_ = begin_; + cycles_++; + } + return *this; + } + + void increment(int64_t n) + { + for (int i = 0; i < n; i++) { + ++*this; + } + } + + constexpr const int64_t &operator*() const + { + return index_; + } + + constexpr bool operator==(const CyclicIterator &other) const + { + return index_ == other.index_ && cycles_ == other.cycles_; + } + constexpr bool operator!=(const CyclicIterator &other) const + { + return !this->operator==(other); + } + }; +}; + +/** \} */ + +/* -------------------------------------------------------------------- + * Utility functions. + */ + /** * Copy the provided point attribute values between all curves in the #curve_ranges index * ranges, assuming that all curves have the same number of control points in #src_curves @@ -88,4 +380,40 @@ void foreach_curve_by_type(const VArray<int8_t> &types, FunctionRef<void(IndexMask)> bezier_fn, FunctionRef<void(IndexMask)> nurbs_fn); +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #CurvePoint Inline Methods + * \{ */ + +inline bool CurvePoint::is_controlpoint() const +{ + return parameter == 0.0 || parameter == 1.0; +} + +inline bool CurvePoint::operator==(const CurvePoint &other) const +{ + return (parameter == other.parameter && index == other.index) || + (parameter == 1.0 && other.parameter == 0.0 && next_index == other.index) || + (parameter == 0.0 && other.parameter == 1.0 && index == other.next_index); +} +inline bool CurvePoint::operator!=(const CurvePoint &other) const +{ + return !this->operator==(other); +} + +inline bool CurvePoint::operator<(const CurvePoint &other) const +{ + if (index == other.index) { + return parameter < other.parameter; + } + else { + /* Use next index for cyclic comparison due to loop segment < first segment. */ + return next_index < other.next_index && + !(next_index == other.index && parameter == 1.0 && other.parameter == 0.0); + } +} + +/** \} */ + } // namespace blender::bke::curves diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 09d37682b3c..24fa5f0e87a 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -178,13 +178,11 @@ bool CustomData_merge_mesh_to_bmesh(const struct CustomData *source, int totelem); /** - * Reallocate custom data to a new element count. - * Only affects on data layers which are owned by the CustomData itself, - * referenced data is kept unchanged, - * - * \note Take care of referenced layers by yourself! + * Reallocate custom data to a new element count. If the new size is larger, the new values use + * the #CD_CONSTRUCT behavior, so trivial types must be initialized by the caller. After being + * resized, the #CustomData does not contain any referenced layers. */ -void CustomData_realloc(struct CustomData *data, int totelem); +void CustomData_realloc(struct CustomData *data, int old_size, int new_size); /** * BMesh version of CustomData_merge; merges the layouts of source and `dest`, diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 677a1053826..4023d6829d4 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -50,19 +50,29 @@ void BKE_defgroup_copy_list(struct ListBase *outbase, const struct ListBase *inb struct bDeformGroup *BKE_defgroup_duplicate(const struct bDeformGroup *ingroup); struct bDeformGroup *BKE_object_defgroup_find_name(const struct Object *ob, const char *name); /** - * \note caller must free. + * Returns flip map for the vertex-groups of `ob`. + * + * \param use_default: How to handle cases where no symmetrical group is found. + * - false: sets these indices to -1, indicating the group should be ignored. + * - true: sets the index to its location in the array (making the group point to it's self). + * Enable this for symmetrical actions which apply weight operations on symmetrical vertices + * where the symmetrical group will be used (if found), otherwise the same group is used. + * + * \return An index array `r_flip_map_num` length, + * (aligned with the list result from `BKE_id_defgroup_list_get(ob)`). + * referencing the index of the symmetrical vertex-group of a fall-back value (see `use_default`). + * The caller is responsible for freeing the array. */ int *BKE_object_defgroup_flip_map(const struct Object *ob, bool use_default, int *r_flip_map_num); /** - * Returns flip map for only unlocked defgroups. - * \note caller must free. + * A version of #BKE_object_defgroup_flip_map that ignores locked groups. */ int *BKE_object_defgroup_flip_map_unlocked(const struct Object *ob, bool use_default, int *r_flip_map_num); /** - * \note caller must free. + * A version of #BKE_object_defgroup_flip_map that only takes a single group into account. */ int *BKE_object_defgroup_flip_map_single(const struct Object *ob, bool use_default, diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh index f2e551a9f32..194820aa4ba 100644 --- a/source/blender/blenkernel/BKE_node_runtime.hh +++ b/source/blender/blenkernel/BKE_node_runtime.hh @@ -21,6 +21,7 @@ struct bNodeType; namespace blender::nodes { struct FieldInferencingInterface; class NodeDeclaration; +struct GeometryNodesLazyFunctionGraphInfo; } // namespace blender::nodes namespace blender::bke { @@ -49,6 +50,15 @@ class bNodeTreeRuntime : NonCopyable, NonMovable { std::unique_ptr<nodes::FieldInferencingInterface> field_inferencing_interface; /** + * For geometry nodes, a lazy function graph with some additional info is cached. This is used to + * evaluate the node group. Caching it here allows us to reuse the preprocessed node tree in case + * its used multiple times. + */ + std::mutex geometry_nodes_lazy_function_graph_info_mutex; + std::unique_ptr<nodes::GeometryNodesLazyFunctionGraphInfo> + geometry_nodes_lazy_function_graph_info; + + /** * Protects access to all topology cache variables below. This is necessary so that the cache can * be updated on a const #bNodeTree. */ @@ -70,6 +80,7 @@ class bNodeTreeRuntime : NonCopyable, NonMovable { MultiValueMap<const bNodeType *, bNode *> nodes_by_type; Vector<bNode *> toposort_left_to_right; Vector<bNode *> toposort_right_to_left; + Vector<bNode *> group_nodes; bool has_link_cycle = false; bool has_undefined_nodes_or_sockets = false; bNode *group_output_node = nullptr; @@ -148,6 +159,12 @@ class bNodeRuntime : NonCopyable, NonMovable { namespace node_tree_runtime { +/** + * Is executed when the depsgraph determines that something in the node group changed that will + * affect the output. + */ +void handle_node_tree_output_changed(bNodeTree &tree_cow); + class AllowUsingOutdatedInfo : NonCopyable, NonMovable { private: const bNodeTree &tree_; @@ -241,6 +258,18 @@ inline blender::Span<bNode *> bNodeTree::all_nodes() return this->runtime->nodes; } +inline blender::Span<const bNode *> bNodeTree::group_nodes() const +{ + BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this)); + return this->runtime->group_nodes; +} + +inline blender::Span<bNode *> bNodeTree::group_nodes() +{ + BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this)); + return this->runtime->group_nodes; +} + inline bool bNodeTree::has_link_cycle() const { BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this)); @@ -413,7 +442,6 @@ inline blender::Span<const bNodeLink *> bNode::internal_links_span() const inline const blender::nodes::NodeDeclaration *bNode::declaration() const { - BLI_assert(this->runtime->declaration != nullptr); return this->runtime->declaration; } diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 9a067e761d7..eef91bacc2f 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -213,9 +213,7 @@ bool BKE_paint_always_hide_test(struct Object *ob); /** * Returns non-zero if any of the face's vertices are hidden, zero otherwise. */ -bool paint_is_face_hidden(const struct MLoopTri *lt, - const bool *hide_vert, - const struct MLoop *mloop); +bool paint_is_face_hidden(const struct MLoopTri *lt, const bool *hide_poly); /** * Returns non-zero if any of the corners of the grid * face whose inner corner is at (x, y) are hidden, zero otherwise. @@ -689,7 +687,7 @@ void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph, bool need_pmap, bool need_mask, bool is_paint_tool); -void BKE_sculpt_update_object_before_eval(const struct Scene *scene, struct Object *ob_eval); +void BKE_sculpt_update_object_before_eval(struct Object *ob_eval); void BKE_sculpt_update_object_after_eval(struct Depsgraph *depsgraph, struct Object *ob_eval); /** @@ -698,6 +696,7 @@ void BKE_sculpt_update_object_after_eval(struct Depsgraph *depsgraph, struct Obj */ struct MultiresModifierData *BKE_sculpt_multires_active(const struct Scene *scene, struct Object *ob); +int *BKE_sculpt_face_sets_ensure(struct Mesh *mesh); int BKE_sculpt_mask_layers_ensure(struct Object *ob, struct MultiresModifierData *mmd); void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene); @@ -719,18 +718,17 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg); /** - * Ensures that a Face Set data-layers exists. If it does not, it creates one respecting the - * visibility stored in the vertices of the mesh. If it does, it copies the visibility from the - * mesh to the Face Sets. */ -void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(struct Mesh *mesh); + * If a face set layer exists, initialize its visibility (sign) from the mesh's hidden values. + */ +void BKE_sculpt_face_sets_update_from_base_mesh_visibility(struct Mesh *mesh); /** - * Ensures we do have expected mesh data in original mesh for the sculpt mode. + * Makes sculpt data consistent with other data on the mesh. * * \note IDs are expected to be original ones here, and calling code should ensure it updates its * depsgraph properly after calling this function if it needs up-to-date evaluated data. */ -void BKE_sculpt_ensure_orig_mesh_data(struct Scene *scene, struct Object *object); +void BKE_sculpt_ensure_orig_mesh_data(struct Object *object); /** * Test if PBVH can be used directly for drawing, which is faster than diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 716ee7d2a21..6a194698bd8 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -491,6 +491,12 @@ void BKE_pbvh_grids_update(PBVH *pbvh, void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, struct SubdivCCG *subdiv_ccg); void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets); +/** + * If an operation causes the hide status stored in the mesh to change, this must be called + * to update the references to those attributes, since they are only added when necessary. + */ +void BKE_pbvh_update_hide_attributes_from_mesh(PBVH *pbvh); + void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default); void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide); @@ -674,6 +680,8 @@ const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3]; const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh); bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh); +const bool *BKE_pbvh_get_poly_hide(const PBVH *pbvh); + PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node); void BKE_pbvh_node_color_buffer_free(PBVH *pbvh); bool BKE_pbvh_get_color_layer(const struct Mesh *me, diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b982c69a378..2f1e1897f8d 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -98,6 +98,7 @@ set(SRC intern/collision.c intern/colorband.c intern/colortools.c + intern/compute_contexts.cc intern/constraint.c intern/context.c intern/crazyspace.cc @@ -352,6 +353,7 @@ set(SRC BKE_collision.h BKE_colorband.h BKE_colortools.h + BKE_compute_contexts.hh BKE_constraint.h BKE_context.h BKE_crazyspace.h diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 0036ed1cf61..d7db0ad765c 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -147,54 +147,6 @@ static MPoly *dm_getPolyArray(DerivedMesh *dm) return mpoly; } -static MVert *dm_dupVertArray(DerivedMesh *dm) -{ - MVert *tmp = (MVert *)MEM_malloc_arrayN( - dm->getNumVerts(dm), sizeof(*tmp), "dm_dupVertArray tmp"); - - if (tmp) { - dm->copyVertArray(dm, tmp); - } - - return tmp; -} - -static MEdge *dm_dupEdgeArray(DerivedMesh *dm) -{ - MEdge *tmp = (MEdge *)MEM_malloc_arrayN( - dm->getNumEdges(dm), sizeof(*tmp), "dm_dupEdgeArray tmp"); - - if (tmp) { - dm->copyEdgeArray(dm, tmp); - } - - return tmp; -} - -static MLoop *dm_dupLoopArray(DerivedMesh *dm) -{ - MLoop *tmp = (MLoop *)MEM_malloc_arrayN( - dm->getNumLoops(dm), sizeof(*tmp), "dm_dupLoopArray tmp"); - - if (tmp) { - dm->copyLoopArray(dm, tmp); - } - - return tmp; -} - -static MPoly *dm_dupPolyArray(DerivedMesh *dm) -{ - MPoly *tmp = (MPoly *)MEM_malloc_arrayN( - dm->getNumPolys(dm), sizeof(*tmp), "dm_dupPolyArray tmp"); - - if (tmp) { - dm->copyPolyArray(dm, tmp); - } - - return tmp; -} - static int dm_getNumLoopTri(DerivedMesh *dm) { const int numlooptris = poly_to_tri_count(dm->getNumPolys(dm), dm->getNumLoops(dm)); @@ -233,10 +185,6 @@ void DM_init_funcs(DerivedMesh *dm) dm->getEdgeArray = dm_getEdgeArray; dm->getLoopArray = dm_getLoopArray; dm->getPolyArray = dm_getPolyArray; - dm->dupVertArray = dm_dupVertArray; - dm->dupEdgeArray = dm_dupEdgeArray; - dm->dupLoopArray = dm_dupLoopArray; - dm->dupPolyArray = dm_dupPolyArray; dm->getLoopTriArray = dm_getLoopTriArray; @@ -331,36 +279,6 @@ bool DM_release(DerivedMesh *dm) return false; } -void DM_DupPolys(DerivedMesh *source, DerivedMesh *target) -{ - CustomData_free(&target->loopData, source->numLoopData); - CustomData_free(&target->polyData, source->numPolyData); - - CustomData_copy(&source->loopData, - &target->loopData, - CD_MASK_DERIVEDMESH.lmask, - CD_DUPLICATE, - source->numLoopData); - CustomData_copy(&source->polyData, - &target->polyData, - CD_MASK_DERIVEDMESH.pmask, - CD_DUPLICATE, - source->numPolyData); - - target->numLoopData = source->numLoopData; - target->numPolyData = source->numPolyData; - - if (!CustomData_has_layer(&target->polyData, CD_MPOLY)) { - MPoly *mpoly; - MLoop *mloop; - - mloop = source->dupLoopArray(source); - mpoly = source->dupPolyArray(source); - CustomData_add_layer(&target->loopData, CD_MLOOP, CD_ASSIGN, mloop, source->numLoopData); - CustomData_add_layer(&target->polyData, CD_MPOLY, CD_ASSIGN, mpoly, source->numPolyData); - } -} - void DM_ensure_looptri_data(DerivedMesh *dm) { const unsigned int totpoly = dm->numPolyData; @@ -1802,7 +1720,7 @@ void makeDerivedMesh(struct Depsgraph *depsgraph, BKE_object_free_derived_caches(ob); if (DEG_is_active(depsgraph)) { - BKE_sculpt_update_object_before_eval(scene, ob); + BKE_sculpt_update_object_before_eval(ob); } /* NOTE: Access the `edit_mesh` after freeing the derived caches, so that `ob->data` is restored diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 24e4305d916..96ac81fdb63 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -371,14 +371,16 @@ static bool get_path_local_ex(char *targetpath, relfolder[0] = '\0'; } - /* Try `{g_app.program_dirname}/2.xx/{folder_name}` the default directory + /* Try `{g_app.program_dirname}/3.xx/{folder_name}` the default directory * for a portable distribution. See `WITH_INSTALL_PORTABLE` build-option. */ const char *path_base = g_app.program_dirname; #if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE) /* Due new code-sign situation in OSX > 10.9.5 - * we must move the blender_version dir with contents to Resources. */ - char osx_resourses[FILE_MAX]; - BLI_snprintf(osx_resourses, sizeof(osx_resourses), "%s../Resources", g_app.program_dirname); + * we must move the blender_version dir with contents to Resources. + * Add 4 + 9 for the temporary `/../` path & `Resources`. */ + char osx_resourses[FILE_MAX + 4 + 9]; + BLI_path_join( + osx_resourses, sizeof(osx_resourses), g_app.program_dirname, "..", "Resources", NULL); /* Remove the '/../' added above. */ BLI_path_normalize(NULL, osx_resourses); path_base = osx_resourses; diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 6ca3a286a5e..1e237da8119 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -14,6 +14,7 @@ #include "DNA_meshdata_types.h" #include "DNA_pointcloud_types.h" +#include "BLI_array_utils.hh" #include "BLI_color.hh" #include "BLI_math_vec_types.hh" #include "BLI_span.hh" @@ -726,8 +727,22 @@ bool CustomDataAttributes::remove(const AttributeIDRef &attribute_id) void CustomDataAttributes::reallocate(const int size) { + const int old_size = size_; size_ = size; - CustomData_realloc(&data, size); + CustomData_realloc(&data, old_size, size_); + if (size_ > old_size) { + /* Fill default new values. */ + const int new_elements_num = size_ - old_size; + this->foreach_attribute( + [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData /*meta_data*/) { + GMutableSpan new_data = this->get_for_write(id)->take_back(new_elements_num); + const CPPType &type = new_data.type(); + type.fill_assign_n(type.default_value(), new_data.data(), new_data.size()); + return true; + }, + /* Dummy. */ + ATTR_DOMAIN_POINT); + } } void CustomDataAttributes::clear() @@ -875,6 +890,16 @@ GAttributeWriter MutableAttributeAccessor::lookup_for_write(const AttributeIDRef return attribute; } +GSpanAttributeWriter MutableAttributeAccessor::lookup_for_write_span( + const AttributeIDRef &attribute_id) +{ + GAttributeWriter attribute = this->lookup_for_write(attribute_id); + if (attribute) { + return GSpanAttributeWriter{std::move(attribute), true}; + } + return {}; +} + GAttributeWriter MutableAttributeAccessor::lookup_or_add_for_write( const AttributeIDRef &attribute_id, const eAttrDomain domain, @@ -950,6 +975,37 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer( return attributes; } +void copy_attribute_domain(const AttributeAccessor src_attributes, + MutableAttributeAccessor dst_attributes, + const IndexMask selection, + const eAttrDomain domain, + const Set<std::string> &skip) +{ + src_attributes.for_all( + [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData &meta_data) { + if (meta_data.domain != domain) { + return true; + } + if (id.is_named() && skip.contains(id.name())) { + return true; + } + if (!id.should_be_kept()) { + return true; + } + + const GVArray src = src_attributes.lookup(id, meta_data.domain); + BLI_assert(src); + + /* Copy attribute. */ + GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span( + id, domain, meta_data.data_type); + array_utils::copy(src, selection, dst.span); + dst.finish(); + + return true; + }); +} + } // namespace blender::bke /** \} */ diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 93286751f92..0261b2d7674 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -244,43 +244,3 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh) { return cdDM_from_mesh_ex(mesh, CD_REFERENCE, &CD_MASK_MESH); } - -DerivedMesh *CDDM_copy(DerivedMesh *source) -{ - CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm"); - DerivedMesh *dm = &cddm->dm; - int numVerts = source->numVertData; - int numEdges = source->numEdgeData; - int numTessFaces = 0; - int numLoops = source->numLoopData; - int numPolys = source->numPolyData; - - /* NOTE: Don't copy tessellation faces if not requested explicitly. */ - - /* ensure these are created if they are made on demand */ - source->getVertDataArray(source, CD_ORIGINDEX); - source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getPolyDataArray(source, CD_ORIGINDEX); - - /* this initializes dm, and copies all non mvert/medge/mface layers */ - DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys); - dm->deformedOnly = source->deformedOnly; - dm->cd_flag = source->cd_flag; - - CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); - CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges); - - /* now add mvert/medge/mface layers */ - cddm->mvert = source->dupVertArray(source); - cddm->medge = source->dupEdgeArray(source); - - CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts); - CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges); - - DM_DupPolys(source, dm); - - cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); - cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); - - return dm; -} diff --git a/source/blender/blenkernel/intern/compute_contexts.cc b/source/blender/blenkernel/intern/compute_contexts.cc new file mode 100644 index 00000000000..026706d363e --- /dev/null +++ b/source/blender/blenkernel/intern/compute_contexts.cc @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BKE_compute_contexts.hh" + +namespace blender::bke { + +ModifierComputeContext::ModifierComputeContext(const ComputeContext *parent, + std::string modifier_name) + : ComputeContext(s_static_type, parent), modifier_name_(std::move(modifier_name)) +{ + hash_.mix_in(s_static_type, strlen(s_static_type)); + hash_.mix_in(modifier_name_.data(), modifier_name_.size()); +} + +void ModifierComputeContext::print_current_in_line(std::ostream &stream) const +{ + stream << "Modifier: " << modifier_name_; +} + +NodeGroupComputeContext::NodeGroupComputeContext(const ComputeContext *parent, + std::string node_name) + : ComputeContext(s_static_type, parent), node_name_(std::move(node_name)) +{ + hash_.mix_in(s_static_type, strlen(s_static_type)); + hash_.mix_in(node_name_.data(), node_name_.size()); +} + +StringRefNull NodeGroupComputeContext::node_name() const +{ + return node_name_; +} + +void NodeGroupComputeContext::print_current_in_line(std::ostream &stream) const +{ + stream << "Node: " << node_name_; +} + +} // namespace blender::bke diff --git a/source/blender/blenkernel/intern/cryptomatte.cc b/source/blender/blenkernel/intern/cryptomatte.cc index 102bda0f2b6..72204f6624e 100644 --- a/source/blender/blenkernel/intern/cryptomatte.cc +++ b/source/blender/blenkernel/intern/cryptomatte.cc @@ -41,7 +41,9 @@ struct CryptomatteSession { CryptomatteSession() = default; CryptomatteSession(const Main *bmain); CryptomatteSession(StampData *stamp_data); + CryptomatteSession(const ViewLayer *view_layer); CryptomatteSession(const Scene *scene); + void init(const ViewLayer *view_layer); blender::bke::cryptomatte::CryptomatteLayer &add_layer(std::string layer_name); std::optional<std::string> operator[](float encoded_hash) const; @@ -54,13 +56,15 @@ struct CryptomatteSession { CryptomatteSession::CryptomatteSession(const Main *bmain) { if (!BLI_listbase_is_empty(&bmain->objects)) { - blender::bke::cryptomatte::CryptomatteLayer &objects = add_layer("CryptoObject"); + blender::bke::cryptomatte::CryptomatteLayer &objects = add_layer( + RE_PASSNAME_CRYPTOMATTE_OBJECT); LISTBASE_FOREACH (ID *, id, &bmain->objects) { objects.add_ID(*id); } } if (!BLI_listbase_is_empty(&bmain->materials)) { - blender::bke::cryptomatte::CryptomatteLayer &materials = add_layer("CryptoMaterial"); + blender::bke::cryptomatte::CryptomatteLayer &materials = add_layer( + RE_PASSNAME_CRYPTOMATTE_MATERIAL); LISTBASE_FOREACH (ID *, id, &bmain->materials) { materials.add_ID(*id); } @@ -83,24 +87,34 @@ CryptomatteSession::CryptomatteSession(StampData *stamp_data) false); } +CryptomatteSession::CryptomatteSession(const ViewLayer *view_layer) +{ + init(view_layer); +} + CryptomatteSession::CryptomatteSession(const Scene *scene) { - LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { - eViewLayerCryptomatteFlags cryptoflags = static_cast<eViewLayerCryptomatteFlags>( - view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_ALL); - if (cryptoflags == 0) { - cryptoflags = static_cast<eViewLayerCryptomatteFlags>(VIEW_LAYER_CRYPTOMATTE_ALL); - } + LISTBASE_FOREACH (const ViewLayer *, view_layer, &scene->view_layers) { + init(view_layer); + } +} - if (cryptoflags & VIEW_LAYER_CRYPTOMATTE_OBJECT) { - add_layer(blender::StringRefNull(view_layer->name) + ".CryptoObject"); - } - if (cryptoflags & VIEW_LAYER_CRYPTOMATTE_ASSET) { - add_layer(blender::StringRefNull(view_layer->name) + ".CryptoAsset"); - } - if (cryptoflags & VIEW_LAYER_CRYPTOMATTE_MATERIAL) { - add_layer(blender::StringRefNull(view_layer->name) + ".CryptoMaterial"); - } +void CryptomatteSession::init(const ViewLayer *view_layer) +{ + eViewLayerCryptomatteFlags cryptoflags = static_cast<eViewLayerCryptomatteFlags>( + view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_ALL); + if (cryptoflags == 0) { + cryptoflags = static_cast<eViewLayerCryptomatteFlags>(VIEW_LAYER_CRYPTOMATTE_ALL); + } + + if (cryptoflags & VIEW_LAYER_CRYPTOMATTE_OBJECT) { + add_layer(blender::StringRefNull(view_layer->name) + "." + RE_PASSNAME_CRYPTOMATTE_OBJECT); + } + if (cryptoflags & VIEW_LAYER_CRYPTOMATTE_ASSET) { + add_layer(blender::StringRefNull(view_layer->name) + "." + RE_PASSNAME_CRYPTOMATTE_ASSET); + } + if (cryptoflags & VIEW_LAYER_CRYPTOMATTE_MATERIAL) { + add_layer(blender::StringRefNull(view_layer->name) + "." + RE_PASSNAME_CRYPTOMATTE_MATERIAL); } } @@ -142,6 +156,12 @@ struct CryptomatteSession *BKE_cryptomatte_init_from_scene(const struct Scene *s return session; } +struct CryptomatteSession *BKE_cryptomatte_init_from_view_layer(const struct ViewLayer *view_layer) +{ + CryptomatteSession *session = new CryptomatteSession(view_layer); + return session; +} + void BKE_cryptomatte_add_layer(struct CryptomatteSession *session, const char *layer_name) { session->add_layer(layer_name); @@ -485,11 +505,6 @@ CryptomatteHash::CryptomatteHash(uint32_t hash) : hash(hash) { } -CryptomatteHash::CryptomatteHash(const char *name, const int name_len) -{ - hash = BLI_hash_mm3((const unsigned char *)name, name_len, 0); -} - CryptomatteHash CryptomatteHash::from_hex_encoded(blender::StringRef hex_encoded) { CryptomatteHash result(0); @@ -504,21 +519,6 @@ std::string CryptomatteHash::hex_encoded() const return encoded.str(); } -float CryptomatteHash::float_encoded() const -{ - uint32_t mantissa = hash & ((1 << 23) - 1); - uint32_t exponent = (hash >> 23) & ((1 << 8) - 1); - exponent = MAX2(exponent, (uint32_t)1); - exponent = MIN2(exponent, (uint32_t)254); - exponent = exponent << 23; - uint32_t sign = (hash >> 31); - sign = sign << 31; - uint32_t float_bits = sign | exponent | mantissa; - float f; - memcpy(&f, &float_bits, sizeof(uint32_t)); - return f; -} - std::unique_ptr<CryptomatteLayer> CryptomatteLayer::read_from_manifest( blender::StringRefNull manifest) { @@ -625,4 +625,9 @@ const blender::Vector<std::string> &BKE_cryptomatte_layer_names_get( return session.layer_names; } +CryptomatteLayer *BKE_cryptomatte_layer_get(CryptomatteSession &session, StringRef layer_name) +{ + return session.layers.lookup_ptr(layer_name); +} + } // namespace blender::bke::cryptomatte diff --git a/source/blender/blenkernel/intern/curve_catmull_rom.cc b/source/blender/blenkernel/intern/curve_catmull_rom.cc index 952d59edcf9..dac88948036 100644 --- a/source/blender/blenkernel/intern/curve_catmull_rom.cc +++ b/source/blender/blenkernel/intern/curve_catmull_rom.cc @@ -17,16 +17,14 @@ int calculate_evaluated_num(const int points_num, const bool cyclic, const int r } /* Adapted from Cycles #catmull_rom_basis_eval function. */ -template<typename T> -static T calculate_basis(const T &a, const T &b, const T &c, const T &d, const float parameter) +void calculate_basis(const float parameter, float r_weights[4]) { const float t = parameter; const float s = 1.0f - parameter; - const float n0 = -t * s * s; - const float n1 = 2.0f + t * t * (3.0f * t - 5.0f); - const float n2 = 2.0f + s * s * (3.0f * s - 5.0f); - const float n3 = -s * t * t; - return 0.5f * (a * n0 + b * n1 + c * n2 + d * n3); + r_weights[0] = -t * s * s; + r_weights[1] = 2.0f + t * t * (3.0f * t - 5.0f); + r_weights[2] = 2.0f + s * s * (3.0f * s - 5.0f); + r_weights[3] = -s * t * t; } template<typename T> @@ -35,7 +33,7 @@ static void evaluate_segment(const T &a, const T &b, const T &c, const T &d, Mut const float step = 1.0f / dst.size(); dst.first() = b; for (const int i : dst.index_range().drop_front(1)) { - dst[i] = calculate_basis<T>(a, b, c, d, i * step); + dst[i] = interpolate<T>(a, b, c, d, i * step); } } diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 35b209179d3..06789e34ad4 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -963,11 +963,11 @@ void CurvesGeometry::ensure_can_interpolate_to_evaluated() const void CurvesGeometry::resize(const int points_num, const int curves_num) { if (points_num != this->point_num) { - CustomData_realloc(&this->point_data, points_num); + CustomData_realloc(&this->point_data, this->points_num(), points_num); this->point_num = points_num; } if (curves_num != this->curve_num) { - CustomData_realloc(&this->curve_data, curves_num); + CustomData_realloc(&this->curve_data, this->curves_num(), curves_num); this->curve_num = curves_num; this->curve_offsets = (int *)MEM_reallocN(this->curve_offsets, sizeof(int) * (curves_num + 1)); } @@ -1380,69 +1380,49 @@ static void reverse_swap_curve_point_data(const CurvesGeometry &curves, }); } -static bool layer_matches_name_and_type(const CustomDataLayer &layer, - const StringRef name, - const eCustomDataType type) -{ - if (layer.type != type) { - return false; - } - return layer.name == name; -} - void CurvesGeometry::reverse_curves(const IndexMask curves_to_reverse) { - CustomData_duplicate_referenced_layers(&this->point_data, this->points_num()); + Set<StringRef> bezier_handle_names{{ATTR_HANDLE_POSITION_LEFT, + ATTR_HANDLE_POSITION_RIGHT, + ATTR_HANDLE_TYPE_LEFT, + ATTR_HANDLE_TYPE_RIGHT}}; - /* Collect the Bezier handle attributes while iterating through the point custom data layers; - * they need special treatment later. */ - MutableSpan<float3> positions_left; - MutableSpan<float3> positions_right; - MutableSpan<int8_t> types_left; - MutableSpan<int8_t> types_right; + MutableAttributeAccessor attributes = this->attributes_for_write(); - for (const int layer_i : IndexRange(this->point_data.totlayer)) { - CustomDataLayer &layer = this->point_data.layers[layer_i]; - - if (positions_left.is_empty() && - layer_matches_name_and_type(layer, ATTR_HANDLE_POSITION_LEFT, CD_PROP_FLOAT3)) { - positions_left = {static_cast<float3 *>(layer.data), this->points_num()}; - continue; - } - if (positions_right.is_empty() && - layer_matches_name_and_type(layer, ATTR_HANDLE_POSITION_RIGHT, CD_PROP_FLOAT3)) { - positions_right = {static_cast<float3 *>(layer.data), this->points_num()}; - continue; - } - if (types_left.is_empty() && - layer_matches_name_and_type(layer, ATTR_HANDLE_TYPE_LEFT, CD_PROP_INT8)) { - types_left = {static_cast<int8_t *>(layer.data), this->points_num()}; - continue; + attributes.for_all([&](const AttributeIDRef &id, AttributeMetaData meta_data) { + if (meta_data.domain != ATTR_DOMAIN_POINT) { + return true; } - if (types_right.is_empty() && - layer_matches_name_and_type(layer, ATTR_HANDLE_TYPE_RIGHT, CD_PROP_INT8)) { - types_right = {static_cast<int8_t *>(layer.data), this->points_num()}; - continue; + if (id.is_named() && bezier_handle_names.contains(id.name())) { + return true; } - const eCustomDataType data_type = static_cast<eCustomDataType>(layer.type); - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id); + attribute_math::convert_to_static_type(attribute.span.type(), [&](auto dummy) { using T = decltype(dummy); - reverse_curve_point_data<T>( - *this, curves_to_reverse, {static_cast<T *>(layer.data), this->points_num()}); + reverse_curve_point_data<T>(*this, curves_to_reverse, attribute.span.typed<T>()); }); - } + attribute.finish(); + return true; + }); /* In order to maintain the shape of Bezier curves, handle attributes must reverse, but also the * values for the left and right must swap. Use a utility to swap and reverse at the same time, * to avoid loading the attribute twice. Generally we can expect the right layer to exist when * the left does, but there's no need to count on it, so check for both attributes. */ - if (!positions_left.is_empty() && !positions_right.is_empty()) { - reverse_swap_curve_point_data(*this, curves_to_reverse, positions_left, positions_right); + if (attributes.contains(ATTR_HANDLE_POSITION_LEFT) && + attributes.contains(ATTR_HANDLE_POSITION_RIGHT)) { + reverse_swap_curve_point_data(*this, + curves_to_reverse, + this->handle_positions_left_for_write(), + this->handle_positions_right_for_write()); } - if (!types_left.is_empty() && !types_right.is_empty()) { - reverse_swap_curve_point_data(*this, curves_to_reverse, types_left, types_right); + if (attributes.contains(ATTR_HANDLE_TYPE_LEFT) && attributes.contains(ATTR_HANDLE_TYPE_RIGHT)) { + reverse_swap_curve_point_data(*this, + curves_to_reverse, + this->handle_types_left_for_write(), + this->handle_types_right_for_write()); } this->tag_topology_changed(); @@ -1450,21 +1430,20 @@ void CurvesGeometry::reverse_curves(const IndexMask curves_to_reverse) void CurvesGeometry::remove_attributes_based_on_types() { - const int points_num = this->points_num(); - const int curves_num = this->curves_num(); + MutableAttributeAccessor attributes = this->attributes_for_write(); if (!this->has_curve_with_type(CURVE_TYPE_BEZIER)) { - CustomData_free_layer_named(&this->point_data, ATTR_HANDLE_TYPE_LEFT.c_str(), points_num); - CustomData_free_layer_named(&this->point_data, ATTR_HANDLE_TYPE_RIGHT.c_str(), points_num); - CustomData_free_layer_named(&this->point_data, ATTR_HANDLE_POSITION_LEFT.c_str(), points_num); - CustomData_free_layer_named(&this->point_data, ATTR_HANDLE_POSITION_RIGHT.c_str(), points_num); + attributes.remove(ATTR_HANDLE_TYPE_LEFT); + attributes.remove(ATTR_HANDLE_TYPE_RIGHT); + attributes.remove(ATTR_HANDLE_POSITION_LEFT); + attributes.remove(ATTR_HANDLE_POSITION_RIGHT); } if (!this->has_curve_with_type(CURVE_TYPE_NURBS)) { - CustomData_free_layer_named(&this->point_data, ATTR_NURBS_WEIGHT.c_str(), points_num); - CustomData_free_layer_named(&this->curve_data, ATTR_NURBS_ORDER.c_str(), curves_num); - CustomData_free_layer_named(&this->curve_data, ATTR_NURBS_KNOTS_MODE.c_str(), curves_num); + attributes.remove(ATTR_NURBS_WEIGHT); + attributes.remove(ATTR_NURBS_ORDER); + attributes.remove(ATTR_NURBS_KNOTS_MODE); } if (!this->has_curve_with_type({CURVE_TYPE_BEZIER, CURVE_TYPE_CATMULL_ROM, CURVE_TYPE_NURBS})) { - CustomData_free_layer_named(&this->curve_data, ATTR_RESOLUTION.c_str(), curves_num); + attributes.remove(ATTR_RESOLUTION); } } diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 24373053896..82a1a2aa8f6 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -2408,19 +2408,37 @@ bool CustomData_merge_mesh_to_bmesh(const CustomData *source, return result; } -void CustomData_realloc(CustomData *data, const int totelem) +void CustomData_realloc(CustomData *data, const int old_size, const int new_size) { - BLI_assert(totelem >= 0); + BLI_assert(new_size >= 0); for (int i = 0; i < data->totlayer; i++) { CustomDataLayer *layer = &data->layers[i]; - const LayerTypeInfo *typeInfo; + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); + + const int64_t old_size_in_bytes = int64_t(old_size) * typeInfo->size; + const int64_t new_size_in_bytes = int64_t(new_size) * typeInfo->size; if (layer->flag & CD_FLAG_NOFREE) { - continue; + const void *old_data = layer->data; + layer->data = MEM_malloc_arrayN(new_size, typeInfo->size, __func__); + if (typeInfo->copy) { + typeInfo->copy(old_data, layer->data, std::min(old_size, new_size)); + } + else { + std::memcpy(layer->data, old_data, std::min(old_size_in_bytes, new_size_in_bytes)); + } + layer->flag &= ~CD_FLAG_NOFREE; + } + else { + layer->data = MEM_reallocN(layer->data, new_size_in_bytes); + } + + if (new_size > old_size) { + /* Initialize new values for non-trivial types. */ + if (typeInfo->construct) { + const int new_elements_num = new_size - old_size; + typeInfo->construct(POINTER_OFFSET(layer->data, old_size_in_bytes), new_elements_num); + } } - typeInfo = layerType_getInfo(layer->type); - /* Use calloc to avoid the need to manually initialize new data in layers. - * Useful for types like #MDeformVert which contain a pointer. */ - layer->data = MEM_recallocN(layer->data, (size_t)totelem * typeInfo->size); } } diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc index e65a94d5301..6f62ee123cb 100644 --- a/source/blender/blenkernel/intern/image_save.cc +++ b/source/blender/blenkernel/intern/image_save.cc @@ -175,12 +175,12 @@ bool BKE_image_save_options_init(ImageSaveOptions *opts, BLI_strncpy(opts->filepath, G.ima, sizeof(opts->filepath)); } else { - BLI_snprintf(opts->filepath, sizeof(opts->filepath), "//%s", DATA_("untitled")); + BLI_path_join(opts->filepath, sizeof(opts->filepath), "//", DATA_("untitled"), nullptr); BLI_path_abs(opts->filepath, BKE_main_blendfile_path(bmain)); } } else { - BLI_snprintf(opts->filepath, sizeof(opts->filepath), "//%s", ima->id.name + 2); + BLI_path_join(opts->filepath, sizeof(opts->filepath), "//", ima->id.name + 2, nullptr); BLI_path_make_safe(opts->filepath); BLI_path_abs(opts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain)); } diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index a0548b7efd4..6bf25da5ae7 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1416,19 +1416,15 @@ void BKE_mesh_material_remap(Mesh *me, const uint *remap, uint remap_len) } else { MutableAttributeAccessor attributes = me->attributes_for_write(); - AttributeWriter<int> material_indices = attributes.lookup_for_write<int>("material_index"); + SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>( + "material_index", ATTR_DOMAIN_FACE); if (!material_indices) { return; } - if (material_indices.domain != ATTR_DOMAIN_FACE) { - BLI_assert_unreachable(); - return; - } - MutableVArraySpan<int> indices_span(material_indices.varray); - for (const int i : indices_span.index_range()) { - MAT_NR_REMAP(indices_span[i]); + for (const int i : material_indices.span.index_range()) { + MAT_NR_REMAP(material_indices.span[i]); } - indices_span.save(); + material_indices.span.save(); material_indices.finish(); } @@ -1616,14 +1612,14 @@ void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh) const Span<MEdge> edges = mesh->edges(); for (const MVert &vert : verts) { - if (vert.bweight != 0) { + if (vert.bweight_legacy != 0) { mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; break; } } for (const MEdge &edge : edges) { - if (edge.bweight != 0) { + if (edge.bweight_legacy != 0) { mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) { break; @@ -2095,11 +2091,11 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) const bool do_edges = (num_new_edges > 0); /* Reallocate all vert and edge related data. */ + CustomData_realloc(&mesh->vdata, mesh->totvert, mesh->totvert + num_new_verts); mesh->totvert += num_new_verts; - CustomData_realloc(&mesh->vdata, mesh->totvert); if (do_edges) { + CustomData_realloc(&mesh->edata, mesh->totedge, mesh->totedge + num_new_edges); mesh->totedge += num_new_edges; - CustomData_realloc(&mesh->edata, mesh->totedge); } /* Update normals manually to avoid recalculation after this operation. */ diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index b7d8972aa7b..e56df0e3fe3 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -105,8 +105,9 @@ static void make_edges_mdata_extend(Mesh &mesh) #endif if (totedge_new) { - CustomData_realloc(&mesh.edata, totedge + totedge_new); - + /* The only layer should be edges, so no other layers need to be initialized. */ + BLI_assert(mesh.edata.totlayer == 1); + CustomData_realloc(&mesh.edata, totedge, totedge + totedge_new); mesh.totedge += totedge_new; MutableSpan<MEdge> edges = mesh.edges_for_write(); MEdge *medge = &edges[totedge]; @@ -634,9 +635,11 @@ void BKE_pointcloud_from_mesh(Mesh *me, PointCloud *pointcloud) using namespace blender; BLI_assert(me != nullptr); - + /* The pointcloud should only contain the position attribute, otherwise more attributes would + * need to be initialized below. */ + BLI_assert(pointcloud->attributes().all_ids().size() == 1); + CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint, me->totvert); pointcloud->totpoint = me->totvert; - CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint); /* Copy over all attributes. */ CustomData_merge(&me->vdata, &pointcloud->pdata, CD_MASK_PROP_ALL, CD_DUPLICATE, me->totvert); diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 10fc8ff3195..627c0057a28 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -929,13 +929,13 @@ void BKE_mesh_legacy_bevel_weight_from_layers(Mesh *mesh) CustomData_get_layer(&mesh->vdata, CD_BWEIGHT))) { mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; for (const int i : verts.index_range()) { - verts[i].bweight = std::clamp(weights[i], 0.0f, 1.0f) * 255.0f; + verts[i].bweight_legacy = std::clamp(weights[i], 0.0f, 1.0f) * 255.0f; } } else { mesh->cd_flag &= ~ME_CDFLAG_VERT_BWEIGHT; for (const int i : verts.index_range()) { - verts[i].bweight = 0; + verts[i].bweight_legacy = 0; } } MutableSpan<MEdge> edges = mesh->edges_for_write(); @@ -943,13 +943,13 @@ void BKE_mesh_legacy_bevel_weight_from_layers(Mesh *mesh) CustomData_get_layer(&mesh->edata, CD_BWEIGHT))) { mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; for (const int i : edges.index_range()) { - edges[i].bweight = std::clamp(weights[i], 0.0f, 1.0f) * 255.0f; + edges[i].bweight_legacy = std::clamp(weights[i], 0.0f, 1.0f) * 255.0f; } } else { mesh->cd_flag &= ~ME_CDFLAG_EDGE_BWEIGHT; for (const int i : edges.index_range()) { - edges[i].bweight = 0; + edges[i].bweight_legacy = 0; } } } @@ -962,7 +962,7 @@ void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh) float *weights = static_cast<float *>( CustomData_add_layer(&mesh->vdata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, verts.size())); for (const int i : verts.index_range()) { - weights[i] = verts[i].bweight / 255.0f; + weights[i] = verts[i].bweight_legacy / 255.0f; } } @@ -971,7 +971,7 @@ void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh) float *weights = static_cast<float *>( CustomData_add_layer(&mesh->edata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, edges.size())); for (const int i : edges.index_range()) { - weights[i] = edges[i].bweight / 255.0f; + weights[i] = edges[i].bweight_legacy / 255.0f; } } } @@ -1077,7 +1077,7 @@ void BKE_mesh_legacy_convert_material_indices_to_mpoly(Mesh *mesh) "material_index", ATTR_DOMAIN_FACE, 0); threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { for (const int i : range) { - polys[i].mat_nr = material_indices[i]; + polys[i].mat_nr_legacy = material_indices[i]; } }); } @@ -1089,12 +1089,12 @@ void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh) MutableAttributeAccessor attributes = mesh->attributes_for_write(); const Span<MPoly> polys = mesh->polys(); if (std::any_of( - polys.begin(), polys.end(), [](const MPoly &poly) { return poly.mat_nr != 0; })) { + polys.begin(), polys.end(), [](const MPoly &poly) { return poly.mat_nr_legacy != 0; })) { SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_only_span<int>( "material_index", ATTR_DOMAIN_FACE); threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { for (const int i : range) { - material_indices.span[i] = polys[i].mat_nr; + material_indices.span[i] = polys[i].mat_nr_legacy; } }); material_indices.finish(); diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index eb14028f49a..a77879fb573 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -124,6 +124,7 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh, /* Construct the new output mesh */ Mesh *mesh = BKE_mesh_new_nomain(qrd.out_totverts, 0, 0, qrd.out_totfaces * 4, qrd.out_totfaces); + BKE_mesh_copy_parameters(mesh, input_mesh); MutableSpan<MVert> mesh_verts = mesh->verts_for_write(); MutableSpan<MPoly> polys = mesh->polys_for_write(); MutableSpan<MLoop> loops = mesh->loops_for_write(); @@ -273,7 +274,9 @@ Mesh *BKE_mesh_remesh_voxel(const Mesh *mesh, { #ifdef WITH_OPENVDB openvdb::FloatGrid::Ptr level_set = remesh_voxel_level_set_create(mesh, voxel_size); - return remesh_voxel_volume_to_mesh(level_set, isovalue, adaptivity, false); + Mesh *result = remesh_voxel_volume_to_mesh(level_set, isovalue, adaptivity, false); + BKE_mesh_copy_parameters(result, mesh); + return result; #else UNUSED_VARS(mesh, voxel_size, adaptivity, isovalue); return nullptr; diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 9457c20eb7d..da508ff865c 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1241,7 +1241,7 @@ static NlaStrip *nlastrip_find_active(ListBase /* NlaStrip */ *strips) float BKE_nlastrip_compute_frame_from_previous_strip(NlaStrip *strip) { - float limit_prev = MINFRAMEF; + float limit_prev = MINAFRAMEF; /* Find the previous end frame, with a special case if the previous strip was a transition : */ if (strip->prev) { diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 2ae0b456b0d..b82cf30416a 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -71,6 +71,7 @@ #include "NOD_composite.h" #include "NOD_function.h" #include "NOD_geometry.h" +#include "NOD_geometry_nodes_lazy_function.hh" #include "NOD_node_declaration.hh" #include "NOD_shader.h" #include "NOD_socket.h" diff --git a/source/blender/blenkernel/intern/node_runtime.cc b/source/blender/blenkernel/intern/node_runtime.cc index a8281820a0b..00b78284791 100644 --- a/source/blender/blenkernel/intern/node_runtime.cc +++ b/source/blender/blenkernel/intern/node_runtime.cc @@ -10,8 +10,22 @@ #include "BLI_task.hh" #include "BLI_timeit.hh" +#include "NOD_geometry_nodes_lazy_function.hh" + namespace blender::bke::node_tree_runtime { +void handle_node_tree_output_changed(bNodeTree &tree_cow) +{ + if (tree_cow.type == NTREE_GEOMETRY) { + /* Rebuild geometry nodes lazy function graph. */ + { + std::lock_guard lock{tree_cow.runtime->geometry_nodes_lazy_function_graph_info_mutex}; + tree_cow.runtime->geometry_nodes_lazy_function_graph_info.reset(); + } + blender::nodes::ensure_geometry_nodes_lazy_function_graph(tree_cow); + } +} + static void double_checked_lock(std::mutex &mutex, bool &data_is_dirty, FunctionRef<void()> fn) { if (!data_is_dirty) { @@ -36,11 +50,15 @@ static void update_node_vector(const bNodeTree &ntree) { bNodeTreeRuntime &tree_runtime = *ntree.runtime; tree_runtime.nodes.clear(); + tree_runtime.group_nodes.clear(); tree_runtime.has_undefined_nodes_or_sockets = false; LISTBASE_FOREACH (bNode *, node, &ntree.nodes) { node->runtime->index_in_tree = tree_runtime.nodes.append_and_get_index(node); node->runtime->owner_tree = const_cast<bNodeTree *>(&ntree); tree_runtime.has_undefined_nodes_or_sockets |= node->typeinfo == &NodeTypeUndefined; + if (node->is_group()) { + tree_runtime.group_nodes.append(node); + } } } diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 7c96c463339..901b42ac0b2 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -526,21 +526,27 @@ static void unpack_generate_paths(const char *name, BLI_strncpy(tempdir, "//", sizeof(tempdir)); } - switch (id_type) { - case ID_VF: - BLI_snprintf(r_relpath, relpathlen, "//fonts/%s", tempname); - break; - case ID_SO: - BLI_snprintf(r_relpath, relpathlen, "//sounds/%s", tempname); - break; - case ID_IM: - BLI_snprintf(r_relpath, relpathlen, "//textures/%s", tempname); - break; - case ID_VO: - BLI_snprintf(r_relpath, relpathlen, "//volumes/%s", tempname); - break; - default: - break; + { + const char *dir_name = NULL; + switch (id_type) { + case ID_VF: + dir_name = "fonts"; + break; + case ID_SO: + dir_name = "sounds"; + break; + case ID_IM: + dir_name = "textures"; + break; + case ID_VO: + dir_name = "volumes"; + break; + default: + break; + } + if (dir_name) { + BLI_path_join(r_relpath, relpathlen, "//", dir_name, tempname, NULL); + } } { diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index d277bbcca63..1a1bf285847 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1088,10 +1088,10 @@ bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint) Sculpt *data = MEM_cnew<Sculpt>(__func__); paint = &data->paint; - /* Turn on X plane mirror symmetry by default */ + /* Turn on X plane mirror symmetry by default. */ paint->symmetry_flags |= PAINT_SYMM_X; - /* Make sure at least dyntopo subdivision is enabled */ + /* Make sure at least dyntopo subdivision is enabled. */ data->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE; } else if ((GpPaint **)r_paint == &ts->gp_paint) { @@ -1146,7 +1146,7 @@ void BKE_paint_init(Main *bmain, Scene *sce, ePaintMode mode, const uchar col[3] brush = BKE_brush_first_search(bmain, ob_mode); if (!brush) { brush = BKE_brush_add(bmain, "Brush", ob_mode); - id_us_min(&brush->id); /* fake user only */ + id_us_min(&brush->id); /* Fake user only. */ } BKE_paint_brush_set(paint, brush); } @@ -1247,18 +1247,17 @@ void BKE_paint_blend_read_lib(BlendLibReader *reader, Scene *sce, Paint *p) } } -bool paint_is_face_hidden(const MLoopTri *lt, const bool *hide_vert, const MLoop *mloop) +bool paint_is_face_hidden(const MLoopTri *lt, const bool *hide_poly) { - if (!hide_vert) { + if (!hide_poly) { return false; } - return ((hide_vert[mloop[lt->tri[0]].v]) || (hide_vert[mloop[lt->tri[1]].v]) || - (hide_vert[mloop[lt->tri[2]].v])); + return hide_poly[lt->poly]; } bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int y) { - /* skip face if any of its corners are hidden */ + /* Skip face if any of its corners are hidden. */ return (BLI_BITMAP_TEST(grid_hidden, y * gridsize + x) || BLI_BITMAP_TEST(grid_hidden, y * gridsize + x + 1) || BLI_BITMAP_TEST(grid_hidden, (y + 1) * gridsize + x + 1) || @@ -1288,7 +1287,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, uint level, uint x, uint y return gpm->data[(y * factor) * gridsize + (x * factor)]; } -/* threshold to move before updating the brush rotation */ +/* Threshold to move before updating the brush rotation. */ #define RAKE_THRESHHOLD 20 void paint_update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, float rotation) @@ -1331,8 +1330,8 @@ bool paint_calculate_rake_rotation(UnifiedPaintSettings *ups, paint_update_brush_rake_rotation(ups, brush, rotation); ok = true; } - /* make sure we reset here to the last rotation to avoid accumulating - * values in case a random rotation is also added */ + /* Make sure we reset here to the last rotation to avoid accumulating + * values in case a random rotation is also added. */ else { paint_update_brush_rake_rotation(ups, brush, ups->last_rake_angle); ok = false; @@ -1528,20 +1527,29 @@ void BKE_sculptsession_free(Object *ob) } } -MultiresModifierData *BKE_sculpt_multires_active(const Scene *scene, Object *ob) +static MultiresModifierData *sculpt_multires_modifier_get(const Scene *scene, + Object *ob, + const bool auto_create_mdisps) { Mesh *me = (Mesh *)ob->data; ModifierData *md; VirtualModifierData virtualModifierData; if (ob->sculpt && ob->sculpt->bm) { - /* can't combine multires and dynamic topology */ + /* Can't combine multires and dynamic topology. */ return nullptr; } + bool need_mdisps = false; + if (!CustomData_get_layer(&me->ldata, CD_MDISPS)) { - /* multires can't work without displacement layer */ - return nullptr; + if (!auto_create_mdisps) { + /* Multires can't work without displacement layer. */ + return nullptr; + } + else { + need_mdisps = true; + } } /* Weight paint operates on original vertices, and needs to treat multires as regular modifier @@ -1559,6 +1567,10 @@ MultiresModifierData *BKE_sculpt_multires_active(const Scene *scene, Object *ob) } if (mmd->sculptlvl > 0 && !(mmd->flags & eMultiresModifierFlag_UseSculptBaseMesh)) { + if (need_mdisps) { + CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, me->totloop); + } + return mmd; } @@ -1569,6 +1581,11 @@ MultiresModifierData *BKE_sculpt_multires_active(const Scene *scene, Object *ob) return nullptr; } +MultiresModifierData *BKE_sculpt_multires_active(const Scene *scene, Object *ob) +{ + return sculpt_multires_modifier_get(scene, ob, false); +} + /* Checks if there are any supported deformation modifiers active */ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) { @@ -1580,14 +1597,14 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) return false; } - /* non-locked shape keys could be handled in the same way as deformed mesh */ + /* Non-locked shape keys could be handled in the same way as deformed mesh. */ if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr) { return true; } md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); - /* exception for shape keys because we can edit those */ + /* Exception for shape keys because we can edit those. */ for (; md; md = md->next) { const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type)); if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { @@ -1614,22 +1631,15 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) return false; } -/** - * \param need_mask: So that the evaluated mesh that is returned has mask data. - */ -static void sculpt_update_object(Depsgraph *depsgraph, - Object *ob, - Object *ob_eval, - bool need_pmap, - bool need_mask, - bool is_paint_tool) +static void sculpt_update_object( + Depsgraph *depsgraph, Object *ob, Object *ob_eval, bool need_pmap, bool is_paint_tool) { Scene *scene = DEG_get_input_scene(depsgraph); Sculpt *sd = scene->toolsettings->sculpt; SculptSession *ss = ob->sculpt; Mesh *me = BKE_object_get_original_mesh(ob); Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); - MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); + MultiresModifierData *mmd = sculpt_multires_modifier_get(scene, ob, true); const bool use_face_sets = (ob->mode & OB_MODE_SCULPT) != 0; BLI_assert(me_eval != nullptr); @@ -1644,15 +1654,6 @@ static void sculpt_update_object(Depsgraph *depsgraph, ss->scene = scene; - if (need_mask) { - if (mmd == nullptr) { - BLI_assert(CustomData_has_layer(&me->vdata, CD_PAINT_MASK)); - } - else { - BLI_assert(CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)); - } - } - ss->shapekey_active = (mmd == nullptr) ? BKE_keyblock_from_object(ob) : nullptr; /* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path, @@ -1708,7 +1709,6 @@ static void sculpt_update_object(Depsgraph *depsgraph, /* Sculpt Face Sets. */ if (use_face_sets) { - BLI_assert(CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)); ss->face_sets = static_cast<int *>(CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS)); } else { @@ -1841,24 +1841,7 @@ static void sculpt_update_object(Depsgraph *depsgraph, } } -static void sculpt_face_sets_ensure(Mesh *mesh) -{ - if (CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) { - return; - } - - int *new_face_sets = static_cast<int *>(CustomData_add_layer( - &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, nullptr, mesh->totpoly)); - - /* Initialize the new Face Set data-layer with a default valid visible ID and set the default - * color to render it white. */ - for (int i = 0; i < mesh->totpoly; i++) { - new_face_sets[i] = 1; - } - mesh->face_sets_color_default = 1; -} - -void BKE_sculpt_update_object_before_eval(const Scene *scene, Object *ob_eval) +void BKE_sculpt_update_object_before_eval(Object *ob_eval) { /* Update before mesh evaluation in the dependency graph. */ SculptSession *ss = ob_eval->sculpt; @@ -1888,16 +1871,6 @@ void BKE_sculpt_update_object_before_eval(const Scene *scene, Object *ob_eval) MEM_freeN(nodes); } } - - if (ss) { - Object *ob_orig = DEG_get_original_object(ob_eval); - Mesh *mesh = BKE_object_get_original_mesh(ob_orig); - MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob_orig); - - /* Ensure attribute layout is still correct. */ - sculpt_face_sets_ensure(mesh); - BKE_sculpt_mask_layers_ensure(ob_orig, mmd); - } } void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval) @@ -1906,7 +1879,7 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval) * other data when modifiers change the mesh. */ Object *ob_orig = DEG_get_original_object(ob_eval); - sculpt_update_object(depsgraph, ob_orig, ob_eval, false, false, false); + sculpt_update_object(depsgraph, ob_orig, ob_eval, false, false); } void BKE_sculpt_color_layer_create_if_needed(Object *object) @@ -1944,13 +1917,53 @@ void BKE_sculpt_color_layer_create_if_needed(Object *object) } void BKE_sculpt_update_object_for_edit( - Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool need_mask, bool is_paint_tool) + Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool /*need_mask*/, bool is_paint_tool) { BLI_assert(ob_orig == DEG_get_original_object(ob_orig)); Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_orig); - sculpt_update_object(depsgraph, ob_orig, ob_eval, need_pmap, need_mask, is_paint_tool); + sculpt_update_object(depsgraph, ob_orig, ob_eval, need_pmap, is_paint_tool); +} + +int *BKE_sculpt_face_sets_ensure(Mesh *mesh) +{ + using namespace blender; + using namespace blender::bke; + if (CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) { + return static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)); + } + + const AttributeAccessor attributes = mesh->attributes_for_write(); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + + MutableSpan<int> face_sets = { + static_cast<int *>(CustomData_add_layer( + &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, nullptr, mesh->totpoly)), + mesh->totpoly}; + + /* Initialize the new face sets with a default valid visible ID and set the default + * color to render it white. */ + if (hide_poly.is_single() && !hide_poly.get_internal_single()) { + face_sets.fill(1); + } + else { + const int face_sets_default_visible_id = 1; + const int face_sets_default_hidden_id = -2; + + const VArraySpan<bool> hide_poly_span{hide_poly}; + for (const int i : face_sets.index_range()) { + /* Assign a new hidden ID to hidden faces. This way we get at initial split in two Face Sets + * between hidden and visible faces based on the previous mesh visibly from other mode that + * can be useful in some cases. */ + face_sets[i] = hide_poly_span[i] ? face_sets_default_hidden_id : + face_sets_default_visible_id; + } + } + + mesh->face_sets_color_default = 1; + return face_sets.data(); } int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) @@ -2014,7 +2027,7 @@ int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) ret |= SCULPT_MASK_LAYER_CALC_LOOP; } - /* create vertex paint mask layer if there isn't one already */ + /* Create vertex paint mask layer if there isn't one already. */ if (!paint_mask) { CustomData_add_layer(&me->vdata, CD_PAINT_MASK, CD_SET_DEFAULT, nullptr, me->totvert); ret |= SCULPT_MASK_LAYER_CALC_VERT; @@ -2038,7 +2051,7 @@ void BKE_sculpt_toolsettings_data_ensure(Scene *scene) sd->constant_detail = 3.0f; } - /* Set sane default tiling offsets */ + /* Set sane default tiling offsets. */ if (!sd->paint.tile_offset[0]) { sd->paint.tile_offset[0] = 1.0f; } @@ -2056,8 +2069,7 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc /* Active modifiers means extra deformation, which can't be handled correct * on birth of PBVH and sculpt "layer" levels, so use PBVH only for internal brush - * stuff and show final evaluated mesh so user would see actual object shape. - */ + * stuff and show final evaluated mesh so user would see actual object shape. */ deformed |= object->sculpt->deform_modifiers_active; if (for_construction) { @@ -2066,75 +2078,55 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc else { /* As in case with modifiers, we can't synchronize deformation made against * PBVH and non-locked keyblock, so also use PBVH only for brushes and - * final DM to give final result to user. - */ + * final DM to give final result to user. */ deformed |= object->sculpt->shapekey_active && (object->shapeflag & OB_SHAPE_LOCK) == 0; } return deformed; } -void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(Mesh *mesh) +void BKE_sculpt_face_sets_update_from_base_mesh_visibility(Mesh *mesh) { - const int face_sets_default_visible_id = 1; - const int face_sets_default_hidden_id = -(face_sets_default_visible_id + 1); - - bool initialize_new_face_sets = false; - - if (CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) { - /* Make everything visible. */ - int *current_face_sets = static_cast<int *>( - CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)); - for (int i = 0; i < mesh->totpoly; i++) { - current_face_sets[i] = abs(current_face_sets[i]); - } - } - else { - initialize_new_face_sets = true; - int *new_face_sets = static_cast<int *>(CustomData_add_layer( - &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, nullptr, mesh->totpoly)); - - /* Initialize the new Face Set data-layer with a default valid visible ID and set the default - * color to render it white. */ - for (int i = 0; i < mesh->totpoly; i++) { - new_face_sets[i] = face_sets_default_visible_id; - } - mesh->face_sets_color_default = face_sets_default_visible_id; + using namespace blender; + using namespace blender::bke; + if (!CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) { + return; } - int *face_sets = static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)); - const bool *hide_poly = (const bool *)CustomData_get_layer_named( - &mesh->pdata, CD_PROP_BOOL, ".hide_poly"); + const AttributeAccessor attributes = mesh->attributes(); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + if (hide_poly.is_single() && !hide_poly.get_internal_single()) { + return; + } - for (int i = 0; i < mesh->totpoly; i++) { - if (!(hide_poly && hide_poly[i])) { - continue; - } + MutableSpan<int> face_sets{ + static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)), mesh->totpoly}; - if (initialize_new_face_sets) { - /* When initializing a new Face Set data-layer, assign a new hidden Face Set ID to hidden - * vertices. This way, we get at initial split in two Face Sets between hidden and - * visible vertices based on the previous mesh visibly from other mode that can be - * useful in some cases. */ - face_sets[i] = face_sets_default_hidden_id; - } - else { - /* Otherwise, set the already existing Face Set ID to hidden. */ - face_sets[i] = -abs(face_sets[i]); - } + for (const int i : hide_poly.index_range()) { + face_sets[i] = hide_poly[i] ? -std::abs(face_sets[i]) : std::abs(face_sets[i]); } } -void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh) +static void set_hide_poly_from_face_sets(Mesh &mesh) { + using namespace blender; using namespace blender::bke; - const int *face_sets = static_cast<const int *>( - CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)); - if (!face_sets) { + if (!CustomData_has_layer(&mesh.pdata, CD_SCULPT_FACE_SETS)) { + return; + } + + const Span<int> face_sets{ + static_cast<const int *>(CustomData_get_layer(&mesh.pdata, CD_SCULPT_FACE_SETS)), + mesh.totpoly}; + + MutableAttributeAccessor attributes = mesh.attributes_for_write(); + if (std::all_of( + face_sets.begin(), face_sets.end(), [&](const int value) { return value > 0; })) { + attributes.remove(".hide_poly"); return; } - MutableAttributeAccessor attributes = mesh->attributes_for_write(); SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>( ".hide_poly", ATTR_DOMAIN_FACE); if (!hide_poly) { @@ -2144,7 +2136,11 @@ void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh) hide_poly.span[i] = face_sets[i] < 0; } hide_poly.finish(); +} +void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh) +{ + set_hide_poly_from_face_sets(*mesh); BKE_mesh_flush_hidden_from_polys(mesh); } @@ -2182,41 +2178,29 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv void BKE_sculpt_sync_face_set_visibility(Mesh *mesh, SubdivCCG *subdiv_ccg) { - BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(mesh); + BKE_sculpt_face_sets_update_from_base_mesh_visibility(mesh); BKE_sculpt_sync_face_sets_visibility_to_base_mesh(mesh); BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, subdiv_ccg); } -void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object) +void BKE_sculpt_ensure_orig_mesh_data(Object *object) { Mesh *mesh = BKE_mesh_from_object(object); - MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, object); - BLI_assert(object->mode == OB_MODE_SCULPT); /* Copy the current mesh visibility to the Face Sets. */ - BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(mesh); - if (object->sculpt != nullptr) { - /* If a sculpt session is active, ensure we have its face-set data properly up-to-date. */ - object->sculpt->face_sets = static_cast<int *>( - CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)); - - /* NOTE: In theory we could add that on the fly when required by sculpt code. - * But this then requires proper update of depsgraph etc. For now we play safe, optimization is - * always possible later if it's worth it. */ - BKE_sculpt_mask_layers_ensure(object, mmd); - } + BKE_sculpt_face_sets_update_from_base_mesh_visibility(mesh); /* Tessfaces aren't used and will become invalid. */ BKE_mesh_tessface_clear(mesh); /* We always need to flush updates from depsgraph here, since at the very least - * `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer of + * `BKE_sculpt_face_sets_update_from_base_mesh_visibility()` will have updated some data layer of * the mesh. * * All known potential sources of updates: * - Addition of, or changes to, the `CD_SCULPT_FACE_SETS` data layer - * (`BKE_sculpt_face_sets_ensure_from_base_mesh_visibility`). + * (`BKE_sculpt_face_sets_update_from_base_mesh_visibility`). * - Addition of a `CD_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`). * - Object has any active modifier (modifier stack can be different in Sculpt mode). * - Multires: diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 6d761f56f13..2e273e076d5 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -285,7 +285,7 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node) } if (has_visible == false) { - if (!paint_is_face_hidden(lt, pbvh->hide_vert, pbvh->mloop)) { + if (!paint_is_face_hidden(lt, pbvh->hide_poly)) { has_visible = true; } } @@ -552,6 +552,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, pbvh->mesh = mesh; pbvh->header.type = PBVH_FACES; pbvh->mpoly = mpoly; + pbvh->hide_poly = (bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"); pbvh->material_indices = (const int *)CustomData_get_layer_named( &mesh->pdata, CD_PROP_INT32, "material_index"); pbvh->mloop = mloop; @@ -1313,11 +1314,7 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata, } case PBVH_FACES: node->draw_buffers = GPU_pbvh_mesh_buffers_build( - pbvh->mesh, - pbvh->looptri, - CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS), - node->prim_indices, - node->totprim); + pbvh->mesh, pbvh->looptri, node->prim_indices, node->totprim); break; case PBVH_BMESH: node->draw_buffers = GPU_pbvh_bmesh_buffers_build(pbvh->flags & @@ -2293,7 +2290,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh, const MLoopTri *lt = &pbvh->looptri[faces[i]]; const int *face_verts = node->face_vert_indices[i]; - if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_vert, mloop)) { + if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_poly)) { continue; } @@ -2602,7 +2599,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh, const MLoopTri *lt = &pbvh->looptri[faces[i]]; const int *face_verts = node->face_vert_indices[i]; - if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_vert, mloop)) { + if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_poly)) { continue; } @@ -3219,6 +3216,12 @@ const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh) return pbvh->hide_vert; } +const bool *BKE_pbvh_get_poly_hide(const PBVH *pbvh) +{ + BLI_assert(pbvh->header.type == PBVH_FACES); + return pbvh->hide_poly; +} + bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh) { BLI_assert(pbvh->header.type == PBVH_FACES); @@ -3244,6 +3247,14 @@ void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets) pbvh->face_sets = face_sets; } +void BKE_pbvh_update_hide_attributes_from_mesh(PBVH *pbvh) +{ + if (pbvh->header.type == PBVH_FACES) { + pbvh->hide_vert = CustomData_get_layer_named(&pbvh->mesh->vdata, CD_PROP_BOOL, ".hide_vert"); + pbvh->hide_poly = CustomData_get_layer_named(&pbvh->mesh->pdata, CD_PROP_BOOL, ".hide_poly"); + } +} + void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide) { pbvh->respect_hide = respect_hide; diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index b848327b7a9..8ab56839f9c 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -156,6 +156,7 @@ struct PBVH { bool *hide_vert; struct MVert *verts; const struct MPoly *mpoly; + bool *hide_poly; /** Material indices. Only valid for polygon meshes. */ const int *material_indices; const struct MLoop *mloop; diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc index fe6353bc72d..b45e164b594 100644 --- a/source/blender/blenkernel/intern/pointcloud.cc +++ b/source/blender/blenkernel/intern/pointcloud.cc @@ -189,8 +189,9 @@ IDTypeInfo IDType_ID_PT = { static void pointcloud_random(PointCloud *pointcloud) { + BLI_assert(pointcloud->totpoint == 0); pointcloud->totpoint = 400; - CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint); + CustomData_realloc(&pointcloud->pdata, 0, pointcloud->totpoint); RNG *rng = BLI_rng_new(0); @@ -238,9 +239,6 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint) nullptr, ID_PT, BKE_idtype_idcode_to_name(ID_PT), LIB_ID_CREATE_LOCALIZE)); pointcloud_init_data(&pointcloud->id); - - pointcloud->totpoint = totpoint; - CustomData_add_layer_named(&pointcloud->pdata, CD_PROP_FLOAT, CD_SET_DEFAULT, @@ -248,8 +246,8 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint) pointcloud->totpoint, POINTCLOUD_ATTR_RADIUS); + CustomData_realloc(&pointcloud->pdata, 0, totpoint); pointcloud->totpoint = totpoint; - CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint); return pointcloud; } |