Home | API | File List | Examples | Download

lib3ds_quat.c

00001 /*
00002     Copyright (C) 1996-2008 by Jan Eric Kyprianidis <www.kyprianidis.com>
00003     All rights reserved.
00004     
00005     This program is free  software: you can redistribute it and/or modify 
00006     it under the terms of the GNU Lesser General Public License as published 
00007     by the Free Software Foundation, either version 2.1 of the License, or 
00008     (at your option) any later version.
00009 
00010     Thisprogram  is  distributed in the hope that it will be useful, 
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of 
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
00013     GNU Lesser General Public License for more details.
00014     
00015     You should  have received a copy of the GNU Lesser General Public License
00016     along with  this program; If not, see <http://www.gnu.org/licenses/>. 
00017 */
00018 
00022 #include "lib3ds_impl.h"
00023 
00024 
00028 void
00029 lib3ds_quat_identity(float c[4]) {
00030     c[0] = c[1] = c[2] = 0.0f;
00031     c[3] = 1.0f;
00032 }
00033 
00034 
00038 void
00039 lib3ds_quat_copy(float dest[4], float src[4]) {
00040     int i;
00041     for (i = 0; i < 4; ++i) {
00042         dest[i] = src[i];
00043     }
00044 }
00045 
00046 
00054 void
00055 lib3ds_quat_axis_angle(float c[4], float axis[3], float angle) {
00056     double omega, s;
00057     double l;
00058 
00059     l = sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
00060     if (l < LIB3DS_EPSILON) {
00061         c[0] = c[1] = c[2] = 0.0f;
00062         c[3] = 1.0f;
00063     } else {
00064         omega = -0.5 * angle;
00065         s = sin(omega) / l;
00066         c[0] = (float)s * axis[0];
00067         c[1] = (float)s * axis[1];
00068         c[2] = (float)s * axis[2];
00069         c[3] = (float)cos(omega);
00070     }
00071 }
00072 
00073 
00077 void
00078 lib3ds_quat_neg(float c[4]) {
00079     int i;
00080     for (i = 0; i < 4; ++i) {
00081         c[i] = -c[i];
00082     }
00083 }
00084 
00085 
00089 void
00090 lib3ds_quat_cnj(float c[4]) {
00091     int i;
00092     for (i = 0; i < 3; ++i) {
00093         c[i] = -c[i];
00094     }
00095 }
00096 
00097 
00104 void
00105 lib3ds_quat_mul(float c[4], float a[4], float b[4]) {
00106     float qa[4], qb[4];
00107     lib3ds_quat_copy(qa, a);
00108     lib3ds_quat_copy(qb, b);
00109     c[0] = qa[3] * qb[0] + qa[0] * qb[3] + qa[1] * qb[2] - qa[2] * qb[1];
00110     c[1] = qa[3] * qb[1] + qa[1] * qb[3] + qa[2] * qb[0] - qa[0] * qb[2];
00111     c[2] = qa[3] * qb[2] + qa[2] * qb[3] + qa[0] * qb[1] - qa[1] * qb[0];
00112     c[3] = qa[3] * qb[3] - qa[0] * qb[0] - qa[1] * qb[1] - qa[2] * qb[2];
00113 }
00114 
00115 
00119 void
00120 lib3ds_quat_scalar(float c[4], float k) {
00121     int i;
00122     for (i = 0; i < 4; ++i) {
00123         c[i] *= k;
00124     }
00125 }
00126 
00127 
00131 void
00132 lib3ds_quat_normalize(float c[4]) {
00133     double l, m;
00134 
00135     l = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3] * c[3]);
00136     if (fabs(l) < LIB3DS_EPSILON) {
00137         c[0] = c[1] = c[2] = 0.0f;
00138         c[3] = 1.0f;
00139     } else {
00140         int i;
00141         m = 1.0f / l;
00142         for (i = 0; i < 4; ++i) {
00143             c[i] = (float)(c[i] * m);
00144         }
00145     }
00146 }
00147 
00148 
00152 void
00153 lib3ds_quat_inv(float c[4]) {
00154     double l, m;
00155 
00156     l = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3] * c[3]);
00157     if (fabs(l) < LIB3DS_EPSILON) {
00158         c[0] = c[1] = c[2] = 0.0f;
00159         c[3] = 1.0f;
00160     } else {
00161         m = 1.0f / l;
00162         c[0] = (float)(-c[0] * m);
00163         c[1] = (float)(-c[1] * m);
00164         c[2] = (float)(-c[2] * m);
00165         c[3] = (float)(c[3] * m);
00166     }
00167 }
00168 
00169 
00173 float
00174 lib3ds_quat_dot(float a[4], float b[4]) {
00175     return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]);
00176 }
00177 
00178 
00179 float
00180 lib3ds_quat_norm(float c[4]) {
00181     return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
00182 }
00183 
00184 
00185 void
00186 lib3ds_quat_ln(float c[4]) {
00187     double om, s, t;
00188 
00189     s = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
00190     om = atan2(s, c[3]);
00191     if (fabs(s) < LIB3DS_EPSILON) {
00192         t = 0.0f;
00193     } else {
00194         t = om / s;
00195     }
00196     {
00197         int i;
00198         for (i = 0; i < 3; ++i) {
00199             c[i] = (float)(c[i] * t);
00200         }
00201         c[3] = 0.0f;
00202     }
00203 }
00204 
00205 
00206 void
00207 lib3ds_quat_ln_dif(float c[4], float a[4], float b[4]) {
00208     float invp[4];
00209 
00210     lib3ds_quat_copy(invp, a);
00211     lib3ds_quat_inv(invp);
00212     lib3ds_quat_mul(c, invp, b);
00213     lib3ds_quat_ln(c);
00214 }
00215 
00216 
00217 void
00218 lib3ds_quat_exp(float c[4]) {
00219     double om, sinom;
00220 
00221     om = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
00222     if (fabs(om) < LIB3DS_EPSILON) {
00223         sinom = 1.0f;
00224     } else {
00225         sinom = sin(om) / om;
00226     }
00227     {
00228         int i;
00229         for (i = 0; i < 3; ++i) {
00230             c[i] = (float)(c[i] * sinom);
00231         }
00232         c[3] = (float)cos(om);
00233     }
00234 }
00235 
00236 
00237 void
00238 lib3ds_quat_slerp(float c[4], float a[4], float b[4], float t) {
00239     double l;
00240     double om, sinom;
00241     double sp, sq;
00242     float flip = 1.0f;
00243     int i;
00244 
00245     l = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
00246     if (l < 0) { 
00247         flip = -1.0f;
00248         l = -l; 
00249     }    
00250     
00251     om = acos(l);
00252     sinom = sin(om);
00253     if (fabs(sinom) > LIB3DS_EPSILON) {
00254         sp = sin((1.0f - t) * om) / sinom;
00255         sq = sin(t * om) / sinom;
00256     } else {
00257         sp = 1.0f - t;
00258         sq = t;
00259     }
00260     sq *= flip;
00261     for (i = 0; i < 4; ++i) {
00262         c[i] = (float)(sp * a[i] + sq * b[i]);
00263     }
00264 }
00265 
00266 
00267 void
00268 lib3ds_quat_squad(float c[4], float a[4], float p[4], float q[4], float b[4], float t) {
00269     float ab[4];
00270     float pq[4];
00271 
00272     lib3ds_quat_slerp(ab, a, b, t);
00273     lib3ds_quat_slerp(pq, p, q, t);
00274     lib3ds_quat_slerp(c, ab, pq, 2*t*(1 - t));
00275 }
00276 
00277 
00278 void
00279 lib3ds_quat_tangent(float c[4], float p[4], float q[4], float n[4]) {
00280     float dn[4], dp[4], x[4];
00281     int i;
00282 
00283     lib3ds_quat_ln_dif(dn, q, n);
00284     lib3ds_quat_ln_dif(dp, q, p);
00285 
00286     for (i = 0; i < 4; i++) {
00287         x[i] = -1.0f / 4.0f * (dn[i] + dp[i]);
00288     }
00289     lib3ds_quat_exp(x);
00290     lib3ds_quat_mul(c, q, x);
00291 }
00292 
00293 
00294 void
00295 lib3ds_quat_dump(float q[4]) {
00296     printf("%f %f %f %f\n", q[0], q[1], q[2], q[3]);
00297 }
00298