d3drm: Implement D3DRMVectorRotate.
[wine] / dlls / d3drm / math.c
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 <stdio.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <assert.h>
24 #include <math.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "d3drmdef.h"
30
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(d3drm);
34
35 /* Product of 2 quaternions */
36 LPD3DRMQUATERNION WINAPI D3DRMQuaternionMultiply(LPD3DRMQUATERNION q, LPD3DRMQUATERNION a, LPD3DRMQUATERNION b)
37 {
38     D3DVECTOR cross_product;
39     D3DRMVectorCrossProduct(&cross_product, &a->v, &b->v);
40     q->s = a->s * b->s - D3DRMVectorDotProduct(&a->v, &b->v);
41     q->v.x = a->s * b->v.x + b->s * a->v.x + cross_product.x;
42     q->v.y = a->s * b->v.y + b->s * a->v.y + cross_product.y;
43     q->v.z = a->s * b->v.z + b->s * a->v.z + cross_product.z;
44     return q;
45 }
46
47 /* Add Two Vectors */
48 LPD3DVECTOR WINAPI D3DRMVectorAdd(LPD3DVECTOR d, LPD3DVECTOR s1, LPD3DVECTOR s2)
49 {
50     d->x=s1->x + s2->x;
51     d->y=s1->y + s2->y;
52     d->z=s1->z + s2->z;
53     return d;
54 }
55
56 /* Subtract Two Vectors */
57 LPD3DVECTOR WINAPI D3DRMVectorSubtract(LPD3DVECTOR d, LPD3DVECTOR s1, LPD3DVECTOR s2)
58 {
59     d->x=s1->x - s2->x;
60     d->y=s1->y - s2->y;
61     d->z=s1->z - s2->z;
62     return d;
63 }
64
65 /* Cross Product of Two Vectors */
66 LPD3DVECTOR WINAPI D3DRMVectorCrossProduct(LPD3DVECTOR d, LPD3DVECTOR s1, LPD3DVECTOR s2)
67 {
68     d->x=s1->y * s2->z - s1->z * s2->y;
69     d->y=s1->z * s2->x - s1->x * s2->z;
70     d->z=s1->x * s2->y - s1->y * s2->x;
71     return d;
72 }
73
74 /* Dot Product of Two vectors */
75 D3DVALUE WINAPI D3DRMVectorDotProduct(LPD3DVECTOR s1, LPD3DVECTOR s2)
76 {
77     D3DVALUE dot_product;
78     dot_product=s1->x * s2->x + s1->y * s2->y + s1->z * s2->z;
79     return dot_product;
80 }
81
82 /* Norm of a vector */
83 D3DVALUE WINAPI D3DRMVectorModulus(LPD3DVECTOR v)
84 {
85     D3DVALUE result;
86     result=sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
87     return result;
88 }
89
90 /* Normalize a vector.  Returns (1,0,0) if INPUT is the NULL vector. */
91 LPD3DVECTOR WINAPI D3DRMVectorNormalize(LPD3DVECTOR u)
92 {
93     D3DVALUE modulus = D3DRMVectorModulus(u);
94     if(modulus)
95     {
96         D3DRMVectorScale(u,u,1.0/modulus);
97     }
98     else
99     {
100         u->x=1.0;
101         u->y=0.0;
102         u->z=0.0;
103     }
104     return u;
105 }
106
107 /* Returns a random unit vector */
108 LPD3DVECTOR WINAPI D3DRMVectorRandom(LPD3DVECTOR d)
109 {
110     d->x = rand();
111     d->y = rand();
112     d->z = rand();
113     D3DRMVectorNormalize(d);
114     return d;
115 }
116
117 /* Reflection of a vector on a surface */
118 LPD3DVECTOR WINAPI D3DRMVectorReflect(LPD3DVECTOR r, LPD3DVECTOR ray, LPD3DVECTOR norm)
119 {
120     D3DVECTOR sca;
121     D3DRMVectorSubtract(r, D3DRMVectorScale(&sca, norm, 2.0*D3DRMVectorDotProduct(ray,norm)), ray);
122     return r;
123 }
124
125 /* Rotation of a vector */
126 LPD3DVECTOR WINAPI D3DRMVectorRotate(LPD3DVECTOR r, LPD3DVECTOR v, LPD3DVECTOR axis, D3DVALUE theta)
127 {
128     D3DRMQUATERNION quaternion,quaternion1, quaternion2, quaternion3, resultq;
129     D3DVECTOR NORM;
130
131     quaternion1.s = cos(theta*.5);
132     quaternion2.s = cos(theta*.5);
133     NORM = *D3DRMVectorNormalize(axis);
134     D3DRMVectorScale(&quaternion1.v, &NORM, sin(theta * .5));
135     D3DRMVectorScale(&quaternion2.v, &NORM, -sin(theta * .5));
136     quaternion3.s = 0.0;
137     quaternion3.v = *v;
138     D3DRMQuaternionMultiply(&quaternion, &quaternion1, &quaternion3);
139     D3DRMQuaternionMultiply(&resultq, &quaternion, &quaternion2);
140     *r = *D3DRMVectorNormalize(&resultq.v);
141     return r;
142 }
143
144 /* Scale a vector */
145 LPD3DVECTOR WINAPI D3DRMVectorScale(LPD3DVECTOR d, LPD3DVECTOR s, D3DVALUE factor)
146 {
147     d->x=factor * s->x;
148     d->y=factor * s->y;
149     d->z=factor * s->z;
150     return d;
151 }