rs_quaternion.rsh revision 20b27d602a4778ed50a83df2147416a35b7c92be
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// Don't edit this file!  It is auto-generated by frameworks/rs/api/generate.sh.
18
19/*
20 * rs_quaternion.rsh: Quaternion Functions
21 *
22 */
23
24#ifndef RENDERSCRIPT_RS_QUATERNION_RSH
25#define RENDERSCRIPT_RS_QUATERNION_RSH
26
27/*
28 * rsQuaternionAdd: Add two quaternions
29 *
30 * Adds two quaternions, i.e. *q += *rhs;
31 *
32 * Parameters:
33 *   q: Destination quaternion to add to.
34 *   rhs: Quaternion to add.
35 */
36static inline void __attribute__((overloadable))
37    rsQuaternionAdd(rs_quaternion* q, const rs_quaternion* rhs) {
38    q->w *= rhs->w;
39    q->x *= rhs->x;
40    q->y *= rhs->y;
41    q->z *= rhs->z;
42}
43
44/*
45 * rsQuaternionConjugate: Conjugate a quaternion
46 *
47 * Conjugates the quaternion.
48 *
49 * Parameters:
50 *   q: Quaternion to modify.
51 */
52static inline void __attribute__((overloadable))
53    rsQuaternionConjugate(rs_quaternion* q) {
54    q->x = -q->x;
55    q->y = -q->y;
56    q->z = -q->z;
57}
58
59/*
60 * rsQuaternionDot: Dot product of two quaternions
61 *
62 * Returns the dot product of two quaternions.
63 *
64 * Parameters:
65 *   q0: First quaternion.
66 *   q1: Second quaternion.
67 */
68static inline float __attribute__((overloadable))
69    rsQuaternionDot(const rs_quaternion* q0, const rs_quaternion* q1) {
70    return q0->w*q1->w + q0->x*q1->x + q0->y*q1->y + q0->z*q1->z;
71}
72
73/*
74 * rsQuaternionGetMatrixUnit: Get a rotation matrix from a quaternion
75 *
76 * Computes a rotation matrix from the normalized quaternion.
77 *
78 * Parameters:
79 *   m: Resulting matrix.
80 *   q: Normalized quaternion.
81 */
82static inline void __attribute__((overloadable))
83    rsQuaternionGetMatrixUnit(rs_matrix4x4* m, const rs_quaternion* q) {
84    float xx = q->x * q->x;
85    float xy = q->x * q->y;
86    float xz = q->x * q->z;
87    float xw = q->x * q->w;
88    float yy = q->y * q->y;
89    float yz = q->y * q->z;
90    float yw = q->y * q->w;
91    float zz = q->z * q->z;
92    float zw = q->z * q->w;
93
94    m->m[0]  = 1.0f - 2.0f * ( yy + zz );
95    m->m[4]  =        2.0f * ( xy - zw );
96    m->m[8]  =        2.0f * ( xz + yw );
97    m->m[1]  =        2.0f * ( xy + zw );
98    m->m[5]  = 1.0f - 2.0f * ( xx + zz );
99    m->m[9]  =        2.0f * ( yz - xw );
100    m->m[2]  =        2.0f * ( xz - yw );
101    m->m[6]  =        2.0f * ( yz + xw );
102    m->m[10] = 1.0f - 2.0f * ( xx + yy );
103    m->m[3]  = m->m[7] = m->m[11] = m->m[12] = m->m[13] = m->m[14] = 0.0f;
104    m->m[15] = 1.0f;
105}
106
107/*
108 * rsQuaternionLoadRotateUnit: Quaternion that represents a rotation about an arbitrary unit vector
109 *
110 * Loads a quaternion that represents a rotation about an arbitrary unit vector.
111 *
112 * Parameters:
113 *   q: Destination quaternion.
114 *   rot: Angle to rotate by, in radians.
115 *   x: X component of the vector.
116 *   y: Y component of the vector.
117 *   z: Z component of the vector.
118 */
119static inline void __attribute__((overloadable))
120    rsQuaternionLoadRotateUnit(rs_quaternion* q, float rot, float x, float y, float z) {
121    rot *= (float)(M_PI / 180.0f) * 0.5f;
122    float c = cos(rot);
123    float s = sin(rot);
124
125    q->w = c;
126    q->x = x * s;
127    q->y = y * s;
128    q->z = z * s;
129}
130
131/*
132 * rsQuaternionSet: Create a quarternion
133 *
134 * Creates a quaternion from its four components or from another quaternion.
135 *
136 * Parameters:
137 *   q: Destination quaternion.
138 *   w: W component.
139 *   x: X component.
140 *   y: Y component.
141 *   z: Z component.
142 *   rhs: Source quaternion.
143 */
144static inline void __attribute__((overloadable))
145    rsQuaternionSet(rs_quaternion* q, float w, float x, float y, float z) {
146    q->w = w;
147    q->x = x;
148    q->y = y;
149    q->z = z;
150}
151
152static inline void __attribute__((overloadable))
153    rsQuaternionSet(rs_quaternion* q, const rs_quaternion* rhs) {
154    q->w = rhs->w;
155    q->x = rhs->x;
156    q->y = rhs->y;
157    q->z = rhs->z;
158}
159
160/*
161 * rsQuaternionLoadRotate: Create a rotation quaternion
162 *
163 * Loads a quaternion that represents a rotation about an arbitrary vector
164 * (doesn't have to be unit)
165 *
166 * Parameters:
167 *   q: Destination quaternion.
168 *   rot: Angle to rotate by.
169 *   x: X component of a vector.
170 *   y: Y component of a vector.
171 *   z: Z component of a vector.
172 */
173static inline void __attribute__((overloadable))
174    rsQuaternionLoadRotate(rs_quaternion* q, float rot, float x, float y, float z) {
175    const float len = x*x + y*y + z*z;
176    if (len != 1) {
177        const float recipLen = 1.f / sqrt(len);
178        x *= recipLen;
179        y *= recipLen;
180        z *= recipLen;
181    }
182    rsQuaternionLoadRotateUnit(q, rot, x, y, z);
183}
184
185/*
186 * rsQuaternionNormalize: Normalize a quaternion
187 *
188 * Normalizes the quaternion.
189 *
190 * Parameters:
191 *   q: Quaternion to normalize.
192 */
193static inline void __attribute__((overloadable))
194    rsQuaternionNormalize(rs_quaternion* q) {
195    const float len = rsQuaternionDot(q, q);
196    if (len != 1) {
197        const float recipLen = 1.f / sqrt(len);
198        q->w *= recipLen;
199        q->x *= recipLen;
200        q->y *= recipLen;
201        q->z *= recipLen;
202    }
203}
204
205/*
206 * rsQuaternionMultiply: Multiply a quaternion by a scalar or another quaternion
207 *
208 * Multiplies a quaternion by a scalar or by another quaternion, e.g
209 * *q = *q * scalar; or *q = *q * *rhs;.
210 *
211 * Parameters:
212 *   q: Destination quaternion.
213 *   scalar: Scalar to multiply the quarternion by.
214 *   rhs: Quarternion to multiply the destination quaternion by.
215 */
216static inline void __attribute__((overloadable))
217    rsQuaternionMultiply(rs_quaternion* q, float scalar) {
218    q->w *= scalar;
219    q->x *= scalar;
220    q->y *= scalar;
221    q->z *= scalar;
222}
223
224static inline void __attribute__((overloadable))
225    rsQuaternionMultiply(rs_quaternion* q, const rs_quaternion* rhs) {
226    rs_quaternion qtmp;
227    rsQuaternionSet(&qtmp, q);
228
229    q->w = qtmp.w*rhs->w - qtmp.x*rhs->x - qtmp.y*rhs->y - qtmp.z*rhs->z;
230    q->x = qtmp.w*rhs->x + qtmp.x*rhs->w + qtmp.y*rhs->z - qtmp.z*rhs->y;
231    q->y = qtmp.w*rhs->y + qtmp.y*rhs->w + qtmp.z*rhs->x - qtmp.x*rhs->z;
232    q->z = qtmp.w*rhs->z + qtmp.z*rhs->w + qtmp.x*rhs->y - qtmp.y*rhs->x;
233    rsQuaternionNormalize(q);
234}
235
236/*
237 * rsQuaternionSlerp: Spherical linear interpolation between two quaternions
238 *
239 * Performs spherical linear interpolation between two quaternions.
240 *
241 * Parameters:
242 *   q: Result quaternion from the interpolation.
243 *   q0: First input quaternion.
244 *   q1: Second input quaternion.
245 *   t: How much to interpolate by.
246 */
247static inline void __attribute__((overloadable))
248    rsQuaternionSlerp(rs_quaternion* q, const rs_quaternion* q0, const rs_quaternion* q1, float t) {
249    if (t <= 0.0f) {
250        rsQuaternionSet(q, q0);
251        return;
252    }
253    if (t >= 1.0f) {
254        rsQuaternionSet(q, q1);
255        return;
256    }
257
258    rs_quaternion tempq0, tempq1;
259    rsQuaternionSet(&tempq0, q0);
260    rsQuaternionSet(&tempq1, q1);
261
262    float angle = rsQuaternionDot(q0, q1);
263    if (angle < 0) {
264        rsQuaternionMultiply(&tempq0, -1.0f);
265        angle *= -1.0f;
266    }
267
268    float scale, invScale;
269    if (angle + 1.0f > 0.05f) {
270        if (1.0f - angle >= 0.05f) {
271            float theta = acos(angle);
272            float invSinTheta = 1.0f / sin(theta);
273            scale = sin(theta * (1.0f - t)) * invSinTheta;
274            invScale = sin(theta * t) * invSinTheta;
275        } else {
276            scale = 1.0f - t;
277            invScale = t;
278        }
279    } else {
280        rsQuaternionSet(&tempq1, tempq0.z, -tempq0.y, tempq0.x, -tempq0.w);
281        scale = sin(M_PI * (0.5f - t));
282        invScale = sin(M_PI * t);
283    }
284
285    rsQuaternionSet(q, tempq0.w*scale + tempq1.w*invScale, tempq0.x*scale + tempq1.x*invScale,
286                        tempq0.y*scale + tempq1.y*invScale, tempq0.z*scale + tempq1.z*invScale);
287}
288
289#endif // RENDERSCRIPT_RS_QUATERNION_RSH
290