2009-11-09 22:42:41 +00:00
|
|
|
/*
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-11-09 22:42:41 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: some of this file.
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-02-27 20:37:56 +00:00
|
|
|
/** \file blender/blenlib/intern/math_matrix.c
|
|
|
|
* \ingroup bli
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2010-11-16 01:19:37 +00:00
|
|
|
#include <assert.h>
|
2009-11-09 22:42:41 +00:00
|
|
|
#include "BLI_math.h"
|
|
|
|
|
|
|
|
/********************************* Init **************************************/
|
|
|
|
|
2009-11-10 19:13:05 +00:00
|
|
|
void zero_m3(float m[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
memset(m, 0, 3 * 3 * sizeof(float));
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2009-11-10 19:13:05 +00:00
|
|
|
void zero_m4(float m[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
memset(m, 0, 4 * 4 * sizeof(float));
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void unit_m3(float m[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
m[0][0] = m[1][1] = m[2][2] = 1.0;
|
|
|
|
m[0][1] = m[0][2] = 0.0;
|
|
|
|
m[1][0] = m[1][2] = 0.0;
|
|
|
|
m[2][0] = m[2][1] = 0.0;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void unit_m4(float m[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0;
|
|
|
|
m[0][1] = m[0][2] = m[0][3] = 0.0;
|
|
|
|
m[1][0] = m[1][2] = m[1][3] = 0.0;
|
|
|
|
m[2][0] = m[2][1] = m[2][3] = 0.0;
|
|
|
|
m[3][0] = m[3][1] = m[3][2] = 0.0;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void copy_m3_m3(float m1[3][3], float m2[3][3])
|
2012-03-25 12:41:58 +00:00
|
|
|
{
|
2009-11-09 22:42:41 +00:00
|
|
|
/* destination comes first: */
|
2012-03-25 12:41:58 +00:00
|
|
|
memcpy(&m1[0], &m2[0], 9 * sizeof(float));
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void copy_m4_m4(float m1[4][4], float m2[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
memcpy(m1, m2, 4 * 4 * sizeof(float));
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void copy_m3_m4(float m1[3][3], float m2[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[0][0] = m2[0][0];
|
|
|
|
m1[0][1] = m2[0][1];
|
|
|
|
m1[0][2] = m2[0][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[1][0] = m2[1][0];
|
|
|
|
m1[1][1] = m2[1][1];
|
|
|
|
m1[1][2] = m2[1][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[2][0] = m2[2][0];
|
|
|
|
m1[2][1] = m2[2][1];
|
|
|
|
m1[2][2] = m2[2][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[0][0] = m2[0][0];
|
|
|
|
m1[0][1] = m2[0][1];
|
|
|
|
m1[0][2] = m2[0][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[1][0] = m2[1][0];
|
|
|
|
m1[1][1] = m2[1][1];
|
|
|
|
m1[1][2] = m2[1][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[2][0] = m2[2][0];
|
|
|
|
m1[2][1] = m2[2][1];
|
|
|
|
m1[2][2] = m2[2][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
/* Reevan's Bugfix */
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[0][3] = 0.0F;
|
|
|
|
m1[1][3] = 0.0F;
|
|
|
|
m1[2][3] = 0.0F;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[3][0] = 0.0F;
|
|
|
|
m1[3][1] = 0.0F;
|
|
|
|
m1[3][2] = 0.0F;
|
|
|
|
m1[3][3] = 1.0F;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-10-25 22:12:05 +00:00
|
|
|
void copy_m3_m3d(float R[3][3], double A[3][3])
|
2013-10-20 12:08:51 +00:00
|
|
|
{
|
|
|
|
/* Keep it stupid simple for better data flow in CPU. */
|
|
|
|
R[0][0] = A[0][0];
|
|
|
|
R[0][1] = A[0][1];
|
|
|
|
R[0][2] = A[0][2];
|
|
|
|
|
|
|
|
R[1][0] = A[1][0];
|
|
|
|
R[1][1] = A[1][1];
|
|
|
|
R[1][2] = A[1][2];
|
|
|
|
|
|
|
|
R[2][0] = A[2][0];
|
|
|
|
R[2][1] = A[2][1];
|
|
|
|
R[2][2] = A[2][2];
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void swap_m3m3(float m1[3][3], float m2[3][3])
|
2011-01-31 20:02:51 +00:00
|
|
|
{
|
|
|
|
float t;
|
|
|
|
int i, j;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < 3; i++) {
|
2011-01-31 20:02:51 +00:00
|
|
|
for (j = 0; j < 3; j++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t = m1[i][j];
|
2011-01-31 20:02:51 +00:00
|
|
|
m1[i][j] = m2[i][j];
|
|
|
|
m2[i][j] = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void swap_m4m4(float m1[4][4], float m2[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float t;
|
|
|
|
int i, j;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < 4; i++) {
|
2009-11-09 22:42:41 +00:00
|
|
|
for (j = 0; j < 4; j++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t = m1[i][j];
|
2009-11-09 22:42:41 +00:00
|
|
|
m1[i][j] = m2[i][j];
|
|
|
|
m2[i][j] = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************** Arithmetic *********************************/
|
|
|
|
|
2013-05-26 18:36:25 +00:00
|
|
|
void mul_m4_m4m4(float m1[4][4], float m3_[4][4], float m2_[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2010-04-15 10:28:32 +00:00
|
|
|
float m2[4][4], m3[4][4];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2010-04-15 10:28:32 +00:00
|
|
|
/* copy so it works when m1 is the same pointer as m2 or m3 */
|
|
|
|
copy_m4_m4(m2, m2_);
|
|
|
|
copy_m4_m4(m3, m3_);
|
|
|
|
|
|
|
|
/* matrix product: m1[j][k] = m2[j][i].m3[i][k] */
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0] + m2[0][3] * m3[3][0];
|
|
|
|
m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1] + m2[0][3] * m3[3][1];
|
|
|
|
m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2] + m2[0][3] * m3[3][2];
|
|
|
|
m1[0][3] = m2[0][0] * m3[0][3] + m2[0][1] * m3[1][3] + m2[0][2] * m3[2][3] + m2[0][3] * m3[3][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0] + m2[1][3] * m3[3][0];
|
|
|
|
m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1] + m2[1][3] * m3[3][1];
|
|
|
|
m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2] + m2[1][3] * m3[3][2];
|
|
|
|
m1[1][3] = m2[1][0] * m3[0][3] + m2[1][1] * m3[1][3] + m2[1][2] * m3[2][3] + m2[1][3] * m3[3][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0] + m2[2][3] * m3[3][0];
|
|
|
|
m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1] + m2[2][3] * m3[3][1];
|
|
|
|
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2] + m2[2][3] * m3[3][2];
|
|
|
|
m1[2][3] = m2[2][0] * m3[0][3] + m2[2][1] * m3[1][3] + m2[2][2] * m3[2][3] + m2[2][3] * m3[3][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[3][0] = m2[3][0] * m3[0][0] + m2[3][1] * m3[1][0] + m2[3][2] * m3[2][0] + m2[3][3] * m3[3][0];
|
|
|
|
m1[3][1] = m2[3][0] * m3[0][1] + m2[3][1] * m3[1][1] + m2[3][2] * m3[2][1] + m2[3][3] * m3[3][1];
|
|
|
|
m1[3][2] = m2[3][0] * m3[0][2] + m2[3][1] * m3[1][2] + m2[3][2] * m3[2][2] + m2[3][3] * m3[3][2];
|
|
|
|
m1[3][3] = m2[3][0] * m3[0][3] + m2[3][1] * m3[1][3] + m2[3][2] * m3[2][3] + m2[3][3] * m3[3][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_m3_m3m3(float m1[3][3], float m3_[3][3], float m2_[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2010-04-15 10:28:32 +00:00
|
|
|
float m2[3][3], m3[3][3];
|
|
|
|
|
|
|
|
/* copy so it works when m1 is the same pointer as m2 or m3 */
|
|
|
|
copy_m3_m3(m2, m2_);
|
|
|
|
copy_m3_m3(m3, m3_);
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
/* m1[i][j] = m2[i][k] * m3[k][j], args are flipped! */
|
|
|
|
m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0];
|
|
|
|
m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1];
|
|
|
|
m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2];
|
2010-04-15 10:28:32 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0];
|
|
|
|
m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1];
|
|
|
|
m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2];
|
2010-04-15 10:28:32 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0];
|
|
|
|
m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1];
|
|
|
|
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_m4_m4m3(float m1[4][4], float m3_[4][4], float m2_[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2011-12-15 16:09:57 +00:00
|
|
|
float m2[3][3], m3[4][4];
|
|
|
|
|
|
|
|
/* copy so it works when m1 is the same pointer as m2 or m3 */
|
|
|
|
copy_m3_m3(m2, m2_);
|
|
|
|
copy_m4_m4(m3, m3_);
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0];
|
|
|
|
m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1];
|
|
|
|
m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2];
|
|
|
|
m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0];
|
|
|
|
m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1];
|
|
|
|
m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2];
|
|
|
|
m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0];
|
|
|
|
m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1];
|
|
|
|
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
2009-11-10 19:13:05 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
/* m1 = m2 * m3, ignore the elements on the 4th row/column of m3 */
|
2013-05-26 18:36:25 +00:00
|
|
|
void mul_m3_m3m4(float m1[3][3], float m3_[4][4], float m2_[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-09-16 15:25:28 +00:00
|
|
|
float m2[3][3], m3[4][4];
|
|
|
|
|
|
|
|
/* copy so it works when m1 is the same pointer as m2 or m3 */
|
|
|
|
copy_m3_m3(m2, m2_);
|
|
|
|
copy_m4_m4(m3, m3_);
|
|
|
|
|
2010-03-22 09:30:00 +00:00
|
|
|
/* m1[i][j] = m2[i][k] * m3[k][j] */
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0];
|
|
|
|
m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1];
|
|
|
|
m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0];
|
|
|
|
m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1];
|
|
|
|
m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0];
|
|
|
|
m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1];
|
|
|
|
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_m4_m3m4(float m1[4][4], float m3_[3][3], float m2_[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-09-16 15:25:28 +00:00
|
|
|
float m2[4][4], m3[3][3];
|
|
|
|
|
|
|
|
/* copy so it works when m1 is the same pointer as m2 or m3 */
|
|
|
|
copy_m4_m4(m2, m2_);
|
|
|
|
copy_m3_m3(m3, m3_);
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0];
|
|
|
|
m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1];
|
|
|
|
m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2];
|
|
|
|
m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0];
|
|
|
|
m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1];
|
|
|
|
m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2];
|
|
|
|
m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0];
|
|
|
|
m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1];
|
|
|
|
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_serie_m3(float answ[3][3],
|
|
|
|
float m1[3][3], float m2[3][3], float m3[3][3],
|
|
|
|
float m4[3][3], float m5[3][3], float m6[3][3],
|
|
|
|
float m7[3][3], float m8[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float temp[3][3];
|
2012-03-25 12:41:58 +00:00
|
|
|
|
|
|
|
if (m1 == NULL || m2 == NULL) return;
|
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(answ, m2, m1);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m3) {
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(temp, m3, answ);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m4) {
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(answ, m4, temp);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m5) {
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(temp, m5, answ);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m6) {
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(answ, m6, temp);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m7) {
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(temp, m7, answ);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m8) {
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(answ, m8, temp);
|
|
|
|
}
|
|
|
|
else copy_m3_m3(answ, temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else copy_m3_m3(answ, temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else copy_m3_m3(answ, temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_serie_m4(float answ[4][4], float m1[4][4],
|
|
|
|
float m2[4][4], float m3[4][4], float m4[4][4],
|
|
|
|
float m5[4][4], float m6[4][4], float m7[4][4],
|
|
|
|
float m8[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float temp[4][4];
|
2012-03-25 12:41:58 +00:00
|
|
|
|
|
|
|
if (m1 == NULL || m2 == NULL) return;
|
|
|
|
|
2013-05-26 18:36:25 +00:00
|
|
|
mul_m4_m4m4(answ, m1, m2);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m3) {
|
2013-05-26 18:36:25 +00:00
|
|
|
mul_m4_m4m4(temp, answ, m3);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m4) {
|
2013-05-26 18:36:25 +00:00
|
|
|
mul_m4_m4m4(answ, temp, m4);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m5) {
|
2013-05-26 18:36:25 +00:00
|
|
|
mul_m4_m4m4(temp, answ, m5);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m6) {
|
2013-05-26 18:36:25 +00:00
|
|
|
mul_m4_m4m4(answ, temp, m6);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m7) {
|
2013-05-26 18:36:25 +00:00
|
|
|
mul_m4_m4m4(temp, answ, m7);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (m8) {
|
2013-05-26 18:36:25 +00:00
|
|
|
mul_m4_m4m4(answ, temp, m8);
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
else copy_m4_m4(answ, temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else copy_m4_m4(answ, temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else copy_m4_m4(answ, temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-11 10:06:54 +00:00
|
|
|
void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
|
|
|
|
{
|
|
|
|
float temp[3], warped[3];
|
|
|
|
|
|
|
|
copy_v2_v2(temp, v);
|
|
|
|
temp[2] = 1.0f;
|
|
|
|
|
|
|
|
mul_v3_m3v3(warped, m, temp);
|
|
|
|
|
|
|
|
r[0] = warped[0] / warped[2];
|
|
|
|
r[1] = warped[1] / warped[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
void mul_m3_v2(float m[3][3], float r[2])
|
|
|
|
{
|
|
|
|
mul_v2_m3v2(r, m, r);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_m4_v3(float mat[4][4], float vec[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
float x, y;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
x = vec[0];
|
|
|
|
y = vec[1];
|
|
|
|
vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
|
|
|
|
vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
|
|
|
|
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2013-03-09 11:55:12 +00:00
|
|
|
void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
float x, y;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
x = vec[0];
|
|
|
|
y = vec[1];
|
2013-03-09 11:55:12 +00:00
|
|
|
r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
|
|
|
|
r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
|
|
|
|
r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2013-05-08 12:55:36 +00:00
|
|
|
void mul_v2_m4v3(float r[2], float mat[4][4], const float vec[3])
|
|
|
|
{
|
|
|
|
float x;
|
|
|
|
|
|
|
|
x = vec[0];
|
|
|
|
r[0] = x * mat[0][0] + vec[1] * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
|
|
|
|
r[1] = x * mat[0][1] + vec[1] * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
|
|
|
|
}
|
|
|
|
|
2013-02-12 00:35:31 +00:00
|
|
|
void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
|
2013-02-11 22:52:13 +00:00
|
|
|
{
|
2013-02-12 00:35:31 +00:00
|
|
|
float x;
|
|
|
|
|
|
|
|
x = vec[0];
|
|
|
|
r[0] = mat[0][0] * x + mat[1][0] * vec[1];
|
|
|
|
r[1] = mat[0][1] * x + mat[1][1] * vec[1];
|
2013-02-11 22:52:13 +00:00
|
|
|
}
|
|
|
|
|
2010-07-26 18:20:20 +00:00
|
|
|
/* same as mul_m4_v3() but doesnt apply translation component */
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_mat3_m4_v3(float mat[4][4], float vec[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
float x, y;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
x = vec[0];
|
|
|
|
y = vec[1];
|
|
|
|
vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2];
|
|
|
|
vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2];
|
|
|
|
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_project_m4_v3(float mat[4][4], float vec[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2013-03-09 15:39:24 +00:00
|
|
|
const float w = mul_project_m4_v3_zfac(mat, vec);
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m4_v3(mat, vec);
|
|
|
|
|
|
|
|
vec[0] /= w;
|
|
|
|
vec[1] /= w;
|
|
|
|
vec[2] /= w;
|
|
|
|
}
|
|
|
|
|
2013-05-08 12:55:36 +00:00
|
|
|
void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
|
|
|
|
{
|
|
|
|
const float w = mul_project_m4_v3_zfac(mat, vec);
|
|
|
|
mul_v2_m4v3(r, mat, vec);
|
|
|
|
|
|
|
|
r[0] /= w;
|
|
|
|
r[1] /= w;
|
|
|
|
}
|
|
|
|
|
2013-02-09 07:14:42 +00:00
|
|
|
void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2010-04-15 10:28:32 +00:00
|
|
|
float x, y, z;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
x = v[0];
|
|
|
|
y = v[1];
|
|
|
|
z = v[2];
|
2010-04-15 10:28:32 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
r[0] = x * mat[0][0] + y * mat[1][0] + z * mat[2][0] + mat[3][0] * v[3];
|
|
|
|
r[1] = x * mat[0][1] + y * mat[1][1] + z * mat[2][1] + mat[3][1] * v[3];
|
|
|
|
r[2] = x * mat[0][2] + y * mat[1][2] + z * mat[2][2] + mat[3][2] * v[3];
|
|
|
|
r[3] = x * mat[0][3] + y * mat[1][3] + z * mat[2][3] + mat[3][3] * v[3];
|
2010-04-15 10:28:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void mul_m4_v4(float mat[4][4], float r[4])
|
|
|
|
{
|
|
|
|
mul_v4_m4v4(r, mat, r);
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-03-08 11:57:51 +00:00
|
|
|
void mul_v4d_m4v4d(double r[4], float mat[4][4], double v[4])
|
|
|
|
{
|
|
|
|
double x, y, z;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
x = v[0];
|
|
|
|
y = v[1];
|
|
|
|
z = v[2];
|
2012-03-08 11:57:51 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
r[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + z * (double)mat[2][0] + (double)mat[3][0] * v[3];
|
|
|
|
r[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + z * (double)mat[2][1] + (double)mat[3][1] * v[3];
|
|
|
|
r[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + z * (double)mat[2][2] + (double)mat[3][2] * v[3];
|
|
|
|
r[3] = x * (double)mat[0][3] + y * (double)mat[1][3] + z * (double)mat[2][3] + (double)mat[3][3] * v[3];
|
2012-03-08 11:57:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void mul_m4_v4d(float mat[4][4], double r[4])
|
|
|
|
{
|
|
|
|
mul_v4d_m4v4d(r, mat, r);
|
|
|
|
}
|
|
|
|
|
2013-02-09 07:14:42 +00:00
|
|
|
void mul_v3_m3v3(float r[3], float M[3][3], const float a[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2013-08-06 02:37:02 +00:00
|
|
|
BLI_assert(r != a);
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
r[0] = M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2];
|
|
|
|
r[1] = M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
|
|
|
|
r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
|
2009-11-28 13:11:41 +00:00
|
|
|
}
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2013-02-09 07:14:42 +00:00
|
|
|
void mul_v2_m3v3(float r[2], float M[3][3], const float a[3])
|
2013-01-29 15:05:23 +00:00
|
|
|
{
|
2013-08-06 02:37:02 +00:00
|
|
|
BLI_assert(r != a);
|
|
|
|
|
2013-01-29 15:05:23 +00:00
|
|
|
r[0] = M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2];
|
|
|
|
r[1] = M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
|
|
|
|
}
|
|
|
|
|
2009-11-28 13:11:41 +00:00
|
|
|
void mul_m3_v3(float M[3][3], float r[3])
|
|
|
|
{
|
|
|
|
float tmp[3];
|
|
|
|
|
|
|
|
mul_v3_m3v3(tmp, M, r);
|
|
|
|
copy_v3_v3(r, tmp);
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_transposed_m3_v3(float mat[3][3], float vec[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
float x, y;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
x = vec[0];
|
|
|
|
y = vec[1];
|
|
|
|
vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2];
|
|
|
|
vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2];
|
|
|
|
vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2013-04-17 23:30:19 +00:00
|
|
|
void mul_transposed_mat3_m4_v3(float mat[4][4], float vec[3])
|
|
|
|
{
|
|
|
|
float x, y;
|
|
|
|
|
|
|
|
x = vec[0];
|
|
|
|
y = vec[1];
|
|
|
|
vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2];
|
|
|
|
vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2];
|
|
|
|
vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-10 19:13:05 +00:00
|
|
|
void mul_m3_fl(float m[3][3], float f)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2009-11-10 19:13:05 +00:00
|
|
|
int i, j;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
for (j = 0; j < 3; j++)
|
2009-11-10 19:13:05 +00:00
|
|
|
m[i][j] *= f;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2009-11-10 19:13:05 +00:00
|
|
|
void mul_m4_fl(float m[4][4], float f)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2009-11-10 19:13:05 +00:00
|
|
|
int i, j;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
for (j = 0; j < 4; j++)
|
2009-11-10 19:13:05 +00:00
|
|
|
m[i][j] *= f;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2009-11-10 19:13:05 +00:00
|
|
|
void mul_mat3_m4_fl(float m[4][4], float f)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2009-11-10 19:13:05 +00:00
|
|
|
int i, j;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
for (j = 0; j < 3; j++)
|
2009-11-10 19:13:05 +00:00
|
|
|
m[i][j] *= f;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mul_m3_v3_double(float mat[3][3], double vec[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
double x, y;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
x = vec[0];
|
|
|
|
y = vec[1];
|
|
|
|
vec[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + (double)mat[2][0] * vec[2];
|
|
|
|
vec[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + (double)mat[2][1] * vec[2];
|
|
|
|
vec[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + (double)mat[2][2] * vec[2];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void add_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
for (j = 0; j < 3; j++)
|
|
|
|
m1[i][j] = m2[i][j] + m3[i][j];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void add_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
for (j = 0; j < 4; j++)
|
|
|
|
m1[i][j] = m2[i][j] + m3[i][j];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void sub_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
for (j = 0; j < 3; j++)
|
|
|
|
m1[i][j] = m2[i][j] - m3[i][j];
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void sub_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
for (j = 0; j < 4; j++)
|
|
|
|
m1[i][j] = m2[i][j] - m3[i][j];
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
2012-12-14 21:41:22 +00:00
|
|
|
float determinant_m3_array(float m[3][3])
|
2012-11-07 09:28:59 +00:00
|
|
|
{
|
|
|
|
return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
|
|
|
|
m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
|
|
|
|
m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
|
|
|
|
}
|
|
|
|
|
|
|
|
int invert_m3_ex(float m[3][3], const float epsilon)
|
|
|
|
{
|
|
|
|
float tmp[3][3];
|
|
|
|
int success;
|
|
|
|
|
|
|
|
success = invert_m3_m3_ex(tmp, m, epsilon);
|
|
|
|
copy_m3_m3(m, tmp);
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
int invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon)
|
|
|
|
{
|
|
|
|
float det;
|
|
|
|
int a, b, success;
|
|
|
|
|
|
|
|
BLI_assert(epsilon >= 0.0f);
|
|
|
|
|
|
|
|
/* calc adjoint */
|
|
|
|
adjoint_m3_m3(m1, m2);
|
|
|
|
|
|
|
|
/* then determinant old matrix! */
|
2012-12-14 21:41:22 +00:00
|
|
|
det = determinant_m3_array(m2);
|
2012-11-07 09:28:59 +00:00
|
|
|
|
|
|
|
success = (fabsf(det) > epsilon);
|
|
|
|
|
|
|
|
if (LIKELY(det != 0.0f)) {
|
|
|
|
det = 1.0f / det;
|
|
|
|
for (a = 0; a < 3; a++) {
|
|
|
|
for (b = 0; b < 3; b++) {
|
|
|
|
m1[a][b] *= det;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2009-11-10 19:13:05 +00:00
|
|
|
int invert_m3(float m[3][3])
|
|
|
|
{
|
|
|
|
float tmp[3][3];
|
|
|
|
int success;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
success = invert_m3_m3(tmp, m);
|
2009-11-10 19:13:05 +00:00
|
|
|
copy_m3_m3(m, tmp);
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
int invert_m3_m3(float m1[3][3], float m2[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float det;
|
2009-11-10 19:13:05 +00:00
|
|
|
int a, b, success;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
/* calc adjoint */
|
2012-03-25 12:41:58 +00:00
|
|
|
adjoint_m3_m3(m1, m2);
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
/* then determinant old matrix! */
|
2012-12-14 21:41:22 +00:00
|
|
|
det = determinant_m3_array(m2);
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-11-07 09:28:59 +00:00
|
|
|
success = (det != 0.0f);
|
2009-11-10 19:13:05 +00:00
|
|
|
|
2012-11-07 09:28:59 +00:00
|
|
|
if (LIKELY(det != 0.0f)) {
|
|
|
|
det = 1.0f / det;
|
|
|
|
for (a = 0; a < 3; a++) {
|
|
|
|
for (b = 0; b < 3; b++) {
|
|
|
|
m1[a][b] *= det;
|
|
|
|
}
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-10 19:13:05 +00:00
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
int invert_m4(float m[4][4])
|
|
|
|
{
|
|
|
|
float tmp[4][4];
|
|
|
|
int success;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
success = invert_m4_m4(tmp, m);
|
2009-11-10 19:13:05 +00:00
|
|
|
copy_m4_m4(m, tmp);
|
|
|
|
|
|
|
|
return success;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2012-03-25 12:41:58 +00:00
|
|
|
* invertmat -
|
2012-03-25 15:56:17 +00:00
|
|
|
* computes the inverse of mat and puts it in inverse. Returns
|
|
|
|
* TRUE on success (i.e. can always find a pivot) and FALSE on failure.
|
|
|
|
* Uses Gaussian Elimination with partial (maximal column) pivoting.
|
2009-11-09 22:42:41 +00:00
|
|
|
*
|
|
|
|
* Mark Segal - 1992
|
|
|
|
*/
|
|
|
|
|
2009-11-10 19:13:05 +00:00
|
|
|
int invert_m4_m4(float inverse[4][4], float mat[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
int i, j, k;
|
|
|
|
double temp;
|
|
|
|
float tempmat[4][4];
|
|
|
|
float max;
|
|
|
|
int maxj;
|
|
|
|
|
2012-12-14 00:49:55 +00:00
|
|
|
BLI_assert(inverse != mat);
|
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* Set inverse to identity */
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
for (j = 0; j < 4; j++)
|
2009-11-09 22:42:41 +00:00
|
|
|
inverse[i][j] = 0;
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
2009-11-09 22:42:41 +00:00
|
|
|
inverse[i][i] = 1;
|
|
|
|
|
|
|
|
/* Copy original matrix so we don't mess it up */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
2012-03-25 12:41:58 +00:00
|
|
|
for (j = 0; j < 4; j++)
|
2009-11-09 22:42:41 +00:00
|
|
|
tempmat[i][j] = mat[i][j];
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i < 4; i++) {
|
2009-11-09 22:42:41 +00:00
|
|
|
/* Look for row with max pivot */
|
|
|
|
max = fabs(tempmat[i][i]);
|
|
|
|
maxj = i;
|
2012-03-24 06:18:31 +00:00
|
|
|
for (j = i + 1; j < 4; j++) {
|
|
|
|
if (fabsf(tempmat[j][i]) > max) {
|
2009-11-09 22:42:41 +00:00
|
|
|
max = fabs(tempmat[j][i]);
|
|
|
|
maxj = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Swap rows if necessary */
|
|
|
|
if (maxj != i) {
|
2012-03-24 06:18:31 +00:00
|
|
|
for (k = 0; k < 4; k++) {
|
2009-11-09 22:42:41 +00:00
|
|
|
SWAP(float, tempmat[i][k], tempmat[maxj][k]);
|
|
|
|
SWAP(float, inverse[i][k], inverse[maxj][k]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
temp = tempmat[i][i];
|
|
|
|
if (temp == 0)
|
2012-03-25 15:56:17 +00:00
|
|
|
return 0; /* No non-zero pivot */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (k = 0; k < 4; k++) {
|
2012-11-04 07:18:29 +00:00
|
|
|
tempmat[i][k] = (float)((double)tempmat[i][k] / temp);
|
|
|
|
inverse[i][k] = (float)((double)inverse[i][k] / temp);
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
if (j != i) {
|
2009-11-09 22:42:41 +00:00
|
|
|
temp = tempmat[j][i];
|
2012-03-24 06:18:31 +00:00
|
|
|
for (k = 0; k < 4; k++) {
|
2012-11-04 07:18:29 +00:00
|
|
|
tempmat[j][k] -= (float)((double)tempmat[i][k] * temp);
|
|
|
|
inverse[j][k] -= (float)((double)inverse[i][k] * temp);
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************** Linear Algebra *******************************/
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void transpose_m3(float mat[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float t;
|
|
|
|
|
2012-02-27 10:35:39 +00:00
|
|
|
t = mat[0][1];
|
|
|
|
mat[0][1] = mat[1][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
mat[1][0] = t;
|
2012-02-27 10:35:39 +00:00
|
|
|
t = mat[0][2];
|
|
|
|
mat[0][2] = mat[2][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
mat[2][0] = t;
|
2012-02-27 10:35:39 +00:00
|
|
|
t = mat[1][2];
|
|
|
|
mat[1][2] = mat[2][1];
|
2009-11-09 22:42:41 +00:00
|
|
|
mat[2][1] = t;
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void transpose_m4(float mat[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float t;
|
|
|
|
|
2012-02-27 10:35:39 +00:00
|
|
|
t = mat[0][1];
|
|
|
|
mat[0][1] = mat[1][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
mat[1][0] = t;
|
2012-02-27 10:35:39 +00:00
|
|
|
t = mat[0][2];
|
|
|
|
mat[0][2] = mat[2][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
mat[2][0] = t;
|
2012-02-27 10:35:39 +00:00
|
|
|
t = mat[0][3];
|
|
|
|
mat[0][3] = mat[3][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
mat[3][0] = t;
|
|
|
|
|
2012-02-27 10:35:39 +00:00
|
|
|
t = mat[1][2];
|
|
|
|
mat[1][2] = mat[2][1];
|
2009-11-09 22:42:41 +00:00
|
|
|
mat[2][1] = t;
|
2012-02-27 10:35:39 +00:00
|
|
|
t = mat[1][3];
|
|
|
|
mat[1][3] = mat[3][1];
|
2009-11-09 22:42:41 +00:00
|
|
|
mat[3][1] = t;
|
|
|
|
|
2012-02-27 10:35:39 +00:00
|
|
|
t = mat[2][3];
|
|
|
|
mat[2][3] = mat[3][2];
|
2009-11-09 22:42:41 +00:00
|
|
|
mat[3][2] = t;
|
|
|
|
}
|
|
|
|
|
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 17:39:20 +00:00
|
|
|
int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit)
|
|
|
|
{
|
|
|
|
if (compare_v4v4(mat1[0], mat2[0], limit))
|
|
|
|
if (compare_v4v4(mat1[1], mat2[1], limit))
|
|
|
|
if (compare_v4v4(mat1[2], mat2[2], limit))
|
|
|
|
if (compare_v4v4(mat1[3], mat2[3], limit))
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void orthogonalize_m3(float mat[3][3], int axis)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float size[3];
|
2010-08-15 15:14:08 +00:00
|
|
|
mat3_to_size(size, mat);
|
2009-11-09 22:42:41 +00:00
|
|
|
normalize_v3(mat[axis]);
|
2012-03-25 12:41:58 +00:00
|
|
|
switch (axis) {
|
2009-11-09 22:42:41 +00:00
|
|
|
case 0:
|
|
|
|
if (dot_v3v3(mat[0], mat[1]) < 1) {
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
|
|
|
normalize_v3(mat[2]);
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (dot_v3v3(mat[0], mat[2]) < 1) {
|
2009-11-09 22:42:41 +00:00
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
|
|
|
normalize_v3(mat[1]);
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-11-02 13:12:30 +00:00
|
|
|
float vec[3];
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
vec[0] = mat[0][1];
|
|
|
|
vec[1] = mat[0][2];
|
|
|
|
vec[2] = mat[0][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], vec);
|
|
|
|
normalize_v3(mat[2]);
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
|
|
|
}
|
2013-07-13 06:54:44 +00:00
|
|
|
break;
|
2009-11-09 22:42:41 +00:00
|
|
|
case 1:
|
|
|
|
if (dot_v3v3(mat[1], mat[0]) < 1) {
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
|
|
|
normalize_v3(mat[2]);
|
|
|
|
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (dot_v3v3(mat[0], mat[2]) < 1) {
|
2009-11-09 22:42:41 +00:00
|
|
|
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
|
|
|
normalize_v3(mat[0]);
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-11-02 13:12:30 +00:00
|
|
|
float vec[3];
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
vec[0] = mat[1][1];
|
|
|
|
vec[1] = mat[1][2];
|
|
|
|
vec[2] = mat[1][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
cross_v3_v3v3(mat[0], mat[1], vec);
|
|
|
|
normalize_v3(mat[0]);
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
|
|
|
}
|
2013-07-13 06:54:44 +00:00
|
|
|
break;
|
2009-11-09 22:42:41 +00:00
|
|
|
case 2:
|
|
|
|
if (dot_v3v3(mat[2], mat[0]) < 1) {
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
|
|
|
normalize_v3(mat[1]);
|
|
|
|
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (dot_v3v3(mat[2], mat[1]) < 1) {
|
2009-11-09 22:42:41 +00:00
|
|
|
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
|
|
|
normalize_v3(mat[0]);
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-11-02 13:12:30 +00:00
|
|
|
float vec[3];
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
vec[0] = mat[2][1];
|
|
|
|
vec[1] = mat[2][2];
|
|
|
|
vec[2] = mat[2][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
cross_v3_v3v3(mat[0], vec, mat[2]);
|
|
|
|
normalize_v3(mat[0]);
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
|
|
|
}
|
2013-07-16 11:39:48 +00:00
|
|
|
break;
|
2013-07-13 06:54:44 +00:00
|
|
|
default:
|
|
|
|
BLI_assert(0);
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
mul_v3_fl(mat[0], size[0]);
|
|
|
|
mul_v3_fl(mat[1], size[1]);
|
|
|
|
mul_v3_fl(mat[2], size[2]);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void orthogonalize_m4(float mat[4][4], int axis)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float size[3];
|
2010-08-15 15:14:08 +00:00
|
|
|
mat4_to_size(size, mat);
|
2009-11-09 22:42:41 +00:00
|
|
|
normalize_v3(mat[axis]);
|
2012-03-25 12:41:58 +00:00
|
|
|
switch (axis) {
|
2009-11-09 22:42:41 +00:00
|
|
|
case 0:
|
|
|
|
if (dot_v3v3(mat[0], mat[1]) < 1) {
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
|
|
|
normalize_v3(mat[2]);
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (dot_v3v3(mat[0], mat[2]) < 1) {
|
2009-11-09 22:42:41 +00:00
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
|
|
|
normalize_v3(mat[1]);
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-11-02 13:12:30 +00:00
|
|
|
float vec[3];
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
vec[0] = mat[0][1];
|
|
|
|
vec[1] = mat[0][2];
|
|
|
|
vec[2] = mat[0][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], vec);
|
|
|
|
normalize_v3(mat[2]);
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
|
|
|
}
|
2013-07-13 06:54:44 +00:00
|
|
|
break;
|
2009-11-09 22:42:41 +00:00
|
|
|
case 1:
|
|
|
|
if (dot_v3v3(mat[1], mat[0]) < 1) {
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
|
|
|
normalize_v3(mat[2]);
|
|
|
|
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (dot_v3v3(mat[0], mat[2]) < 1) {
|
2009-11-09 22:42:41 +00:00
|
|
|
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
|
|
|
normalize_v3(mat[0]);
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-11-02 13:12:30 +00:00
|
|
|
float vec[3];
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
vec[0] = mat[1][1];
|
|
|
|
vec[1] = mat[1][2];
|
|
|
|
vec[2] = mat[1][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
cross_v3_v3v3(mat[0], mat[1], vec);
|
|
|
|
normalize_v3(mat[0]);
|
|
|
|
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
|
|
|
}
|
2013-07-13 06:54:44 +00:00
|
|
|
break;
|
2009-11-09 22:42:41 +00:00
|
|
|
case 2:
|
|
|
|
if (dot_v3v3(mat[2], mat[0]) < 1) {
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
|
|
|
normalize_v3(mat[1]);
|
|
|
|
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (dot_v3v3(mat[2], mat[1]) < 1) {
|
2009-11-09 22:42:41 +00:00
|
|
|
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
|
|
|
normalize_v3(mat[0]);
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-11-02 13:12:30 +00:00
|
|
|
float vec[3];
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
vec[0] = mat[2][1];
|
|
|
|
vec[1] = mat[2][2];
|
|
|
|
vec[2] = mat[2][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
cross_v3_v3v3(mat[0], vec, mat[2]);
|
|
|
|
normalize_v3(mat[0]);
|
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
|
|
|
}
|
2013-07-13 06:54:44 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BLI_assert(0);
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
mul_v3_fl(mat[0], size[0]);
|
|
|
|
mul_v3_fl(mat[1], size[1]);
|
|
|
|
mul_v3_fl(mat[2], size[2]);
|
|
|
|
}
|
|
|
|
|
2013-07-26 11:15:22 +00:00
|
|
|
bool is_orthogonal_m3(float m[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-24 07:36:32 +00:00
|
|
|
int i, j;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-24 07:36:32 +00:00
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
for (j = 0; j < i; j++) {
|
|
|
|
if (fabsf(dot_v3v3(m[i], m[j])) > 1.5f * FLT_EPSILON)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2012-01-26 17:11:43 +00:00
|
|
|
|
2012-03-24 07:36:32 +00:00
|
|
|
return 1;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2013-07-26 11:15:22 +00:00
|
|
|
bool is_orthogonal_m4(float m[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-24 07:36:32 +00:00
|
|
|
int i, j;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-24 07:36:32 +00:00
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
for (j = 0; j < i; j++) {
|
2013-12-04 09:23:29 +11:00
|
|
|
if (fabsf(dot_v4v4(m[i], m[j])) > 1.5f * FLT_EPSILON)
|
2012-03-24 07:36:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-24 07:36:32 +00:00
|
|
|
}
|
2012-01-26 17:11:43 +00:00
|
|
|
|
2012-03-24 07:36:32 +00:00
|
|
|
return 1;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2013-07-26 11:15:22 +00:00
|
|
|
bool is_orthonormal_m3(float m[3][3])
|
2012-04-01 00:14:41 +00:00
|
|
|
{
|
|
|
|
if (is_orthogonal_m3(m)) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-07-26 11:15:22 +00:00
|
|
|
bool is_orthonormal_m4(float m[4][4])
|
2012-04-01 00:14:41 +00:00
|
|
|
{
|
|
|
|
if (is_orthogonal_m4(m)) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
2013-12-04 09:23:29 +11:00
|
|
|
if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON)
|
2012-04-01 00:14:41 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-07-26 11:15:22 +00:00
|
|
|
bool is_uniform_scaled_m3(float m[3][3])
|
2012-05-01 11:01:24 +00:00
|
|
|
{
|
|
|
|
const float eps = 1e-7;
|
|
|
|
float t[3][3];
|
|
|
|
float l1, l2, l3, l4, l5, l6;
|
|
|
|
|
|
|
|
copy_m3_m3(t, m);
|
|
|
|
transpose_m3(t);
|
|
|
|
|
|
|
|
l1 = len_squared_v3(m[0]);
|
|
|
|
l2 = len_squared_v3(m[1]);
|
|
|
|
l3 = len_squared_v3(m[2]);
|
|
|
|
|
|
|
|
l4 = len_squared_v3(t[0]);
|
|
|
|
l5 = len_squared_v3(t[1]);
|
|
|
|
l6 = len_squared_v3(t[2]);
|
|
|
|
|
|
|
|
if (fabsf(l2 - l1) <= eps &&
|
|
|
|
fabsf(l3 - l1) <= eps &&
|
|
|
|
fabsf(l4 - l1) <= eps &&
|
|
|
|
fabsf(l5 - l1) <= eps &&
|
|
|
|
fabsf(l6 - l1) <= eps)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void normalize_m3(float mat[3][3])
|
2012-03-25 12:41:58 +00:00
|
|
|
{
|
2009-11-09 22:42:41 +00:00
|
|
|
normalize_v3(mat[0]);
|
|
|
|
normalize_v3(mat[1]);
|
|
|
|
normalize_v3(mat[2]);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void normalize_m3_m3(float rmat[3][3], float mat[3][3])
|
2012-03-25 12:41:58 +00:00
|
|
|
{
|
2010-10-18 02:36:43 +00:00
|
|
|
normalize_v3_v3(rmat[0], mat[0]);
|
|
|
|
normalize_v3_v3(rmat[1], mat[1]);
|
|
|
|
normalize_v3_v3(rmat[2], mat[2]);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void normalize_m4(float mat[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float len;
|
2012-03-25 12:41:58 +00:00
|
|
|
|
|
|
|
len = normalize_v3(mat[0]);
|
|
|
|
if (len != 0.0f) mat[0][3] /= len;
|
|
|
|
len = normalize_v3(mat[1]);
|
|
|
|
if (len != 0.0f) mat[1][3] /= len;
|
|
|
|
len = normalize_v3(mat[2]);
|
|
|
|
if (len != 0.0f) mat[2][3] /= len;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void normalize_m4_m4(float rmat[4][4], float mat[4][4])
|
2010-10-18 02:36:43 +00:00
|
|
|
{
|
2013-01-23 14:37:12 +00:00
|
|
|
copy_m4_m4(rmat, mat);
|
|
|
|
normalize_m4(rmat);
|
2010-10-18 02:36:43 +00:00
|
|
|
}
|
|
|
|
|
2012-12-23 08:20:44 +00:00
|
|
|
void adjoint_m2_m2(float m1[2][2], float m[2][2])
|
2012-10-29 03:36:55 +00:00
|
|
|
{
|
|
|
|
BLI_assert(m1 != m);
|
|
|
|
m1[0][0] = m[1][1];
|
2013-05-12 09:26:02 +00:00
|
|
|
m1[0][1] = -m[0][1];
|
|
|
|
m1[1][0] = -m[1][0];
|
2012-10-29 03:36:55 +00:00
|
|
|
m1[1][1] = m[0][0];
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void adjoint_m3_m3(float m1[3][3], float m[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-10-29 03:36:55 +00:00
|
|
|
BLI_assert(m1 != m);
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
|
|
|
|
m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1];
|
|
|
|
m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[1][0] = -m[1][0] * m[2][2] + m[1][2] * m[2][0];
|
|
|
|
m1[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];
|
|
|
|
m1[1][2] = -m[0][0] * m[1][2] + m[0][2] * m[1][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
m1[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];
|
|
|
|
m1[2][1] = -m[0][0] * m[2][1] + m[0][1] * m[2][0];
|
|
|
|
m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void adjoint_m4_m4(float out[4][4], float in[4][4]) /* out = ADJ(in) */
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float a1, a2, a3, a4, b1, b2, b3, b4;
|
|
|
|
float c1, c2, c3, c4, d1, d2, d3, d4;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
a1 = in[0][0];
|
|
|
|
b1 = in[0][1];
|
|
|
|
c1 = in[0][2];
|
|
|
|
d1 = in[0][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
a2 = in[1][0];
|
|
|
|
b2 = in[1][1];
|
|
|
|
c2 = in[1][2];
|
|
|
|
d2 = in[1][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
a3 = in[2][0];
|
|
|
|
b3 = in[2][1];
|
|
|
|
c3 = in[2][2];
|
|
|
|
d3 = in[2][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
a4 = in[3][0];
|
|
|
|
b4 = in[3][1];
|
|
|
|
c4 = in[3][2];
|
|
|
|
d4 = in[3][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
out[0][0] = determinant_m3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
|
|
|
|
out[1][0] = -determinant_m3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
|
|
|
|
out[2][0] = determinant_m3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
|
|
|
|
out[3][0] = -determinant_m3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
out[0][1] = -determinant_m3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
|
|
|
|
out[1][1] = determinant_m3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
|
|
|
|
out[2][1] = -determinant_m3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
|
|
|
|
out[3][1] = determinant_m3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
out[0][2] = determinant_m3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
|
|
|
|
out[1][2] = -determinant_m3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
|
|
|
|
out[2][2] = determinant_m3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
|
|
|
|
out[3][2] = -determinant_m3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
out[0][3] = -determinant_m3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
|
|
|
|
out[1][3] = determinant_m3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
|
|
|
|
out[2][3] = -determinant_m3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
|
|
|
|
out[3][3] = determinant_m3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
float determinant_m2(float a, float b, float c, float d)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
return a * d - b * c;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float determinant_m3(float a1, float a2, float a3,
|
2012-03-25 12:41:58 +00:00
|
|
|
float b1, float b2, float b3,
|
|
|
|
float c1, float c2, float c3)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float ans;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
ans = (a1 * determinant_m2(b2, b3, c2, c3) -
|
|
|
|
b1 * determinant_m2(a2, a3, c2, c3) +
|
|
|
|
c1 * determinant_m2(a2, a3, b2, b3));
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
return ans;
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
float determinant_m4(float m[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float ans;
|
2012-03-25 12:41:58 +00:00
|
|
|
float a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
a1 = m[0][0];
|
|
|
|
b1 = m[0][1];
|
|
|
|
c1 = m[0][2];
|
|
|
|
d1 = m[0][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
a2 = m[1][0];
|
|
|
|
b2 = m[1][1];
|
|
|
|
c2 = m[1][2];
|
|
|
|
d2 = m[1][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
a3 = m[2][0];
|
|
|
|
b3 = m[2][1];
|
|
|
|
c3 = m[2][2];
|
|
|
|
d3 = m[2][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
a4 = m[3][0];
|
|
|
|
b4 = m[3][1];
|
|
|
|
c4 = m[3][2];
|
|
|
|
d4 = m[3][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
ans = (a1 * determinant_m3(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
|
|
|
|
b1 * determinant_m3(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
|
|
|
|
c1 * determinant_m3(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
|
|
|
|
d1 * determinant_m3(a2, a3, a4, b2, b3, b4, c2, c3, c4));
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
return ans;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************** Transformations ******************************/
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void size_to_mat3(float mat[3][3], const float size[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
mat[0][0] = size[0];
|
|
|
|
mat[0][1] = 0.0f;
|
|
|
|
mat[0][2] = 0.0f;
|
|
|
|
mat[1][1] = size[1];
|
|
|
|
mat[1][0] = 0.0f;
|
|
|
|
mat[1][2] = 0.0f;
|
|
|
|
mat[2][2] = size[2];
|
|
|
|
mat[2][1] = 0.0f;
|
|
|
|
mat[2][0] = 0.0f;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void size_to_mat4(float mat[4][4], const float size[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float tmat[3][3];
|
2012-03-25 12:41:58 +00:00
|
|
|
|
|
|
|
size_to_mat3(tmat, size);
|
2009-11-09 22:42:41 +00:00
|
|
|
unit_m4(mat);
|
|
|
|
copy_m4_m3(mat, tmat);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mat3_to_size(float size[3], float mat[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
size[0] = len_v3(mat[0]);
|
|
|
|
size[1] = len_v3(mat[1]);
|
|
|
|
size[2] = len_v3(mat[2]);
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mat4_to_size(float size[3], float mat[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
size[0] = len_v3(mat[0]);
|
|
|
|
size[1] = len_v3(mat[1]);
|
|
|
|
size[2] = len_v3(mat[2]);
|
2009-11-09 22:42:41 +00: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 */
|
2012-12-11 14:29:01 +00:00
|
|
|
float mat3_to_scale(float mat[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
/* unit length vector */
|
2013-07-10 12:12:58 +00:00
|
|
|
float unit_vec[3];
|
|
|
|
copy_v3_fl(unit_vec, 0.577350269189626f);
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_v3(mat, unit_vec);
|
|
|
|
return len_v3(unit_vec);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
float mat4_to_scale(float mat[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2013-07-10 12:12:58 +00:00
|
|
|
/* unit length vector */
|
|
|
|
float unit_vec[3];
|
|
|
|
copy_v3_fl(unit_vec, 0.577350269189626f);
|
|
|
|
mul_mat3_m4_v3(mat, unit_vec);
|
|
|
|
return len_v3(unit_vec);
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2010-11-22 10:39:28 +00:00
|
|
|
void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
|
2010-10-26 12:48:07 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
float mat3_n[3][3]; /* mat3 -> normalized, 3x3 */
|
2010-11-22 10:39:28 +00:00
|
|
|
float imat3_n[3][3]; /* mat3 -> normalized & inverted, 3x3 */
|
2010-10-26 12:48:07 +00:00
|
|
|
|
|
|
|
/* rotation & scale are linked, we need to create the mat's
|
|
|
|
* for these together since they are related. */
|
2010-11-22 10:39:28 +00:00
|
|
|
|
2012-07-18 11:01:23 +00:00
|
|
|
/* so scale doesn't interfere with rotation [#24291] */
|
2010-10-26 12:48:07 +00:00
|
|
|
/* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */
|
2010-10-26 20:41:16 +00:00
|
|
|
normalize_m3_m3(mat3_n, mat3);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (is_negative_m3(mat3)) {
|
2010-10-26 12:48:07 +00:00
|
|
|
negate_v3(mat3_n[0]);
|
|
|
|
negate_v3(mat3_n[1]);
|
|
|
|
negate_v3(mat3_n[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* rotation */
|
|
|
|
/* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */
|
|
|
|
copy_m3_m3(rot, mat3_n);
|
|
|
|
|
|
|
|
/* scale */
|
|
|
|
/* note: mat4_to_size(ob->size, mat) fails for negative scale */
|
|
|
|
invert_m3_m3(imat3_n, mat3_n);
|
|
|
|
mul_m3_m3m3(mat3, imat3_n, mat3);
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
size[0] = mat3[0][0];
|
|
|
|
size[1] = mat3[1][1];
|
|
|
|
size[2] = mat3[2][2];
|
2010-10-26 12:48:07 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4])
|
2010-11-22 10:39:28 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
float mat3[3][3]; /* wmat -> 3x3 */
|
2010-11-22 10:39:28 +00:00
|
|
|
|
|
|
|
copy_m3_m4(mat3, wmat);
|
|
|
|
mat3_to_rot_size(rot, size, mat3);
|
|
|
|
|
|
|
|
/* location */
|
|
|
|
copy_v3_v3(loc, wmat[3]);
|
|
|
|
}
|
|
|
|
|
2013-01-23 05:56:05 +00:00
|
|
|
void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4])
|
|
|
|
{
|
|
|
|
float mat3[3][3];
|
|
|
|
float mat3_n[3][3]; /* normalized mat3 */
|
|
|
|
|
|
|
|
copy_m3_m4(mat3, wmat);
|
|
|
|
normalize_m3_m3(mat3_n, mat3);
|
|
|
|
|
|
|
|
/* so scale doesn't interfere with rotation [#24291] */
|
|
|
|
/* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */
|
|
|
|
if (is_negative_m3(mat3)) {
|
|
|
|
negate_v3(mat3_n[0]);
|
|
|
|
negate_v3(mat3_n[1]);
|
|
|
|
negate_v3(mat3_n[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
mat3_to_quat(quat, mat3_n);
|
|
|
|
copy_v3_v3(loc, wmat[3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4])
|
|
|
|
{
|
|
|
|
float rot[3][3];
|
|
|
|
mat4_to_loc_rot_size(loc, rot, size, wmat);
|
|
|
|
mat3_to_quat(quat, rot);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void scale_m3_fl(float m[3][3], float scale)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
m[0][0] = m[1][1] = m[2][2] = scale;
|
|
|
|
m[0][1] = m[0][2] = 0.0;
|
|
|
|
m[1][0] = m[1][2] = 0.0;
|
|
|
|
m[2][0] = m[2][1] = 0.0;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void scale_m4_fl(float m[4][4], float scale)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
m[0][0] = m[1][1] = m[2][2] = scale;
|
|
|
|
m[3][3] = 1.0;
|
|
|
|
m[0][1] = m[0][2] = m[0][3] = 0.0;
|
|
|
|
m[1][0] = m[1][2] = m[1][3] = 0.0;
|
|
|
|
m[2][0] = m[2][1] = m[2][3] = 0.0;
|
|
|
|
m[3][0] = m[3][1] = m[3][2] = 0.0;
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2012-03-25 12:41:58 +00:00
|
|
|
mat[3][0] += (Tx * mat[0][0] + Ty * mat[1][0] + Tz * mat[2][0]);
|
|
|
|
mat[3][1] += (Tx * mat[0][1] + Ty * mat[1][1] + Tz * mat[2][1]);
|
|
|
|
mat[3][2] += (Tx * mat[0][2] + Ty * mat[1][2] + Tz * mat[2][2]);
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void rotate_m4(float mat[4][4], const char axis, const float angle)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
int col;
|
2012-03-25 12:41:58 +00:00
|
|
|
float temp[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
2010-03-22 09:30:00 +00:00
|
|
|
float cosine, sine;
|
|
|
|
|
2010-11-16 01:19:37 +00:00
|
|
|
assert(axis >= 'X' && axis <= 'Z');
|
|
|
|
|
2013-01-12 14:28:23 +00:00
|
|
|
cosine = cosf(angle);
|
|
|
|
sine = sinf(angle);
|
2012-02-27 10:35:39 +00:00
|
|
|
switch (axis) {
|
2012-03-25 12:41:58 +00:00
|
|
|
case 'X':
|
|
|
|
for (col = 0; col < 4; col++)
|
|
|
|
temp[col] = cosine * mat[1][col] + sine * mat[2][col];
|
|
|
|
for (col = 0; col < 4; col++) {
|
|
|
|
mat[2][col] = -sine * mat[1][col] + cosine * mat[2][col];
|
|
|
|
mat[1][col] = temp[col];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'Y':
|
|
|
|
for (col = 0; col < 4; col++)
|
|
|
|
temp[col] = cosine * mat[0][col] - sine * mat[2][col];
|
|
|
|
for (col = 0; col < 4; col++) {
|
|
|
|
mat[2][col] = sine * mat[0][col] + cosine * mat[2][col];
|
|
|
|
mat[0][col] = temp[col];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'Z':
|
|
|
|
for (col = 0; col < 4; col++)
|
|
|
|
temp[col] = cosine * mat[0][col] + sine * mat[1][col];
|
|
|
|
for (col = 0; col < 4; col++) {
|
|
|
|
mat[1][col] = -sine * mat[0][col] + cosine * mat[1][col];
|
|
|
|
mat[0][col] = temp[col];
|
|
|
|
}
|
|
|
|
break;
|
2010-03-22 09:30:00 +00:00
|
|
|
}
|
2009-11-09 22:42:41 +00:00
|
|
|
}
|
|
|
|
|
2013-02-11 22:52:13 +00:00
|
|
|
void rotate_m2(float mat[2][2], const float angle)
|
|
|
|
{
|
|
|
|
mat[0][0] = mat[1][1] = cosf(angle);
|
|
|
|
mat[0][1] = sinf(angle);
|
|
|
|
mat[1][0] = -mat[0][1];
|
|
|
|
}
|
|
|
|
|
2013-07-30 10:58:36 +00: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.
|
|
|
|
*/
|
|
|
|
void transform_pivot_set_m4(float mat[4][4], const float pivot[3])
|
2013-07-26 06:12:49 +00:00
|
|
|
{
|
|
|
|
float tmat[4][4];
|
|
|
|
|
|
|
|
unit_m4(tmat);
|
|
|
|
|
|
|
|
copy_v3_v3(tmat[3], pivot);
|
|
|
|
mul_m4_m4m4(mat, tmat, mat);
|
|
|
|
|
|
|
|
/* invert the matrix */
|
|
|
|
negate_v3(tmat[3]);
|
|
|
|
mul_m4_m4m4(mat, mat, tmat);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const float srcweight)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2010-11-22 10:39:28 +00:00
|
|
|
float srot[3][3], drot[3][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
float squat[4], dquat[4], fquat[4];
|
2011-12-04 03:35:54 +00:00
|
|
|
float sscale[3], dscale[3], fsize[3];
|
2009-11-09 22:42:41 +00:00
|
|
|
float rmat[3][3], smat[3][3];
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2011-12-04 03:35:54 +00:00
|
|
|
mat3_to_rot_size(drot, dscale, dst);
|
|
|
|
mat3_to_rot_size(srot, sscale, src);
|
2010-11-22 10:39:28 +00:00
|
|
|
|
|
|
|
mat3_to_quat(dquat, drot);
|
|
|
|
mat3_to_quat(squat, srot);
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
/* do blending */
|
|
|
|
interp_qt_qtqt(fquat, dquat, squat, srcweight);
|
2011-12-04 03:35:54 +00:00
|
|
|
interp_v3_v3v3(fsize, dscale, sscale, srcweight);
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
/* compose new matrix */
|
2012-03-25 12:41:58 +00:00
|
|
|
quat_to_mat3(rmat, fquat);
|
|
|
|
size_to_mat3(smat, fsize);
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(out, rmat, smat);
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const float srcweight)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
2010-11-22 10:39:28 +00:00
|
|
|
float sloc[3], dloc[3], floc[3];
|
|
|
|
float srot[3][3], drot[3][3];
|
2009-11-09 22:42:41 +00:00
|
|
|
float squat[4], dquat[4], fquat[4];
|
2011-12-04 03:35:54 +00:00
|
|
|
float sscale[3], dscale[3], fsize[3];
|
2009-11-09 22:42:41 +00:00
|
|
|
|
2011-12-04 03:35:54 +00:00
|
|
|
mat4_to_loc_rot_size(dloc, drot, dscale, dst);
|
|
|
|
mat4_to_loc_rot_size(sloc, srot, sscale, src);
|
2010-11-22 10:39:28 +00:00
|
|
|
|
|
|
|
mat3_to_quat(dquat, drot);
|
|
|
|
mat3_to_quat(squat, srot);
|
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* do blending */
|
|
|
|
interp_v3_v3v3(floc, dloc, sloc, srcweight);
|
|
|
|
interp_qt_qtqt(fquat, dquat, squat, srcweight);
|
2011-12-04 03:35:54 +00:00
|
|
|
interp_v3_v3v3(fsize, dscale, sscale, srcweight);
|
2009-11-09 22:42:41 +00:00
|
|
|
|
|
|
|
/* compose new matrix */
|
|
|
|
loc_quat_size_to_mat4(out, floc, fquat, fsize);
|
|
|
|
}
|
|
|
|
|
2013-07-26 11:15:22 +00:00
|
|
|
bool is_negative_m3(float mat[3][3])
|
2010-01-30 13:15:39 +00:00
|
|
|
{
|
|
|
|
float vec[3];
|
|
|
|
cross_v3_v3v3(vec, mat[0], mat[1]);
|
|
|
|
return (dot_v3v3(vec, mat[2]) < 0.0f);
|
|
|
|
}
|
|
|
|
|
2013-07-26 11:15:22 +00:00
|
|
|
bool is_negative_m4(float mat[4][4])
|
2010-01-30 13:15:39 +00:00
|
|
|
{
|
|
|
|
float vec[3];
|
|
|
|
cross_v3_v3v3(vec, mat[0], mat[1]);
|
|
|
|
return (dot_v3v3(vec, mat[2]) < 0.0f);
|
|
|
|
}
|
|
|
|
|
2013-07-26 11:15:22 +00:00
|
|
|
bool is_zero_m3(float mat[3][3])
|
|
|
|
{
|
|
|
|
return (is_zero_v3(mat[0]) &&
|
|
|
|
is_zero_v3(mat[1]) &&
|
|
|
|
is_zero_v3(mat[2]));
|
|
|
|
}
|
|
|
|
bool is_zero_m4(float mat[4][4])
|
|
|
|
{
|
|
|
|
return (is_zero_v4(mat[0]) &&
|
|
|
|
is_zero_v4(mat[1]) &&
|
|
|
|
is_zero_v4(mat[2]) &&
|
|
|
|
is_zero_v4(mat[3]));
|
|
|
|
}
|
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* make a 4x4 matrix out of 3 transform components */
|
|
|
|
/* matrices are made in the order: scale * rot * loc */
|
2012-07-06 23:56:59 +00:00
|
|
|
/* TODO: need to have a version that allows for rotation order... */
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2010-10-22 03:56:50 +00:00
|
|
|
void loc_eul_size_to_mat4(float mat[4][4], const float loc[3], const float eul[3], const float size[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float rmat[3][3], smat[3][3], tmat[3][3];
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2012-03-02 16:05:54 +00:00
|
|
|
/* initialize new matrix */
|
2009-11-09 22:42:41 +00:00
|
|
|
unit_m4(mat);
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* make rotation + scaling part */
|
2012-03-25 12:41:58 +00:00
|
|
|
eul_to_mat3(rmat, eul);
|
|
|
|
size_to_mat3(smat, size);
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(tmat, rmat, smat);
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* copy rot/scale part to output matrix*/
|
|
|
|
copy_m4_m3(mat, tmat);
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* copy location to matrix */
|
|
|
|
mat[3][0] = loc[0];
|
|
|
|
mat[3][1] = loc[1];
|
|
|
|
mat[3][2] = loc[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make a 4x4 matrix out of 3 transform components */
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* matrices are made in the order: scale * rot * loc */
|
2010-10-22 03:56:50 +00:00
|
|
|
void loc_eulO_size_to_mat4(float mat[4][4], const float loc[3], const float eul[3], const float size[3], const short rotOrder)
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float rmat[3][3], smat[3][3], tmat[3][3];
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2012-03-02 16:05:54 +00:00
|
|
|
/* initialize new matrix */
|
2009-11-09 22:42:41 +00:00
|
|
|
unit_m4(mat);
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* make rotation + scaling part */
|
2012-03-25 12:41:58 +00:00
|
|
|
eulO_to_mat3(rmat, eul, rotOrder);
|
|
|
|
size_to_mat3(smat, size);
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(tmat, rmat, smat);
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* copy rot/scale part to output matrix*/
|
|
|
|
copy_m4_m3(mat, tmat);
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* copy location to matrix */
|
|
|
|
mat[3][0] = loc[0];
|
|
|
|
mat[3][1] = loc[1];
|
|
|
|
mat[3][2] = loc[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* make a 4x4 matrix out of 3 transform components */
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* matrices are made in the order: scale * rot * loc */
|
2010-10-22 03:56:50 +00:00
|
|
|
void loc_quat_size_to_mat4(float mat[4][4], const float loc[3], const float quat[4], const float size[3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
float rmat[3][3], smat[3][3], tmat[3][3];
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2012-03-02 16:05:54 +00:00
|
|
|
/* initialize new matrix */
|
2009-11-09 22:42:41 +00:00
|
|
|
unit_m4(mat);
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* make rotation + scaling part */
|
2012-03-25 12:41:58 +00:00
|
|
|
quat_to_mat3(rmat, quat);
|
|
|
|
size_to_mat3(smat, size);
|
2009-11-09 22:42:41 +00:00
|
|
|
mul_m3_m3m3(tmat, rmat, smat);
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* copy rot/scale part to output matrix*/
|
|
|
|
copy_m4_m3(mat, tmat);
|
2012-03-25 12:41:58 +00:00
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/* copy location to matrix */
|
|
|
|
mat[3][0] = loc[0];
|
|
|
|
mat[3][1] = loc[1];
|
|
|
|
mat[3][2] = loc[2];
|
|
|
|
}
|
|
|
|
|
2010-10-22 03:56:50 +00:00
|
|
|
void loc_axisangle_size_to_mat4(float mat[4][4], const float loc[3], const float axis[3], const float angle, const float size[3])
|
|
|
|
{
|
|
|
|
float q[4];
|
|
|
|
axis_angle_to_quat(q, axis, angle);
|
|
|
|
loc_quat_size_to_mat4(mat, loc, q, size);
|
|
|
|
}
|
|
|
|
|
2009-11-09 22:42:41 +00:00
|
|
|
/*********************************** Other ***********************************/
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void print_m3(const char *str, float m[3][3])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
printf("%s\n", str);
|
2012-03-25 12:41:58 +00:00
|
|
|
printf("%f %f %f\n", m[0][0], m[1][0], m[2][0]);
|
|
|
|
printf("%f %f %f\n", m[0][1], m[1][1], m[2][1]);
|
|
|
|
printf("%f %f %f\n", m[0][2], m[1][2], m[2][2]);
|
2009-11-09 22:42:41 +00:00
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void print_m4(const char *str, float m[4][4])
|
2009-11-09 22:42:41 +00:00
|
|
|
{
|
|
|
|
printf("%s\n", str);
|
2012-03-25 12:41:58 +00:00
|
|
|
printf("%f %f %f %f\n", m[0][0], m[1][0], m[2][0], m[3][0]);
|
|
|
|
printf("%f %f %f %f\n", m[0][1], m[1][1], m[2][1], m[3][1]);
|
|
|
|
printf("%f %f %f %f\n", m[0][2], m[1][2], m[2][2], m[3][2]);
|
|
|
|
printf("%f %f %f %f\n", m[0][3], m[1][3], m[2][3], m[3][3]);
|
2009-11-09 22:42:41 +00:00
|
|
|
printf("\n");
|
|
|
|
}
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
/*********************************** SVD ************************************
|
|
|
|
* from TNT matrix library
|
2012-03-03 20:19:11 +00:00
|
|
|
*
|
2010-06-22 15:20:06 +00:00
|
|
|
* Compute the Single Value Decomposition of an arbitrary matrix A
|
2012-03-25 12:41:58 +00:00
|
|
|
* 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
|
2010-06-22 15:20:06 +00:00
|
|
|
* (pseudo-inverse) of A as Ainv = V.Winv.tranpose(U).
|
|
|
|
*/
|
|
|
|
|
|
|
|
void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
|
|
|
|
{
|
|
|
|
float A[4][4];
|
|
|
|
float work1[4], work2[4];
|
|
|
|
int m = 4;
|
|
|
|
int n = 4;
|
|
|
|
int maxiter = 200;
|
2012-10-23 13:28:22 +00:00
|
|
|
int nu = min_ff(m, n);
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
float *work = work1;
|
|
|
|
float *e = work2;
|
|
|
|
float eps;
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
int i = 0, j = 0, k = 0, p, pp, iter;
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Reduce A to bidiagonal form, storing the diagonal elements
|
|
|
|
* in s and the super-diagonal elements in e. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-23 13:28:22 +00:00
|
|
|
int nct = min_ff(m - 1, n);
|
|
|
|
int nrt = max_ff(0, min_ff(n - 2, m));
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
copy_m4_m4(A, A_);
|
|
|
|
zero_m4(U);
|
|
|
|
zero_v4(s);
|
|
|
|
|
2012-10-23 13:28:22 +00:00
|
|
|
for (k = 0; k < max_ff(nct, nrt); k++) {
|
2010-06-22 15:20:06 +00:00
|
|
|
if (k < nct) {
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Compute the transformation for the k-th column and
|
|
|
|
* place the k-th diagonal in s[k].
|
|
|
|
* Compute 2-norm of k-th column without under/overflow. */
|
2010-06-22 15:20:06 +00:00
|
|
|
s[k] = 0;
|
|
|
|
for (i = k; i < m; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
s[k] = hypotf(s[k], A[i][k]);
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
if (s[k] != 0.0f) {
|
|
|
|
float invsk;
|
|
|
|
if (A[k][k] < 0.0f) {
|
|
|
|
s[k] = -s[k];
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
invsk = 1.0f / s[k];
|
2010-06-22 15:20:06 +00:00
|
|
|
for (i = k; i < m; i++) {
|
|
|
|
A[i][k] *= invsk;
|
|
|
|
}
|
|
|
|
A[k][k] += 1.0f;
|
|
|
|
}
|
|
|
|
s[k] = -s[k];
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
for (j = k + 1; j < n; j++) {
|
2012-02-27 10:35:39 +00:00
|
|
|
if ((k < nct) && (s[k] != 0.0f)) {
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Apply the transformation. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
float t = 0;
|
|
|
|
for (i = k; i < m; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t += A[i][k] * A[i][j];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
t = -t / A[k][k];
|
2010-06-22 15:20:06 +00:00
|
|
|
for (i = k; i < m; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
A[i][j] += t * A[i][k];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Place the k-th row of A into e for the */
|
|
|
|
/* subsequent calculation of the row transformation. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
e[j] = A[k][j];
|
|
|
|
}
|
|
|
|
if (k < nct) {
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Place the transformation in U for subsequent back
|
|
|
|
* multiplication. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
for (i = k; i < m; i++)
|
|
|
|
U[i][k] = A[i][k];
|
|
|
|
}
|
|
|
|
if (k < nrt) {
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Compute the k-th row transformation and place the
|
|
|
|
* k-th super-diagonal in e[k].
|
|
|
|
* Compute 2-norm without under/overflow. */
|
2010-06-22 15:20:06 +00:00
|
|
|
e[k] = 0;
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = k + 1; i < n; i++) {
|
|
|
|
e[k] = hypotf(e[k], e[i]);
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
if (e[k] != 0.0f) {
|
|
|
|
float invek;
|
2012-03-25 12:41:58 +00:00
|
|
|
if (e[k + 1] < 0.0f) {
|
2010-06-22 15:20:06 +00:00
|
|
|
e[k] = -e[k];
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
invek = 1.0f / e[k];
|
|
|
|
for (i = k + 1; i < n; i++) {
|
2010-06-22 15:20:06 +00:00
|
|
|
e[i] *= invek;
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
e[k + 1] += 1.0f;
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
e[k] = -e[k];
|
2012-03-25 12:41:58 +00:00
|
|
|
if ((k + 1 < m) & (e[k] != 0.0f)) {
|
2010-06-22 15:20:06 +00:00
|
|
|
float invek1;
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Apply the transformation. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = k + 1; i < m; i++) {
|
2010-06-22 15:20:06 +00:00
|
|
|
work[i] = 0.0f;
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
for (j = k + 1; j < n; j++) {
|
|
|
|
for (i = k + 1; i < m; i++) {
|
|
|
|
work[i] += e[j] * A[i][j];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
invek1 = 1.0f / e[k + 1];
|
|
|
|
for (j = k + 1; j < n; j++) {
|
|
|
|
float t = -e[j] * invek1;
|
|
|
|
for (i = k + 1; i < m; i++) {
|
|
|
|
A[i][j] += t * work[i];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Place the transformation in V for subsequent
|
|
|
|
* back multiplication. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = k + 1; i < n; i++)
|
2010-06-22 15:20:06 +00:00
|
|
|
V[i][k] = e[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Set up the final bidiagonal matrix or order p. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-23 13:28:22 +00:00
|
|
|
p = min_ff(n, m + 1);
|
2010-06-22 15:20:06 +00:00
|
|
|
if (nct < n) {
|
|
|
|
s[nct] = A[nct][nct];
|
|
|
|
}
|
|
|
|
if (m < p) {
|
2012-03-25 12:41:58 +00:00
|
|
|
s[p - 1] = 0.0f;
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
if (nrt + 1 < p) {
|
|
|
|
e[nrt] = A[nrt][p - 1];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
e[p - 1] = 0.0f;
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* If required, generate U. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
for (j = nct; j < nu; j++) {
|
|
|
|
for (i = 0; i < m; i++) {
|
|
|
|
U[i][j] = 0.0f;
|
|
|
|
}
|
|
|
|
U[j][j] = 1.0f;
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
for (k = nct - 1; k >= 0; k--) {
|
2010-06-22 15:20:06 +00:00
|
|
|
if (s[k] != 0.0f) {
|
2012-03-25 12:41:58 +00:00
|
|
|
for (j = k + 1; j < nu; j++) {
|
2010-06-22 15:20:06 +00:00
|
|
|
float t = 0;
|
|
|
|
for (i = k; i < m; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t += U[i][k] * U[i][j];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
t = -t / U[k][k];
|
2010-06-22 15:20:06 +00:00
|
|
|
for (i = k; i < m; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
U[i][j] += t * U[i][k];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = k; i < m; i++) {
|
2010-06-22 15:20:06 +00:00
|
|
|
U[i][k] = -U[i][k];
|
|
|
|
}
|
|
|
|
U[k][k] = 1.0f + U[k][k];
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < k - 1; i++) {
|
2010-06-22 15:20:06 +00:00
|
|
|
U[i][k] = 0.0f;
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-06-22 15:20:06 +00:00
|
|
|
for (i = 0; i < m; i++) {
|
|
|
|
U[i][k] = 0.0f;
|
|
|
|
}
|
|
|
|
U[k][k] = 1.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* If required, generate V. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (k = n - 1; k >= 0; k--) {
|
2010-06-22 15:20:06 +00:00
|
|
|
if ((k < nrt) & (e[k] != 0.0f)) {
|
2012-03-25 12:41:58 +00:00
|
|
|
for (j = k + 1; j < nu; j++) {
|
2010-06-22 15:20:06 +00:00
|
|
|
float t = 0;
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = k + 1; i < n; i++) {
|
|
|
|
t += V[i][k] * V[i][j];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
t = -t / V[k + 1][k];
|
|
|
|
for (i = k + 1; i < n; i++) {
|
|
|
|
V[i][j] += t * V[i][k];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
V[i][k] = 0.0f;
|
|
|
|
}
|
|
|
|
V[k][k] = 1.0f;
|
|
|
|
}
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Main iteration loop for the singular values. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
pp = p - 1;
|
2010-06-22 15:20:06 +00:00
|
|
|
iter = 0;
|
2012-03-25 12:41:58 +00:00
|
|
|
eps = powf(2.0f, -52.0f);
|
2010-06-22 15:20:06 +00:00
|
|
|
while (p > 0) {
|
2012-03-25 12:41:58 +00:00
|
|
|
int kase = 0;
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Test for maximum iterations to avoid infinite loop */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (maxiter == 0)
|
2010-06-22 15:20:06 +00:00
|
|
|
break;
|
|
|
|
maxiter--;
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* This section of the program inspects for
|
|
|
|
* negligible elements in the s and e arrays. On
|
|
|
|
* completion the variables kase and k are set as follows.
|
|
|
|
*
|
|
|
|
* kase = 1 if s(p) and e[k - 1] are negligible and k<p
|
|
|
|
* kase = 2 if s(k) is negligible and k<p
|
|
|
|
* kase = 3 if e[k - 1] is negligible, k<p, and
|
|
|
|
* s(k), ..., s(p) are not negligible (qr step).
|
|
|
|
* kase = 4 if e(p - 1) is negligible (convergence). */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (k = p - 2; k >= -1; k--) {
|
2010-06-22 15:20:06 +00:00
|
|
|
if (k == -1) {
|
|
|
|
break;
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
if (fabsf(e[k]) <= eps * (fabsf(s[k]) + fabsf(s[k + 1]))) {
|
2010-06-22 15:20:06 +00:00
|
|
|
e[k] = 0.0f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
if (k == p - 2) {
|
2010-06-22 15:20:06 +00:00
|
|
|
kase = 4;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-06-22 15:20:06 +00:00
|
|
|
int ks;
|
2012-03-25 12:41:58 +00:00
|
|
|
for (ks = p - 1; ks >= k; ks--) {
|
2010-06-22 15:20:06 +00:00
|
|
|
float t;
|
|
|
|
if (ks == k) {
|
|
|
|
break;
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
t = (ks != p ? fabsf(e[ks]) : 0.f) +
|
2012-03-25 15:56:17 +00:00
|
|
|
(ks != k + 1 ? fabsf(e[ks - 1]) : 0.0f);
|
2012-03-25 12:41:58 +00:00
|
|
|
if (fabsf(s[ks]) <= eps * t) {
|
2010-06-22 15:20:06 +00:00
|
|
|
s[ks] = 0.0f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ks == k) {
|
|
|
|
kase = 3;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
else if (ks == p - 1) {
|
2010-06-22 15:20:06 +00:00
|
|
|
kase = 1;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-06-22 15:20:06 +00:00
|
|
|
kase = 2;
|
|
|
|
k = ks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
k++;
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Perform the task indicated by kase. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
switch (kase) {
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Deflate negligible s(p). */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
float f = e[p - 2];
|
|
|
|
e[p - 2] = 0.0f;
|
|
|
|
for (j = p - 2; j >= k; j--) {
|
|
|
|
float t = hypotf(s[j], f);
|
|
|
|
float invt = 1.0f / t;
|
|
|
|
float cs = s[j] * invt;
|
|
|
|
float sn = f * invt;
|
2010-06-22 15:20:06 +00:00
|
|
|
s[j] = t;
|
|
|
|
if (j != k) {
|
2012-03-25 12:41:58 +00:00
|
|
|
f = -sn * e[j - 1];
|
|
|
|
e[j - 1] = cs * e[j - 1];
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t = cs * V[i][j] + sn * V[i][p - 1];
|
|
|
|
V[i][p - 1] = -sn * V[i][j] + cs * V[i][p - 1];
|
2010-06-22 15:20:06 +00:00
|
|
|
V[i][j] = t;
|
|
|
|
}
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
break;
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Split at negligible s(k). */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
float f = e[k - 1];
|
|
|
|
e[k - 1] = 0.0f;
|
2010-06-22 15:20:06 +00:00
|
|
|
for (j = k; j < p; j++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
float t = hypotf(s[j], f);
|
|
|
|
float invt = 1.0f / t;
|
|
|
|
float cs = s[j] * invt;
|
|
|
|
float sn = f * invt;
|
2010-06-22 15:20:06 +00:00
|
|
|
s[j] = t;
|
2012-03-25 12:41:58 +00:00
|
|
|
f = -sn * e[j];
|
|
|
|
e[j] = cs * e[j];
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
for (i = 0; i < m; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t = cs * U[i][j] + sn * U[i][k - 1];
|
|
|
|
U[i][k - 1] = -sn * U[i][j] + cs * U[i][k - 1];
|
2010-06-22 15:20:06 +00:00
|
|
|
U[i][j] = t;
|
|
|
|
}
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
break;
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Perform one qr step. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
case 3:
|
|
|
|
{
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Calculate the shift. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-23 13:28:22 +00:00
|
|
|
float scale = max_ff(max_ff(max_ff(max_ff(
|
2012-04-29 15:47:02 +00:00
|
|
|
fabsf(s[p - 1]), fabsf(s[p - 2])), fabsf(e[p - 2])),
|
|
|
|
fabsf(s[k])), fabsf(e[k]));
|
2012-03-25 12:41:58 +00:00
|
|
|
float invscale = 1.0f / scale;
|
|
|
|
float sp = s[p - 1] * invscale;
|
|
|
|
float spm1 = s[p - 2] * invscale;
|
|
|
|
float epm1 = e[p - 2] * invscale;
|
|
|
|
float sk = s[k] * invscale;
|
|
|
|
float ek = e[k] * invscale;
|
|
|
|
float b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) * 0.5f;
|
|
|
|
float c = (sp * epm1) * (sp * epm1);
|
2010-06-22 15:20:06 +00:00
|
|
|
float shift = 0.0f;
|
|
|
|
float f, g;
|
|
|
|
if ((b != 0.0f) || (c != 0.0f)) {
|
2012-03-25 12:41:58 +00:00
|
|
|
shift = sqrtf(b * b + c);
|
2010-06-22 15:20:06 +00:00
|
|
|
if (b < 0.0f) {
|
|
|
|
shift = -shift;
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
shift = c / (b + shift);
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
f = (sk + sp) * (sk - sp) + shift;
|
|
|
|
g = sk * ek;
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Chase zeros. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
for (j = k; j < p - 1; j++) {
|
|
|
|
float t = hypotf(f, g);
|
2010-06-22 15:20:06 +00:00
|
|
|
/* division by zero checks added to avoid NaN (brecht) */
|
2012-03-25 12:41:58 +00:00
|
|
|
float cs = (t == 0.0f) ? 0.0f : f / t;
|
|
|
|
float sn = (t == 0.0f) ? 0.0f : g / t;
|
2010-06-22 15:20:06 +00:00
|
|
|
if (j != k) {
|
2012-03-25 12:41:58 +00:00
|
|
|
e[j - 1] = t;
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
f = cs * s[j] + sn * e[j];
|
|
|
|
e[j] = cs * e[j] - sn * s[j];
|
|
|
|
g = sn * s[j + 1];
|
|
|
|
s[j + 1] = cs * s[j + 1];
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t = cs * V[i][j] + sn * V[i][j + 1];
|
|
|
|
V[i][j + 1] = -sn * V[i][j] + cs * V[i][j + 1];
|
2010-06-22 15:20:06 +00:00
|
|
|
V[i][j] = t;
|
|
|
|
}
|
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
t = hypotf(f, g);
|
2010-06-22 15:20:06 +00:00
|
|
|
/* division by zero checks added to avoid NaN (brecht) */
|
2012-03-25 12:41:58 +00:00
|
|
|
cs = (t == 0.0f) ? 0.0f : f / t;
|
|
|
|
sn = (t == 0.0f) ? 0.0f : g / t;
|
2010-06-22 15:20:06 +00:00
|
|
|
s[j] = t;
|
2012-03-25 12:41:58 +00:00
|
|
|
f = cs * e[j] + sn * s[j + 1];
|
|
|
|
s[j + 1] = -sn * e[j] + cs * s[j + 1];
|
|
|
|
g = sn * e[j + 1];
|
|
|
|
e[j + 1] = cs * e[j + 1];
|
|
|
|
if (j < m - 1) {
|
2010-06-22 15:20:06 +00:00
|
|
|
for (i = 0; i < m; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t = cs * U[i][j] + sn * U[i][j + 1];
|
|
|
|
U[i][j + 1] = -sn * U[i][j] + cs * U[i][j + 1];
|
2010-06-22 15:20:06 +00:00
|
|
|
U[i][j] = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
e[p - 2] = f;
|
2010-06-22 15:20:06 +00:00
|
|
|
iter = iter + 1;
|
2012-03-25 12:41:58 +00:00
|
|
|
break;
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Convergence. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-03-25 12:41:58 +00:00
|
|
|
case 4:
|
|
|
|
{
|
2010-06-22 15:20:06 +00:00
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Make the singular values positive. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
if (s[k] <= 0.0f) {
|
|
|
|
s[k] = (s[k] < 0.0f ? -s[k] : 0.0f);
|
|
|
|
|
|
|
|
for (i = 0; i <= pp; i++)
|
|
|
|
V[i][k] = -V[i][k];
|
|
|
|
}
|
|
|
|
|
2012-10-20 20:20:02 +00:00
|
|
|
/* Order the singular values. */
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
while (k < pp) {
|
|
|
|
float t;
|
2012-03-25 12:41:58 +00:00
|
|
|
if (s[k] >= s[k + 1]) {
|
2010-06-22 15:20:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
t = s[k];
|
2012-03-25 12:41:58 +00:00
|
|
|
s[k] = s[k + 1];
|
|
|
|
s[k + 1] = t;
|
|
|
|
if (k < n - 1) {
|
2010-06-22 15:20:06 +00:00
|
|
|
for (i = 0; i < n; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t = V[i][k + 1];
|
|
|
|
V[i][k + 1] = V[i][k];
|
|
|
|
V[i][k] = t;
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
}
|
2012-03-25 12:41:58 +00:00
|
|
|
if (k < m - 1) {
|
2010-06-22 15:20:06 +00:00
|
|
|
for (i = 0; i < m; i++) {
|
2012-03-25 12:41:58 +00:00
|
|
|
t = U[i][k + 1];
|
|
|
|
U[i][k + 1] = U[i][k];
|
|
|
|
U[i][k] = t;
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
iter = 0;
|
|
|
|
p--;
|
2012-03-25 12:41:58 +00:00
|
|
|
break;
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void pseudoinverse_m4_m4(float Ainv[4][4], float A[4][4], float epsilon)
|
|
|
|
{
|
|
|
|
/* compute moon-penrose pseudo inverse of matrix, singular values
|
2012-03-03 20:19:11 +00:00
|
|
|
* below epsilon are ignored for stability (truncated SVD) */
|
2010-06-22 15:20:06 +00:00
|
|
|
float V[4][4], W[4], Wm[4][4], U[4][4];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
transpose_m4(A);
|
|
|
|
svd_m4(V, W, U, A);
|
|
|
|
transpose_m4(U);
|
|
|
|
transpose_m4(V);
|
|
|
|
|
|
|
|
zero_m4(Wm);
|
2012-03-25 12:41:58 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
Wm[i][i] = (W[i] < epsilon) ? 0.0f : 1.0f / W[i];
|
2010-06-22 15:20:06 +00:00
|
|
|
|
|
|
|
transpose_m4(V);
|
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
mul_serie_m4(Ainv, U, Wm, V, NULL, NULL, NULL, NULL, NULL);
|
2010-06-22 15:20:06 +00:00
|
|
|
}
|
2012-12-14 21:41:22 +00:00
|
|
|
|
|
|
|
void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon)
|
|
|
|
{
|
|
|
|
/* try regular inverse when possible, otherwise fall back to slow svd */
|
2012-12-15 02:48:25 +00:00
|
|
|
if (!invert_m3_m3(Ainv, A)) {
|
2012-12-14 21:41:22 +00:00
|
|
|
float tmp[4][4], tmpinv[4][4];
|
|
|
|
|
|
|
|
copy_m4_m3(tmp, A);
|
|
|
|
pseudoinverse_m4_m4(tmpinv, tmp, epsilon);
|
|
|
|
copy_m3_m4(Ainv, tmpinv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-18 23:38:51 +00:00
|
|
|
bool has_zero_axis_m4(float matrix[4][4])
|
|
|
|
{
|
|
|
|
return len_squared_v3(matrix[0]) < FLT_EPSILON ||
|
|
|
|
len_squared_v3(matrix[1]) < FLT_EPSILON ||
|
|
|
|
len_squared_v3(matrix[2]) < FLT_EPSILON;
|
|
|
|
}
|