1 /* 2 * Copyright 2007 David Adam 3 * Copyright 2007 Vijay Kiran Kamuju 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include "d3drm_private.h" 21 22 /* Create a RGB color from its components */ 23 D3DCOLOR WINAPI D3DRMCreateColorRGB(D3DVALUE red, D3DVALUE green, D3DVALUE blue) 24 { 25 return D3DRMCreateColorRGBA(red, green, blue, 1.0f); 26 } 27 /* Create a RGBA color from its components */ 28 D3DCOLOR WINAPI D3DRMCreateColorRGBA(D3DVALUE red, D3DVALUE green, D3DVALUE blue, D3DVALUE alpha) 29 { 30 D3DCOLOR color; 31 32 d3drm_set_color(&color, red, green, blue, alpha); 33 34 return color; 35 } 36 37 /* Determine the alpha part of a color */ 38 D3DVALUE WINAPI D3DRMColorGetAlpha(D3DCOLOR color) 39 { 40 return (RGBA_GETALPHA(color)/255.0); 41 } 42 43 /* Determine the blue part of a color */ 44 D3DVALUE WINAPI D3DRMColorGetBlue(D3DCOLOR color) 45 { 46 return (RGBA_GETBLUE(color)/255.0); 47 } 48 49 /* Determine the green part of a color */ 50 D3DVALUE WINAPI D3DRMColorGetGreen(D3DCOLOR color) 51 { 52 return (RGBA_GETGREEN(color)/255.0); 53 } 54 55 /* Determine the red part of a color */ 56 D3DVALUE WINAPI D3DRMColorGetRed(D3DCOLOR color) 57 { 58 return (RGBA_GETRED(color)/255.0); 59 } 60 61 /* Product of 2 quaternions */ 62 D3DRMQUATERNION * WINAPI D3DRMQuaternionMultiply(D3DRMQUATERNION *q, D3DRMQUATERNION *a, D3DRMQUATERNION *b) 63 { 64 D3DRMQUATERNION temp; 65 D3DVECTOR cross_product; 66 67 D3DRMVectorCrossProduct(&cross_product, &a->v, &b->v); 68 temp.s = a->s * b->s - D3DRMVectorDotProduct(&a->v, &b->v); 69 temp.v.u1.x = a->s * b->v.u1.x + b->s * a->v.u1.x + cross_product.u1.x; 70 temp.v.u2.y = a->s * b->v.u2.y + b->s * a->v.u2.y + cross_product.u2.y; 71 temp.v.u3.z = a->s * b->v.u3.z + b->s * a->v.u3.z + cross_product.u3.z; 72 73 *q = temp; 74 return q; 75 } 76 77 /* Matrix for the Rotation that a unit quaternion represents */ 78 void WINAPI D3DRMMatrixFromQuaternion(D3DRMMATRIX4D m, D3DRMQUATERNION *q) 79 { 80 D3DVALUE w,x,y,z; 81 w = q->s; 82 x = q->v.u1.x; 83 y = q->v.u2.y; 84 z = q->v.u3.z; 85 m[0][0] = 1.0-2.0*(y*y+z*z); 86 m[1][1] = 1.0-2.0*(x*x+z*z); 87 m[2][2] = 1.0-2.0*(x*x+y*y); 88 m[1][0] = 2.0*(x*y+z*w); 89 m[0][1] = 2.0*(x*y-z*w); 90 m[2][0] = 2.0*(x*z-y*w); 91 m[0][2] = 2.0*(x*z+y*w); 92 m[2][1] = 2.0*(y*z+x*w); 93 m[1][2] = 2.0*(y*z-x*w); 94 m[3][0] = 0.0; 95 m[3][1] = 0.0; 96 m[3][2] = 0.0; 97 m[0][3] = 0.0; 98 m[1][3] = 0.0; 99 m[2][3] = 0.0; 100 m[3][3] = 1.0; 101 } 102 103 /* Return a unit quaternion that represents a rotation of an angle around an axis */ 104 D3DRMQUATERNION * WINAPI D3DRMQuaternionFromRotation(D3DRMQUATERNION *q, D3DVECTOR *v, D3DVALUE theta) 105 { 106 q->s = cos(theta/2.0); 107 D3DRMVectorScale(&q->v, D3DRMVectorNormalize(v), sin(theta/2.0)); 108 return q; 109 } 110 111 /* Interpolation between two quaternions */ 112 D3DRMQUATERNION * WINAPI D3DRMQuaternionSlerp(D3DRMQUATERNION *q, 113 D3DRMQUATERNION *a, D3DRMQUATERNION *b, D3DVALUE alpha) 114 { 115 D3DVALUE dot, epsilon, temp, theta, u; 116 D3DVECTOR v1, v2; 117 118 dot = a->s * b->s + D3DRMVectorDotProduct(&a->v, &b->v); 119 epsilon = 1.0f; 120 temp = 1.0f - alpha; 121 u = alpha; 122 if (dot < 0.0) 123 { 124 epsilon = -1.0; 125 dot = -dot; 126 } 127 if( 1.0f - dot > 0.001f ) 128 { 129 theta = acos(dot); 130 temp = sin(theta * temp) / sin(theta); 131 u = sin(theta * alpha) / sin(theta); 132 } 133 q->s = temp * a->s + epsilon * u * b->s; 134 D3DRMVectorScale(&v1, &a->v, temp); 135 D3DRMVectorScale(&v2, &b->v, epsilon * u); 136 D3DRMVectorAdd(&q->v, &v1, &v2); 137 return q; 138 } 139 140 /* Add Two Vectors */ 141 D3DVECTOR * WINAPI D3DRMVectorAdd(D3DVECTOR *d, D3DVECTOR *s1, D3DVECTOR *s2) 142 { 143 D3DVECTOR temp; 144 145 temp.u1.x=s1->u1.x + s2->u1.x; 146 temp.u2.y=s1->u2.y + s2->u2.y; 147 temp.u3.z=s1->u3.z + s2->u3.z; 148 149 *d = temp; 150 return d; 151 } 152 153 /* Subtract Two Vectors */ 154 D3DVECTOR * WINAPI D3DRMVectorSubtract(D3DVECTOR *d, D3DVECTOR *s1, D3DVECTOR *s2) 155 { 156 D3DVECTOR temp; 157 158 temp.u1.x=s1->u1.x - s2->u1.x; 159 temp.u2.y=s1->u2.y - s2->u2.y; 160 temp.u3.z=s1->u3.z - s2->u3.z; 161 162 *d = temp; 163 return d; 164 } 165 166 /* Cross Product of Two Vectors */ 167 D3DVECTOR * WINAPI D3DRMVectorCrossProduct(D3DVECTOR *d, D3DVECTOR *s1, D3DVECTOR *s2) 168 { 169 D3DVECTOR temp; 170 171 temp.u1.x=s1->u2.y * s2->u3.z - s1->u3.z * s2->u2.y; 172 temp.u2.y=s1->u3.z * s2->u1.x - s1->u1.x * s2->u3.z; 173 temp.u3.z=s1->u1.x * s2->u2.y - s1->u2.y * s2->u1.x; 174 175 *d = temp; 176 return d; 177 } 178 179 /* Dot Product of Two vectors */ 180 D3DVALUE WINAPI D3DRMVectorDotProduct(D3DVECTOR *s1, D3DVECTOR *s2) 181 { 182 D3DVALUE dot_product; 183 dot_product=s1->u1.x * s2->u1.x + s1->u2.y * s2->u2.y + s1->u3.z * s2->u3.z; 184 return dot_product; 185 } 186 187 /* Norm of a vector */ 188 D3DVALUE WINAPI D3DRMVectorModulus(D3DVECTOR *v) 189 { 190 D3DVALUE result; 191 result=sqrt(v->u1.x * v->u1.x + v->u2.y * v->u2.y + v->u3.z * v->u3.z); 192 return result; 193 } 194 195 /* Normalize a vector. Returns (1,0,0) if INPUT is the NULL vector. */ 196 D3DVECTOR * WINAPI D3DRMVectorNormalize(D3DVECTOR *u) 197 { 198 D3DVALUE modulus = D3DRMVectorModulus(u); 199 if(modulus) 200 { 201 D3DRMVectorScale(u,u,1.0/modulus); 202 } 203 else 204 { 205 u->u1.x=1.0; 206 u->u2.y=0.0; 207 u->u3.z=0.0; 208 } 209 return u; 210 } 211 212 /* Returns a random unit vector */ 213 D3DVECTOR * WINAPI D3DRMVectorRandom(D3DVECTOR *d) 214 { 215 d->u1.x = rand(); 216 d->u2.y = rand(); 217 d->u3.z = rand(); 218 D3DRMVectorNormalize(d); 219 return d; 220 } 221 222 /* Reflection of a vector on a surface */ 223 D3DVECTOR * WINAPI D3DRMVectorReflect(D3DVECTOR *r, D3DVECTOR *ray, D3DVECTOR *norm) 224 { 225 D3DVECTOR sca, temp; 226 D3DRMVectorSubtract(&temp, D3DRMVectorScale(&sca, norm, 2.0*D3DRMVectorDotProduct(ray,norm)), ray); 227 228 *r = temp; 229 return r; 230 } 231 232 /* Rotation of a vector */ 233 D3DVECTOR * WINAPI D3DRMVectorRotate(D3DVECTOR *r, D3DVECTOR *v, D3DVECTOR *axis, D3DVALUE theta) 234 { 235 D3DRMQUATERNION quaternion1, quaternion2, quaternion3; 236 D3DVECTOR norm; 237 238 quaternion1.s = cos(theta * 0.5f); 239 quaternion2.s = cos(theta * 0.5f); 240 norm = *D3DRMVectorNormalize(axis); 241 D3DRMVectorScale(&quaternion1.v, &norm, sin(theta * 0.5f)); 242 D3DRMVectorScale(&quaternion2.v, &norm, -sin(theta * 0.5f)); 243 quaternion3.s = 0.0; 244 quaternion3.v = *v; 245 D3DRMQuaternionMultiply(&quaternion1, &quaternion1, &quaternion3); 246 D3DRMQuaternionMultiply(&quaternion1, &quaternion1, &quaternion2); 247 248 *r = *D3DRMVectorNormalize(&quaternion1.v); 249 return r; 250 } 251 252 /* Scale a vector */ 253 D3DVECTOR * WINAPI D3DRMVectorScale(D3DVECTOR *d, D3DVECTOR *s, D3DVALUE factor) 254 { 255 D3DVECTOR temp; 256 257 temp.u1.x=factor * s->u1.x; 258 temp.u2.y=factor * s->u2.y; 259 temp.u3.z=factor * s->u3.z; 260 261 *d = temp; 262 return d; 263 } 264