| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2008 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 17:14:50 +02:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 09:20:45 +02:00
										 |  |  | #include "BCMath.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | #include "BlenderContext.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 22:08:23 +02:00
										 |  |  | void BCQuat::rotate_to(Matrix &mat_to) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Quat qd; | 
					
						
							|  |  |  |   Matrix matd; | 
					
						
							|  |  |  |   Matrix mati; | 
					
						
							|  |  |  |   Matrix mat_from; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   quat_to_mat4(mat_from, q); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Calculate the difference matrix matd between mat_from and mat_to */ | 
					
						
							|  |  |  |   invert_m4_m4(mati, mat_from); | 
					
						
							|  |  |  |   mul_m4_m4m4(matd, mati, mat_to); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mat4_to_quat(qd, matd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mul_qt_qtqt(q, qd, q); /* rotate to the final rotation to mat_to */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | BCMatrix::BCMatrix(const BCMatrix &mat) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   set_transform(mat.matrix); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BCMatrix::BCMatrix(Matrix &mat) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   set_transform(mat); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BCMatrix::BCMatrix(Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   set_transform(ob); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BCMatrix::BCMatrix() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   unit(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BCMatrix::BCMatrix(BC_global_forward_axis global_forward_axis, BC_global_up_axis global_up_axis) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float mrot[3][3]; | 
					
						
							|  |  |  |   float mat[4][4]; | 
					
						
							|  |  |  |   mat3_from_axis_conversion( | 
					
						
							|  |  |  |       BC_DEFAULT_FORWARD, BC_DEFAULT_UP, global_forward_axis, global_up_axis, mrot); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   transpose_m3( | 
					
						
							|  |  |  |       mrot); /* TODO: Verify that mat3_from_axis_conversion() returns a transposed matrix */ | 
					
						
							|  |  |  |   copy_m4_m3(mat, mrot); | 
					
						
							|  |  |  |   set_transform(mat); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  | void BCMatrix::add_transform(const Matrix &mat, bool inverted) | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  |   add_transform(this->matrix, mat, this->matrix, inverted); | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  | void BCMatrix::add_transform(const BCMatrix &mat, bool inverted) | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  |   add_transform(this->matrix, mat.matrix, this->matrix, inverted); | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  | void BCMatrix::apply_transform(const BCMatrix &mat, bool inverted) | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  |   apply_transform(this->matrix, mat.matrix, this->matrix, inverted); | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  | void BCMatrix::add_transform(Matrix &to, | 
					
						
							|  |  |  |                              const Matrix &transform, | 
					
						
							|  |  |  |                              const Matrix &from, | 
					
						
							|  |  |  |                              bool inverted) | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  |   if (inverted) { | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  |     Matrix globinv; | 
					
						
							|  |  |  |     invert_m4_m4(globinv, transform); | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  |     add_transform(to, globinv, from, /*inverted=*/false); | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     mul_m4_m4m4(to, transform, from); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BCMatrix::apply_transform(Matrix &to, | 
					
						
							|  |  |  |                                const Matrix &transform, | 
					
						
							|  |  |  |                                const Matrix &from, | 
					
						
							|  |  |  |                                bool inverse) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Matrix globinv; | 
					
						
							|  |  |  |   invert_m4_m4(globinv, transform); | 
					
						
							|  |  |  |   if (inverse) { | 
					
						
							| 
									
										
										
										
											2020-07-03 16:38:01 +02:00
										 |  |  |     add_transform(to, globinv, from, /*inverted=*/false); | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     mul_m4_m4m4(to, transform, from); | 
					
						
							|  |  |  |     mul_m4_m4m4(to, to, globinv); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BCMatrix::add_inverted_transform(Matrix &to, const Matrix &transform, const Matrix &from) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Matrix workmat; | 
					
						
							|  |  |  |   invert_m4_m4(workmat, transform); | 
					
						
							|  |  |  |   mul_m4_m4m4(to, workmat, from); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BCMatrix::set_transform(Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Matrix lmat; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BKE_object_matrix_local_get(ob, lmat); | 
					
						
							|  |  |  |   copy_m4_m4(matrix, lmat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mat4_decompose(this->loc, this->q, this->size, lmat); | 
					
						
							|  |  |  |   quat_to_compatible_eul(this->rot, ob->rot, this->q); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BCMatrix::set_transform(Matrix &mat) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   copy_m4_m4(matrix, mat); | 
					
						
							|  |  |  |   mat4_decompose(this->loc, this->q, this->size, mat); | 
					
						
							|  |  |  |   quat_to_eul(this->rot, this->q); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 20:59:13 +02:00
										 |  |  | void BCMatrix::copy(Matrix &r, Matrix &a) | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   /* destination comes first: */ | 
					
						
							| 
									
										
										
										
											2020-09-04 20:59:13 +02:00
										 |  |  |   memcpy(r, a, sizeof(Matrix)); | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BCMatrix::transpose(Matrix &mat) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   transpose_m4(mat); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BCMatrix::sanitize(Matrix &mat, int precision) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |   for (auto &row : mat) { | 
					
						
							|  |  |  |     for (float &cell : row) { | 
					
						
							|  |  |  |       double val = (double)cell; | 
					
						
							| 
									
										
										
										
											2019-05-28 09:23:05 +02:00
										 |  |  |       val = double_round(val, precision); | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |       cell = (float)val; | 
					
						
							| 
									
										
										
										
											2019-05-28 09:23:05 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-04 00:17:37 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-28 09:23:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BCMatrix::sanitize(DMatrix &mat, int precision) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |   for (auto &row : mat) { | 
					
						
							| 
									
										
										
										
											2020-12-07 12:54:46 +01:00
										 |  |  |     for (double &cell : row) { | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |       cell = double_round(cell, precision); | 
					
						
							| 
									
										
										
										
											2019-06-04 00:17:37 +10:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BCMatrix::unit() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   unit_m4(this->matrix); | 
					
						
							|  |  |  |   mat4_decompose(this->loc, this->q, this->size, this->matrix); | 
					
						
							|  |  |  |   quat_to_eul(this->rot, this->q); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* We need double here because the OpenCollada API needs it.
 | 
					
						
							|  |  |  |  * precision = -1 indicates to not limit the precision. */ | 
					
						
							|  |  |  | void BCMatrix::get_matrix(DMatrix &mat, const bool transposed, const int precision) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-04 00:17:37 +10:00
										 |  |  |   for (int i = 0; i < 4; i++) { | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  |     for (int j = 0; j < 4; j++) { | 
					
						
							|  |  |  |       float val = (transposed) ? matrix[j][i] : matrix[i][j]; | 
					
						
							| 
									
										
										
										
											2019-06-04 11:14:59 +10:00
										 |  |  |       if (precision >= 0) { | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  |         val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision); | 
					
						
							| 
									
										
										
										
											2019-06-04 11:14:59 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  |       mat[i][j] = val; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-04 00:17:37 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BCMatrix::get_matrix(Matrix &mat, | 
					
						
							|  |  |  |                           const bool transposed, | 
					
						
							|  |  |  |                           const int precision, | 
					
						
							|  |  |  |                           const bool inverted) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-04 00:17:37 +10:00
										 |  |  |   for (int i = 0; i < 4; i++) { | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  |     for (int j = 0; j < 4; j++) { | 
					
						
							|  |  |  |       float val = (transposed) ? matrix[j][i] : matrix[i][j]; | 
					
						
							| 
									
										
										
										
											2019-06-04 11:14:59 +10:00
										 |  |  |       if (precision >= 0) { | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  |         val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision); | 
					
						
							| 
									
										
										
										
											2019-06-04 11:14:59 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  |       mat[i][j] = val; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-04 00:17:37 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (inverted) { | 
					
						
							|  |  |  |     invert_m4(mat); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 12:04:47 +02:00
										 |  |  | bool BCMatrix::in_range(const BCMatrix &other, float distance) const | 
					
						
							| 
									
										
										
										
											2019-05-28 00:32:53 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   for (int i = 0; i < 4; i++) { | 
					
						
							|  |  |  |     for (int j = 0; j < 4; j++) { | 
					
						
							|  |  |  |       if (fabs(other.matrix[i][j] - matrix[i][j]) > distance) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float (&BCMatrix::location() const)[3] | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return loc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float (&BCMatrix::rotation() const)[3] | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return rot; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float (&BCMatrix::scale() const)[3] | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float (&BCMatrix::quat() const)[4] | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return q; | 
					
						
							|  |  |  | } |