diff options
Diffstat (limited to 'source/blender/blenlib/intern')
-rw-r--r-- | source/blender/blenlib/intern/bitmap.c | 20 | ||||
-rw-r--r-- | source/blender/blenlib/intern/filereader_zstd.c | 5 | ||||
-rw-r--r-- | source/blender/blenlib/intern/generic_virtual_array.cc | 114 | ||||
-rw-r--r-- | source/blender/blenlib/intern/index_mask.cc | 5 | ||||
-rw-r--r-- | source/blender/blenlib/intern/length_parameterize.cc | 150 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_base_inline.c | 10 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_matrix.c | 16 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_rotation.c | 49 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_rotation.cc | 13 | ||||
-rw-r--r-- | source/blender/blenlib/intern/mesh_boolean.cc | 32 | ||||
-rw-r--r-- | source/blender/blenlib/intern/rct.c | 4 | ||||
-rw-r--r-- | source/blender/blenlib/intern/timeit.cc | 18 |
12 files changed, 294 insertions, 142 deletions
diff --git a/source/blender/blenlib/intern/bitmap.c b/source/blender/blenlib/intern/bitmap.c index 7fcbc31c066..2cc2fbc3e2f 100644 --- a/source/blender/blenlib/intern/bitmap.c +++ b/source/blender/blenlib/intern/bitmap.c @@ -11,6 +11,7 @@ #include <string.h> #include "BLI_bitmap.h" +#include "BLI_math_bits.h" #include "BLI_utildefines.h" void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits) @@ -46,3 +47,22 @@ void BLI_bitmap_or_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits) dst[i] |= src[i]; } } + +int BLI_bitmap_find_first_unset(const BLI_bitmap *bitmap, const size_t bits) +{ + const size_t blocks_num = _BITMAP_NUM_BLOCKS(bits); + int result = -1; + /* Skip over completely set blocks. */ + int index = 0; + while (index < blocks_num && bitmap[index] == ~0u) { + index++; + } + if (index < blocks_num) { + /* Found a partially used block: find the lowest unused bit. */ + const uint m = ~bitmap[index]; + BLI_assert(m != 0); + const uint bit_index = bitscan_forward_uint(m); + result = bit_index + (index << _BITMAP_POWER); + } + return result; +} diff --git a/source/blender/blenlib/intern/filereader_zstd.c b/source/blender/blenlib/intern/filereader_zstd.c index 5f114f24fb0..aeb000e9754 100644 --- a/source/blender/blenlib/intern/filereader_zstd.c +++ b/source/blender/blenlib/intern/filereader_zstd.c @@ -281,7 +281,10 @@ static void zstd_close(FileReader *reader) if (zstd->reader.seek) { MEM_freeN(zstd->seek.uncompressed_ofs); MEM_freeN(zstd->seek.compressed_ofs); - MEM_freeN(zstd->seek.cached_content); + /* When an error has occurred this may be NULL, see: T99744. */ + if (zstd->seek.cached_content) { + MEM_freeN(zstd->seek.cached_content); + } } else { MEM_freeN((void *)zstd->in_buf.src); diff --git a/source/blender/blenlib/intern/generic_virtual_array.cc b/source/blender/blenlib/intern/generic_virtual_array.cc index 624af3c6ed1..f66b1e14fc6 100644 --- a/source/blender/blenlib/intern/generic_virtual_array.cc +++ b/source/blender/blenlib/intern/generic_virtual_array.cc @@ -284,11 +284,18 @@ template<int BufferSize> class GVArrayImpl_For_SmallTrivialSingleValue : public /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArray_GSpan +/** \name #GVArraySpan * \{ */ -GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray)) +GVArraySpan::GVArraySpan() = default; + +GVArraySpan::GVArraySpan(GVArray varray) + : GSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray)) { + if (!varray_) { + return; + } + size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { @@ -301,7 +308,27 @@ GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std } } -GVArray_GSpan::~GVArray_GSpan() +GVArraySpan::GVArraySpan(GVArraySpan &&other) + : GSpan(other.type_ptr()), varray_(std::move(other.varray_)), owned_data_(other.owned_data_) +{ + if (!varray_) { + return; + } + + size_ = varray_.size(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + data_ = info.data; + } + else { + data_ = owned_data_; + } + other.owned_data_ = nullptr; + other.data_ = nullptr; + other.size_ = 0; +} + +GVArraySpan::~GVArraySpan() { if (owned_data_ != nullptr) { type_->destruct_n(owned_data_, size_); @@ -309,15 +336,30 @@ GVArray_GSpan::~GVArray_GSpan() } } +GVArraySpan &GVArraySpan::operator=(GVArraySpan &&other) +{ + if (this == &other) { + return *this; + } + std::destroy_at(this); + new (this) GVArraySpan(std::move(other)); + return *this; +} + /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVMutableArray_GSpan +/** \name #GMutableVArraySpan * \{ */ -GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool copy_values_to_span) - : GMutableSpan(varray.type()), varray_(std::move(varray)) +GMutableVArraySpan::GMutableVArraySpan() = default; + +GMutableVArraySpan::GMutableVArraySpan(GVMutableArray varray, const bool copy_values_to_span) + : GMutableSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray)) { + if (!varray_) { + return; + } size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); if (info.type == CommonVArrayInfo::Type::Span) { @@ -335,11 +377,35 @@ GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool cop } } -GVMutableArray_GSpan::~GVMutableArray_GSpan() +GMutableVArraySpan::GMutableVArraySpan(GMutableVArraySpan &&other) + : GMutableSpan(other.type_ptr()), + varray_(std::move(other.varray_)), + owned_data_(other.owned_data_), + show_not_saved_warning_(other.show_not_saved_warning_) { - if (show_not_saved_warning_) { - if (!save_has_been_called_) { - std::cout << "Warning: Call `apply()` to make sure that changes persist in all cases.\n"; + if (!varray_) { + return; + } + size_ = varray_.size(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + data_ = const_cast<void *>(info.data); + } + else { + data_ = owned_data_; + } + other.owned_data_ = nullptr; + other.data_ = nullptr; + other.size_ = 0; +} + +GMutableVArraySpan::~GMutableVArraySpan() +{ + if (varray_) { + if (show_not_saved_warning_) { + if (!save_has_been_called_) { + std::cout << "Warning: Call `save()` to make sure that changes persist in all cases.\n"; + } } } if (owned_data_ != nullptr) { @@ -348,7 +414,17 @@ GVMutableArray_GSpan::~GVMutableArray_GSpan() } } -void GVMutableArray_GSpan::save() +GMutableVArraySpan &GMutableVArraySpan::operator=(GMutableVArraySpan &&other) +{ + if (this == &other) { + return *this; + } + std::destroy_at(this); + new (this) GMutableVArraySpan(std::move(other)); + return *this; +} + +void GMutableVArraySpan::save() { save_has_been_called_ = true; if (data_ != owned_data_) { @@ -357,11 +433,16 @@ void GVMutableArray_GSpan::save() varray_.set_all(owned_data_); } -void GVMutableArray_GSpan::disable_not_applied_warning() +void GMutableVArraySpan::disable_not_applied_warning() { show_not_saved_warning_ = false; } +const GVMutableArray &GMutableVArraySpan::varray() const +{ + return varray_; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -633,6 +714,15 @@ GVArray GVArray::ForEmpty(const CPPType &type) GVArray GVArray::slice(IndexRange slice) const { + const CommonVArrayInfo info = this->common_info(); + if (info.type == CommonVArrayInfo::Type::Single) { + return GVArray::ForSingle(this->type(), slice.size(), info.data); + } + /* Need to check for ownership, because otherwise the referenced data can be destructed when + * #this is destructed. */ + if (info.type == CommonVArrayInfo::Type::Span && !info.may_have_ownership) { + return GVArray::ForSpan(GSpan(this->type(), info.data, this->size()).slice(slice)); + } return GVArray::For<GVArrayImpl_For_SlicedGVArray>(*this, slice); } diff --git a/source/blender/blenlib/intern/index_mask.cc b/source/blender/blenlib/intern/index_mask.cc index f3590e4a41c..e9af183d60d 100644 --- a/source/blender/blenlib/intern/index_mask.cc +++ b/source/blender/blenlib/intern/index_mask.cc @@ -142,6 +142,7 @@ IndexMask find_indices_based_on_predicate__merge( int64_t result_mask_size = 0; for (Vector<Vector<int64_t>> &local_sub_masks : sub_masks) { for (Vector<int64_t> &sub_mask : local_sub_masks) { + BLI_assert(!sub_mask.is_empty()); all_vectors.append(&sub_mask); result_mask_size += sub_mask.size(); } @@ -232,7 +233,9 @@ IndexMask find_indices_from_virtual_array(const IndexMask indices_to_check, } } }); - sub_masks.local().append(std::move(masked_indices)); + if (!masked_indices.is_empty()) { + sub_masks.local().append(std::move(masked_indices)); + } }); return detail::find_indices_based_on_predicate__merge(indices_to_check, sub_masks, r_indices); diff --git a/source/blender/blenlib/intern/length_parameterize.cc b/source/blender/blenlib/intern/length_parameterize.cc index 7c0fc860b53..06cca281510 100644 --- a/source/blender/blenlib/intern/length_parameterize.cc +++ b/source/blender/blenlib/intern/length_parameterize.cc @@ -1,144 +1,58 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_length_parameterize.hh" +#include "BLI_task.hh" namespace blender::length_parameterize { -void create_uniform_samples(const Span<float> lengths, - const bool cyclic, - MutableSpan<int> indices, - MutableSpan<float> factors) +void sample_uniform(const Span<float> lengths, + const bool include_last_point, + MutableSpan<int> r_segment_indices, + MutableSpan<float> r_factors) { - const int count = indices.size(); + const int count = r_segment_indices.size(); BLI_assert(count > 0); BLI_assert(lengths.size() >= 1); BLI_assert(std::is_sorted(lengths.begin(), lengths.end())); - const int segments_num = lengths.size(); - const int points_num = cyclic ? segments_num : segments_num + 1; - indices.first() = 0; - factors.first() = 0.0f; if (count == 1) { + r_segment_indices[0] = 0; + r_factors[0] = 0.0f; return; } - const float total_length = lengths.last(); - if (total_length == 0.0f) { - indices.fill(0); - factors.fill(0.0f); - return; - } - - const float step_length = total_length / (count - (cyclic ? 0 : 1)); - const float step_length_inv = 1.0f / step_length; - - int i_dst = 1; - /* Store the length at the previous point in a variable so it can start out at zero - * (the lengths array doesn't contain 0 for the first point). */ - float prev_length = 0.0f; - for (const int i_src : IndexRange(points_num - 1)) { - const float next_length = lengths[i_src]; - const float segment_length = next_length - prev_length; - if (segment_length == 0.0f) { - continue; - } - /* Add every sample that fits in this segment. */ - const float segment_length_inv = 1.0f / segment_length; - const int segment_samples_num = std::ceil(next_length * step_length_inv - i_dst); - indices.slice(i_dst, segment_samples_num).fill(i_src); - - for (const int i : factors.index_range().slice(i_dst, segment_samples_num)) { - const float length_in_segment = step_length * i - prev_length; - factors[i] = length_in_segment * segment_length_inv; - } - - i_dst += segment_samples_num; - - prev_length = next_length; - } - - /* Add the samples on the last cyclic segment if necessary, and also the samples - * that weren't created in the previous loop due to floating point inaccuracy. */ - if (cyclic && lengths.size() > 1) { - indices.drop_front(i_dst).fill(points_num - 1); - const float segment_length = lengths.last() - lengths.last(1); - if (segment_length == 0.0f) { - return; - } - const float segment_length_inv = 1.0f / segment_length; - for (const int i : indices.index_range().drop_front(i_dst)) { - const float length_in_segment = step_length * i - prev_length; - factors[i] = length_in_segment * segment_length_inv; + const float step_length = total_length / (count - include_last_point); + threading::parallel_for(IndexRange(count), 512, [&](const IndexRange range) { + SampleSegmentHint hint; + for (const int i : range) { + /* Use minimum to avoid issues with floating point accuracy. */ + const float sample_length = std::min(total_length, i * step_length); + sample_at_length(lengths, sample_length, r_segment_indices[i], r_factors[i], &hint); } - } - else { - indices.drop_front(i_dst).fill(points_num - 2); - factors.drop_front(i_dst).fill(1.0f); - } + }); } -void create_samples_from_sorted_lengths(const Span<float> lengths, - const Span<float> sample_lengths, - const bool cyclic, - MutableSpan<int> indices, - MutableSpan<float> factors) +void sample_at_lengths(const Span<float> accumulated_segment_lengths, + const Span<float> sample_lengths, + MutableSpan<int> r_segment_indices, + MutableSpan<float> r_factors) { - BLI_assert(std::is_sorted(lengths.begin(), lengths.end())); + BLI_assert( + std::is_sorted(accumulated_segment_lengths.begin(), accumulated_segment_lengths.end())); BLI_assert(std::is_sorted(sample_lengths.begin(), sample_lengths.end())); - BLI_assert(indices.size() == sample_lengths.size()); - BLI_assert(indices.size() == factors.size()); - const int segments_num = lengths.size(); - const int points_num = cyclic ? segments_num : segments_num + 1; - const float total_length = lengths.last(); - if (total_length == 0.0f) { - indices.fill(0); - factors.fill(0.0f); - return; - } + const int count = sample_lengths.size(); + BLI_assert(count == r_segment_indices.size()); + BLI_assert(count == r_factors.size()); - int i_dst = 0; - /* Store the length at the previous point in a variable so it can start out at zero - * (the lengths array doesn't contain 0 for the first point). */ - float prev_length = 0.0f; - for (const int i_src : IndexRange(points_num - 1)) { - const float next_length = lengths[i_src]; - const float segment_length = next_length - prev_length; - if (segment_length == 0.0f) { - continue; - } - /* Add every sample that fits in this segment. It's also necessary to check if the last sample - * has been reached, since there is no upper bound on the number of samples in each segment. */ - const float segment_length_inv = 1.0f / segment_length; - while (i_dst < sample_lengths.size() && sample_lengths[i_dst] < next_length) { - const float length_in_segment = sample_lengths[i_dst] - prev_length; - const float factor = length_in_segment * segment_length_inv; - indices[i_dst] = i_src; - factors[i_dst] = factor; - i_dst++; + threading::parallel_for(IndexRange(count), 512, [&](const IndexRange range) { + SampleSegmentHint hint; + for (const int i : range) { + const float sample_length = sample_lengths[i]; + sample_at_length( + accumulated_segment_lengths, sample_length, r_segment_indices[i], r_factors[i], &hint); } - - prev_length = next_length; - } - - /* Add the samples on the last cyclic segment if necessary, and also the samples - * that weren't created in the previous loop due to floating point inaccuracy. */ - if (cyclic && lengths.size() > 1) { - const float segment_length = lengths.last() - lengths.last(1); - while (sample_lengths[i_dst] < total_length) { - const float length_in_segment = sample_lengths[i_dst] - prev_length; - const float factor = length_in_segment / segment_length; - indices[i_dst] = points_num - 1; - factors[i_dst] = factor; - i_dst++; - } - indices.drop_front(i_dst).fill(points_num - 1); - factors.drop_front(i_dst).fill(1.0f); - } - else { - indices.drop_front(i_dst).fill(points_num - 2); - factors.drop_front(i_dst).fill(1.0f); - } + }); } } // namespace blender::length_parameterize diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index cb7659a7059..fb71e84c23e 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -370,6 +370,11 @@ MINLINE uint divide_ceil_u(uint a, uint b) return (a + b - 1) / b; } +MINLINE uint64_t divide_ceil_ul(uint64_t a, uint64_t b) +{ + return (a + b - 1) / b; +} + /** * Returns \a a if it is a multiple of \a b or the next multiple or \a b after \b a . */ @@ -378,6 +383,11 @@ MINLINE uint ceil_to_multiple_u(uint a, uint b) return divide_ceil_u(a, b) * b; } +MINLINE uint64_t ceil_to_multiple_ul(uint64_t a, uint64_t b) +{ + return divide_ceil_ul(a, b) * b; +} + MINLINE int mod_i(int i, int n) { return (i % n + n) % n; diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index ce9abc36cad..fcd017b3082 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -1116,6 +1116,22 @@ double determinant_m3_array_db(const double m[3][3]) m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1])); } +bool invert_m2_m2(float m1[2][2], const float m2[2][2]) +{ + adjoint_m2_m2(m1, m2); + float det = determinant_m2(m2[0][0], m2[1][0], m2[0][1], m2[1][1]); + + bool success = (det != 0.0f); + if (success) { + m1[0][0] /= det; + m1[1][0] /= det; + m1[0][1] /= det; + m1[1][1] /= det; + } + + return success; +} + bool invert_m3_ex(float m[3][3], const float epsilon) { float tmp[3][3]; diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 92223bdf1d5..f0bfc7c21e1 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -915,6 +915,55 @@ float tri_to_quat(float q[4], const float a[3], const float b[3], const float c[ return len; } +void sin_cos_from_fraction(const int numerator, const int denominator, float *r_sin, float *r_cos) +{ + BLI_assert((numerator <= denominator) && (denominator > 0)); + if ((denominator & 3) == 0) { + const int denominator_4 = denominator / 4; + if (numerator <= denominator_4) { + /* Fall through. */ + } + else { + if (numerator <= denominator_4 * 2) { + const float phi = (float)(2.0 * M_PI) * + ((float)(numerator - denominator_4) / (float)denominator); + *r_sin = cosf(phi); + *r_cos = -sinf(phi); + } + else if (numerator <= denominator_4 * 3) { + const float phi = (float)(2.0 * M_PI) * + ((float)(numerator - (denominator_4 * 2)) / (float)denominator); + *r_sin = -sinf(phi); + *r_cos = -cosf(phi); + } + else { + const float phi = (float)(2.0 * M_PI) * + ((float)(numerator - (denominator_4 * 3)) / (float)denominator); + *r_cos = sinf(phi); + *r_sin = -cosf(phi); + } + return; + } + } + else if ((denominator & 1) == 0) { + const int denominator_2 = denominator / 2; + if (numerator <= denominator_2) { + /* Fall through. */ + } + else { + const float phi = (float)(2.0 * M_PI) * + ((float)(numerator - denominator_2) / (float)denominator); + *r_sin = -sinf(phi); + *r_cos = -cosf(phi); + return; + } + } + + const float phi = (float)(2.0 * M_PI) * ((float)numerator / (float)denominator); + *r_sin = sinf(phi); + *r_cos = cosf(phi); +} + void print_qt(const char *str, const float q[4]) { printf("%s: %.3f %.3f %.3f %.3f\n", str, q[0], q[1], q[2], q[3]); diff --git a/source/blender/blenlib/intern/math_rotation.cc b/source/blender/blenlib/intern/math_rotation.cc index 74300d55954..091e8af85d9 100644 --- a/source/blender/blenlib/intern/math_rotation.cc +++ b/source/blender/blenlib/intern/math_rotation.cc @@ -23,4 +23,17 @@ float3 rotate_direction_around_axis(const float3 &direction, const float3 &axis, return axis_scaled + diff * std::cos(angle) + cross * std::sin(angle); } +float3 rotate_around_axis(const float3 &vector, + const float3 ¢er, + const float3 &axis, + const float angle) + +{ + float3 result = vector - center; + float mat[3][3]; + axis_angle_normalized_to_mat3(mat, axis, angle); + mul_m3_v3(mat, result); + return result + center; +} + } // namespace blender::math diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 700c126ca4c..d4586f95fe0 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -2966,6 +2966,11 @@ static std::ostream &operator<<(std::ostream &os, const FaceMergeState &fms) * \a tris all have the same original face. * Find the 2d edge/triangle topology for these triangles, but only the ones facing in the * norm direction, and whether each edge is dissolvable or not. + * If we did the initial triangulation properly, and any Delaunay triangulations of interections + * properly, then each triangle edge should have at most one neighbor. + * However, there can be anonalies. For example, if an input face is self-intersecting, we fall + * back on the floating poing polyfill triangulation, which, after which all bets are off. + * Hence, try to be tolerant of such unexpected topology. */ static void init_face_merge_state(FaceMergeState *fms, const Vector<int> &tris, @@ -3053,16 +3058,35 @@ static void init_face_merge_state(FaceMergeState *fms, std::cout << "me.v1 == mf.vert[i] so set edge[" << me_index << "].left_face = " << f << "\n"; } - BLI_assert(me.left_face == -1); - fms->edge[me_index].left_face = f; + if (me.left_face != -1) { + /* Unexpected in the normal case: this means more than one triangle shares this + * edge in the same orientation. But be tolerant of this case. By making this + * edge not dissolvable, we'll avoid future problems due to this non-manifold topology. + */ + if (dbg_level > 1) { + std::cout << "me.left_face was already occupied, so triangulation wasn't good\n"; + } + me.dissolvable = false; + } + else { + fms->edge[me_index].left_face = f; + } } else { if (dbg_level > 1) { std::cout << "me.v1 != mf.vert[i] so set edge[" << me_index << "].right_face = " << f << "\n"; } - BLI_assert(me.right_face == -1); - fms->edge[me_index].right_face = f; + if (me.right_face != -1) { + /* Unexpected, analogous to the me.left_face != -1 case above. */ + if (dbg_level > 1) { + std::cout << "me.right_face was already occupied, so triangulation wasn't good\n"; + } + me.dissolvable = false; + } + else { + fms->edge[me_index].right_face = f; + } } fms->face[f].edge.append(me_index); } diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index 0bb606c288e..7248db5b718 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -265,7 +265,7 @@ bool BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2]) /* diagonal: [/] */ tvec1[0] = rect->xmin; tvec1[1] = rect->ymin; - tvec2[0] = rect->xmin; + tvec2[0] = rect->xmax; tvec2[1] = rect->ymax; if (isect_segments_i(s1, s2, tvec1, tvec2)) { return true; @@ -311,7 +311,7 @@ bool BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[ /* diagonal: [/] */ tvec1[0] = rect->xmin; tvec1[1] = rect->ymin; - tvec2[0] = rect->xmin; + tvec2[0] = rect->xmax; tvec2[1] = rect->ymax; if (isect_segments_fl(s1, s2, tvec1, tvec2)) { return true; diff --git a/source/blender/blenlib/intern/timeit.cc b/source/blender/blenlib/intern/timeit.cc index f11f9c4ad94..7a8cf8da038 100644 --- a/source/blender/blenlib/intern/timeit.cc +++ b/source/blender/blenlib/intern/timeit.cc @@ -3,19 +3,29 @@ #include "BLI_timeit.hh" #include <algorithm> +#include <iomanip> namespace blender::timeit { void print_duration(Nanoseconds duration) { - if (duration < std::chrono::microseconds(100)) { + using namespace std::chrono; + if (duration < microseconds(100)) { std::cout << duration.count() << " ns"; } - else if (duration < std::chrono::seconds(5)) { - std::cout << duration.count() / 1.0e6 << " ms"; + else if (duration < seconds(5)) { + std::cout << std::fixed << std::setprecision(1) << duration.count() / 1.0e6 << " ms"; + } + else if (duration > seconds(90)) { + /* Long durations: print seconds, and also H:m:s */ + const auto dur_hours = duration_cast<hours>(duration); + const auto dur_mins = duration_cast<minutes>(duration - dur_hours); + const auto dur_sec = duration_cast<seconds>(duration - dur_hours - dur_mins); + std::cout << std::fixed << std::setprecision(1) << duration.count() / 1.0e9 << " s (" + << dur_hours.count() << "H:" << dur_mins.count() << "m:" << dur_sec.count() << "s)"; } else { - std::cout << duration.count() / 1.0e9 << " s"; + std::cout << std::fixed << std::setprecision(1) << duration.count() / 1.0e9 << " s"; } } |