Reference identifiers instead of "above" in code comments as these
tends to become outdated. Even when declarations are removed it's at
least clear that the reference no longer exists instead of referring to
whatever is currently above the declaration.
It's also straightforward to search history for a removed identifier.
Corrected 4 cases of references to things that were no longer above
the doc-strings. Noticed other references which look to be incorrect
but need further investigation.
Fix of conversion identity quaternion to axis angle. Basically,
if the length of the imaginary part-vector is zero, it is
incorrect to normalize it. Simple identity should be returned.
Pull Request: https://projects.blender.org/blender/blender/pulls/119762
All official Blender platforms use the SIMD code path, with pow() approximations
for 2.4 and 1/2.4 powers. The non-SIMD code path would only be used on other
platforms like PowerPC etc. Make that fallback scalar code path use the same
math approximation for consistency. This is part of #121312.
This also makes srgb_to_linearrgb_v3_v3 and linearrgb_to_srgb_v3_v3 functions
non-inlined. They are 50-100 CPU instructions, and thus hardly good candidates
for forced inlining into each and every call site.
Also _bli_math_blend_sse now uses actual SSE4 blend instruction instead of doing
it in a roundabout way.
Pull Request: https://projects.blender.org/blender/blender/pulls/121368
Factors out utility function "does the path contain any hidden file/folder
components?" function out of innards of UI code (edit_file,
is_hidden_dot_filename) into a BLI function BLI_path_has_hidden_component
and then:
- Adds unit test coverage to it, which uncovered some inconsistencies
- Fix the behavior inconsistencies:
- A path component that is just a dot (.), was not considered hidden.
Unless it was the first folder component (now this is fixed).
- A path component that ended in a tilde (~) was considered hidden.
Unless it was the first folder component (now this is fixed).
- Speedup the function by not doing several recursive scans over the
string; instead all the logic is done in a single string scan.
Synthetic HasHiddenComponents_Performance test: 6.0s -> 1.1s for 50M calls
on Mac M1 Max.
More real world test (setup as in #120494): out of whole build_catalog_tree
time, the time taken by BLI_path_has_hidden_component drops from 37% down
to 28%
Pull Request: https://projects.blender.org/blender/blender/pulls/120541
Previously, this conversion would often result in invalid quaternions or
hit an assert in `normalized_to_quat_fast`. It's not super nice to convert
to euler as an intermediate step performance wise, but it seems to be
the easiest solution for now. Extracting rotations from matrices should
not be done all that often anyway.
Pull Request: https://projects.blender.org/blender/blender/pulls/120568
The `IndexMask` class already had a static function `from_union`.
This adds two new functions `from_difference` and `from_intersection`
as well as tests for each of them.
It also uses `from_intersection` in two grease pencil utility functions.
Pull Request: https://projects.blender.org/blender/blender/pulls/120419
Previously the hulls edges were simply iterated over causing the
rotating calipers to step over points 4x as many times as is needed.
Avoid this by adding angle stepping logic that maps all angles to a
single quadrant, reducing the checks needed to advance the calipers
to each new angle. This gives ~1.4x speedup to AABB fitting logic.
Also add a test for octagon shapes to ensure axis aligned edges work
as expected.
Begin testing the edge edge between indices [0, 1] indices,
instead of [last, 0]. This only ever makes a difference as a tie breaker,
where [0, 1] is now prioritized.
This minor change simplifies further optimizations.
This is intended to be used in the new exact mesh boolean algorithm by @howardt.
The new `BLI_fixed_width_int.hh` header provides types like `Int256` and
`UInt256` which are like e.g. `uint64_t` but with higher precision. The code
supports many different integer sizes.
The following operations are supported:
* Addition
* Subtraction
* Multiplication
* Comparisons
* Negation
* Conversion to and from other number types
* Conversion to and from string (based on `GMP`)
Division is not implemented. It could be implemented, but it's more complex and
is not required for the new mesh boolean algorithm.
Some alternatives to having a custom implementation have been discussed in
https://devtalk.blender.org/t/fixed-length-multiprecision-arithmetic/29189/.
Generally, the implementation is fairly straight forward. The main complexity is
the addition/multiplication algorithm which isn't too complicated. It's nice to
have control over this part as it allows us to optimize the code more if
necessary. Also, from what I understand, we might be able to benefit from some
special cases like multiplying a large integer with a smaller one.
I tried some different ways to optimize this already, but so far the normal
compiler optimization turned out to work best. Not sure if the same is true on
windows though, as it doesn't have native support for an `int128` which helps
the compiler understand what I'm doing. Alternatives I tried so far are using
intrinsics directly (mainly `_addcarry_u64` and similar), writing inline
assembly manually and copying the assembly output from the compiler. I assume
the assembly implementation didn't help for me because it prohibited other
compiler optimizations.
Pull Request: https://projects.blender.org/blender/blender/pulls/119528
This patch adds clamped boundaries variants of the nearest interpolation
functions in the BLI module. The naming convention used by the bilinear
functions were followed.
Needed by #119414.
Pull Request: https://projects.blender.org/blender/blender/pulls/119732
The `IndexMask` data structure was designed to allow us to implement set
operations like `union`, `intersection` and `difference` efficiently
(2cfcb8b0b8). This patch adds an evaluator for
arbitrary expressions involving the mentioned operations. The evaluator makes
use of the design of the `IndexMask` data structure to be quite efficient.
In some common cases, the evaluator runs in constant time. So it's very fast
even if the mask contains many millions of indices. If possible the evaluator
works on entire segments at once instead of looking at the individual indices.
This results in a very low constant factor even if the evaluation time is
linear. If the evaluator has to look at the individual indices to be able to
perform the operation, it can make use of multi-threading.
The evaluation consists of the following steps:
1. A coarse evaluation that looks at entire segments at once.
2. All segments that couldn't be fully evaluated by the coarse evaluation are
evaluated exactly by looking at the actual indices. There are two evaluators
for this case. One that is based on `std::set_union` etc. The other one first
converts the index masks to bit spans, then does bit operations to evaluate
the expression, and then converts the bits back into indices. Depending on
the expression, one or the other can be more efficient.
3. Construct an index mask from the evaluated segments.
Showing the performance of the evaluator is kind of difficult because it highly
depends on the input data. Comparing the performance to something that does not
short-circuit when there are full ranges is meaningless, because one can
construct an example where the new evaluator is arbitrarily faster. I'm still
working on a case where performance can be compared to e.g. using
`std::set_union`. This comparison is only fair when the input data when
constructing a case where the new evaluator can't short-circuit.
One of the main remaining bottlenecks are the calls to `slice_content` on large
index masks. I think the impact of those can still be reduced.
We are not using this evaluator much yet, except through `IndexMask::complement`
calls. I intend to use it when I get to refactoring the field evaluator for
geometry nodes to optimize the evaluation of selections.
Pull Request: https://projects.blender.org/blender/blender/pulls/117805
This adds a new special purpose container data structure that can be
used to gather many elements into many (potentially small) lists efficiently.
I originally worked on this data structure because I might want to use it
in #118772. However, also it's useful in the geometry nodes logger already.
I'm measuring a 10-20% speed improvement in my many-math-nodes file
when I enable logging for all sockets (not just the ones that are currently visible).
Pull Request: https://projects.blender.org/blender/blender/pulls/118774
Unless you're very familiar with `IndexRange`, it's often hard to know what
e.g. `IndexRange(10, 15)` means. Without more context, one could think
that it means `10-14`, `10-15` or `10-24`. This patch adds named constructors
to `IndexRange` to make the behavior more obvious when writing and when
reading the code. With those one can use `IndexRange::from_begin_end(10, 15)`,
`IndexRange::from_begin_end_inclusive(10, 15)` or `IndexRange::from_begin_size(10, 15)`
respectively. While being a bit more verbose, the explicitness makes code easier to
understand and also allows abstracting away some common index computations.
The old unnamed constructor that takes a begin and size is not removed by this patch,
as that would make the patch significantly bigger. I think it's reasonable to generally
use the named constructors going forward and to change the existing usages of the
old constructor over time.
Pull Request: https://projects.blender.org/blender/blender/pulls/118606
Add some comments that clarify that `StringRefNull` can be compared with
other `StringRefNull` and with `StringRef` instances.
Add unit tests that cover these cases.
Pull Request: https://projects.blender.org/blender/blender/pulls/118515
The difficulty of implementing this iterator is that it requires lots of operator
overloads which are usually very simple to implement, but result in a lot of code.
The goal of this patch is to abstract the common parts so that it becomes easier
to implement random accessor iterators. Many algorithms can work more
efficiently with random access iterators than with other iterator types.
Also see https://en.cppreference.com/w/cpp/iterator/random_access_iterator
Pull Request: https://projects.blender.org/blender/blender/pulls/118113
The convex hull tests included a reference AABB-fitting function for
comparison which was used to validate the optimized implementation.
This wasn't great as it depended on matching exact return values and
didn't test the logic of AABB-fitting worked usefully.
Replace this with a more general test that creates random polygons with
known bounds, apply a random rotation & translation, then use
AABB-fitting to un-rotate the points, passing when the bounds are no
larger than the size of the generated input.
Details:
- Make BLI_convexhull_aabb_fit_hull_2d a static function again as it was
only exposed for tests. Use BLI_convexhull_aabb_fit_points_2d instead.
- Remove brute force reference implementation from tests,
moving this to an assertion within convexhull_2d
(disabled by default since it's quite slow).
Use EXPECT_NEAR instead of EXPECT_EQ to account for a differences in
atan2 implementation on macOS, more generally relying on exact
float comparison for tests is error prone.
Move BLI_convexhull_aabb_fit_points_2d to a public function to be able
to compare compare fitting one convex hull with a simple reference
method.
One test is disabled as it exposes an error in convex hull calculation
which needs further investigation.
The result of cross_poly_v2 was flipped compared with cross_tri_v2 &
cross_poly_v3 (with the Z values zeroed).
Ensure cross_poly_v2/3, cross_tri_v2/3 return compatible results and
updating the doc-strings noting that a negative Z is for clock-wise
polygons.
This adds two new constructors to `IndexMask`:
* `from_repeating(mask_to_repeat, repetitions, stride, initial_offset, memory)`:
It allows repeating an existing index mask with a stride.
* `from_every_nth(n, indices_num, initial_offset, memory)`: Creates an index
mask like `{0, 2, 4, 6, ...}`.
`from_every_nth` is implemented in terms of `from_repeating` which is optimized
to handle this case (and other cases) very efficiently.
Pull Request: https://projects.blender.org/blender/blender/pulls/118084
Previously, it was only possible to `find` a specific index in an `IndexMask`.
Now it's also possible to find the closest larger/smaller index if an exact
match doesn't exist. This could be used for slicing the mask so that it only
contains certain indices.
Pull Request: https://projects.blender.org/blender/blender/pulls/117852
isect_point_tri_v2 and isect_point_quad_v2 are handling tris/quads
in either clockwise or counter-clockwise vertex orderings. However,
for clockwise order it was considering points that lie on the edges
or vertices as "inside", whereas for counter-clockwise it was treating
them as "outside".
Visibly affected place is VSE: it has an optimization that checks
whether a fully opaque strip image fully covers the rendered area.
When the strip was scaled up to *exactly* cover the rendered area,
the check was failing since isect_point_quad_v2 was saying that a
point is outside the rect.
As far as I can tell, the functions have been "slightly wrong" in
this way for at least 15 years; harder to see through earlier
history in git.
Added a bunch of unit tests to cover this. Without the fix, "edge"
and "corner" cases against "cw" tri/quad were failing.
Performance (checked on clang15 on M1 Max):
- isect_point_tri_v2 is pretty much the same performance (assembly
several instructions shorter),
- isect_point_quad_v2 is about three times *faster* (assembly 2x
shorter), seemingly the compiler is able to use some SIMD now.
Pull Request: https://projects.blender.org/blender/blender/pulls/117786
Part of overall "improve image filtering situation" (#116980), this PR addresses
two issues:
- Bilinear (default) image filtering makes half a source pixel wide transparent
border around the image. This is very noticeable when scaling images/movies up
in VSE. However, when there is no scaling up but you have slightly rotated
image, this creates a "somewhat nice" anti-aliasing around the edge.
- The other filtering kinds (e.g. cubic) do not have this behavior. So they do
not create unexpected transparency when scaling up (yay), however for slightly
rotated images the edge is "jagged" (oh no).
More detail and images in PR.
Pull Request: https://projects.blender.org/blender/blender/pulls/117717
Part of overall "improve filtering situation" (#116980) task:
Add "Cubic Mitchell" filtering option to VSE strips. This is a cubic (4x4)
filter that generally looks better than bilinear, while not blurring the image
as much as the Cubic BSpline filter that exists elsewhere within Blender. It is
also default in many other apps.
Rename the (very recently added) VSE Bicubic filter option to Cubic BSpline.
Images in the PR.
Pull Request: https://projects.blender.org/blender/blender/pulls/117517
There exist a bunch of "give me a (filtered) image pixel at this location"
functions, some with duplicated functionality, some with almost the same but
not quite, some that look similar but behave slightly differently, etc.
Some of them were in BLI, some were in ImBuf.
This commit tries to improve the situation by:
* Adding low level interpolation functions to `BLI_math_interp.hh`
- With documentation on their behavior,
- And with more unit tests.
* At `ImBuf` level, there are only convenience inline wrappers to the above BLI
functions (split off into a separate header `IMB_interp.hh`). However, since
these wrappers are inline, some things get a tiny bit faster as a side
effect. E.g. VSE image strip, scaling to 4K resolution (Windows/Ryzen5950X):
- Nearest filter: 2.33 -> 1.94ms
- Bilinear filter: 5.83 -> 5.69ms
- Subsampled3x3 filter: 28.6 -> 22.4ms
Details on the functions:
- All of them have `_byte` and `_fl` suffixes.
- They exist in 4-channel byte (uchar4) and float (float4), as well as
explicitly passed amount of channels for other float images.
- New functions in BLI `blender::math` namespace:
- `interpolate_nearest`
- `interpolate_bilinear`
- `interpolate_bilinear_wrap`. Note that unlike previous "wrap" function,
this one no longer requires the caller to do their own wrapping.
- `interpolate_cubic_bspline`. Previous similar function was called just
"bicubic" which could mean many different things.
- Same functions exist in `IMB_interp.hh`, they are just convenience that takes
ImBuf and uses data pointer, width, height from that.
Other bits:
- Renamed `mod_f_positive` to `floored_fmod` (better matches `safe_floored_modf`
and `floored_modulo` that exist elsewhere), made it branchless and added more
unit tests.
- `interpolate_bilinear_wrap_fl` no longer clamps result to 0..1 range. Instead,
moved the clamp to be outside of the call in `paint_image_proj.cc` and
`paint_utils.cc`. Though the need for clamping in there is also questionable.
Pull Request: https://projects.blender.org/blender/blender/pulls/117387