xref: /reactos/dll/directx/wine/d3drm/math.c (revision 3d017d71)
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 */
D3DRMCreateColorRGB(D3DVALUE red,D3DVALUE green,D3DVALUE blue)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 */
D3DRMCreateColorRGBA(D3DVALUE red,D3DVALUE green,D3DVALUE blue,D3DVALUE alpha)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 */
D3DRMColorGetAlpha(D3DCOLOR 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 */
D3DRMColorGetBlue(D3DCOLOR 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 */
D3DRMColorGetGreen(D3DCOLOR 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 */
D3DRMColorGetRed(D3DCOLOR color)56 D3DVALUE WINAPI D3DRMColorGetRed(D3DCOLOR color)
57 {
58     return (RGBA_GETRED(color)/255.0);
59 }
60 
61 /* Product of 2 quaternions */
D3DRMQuaternionMultiply(D3DRMQUATERNION * q,D3DRMQUATERNION * a,D3DRMQUATERNION * b)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 */
D3DRMMatrixFromQuaternion(D3DRMMATRIX4D m,D3DRMQUATERNION * q)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 */
D3DRMQuaternionFromRotation(D3DRMQUATERNION * q,D3DVECTOR * v,D3DVALUE theta)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 */
D3DRMQuaternionSlerp(D3DRMQUATERNION * q,D3DRMQUATERNION * a,D3DRMQUATERNION * b,D3DVALUE alpha)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 */
D3DRMVectorAdd(D3DVECTOR * d,D3DVECTOR * s1,D3DVECTOR * s2)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 */
D3DRMVectorSubtract(D3DVECTOR * d,D3DVECTOR * s1,D3DVECTOR * s2)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 */
D3DRMVectorCrossProduct(D3DVECTOR * d,D3DVECTOR * s1,D3DVECTOR * s2)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 */
D3DRMVectorDotProduct(D3DVECTOR * s1,D3DVECTOR * s2)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 */
D3DRMVectorModulus(D3DVECTOR * v)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. */
D3DRMVectorNormalize(D3DVECTOR * u)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 */
D3DRMVectorRandom(D3DVECTOR * d)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 */
D3DRMVectorReflect(D3DVECTOR * r,D3DVECTOR * ray,D3DVECTOR * norm)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 */
D3DRMVectorRotate(D3DVECTOR * r,D3DVECTOR * v,D3DVECTOR * axis,D3DVALUE theta)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 */
D3DRMVectorScale(D3DVECTOR * d,D3DVECTOR * s,D3DVALUE factor)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