32922d786c803536d8a837d83e62ad6dafbf2ce1
[summerhack] / src / 3dengfx / libs / lib3ds / vector.c
1 /*
2  * The 3D Studio File Format Library
3  * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
4  * All rights reserved.
5  *
6  * This program is  free  software;  you can redistribute it and/or modify it
7  * under the terms of the  GNU Lesser General Public License  as published by 
8  * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
9  * your option) any later version.
10  *
11  * This  program  is  distributed in  the  hope that it will  be useful,  but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
14  * License for more details.
15  *
16  * You should  have received  a copy of the GNU Lesser General Public License
17  * along with  this program;  if not, write to the  Free Software Foundation,
18  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * $Id: vector.c,v 1.9 2004/11/16 07:41:44 efalk Exp $
21  */
22 #define LIB3DS_EXPORT
23 #include <lib3ds/vector.h>
24 #include <math.h>
25
26
27 /*!
28  * \defgroup vector Vector Mathematics
29  *
30  * \author J.E. Hoffmann <je-h@gmx.net>
31  */
32 /*!
33  * \typedef Lib3dsVector
34  *   \ingroup vector
35  */
36
37
38 /*!
39  * Clear a vector to zero.
40  *
41  * \param c Vector to clear.
42  *
43  * \ingroup vector
44  */
45 void
46 lib3ds_vector_zero(Lib3dsVector c)
47 {
48   int i;
49   for (i=0; i<3; ++i) {
50     c[i]=0.0f;
51   }
52 }
53
54
55 /*!
56  * Copy a vector.
57  *
58  * \param dest Destination vector.
59  * \param src Source vector.
60  *
61  * \ingroup vector
62  */
63 void
64 lib3ds_vector_copy(Lib3dsVector dest, Lib3dsVector src)
65 {
66   int i;
67   for (i=0; i<3; ++i) {
68     dest[i]=src[i];
69   }
70 }
71
72
73 /*!
74  * Negate a vector.
75  *
76  * \param c Vector to negate.
77  *
78  * \ingroup vector
79  */
80 void
81 lib3ds_vector_neg(Lib3dsVector c)
82 {
83   int i;
84   for (i=0; i<3; ++i) {
85     c[i]=-c[i];
86   }
87 }
88
89
90 /*!
91  * Add two vectors.
92  *
93  * \param c Result.
94  * \param a First addend.
95  * \param b Second addend.
96  *
97  * \ingroup vector
98  */
99 void
100 lib3ds_vector_add(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b)
101 {
102   int i;
103   for (i=0; i<3; ++i) {
104     c[i]=a[i]+b[i];
105   }
106 }
107
108
109 /*!
110  * Subtract two vectors.
111  *
112  * \param c Result.
113  * \param a Addend.
114  * \param b Minuend.
115  *
116  * \ingroup vector
117  */
118 void
119 lib3ds_vector_sub(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b)
120 {
121   int i;
122   for (i=0; i<3; ++i) {
123     c[i]=a[i]-b[i];
124   }
125 }
126
127
128 /*!
129  * Multiply a vector by a scalar.
130  *
131  * \param c Vector to be multiplied.
132  * \param k Scalar.
133  *
134  * \ingroup vector
135  */
136 void
137 lib3ds_vector_scalar(Lib3dsVector c, Lib3dsFloat k)
138 {
139   int i;
140   for (i=0; i<3; ++i) {
141     c[i]*=k;
142   }
143 }
144
145
146 /*!
147  * Compute cross product.
148  *
149  * \param c Result.
150  * \param a First vector.
151  * \param b Second vector.
152  *
153  * \ingroup vector
154  */
155 void
156 lib3ds_vector_cross(Lib3dsVector c, Lib3dsVector a, Lib3dsVector b)
157 {
158   c[0]=a[1]*b[2] - a[2]*b[1];
159   c[1]=a[2]*b[0] - a[0]*b[2];
160   c[2]=a[0]*b[1] - a[1]*b[0];
161 }
162
163
164 /*!
165  * Compute dot product.
166  *
167  * \param a First vector.
168  * \param b Second vector.
169  *
170  * \return Dot product.
171  *
172  * \ingroup vector
173  */
174 Lib3dsFloat
175 lib3ds_vector_dot(Lib3dsVector a, Lib3dsVector b)
176 {
177   return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
178 }
179
180
181 /*!
182  * Compute square of vector.
183  *
184  * Computes x*x + y*y + z*z.
185  *
186  * \param c Vector to square.
187  *
188  * \return Square of vector.
189  *
190  * \ingroup vector
191  */
192 Lib3dsFloat
193 lib3ds_vector_squared(Lib3dsVector c)
194 {
195   return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
196 }
197
198
199 /*!
200  * Compute length of vector.
201  *
202  * Computes |c| = sqrt(x*x + y*y + z*z)
203  *
204  * \param c Vector to compute.
205  *
206  * \return Length of vector.
207  *
208  * \ingroup vector
209  */
210 Lib3dsFloat
211 lib3ds_vector_length(Lib3dsVector c)
212 {
213   return((Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]));
214 }
215
216
217 /*!
218  * Normalize a vector.
219  *
220  * Scales a vector so that its length is 1.0.
221  *
222  * \param c Vector to normalize.
223  *
224  * \ingroup vector
225  */
226 void
227 lib3ds_vector_normalize(Lib3dsVector c)
228 {
229   Lib3dsFloat l,m;
230
231   l=(Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
232   if (fabs(l)<LIB3DS_EPSILON) {
233     if ((c[0]>=c[1]) && (c[0]>=c[2])) {
234       c[0]=1.0f;
235       c[1]=c[2]=0.0f;
236     }
237     else
238     if (c[1]>=c[2]) {
239       c[1]=1.0f;
240       c[0]=c[2]=0.0f;
241     }
242     else {
243       c[2]=1.0f;
244       c[0]=c[1]=0.0f;
245     }
246   }
247   else {
248     m=1.0f/l;
249     c[0]*=m;
250     c[1]*=m;
251     c[2]*=m;
252   }
253 }
254
255
256 /*!
257  * Compute a vector normal to two line segments.
258  *
259  * Computes the normal vector to the lines b-a and b-c.
260  *
261  * \param n Returned normal vector.
262  * \param a Endpoint of first line.
263  * \param b Base point of both lines.
264  * \param c Endpoint of second line.
265  *
266  * \ingroup vector
267  */
268 void
269 lib3ds_vector_normal(Lib3dsVector n, Lib3dsVector a, Lib3dsVector b, Lib3dsVector c)
270 {
271   Lib3dsVector p,q;
272
273   lib3ds_vector_sub(p,c,b);
274   lib3ds_vector_sub(q,a,b);
275   lib3ds_vector_cross(n,p,q);
276   lib3ds_vector_normalize(n);
277 }
278
279
280 /*!
281  * Multiply a point by a transformation matrix.
282  *
283  * Applies the given transformation matrix to the given point.  With some
284  * transformation matrices, a vector may also be transformed.
285  *
286  * \param c Result.
287  * \param m Transformation matrix.
288  * \param a Input point.
289  *
290  * \ingroup vector
291  */
292 void
293 lib3ds_vector_transform(Lib3dsVector c, Lib3dsMatrix m, Lib3dsVector a)
294 {
295   c[0]= m[0][0]*a[0] + m[1][0]*a[1] + m[2][0]*a[2] + m[3][0];
296   c[1]= m[0][1]*a[0] + m[1][1]*a[1] + m[2][1]*a[2] + m[3][1];
297   c[2]= m[0][2]*a[0] + m[1][2]*a[1] + m[2][2]*a[2] + m[3][2];
298 }
299
300
301 /*!
302  * Compute a point on a cubic spline.
303  *
304  * Computes a point on a parametric Bezier spline.
305  *
306  * \param c Result.
307  * \param a First endpoint of the spline.
308  * \param p First tangent vector of the spline.
309  * \param q Second tangent vector of the spline.
310  * \param b Second endpoint of the spline.
311  * \param t Spline parameter [0. 1.]
312  *
313  * \ingroup vector
314  */
315 void
316 lib3ds_vector_cubic(Lib3dsVector c, Lib3dsVector a, Lib3dsVector p, Lib3dsVector q,
317   Lib3dsVector b, Lib3dsFloat t)
318 {
319   Lib3dsDouble x,y,z,w;   
320
321   x=2*t*t*t - 3*t*t + 1;
322   y=-2*t*t*t + 3*t*t;
323   z=t*t*t - 2*t*t + t;
324   w=t*t*t - t*t;
325   c[0]=(Lib3dsFloat)(x*a[0] + y*b[0] + z*p[0] + w*q[0]);
326   c[1]=(Lib3dsFloat)(x*a[1] + y*b[1] + z*p[1] + w*q[1]);
327   c[2]=(Lib3dsFloat)(x*a[2] + y*b[2] + z*p[2] + w*q[2]);
328 }
329
330
331 /*!
332  * c[i] = min(c[i], a[i]);
333  *
334  * Computes minimum values of x,y,z independently.
335  *
336  * \ingroup vector
337  */
338 void 
339 lib3ds_vector_min(Lib3dsVector c, Lib3dsVector a)
340 {
341   int i;
342   for (i=0; i<3; ++i) {
343     if (a[i]<c[i]) {
344       c[i] = a[i];
345     }
346   }
347 }
348
349
350 /*!
351  * c[i] = max(c[i], a[i]);
352  *
353  * Computes maximum values of x,y,z independently.
354  *
355  * \ingroup vector
356  */
357 void 
358 lib3ds_vector_max(Lib3dsVector c, Lib3dsVector a)
359 {
360   int i;
361   for (i=0; i<3; ++i) {
362     if (a[i]>c[i]) {
363       c[i] = a[i];
364     }
365   }
366 }
367
368
369 /*!
370  * \ingroup vector
371  */
372 void
373 lib3ds_vector_dump(Lib3dsVector c)
374 {
375   fprintf(stderr, "%f %f %f\n", c[0], c[1], c[2]);
376 }
377