
org.ode4j.ode.OdeMath Maven / Gradle / Ivy
/*************************************************************************
* *
* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
* All rights reserved. Email: [email protected] Web: www.q12.org *
* Open Dynamics Engine 4J, Copyright (C) 2009-2014 Tilmann Zaeschke *
* All rights reserved. Email: [email protected] Web: www.ode4j.org *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of EITHER: *
* (1) The GNU Lesser General Public License as published by the Free *
* Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. The text of the GNU Lesser *
* General Public License is included with this library in the *
* file LICENSE.TXT. *
* (2) The BSD-style license that is included with this library in *
* the file ODE-LICENSE-BSD.TXT and ODE4J-LICENSE-BSD.TXT. *
* *
* This library 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 files *
* LICENSE.TXT, ODE-LICENSE-BSD.TXT and ODE4J-LICENSE-BSD.TXT for more *
* details. *
* *
*************************************************************************/
package org.ode4j.ode;
import org.ode4j.math.*;
import org.ode4j.math.DMatrix3.DVector3RowTView;
import org.ode4j.ode.internal.Common;
import static org.ode4j.ode.internal.Common.*;
import static org.ode4j.ode.internal.CommonEnums.*;
/**
* ODE math functions.
*
* @author Tilmann Zaeschke
*/
public class OdeMath extends DRotation {
private OdeMath() {
//private
}
// /**
// * macro to access elements i,j in an NxM matrix A, independent of the
// * matrix storage convention.
// */
// //#define dACCESS33(A,i,j) ((A)[(i)*4+(j)])
// private double dACCESS33(double[] A, int i, int j) {
// return A[ i*4 + j ];
// }
//
//
// /**
// * Macro to test for valid floating point values
// */
// //#define dVALIDVEC3(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2])))
// //#define dVALIDVEC4(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2]) || dIsNan(v[3])))
// //#define dVALIDMAT3(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11])))
// //#define dVALIDMAT4(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11]) || dIsNan(m[12]) || dIsNan(m[13]) || dIsNan(m[14]) || dIsNan(m[15]) ))
// private boolean dVALIDVEC3(DVector3 v3) {
// double[] v = v3.v;
// return (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2])));
// }
// private boolean dVALIDVEC4(DVector4 v4) {
// double[] v = v4.v;
// return (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2]) || dIsNan(v[3])));
// }
// private boolean dVALIDMAT3(DMatrix3 m3) {
// double[] m = m3.v;
// return (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3])
// || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7])
// || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11])));
// }
// private boolean dVALIDMAT4(dMatrix4 m4) {
// double[] m = m4.v;
// return (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3])
// || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7])
// || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11])
// || dIsNan(m[12]) || dIsNan(m[13]) || dIsNan(m[14]) || dIsNan(m[15]) ));
// }
// Some vector math
public static void dAddVectors3(DVector3 res, DVector3C a, DVector3C b) {
res.eqSum(a, b);
}
// PURE_INLINE void dAddVectors3(dReal *res, const dReal *a, const dReal *b)
// {
// dReal res_0, res_1, res_2;
// res_0 = a[0] + b[0];
// res_1 = a[1] + b[1];
// res_2 = a[2] + b[2];
// // Only assign after all the calculations are over to avoid incurring memory aliasing
// res[0] = res_0; res[1] = res_1; res[2] = res_2;
// }
//
public static void dSubtractVectors3(DVector3 res, DVector3C a, DVector3C b) {
res.eqDiff(a, b);
}
// PURE_INLINE void dSubtractVectors3(dReal *res, const dReal *a, const dReal *b)
// {
// dReal res_0, res_1, res_2;
// res_0 = a[0] - b[0];
// res_1 = a[1] - b[1];
// res_2 = a[2] - b[2];
// // Only assign after all the calculations are over to avoid incurring memory aliasing
// res[0] = res_0; res[1] = res_1; res[2] = res_2;
// }
// ODE_PURE_INLINE void dAddVectorScaledVector3(dReal *res, const dReal *a, const dReal *b, dReal b_scale)
// {
// const dReal res_0 = a[0] + b_scale * b[0];
// const dReal res_1 = a[1] + b_scale * b[1];
// const dReal res_2 = a[2] + b_scale * b[2];
// /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
// res[0] = res_0; res[1] = res_1; res[2] = res_2;
// }
public static void dAddVectorScaledVector3(DVector3 res, DVector3C a, DVector3C b, double b_scale) {
res.set0(a.get0() + b_scale * b.get0());
res.set1(a.get1() + b_scale * b.get1());
res.set2(a.get2() + b_scale * b.get2());
}
public static void dAddScaledVectors3(DVector3 res, DVector3C a, DVector3C b,
double a_scale, double b_scale)
{
double res_0, res_1, res_2;
res_0 = a_scale * a.get0() + b_scale * b.get0();
res_1 = a_scale * a.get1() + b_scale * b.get1();
res_2 = a_scale * a.get2() + b_scale * b.get2();
// Only assign after all the calculations are over to avoid incurring memory aliasing
res.set( res_0, res_1, res_2 );
}
// ODE_PURE_INLINE void dAddThreeScaledVectors3(dReal *res, const dReal *a, const dReal *b, const dReal *c, dReal a_scale, dReal b_scale, dReal c_scale)
// {
// const dReal res_0 = a_scale * a[0] + b_scale * b[0] + c_scale * c[0];
// const dReal res_1 = a_scale * a[1] + b_scale * b[1] + c_scale * c[1];
// const dReal res_2 = a_scale * a[2] + b_scale * b[2] + c_scale * c[2];
// /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
// res[0] = res_0; res[1] = res_1; res[2] = res_2;
// }
public static void dAddThreeScaledVectors3(DVector3 res, DVector3C a, DVector3C b, DVector3C c, double a_scale,
double b_scale, double c_scale) {
double res_0 = a_scale * a.get0() + b_scale * b.get0() + c_scale * c.get0();
double res_1 = a_scale * a.get1() + b_scale * b.get1() + c_scale * c.get1();
double res_2 = a_scale * a.get2() + b_scale * b.get2() + c_scale * c.get2();
/* Only assign after all the calculations are over to avoid incurring memory aliasing*/
res.set(res_0, res_1, res_2);
}
// PURE_INLINE void dScaleVector3(dReal *res, dReal nScale)
// {
// res[0] *= nScale ;
// res[1] *= nScale ;
// res[2] *= nScale ;
// }
//
// PURE_INLINE void dNegateVector3(dReal *res)
// {
// res[0] = -res[0];
// res[1] = -res[1];
// res[2] = -res[2];
// }
public static void dNegateVector3(DVector3 res) {
res.set0(-res.get0());
res.set1(-res.get1());
res.set2(-res.get2());
}
public static void dCopyVector3(DVector3 a, final DVector3C b) {
a.set(b);
}
public static void dCopyVector3(float[] a, int ofs, final DVector3C b) {
a[0+ofs] = (float) b.get0();
a[1+ofs] = (float) b.get1();
a[2+ofs] = (float) b.get2();
}
public static void dCopyVector3(double[] resA, int resOfs, final DVector3C a) {
final double res_0 = a.get0();
final double res_1 = a.get1();
final double res_2 = a.get2();
/* Only assign after all the calculations are over to avoid incurring memory aliasing*/
resA[resOfs + 0] = res_0;
resA[resOfs + 1] = res_1;
resA[resOfs + 2] = res_2;
}
public static void dCopyVector3(double[] resA, int resOfs, final double[] aA, final int aOfs) {
resA[resOfs + 0] = aA[aOfs + 0];
resA[resOfs + 1] = aA[aOfs + 1];
resA[resOfs + 2] = aA[aOfs + 2];
}
public static void dCopyNegatedVector3(DVector3 res, final DVector3C a) {
res.set(-a.get0(), -a.get1(), -a.get2());
}
public static void dCopyNegatedVector3(double[] resA, int resOfs, final DVector3C a) {
final double res_0 = -a.get0();
final double res_1 = -a.get1();
final double res_2 = -a.get2();
/* Only assign after all the calculations are over to avoid incurring memory aliasing*/
resA[resOfs + 0] = res_0;
resA[resOfs + 1] = res_1;
resA[resOfs + 2] = res_2;
}
// PURE_INLINE void dCopyScaledVector3(dReal *res, const dReal *a, dReal nScale)
// {
// dReal res_0, res_1, res_2;
// res_0 = a[0] * nScale;
// res_1 = a[1] * nScale;
// res_2 = a[2] * nScale;
// // Only assign after all the calculations are over to avoid incurring memory aliasing
// res[0] = res_0; res[1] = res_1; res[2] = res_2;
// }
public static void dCopyScaledVector3(double[] resA, int resOfs, final DVector3C a, double nScale) {
resA[resOfs + 0] = a.get0() * nScale;
resA[resOfs + 1] = a.get1() * nScale;
resA[resOfs + 2] = a.get2() * nScale;
}
public static void dCopyScaledVector3(DVector3 res, final DVector3C a, double nScale) {
res.set0( a.get0() * nScale);
res.set1( a.get1() * nScale);
res.set2( a.get2() * nScale);
}
// PURE_INLINE void dCopyVector4(dReal *res, const dReal *a)
// {
// dReal res_0, res_1, res_2, res_3;
// res_0 = a[0];
// res_1 = a[1];
// res_2 = a[2];
// res_3 = a[3];
// // Only assign after all the calculations are over to avoid incurring memory aliasing
// res[0] = res_0; res[1] = res_1; res[2] = res_2; res[3] = res_3;
// }
//
// PURE_INLINE void dCopyMatrix4x4(dReal *res, const dReal *a)
// {
// dCopyVector4(res + 0, a + 0);
// dCopyVector4(res + 4, a + 4);
// dCopyVector4(res + 8, a + 8);
// }
//
// PURE_INLINE void dCopyMatrix4x3(dReal *res, const dReal *a)
// {
// dCopyVector3(res + 0, a + 0);
// dCopyVector3(res + 4, a + 4);
// dCopyVector3(res + 8, a + 8);
// }
//
// PURE_INLINE void dGetMatrixColumn3(dReal *res, const dReal *a, unsigned n)
// {
// dReal res_0, res_1, res_2;
// res_0 = a[n + 0];
// res_1 = a[n + 4];
// res_2 = a[n + 8];
// // Only assign after all the calculations are over to avoid incurring memory aliasing
// res[0] = res_0; res[1] = res_1; res[2] = res_2;
// }
@Deprecated
public enum OP { ADD, SUB, MUL, DIV, EQ, /** += */ ADD_EQ, /** =- */ EQ_SUB,
/** *= */ MUL_EQ, /** -= */ SUB_EQ; }
/*
* General purpose vector operations with other vectors or constants.
*/
//#define dOP(a,op,b,c) \
// (a)[0] = ((b)[0]) op ((c)[0]); \
// (a)[1] = ((b)[1]) op ((c)[1]); \
// (a)[2] = ((b)[2]) op ((c)[2]);
//#define dOPC(a,op,b,c) \
// (a)[0] = ((b)[0]) op (c); \
// (a)[1] = ((b)[1]) op (c); \
// (a)[2] = ((b)[2]) op (c);
//#define dOPE(a,op,b) \
// (a)[0] op ((b)[0]); \
// (a)[1] op ((b)[1]); \
// (a)[2] op ((b)[2]);
//#define dOPEC(a,op,c) \
// (a)[0] op (c); \
// (a)[1] op (c); \
// (a)[2] op (c);
// public static void dOP(double[] a, OP op, double[] b, double[] c) {
// switch (op) {
// case ADD: dOPadd(a, b, c); return;
// case SUB: dOPsub(a, b, c); return;
// case MUL: dOPmul(a, b, c); return;
// case DIV: dOPdiv(a, b, c); return;
// }
// throw new UnsupportedOperationException(op.name());
// }
//
// public static void dOPE(double[] a, int ofs, OP op, double[] b) {
// if (op == OP.EQ) {
// a[0+ofs] = b[0];
// a[1+ofs] = b[1];
// a[2+ofs] = b[2];
// } else if (op == OP.ADD_EQ) {
// a[0+ofs] += b[0];
// a[1+ofs] += b[1];
// a[2+ofs] += b[2];
// } else if (op == OP.EQ_SUB) {
// a[0+ofs] = -b[0];
// a[1+ofs] = -b[1];
// a[2+ofs] = -b[2];
// } else {
// throw new UnsupportedOperationException(op.name());
// }
// }
//
// public static void dOPE(double[] a, int ofs, OP op, DVector3C b) {
// if (op == OP.EQ) {
// a[0+ofs] = b.get0();
// a[1+ofs] = b.get1();
// a[2+ofs] = b.get2();
// } else if (op == OP.ADD_EQ) {
// a[0+ofs] += b.get0();
// a[1+ofs] += b.get1();
// a[2+ofs] += b.get2();
// } else if (op == OP.EQ_SUB) {
// a[0+ofs] = -b.get0();
// a[1+ofs] = -b.get1();
// a[2+ofs] = -b.get2();
// } else {
// throw new UnsupportedOperationException(op.name());
// }
// }
// private static void dOPadd(double[] a, double[] b, double[] c) {
// a[0] = ((b)[0]) + ((c)[0]);
// a[1] = ((b)[1]) + ((c)[1]);
// a[2] = ((b)[2]) + ((c)[2]);
// }
// private static void dOPsub(double[] a, double[] b, double[] c) {
// a[0] = ((b)[0]) - ((c)[0]);
// a[1] = ((b)[1]) - ((c)[1]);
// a[2] = ((b)[2]) - ((c)[2]);
// }
// private static void dOPmul(double[] a, double[] b, double[] c) {
// a[0] = ((b)[0]) * ((c)[0]);
// a[1] = ((b)[1]) * ((c)[1]);
// a[2] = ((b)[2]) * ((c)[2]);
// }
// private static void dOPdiv(double[] a, double[] b, double[] c) {
// a[0] = ((b)[0]) / ((c)[0]);
// a[1] = ((b)[1]) / ((c)[1]);
// a[2] = ((b)[2]) / ((c)[2]);
// }
//
// /** @deprecated Use dVector3.scale(c) instead (TZ). */
// public static void dOPEC(double[] a, OP op, double c) {
// switch (op) {
// case MUL_EQ: for (int i = 0; i < a.length; i++) a[i] *= c; return;
// }
// throw new UnsupportedOperationException(op.name());
// }
//#define dOPC(a,op,b,c) \
//(a)[0] = ((b)[0]) op (c); \
//(a)[1] = ((b)[1]) op (c); \
//(a)[2] = ((b)[2]) op (c);
//#define dOPE(a,op,b) \
//(a)[0] op ((b)[0]); \
//(a)[1] op ((b)[1]); \
//(a)[2] op ((b)[2]);
//#define dOPEC(a,op,c) \
//(a)[0] op (c); \
//(a)[1] op (c); \
//(a)[2] op (c);
/// Define an equation with operatos
/// For example this function can be used to replace
///
/// for (int i=0; i<3; ++i)
/// a[i] += b[i] + c[i];
///
//#define dOPE2(a,op1,b,op2,c) \
// (a)[0] op1 ((b)[0]) op2 ((c)[0]); \
// (a)[1] op1 ((b)[1]) op2 ((c)[1]); \
// (a)[2] op1 ((b)[2]) op2 ((c)[2]);
// public static void dOPE2(double[] a, OP op1, double[] b, OP op2, double[] c) {
// if (op1 == OP.SUB_EQ && op2 == OP.ADD) {
// a[0] -= b[0] + c[0];
// a[1] -= b[1] + c[1];
// a[2] -= b[2] + c[2];
// } else {
// throw new UnsupportedOperationException(op1 + " / " + op2);
// }
// }
/*
* Length, and squared length helpers. dLENGTH returns the length of a dVector3.
* dLENGTHSQUARED return the squared length of a dVector3.
*/
//#define dLENGTHSQUARED(a) (((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]))
//public
// private double dLENGTHSQUARED(DVector3 a) {
// return ((a.v[0])*(a.v[0]) + (a.v[1])*(a.v[1]) + (a.v[2])*(a.v[2]));
// }
//#ifdef __cplusplus
//PURE_INLINE dReal dLENGTH (const dReal *a) { return dSqrt(dLENGTHSQUARED(a)); }
//public double dReal dLENGTH (const dReal *a) { return dSqrt(dLENGTHSQUARED(a)); }
//#else
//#define dLENGTH(a) ( dSqrt( ((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]) ) )
// public static double dLENGTH(DVector3 a) {
// return dSqrt( (a.v[0])*(a.v[0]) + (a.v[1])*(a.v[1]) +
// (a.v[2])*(a.v[2]) ) ;
// }
//#endif /* __cplusplus */
/*
* 3-way dot product. dDOTpq means that elements of `a' and `b' are spaced
* p and q indexes apart respectively. dDOT() means dDOT11.
* in C++ we could use function templates to get all the versions of these
* functions - but on some compilers this will result in sub-optimal code.
*/
//#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
//by TZ: multiply matrices with offset
private static double dDOTpq(double[] a, double[] b, int p, int q) {
return a[0]*b[0] + a[p]*b[q] + a[2*p]*b[2*q];
}
private static double dDOTpq(double[] a, int o1, double[] b, int o2, int p, int q) {
return a[0+o1]*b[0+o2] + a[p+o1]*b[q+o2] + a[2*p+o1]*b[2*q+o2];
}
// private static double dDOTpq(double[] a, int o1, int p, DVector3C b) {
// return a[0+o1]*b.get0() + a[p+o1]*b.get1() + a[2*p+o1]*b.get2();
// }
private static double dDOTpq(double[] a, int o1, DVector3C b) {
return a[o1]*b.get0() + a[1+o1]*b.get1() + a[2+o1]*b.get2();
}
private static double dDOTpq(DVector3C a, double[] b, int o2, int q) {
return a.get0()*b[0+o2] + a.get1()*b[q+o2] + a.get2()*b[2*q+o2];
}
// private static double dDOTpq(double[] a, int o1, DVector3C b, int p, int q) {
// return a[0+o1]*b.get0() + a[p+o1]*b.get1() + a[2*p+o1]*b.get2();
// }
//#ifdef __cplusplus
//
//PURE_INLINE dReal dDOT (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,1); }
//PURE_INLINE dReal dDOT13 (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,3); }
//PURE_INLINE dReal dDOT31 (const dReal *a, const dReal *b) { return dDOTpq(a,b,3,1); }
//PURE_INLINE dReal dDOT33 (const dReal *a, const dReal *b) { return dDOTpq(a,b,3,3); }
//PURE_INLINE dReal dDOT14 (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,4); }
//PURE_INLINE dReal dDOT41 (const dReal *a, const dReal *b) { return dDOTpq(a,b,4,1); }
//PURE_INLINE dReal dDOT44 (const dReal *a, const dReal *b) { return dDOTpq(a,b,4,4); }
//
//#else
//#define dDOT(a,b) dDOTpq(a,b,1,1)
//#define dDOT13(a,b) dDOTpq(a,b,1,3)
//#define dDOT31(a,b) dDOTpq(a,b,3,1)
//#define dDOT33(a,b) dDOTpq(a,b,3,3)
//#define dDOT14(a,b) dDOTpq(a,b,1,4)
//#define dDOT41(a,b) dDOTpq(a,b,4,1)
//#define dDOT44(a,b) dDOTpq(a,b,4,4)
@Deprecated //Please use a.dot(b);
public static double dDOT(DVector3C a, DVector3C b) { return a.dot(b); }
/**
* Instead, please use a.dot(b).
* @param a a
* @param b b
* @return dot product
*/
public static double dCalcVectorDot3(DVector3C a, DVector3C b) {
return a.dot(b);
}
public static double dCalcVectorDot3(double[] a, int o1, DVector3C b) { return dDOTpq(a,o1,b); }
public static double dCalcVectorDot3(DVector3C a, double[] b, int o2) { return dDOTpq(a,b,o2,1); }
public static double dCalcVectorDot3(double[] a, double[] b) { return dDOTpq(a,b,1,1); }
public static double dCalcVectorDot3(double[] a, int o1, double[] b, int o2) { return dDOTpq(a,o1,b,o2,1,1); }
//public static double dDOT13(double[] a, int o1, double[] b, int o2) { return dDOTpq(a,o1,b,o2,1,3); }
//public static double dDOT13(DVector3C a, double[] b, int o2) { return dDOTpq(a,b,o2,3); }
//public static double dDOT13(DVector3C a, DVector3ColView b) { return a.dot(b); }
//Used? public double dDOT14(dVector3 a, dVector3 b) { return dDOTpq(a,b,1,4); }
//public static double dDOT14(DVector3 a, DMatrix3 b, int o2) { return dDOTpq(a,b.v,o2,4); }
public static double dCalcVectorDot3_14(DVector3C a, DMatrix3C b, int o2) { return a.dotCol(b, o2); }
//return dDOTpq(a,((DMatrix3)b).v,o2,4); }
//public static double dDOT41(DMatrix3 a, int o1, DVector3C b) { return dDOTpq(a.v,o1,b,4,1); }
public static double dCalcVectorDot3_41(DMatrix3C a, int o1, DVector3C b) { return a.dotCol(o1, b); }
// return dDOTpq(((DMatrix3)a).v,o1,b,4,1); }
//public static double dDOT44(DMatrix3 a, int o1, DMatrix3 b, int o2) { return dDOTpq(a.v,o1,b.v,o2,4,4); }
public static double dCalcVectorDot3_44(DMatrix3C a, int o1, DMatrix3C b, int o2) { return a.dotColCol(o1, b, o2); }
//return dDOTpq(((DMatrix3)a).v,o1,((DMatrix3)b).v,o2,4,4); }
//private double dDOT(dMatrix3 a, int o1, dVector3 b, int o2) { return dDOTpq(a.v, o1, b.v, o2, 1,1); }
public static double dCalcVectorDot3_14(double[] a, int o1, double[] b, int o2) { return dDOTpq(a,o1,b,o2,1,4); }
public static double dCalcVectorDot3_14(DVector3C a, double[] b, int o2) { return dDOTpq(a,b,o2,4); }
//private static double dDOT41(double[] a, int o1, double[] b, int o2) { return dDOTpq(a,o1,b,o2,4,1); }
// private static double dDOT41(double[] a, int o1, DVector3C b) { return dDOTpq(a,o1,4, b); }
// private static double dDOT44(double[] a, int o1, double[] b, int o2) { return dDOTpq(a,o1,b,o2,4,4); }
//#endif /* __cplusplus */
// public static double dCalcVectorLength3(final DVector3C a) {
// return dSqrt(a.get0() * a.get0() + a.get1() * a.get1() + a.get2() * a.get2());
// }
//
public static double dCalcVectorLengthSquare3(final DVector3C a) {
return (a.get0() * a.get0() + a.get1() * a.get1() + a.get2() * a.get2());
}
// public static double dCalcPointDepth3(const dReal *test_p, const dReal *plane_p, const dReal *plane_n)
// {
// return (plane_p[0] - test_p[0]) * plane_n[0] + (plane_p[1] - test_p[1]) * plane_n[1] + (plane_p[2] - test_p[2]) * plane_n[2];
// }
/*
* cross product, set a = b x c. dCROSSpqr means that elements of `a', `b'
* and `c' are spaced p, q and r indexes apart respectively.
* dCROSS() means dCROSS111. `op' is normally `=', but you can set it to
* +=, -= etc to get other effects.
*/
//#define dCROSS(a,op,b,c) \
//do { \
// (a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \
// (a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \
// (a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]); \
//} while(0)
//#define dCROSSpqr(a,op,b,c,p,q,r) \
//do { \
// (a)[ 0] op ((b)[ q]*(c)[2*r] - (b)[2*q]*(c)[ r]); \
// (a)[ p] op ((b)[2*q]*(c)[ 0] - (b)[ 0]*(c)[2*r]); \
// (a)[2*p] op ((b)[ 0]*(c)[ r] - (b)[ q]*(c)[ 0]); \
//} while(0)
/**
* @param a a
* @param op op
* @param b b
* @param c c
* @deprecated Use dCalcVetorCross3, dAddVectorCross3 or dSubtractVectorCross3.
*/
@Deprecated
public static void dCROSS(DVector3 a, OP op, DVector3C b, DVector3C c) {
if (op == OP.EQ) {
dCalcVectorCross3(a, b, c);
} else if (op == OP.ADD_EQ) {
dAddVectorCross3(a, b, c);
} else if (op == OP.SUB_EQ) {
dSubtractVectorCross3(a, b, c);
} else {
throw new UnsupportedOperationException(op.name());
}
}
/**
* Cross product, set a = b x c.
* @param a a
* @param b b
* @param c c
*/
public static void dCalcVectorCross3(DVector3 a, DVector3C b, DVector3C c) {
a.set0( b.get1()*c.get2() - b.get2()*c.get1() );
a.set1( b.get2()*c.get0() - b.get0()*c.get2() );
a.set2( b.get0()*c.get1() - b.get1()*c.get0() );
}
/*
* cross product, set res = a x b. _dCalcVectorCross3 means that elements of `res', `a'
* and `b' are spaced step_res, step_a and step_b indexes apart respectively.
* dCalcVectorCross3() means dCross3111.
*/
public static void dCalcVectorCross3(double[] resA, int resOfs, DVector3C a, DVector3C b) {
final double res_0 = a.get1() * b.get2() - a.get2() * b.get1();
final double res_1 = a.get2() * b.get0() - a.get0() * b.get2();
final double res_2 = a.get0() * b.get1() - a.get1() * b.get0();
/* Only assign after all the calculations are over to avoid incurring memory aliasing*/
resA[resOfs + 0] = res_0;
resA[resOfs + 1] = res_1;
resA[resOfs + 2] = res_2;
}
public static void dCalcVectorCross3(double[] resA, int resOfs, DVector3C a, double[] bA, int bOfs) {
double b0 = bA[bOfs + 0];
double b1 = bA[bOfs + 1];
double b2 = bA[bOfs + 2];
final double res_0 = a.get1() * b2 - a.get2() * b1;
final double res_1 = a.get2() * b0 - a.get0() * b2;
final double res_2 = a.get0() * b1 - a.get1() * b0;
/* Only assign after all the calculations are over to avoid incurring memory aliasing*/
resA[resOfs + 0] = res_0;
resA[resOfs + 1] = res_1;
resA[resOfs + 2] = res_2;
}
/**
* Cross product, set a += b x c.
* @param a a
* @param b b
* @param c c
*/
public static void dAddVectorCross3(DVector3 a, DVector3C b, DVector3C c) {
a.add0( b.get1()*c.get2() - b.get2()*c.get1() );
a.add1( b.get2()*c.get0() - b.get0()*c.get2() );
a.add2( b.get0()*c.get1() - b.get1()*c.get0() );
}
/**
* Cross product, set a -= b x c.
* @param a a
* @param b b
* @param c c
*/
public static void dSubtractVectorCross3(DVector3 a, DVector3C b, DVector3C c) {
a.add0( -b.get1()*c.get2() + b.get2()*c.get1() );
a.add1( -b.get2()*c.get0() + b.get0()*c.get2() );
a.add2( -b.get0()*c.get1() + b.get1()*c.get0() );
}
// public static void dCROSS(float[] a, OP op, float[] b, float[] c) {
// if (op == OP.EQ) {
// a[0] = ((b)[1]*(c)[2] - (b)[2]*(c)[1]);
// a[1] = ((b)[2]*(c)[0] - (b)[0]*(c)[2]);
// a[2] = ((b)[0]*(c)[1] - (b)[1]*(c)[0]);
// } else if (op == OP.ADD_EQ) {
// a[0] += ((b)[1]*(c)[2] - (b)[2]*(c)[1]);
// a[1] += ((b)[2]*(c)[0] - (b)[0]*(c)[2]);
// a[2] += ((b)[0]*(c)[1] - (b)[1]*(c)[0]);
// } else if (op == OP.SUB_EQ) {
// a[0] -= ((b)[1]*(c)[2] - (b)[2]*(c)[1]);
// a[1] -= ((b)[2]*(c)[0] - (b)[0]*(c)[2]);
// a[2] -= ((b)[0]*(c)[1] - (b)[1]*(c)[0]);
// } else {
// throw new UnsupportedOperationException(op.name());
// }
// }
// /**
// * Cross product, set a = b x c.
// */
// public static void dAddVectorCross3(float[] a, float[] b, float[] c) {
// a[0] += ((b)[1]*(c)[2] - (b)[2]*(c)[1]);
// a[1] += ((b)[2]*(c)[0] - (b)[0]*(c)[2]);
// a[2] += ((b)[0]*(c)[1] - (b)[1]*(c)[0]);
// }
// public static void dSubtractVectorCross3(float[] a, float[] b, float[] c) {
// a[0] -= ((b)[1]*(c)[2] - (b)[2]*(c)[1]);
// a[1] -= ((b)[2]*(c)[0] - (b)[0]*(c)[2]);
// a[2] -= ((b)[0]*(c)[1] - (b)[1]*(c)[0]);
// }
// public static void dCROSS(double[] a, int ofs, OP op, DVector3C b, DVector3C c) {
// if (op == OP.EQ) {
// a[0+ofs] = (b.get1()*c.get2() - b.get2()*c.get1());
// a[1+ofs] = (b.get2()*c.get0() - b.get0()*c.get2());
// a[2+ofs] = (b.get0()*c.get1() - b.get1()*c.get0());
// } else if (op == OP.EQ_SUB) {
// a[0+ofs] = -(b.get1()*c.get2() - b.get2()*c.get1());
// a[1+ofs] = -(b.get2()*c.get0() - b.get0()*c.get2());
// a[2+ofs] = -(b.get0()*c.get1() - b.get1()*c.get0());
// } else {
// throw new UnsupportedOperationException(op.name());
// }
// }
// public static void dSubtractVectorCross3(double[] a, int ofs, DVector3C b, DVector3C c) {
// a[0+ofs] = -(b.get1()*c.get2() - b.get2()*c.get1());
// a[1+ofs] = -(b.get2()*c.get0() - b.get0()*c.get2());
// a[2+ofs] = -(b.get0()*c.get1() - b.get1()*c.get0());
// }
/**
* Cross product, set a = b x c.
* @param a a
* @param b b
* @param c c
*/
public static void dCalcVectorCross3(DVector3View a, DVector3View b, DVector3View c) {
a.set0( b.get1()*c.get2() - b.get2()*c.get1() );
a.set1( b.get2()*c.get0() - b.get0()*c.get2() );
a.set2( b.get0()*c.get1() - b.get1()*c.get0() );
}
public static void dSubtractVectorCross3(DVector3 a, DVector3C b, DMatrix3C c) {
a.add0( - (b.get1()*c.get02() - b.get2()*c.get01()) );
a.add1( - (b.get2()*c.get00() - b.get0()*c.get02()) );
a.add2( - (b.get0()*c.get01() - b.get1()*c.get00()) );
}
// public static void dCROSS(DVector3 a, OP op, DVector3C b, DMatrix3C c) {
// if (op == OP.EQ) {
// a.set0( b.get1()*c.get02() - b.get2()*c.get01());
// a.set1( b.get2()*c.get00() - b.get0()*c.get02());
// a.set2( b.get0()*c.get01() - b.get1()*c.get00());
// } else if (op == OP.SUB_EQ) {
// a.add0( - (b.get1()*c.get02() - b.get2()*c.get01()) );
// a.add1( - (b.get2()*c.get00() - b.get0()*c.get02()) );
// a.add2( - (b.get0()*c.get01() - b.get1()*c.get00()) );
// } else {
// throw new UnsupportedOperationException(op.name());
// }
// }
// private void dCROSSpqr(DVector3 a, OP op, DVector3 b, DVector3 c,
// int p, int q, int r) {
// (a).v[ 0] = ((b).v[ q]*(c).v[2*r] - (b).v[2*q]*(c).v[ r]);
// (a).v[ p] = ((b).v[2*q]*(c).v[ 0] - (b).v[ 0]*(c).v[2*r]);
// (a).v[2*p] = ((b).v[ 0]*(c).v[ r] - (b).v[ q]*(c).v[ 0]);
// }
//
// public void dCROSS114(DVector3 a, OP op, DVector3 b, DVector3 c) {
// dCROSSpqr(a,op,b,c,1,1,4);
// }
// public void dCROSS141(DVector3 a, OP op, DVector3 b, DVector3 c) {
// dCROSSpqr(a,op,b,c,1,4,1);
// }
// public void dCROSS144(DVector3 a, OP op, DVector3 b, DVector3 c) {
// dCROSSpqr(a,op,b,c,1,4,4);
// }
// public void dCROSS411(DVector3 a, OP op, DVector3 b, DVector3 c) {
// dCROSSpqr(a,op,b,c,4,1,1);
// }
// public void dCROSS414(DVector3 a, OP op, DVector3 b, DVector3 c) {
// dCROSSpqr(a,op,b,c,4,1,4);
// }
// public void dCROSS441(DVector3 a, OP op, DVector3 b, DVector3 c) {
// dCROSSpqr(a,op,b,c,4,4,1);
// }
// public void dCROSS444(DVector3 a, OP op, DVector3 b, DVector3 c) {
// dCROSSpqr(a,op,b,c,4,4,4);
// }
/**
* Set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b.
* The matrix is assumed to be already zero, so this does not write zero elements!
* A positive version will be written.
* @param A A
* @param a a
*/
public static void dSetCrossMatrixPlus(DMatrix3 A, DVector3C a) {
A.set01( -a.get2() );
A.set02( +a.get1() );
A.set10( +a.get2() );
A.set12( -a.get0() );
A.set20( -a.get1() );
A.set21( +a.get0() );
}
/**
* Set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b.
* The matrix is assumed to be already zero, so this does not write zero elements!
* A negative version will be written.
* @param A A
* @param a a
*/
public static void dSetCrossMatrixMinus(DMatrix3 A, DVector3C a) {
A.set01( +a.get2() );
A.set02( -a.get1() );
A.set10( -a.get2() );
A.set12( +a.get0() );
A.set20( +a.get1() );
A.set21( -a.get0() );
}
public static void dSetCrossMatrixMinus(double[] resA, int resOfs, final DVector3C a, int skip) {
final double a_0 = a.get0(), a_1 = a.get1(), a_2 = a.get2();
resA[resOfs + 1] = +a_2;
resA[resOfs + 2] = -a_1;
resA[resOfs + skip + 0] = -a_2;
resA[resOfs + skip + 2] = +a_0;
resA[resOfs + 2 * skip + 0] = +a_1;
resA[resOfs + 2 * skip + 1] = -a_0;
}
/**
* set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b.
* A is stored by rows, and has `skip' elements per row. the matrix is
* assumed to be already zero, so this does not write zero elements!
* A positive version will be written.
* @param A A
* @param ofs ofs
* @param a a
* @param skip skip
*/
public static void dSetCrossMatrixPlus(double[] A, int ofs, DVector3C a, int skip) {
A[ofs+1] = -a.get2();
A[ofs+2] = +a.get1();
A[ofs+skip+0] = +a.get2();
A[ofs+skip+2] = -a.get0();
A[ofs+2*skip+0] = -a.get1();
A[ofs+2*skip+1] = +a.get0();
}
//#define dCROSSMAT(A,a,skip,plus,minus) \
//do { \
// (A)[1] = minus (a)[2]; \
// (A)[2] = plus (a)[1]; \
// (A)[(skip)+0] = plus (a)[2]; \
// (A)[(skip)+2] = minus (a)[0]; \
// (A)[2*(skip)+0] = minus (a)[1]; \
// (A)[2*(skip)+1] = plus (a)[0]; \
//} while(0)
/**
* For +1/-1 use dSetCrossMatrixPlus(), for -1/+1 use dSetCrossMatrixMinus().
* @param A A
* @param a a
* @param skip skip
* @param plus plus
* @param minus minus
* @deprecated
*/
@Deprecated
public static void dCROSSMAT(DMatrix3 A, DVector3C a, int skip, int plus, int minus) {
A.set01( minus * a.get2() );
A.set02( plus * a.get1() );
A.set10( plus * a.get2() );
A.set12( minus * a.get0() );
A.set20( minus * a.get1() );
A.set21( plus * a.get0() );
}
//#ifdef __cplusplus
//PURE_INLINE dReal dDISTANCE (const dVector3 a, const dVector3 b)
// { return dSqrt( (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]) ); }
// /**
// * Compute the distance between two 3D-vectors.
// * Please use a.distance(b) instead.
// * @param a
// * @param b
// * @return distance
// */
// public static double dCalcPointsDistance3 (final DVector3C a, final DVector3C b) {
// return a.distance(b);
// }
// /**
// * Compute the distance between two 3D-vectors.
// * @param a
// * @param b
// * @return distance
// */
// public static double dDISTANCE (final DVector3C a, final DVector3C b) {
// return a.distance(b);
// }
//#else
//#define dDISTANCE(a,b) \
// (dSqrt( ((a)[0]-(b)[0])*((a)[0]-(b)[0]) + ((a)[1]-(b)[1])*((a)[1]-(b)[1]) + ((a)[2]-(b)[2])*((a)[2]-(b)[2]) ))
//#endif
/*
* special case matrix multipication, with operator selection
*/
private static void dMultiplyHelper0_331(DVector3 res, DMatrix3C a, DVector3C b) {
double res_0 = a.dotRow(0, b);
double res_1 = a.dotRow(1, b);
double res_2 = a.dotRow(2, b);
/* Only assign after all the calculations are over to avoid incurring memory aliasing*/
res.set(res_0, res_1, res_2);
}
private static void dMultiplyHelper1_331(DVector3 res, DMatrix3C a, DVector3C b) {
double res_0 = a.dotCol(0, b);
double res_1 = a.dotCol(1, b);
double res_2 = a.dotCol(2, b);
/* Only assign after all the calculations are over to avoid incurring memory aliasing*/
res.set(res_0, res_1, res_2);
}
private static void dMultiplyHelper0_133(DVector3 res, DVector3C a, DMatrix3C b) {
double res_0 = a.dotCol(b, 0);
double res_1 = a.dotCol(b, 1);
double res_2 = a.dotCol(b, 2);
/* Only assign after all the calculations are over to avoid incurring memory aliasing*/
res.set(res_0, res_1, res_2);
}
private static void dMULTIPLYOP0_331(DMatrix3 A, DMatrix3C B, DVector3C C) {
//DMatrix3 B = (DMatrix3) B2;
A.set00( B.dotRow(0, C) );
A.set01( B.dotRow(1, C) );
A.set02( B.dotRow(2, C) );
}
//TZ
private static void dMULTIPLYOP0_331(DVector3 A, DMatrix3C B, double[] C, int c) {
A.set0( B.dotRow(0, C, c) );//dDOT(B.v, 0, C, c) );
A.set1( B.dotRow(1, C, c) );//dDOT(B.v, 4, C, c) );
A.set2( B.dotRow(2, C, c) );//dDOT(B.v, 8, C, c) );
}
//TZ
// private static void dMULTIPLYOP0_331(DVector3 A, DMatrix3 B, DVector4 C) {
// A.set0( dDOT(B.v, 0, C.v, 0) );
// A.set1( dDOT(B.v, 4, C.v, 0) );
// A.set2( dDOT(B.v, 8, C.v, 0) );
// }
//TZ
private static void dMULTIPLYOP0_331(double[] A, int a, double[] B, int b,
double[] C, int c) {
A[0+a] = dCalcVectorDot3(B, 0+b, C, c);
A[1+a] = dCalcVectorDot3(B, 4+b, C, c);
A[2+a] = dCalcVectorDot3(B, 8+b, C, c);
}
//TZ
private static void dMULTIPLYOP0_331(double[] A, int a, double[] B, int b,
DVector3C C) {
A[0+a] = dCalcVectorDot3(B, 0+b, C);
A[1+a] = dCalcVectorDot3(B, 4+b, C);
A[2+a] = dCalcVectorDot3(B, 8+b, C);
}
private static void dMULTIPLYOP0_333(double[] A, int a, DMatrix3C B, DMatrix3C C) {
A[0+a] = B.dotRowCol(0, C, 0);//dDOT14(B.v,0,C.v,0);
A[1+a] = B.dotRowCol(0, C, 1);//dDOT14(B.v,0,C.v,1);
A[2+a] = B.dotRowCol(0, C, 2);//dDOT14(B.v,0,C.v,2);
A[4+a] = B.dotRowCol(1, C, 0);//dDOT14(B.v,4,C.v,0);
A[5+a] = B.dotRowCol(1, C, 1);//dDOT14(B.v,4,C.v,1);
A[6+a] = B.dotRowCol(1, C, 2);//dDOT14(B.v,4,C.v,2);
A[8+a] = B.dotRowCol(2, C, 0);//dDOT14(B.v,8,C.v,0);
A[9+a] = B.dotRowCol(2, C, 1);//dDOT14(B.v,8,C.v,1);
A[10+a] = B.dotRowCol(2, C, 2);//dDOT14(B.v,8,C.v,2);
}
private static void dMULTIPLYOP0_333(DMatrix3 A, DMatrix3C B, DMatrix3C C) {
A.set00( B.dotRowCol(0, C, 0) );//(A).v[0] = dDOT14(B.v,0,C.v,0);
A.set01( B.dotRowCol(0, C, 1) );//(A).v[1] = dDOT14(B.v,0,C.v,1);
A.set02( B.dotRowCol(0, C, 2) );//(A).v[2] = dDOT14(B.v,0,C.v,2);
A.set10( B.dotRowCol(1, C, 0) );//(A).v[4] = dDOT14(B.v,4,C.v,0);
A.set11( B.dotRowCol(1, C, 1) );//(A).v[5] = dDOT14(B.v,4,C.v,1);
A.set12( B.dotRowCol(1, C, 2) );//(A).v[6] = dDOT14(B.v,4,C.v,2);
A.set20( B.dotRowCol(2, C, 0) );//(A).v[8] = dDOT14(B.v,8,C.v,0);
A.set21( B.dotRowCol(2, C, 1) );//(A).v[9] = dDOT14(B.v,8,C.v,1);
A.set22( B.dotRowCol(2, C, 2) );//(A).v[10] = dDOT14(B.v,8,C.v,2);
}
private static void dMULTIPLYOP1_333(DMatrix3 A, DMatrix3C B, DMatrix3C C) {
A.set00( dCalcVectorDot3_44(B,0,C,0) );
A.set01( dCalcVectorDot3_44(B,0,C,1) );
A.set02( dCalcVectorDot3_44(B,0,C,2) );
A.set10( dCalcVectorDot3_44(B,1,C,0) );
A.set11( dCalcVectorDot3_44(B,1,C,1) );
A.set12( dCalcVectorDot3_44(B,1,C,2) );
A.set20( dCalcVectorDot3_44(B,2,C,0) );
A.set21( dCalcVectorDot3_44(B,2,C,1) );
A.set22( dCalcVectorDot3_44(B,2,C,2) );
}
private static void dMULTIPLYOP2_333(DMatrix3 A, DMatrix3C B, DMatrix3C C) {
// A.v[0] = dDOT(B.v, 0, C.v, 0);
// A.v[1] = dDOT(B.v, 0, C.v, 4);
// A.v[2] = dDOT(B.v, 0, C.v, 8);
// A.v[4] = dDOT(B.v, 4, C.v, 0);
// A.v[5] = dDOT(B.v, 4, C.v, 4);
// A.v[6] = dDOT(B.v, 4, C.v, 8);
// A.v[8] = dDOT(B.v, 8, C.v, 0);
// A.v[9] = dDOT(B.v, 8, C.v, 4);
// A.v[10] = dDOT(B.v, 8, C.v, 8);
// A.v[0] = B.v[0]*C.v[0] + B.v[1]*C.v[1] + B.v[2]*C.v[2];
// A.v[1] = B.v[0]*C.v[4] + B.v[1]*C.v[5] + B.v[2]*C.v[6];
// A.v[2] = B.v[0]*C.v[8] + B.v[1]*C.v[9] + B.v[2]*C.v[10];
// A.v[4] = B.v[4]*C.v[0] + B.v[5]*C.v[1] + B.v[6]*C.v[2];
// A.v[5] = B.v[4]*C.v[4] + B.v[5]*C.v[5] + B.v[6]*C.v[6];
// A.v[6] = B.v[4]*C.v[8] + B.v[5]*C.v[9] + B.v[6]*C.v[10];
// A.v[8] = B.v[8]*C.v[0] + B.v[9]*C.v[1] + B.v[10]*C.v[2];
// A.v[9] = B.v[8]*C.v[4] + B.v[9]*C.v[5] + B.v[10]*C.v[6];
// A.v[10] = B.v[8]*C.v[8] + B.v[9]*C.v[9] + B.v[10]*C.v[10];
A.set00( B.dotRowRow( 0, C, 0) );
A.set01( B.dotRowRow( 0, C, 1) );
A.set02( B.dotRowRow( 0, C, 2) );
A.set10( B.dotRowRow( 1, C, 0) );
A.set11( B.dotRowRow( 1, C, 1) );
A.set12( B.dotRowRow( 1, C, 2) );
A.set20( B.dotRowRow( 2, C, 0) );
A.set21( B.dotRowRow( 2, C, 1) );
A.set22( B.dotRowRow( 2, C, 2) );
}
//#ifdef __cplusplus
//
//#define DECL template PURE_INLINE void
//
///*
//Note: NEVER call any of these functions/macros with the same variable for A and C,
//it is not equivalent to A*=B.
//*/
//
//DECL dMULTIPLY0_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_331(A,=,B,C); }
//DECL dMULTIPLY1_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_331(A,=,B,C); }
//DECL dMULTIPLY0_133(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_133(A,=,B,C); }
//DECL dMULTIPLY0_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_333(A,=,B,C); }
//DECL dMULTIPLY1_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_333(A,=,B,C); }
//DECL dMULTIPLY2_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP2_333(A,=,B,C); }
//
//DECL dMULTIPLYADD0_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_331(A,+=,B,C); }
//DECL dMULTIPLYADD1_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_331(A,+=,B,C); }
//DECL dMULTIPLYADD0_133(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_133(A,+=,B,C); }
//DECL dMULTIPLYADD0_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_333(A,+=,B,C); }
//DECL dMULTIPLYADD1_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_333(A,+=,B,C); }
//DECL dMULTIPLYADD2_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP2_333(A,+=,B,C); }
//
//#undef DECL
//
//#else
//#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
//#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
//#define dMULTIPLY0_133(A,B,C) dMULTIPLYOP0_133(A,=,B,C)
//#define dMULTIPLY0_333(A,B,C) dMULTIPLYOP0_333(A,=,B,C)
//#define dMULTIPLY1_333(A,B,C) dMULTIPLYOP1_333(A,=,B,C)
//#define dMULTIPLY2_333(A,B,C) dMULTIPLYOP2_333(A,=,B,C)
public static void dMultiply0_331(DVector3 res, DMatrix3C a, DVector3C b) {
dMultiplyHelper0_331(res, a, b); }
public static void dMultiply0_331(DMatrix3 A, DMatrix3C B, DVector3C C) {
dMULTIPLYOP0_331(A,B,C); }
// public static void dMULTIPLY0_331(DVector3 A, DMatrix3 B, DVector4 C) {
// dMULTIPLYOP0_331(A,B,C); } //TZ
public static void dMultiply0_331(DVector3 A, DMatrix3C B, double[] C, int c) {
dMULTIPLYOP0_331(A, B, C, c); //TZ
}
public static void dMultiply0_331(double[] A, int a, double[] B, int b,
DVector3C C) {
dMULTIPLYOP0_331(A, a, B, b, C); //TZ
}
public static void dMultiply0_331(double[] A, int a, double[] B, int b,
double[] C, int c) {
dMULTIPLYOP0_331(A, a, B, b, C, c); //TZ
}
@Deprecated
public static void dMULTIPLY0_331(DVector3 A, DMatrix3C B, DVector3C C) {
dMultiply0_331(A, B, C);
}
@Deprecated
public static void dMULTIPLY0_331(DMatrix3 A, DMatrix3C B, DVector3C C) {
dMultiply0_331(A, B, C);
}
@Deprecated
public static void dMULTIPLY0_331(DVector3 A, DMatrix3C B, double[] C, int c) {
dMultiply0_331(A, B, C, c);
}
public static void dMultiply1_331(DVector3 res, DMatrix3C a, DVector3C b) {
dMultiplyHelper1_331(res, a, b); }
public static void dMultiply1_331(double[] resA, int resOfs, DMatrix3C a, DVector3C b) {
double res_0 = a.dotCol(0, b);
double res_1 = a.dotCol(1, b);
double res_2 = a.dotCol(2, b);
/* Only assign after all the calculations are over to avoid incurring memory aliasing*/
resA[resOfs + 0] = res_0;
resA[resOfs + 1] = res_1;
resA[resOfs + 2] = res_2;
}
public static void dMultiply0_133(DVector3 res, DVector3C a, DMatrix3C b) {
dMultiplyHelper0_133(res, a, b); }
public static void dMultiply0_133(double[] A, int a, double[] B, int b,
double[] C, int c) {
A[0+a] = dCalcVectorDot3_14(B, b, C, 0 + c);
A[1+a] = dCalcVectorDot3_14(B, b, C, 1 + c);
A[2+a] = dCalcVectorDot3_14(B, b, C, 2 + c);
}
public static void dMultiply0_333(DMatrix3 A, DMatrix3C B, DMatrix3C C) {
dMULTIPLYOP0_333(A,B,C); }
public static void dMultiply0_333(double[] A, int a, DMatrix3C B, DMatrix3C C) {
dMULTIPLYOP0_333(A,a,B,C); }
@Deprecated
public static void dMULTIPLY1_331(DVector3 A, DMatrix3C B, DVector3C C) {
dMultiply1_331(A, B, C);
}
@Deprecated
public static void dMULTIPLY0_133(DVector3 A, DVector3C B, DMatrix3C C) {
dMultiply0_133(A, B, C);
}
@Deprecated
public static void dMULTIPLY0_333(DMatrix3 A, DMatrix3C B, DMatrix3C C) {
dMultiply0_333(A, B, C);
}
// public static void dMULTIPLY0_333(double[] A, int a, double[] B, int b,
// double[] C, int c) {
// A[0+a] = dDOT14(B,0+b,C,0+c);
// A[1+a] = dDOT14(B,0+b,C,1+c);
// A[2+a] = dDOT14(B,0+b,C,2+c);
// A[4+a] = dDOT14(B,4+b,C,0+c);
// A[5+a] = dDOT14(B,4+b,C,1+c);
// A[6+a] = dDOT14(B,4+b,C,2+c);
// A[8+a] = dDOT14(B,8+b,C,0+c);
// A[9+a] = dDOT14(B,8+b,C,1+c);
// A[10+a] = dDOT14(B,8+b,C,2+c);
// }
public static void dMultiply1_333(DMatrix3 A, DMatrix3C B, DMatrix3C C) {
dMULTIPLYOP1_333(A,B,C); }
public static void dMultiply2_333(DMatrix3 A, DMatrix3C B, DMatrix3C C) {
dMULTIPLYOP2_333(A,B,C); }
@Deprecated
public static void dMULTIPLY1_333(DMatrix3 A, DMatrix3C B, DMatrix3C C) {
dMultiply1_333(A, B, C);
}
@Deprecated
public static void dMULTIPLY2_333(DMatrix3 A, DMatrix3C B, DMatrix3C C) {
dMultiply2_333(A, B, C);
}
//
//#define dMULTIPLYADD0_331(A,B,C) dMULTIPLYOP0_331(A,+=,B,C)
// public static void dMULTIPLYADD0_331(double[] A, int a, double[] B, int b, double[] C, int c) {
// A[0+a] += dDOT(B, b+0, C, c);
// A[1+a] += dDOT(B, b+4, C, c);
// A[2+a] += dDOT(B, b+8, C, c);
// }
public static void dMultiplyAdd0_331(DVector3 A, double[] B, int b, DVector3C C) {
A.add0( dCalcVectorDot3(B, b+0, C) );
A.add1( dCalcVectorDot3(B, b+4, C) );
A.add2( dCalcVectorDot3(B, b+8, C) );
}
public static void dMultiplyAdd0_331(DVector3 A, double[] B, int b, double[] C, int c) {
A.add0( dCalcVectorDot3(B, b+0, C, c) );
A.add1( dCalcVectorDot3(B, b+4, C, c) );
A.add2( dCalcVectorDot3(B, b+8, C, c) );
}
@Deprecated
public static void dMULTIPLYADD0_331(DVector3 A, double[] B, int b, DVector3C C) {
dMultiplyAdd0_331(A, B, b, C);
}
@Deprecated
public static void dMULTIPLYADD0_331(DVector3 A, double[] B, int b, double[] C, int c) {
dMultiplyAdd0_331(A, B, b, C, c);
}
//#define dMULTIPLYADD1_331(A,B,C) dMULTIPLYOP1_331(A,+=,B,C)
//#define dMULTIPLYADD0_133(A,B,C) dMULTIPLYOP0_133(A,+=,B,C)
//#define dMULTIPLYADD0_333(A,B,C) dMULTIPLYOP0_333(A,+=,B,C)
//#define dMULTIPLYADD1_333(A,B,C) dMULTIPLYOP1_333(A,+=,B,C)
//#define dMULTIPLYADD2_333(A,B,C) dMULTIPLYOP2_333(A,+=,B,C)
public static double dCalcMatrix3Det( final DMatrix3C mat ) {
double det;
// det = mat[0] * ( mat[5]*mat[10] - mat[9]*mat[6] )
// - mat[1] * ( mat[4]*mat[10] - mat[8]*mat[6] )
// + mat[2] * ( mat[4]*mat[9] - mat[8]*mat[5] );
det = mat.get00() * ( mat.get11()*mat.get22() - mat.get21()*mat.get12() )
- mat.get01() * ( mat.get10()*mat.get22() - mat.get20()*mat.get12() )
+ mat.get02() * ( mat.get10()*mat.get21() - mat.get20()*mat.get11() );
return( det );
}
/**
* Closed form matrix inversion, copied from
* collision_util.h for use in the stepper.
*
* Returns the determinant.
* returns 0 and does nothing if the matrix is singular.
* @param dst dst
* @param ma ma
* @return determinant
*/
public static double dInvertMatrix3( DMatrix3 dst, final DMatrix3C ma) {
double det;
double detRecip;
det = dCalcMatrix3Det( ma );
/* Setting an arbitrary non-zero threshold
for the determinant doesn't do anyone
any favors. The condition number is the
important thing. If all the eigen-values
of the matrix are small, so is the
determinant, but it can still be well
conditioned.
A single extremely large eigen-value could
push the determinant over threshold, but
produce a very unstable result if the other
eigen-values are small. So we just say that
the determinant must be non-zero and trust the
caller to provide well-conditioned matrices.
*/
if ( det == 0 )
{
return 0;
}
detRecip = dRecip(det);
dst.set00( ( ma.get11()*ma.get22() - ma.get12()*ma.get21() ) * detRecip );
dst.set01( ( ma.get21()*ma.get02() - ma.get01()*ma.get22() ) * detRecip );
dst.set02( ( ma.get01()*ma.get12() - ma.get11()*ma.get02() ) * detRecip );
dst.set10( ( ma.get12()*ma.get20() - ma.get10()*ma.get22() ) * detRecip );
dst.set11( ( ma.get00()*ma.get22() - ma.get20()*ma.get02() ) * detRecip );
dst.set12( ( ma.get10()*ma.get02() - ma.get00()*ma.get12() ) * detRecip );
dst.set20( ( ma.get10()*ma.get21() - ma.get20()*ma.get11() ) * detRecip );
dst.set21( ( ma.get20()*ma.get01() - ma.get00()*ma.get21() ) * detRecip );
dst.set22( ( ma.get00()*ma.get11() - ma.get01()*ma.get10() ) * detRecip );
return det;
}
/*
* normalize 3x1 and 4x1 vectors (i.e. scale them to unit length)
*/
//#if defined(__ODE__)
//
//int _dSafeNormalize3 (dVector3 a);
//int _dSafeNormalize4 (dVector4 a);
//static __inline void _dNormalize3(dVector3 a)
private static void dxNormalize3(DVector3 a) {
boolean bSafeNormalize3Fault;
if ((bSafeNormalize3Fault = !dxSafeNormalize3(a))) {
dIVERIFY(!bSafeNormalize3Fault);
a.set(1.0, 0.0, 0.0);
}
}
//static __inline void _dNormalize4(dVector4 a)
// private static void _dNormalize4(double[] a)
// {
// int bNormalizationResult = _dSafeNormalize4(a);
// dIVERIFY(bNormalizationResult);
// }
//#endif // defined(__ODE__)
// For DLL export
//ODE_API int dSafeNormalize3 (dVector3 a);
//ODE_API int dSafeNormalize4 (dVector4 a);
//ODE_API void dNormalize3 (dVector3 a); // Potentially asserts on zero vec
//ODE_API void dNormalize4 (dVector4 a); // Potentially asserts on zero vec
//#if defined(__ODE__)
//
//// For internal use
//#define dSafeNormalize3(a) _dSafeNormalize3(a)
//#define dSafeNormalize4(a) _dSafeNormalize4(a)
//#define dNormalize3(a) _dNormalize3(a)
//#define dNormalize4(a) _dNormalize4(a)
//
//#endif // defined(__ODE__)
//#ifdef __cplusplus
//}
//#endif
//
//#endif
/// FROM odemath.cpp
// Please us DVector.safeNormalize instead
// int dSafeNormalize3 (dVector3 a)
// {
// return dxSafeNormalize3(a);
// }
//
// int dSafeNormalize4 (dVector4 a)
// {
// return dxSafeNormalize4(a);
// }
//
// void dNormalize3(dVector3 a)
// {
// dxNormalize3(a);
// }
//
// void dNormalize4(dVector4 a)
// {
// dxNormalize4(a);
// }
public static void dPlaneSpace(DVector3C n, DVector3 p, DVector3 q)
{
dxPlaneSpace(n, p, q);
}
public static boolean dOrthogonalizeR(DMatrix3 m)
{
return dxOrthogonalizeR(m);
}
/*extern */
boolean dxCouldBeNormalized3(DVector3C a)
{
dAASSERT (a);
boolean ret = false;
for (int axis = dV3E__AXES_MIN; axis != dV3E__AXES_MAX; ++axis) {
if (a.get(axis) != 0.0) {
ret = true;
break;
}
}
return ret;
}
/**
* this may be called for vectors `a' with extremely small magnitude, for
* example the result of a cross product on two nearly perpendicular vectors.
* we must be robust to these small vectors. to prevent numerical error,
* first find the component a[i] with the largest magnitude and then scale
* all the components by 1/a[i]. then we can compute the length of `a' and
* scale the components by 1/l. this has been verified to work with vectors
* containing the smallest representable numbers.
*
* TZ: Plain lengthSquared() == 0 checking with scale(1/lengthSquared() is about 4x faster. But we leave the
* safe version here.
* @param a the vector to normalize
* @return "true" if normalization succeeded
*/
public static boolean dxSafeNormalize3(DVector3 a) {
dAASSERT(a);
boolean ret = false;
do {
double abs_a0 = dFabs(a.get(dV3E_X));
double abs_a1 = dFabs(a.get(dV3E_Y));
double abs_a2 = dFabs(a.get(dV3E_Z));
//dVec3Element idx;
int idx = 0;
if (abs_a1 > abs_a0) {
if (abs_a2 > abs_a1) { // abs_a2 is the largest
idx = dV3E_Z;
} else { // abs_a1 is the largest
idx = dV3E_Y;
}
} else if (abs_a2 > abs_a0) {// abs_a2 is the largest
idx = dV3E_Z;
} else { // aa[0] might be the largest
if (!(abs_a0 > (0.0))) {
// if all a's are zero, this is where we'll end up.
// return the vector unchanged.
break;
}
// abs_a0 is the largest
idx = dV3E_X;
}
if (idx == dV3E_X) {
double aa0_recip = dRecip(abs_a0);
double a1 = a.get(dV3E_Y) * aa0_recip;
double a2 = a.get(dV3E_Z) * aa0_recip;
double l = dRecipSqrt((1.0) + a1 * a1 + a2 * a2);
a.set(dV3E_Y, a1 * l);
a.set(dV3E_Z, a2 * l);
a.set(dV3E_X, dCopySign(l, a.get(dV3E_X)));
} else if (idx == dV3E_Y) {
double aa1_recip = dRecip(abs_a1);
double a0 = a.get(dV3E_X) * aa1_recip;
double a2 = a.get(dV3E_Z) * aa1_recip;
double l = dRecipSqrt((1.0) + a0 * a0 + a2 * a2);
a.set(dV3E_X, a0 * l);
a.set(dV3E_Z, a2 * l);
a.set(dV3E_Y, dCopySign(l, a.get(dV3E_Y)));
} else {
double aa2_recip = dRecip(abs_a2);
double a0 = a.get(dV3E_X) * aa2_recip;
double a1 = a.get(dV3E_Y) * aa2_recip;
double l = dRecipSqrt((1.0) + a0 * a0 + a1 * a1);
a.set(dV3E_X, a0 * l);
a.set(dV3E_Y, a1 * l);
a.set(dV3E_Z, dCopySign(l, a.get(dV3E_Z)));
}
ret = true;
}
while (false);
return ret;
}
static boolean dxSafeNormalize3(DVector3View a) {
dAASSERT(a);
boolean ret = false;
do {
double abs_a0 = dFabs(a.get(dV3E_X));
double abs_a1 = dFabs(a.get(dV3E_Y));
double abs_a2 = dFabs(a.get(dV3E_Z));
//dVec3Element idx;
int idx = 0;
if (abs_a1 > abs_a0) {
if (abs_a2 > abs_a1) { // abs_a2 is the largest
idx = dV3E_Z;
} else { // abs_a1 is the largest
idx = dV3E_Y;
}
} else if (abs_a2 > abs_a0) {// abs_a2 is the largest
idx = dV3E_Z;
} else { // aa[0] might be the largest
if (!(abs_a0 > (0.0))) {
// if all a's are zero, this is where we'll end up.
// return the vector unchanged.
break;
}
// abs_a0 is the largest
idx = dV3E_X;
}
if (idx == dV3E_X) {
double aa0_recip = dRecip(abs_a0);
double a1 = a.get(dV3E_Y) * aa0_recip;
double a2 = a.get(dV3E_Z) * aa0_recip;
double l = dRecipSqrt((1.0) + a1 * a1 + a2 * a2);
a.set(dV3E_Y, a1 * l);
a.set(dV3E_Z, a2 * l);
a.set(dV3E_X, dCopySign(l, a.get(dV3E_X)));
} else if (idx == dV3E_Y) {
double aa1_recip = dRecip(abs_a1);
double a0 = a.get(dV3E_X) * aa1_recip;
double a2 = a.get(dV3E_Z) * aa1_recip;
double l = dRecipSqrt((1.0) + a0 * a0 + a2 * a2);
a.set(dV3E_X, a0 * l);
a.set(dV3E_Z, a2 * l);
a.set(dV3E_Y, dCopySign(l, a.get(dV3E_Y)));
} else {
double aa2_recip = dRecip(abs_a2);
double a0 = a.get(dV3E_X) * aa2_recip;
double a1 = a.get(dV3E_Y) * aa2_recip;
double l = dRecipSqrt((1.0) + a0 * a0 + a1 * a1);
a.set(dV3E_X, a0 * l);
a.set(dV3E_Y, a1 * l);
a.set(dV3E_Z, dCopySign(l, a.get(dV3E_Z)));
}
ret = true;
}
while (false);
return ret;
}
// static boolean dxSafeNormalize3 (DVector3 a)
// {
// double s;
// double aa0 = Math.abs(a.get0());
// double aa1 = Math.abs(a.get1());
// double aa2 = Math.abs(a.get2());
// if (aa1 > aa0) {
// if (aa2 > aa1) { // aa[2] is largest
// s = aa2;
// }
// else { // aa[1] is largest
// s = aa1;
// }
// }
// else {
// if (aa2 > aa0) {// aa[2] is largest
// s = aa2;
// }
// else { // aa[0] might be the largest
// if (aa0 <= 0) { // aa[0] might is largest
//// a.v[0] = 1; // if all a's are zero, this is where we'll end up.
//// a.v[1] = 0; // return a default unit length vector.
//// a.v[2] = 0;
// a.set(1, 0, 0);
// return false;
// }
// else {
// s = aa0;
// }
// }
// }
//
//// a.v[0] /= aa[idx];
//// a.v[1] /= aa[idx];
//// a.v[2] /= aa[idx];
// a.scale(1./s);
// //l = dRecipSqrt (a.v[0]*a.v[0] + a.v[1]*a.v[1] + a.v[2]*a.v[2]);
//// a.v[0] *= l;
//// a.v[1] *= l;
//// a.v[2] *= l;
// a.scale(1./a.length());
// return true;
// }
// static boolean _dSafeNormalize3 (DVector3View a)
// {
// double s;
// double aa0 = Math.abs(a.get0());
// double aa1 = Math.abs(a.get1());
// double aa2 = Math.abs(a.get2());
// if (aa1 > aa0) {
// if (aa2 > aa1) { // aa[2] is largest
// s = aa2;
// }
// else { // aa[1] is largest
// s = aa1;
// }
// }
// else {
// if (aa2 > aa0) {// aa[2] is largest
// s = aa2;
// }
// else { // aa[0] might be the largest
// if (aa0 <= 0) { // aa[0] might is largest
// // if all a's are zero, this is where we'll end up.
// // return a default unit length vector.
// a.set(1, 0, 0);
// return false;
// }
// else {
// s = aa0;
// }
// }
// }
//
// a.scale(1./s);
// a.scale(1./a.length());
// return true;
// }
/* OLD VERSION */
/*
void dNormalize3 (dVector3 a)
{
dIASSERT (a);
dReal l = dDOT(a,a);
if (l > 0) {
l = dRecipSqrt(l);
a[0] *= l;
a[1] *= l;
a[2] *= l;
}
else {
a[0] = 1;
a[1] = 0;
a[2] = 0;
}
}
*/
/**
* Normalize 3x1 vectors (i.e. scale them to unit length).
* @param a a
* @return 'false' if normalization failed
*/
public static boolean dSafeNormalize3 (DVector3 a)
{
return dxSafeNormalize3(a);
}
/**
* Normalize 3x1 vectors (i.e. scale them to unit length).
* @param a a
* @return 'false' if normalization failed
*/
public static boolean dSafeNormalize3 (DVector3View a)
{
return dxSafeNormalize3(a);
}
/**
* normalize 3x1 vectors (i.e. scale them to unit length).
* Potentially asserts on zero vec.
* @param a a
*/
public static void dNormalize3(DVector3 a)
{
dxNormalize3(a);
}
/*extern */
boolean dxCouldBeNormalized4(DVector4C a) {
dAASSERT(a);
boolean ret = false;
for (int axis = dV4E__MIN; axis != dV4E__MAX; ++axis) {
if (a.get(axis) != (0.0)) {
ret = true;
break;
}
}
return ret;
}
/*extern */
@Deprecated // use a.safeNormalize() instead
public static boolean dxSafeNormalize4(DVector4 a) {
dAASSERT(a);
boolean ret = false;
double l = a.get(dV4E_X) * a.get(dV4E_X)
+ a.get(dV4E_Y) * a.get(dV4E_Y)
+ a.get(dV4E_Z) * a.get(dV4E_Z)
+ a.get(dV4E_O) * a.get(dV4E_O);
if (l > 0) {
l = dRecipSqrt(l);
a.scale(l);
dAssertVec3Element();
// a[dV4E_X] *= l;
// a[dV4E_Y] *= l;
// a[dV4E_Z] *= l;
// a[dV4E_O] *= l;
ret = true;
}
return ret;
}
public static boolean dSafeNormalize4 (DVector4 a)
{
//return _dSafeNormalize4(a);
return a.safeNormalize4();
}
/**
* Potentially asserts on zero vec.
* @param a a
*/
public static void dNormalize4(DVector4 a) {
a.normalize();
}
/**
* Potentially asserts on zero vec.
* @param a a
*/
public static void dNormalize4(DQuaternion a)
{
//_dNormalize4(a.v);
// if (!_dSafeNormalize4(a)) throw new IllegalStateException(
// "Normalization failed: " + a);
a.normalize();
}
/**
* Given a unit length "normal" vector n, generate vectors p and q vectors
* that are an orthonormal basis for the plane space perpendicular to n.
* i.e. this makes p,q such that n,p,q are all perpendicular to each other.
* q will equal n x p. if n is not unit length then p will be unit length but
* q wont be.
* @param n n
* @param p p
* @param q q
*/
//ODE_API void dPlaneSpace (const dVector3 n, dVector3 p, dVector3 q);
public static void dxPlaneSpace (DVector3C n, DVector3 p, DVector3 q)
{
//Common.dAASSERT (n, p, q);
if (Math.abs(n.get2()) > Common.M_SQRT1_2) {
// choose p in y-z plane
double a = n.get1()*n.get1() + n.get2()*n.get2();
double k = Common.dRecipSqrt (a);
// p.v[0] = 0;
// p.v[1] = -n.v[2]*k;
// p.v[2] = n.v[1]*k;
p.set( 0, -n.get2()*k, n.get1()*k );
// set q = n x p
q.set0( a*k );
q.set1( -n.get0()*p.get2() );
q.set2( n.get0()*p.get1() );
}
else {
// choose p in x-y plane
double a = n.get0()*n.get0() + n.get1()*n.get1();
double k = Common.dRecipSqrt (a);
p.set0( -n.get1()*k );
p.set1( n.get0()*k );
p.set2( 0 );
// set q = n x p
q.set0( -n.get2()*p.get1() );
q.set1( n.get2()*p.get0() );
q.set2( a*k );
}
}
/**
* This takes what is supposed to be a rotation matrix,
* and make sure it is correct.
* Note: this operates on rows, not columns, because for rotations
* both ways give equivalent results.
* @param m m
* @return "true" unconditionally
*/
public static boolean dxOrthogonalizeR(DMatrix3 m) {
boolean ret = false;
dAssertVec3Element(); // because this is the old version, the new Version with dM3E__X_MIN is below
do {
//double n0 = dLENGTHSQUARED(m);
DVector3RowTView row0 = m.viewRowT(0);
double n0 = row0.length();
if (n0 != 1)
//dSafeNormalize3(m);
dSafeNormalize3(row0);
// project row[0] on row[1], should be zero
//double proj = dDOT(m, m+4);
DVector3View row1 = m.viewRowT(1);
double proj = row0.dot(row1);
if (proj != 0) {
// Gram-Schmidt step on row[1]
// m[4] -= proj * m[0];
// m[5] -= proj * m[1];
// m[6] -= proj * m[2];
m.set10(m.get10() - proj * m.get00());
m.set11(m.get11() - proj * m.get01());
m.set12(m.get12() - proj * m.get02());
}
double n1 = row1.dot(row1);//dLENGTHSQUARED(m+4);
if (n1 != 1)
//dSafeNormalize3(m+4);
dSafeNormalize3(row1);
/* just overwrite row[2], this makes sure the matrix is not
a reflection */
//dCROSS(m+8, =, m, m+4);
//dCROSS(m, 8, OP.EQ, m, 0, m, 4);
DVector3View row2 = m.viewRowT(2);
dCalcVectorCross3(row2, row0, row1);
//TZ m[3] = m[4+3] = m[8+3] = 0;
ret = true;
}
while (false);
return ret;
}
// TZ: This is the new version, but it is hard to translate to Java...
// boolean dxOrthogonalizeR(DMatrix3 m)
// {
// boolean ret = false;
//
// do {
// if (!dxCouldBeNormalized3(m + dM3E__X_MIN)) {
// break;
// }
//
// double n0 = dCalcVectorLengthSquare3(m + dM3E__X_MIN);
//
// DVector3 row2_store;
// dReal *row2 = m + dM3E__Y_MIN;
// // project row[0] on row[1], should be zero
// double proj = dCalcVectorDot3(m + dM3E__X_MIN, m + dM3E__Y_MIN);
// if (proj != 0) {
// // Gram-Schmidt step on row[1]
// double proj_div_n0 = proj / n0;
// row2_store[dV3E_X] = m[dM3E__Y_MIN + dV3E_X] - proj_div_n0 * m[dM3E__X_MIN + dV3E_X] ;
// row2_store[dV3E_Y] = m[dM3E__Y_MIN + dV3E_Y] - proj_div_n0 * m[dM3E__X_MIN + dV3E_Y];
// row2_store[dV3E_Z] = m[dM3E__Y_MIN + dV3E_Z] - proj_div_n0 * m[dM3E__X_MIN + dV3E_Z];
// row2 = row2_store;
// }
//
// if (!dxCouldBeNormalized3(row2)) {
// break;
// }
//
// if (n0 != (1.0)) {
// boolean row0_norm_fault = !dxSafeNormalize3(m + dM3E__X_MIN);
// dIVERIFY(!row0_norm_fault);
// }
//
// double n1 = dCalcVectorLengthSquare3(row2);
// if (n1 != (1.0)) {
// boolean row1_norm_fault = !dxSafeNormalize3(row2);
// dICHECK(!row1_norm_fault);
// }
//
// dIASSERT(dFabs(dCalcVectorDot3(m + dM3E__X_MIN, row2)) < 1e-6);
//
// /* just overwrite row[2], this makes sure the matrix is not
// a reflection */
// dCalcVectorCross3(m + dM3E__Z_MIN, m + dM3E__X_MIN, row2);
//
// m[dM3E_XPAD] = m[dM3E_YPAD] = m[dM3E_ZPAD] = 0;
//
// ret = true;
// }
// while (false);
//
// return ret;
// }
}