Blender V4.3
BLI_math_vector.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
11#include <cmath>
12#include <type_traits>
13
14#include "BLI_math_base.hh"
16#include "BLI_span.hh"
17#include "BLI_utildefines.h"
18
19namespace blender::math {
20
25template<typename T, int Size>
26[[nodiscard]] inline bool almost_equal_relative(const VecBase<T, Size> &a,
27 const VecBase<T, Size> &b,
28 const T &epsilon_factor)
29{
30 for (int i = 0; i < Size; i++) {
31 const float epsilon = epsilon_factor * math::abs(a[i]);
32 if (math::distance(a[i], b[i]) > epsilon) {
33 return false;
34 }
35 }
36 return true;
37}
38
39template<typename T, int Size> [[nodiscard]] inline VecBase<T, Size> abs(const VecBase<T, Size> &a)
40{
42 for (int i = 0; i < Size; i++) {
43 result[i] = a[i] >= 0 ? a[i] : -a[i];
44 }
45 return result;
46}
47
51template<typename T, int Size>
52[[nodiscard]] inline VecBase<T, Size> sign(const VecBase<T, Size> &a)
53{
55}
56
57template<typename T, int Size>
62
63template<typename T, int Size>
68
69template<typename T, int Size>
70[[nodiscard]] inline VecBase<T, Size> clamp(const VecBase<T, Size> &a,
71 const VecBase<T, Size> &min,
72 const VecBase<T, Size> &max)
73{
74 VecBase<T, Size> result = a;
75 for (int i = 0; i < Size; i++) {
76 result[i] = math::clamp(result[i], min[i], max[i]);
77 }
78 return result;
79}
80
81template<typename T, int Size>
82[[nodiscard]] inline VecBase<T, Size> clamp(const VecBase<T, Size> &a, const T &min, const T &max)
83{
84 VecBase<T, Size> result = a;
85 for (int i = 0; i < Size; i++) {
86 result[i] = math::clamp(result[i], min, max);
87 }
88 return result;
89}
90
91template<typename T, int Size>
92[[nodiscard]] inline VecBase<T, Size> step(const VecBase<T, Size> &edge,
93 const VecBase<T, Size> &value)
94{
96}
97
98template<typename T, int Size>
99[[nodiscard]] inline VecBase<T, Size> step(const T &edge, const VecBase<T, Size> &value)
100{
101 VecBase<T, Size> result = value;
102 for (int i = 0; i < Size; i++) {
103 result[i] = math::step(edge, result[i]);
104 }
105 return result;
106}
107
108template<typename T, int Size>
109[[nodiscard]] inline VecBase<T, Size> mod(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
110{
112}
113
114template<typename T, int Size>
115[[nodiscard]] inline VecBase<T, Size> mod(const VecBase<T, Size> &a, const T &b)
116{
117 BLI_assert(b != 0);
119 for (int i = 0; i < Size; i++) {
120 result[i] = math::mod(a[i], b);
121 }
122 return result;
123}
124
128template<typename T, int Size>
134
138template<typename T, int Size>
139[[nodiscard]] inline VecBase<T, Size> safe_mod(const VecBase<T, Size> &a, const T &b)
140{
141 if (b == 0) {
142 return VecBase<T, Size>(0);
143 }
145 for (int i = 0; i < Size; i++) {
146 result[i] = math::mod(a[i], b);
147 }
148 return result;
149}
150
155template<typename T, int Size>
156[[nodiscard]] inline VecBase<T, Size> pow(const VecBase<T, Size> &x, const T &y)
157{
159 for (int i = 0; i < Size; i++) {
160 result[i] = math::pow(x[i], y);
161 }
162 return result;
163}
164
169template<typename T, int Size>
170[[nodiscard]] inline VecBase<T, Size> pow(const VecBase<T, Size> &x, const VecBase<T, Size> &y)
171{
173}
174
176template<typename T, int Size>
177[[nodiscard]] inline VecBase<T, Size> square(const VecBase<T, Size> &a)
178{
180}
181
182/* Per-element exponent. */
183template<typename T, int Size> [[nodiscard]] inline VecBase<T, Size> exp(const VecBase<T, Size> &x)
184{
186}
187
193template<typename T, int Size>
195 const VecBase<T, Size> &b)
196{
198 for (int i = 0; i < Size; i++) {
199 BLI_assert(a[i] >= 0);
200 BLI_assert(b[i] > 0);
201 result[i] = ((a[i] + b[i] - 1) / b[i]) * b[i];
202 }
203 return result;
204}
205
210template<typename T, int Size>
211[[nodiscard]] inline VecBase<T, Size> divide_ceil(const VecBase<T, Size> &a,
212 const VecBase<T, Size> &b)
213{
215 for (int i = 0; i < Size; i++) {
216 BLI_assert(a[i] >= 0);
217 BLI_assert(b[i] > 0);
218 result[i] = (a[i] + b[i] - 1) / b[i];
219 }
220 return result;
221}
222
223template<typename T, int Size>
225{
227 max = math::max(vector, max);
228}
229
233template<typename T, int Size>
239
243template<typename T, int Size>
244[[nodiscard]] inline VecBase<T, Size> safe_divide(const VecBase<T, Size> &a, const T &b)
245{
246 return (b != 0) ? a / b : VecBase<T, Size>(0.0f);
247}
248
249template<typename T, int Size>
250[[nodiscard]] inline VecBase<T, Size> floor(const VecBase<T, Size> &a)
251{
253}
254
255template<typename T, int Size>
256[[nodiscard]] inline VecBase<T, Size> round(const VecBase<T, Size> &a)
257{
259}
260
261template<typename T, int Size>
262[[nodiscard]] inline VecBase<T, Size> ceil(const VecBase<T, Size> &a)
263{
265}
266
271template<typename T, int Size>
272[[nodiscard]] inline VecBase<T, Size> sqrt(const VecBase<T, Size> &a)
273{
275}
276
281template<typename T, int Size>
282[[nodiscard]] inline VecBase<T, Size> safe_sqrt(const VecBase<T, Size> &a)
283{
285 for (int i = 0; i < Size; i++) {
286 result[i] = a[i] >= T(0) ? math ::sqrt(a[i]) : T(0);
287 }
288 return result;
289}
290
295template<typename T, int Size> [[nodiscard]] inline VecBase<T, Size> rcp(const VecBase<T, Size> &a)
296{
298}
299
304template<typename T, int Size>
309
310template<typename T, int Size>
311[[nodiscard]] inline VecBase<T, Size> fract(const VecBase<T, Size> &a)
312{
314}
315
322template<typename T, int Size>
323[[nodiscard]] inline T dot(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
324{
325 T result = a[0] * b[0];
326 for (int i = 1; i < Size; i++) {
327 result += a[i] * b[i];
328 }
329 return result;
330}
331
335template<typename T, int Size> [[nodiscard]] inline T length_manhattan(const VecBase<T, Size> &a)
336{
337 T result = math::abs(a[0]);
338 for (int i = 1; i < Size; i++) {
339 result += math::abs(a[i]);
340 }
341 return result;
342}
343
344template<typename T, int Size> [[nodiscard]] inline T length_squared(const VecBase<T, Size> &a)
345{
346 return dot(a, a);
347}
348
349template<typename T, int Size> [[nodiscard]] inline T length(const VecBase<T, Size> &a)
350{
351 return math::sqrt(length_squared(a));
352}
353
355template<typename T, int Size> [[nodiscard]] inline bool is_unit_scale(const VecBase<T, Size> &v)
356{
357 /* Checks are flipped so NAN doesn't assert because we're making sure the value was
358 * normalized and in the case we don't want NAN to be raising asserts since there
359 * is nothing to be done in that case. */
360 const T test_unit = math::length_squared(v);
361 return (!(math::abs(test_unit - T(1)) >= AssertUnitEpsilon<T>::value) ||
362 !(math::abs(test_unit) >= AssertUnitEpsilon<T>::value));
363}
364
365template<typename T, int Size>
366[[nodiscard]] inline T distance_manhattan(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
367{
368 return length_manhattan(a - b);
369}
370
371template<typename T, int Size>
372[[nodiscard]] inline T distance_squared(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
373{
374 return length_squared(a - b);
375}
376
377template<typename T, int Size>
378[[nodiscard]] inline T distance(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
379{
380 return length(a - b);
381}
382
383template<typename T, int Size>
384[[nodiscard]] inline VecBase<T, Size> reflect(const VecBase<T, Size> &incident,
385 const VecBase<T, Size> &normal)
386{
387 BLI_assert(is_unit_scale(normal));
388 return incident - 2.0 * dot(normal, incident) * normal;
389}
390
391template<typename T, int Size>
392[[nodiscard]] inline VecBase<T, Size> refract(const VecBase<T, Size> &incident,
393 const VecBase<T, Size> &normal,
394 const T &eta)
395{
396 float dot_ni = dot(normal, incident);
397 float k = 1.0f - eta * eta * (1.0f - dot_ni * dot_ni);
398 if (k < 0.0f) {
399 return VecBase<T, Size>(0.0f);
400 }
401 return eta * incident - (eta * dot_ni + sqrt(k)) * normal;
402}
403
408template<typename T, int Size>
409[[nodiscard]] inline VecBase<T, Size> project(const VecBase<T, Size> &p,
410 const VecBase<T, Size> &v_proj)
411{
412 if (UNLIKELY(is_zero(v_proj))) {
413 return VecBase<T, Size>(0.0f);
414 }
415 return v_proj * (dot(p, v_proj) / dot(v_proj, v_proj));
416}
417
418template<typename T, int Size>
420 T &out_length)
421{
422 out_length = length_squared(v);
423 /* A larger value causes normalize errors in a scaled down models with camera extreme close. */
424 constexpr T threshold = std::is_same_v<T, double> ? 1.0e-70 : 1.0e-35f;
425 if (out_length > threshold) {
426 out_length = sqrt(out_length);
427 return v / out_length;
428 }
429 /* Either the vector is small or one of it's values contained `nan`. */
430 out_length = 0.0;
431 return VecBase<T, Size>(0.0);
432}
433
434template<typename T, int Size>
435[[nodiscard]] inline VecBase<T, Size> normalize(const VecBase<T, Size> &v)
436{
437 T len;
439}
440
449template<typename T>
450[[nodiscard]] inline VecBase<T, 3> cross(const VecBase<T, 3> &a, const VecBase<T, 3> &b)
451{
452 return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
453}
454
459 const VecBase<float, 3> &b)
460{
461 return {float(double(a.y) * double(b.z) - double(a.z) * double(b.y)),
462 float(double(a.z) * double(b.x) - double(a.x) * double(b.z)),
463 float(double(a.x) * double(b.y) - double(a.y) * double(b.x))};
464}
465
471template<typename T> [[nodiscard]] inline VecBase<T, 3> cross_poly(Span<VecBase<T, 3>> poly)
472{
473 /* Newell's Method. */
474 int nv = int(poly.size());
475 if (nv < 3) {
476 return VecBase<T, 3>(0, 0, 0);
477 }
478 const VecBase<T, 3> *v_prev = &poly[nv - 1];
479 const VecBase<T, 3> *v_curr = &poly[0];
480 VecBase<T, 3> n(0, 0, 0);
481 for (int i = 0; i < nv;) {
482 n[0] = n[0] + ((*v_prev)[1] - (*v_curr)[1]) * ((*v_prev)[2] + (*v_curr)[2]);
483 n[1] = n[1] + ((*v_prev)[2] - (*v_curr)[2]) * ((*v_prev)[0] + (*v_curr)[0]);
484 n[2] = n[2] + ((*v_prev)[0] - (*v_curr)[0]) * ((*v_prev)[1] + (*v_curr)[1]);
485 v_prev = v_curr;
486 ++i;
487 if (i < nv) {
488 v_curr = &poly[i];
489 }
490 }
491 return n;
492}
493
498template<typename T>
499[[nodiscard]] inline VecBase<T, 3> cross_tri(const VecBase<T, 3> &v1,
500 const VecBase<T, 3> &v2,
501 const VecBase<T, 3> &v3)
502{
503 return cross(v1 - v2, v2 - v3);
504}
505
510template<typename T>
511[[nodiscard]] inline VecBase<T, 3> normal_tri(const VecBase<T, 3> &v1,
512 const VecBase<T, 3> &v2,
513 const VecBase<T, 3> &v3)
514{
515 return normalize(cross_tri(v1, v2, v3));
516}
517
523template<typename T, typename FactorT, int Size>
524[[nodiscard]] inline VecBase<T, Size> interpolate(const VecBase<T, Size> &a,
525 const VecBase<T, Size> &b,
526 const FactorT &t)
527{
528 return a * (1 - t) + b * t;
529}
530
534template<typename T, int Size>
535[[nodiscard]] inline VecBase<T, Size> midpoint(const VecBase<T, Size> &a,
536 const VecBase<T, Size> &b)
537{
538 return (a + b) * 0.5;
539}
540
544template<typename T, int Size>
546 const VecBase<T, Size> &incident,
547 const VecBase<T, Size> &reference)
548{
549 return (dot(reference, incident) < 0) ? vector : -vector;
550}
551
555template<typename T> [[nodiscard]] inline int dominant_axis(const VecBase<T, 3> &a)
556{
557 VecBase<T, 3> b = abs(a);
558 return ((b.x > b.y) ? ((b.x > b.z) ? 0 : 2) : ((b.y > b.z) ? 1 : 2));
559}
560
564template<typename T, int Size> [[nodiscard]] inline T reduce_max(const VecBase<T, Size> &a)
565{
566 T result = a[0];
567 for (int i = 1; i < Size; i++) {
568 if (a[i] > result) {
569 result = a[i];
570 }
571 }
572 return result;
573}
574
578template<typename T, int Size> [[nodiscard]] inline T reduce_min(const VecBase<T, Size> &a)
579{
580 T result = a[0];
581 for (int i = 1; i < Size; i++) {
582 if (a[i] < result) {
583 result = a[i];
584 }
585 }
586 return result;
587}
588
592template<typename T, int Size> [[nodiscard]] inline T reduce_add(const VecBase<T, Size> &a)
593{
594 T result = a[0];
595 for (int i = 1; i < Size; i++) {
596 result += a[i];
597 }
598 return result;
599}
600
604template<typename T, int Size> [[nodiscard]] inline T reduce_mul(const VecBase<T, Size> &a)
605{
606 T result = a[0];
607 for (int i = 1; i < Size; i++) {
608 result *= a[i];
609 }
610 return result;
611}
612
616template<typename T, int Size> [[nodiscard]] inline T average(const VecBase<T, Size> &a)
617{
618 return reduce_add(a) * (T(1) / T(Size));
619}
620
626template<typename T> [[nodiscard]] inline VecBase<T, 3> orthogonal(const VecBase<T, 3> &v)
627{
628 const int axis = dominant_axis(v);
629 switch (axis) {
630 case 0:
631 return {-v.y - v.z, v.x, v.x};
632 case 1:
633 return {v.y, -v.x - v.z, v.y};
634 case 2:
635 return {v.z, v.z, -v.x - v.y};
636 }
637 return v;
638}
639
644template<typename T> [[nodiscard]] inline VecBase<T, 2> orthogonal(const VecBase<T, 2> &v)
645{
646 return {-v.y, v.x};
647}
648
652template<typename T, int Size>
653[[nodiscard]] inline bool is_equal(const VecBase<T, Size> &a,
654 const VecBase<T, Size> &b,
655 const T epsilon = T(0))
656{
657 for (int i = 0; i < Size; i++) {
658 if (math::abs(a[i] - b[i]) > epsilon) {
659 return false;
660 }
661 }
662 return true;
663}
664
671template<typename T, int Size>
672[[nodiscard]] inline bool is_zero(const VecBase<T, Size> &a, const T epsilon = T(0))
673{
674 for (int i = 0; i < Size; i++) {
675 if (math::abs(a[i]) > epsilon) {
676 return false;
677 }
678 }
679 return true;
680}
681
685template<typename T, int Size> [[nodiscard]] inline bool is_any_zero(const VecBase<T, Size> &a)
686{
687 for (int i = 0; i < Size; i++) {
688 if (a[i] == T(0)) {
689 return true;
690 }
691 }
692 return false;
693}
694
699template<typename T, int Size>
700[[nodiscard]] inline bool is_unit(const VecBase<T, Size> &a,
701 const T epsilon = T(10) * std::numeric_limits<T>::epsilon())
702{
703 const T length = length_squared(a);
704 return math::abs(length - T(1)) <= epsilon;
705}
706
709template<typename T> struct isect_result {
710 enum {
716 typename T::base_type lambda;
717};
718
719template<typename T, int Size>
721 const VecBase<T, Size> &v2,
722 const VecBase<T, Size> &v3,
723 const VecBase<T, Size> &v4);
724
725} // namespace blender::math
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_UNROLL_MATH_VEC_FUNC_VEC_VEC(op, a, b)
#define BLI_UNROLL_MATH_VEC_OP_VEC(op, a)
#define UNLIKELY(x)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a vector
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
local_group_size(16, 16) .push_constant(Type b
int len
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define T
T length_squared(const VecBase< T, Size > &a)
VecBase< T, 3 > normal_tri(const VecBase< T, 3 > &v1, const VecBase< T, 3 > &v2, const VecBase< T, 3 > &v3)
T pow(const T &x, const T &power)
T clamp(const T &a, const T &min, const T &max)
T safe_rcp(const T &a)
bool is_any_zero(const T &a)
T sqrt(const T &a)
T safe_divide(const T &a, const T &b)
T sign(const T &a)
T floor(const T &a)
VecBase< T, Size > project(const VecBase< T, Size > &p, const VecBase< T, Size > &v_proj)
T reduce_max(const VecBase< T, Size > &a)
isect_result< VecBase< T, Size > > isect_seg_seg(const VecBase< T, Size > &v1, const VecBase< T, Size > &v2, const VecBase< T, Size > &v3, const VecBase< T, Size > &v4)
T distance(const T &a, const T &b)
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T exp(const T &x)
VecBase< float, 3 > cross_high_precision(const VecBase< float, 3 > &a, const VecBase< float, 3 > &b)
QuaternionBase< T > normalize_and_get_length(const QuaternionBase< T > &q, T &out_length)
bool is_unit_scale(const MatBase< T, NumCol, NumRow > &m)
T length_manhattan(const VecBase< T, Size > &a)
T reduce_min(const VecBase< T, Size > &a)
T average(const VecBase< T, Size > &a)
T min(const T &a, const T &b)
T step(const T &edge, const T &value)
bool is_zero(const T &a)
T midpoint(const T &a, const T &b)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
T safe_mod(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
T fract(const T &a)
VecBase< T, 3 > cross_tri(const VecBase< T, 3 > &v1, const VecBase< T, 3 > &v2, const VecBase< T, 3 > &v3)
T rcp(const T &a)
void min_max(const T &value, T &min, T &max)
T reduce_mul(const VecBase< T, Size > &a)
VecBase< T, Size > refract(const VecBase< T, Size > &incident, const VecBase< T, Size > &normal, const T &eta)
T square(const T &a)
VecBase< T, Size > faceforward(const VecBase< T, Size > &vector, const VecBase< T, Size > &incident, const VecBase< T, Size > &reference)
T ceil(const T &a)
bool almost_equal_relative(const VecBase< T, Size > &a, const VecBase< T, Size > &b, const T &epsilon_factor)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T distance_manhattan(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
bool is_equal(const MatBase< T, NumCol, NumRow > &a, const MatBase< T, NumCol, NumRow > &b, const T epsilon=T(0))
VecBase< T, 3 > orthogonal(const VecBase< T, 3 > &v)
int dominant_axis(const VecBase< T, 3 > &a)
VecBase< T, Size > reflect(const VecBase< T, Size > &incident, const VecBase< T, Size > &normal)
VecBase< T, Size > ceil_to_multiple(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T max(const T &a, const T &b)
T mod(const T &a, const T &b)
bool is_unit(const VecBase< T, Size > &a, const T epsilon=T(10) *std::numeric_limits< T >::epsilon())
T abs(const T &a)
T round(const T &a)
VecBase< T, 3 > cross_poly(Span< VecBase< T, 3 > > poly)
T reduce_add(const VecBase< T, Size > &a)
VecBase< T, Size > safe_sqrt(const VecBase< T, Size > &a)
#define min(a, b)
Definition sort.c:32
enum blender::math::isect_result::@111 kind
float max