1 /************************************************************************
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
26 /* create a new quaternion */
27 quaternion_t
*quat_create_quat(float x
, float y
, float z
, float w
)
29 quaternion_t
*q
= malloc(sizeof(quaternion_t
));
31 quat_init_quat(q
,x
,y
,z
,w
);
36 /* create a new quaternion from euler values */
37 quaternion_t
*quat_create_euler(float x
, float y
, float z
)
39 quaternion_t
*q
= malloc(sizeof(quaternion_t
));
41 quat_init_euler(q
,x
,y
,z
);
47 /* create a new quaternion from axis values */
48 quaternion_t
*quat_create_axis(v3_t
*v
, float angle
)
50 quaternion_t
*q
= malloc(sizeof(quaternion_t
));
52 quat_init_axis(q
,v
,angle
);
58 /* init a quaternion */
59 void quat_init_quat(quaternion_t
*q
, float x
, float y
, float z
, float w
)
70 /* init a quaternion from euler values */
71 void quat_init_euler(quaternion_t
*q
, float x
, float y
, float z
)
73 float poa
= M_PI
/180.0;
74 float rx
= y
* poa
/ 2.0;
75 float ry
= z
* poa
/ 2.0;
76 float rz
= x
* poa
/ 2.0;
85 q
->x
= sinr
* cosp
* cosy
- cosr
* sinp
* siny
;
86 q
->y
= cosr
* sinp
* cosy
+ sinr
* cosp
* siny
;
87 q
->z
= cosr
* cosp
* siny
- sinr
* sinp
* cosy
;
88 q
->w
= cosr
* cosp
* cosy
+ sinr
* sinp
* siny
;
93 /* init a quaternion from axis values */
94 void quat_init_axis(quaternion_t
*q
, v3_t
*v
, float angle
)
99 if (sqrt((v
->x
*v
->x
)+(v
->y
*v
->y
)+(v
->z
*v
->z
)) == 0.0) {
120 /* normalise a quaternion */
121 void quat_normalise(quaternion_t
*q
)
123 float mag
= sqrt((q
->x
*q
->x
)+(q
->y
*q
->y
)+(q
->z
*q
->z
)+(q
->w
*q
->w
));
125 /* Check for bogus length, to protect against divide by zero */
134 /* get axis values from a quaternion */
135 void quat_get_axis(quaternion_t
*q
, v3_t
*v
, float *angle
)
139 *angle
= acos(q
->w
)*2.0;
141 scale
= sqrt((q
->x
*q
->x
)+(q
->y
*q
->y
)+(q
->z
*q
->z
));
158 /* multiply a quaternion by a vector */
159 void quat_multiply_vector(quaternion_t
*q
, quaternion_t
*rq
, v3_t
*v
)
161 rq
->w
= -((q
->x
*v
->x
)-(q
->y
*v
->y
)-(q
->z
*v
->z
));
162 rq
->x
= (q
->w
*v
->x
)+(q
->y
*v
->z
)-(q
->z
*v
->y
);
163 rq
->y
= (q
->w
*v
->y
)+(q
->z
*v
->x
)-(q
->x
*v
->z
);
164 rq
->z
= (q
->w
*v
->z
)+(q
->x
*v
->y
)-(q
->y
*v
->x
);
167 /* multiply a quaternion by a quaternion */
168 void quat_multiply(quaternion_t
*q1
, quaternion_t
*q2
, quaternion_t
*rq
)
170 rq
->w
= (q1
->w
*q2
->w
)-(q1
->x
*q2
->x
)-(q1
->y
*q2
->y
)-(q1
->z
*q2
->z
);
171 rq
->x
= (q1
->w
*q2
->x
)+(q1
->x
*q2
->w
)+(q1
->y
*q2
->z
)-(q1
->z
*q2
->y
);
172 rq
->y
= (q1
->w
*q2
->y
)+(q1
->y
*q2
->w
)+(q1
->z
*q2
->x
)-(q1
->x
*q2
->z
);
173 rq
->z
= (q1
->w
*q2
->z
)+(q1
->z
*q2
->w
)+(q1
->x
*q2
->y
)-(q1
->y
*q2
->x
);
176 /* print the values of a quaternion */
177 void quat_print(quaternion_t
*q
)
179 printf("w:%f, x:%f, y:%f, z:%f",q
->w
,q
->x
,q
->y
,q
->z
);
183 /* compute the w value of a quaternion */
184 void quat_computew(quaternion_t
*q
)
186 float t
= 1.0-(q
->x
*q
->x
)-(q
->y
*q
->y
)-(q
->z
*q
->z
);
195 /* get the world position of a vertex, from a joint/weight */
196 void quat_rotate(quaternion_t
*q
, v3_t
*in
, v3_t
*out
)
212 quat_multiply(q
, &qin
, &tmp
);
213 quat_multiply(&tmp
, &inv
, &qin
);