C:/jkyprian/devel/lib3ds/lib3ds/quat.c

00001 /*
00002  * The 3D Studio File Format Library
00003  * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com>
00004  * All rights reserved.
00005  *
00006  * This program is  free  software;  you can redistribute it and/or modify it
00007  * under the terms of the  GNU Lesser General Public License  as published by 
00008  * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
00009  * your option) any later version.
00010  *
00011  * This  program  is  distributed in  the  hope that it will  be useful,  but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00013  * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
00014  * License for more details.
00015  *
00016  * You should  have received  a copy of the GNU Lesser General Public License
00017  * along with  this program;  if not, write to the  Free Software Foundation,
00018  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  *
00020  * $Id: quat.c,v 1.9 2007/06/20 17:04:09 jeh Exp $
00021  */
00022 #include <lib3ds/quat.h>
00023 #include <math.h>
00024 
00025 
00041 void
00042 lib3ds_quat_zero(Lib3dsQuat c)
00043 {
00044   c[0]=c[1]=c[2]=c[3]=0.0f;
00045 }
00046 
00047 
00052 void
00053 lib3ds_quat_identity(Lib3dsQuat c)
00054 {
00055   c[0]=c[1]=c[2]=0.0f;
00056   c[3]=1.0f;
00057 }
00058 
00059 
00064 void 
00065 lib3ds_quat_copy(Lib3dsQuat dest, Lib3dsQuat src)
00066 {
00067   int i;
00068   for (i=0; i<4; ++i) {
00069     dest[i]=src[i];
00070   }
00071 }
00072 
00073 
00083 void
00084 lib3ds_quat_axis_angle(Lib3dsQuat c, Lib3dsVector axis, Lib3dsFloat angle)
00085 {
00086   Lib3dsDouble omega,s;
00087   Lib3dsDouble l;
00088 
00089   l=sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
00090   if (l<LIB3DS_EPSILON) {
00091     c[0]=c[1]=c[2]=0.0f;
00092     c[3]=1.0f;
00093   }
00094   else {
00095     omega=-0.5*angle;
00096     s=sin(omega)/l;
00097     c[0]=(Lib3dsFloat)s*axis[0];
00098     c[1]=(Lib3dsFloat)s*axis[1];
00099     c[2]=(Lib3dsFloat)s*axis[2];
00100     c[3]=(Lib3dsFloat)cos(omega);
00101   }
00102 }
00103 
00104 
00110 void
00111 lib3ds_quat_neg(Lib3dsQuat c)
00112 {
00113   int i;
00114   for (i=0; i<4; ++i) {
00115     c[i]=-c[i];
00116   }
00117 }
00118 
00119 
00125 void
00126 lib3ds_quat_abs(Lib3dsQuat c)
00127 {
00128   int i;
00129   for (i=0; i<4; ++i) {
00130     c[i]=(Lib3dsFloat)fabs(c[i]);
00131   }
00132 }
00133 
00134 
00140 void
00141 lib3ds_quat_cnj(Lib3dsQuat c)
00142 {
00143   int i;
00144   for (i=0; i<3; ++i) {
00145     c[i]=-c[i];
00146   }
00147 }
00148 
00149 
00157 void
00158 lib3ds_quat_mul(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b)
00159 {
00160   c[0]=a[3]*b[0] + a[0]*b[3] + a[1]*b[2] - a[2]*b[1];
00161   c[1]=a[3]*b[1] + a[1]*b[3] + a[2]*b[0] - a[0]*b[2];
00162   c[2]=a[3]*b[2] + a[2]*b[3] + a[0]*b[1] - a[1]*b[0];
00163   c[3]=a[3]*b[3] - a[0]*b[0] - a[1]*b[1] - a[2]*b[2];
00164 }
00165 
00166 
00172 void
00173 lib3ds_quat_scalar(Lib3dsQuat c, Lib3dsFloat k)
00174 {
00175   int i;
00176   for (i=0; i<4; ++i) {
00177     c[i]*=k;
00178   }
00179 }
00180 
00181 
00187 void
00188 lib3ds_quat_normalize(Lib3dsQuat c)
00189 {
00190   Lib3dsDouble l,m;
00191 
00192   l=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
00193   if (fabs(l)<LIB3DS_EPSILON) {
00194     c[0]=c[1]=c[2]=0.0f;
00195     c[3]=1.0f; 
00196   }
00197   else {  
00198     int i;
00199     m=1.0f/l;
00200     for (i=0; i<4; ++i) {
00201       c[i]=(Lib3dsFloat)(c[i]*m);
00202     }
00203   }
00204 }
00205 
00206 
00212 void
00213 lib3ds_quat_inv(Lib3dsQuat c)
00214 {
00215   Lib3dsDouble l,m;
00216 
00217   l=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
00218   if (fabs(l)<LIB3DS_EPSILON) {
00219     c[0]=c[1]=c[2]=0.0f;
00220     c[3]=1.0f; 
00221   }
00222   else {  
00223     m=1.0f/l;
00224     c[0]=(Lib3dsFloat)(-c[0]*m);
00225     c[1]=(Lib3dsFloat)(-c[1]*m);
00226     c[2]=(Lib3dsFloat)(-c[2]*m);
00227     c[3]=(Lib3dsFloat)(c[3]*m);
00228   }
00229 }
00230 
00231 
00237 Lib3dsFloat
00238 lib3ds_quat_dot(Lib3dsQuat a, Lib3dsQuat b)
00239 {
00240   return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]);
00241 }
00242 
00243 
00247 Lib3dsFloat
00248 lib3ds_quat_squared(Lib3dsQuat c)
00249 {
00250   return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
00251 }
00252 
00253 
00257 Lib3dsFloat
00258 lib3ds_quat_length(Lib3dsQuat c)
00259 {
00260   return((Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]));
00261 }
00262 
00263 
00267 void
00268 lib3ds_quat_ln(Lib3dsQuat c)
00269 {
00270   Lib3dsDouble om,s,t;
00271 
00272   s=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
00273   om=atan2(s,c[3]);
00274   if (fabs(s)<LIB3DS_EPSILON) {
00275     t=0.0f;
00276   }
00277   else {
00278     t=om/s;
00279   }
00280   {
00281     int i;
00282     for (i=0; i<3; ++i) {
00283       c[i]=(Lib3dsFloat)(c[i]*t);
00284     }
00285     c[3]=0.0f;
00286   }
00287 }
00288 
00289 
00293 void
00294 lib3ds_quat_ln_dif(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b)
00295 {
00296   Lib3dsQuat invp;
00297 
00298   lib3ds_quat_copy(invp, a);
00299   lib3ds_quat_inv(invp);
00300   lib3ds_quat_mul(c, invp, b);
00301   lib3ds_quat_ln(c);
00302 }
00303 
00304 
00308 void
00309 lib3ds_quat_exp(Lib3dsQuat c)
00310 {
00311   Lib3dsDouble om,sinom;
00312 
00313   om=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
00314   if (fabs(om)<LIB3DS_EPSILON) {
00315     sinom=1.0f;
00316   }
00317   else {
00318     sinom=sin(om)/om;
00319   }
00320   {
00321     int i;
00322     for (i=0; i<3; ++i) {
00323       c[i]=(Lib3dsFloat)(c[i]*sinom);
00324     }
00325     c[3]=(Lib3dsFloat)cos(om);
00326   }
00327 }
00328 
00329 
00333 void
00334 lib3ds_quat_slerp(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b, Lib3dsFloat t)
00335 {
00336   Lib3dsDouble l;
00337   Lib3dsDouble om,sinom;
00338   Lib3dsDouble sp,sq;
00339   Lib3dsQuat q;
00340 
00341   l=a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];
00342   if ((1.0+l)>LIB3DS_EPSILON) {
00343     if (fabs(l)>1.0f) l/=fabs(l);
00344     om=acos(l);
00345     sinom=sin(om);
00346     if (fabs(sinom)>LIB3DS_EPSILON) {
00347       sp=sin((1.0f-t)*om)/sinom;
00348       sq=sin(t*om)/sinom;
00349     }
00350     else {
00351       sp=1.0f-t;
00352       sq=t;
00353     }
00354     c[0]=(Lib3dsFloat)(sp*a[0] + sq*b[0]);
00355     c[1]=(Lib3dsFloat)(sp*a[1] + sq*b[1]);
00356     c[2]=(Lib3dsFloat)(sp*a[2] + sq*b[2]);
00357     c[3]=(Lib3dsFloat)(sp*a[3] + sq*b[3]);
00358   }
00359   else {
00360     q[0]=-a[1];
00361     q[1]=a[0];
00362     q[2]=-a[3];
00363     q[3]=a[2];
00364     sp=sin((1.0-t)*LIB3DS_HALFPI);
00365     sq=sin(t*LIB3DS_HALFPI);
00366     c[0]=(Lib3dsFloat)(sp*a[0] + sq*q[0]);
00367     c[1]=(Lib3dsFloat)(sp*a[1] + sq*q[1]);
00368     c[2]=(Lib3dsFloat)(sp*a[2] + sq*q[2]);
00369     c[3]=(Lib3dsFloat)(sp*a[3] + sq*q[3]);
00370   }
00371 }
00372 
00373 
00377 void
00378 lib3ds_quat_squad(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat p, Lib3dsQuat q,
00379   Lib3dsQuat b, Lib3dsFloat t)
00380 {
00381   Lib3dsQuat ab;
00382   Lib3dsQuat pq;
00383 
00384   lib3ds_quat_slerp(ab,a,b,t);
00385   lib3ds_quat_slerp(pq,p,q,t);
00386   lib3ds_quat_slerp(c,ab,pq,2*t*(1-t));
00387 }
00388 
00389 
00393 void
00394 lib3ds_quat_tangent(Lib3dsQuat c, Lib3dsQuat p, Lib3dsQuat q, Lib3dsQuat n)
00395 {
00396   Lib3dsQuat dn,dp,x;
00397   int i;
00398 
00399   lib3ds_quat_ln_dif(dn, q, n);
00400   lib3ds_quat_ln_dif(dp, q, p);
00401 
00402   for (i=0; i<4; i++) {
00403     x[i]=-1.0f/4.0f*(dn[i]+dp[i]);
00404   }
00405   lib3ds_quat_exp(x);
00406   lib3ds_quat_mul(c,q,x);
00407 }
00408 
00409 
00413 void
00414 lib3ds_quat_dump(Lib3dsQuat q)
00415 {
00416   printf("%f %f %f %f\n", q[0], q[1], q[2], q[3]);
00417 }
00418 

Hosted by
SourceForge.net Logo
Generated at Wed Jun 20 18:51:36 2007 by Doxygen 1.5.2