ode/src/odemath.cpp
changeset 0 2f259fa3e83a
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*************************************************************************
       
     2  *                                                                       *
       
     3  * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
       
     4  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
       
     5  *                                                                       *
       
     6  * This library is free software; you can redistribute it and/or         *
       
     7  * modify it under the terms of EITHER:                                  *
       
     8  *   (1) The GNU Lesser General Public License as published by the Free  *
       
     9  *       Software Foundation; either version 2.1 of the License, or (at  *
       
    10  *       your option) any later version. The text of the GNU Lesser      *
       
    11  *       General Public License is included with this library in the     *
       
    12  *       file LICENSE.TXT.                                               *
       
    13  *   (2) The BSD-style license that is included with this library in     *
       
    14  *       the file LICENSE-BSD.TXT.                                       *
       
    15  *                                                                       *
       
    16  * This library is distributed in the hope that it will be useful,       *
       
    17  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
       
    18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
       
    19  * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
       
    20  *                                                                       *
       
    21  *************************************************************************/
       
    22 
       
    23 #include <ode/common.h>
       
    24 #include <ode/odemath.h>
       
    25 
       
    26 
       
    27 // this may be called for vectors `a' with extremely small magnitude, for
       
    28 // example the result of a cross product on two nearly perpendicular vectors.
       
    29 // we must be robust to these small vectors. to prevent numerical error,
       
    30 // first find the component a[i] with the largest magnitude and then scale
       
    31 // all the components by 1/a[i]. then we can compute the length of `a' and
       
    32 // scale the components by 1/l. this has been verified to work with vectors
       
    33 // containing the smallest representable numbers.
       
    34 
       
    35 EXPORT_C void dNormalize3 (dVector3 a)
       
    36 {
       
    37   dReal a0,a1,a2,aa0,aa1,aa2,l;
       
    38   a0 = a[0];
       
    39   a1 = a[1];
       
    40   a2 = a[2];
       
    41   aa0 = dFabs(a0);
       
    42   aa1 = dFabs(a1);
       
    43   aa2 = dFabs(a2);
       
    44   if (aa1 > aa0) {
       
    45     if (aa2 > aa1) {
       
    46       goto aa2_largest;
       
    47     }
       
    48     else {		// aa1 is largest
       
    49       a0 = dDIV(a0,aa1);
       
    50       a2 = dDIV(a2,aa1);
       
    51       l = dRecipSqrt (dMUL(a0,a0) + dMUL(a2,a2) + REAL(1.0));
       
    52       a[0] = dMUL(a0,l);
       
    53       a[1] = dCopySign(l,a1);
       
    54       a[2] = dMUL(a2,l);
       
    55     }
       
    56   }
       
    57   else {
       
    58     if (aa2 > aa0) {
       
    59       aa2_largest:	// aa2 is largest
       
    60       a0 = dDIV(a0,aa2);
       
    61       a1 = dDIV(a1,aa2);
       
    62       l = dRecipSqrt (dMUL(a0,a0) + dMUL(a1,a1) + REAL(1.0));
       
    63       a[0] = dMUL(a0,l);
       
    64       a[1] = dMUL(a1,l);
       
    65       a[2] = dCopySign(l,a2);
       
    66     }
       
    67     else {		// aa0 is largest
       
    68       if (aa0 <= 0) {
       
    69 	a[0] = REAL(1.0);	// if all a's are zero, this is where we'll end up.
       
    70 	a[1] = 0;	// return a default unit length vector.
       
    71 	a[2] = 0;
       
    72 	return;
       
    73       }
       
    74       a1 = dDIV(a1,aa0);
       
    75       a2 = dDIV(a2,aa0);
       
    76       l = dRecipSqrt (dMUL(a1,a1) + dMUL(a2,a2) + REAL(1.0));
       
    77       a[0] = dCopySign(l,a0);
       
    78       a[1] = dMUL(a1,l);
       
    79       a[2] = dMUL(a2,l);
       
    80     }
       
    81   }
       
    82 }
       
    83 
       
    84 
       
    85 /* OLD VERSION */
       
    86 /*
       
    87 void dNormalize3 (dVector3 a)
       
    88 {
       
    89 
       
    90   dReal l = dDOT(a,a);
       
    91   if (l > 0) {
       
    92     l = dRecipSqrt(l);
       
    93     a[0] *= l;
       
    94     a[1] *= l;
       
    95     a[2] *= l;
       
    96   }
       
    97   else {
       
    98     a[0] = 1;
       
    99     a[1] = 0;
       
   100     a[2] = 0;
       
   101   }
       
   102 }
       
   103 */
       
   104 
       
   105 
       
   106 EXPORT_C void dNormalize4 (dVector4 a)
       
   107 {
       
   108 
       
   109   dReal l = dDOT(a,a)+dMUL(a[3],a[3]);
       
   110   if (l > 0) {
       
   111     l = dRecipSqrt(l);
       
   112     a[0] = dMUL(a[0],l);
       
   113     a[1] = dMUL(a[1],l);
       
   114     a[2] = dMUL(a[2],l);
       
   115     a[3] = dMUL(a[3],l);
       
   116   }
       
   117   else {
       
   118     a[0] = REAL(1.0);
       
   119     a[1] = 0;
       
   120     a[2] = 0;
       
   121     a[3] = 0;
       
   122   }
       
   123 }
       
   124 
       
   125 
       
   126 EXPORT_C void dPlaneSpace (const dVector3 n, dVector3 p, dVector3 q)
       
   127 {
       
   128   if (dFabs(n[2]) > dSQRT1_2) {
       
   129     // choose p in y-z plane
       
   130     dReal a = dMUL(n[1],n[1]) + dMUL(n[2],n[2]);
       
   131     dReal k = dRecipSqrt (a);
       
   132     p[0] = 0;
       
   133     p[1] = -dMUL(n[2],k);
       
   134     p[2] = dMUL(n[1],k);
       
   135     // set q = n x p
       
   136     q[0] = dMUL(a,k);
       
   137     q[1] = -dMUL(n[0],p[2]);
       
   138     q[2] = dMUL(n[0],p[1]);
       
   139   }
       
   140   else {
       
   141     // choose p in x-y plane
       
   142     dReal a = dMUL(n[0],n[0]) + dMUL(n[1],n[1]);
       
   143     dReal k = dRecipSqrt (a);
       
   144     p[0] = -dMUL(n[1],k);
       
   145     p[1] = dMUL(n[0],k);
       
   146     p[2] = 0;
       
   147     // set q = n x p
       
   148     q[0] = -dMUL(n[2],p[1]);
       
   149     q[1] = dMUL(n[2],p[0]);
       
   150     q[2] = dMUL(a,k);
       
   151   }
       
   152 }
       
   153 
       
   154 EXPORT_C dReal dArcTan2(const dReal y, const dReal x)
       
   155 {
       
   156 	dReal coeff_1 = dPI/4;
       
   157   	dReal coeff_2 = 3*coeff_1;
       
   158 	dReal abs_y = dFabs(y) + dEpsilon;      // kludge to prevent 0/0 condition
       
   159 	dReal angle;
       
   160    if (x>=0)
       
   161    {
       
   162       dReal r = dDIV((x - abs_y),(x + abs_y));
       
   163       //angle = coeff_1 - dMUL(coeff_1,r);
       
   164       angle = dMUL(REAL(0.1963),dMUL(r,dMUL(r,r))) - dMUL(REAL(0.9817),r) + coeff_1;
       
   165    }
       
   166    else
       
   167    {
       
   168       dReal r = dDIV((x + abs_y),(abs_y - x));
       
   169       //angle = coeff_2 - dMUL(coeff_1,r);
       
   170       angle = dMUL(REAL(0.1963),dMUL(r,dMUL(r,r))) - dMUL(REAL(0.9817),r) + coeff_2;
       
   171    }
       
   172    if (y < 0)
       
   173    return(-angle);     // negate if in quad III or IV
       
   174    else
       
   175    return(angle);
       
   176 }
       
   177 
       
   178 EXPORT_C dReal dArcSin(dReal arg)
       
   179 {
       
   180 	dReal temp;
       
   181 	int sign;
       
   182 
       
   183 	sign = 0;
       
   184 	if(arg < 0)
       
   185 	{
       
   186 		arg = -arg;
       
   187 		sign++;
       
   188 	}
       
   189 	if(arg > REAL(1.0)) {
       
   190 		arg = REAL(1.0);
       
   191 		//return dInfinity;
       
   192 	}
       
   193 	temp = dSqrt(REAL(1.0) - dMUL(arg,arg));
       
   194 	if(arg > REAL(0.7))
       
   195 		temp = dPI/2 - dArcTan2(temp,arg);
       
   196 	else
       
   197 		temp = dArcTan2(arg,temp);
       
   198 	if(sign > 0)
       
   199 		temp = -temp;
       
   200 	return temp;
       
   201 }
       
   202