4 Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
6 This file is part of libc3.
8 libc3 is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 libc3 is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with libc3. If not, see <http://www.gnu.org/licenses/>.
23 #include "c3quaternion.h"
26 #define DEG2RAD(x) ((x)/180.0*M_PI)
27 #define RAD2DEG(x) ((x)/M_PI*180.0)
36 return c3quat_identity();
39 /************************************************* c3quat_identity() *****/
40 /* Returns quaternion identity element */
45 return c3quat_vec3( c3vec3f( 0.0, 0.0, 0.0 ), 1.0 );
55 c3quat q = { .v = c3vec3f(x,y,z), .s = w };
64 c3quat q = { .v = v, .s = s };
72 c3quat q = { .v = c3vec3f(v.n[0], v.n[1], v.n[2]), .s = v.n[3] };
81 q.v.n[0] = (c3f) d[0];
82 q.v.n[1] = (c3f) d[1];
83 q.v.n[2] = (c3f) d[2];
94 return c3quat_vec3(c3vec3_add(a.v, b.v), a.s + b.s );
102 return c3quat_vec3(c3vec3_sub(a.v, b.v), a.s - b.s );
109 return c3quat_vec3(c3vec3_minus(a.v), -a.s);
117 // return c3quat( a.s*b.s - a.v*b.v, a.s*b.v + b.s*a.v + a.v^b.v );
119 c3vec3_add(c3vec3_mulf(b.v, a.s), c3vec3_add(c3vec3_mulf(a.v, b.s), c3vec3_cross(a.v, b.v))),
120 (a.s * b.s) - c3vec3_dot(a.v, b.v));
124 c3quat_mulf( const c3quat a, const c3f t)
126 return c3quat_vec3(c3vec3_mulf(a.v, t), a.s * t );
133 c3f xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
135 c3f t = 2.0f / (c3vec3_dot(a.v, a.v) + (a.s * a.s));
137 xs = a.v.n[VX]*t; ys = a.v.n[VY]*t; zs = a.v.n[VZ]*t;
138 wx = a.s*xs; wy = a.s*ys; wz = a.s*zs;
139 xx = a.v.n[VX]*xs; xy = a.v.n[VX]*ys; xz = a.v.n[VX]*zs;
140 yy = a.v.n[VY]*ys; yz = a.v.n[VY]*zs; zz = a.v.n[VZ]*zs;
142 c3mat4 m = c3mat4_vec4(
143 c3vec4f(1.0f-(yy+zz), xy+wz, xz-wy, 0.0f),
144 c3vec4f(xy-wz, 1.0f-(xx+zz), yz+wx, 0.0f),
145 c3vec4f(xz+wy, yz-wx, 1.0f-(xx+yy), 0.0f),
146 c3vec4f(0.0f, 0.0f, 0.0f, 1.0f ));
152 /************************************************ quat_slerp() ********/
153 /* Quaternion spherical interpolation */
162 c3f omega, cosom, sinom, scale0, scale1;
164 /* calculate cosine */
165 cosom = c3vec3_dot(from.v, to.v) + from.s + to.s;
167 /* Adjust signs (if necessary) */
170 to1 = c3quat_minus(to);
175 /* Calculate coefficients */
176 if ((1.0 - cosom) > FUDGE ) {
177 /* standard case (slerp) */
178 omega = (c3f) acos( cosom );
179 sinom = (c3f) sin( omega );
180 scale0 = (c3f) sin((1.0 - t) * omega) / sinom;
181 scale1 = (c3f) sin(t * omega) / sinom;
183 /* 'from' and 'to' are very close - just do linear interpolation */
188 return c3quat_add(c3quat_mulf(from, scale0), c3quat_mulf(to1, scale1));
191 /********************************************** set_angle() ************/
192 /* set rot angle (degrees) */
199 c3vec3 axis = c3quat_get_axis(a);
201 a->s = (c3f) cos( DEG2RAD( f ) / 2.0 );
203 a->v = c3vec3_mulf(axis, (c3f) sin(DEG2RAD(f) / 2.0));
207 /********************************************** scale_angle() ************/
208 /* scale rot angle (degrees) */
215 return c3quat_set_angle(a, f * c3quat_get_angle(a) );
218 /********************************************** get_angle() ************/
219 /* get rot angle (degrees). Assumes s is between -1 and 1 */
225 return (c3f) RAD2DEG( 2.0 * acos( a->s ) );
228 /********************************************* get_axis() **************/
234 c3f scale = (c3f) sin( acos( a->s ) );
236 if ( scale < FUDGE && scale > -FUDGE )
237 return c3vec3f( 0.0, 0.0, 0.0 );
239 return c3vec3_divf(a->v, scale);
242 /******************************************* c3quat_print() ************/
244 void c3quat_print(FILE *dest, const char *name) const
246 fprintf( dest, "%s: v:<%3.2f %3.2f %3.2f> s:%3.2f\n",
247 name, v[0], v[1], v[2], s );