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 17header: 18summary: Quaternion Functions 19description: 20 The following functions manipulate quaternions. 21end: 22 23function: rsQuaternionAdd 24ret: void 25arg: rs_quaternion* q, "Destination quaternion to add to." 26arg: const rs_quaternion* rhs, "Quaternion to add." 27summary: Add two quaternions 28description: 29 Adds two quaternions, i.e. <code>*q += *rhs;</code> 30inline: 31 q->w *= rhs->w; 32 q->x *= rhs->x; 33 q->y *= rhs->y; 34 q->z *= rhs->z; 35test: none 36end: 37 38function: rsQuaternionConjugate 39ret: void 40arg: rs_quaternion* q, "Quaternion to modify." 41summary: Conjugate a quaternion 42description: 43 Conjugates the quaternion. 44inline: 45 q->x = -q->x; 46 q->y = -q->y; 47 q->z = -q->z; 48test: none 49end: 50 51function: rsQuaternionDot 52ret: float 53arg: const rs_quaternion* q0, "First quaternion." 54arg: const rs_quaternion* q1, "Second quaternion." 55summary: Dot product of two quaternions 56description: 57 Returns the dot product of two quaternions. 58inline: 59 return q0->w*q1->w + q0->x*q1->x + q0->y*q1->y + q0->z*q1->z; 60test: none 61end: 62 63function: rsQuaternionGetMatrixUnit 64ret: void 65arg: rs_matrix4x4* m, "Resulting matrix." 66arg: const rs_quaternion* q, "Normalized quaternion." 67summary: Get a rotation matrix from a quaternion 68description: 69 Computes a rotation matrix from the normalized quaternion. 70inline: 71 float xx = q->x * q->x; 72 float xy = q->x * q->y; 73 float xz = q->x * q->z; 74 float xw = q->x * q->w; 75 float yy = q->y * q->y; 76 float yz = q->y * q->z; 77 float yw = q->y * q->w; 78 float zz = q->z * q->z; 79 float zw = q->z * q->w; 80 81 m->m[0] = 1.0f - 2.0f * ( yy + zz ); 82 m->m[4] = 2.0f * ( xy - zw ); 83 m->m[8] = 2.0f * ( xz + yw ); 84 m->m[1] = 2.0f * ( xy + zw ); 85 m->m[5] = 1.0f - 2.0f * ( xx + zz ); 86 m->m[9] = 2.0f * ( yz - xw ); 87 m->m[2] = 2.0f * ( xz - yw ); 88 m->m[6] = 2.0f * ( yz + xw ); 89 m->m[10] = 1.0f - 2.0f * ( xx + yy ); 90 m->m[3] = m->m[7] = m->m[11] = m->m[12] = m->m[13] = m->m[14] = 0.0f; 91 m->m[15] = 1.0f; 92test: none 93end: 94 95function: rsQuaternionLoadRotateUnit 96ret: void 97arg: rs_quaternion* q, "Destination quaternion." 98arg: float rot, "Angle to rotate by, in radians." 99arg: float x, "X component of the vector." 100arg: float y, "Y component of the vector." 101arg: float z, "Z component of the vector." 102summary: Quaternion that represents a rotation about an arbitrary unit vector 103description: 104 Loads a quaternion that represents a rotation about an arbitrary unit vector. 105inline: 106 rot *= (float)(M_PI / 180.0f) * 0.5f; 107 float c = cos(rot); 108 float s = sin(rot); 109 110 q->w = c; 111 q->x = x * s; 112 q->y = y * s; 113 q->z = z * s; 114test: none 115end: 116 117function: rsQuaternionSet 118ret: void 119arg: rs_quaternion* q, "Destination quaternion." 120arg: float w, "W component." 121arg: float x, "X component." 122arg: float y, "Y component." 123arg: float z, "Z component." 124summary: Create a quaternion 125description: 126 Creates a quaternion from its four components or from another quaternion. 127inline: 128 q->w = w; 129 q->x = x; 130 q->y = y; 131 q->z = z; 132test: none 133end: 134 135function: rsQuaternionSet 136ret: void 137arg: rs_quaternion* q 138arg: const rs_quaternion* rhs, "Source quaternion." 139inline: 140 q->w = rhs->w; 141 q->x = rhs->x; 142 q->y = rhs->y; 143 q->z = rhs->z; 144test: none 145end: 146 147# NOTE: The following inline definitions depend on each other. The order must be preserved 148# for the compilation to work. 149 150function: rsQuaternionLoadRotate 151ret: void 152arg: rs_quaternion* q, "Destination quaternion." 153arg: float rot, "Angle to rotate by." 154arg: float x, "X component of a vector." 155arg: float y, "Y component of a vector." 156arg: float z, "Z component of a vector." 157summary: Create a rotation quaternion 158description: 159 Loads a quaternion that represents a rotation about an arbitrary vector 160 (doesn't have to be unit) 161inline: 162 const float len = x*x + y*y + z*z; 163 if (len != 1) { 164 const float recipLen = 1.f / sqrt(len); 165 x *= recipLen; 166 y *= recipLen; 167 z *= recipLen; 168 } 169 rsQuaternionLoadRotateUnit(q, rot, x, y, z); 170test: none 171end: 172 173function: rsQuaternionNormalize 174ret: void 175arg: rs_quaternion* q, "Quaternion to normalize." 176summary: Normalize a quaternion 177description: 178 Normalizes the quaternion. 179inline: 180 const float len = rsQuaternionDot(q, q); 181 if (len != 1) { 182 const float recipLen = 1.f / sqrt(len); 183 q->w *= recipLen; 184 q->x *= recipLen; 185 q->y *= recipLen; 186 q->z *= recipLen; 187 } 188test: none 189end: 190 191function: rsQuaternionMultiply 192ret: void 193arg: rs_quaternion* q, "Destination quaternion." 194arg: float scalar, "Scalar to multiply the quaternion by." 195summary: Multiply a quaternion by a scalar or another quaternion 196description: 197 Multiplies a quaternion by a scalar or by another quaternion, e.g 198 <code>*q = *q * scalar;</code> or <code>*q = *q * *rhs;</code>. 199inline: 200 q->w *= scalar; 201 q->x *= scalar; 202 q->y *= scalar; 203 q->z *= scalar; 204test: none 205end: 206 207function: rsQuaternionMultiply 208ret: void 209arg: rs_quaternion* q 210arg: const rs_quaternion* rhs, "Quaternion to multiply the destination quaternion by." 211inline: 212 rs_quaternion qtmp; 213 rsQuaternionSet(&qtmp, q); 214 215 q->w = qtmp.w*rhs->w - qtmp.x*rhs->x - qtmp.y*rhs->y - qtmp.z*rhs->z; 216 q->x = qtmp.w*rhs->x + qtmp.x*rhs->w + qtmp.y*rhs->z - qtmp.z*rhs->y; 217 q->y = qtmp.w*rhs->y + qtmp.y*rhs->w + qtmp.z*rhs->x - qtmp.x*rhs->z; 218 q->z = qtmp.w*rhs->z + qtmp.z*rhs->w + qtmp.x*rhs->y - qtmp.y*rhs->x; 219 rsQuaternionNormalize(q); 220test: none 221end: 222 223function: rsQuaternionSlerp 224ret: void 225arg: rs_quaternion* q, "Result quaternion from the interpolation." 226arg: const rs_quaternion* q0, "First input quaternion." 227arg: const rs_quaternion* q1, "Second input quaternion." 228arg: float t, "How much to interpolate by." 229summary: Spherical linear interpolation between two quaternions 230description: 231 Performs spherical linear interpolation between two quaternions. 232inline: 233 if (t <= 0.0f) { 234 rsQuaternionSet(q, q0); 235 return; 236 } 237 if (t >= 1.0f) { 238 rsQuaternionSet(q, q1); 239 return; 240 } 241 242 rs_quaternion tempq0, tempq1; 243 rsQuaternionSet(&tempq0, q0); 244 rsQuaternionSet(&tempq1, q1); 245 246 float angle = rsQuaternionDot(q0, q1); 247 if (angle < 0) { 248 rsQuaternionMultiply(&tempq0, -1.0f); 249 angle *= -1.0f; 250 } 251 252 float scale, invScale; 253 if (angle + 1.0f > 0.05f) { 254 if (1.0f - angle >= 0.05f) { 255 float theta = acos(angle); 256 float invSinTheta = 1.0f / sin(theta); 257 scale = sin(theta * (1.0f - t)) * invSinTheta; 258 invScale = sin(theta * t) * invSinTheta; 259 } else { 260 scale = 1.0f - t; 261 invScale = t; 262 } 263 } else { 264 rsQuaternionSet(&tempq1, tempq0.z, -tempq0.y, tempq0.x, -tempq0.w); 265 scale = sin(M_PI * (0.5f - t)); 266 invScale = sin(M_PI * t); 267 } 268 269 rsQuaternionSet(q, tempq0.w*scale + tempq1.w*invScale, tempq0.x*scale + tempq1.x*invScale, 270 tempq0.y*scale + tempq1.y*invScale, tempq0.z*scale + tempq1.z*invScale); 271test: none 272end: 273