2023-05-31 16:19:06 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2012-02-17 19:59:41 +01:00
|
|
|
#pragma once
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2019-02-17 22:08:12 +01:00
|
|
|
/** \file
|
|
|
|
* \ingroup bli
|
2011-02-18 14:58:08 +01:00
|
|
|
*/
|
|
|
|
|
2020-05-08 18:16:39 +02:00
|
|
|
#include "BLI_compiler_attrs.h"
|
|
|
|
#include "BLI_sys_types.h"
|
|
|
|
|
2009-11-09 23:42:41 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Init
|
|
|
|
* \{ */
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
void zero_m2(float m[2][2]);
|
|
|
|
void zero_m3(float m[3][3]);
|
|
|
|
void zero_m4(float m[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
void unit_m2(float m[2][2]);
|
|
|
|
void unit_m3(float m[3][3]);
|
|
|
|
void unit_m4(float m[4][4]);
|
2019-08-20 15:09:55 +02:00
|
|
|
void unit_m4_db(double m[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
void copy_m2_m2(float m1[2][2], const float m2[2][2]);
|
|
|
|
void copy_m3_m3(float m1[3][3], const float m2[3][3]);
|
|
|
|
void copy_m4_m4(float m1[4][4], const float m2[4][4]);
|
|
|
|
void copy_m3_m4(float m1[3][3], const float m2[4][4]);
|
|
|
|
void copy_m4_m3(float m1[4][4], const float m2[3][3]);
|
|
|
|
void copy_m3_m2(float m1[3][3], const float m2[2][2]);
|
|
|
|
void copy_m4_m2(float m1[4][4], const float m2[2][2]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2019-08-20 15:09:55 +02:00
|
|
|
void copy_m4_m4_db(double m1[4][4], const double m2[4][4]);
|
|
|
|
|
2013-10-20 14:08:51 +02:00
|
|
|
/* double->float */
|
2021-12-20 09:01:14 +01:00
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
void copy_m3_m3d(float m1[3][3], const double m2[3][3]);
|
2013-10-20 14:08:51 +02:00
|
|
|
|
2019-08-20 15:09:55 +02:00
|
|
|
/* float->double */
|
2021-12-20 09:01:14 +01:00
|
|
|
|
2020-11-21 14:06:02 +01:00
|
|
|
void copy_m3d_m3(double m1[3][3], const float m2[3][3]);
|
2020-09-04 20:59:13 +02:00
|
|
|
void copy_m4d_m4(double m1[4][4], const float m2[4][4]);
|
2019-08-20 15:09:55 +02:00
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
void swap_m3m3(float m1[3][3], float m2[3][3]);
|
|
|
|
void swap_m4m4(float m1[4][4], float m2[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2021-12-20 09:01:14 +01:00
|
|
|
/** Build index shuffle matrix. */
|
2020-07-13 11:27:09 +02:00
|
|
|
void shuffle_m4(float R[4][4], const int index[4]);
|
2020-02-15 01:49:50 +01:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Arithmetic
|
|
|
|
* \{ */
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2016-09-24 16:21:38 +02:00
|
|
|
void add_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
|
|
|
|
void add_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
|
2011-09-05 23:01:50 +02:00
|
|
|
|
2022-01-07 01:38:08 +01:00
|
|
|
void madd_m3_m3m3fl(float R[3][3], const float A[3][3], const float B[3][3], float f);
|
|
|
|
void madd_m4_m4m4fl(float R[4][4], const float A[4][4], const float B[4][4], float f);
|
2019-04-05 17:40:59 +02:00
|
|
|
|
2016-09-24 16:21:38 +02:00
|
|
|
void sub_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
|
|
|
|
void sub_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2016-09-24 16:21:38 +02:00
|
|
|
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
|
|
|
|
void mul_m4_m3m4(float R[4][4], const float A[3][3], const float B[4][4]);
|
|
|
|
void mul_m4_m4m3(float R[4][4], const float A[4][4], const float B[3][3]);
|
|
|
|
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* `R = A * B`, ignore the elements on the 4th row/column of A.
|
|
|
|
*/
|
2019-04-14 17:13:39 +02:00
|
|
|
void mul_m3_m3m4(float R[3][3], const float A[3][3], const float B[4][4]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* `R = A * B`, ignore the elements on the 4th row/column of B.
|
|
|
|
*/
|
2019-04-14 17:13:39 +02:00
|
|
|
void mul_m3_m4m3(float R[3][3], const float A[4][4], const float B[3][3]);
|
|
|
|
void mul_m3_m4m4(float R[3][3], const float A[4][4], const float B[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Special matrix multiplies
|
|
|
|
* - pre: `R <-- AR`
|
|
|
|
* - post: `R <-- RB`.
|
2016-09-25 18:48:11 +02:00
|
|
|
*/
|
|
|
|
void mul_m3_m3_pre(float R[3][3], const float A[3][3]);
|
|
|
|
void mul_m3_m3_post(float R[3][3], const float B[3][3]);
|
2023-01-16 23:14:52 +01:00
|
|
|
void mul_m4db_m4db_m4fl(double R[4][4], const double A[4][4], const float B[4][4]);
|
2016-09-25 18:48:11 +02:00
|
|
|
void mul_m4_m4_pre(float R[4][4], const float A[4][4]);
|
|
|
|
void mul_m4_m4_post(float R[4][4], const float B[4][4]);
|
2016-09-25 14:27:48 +02:00
|
|
|
|
2021-12-20 09:01:14 +01:00
|
|
|
/* Implement #mul_m3_series macro. */
|
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
void _va_mul_m3_series_3(float r[3][3], const float m1[3][3], const float m2[3][3]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m3_series_4(float r[3][3],
|
|
|
|
const float m1[3][3],
|
|
|
|
const float m2[3][3],
|
|
|
|
const float m3[3][3]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m3_series_5(float r[3][3],
|
|
|
|
const float m1[3][3],
|
|
|
|
const float m2[3][3],
|
|
|
|
const float m3[3][3],
|
|
|
|
const float m4[3][3]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m3_series_6(float r[3][3],
|
|
|
|
const float m1[3][3],
|
|
|
|
const float m2[3][3],
|
|
|
|
const float m3[3][3],
|
|
|
|
const float m4[3][3],
|
|
|
|
const float m5[3][3]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m3_series_7(float r[3][3],
|
|
|
|
const float m1[3][3],
|
|
|
|
const float m2[3][3],
|
|
|
|
const float m3[3][3],
|
|
|
|
const float m4[3][3],
|
|
|
|
const float m5[3][3],
|
|
|
|
const float m6[3][3]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m3_series_8(float r[3][3],
|
|
|
|
const float m1[3][3],
|
|
|
|
const float m2[3][3],
|
|
|
|
const float m3[3][3],
|
|
|
|
const float m4[3][3],
|
|
|
|
const float m5[3][3],
|
|
|
|
const float m6[3][3],
|
|
|
|
const float m7[3][3]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m3_series_9(float r[3][3],
|
|
|
|
const float m1[3][3],
|
|
|
|
const float m2[3][3],
|
|
|
|
const float m3[3][3],
|
|
|
|
const float m4[3][3],
|
|
|
|
const float m5[3][3],
|
|
|
|
const float m6[3][3],
|
|
|
|
const float m7[3][3],
|
|
|
|
const float m8[3][3]) ATTR_NONNULL();
|
2021-12-20 09:01:14 +01:00
|
|
|
|
|
|
|
/* Implement #mul_m4_series macro. */
|
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
void _va_mul_m4_series_3(float r[4][4], const float m1[4][4], const float m2[4][4]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m4_series_4(float r[4][4],
|
|
|
|
const float m1[4][4],
|
|
|
|
const float m2[4][4],
|
|
|
|
const float m3[4][4]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m4_series_5(float r[4][4],
|
|
|
|
const float m1[4][4],
|
|
|
|
const float m2[4][4],
|
|
|
|
const float m3[4][4],
|
|
|
|
const float m4[4][4]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m4_series_6(float r[4][4],
|
|
|
|
const float m1[4][4],
|
|
|
|
const float m2[4][4],
|
|
|
|
const float m3[4][4],
|
|
|
|
const float m4[4][4],
|
|
|
|
const float m5[4][4]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m4_series_7(float r[4][4],
|
|
|
|
const float m1[4][4],
|
|
|
|
const float m2[4][4],
|
|
|
|
const float m3[4][4],
|
|
|
|
const float m4[4][4],
|
|
|
|
const float m5[4][4],
|
|
|
|
const float m6[4][4]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m4_series_8(float r[4][4],
|
|
|
|
const float m1[4][4],
|
|
|
|
const float m2[4][4],
|
|
|
|
const float m3[4][4],
|
|
|
|
const float m4[4][4],
|
|
|
|
const float m5[4][4],
|
|
|
|
const float m6[4][4],
|
|
|
|
const float m7[4][4]) ATTR_NONNULL();
|
|
|
|
void _va_mul_m4_series_9(float r[4][4],
|
|
|
|
const float m1[4][4],
|
|
|
|
const float m2[4][4],
|
|
|
|
const float m3[4][4],
|
|
|
|
const float m4[4][4],
|
|
|
|
const float m5[4][4],
|
|
|
|
const float m6[4][4],
|
|
|
|
const float m7[4][4],
|
|
|
|
const float m8[4][4]) ATTR_NONNULL();
|
2014-07-21 10:55:12 +02:00
|
|
|
|
|
|
|
#define mul_m3_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m3_series_, __VA_ARGS__)
|
|
|
|
#define mul_m4_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m4_series_, __VA_ARGS__)
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2016-09-24 16:21:38 +02:00
|
|
|
void mul_m4_v3(const float M[4][4], float r[3]);
|
2022-08-21 07:06:28 +02:00
|
|
|
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3]);
|
2019-08-20 15:09:55 +02:00
|
|
|
void mul_v3_m4v3_db(double r[3], const double mat[4][4], const double vec[3]);
|
|
|
|
void mul_v4_m4v3_db(double r[4], const double mat[4][4], const double vec[3]);
|
2022-08-21 07:06:28 +02:00
|
|
|
void mul_v2_m4v3(float r[2], const float mat[4][4], const float vec[3]);
|
|
|
|
void mul_v2_m2v2(float r[2], const float mat[2][2], const float vec[2]);
|
|
|
|
void mul_m2_v2(const float mat[2][2], float vec[2]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/** Same as #mul_m4_v3() but doesn't apply translation component. */
|
2022-08-21 07:06:28 +02:00
|
|
|
void mul_mat3_m4_v3(const float mat[4][4], float r[3]);
|
|
|
|
void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3]);
|
|
|
|
void mul_v3_mat3_m4v3_db(double r[3], const double mat[4][4], const double vec[3]);
|
|
|
|
void mul_m4_v4(const float mat[4][4], float r[4]);
|
|
|
|
void mul_v4_m4v4(float r[4], const float mat[4][4], const float v[4]);
|
2016-09-25 19:01:18 +02:00
|
|
|
void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3]); /* v has implicit w = 1.0f */
|
2022-08-21 07:06:28 +02:00
|
|
|
void mul_project_m4_v3(const float mat[4][4], float vec[3]);
|
2016-09-24 16:21:38 +02:00
|
|
|
void mul_v3_project_m4_v3(float r[3], const float mat[4][4], const float vec[3]);
|
2022-08-21 07:06:28 +02:00
|
|
|
void mul_v2_project_m4_v3(float r[2], const float mat[4][4], const float vec[3]);
|
2016-09-24 16:21:38 +02:00
|
|
|
|
|
|
|
void mul_m3_v2(const float m[3][3], float r[2]);
|
|
|
|
void mul_v2_m3v2(float r[2], const float m[3][3], const float v[2]);
|
|
|
|
void mul_m3_v3(const float M[3][3], float r[3]);
|
|
|
|
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3]);
|
|
|
|
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3]);
|
|
|
|
void mul_transposed_m3_v3(const float M[3][3], float r[3]);
|
|
|
|
void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3]);
|
|
|
|
void mul_m3_v3_double(const float M[3][3], double r[3]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Combines transformations, handling scale separately in a manner equivalent
|
|
|
|
* to the Aligned Inherit Scale mode, in order to avoid creating shear.
|
|
|
|
* If A scale is uniform, the result is equivalent to ordinary multiplication.
|
|
|
|
*
|
|
|
|
* NOTE: this effectively takes output location from simple multiplication,
|
|
|
|
* and uses mul_m4_m4m4_split_channels for rotation and scale.
|
|
|
|
*/
|
Action Constraint: introduce a mix mode setting.
Currently the action channels are applied after the existing
transformation, as if the action controlled a child of the
bone. This is not very natural, but more importantly, the
transform tools are not designed to work conveniently with an
additional 'pseudo-child' transformation, resulting in effects
like an unexpected pivot location.
Implementing a Before mode that integrates the action channels
as if applied to a parent allows using the special transform
tool code intended for dealing with such constraints.
Note that in either mode, Action constraints should be added
in reverse order, putting a new constraint before the existing
ones that the Action was keyframed to work together.
In order to implement the option, extract a utility from
the Copy Transform constraint code for combining transforms
with special anti-shear scale handling that matches the
Aligned Inherit Scale mode.
The Before mode also requires switching the constraint to
the Local owner space, while the After mode can still use the
World space for efficiency as before. Since the constraint
doesn't have an Owner space option in the UI, this has to be
handled in an RNA setter.
For full backward compatibility, the original simple matrix
multiplication mode is preserved as the third option, but it
is not recommended due to creating shear.
Differential Revision: https://developer.blender.org/D6297
2019-11-23 11:11:39 +01:00
|
|
|
void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Separately combines location, rotation and scale of the input matrices.
|
|
|
|
*/
|
2020-11-04 17:29:27 +01:00
|
|
|
void mul_m4_m4m4_split_channels(float R[4][4], const float A[4][4], const float B[4][4]);
|
Action Constraint: introduce a mix mode setting.
Currently the action channels are applied after the existing
transformation, as if the action controlled a child of the
bone. This is not very natural, but more importantly, the
transform tools are not designed to work conveniently with an
additional 'pseudo-child' transformation, resulting in effects
like an unexpected pivot location.
Implementing a Before mode that integrates the action channels
as if applied to a parent allows using the special transform
tool code intended for dealing with such constraints.
Note that in either mode, Action constraints should be added
in reverse order, putting a new constraint before the existing
ones that the Action was keyframed to work together.
In order to implement the option, extract a utility from
the Copy Transform constraint code for combining transforms
with special anti-shear scale handling that matches the
Aligned Inherit Scale mode.
The Before mode also requires switching the constraint to
the Local owner space, while the After mode can still use the
World space for efficiency as before. Since the constraint
doesn't have an Owner space option in the UI, this has to be
handled in an RNA setter.
For full backward compatibility, the original simple matrix
multiplication mode is preserved as the third option, but it
is not recommended due to creating shear.
Differential Revision: https://developer.blender.org/D6297
2019-11-23 11:11:39 +01:00
|
|
|
|
2009-11-10 20:13:05 +01:00
|
|
|
void mul_m3_fl(float R[3][3], float f);
|
|
|
|
void mul_m4_fl(float R[4][4], float f);
|
|
|
|
void mul_mat3_m4_fl(float R[4][4], float f);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2014-10-30 10:26:22 +01:00
|
|
|
void negate_m3(float R[3][3]);
|
2014-10-30 15:26:41 +01:00
|
|
|
void negate_mat3_m4(float R[4][4]);
|
2014-05-29 16:26:05 +02:00
|
|
|
void negate_m4(float R[4][4]);
|
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
bool invert_m3_ex(float mat[3][3], float epsilon);
|
|
|
|
bool invert_m3_m3_ex(float inverse[3][3], const float mat[3][3], float epsilon);
|
2012-11-07 10:28:59 +01:00
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
bool invert_m3(float mat[3][3]);
|
|
|
|
bool invert_m2_m2(float inverse[2][2], const float mat[2][2]);
|
|
|
|
bool invert_m3_m3(float inverse[3][3], const float mat[3][3]);
|
|
|
|
bool invert_m4(float mat[4][4]);
|
|
|
|
bool invert_m4_m4(float inverse[4][4], const float mat[4][4]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Computes the inverse of mat and puts it in inverse.
|
|
|
|
* Uses Gaussian Elimination with partial (maximal column) pivoting.
|
|
|
|
* \return true on success (i.e. can always find a pivot) and false on failure.
|
|
|
|
* Mark Segal - 1992.
|
|
|
|
*
|
|
|
|
* \note this has worse performance than #EIG_invert_m4_m4 (Eigen), but e.g.
|
|
|
|
* for non-invertible scale matrices, finding a partial solution can
|
2023-02-12 04:37:16 +01:00
|
|
|
* be useful to have a valid local transform center, see #57767.
|
2021-12-09 10:01:44 +01:00
|
|
|
*/
|
2022-08-21 07:06:28 +02:00
|
|
|
bool invert_m4_m4_fallback(float inverse[4][4], const float mat[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2021-12-20 09:01:14 +01:00
|
|
|
/* Double arithmetic (mixed float/double). */
|
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
void mul_m4_v4d(const float mat[4][4], double r[4]);
|
|
|
|
void mul_v4d_m4v4d(double r[4], const float mat[4][4], const double v[4]);
|
2012-03-08 12:57:51 +01:00
|
|
|
|
2021-12-20 09:01:14 +01:00
|
|
|
/* Double matrix functions (no mixing types). */
|
|
|
|
|
2016-09-24 16:21:38 +02:00
|
|
|
void mul_v3_m3v3_db(double r[3], const double M[3][3], const double a[3]);
|
|
|
|
void mul_m3_v3_db(const double M[3][3], double r[3]);
|
2016-06-14 08:43:14 +02:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Linear Algebra
|
|
|
|
* \{ */
|
2009-11-09 23:42:41 +01:00
|
|
|
|
|
|
|
void transpose_m3(float R[3][3]);
|
2020-09-04 20:59:13 +02:00
|
|
|
void transpose_m3_m3(float R[3][3], const float M[3][3]);
|
2021-12-20 09:01:14 +01:00
|
|
|
/**
|
|
|
|
* \note Seems obscure but in-fact a common operation.
|
|
|
|
*/
|
2020-09-04 20:59:13 +02:00
|
|
|
void transpose_m3_m4(float R[3][3], const float M[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
void transpose_m4(float R[4][4]);
|
2020-09-04 20:59:13 +02:00
|
|
|
void transpose_m4_m4(float R[4][4], const float M[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
bool compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit);
|
Blender Internal Render in viewport
Because of our release soon, feature has been added behind the Debug Menu.
CTRL+ALT+D and set it to -1. Or commandline --debug-value -1.
When debug set to -1, you can put the viewport to 'render' mode, just like
for Cycles. Notes for testers: (and please no bugs in tracker for this :)
- It renders without AA, MBlur, Panorama, Sequence, Composite
- Only active render layer gets rendered. Select another layer will re-render.
- But yes: it works for FreeStyle renders!
- Also does great for local view.
- BI is not well suited for incremental renders on view changes. This only
works for non-raytrace scenes, or zoom in ortho or camera mode, or for
Material changes. In most cases a full re-render is being done.
- ESC works to stop the preview render.
- Borders render as well. (CTRL+B)
- Force a refresh with arrow key left/right. A lot of settings don't trigger
re-render yet.
Tech notes:
- FreeStyle is adding a lot of temp objects/meshes in the Main database. This
caused DepsGraph to trigger changes (and redraws). I've prepended the names
for these temp objects with char number 27 (ESC), and made these names be
ignored for tag update checking.
- Fixed some bugs that were noticable with such excessive re-renders, like
for opening file window, quit during renders.
2013-04-16 19:39:20 +02:00
|
|
|
|
2020-02-20 02:48:42 +01:00
|
|
|
void normalize_m2_ex(float R[2][2], float r_scale[2]) ATTR_NONNULL();
|
|
|
|
void normalize_m2(float R[2][2]) ATTR_NONNULL();
|
2020-09-04 20:59:13 +02:00
|
|
|
void normalize_m2_m2_ex(float R[2][2], const float M[2][2], float r_scale[2]) ATTR_NONNULL();
|
|
|
|
void normalize_m2_m2(float R[2][2], const float M[2][2]) ATTR_NONNULL();
|
2015-10-15 12:03:27 +02:00
|
|
|
void normalize_m3_ex(float R[3][3], float r_scale[3]) ATTR_NONNULL();
|
|
|
|
void normalize_m3(float R[3][3]) ATTR_NONNULL();
|
2020-09-04 20:59:13 +02:00
|
|
|
void normalize_m3_m3_ex(float R[3][3], const float M[3][3], float r_scale[3]) ATTR_NONNULL();
|
|
|
|
void normalize_m3_m3(float R[3][3], const float M[3][3]) ATTR_NONNULL();
|
2015-10-15 12:03:27 +02:00
|
|
|
void normalize_m4_ex(float R[4][4], float r_scale[3]) ATTR_NONNULL();
|
|
|
|
void normalize_m4(float R[4][4]) ATTR_NONNULL();
|
2022-08-21 07:06:28 +02:00
|
|
|
void normalize_m4_m4_ex(float rmat[4][4], const float mat[4][4], float r_scale[3]) ATTR_NONNULL();
|
|
|
|
void normalize_m4_m4(float rmat[4][4], const float mat[4][4]) ATTR_NONNULL();
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Make an orthonormal matrix around the selected axis of the given matrix.
|
|
|
|
*
|
|
|
|
* \param axis: Axis to build the orthonormal basis around.
|
|
|
|
*/
|
2009-11-09 23:42:41 +01:00
|
|
|
void orthogonalize_m3(float R[3][3], int axis);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Make an orthonormal matrix around the selected axis of the given matrix.
|
|
|
|
*
|
|
|
|
* \param axis: Axis to build the orthonormal basis around.
|
|
|
|
*/
|
2009-11-09 23:42:41 +01:00
|
|
|
void orthogonalize_m4(float R[4][4], int axis);
|
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Make an orthonormal matrix around the selected axis of the given matrix,
|
|
|
|
* in a way that is symmetric and stable to variations in the input, and
|
|
|
|
* preserving the value of the determinant, i.e. the overall volume change.
|
|
|
|
*
|
|
|
|
* \param axis: Axis to build the orthonormal basis around.
|
|
|
|
* \param normalize: Normalize the matrix instead of preserving volume.
|
|
|
|
*/
|
Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
The cleanup math is specifically designed to preserve the main
axis of the bone, its length and total volume, and minimally
affect roll on average. It however will not prevent reappearance
of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
This is the simplest foolproof solution that will inherit some
scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
This mode does not handle parent shear in any way, so the child
is likely to end up having both scale and shear. It is retained
for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
2019-09-04 09:10:27 +02:00
|
|
|
void orthogonalize_m3_stable(float R[3][3], int axis, bool normalize);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Make an orthonormal matrix around the selected axis of the given matrix,
|
|
|
|
* in a way that is symmetric and stable to variations in the input, and
|
|
|
|
* preserving the value of the determinant, i.e. the overall volume change.
|
|
|
|
*
|
|
|
|
* \param axis: Axis to build the orthonormal basis around.
|
|
|
|
* \param normalize: Normalize the matrix instead of preserving volume.
|
|
|
|
*/
|
Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
The cleanup math is specifically designed to preserve the main
axis of the bone, its length and total volume, and minimally
affect roll on average. It however will not prevent reappearance
of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
This is the simplest foolproof solution that will inherit some
scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
This mode does not handle parent shear in any way, so the child
is likely to end up having both scale and shear. It is retained
for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
2019-09-04 09:10:27 +02:00
|
|
|
void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize);
|
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
bool orthogonalize_m3_zero_axes(float m[3][3], float unit_length);
|
|
|
|
bool orthogonalize_m4_zero_axes(float m[4][4], float unit_length);
|
2021-04-01 12:16:09 +02:00
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
bool is_orthogonal_m3(const float m[3][3]);
|
|
|
|
bool is_orthogonal_m4(const float m[4][4]);
|
|
|
|
bool is_orthonormal_m3(const float m[3][3]);
|
|
|
|
bool is_orthonormal_m4(const float m[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
bool is_uniform_scaled_m3(const float m[3][3]);
|
2016-09-24 16:21:38 +02:00
|
|
|
bool is_uniform_scaled_m4(const float m[4][4]);
|
2012-05-01 13:01:24 +02:00
|
|
|
|
2021-07-03 15:08:40 +02:00
|
|
|
/* NOTE: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix!
|
2015-12-07 12:35:36 +01:00
|
|
|
* Nowadays 'adjoint' usually refers to the conjugate transpose,
|
2021-12-09 10:01:44 +01:00
|
|
|
* which for real-valued matrices is simply the transpose. */
|
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
void adjoint_m2_m2(float R[2][2], const float M[2][2]);
|
|
|
|
void adjoint_m3_m3(float R[3][3], const float M[3][3]);
|
|
|
|
void adjoint_m4_m4(float R[4][4], const float M[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2012-05-12 22:39:39 +02:00
|
|
|
float determinant_m2(float a, float b, float c, float d);
|
|
|
|
float determinant_m3(
|
2020-09-04 20:59:13 +02:00
|
|
|
float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3);
|
2016-09-24 16:21:38 +02:00
|
|
|
float determinant_m3_array(const float m[3][3]);
|
2019-05-05 12:25:43 +02:00
|
|
|
float determinant_m4_mat3_array(const float m[4][4]);
|
2020-11-21 14:06:02 +01:00
|
|
|
double determinant_m3_array_db(const double m[3][3]);
|
2020-09-04 20:59:13 +02:00
|
|
|
float determinant_m4(const float m[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2012-12-14 22:41:22 +01:00
|
|
|
#define PSEUDOINVERSE_EPSILON 1e-8f
|
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Compute the Single Value Decomposition of an arbitrary matrix A
|
|
|
|
* That is compute the 3 matrices U,W,V with U column orthogonal (m,n)
|
|
|
|
* ,W a diagonal matrix and V an orthogonal square matrix `s.t.A = U.W.Vt`.
|
|
|
|
* From this decomposition it is trivial to compute the (pseudo-inverse)
|
|
|
|
* of `A` as `Ainv = V.Winv.transpose(U)`.
|
|
|
|
*/
|
2022-08-21 07:06:28 +02:00
|
|
|
void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]);
|
|
|
|
void pseudoinverse_m4_m4(float inverse[4][4], const float mat[4][4], float epsilon);
|
|
|
|
void pseudoinverse_m3_m3(float inverse[3][3], const float mat[3][3], float epsilon);
|
2010-06-22 17:20:06 +02:00
|
|
|
|
2016-09-24 16:21:38 +02:00
|
|
|
bool has_zero_axis_m4(const float matrix[4][4]);
|
2022-10-05 22:10:53 +02:00
|
|
|
/** Fix any zero scale axis adding a small bias orthogonal to the other valid axis. */
|
|
|
|
void zero_axis_bias_m4(float mat[4][4]);
|
2013-10-19 01:38:51 +02:00
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
void invert_m4_m4_safe(float inverse[4][4], const float mat[4][4]);
|
2014-03-25 11:05:28 +01:00
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
void invert_m3_m3_safe_ortho(float inverse[3][3], const float mat[3][3]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* A safe version of invert that uses valid axes, calculating the zero'd axis
|
|
|
|
* based on the non-zero ones.
|
|
|
|
*
|
2022-06-07 13:22:11 +02:00
|
|
|
* This works well for transformation matrices, when a single axis is zeroed.
|
2021-12-09 10:01:44 +01:00
|
|
|
*/
|
2022-08-21 07:06:28 +02:00
|
|
|
void invert_m4_m4_safe_ortho(float inverse[4][4], const float mat[4][4]);
|
2020-08-25 04:35:44 +02:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Transformations
|
|
|
|
* \{ */
|
2009-11-09 23:42:41 +01:00
|
|
|
|
|
|
|
void scale_m3_fl(float R[3][3], float scale);
|
|
|
|
void scale_m4_fl(float R[4][4], float scale);
|
2022-01-28 08:37:12 +01:00
|
|
|
void scale_m4_v2(float R[4][4], const float scale[2]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* This computes the overall volume scale factor of a transformation matrix.
|
|
|
|
* For an orthogonal matrix, it is the product of all three scale values.
|
|
|
|
* Returns a negative value if the transform is flipped by negative scale.
|
|
|
|
*/
|
2022-08-21 07:06:28 +02:00
|
|
|
float mat3_to_volume_scale(const float mat[3][3]);
|
|
|
|
float mat4_to_volume_scale(const float mat[4][4]);
|
2019-05-05 12:25:43 +02:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* This gets the average scale of a matrix, only use when your scaling
|
|
|
|
* data that has no idea of scale axis, examples are bone-envelope-radius
|
|
|
|
* and curve radius.
|
|
|
|
*/
|
2022-08-21 07:06:28 +02:00
|
|
|
float mat3_to_scale(const float mat[3][3]);
|
|
|
|
float mat4_to_scale(const float mat[4][4]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/** Return 2D scale (in XY plane) of given mat4. */
|
2022-08-21 07:06:28 +02:00
|
|
|
float mat4_to_xy_scale(const float mat[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2010-10-22 05:56:50 +02:00
|
|
|
void size_to_mat3(float R[3][3], const float size[3]);
|
|
|
|
void size_to_mat4(float R[4][4], const float size[3]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2022-09-09 13:15:01 +02:00
|
|
|
/** Return 2D size assuming the given matrix is a 2D affine matrix. */
|
|
|
|
void mat3_to_size_2d(float size[2], const float M[3][3]);
|
2020-09-04 20:59:13 +02:00
|
|
|
void mat3_to_size(float size[3], const float M[3][3]);
|
|
|
|
void mat4_to_size(float size[3], const float M[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2022-02-08 12:16:51 +01:00
|
|
|
/**
|
|
|
|
* Return the largest scale on any axis, the equivalent of calling:
|
|
|
|
* \code{.c}
|
|
|
|
* mat3_to_size(size_v3, mat);
|
|
|
|
* size = size_v3[max_axis_v3(size_v3)];
|
|
|
|
* \endcode
|
|
|
|
* .. without 2x unnecessary `sqrtf` calls.
|
|
|
|
*/
|
|
|
|
float mat3_to_size_max_axis(const float M[3][3]);
|
|
|
|
/**
|
|
|
|
* Only the first 3 axes are used.
|
|
|
|
*/
|
|
|
|
float mat4_to_size_max_axis(const float M[4][4]);
|
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Extract scale factors from the matrix, with correction to ensure
|
|
|
|
* exact volume in case of a sheared matrix.
|
|
|
|
*/
|
2020-09-04 20:59:13 +02:00
|
|
|
void mat4_to_size_fix_shear(float size[3], const float M[4][4]);
|
Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
The cleanup math is specifically designed to preserve the main
axis of the bone, its length and total volume, and minimally
affect roll on average. It however will not prevent reappearance
of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
This is the simplest foolproof solution that will inherit some
scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
This mode does not handle parent shear in any way, so the child
is likely to end up having both scale and shear. It is retained
for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
2019-09-04 09:10:27 +02:00
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Rotate a matrix in-place.
|
|
|
|
*
|
|
|
|
* \note To create a new rotation matrix see:
|
|
|
|
* #axis_angle_to_mat4_single, #axis_angle_to_mat3_single, #angle_to_mat2
|
|
|
|
* (axis & angle args are compatible).
|
|
|
|
*/
|
2022-01-07 01:38:08 +01:00
|
|
|
void rotate_m4(float mat[4][4], char axis, float angle);
|
2021-12-09 10:01:44 +01:00
|
|
|
/** Scale a matrix in-place. */
|
2019-09-04 11:06:59 +02:00
|
|
|
void rescale_m4(float mat[4][4], const float scale[3]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Scale or rotate around a pivot point,
|
|
|
|
* a convenience function to avoid having to do inline.
|
|
|
|
*
|
|
|
|
* Since its common to make a scale/rotation matrix that pivots around an arbitrary point.
|
|
|
|
*
|
|
|
|
* Typical use case is to make 3x3 matrix, copy to 4x4, then pass to this function.
|
|
|
|
*/
|
2013-07-30 12:58:36 +02:00
|
|
|
void transform_pivot_set_m4(float mat[4][4], const float pivot[3]);
|
2010-11-22 11:39:28 +01:00
|
|
|
|
2022-08-25 04:45:43 +02:00
|
|
|
/**
|
|
|
|
* \param rot: A 3x3 rotation matrix, normalized never negative.
|
|
|
|
*/
|
2021-03-08 18:45:06 +01:00
|
|
|
void mat4_to_rot(float rot[3][3], const float wmat[4][4]);
|
2022-08-25 04:45:43 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \param rot: A 3x3 rotation matrix, normalized never negative.
|
|
|
|
* \param size: The scale, negative if `mat3` is negative.
|
|
|
|
*/
|
2016-09-24 16:21:38 +02:00
|
|
|
void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3]);
|
2022-08-25 04:45:43 +02:00
|
|
|
/**
|
|
|
|
* \param rot: A 3x3 rotation matrix, normalized never negative.
|
|
|
|
* \param size: The scale, negative if `mat3` is negative.
|
|
|
|
*/
|
2016-09-24 16:21:38 +02:00
|
|
|
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4]);
|
|
|
|
void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4]);
|
|
|
|
void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4]);
|
2010-10-26 14:48:07 +02:00
|
|
|
|
2016-09-24 16:21:38 +02:00
|
|
|
void mat3_polar_decompose(const float mat3[3][3], float r_U[3][3], float r_P[3][3]);
|
2015-10-09 20:57:37 +02:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Make a 4x4 matrix out of 3 transform components.
|
|
|
|
* Matrices are made in the order: `scale * rot * loc`
|
|
|
|
*/
|
2019-09-04 11:06:59 +02:00
|
|
|
void loc_rot_size_to_mat4(float R[4][4],
|
|
|
|
const float loc[3],
|
|
|
|
const float rot[3][3],
|
|
|
|
const float size[3]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Make a 4x4 matrix out of 3 transform components.
|
|
|
|
* Matrices are made in the order: `scale * rot * loc`
|
|
|
|
*
|
|
|
|
* TODO: need to have a version that allows for rotation order.
|
|
|
|
*/
|
2009-11-09 23:42:41 +01:00
|
|
|
void loc_eul_size_to_mat4(float R[4][4],
|
2012-05-12 22:39:39 +02:00
|
|
|
const float loc[3],
|
|
|
|
const float eul[3],
|
|
|
|
const float size[3]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Make a 4x4 matrix out of 3 transform components.
|
|
|
|
* Matrices are made in the order: `scale * rot * loc`
|
|
|
|
*/
|
2009-11-09 23:42:41 +01:00
|
|
|
void loc_eulO_size_to_mat4(
|
2022-01-07 01:38:08 +01:00
|
|
|
float R[4][4], const float loc[3], const float eul[3], const float size[3], short order);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Make a 4x4 matrix out of 3 transform components.
|
|
|
|
* Matrices are made in the order: `scale * rot * loc`
|
|
|
|
*/
|
2009-11-09 23:42:41 +01:00
|
|
|
void loc_quat_size_to_mat4(float R[4][4],
|
2012-05-12 22:39:39 +02:00
|
|
|
const float loc[3],
|
|
|
|
const float quat[4],
|
|
|
|
const float size[3]);
|
2022-01-07 01:38:08 +01:00
|
|
|
void loc_axisangle_size_to_mat4(
|
|
|
|
float R[4][4], const float loc[3], const float axis[3], float angle, const float size[3]);
|
|
|
|
|
|
|
|
void blend_m3_m3m3(float out[3][3], const float dst[3][3], const float src[3][3], float srcweight);
|
|
|
|
void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4], float srcweight);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* A polar-decomposition-based interpolation between matrix A and matrix B.
|
|
|
|
*
|
|
|
|
* \note This code is about five times slower as the 'naive' interpolation done by #blend_m3_m3m3
|
|
|
|
* (it typically remains below 2 usec on an average i74700,
|
|
|
|
* while #blend_m3_m3m3 remains below 0.4 usec).
|
|
|
|
* However, it gives expected results even with non-uniformly scaled matrices,
|
2023-02-12 04:37:16 +01:00
|
|
|
* see #46418 for an example.
|
2021-12-09 10:01:44 +01:00
|
|
|
*
|
|
|
|
* Based on "Matrix Animation and Polar Decomposition", by Ken Shoemake & Tom Duff
|
|
|
|
*
|
|
|
|
* \param R: Resulting interpolated matrix.
|
|
|
|
* \param A: Input matrix which is totally effective with `t = 0.0`.
|
|
|
|
* \param B: Input matrix which is totally effective with `t = 1.0`.
|
|
|
|
* \param t: Interpolation factor.
|
|
|
|
*/
|
2022-01-07 01:38:08 +01:00
|
|
|
void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], float t);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Complete transform matrix interpolation,
|
|
|
|
* based on polar-decomposition-based interpolation from #interp_m3_m3m3.
|
|
|
|
*
|
|
|
|
* \param R: Resulting interpolated matrix.
|
|
|
|
* \param A: Input matrix which is totally effective with `t = 0.0`.
|
|
|
|
* \param B: Input matrix which is totally effective with `t = 1.0`.
|
|
|
|
* \param t: Interpolation factor.
|
|
|
|
*/
|
2022-01-07 01:38:08 +01:00
|
|
|
void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], float t);
|
2015-10-09 20:57:37 +02:00
|
|
|
|
2022-08-24 08:34:04 +02:00
|
|
|
/**
|
|
|
|
* Return true when the matrices determinant is less than zero.
|
|
|
|
*
|
|
|
|
* \note This is often used to check if a matrix flips content in 3D space,
|
|
|
|
* where transforming geometry (for example) would flip the direction of polygon normals
|
|
|
|
* from pointing outside a closed volume, to pointing inside (or the reverse).
|
|
|
|
*
|
|
|
|
* When the matrix is constructed from location, rotation & scale
|
|
|
|
* as matrix will be negative when it has an odd number of negative scales.
|
|
|
|
*/
|
2016-09-24 16:21:38 +02:00
|
|
|
bool is_negative_m3(const float mat[3][3]);
|
2022-08-24 08:34:04 +02:00
|
|
|
/** A version of #is_negative_m3 that takes a 4x4 matrix. */
|
2016-09-24 16:21:38 +02:00
|
|
|
bool is_negative_m4(const float mat[4][4]);
|
2013-07-26 13:15:22 +02:00
|
|
|
|
2016-09-24 16:21:38 +02:00
|
|
|
bool is_zero_m3(const float mat[3][3]);
|
|
|
|
bool is_zero_m4(const float mat[4][4]);
|
2010-01-30 14:15:39 +01:00
|
|
|
|
2016-09-24 16:21:38 +02:00
|
|
|
bool equals_m3m3(const float mat1[3][3], const float mat2[3][3]);
|
|
|
|
bool equals_m4m4(const float mat1[4][4], const float mat2[4][4]);
|
2016-05-12 12:07:31 +02:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* #SpaceTransform struct encapsulates all needed data to convert between two coordinate spaces
|
|
|
|
* (where conversion can be represented by a matrix multiplication).
|
|
|
|
*
|
|
|
|
* A #SpaceTransform is initialized using:
|
|
|
|
* - #BLI_SPACE_TRANSFORM_SETUP(&data, ob1, ob2)
|
|
|
|
*
|
|
|
|
* After that the following calls can be used:
|
|
|
|
* - Converts a coordinate in ob1 space to the corresponding ob2 space:
|
|
|
|
* #BLI_space_transform_apply(&data, co);
|
|
|
|
* - Converts a coordinate in ob2 space to the corresponding ob1 space:
|
|
|
|
* #BLI_space_transform_invert(&data, co);
|
|
|
|
*
|
|
|
|
* Same concept as #BLI_space_transform_apply and #BLI_space_transform_invert,
|
|
|
|
* but no is normalized after conversion (and not translated at all!):
|
|
|
|
* - #BLI_space_transform_apply_normal(&data, no);
|
|
|
|
* - #BLI_space_transform_invert_normal(&data, no);
|
|
|
|
*/
|
2014-08-01 16:28:31 +02:00
|
|
|
typedef struct SpaceTransform {
|
|
|
|
float local2target[4][4];
|
|
|
|
float target2local[4][4];
|
|
|
|
|
|
|
|
} SpaceTransform;
|
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Global-invariant transform.
|
|
|
|
*
|
|
|
|
* This defines a matrix transforming a point in local space to a point in target space
|
|
|
|
* such that its global coordinates remain unchanged.
|
|
|
|
*
|
|
|
|
* In other words, if we have a global point P with local coordinates (x, y, z)
|
|
|
|
* and global coordinates (X, Y, Z),
|
|
|
|
* this defines a transform matrix TM such that (x', y', z') = TM * (x, y, z)
|
|
|
|
* where (x', y', z') are the coordinates of P' in target space
|
|
|
|
* such that it keeps (X, Y, Z) coordinates in global space.
|
|
|
|
*/
|
2016-09-24 16:21:38 +02:00
|
|
|
void BLI_space_transform_from_matrices(struct SpaceTransform *data,
|
|
|
|
const float local[4][4],
|
|
|
|
const float target[4][4]);
|
2021-12-09 10:01:44 +01:00
|
|
|
/**
|
|
|
|
* Local-invariant transform.
|
|
|
|
*
|
|
|
|
* This defines a matrix transforming a point in global space
|
|
|
|
* such that its local coordinates (from local space to target space) remain unchanged.
|
|
|
|
*
|
|
|
|
* In other words, if we have a local point p with local coordinates (x, y, z)
|
|
|
|
* and global coordinates (X, Y, Z),
|
|
|
|
* this defines a transform matrix TM such that (X', Y', Z') = TM * (X, Y, Z)
|
|
|
|
* where (X', Y', Z') are the coordinates of p' in global space
|
|
|
|
* such that it keeps (x, y, z) coordinates in target space.
|
|
|
|
*/
|
2016-09-24 16:21:38 +02:00
|
|
|
void BLI_space_transform_global_from_matrices(struct SpaceTransform *data,
|
|
|
|
const float local[4][4],
|
|
|
|
const float target[4][4]);
|
2014-08-01 16:28:31 +02:00
|
|
|
void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3]);
|
|
|
|
void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3]);
|
|
|
|
void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float no[3]);
|
|
|
|
void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3]);
|
|
|
|
|
|
|
|
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target) \
|
2024-02-14 16:14:49 +01:00
|
|
|
BLI_space_transform_from_matrices( \
|
|
|
|
(data), (local)->object_to_world().ptr(), (target)->object_to_world().ptr())
|
2014-08-01 16:28:31 +02:00
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Other
|
|
|
|
* \{ */
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2022-08-21 07:06:28 +02:00
|
|
|
void print_m3(const char *str, const float m[3][3]);
|
|
|
|
void print_m4(const char *str, const float m[4][4]);
|
2009-11-09 23:42:41 +01:00
|
|
|
|
2014-03-30 04:03:30 +02:00
|
|
|
#define print_m3_id(M) print_m3(STRINGIFY(M), M)
|
|
|
|
#define print_m4_id(M) print_m4(STRINGIFY(M), M)
|
|
|
|
|
2021-12-09 10:01:44 +01:00
|
|
|
/** \} */
|
|
|
|
|
2009-11-09 23:42:41 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|