1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: m_vectors.cpp 4661 2014-03-21 19:14:21Z dr_sean $
5 //
6 // Copyright (C) 1997-2000 by id Software Inc.
7 // Copyright (C) 1998-2006 by Randy Heit (ZDoom).
8 // Copyright (C) 2006-2014 by The Odamex Team.
9 //
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // as published by the Free Software Foundation; either version 2
13 // of the License, or (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // DESCRIPTION:
21 // Vector math routines which I took from Quake2's source since they
22 // make more sense than the way Doom does things. :-)
23 //
24 // [SL] 2012-02-18 - Reworked all of the functions to be more uniform with
25 // the ordering of parameters, based in part on m_vectors.cpp from Eternity
26 // Engine. Also changed from using an array of floats as the underlying type
27 // to using a struct.
28 //-----------------------------------------------------------------------------
29
30
31 #include <stdio.h>
32
33 #include "m_fixed.h"
34 #include "m_vectors.h"
35 #include "actor.h"
36 #include "tables.h"
37
38 #include <cmath>
39
40 #ifndef M_PI
41 #define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
42 #endif
43
DEG2RAD(double a)44 static inline double DEG2RAD(double a)
45 {
46 static const double factor = M_PI / 180.0;
47 return a * factor;
48 }
49
50 //
51 // M_SetVec3f
52 //
53 // Sets the components of dest to the values of the parameters x, y, z
54 //
M_SetVec3f(v3float_t * dest,float x,float y,float z)55 void M_SetVec3f(v3float_t *dest, float x, float y, float z)
56 {
57 dest->x = x;
58 dest->y = y;
59 dest->z = z;
60 }
61
M_SetVec3f(v3float_t * dest,fixed_t x,fixed_t y,fixed_t z)62 void M_SetVec3f(v3float_t *dest, fixed_t x, fixed_t y, fixed_t z)
63 {
64 dest->x = FIXED2FLOAT(x);
65 dest->y = FIXED2FLOAT(y);
66 dest->z = FIXED2FLOAT(z);
67 }
68
M_SetVec3(v3double_t * dest,double x,double y,double z)69 void M_SetVec3(v3double_t *dest, double x, double y, double z)
70 {
71 dest->x = x;
72 dest->y = y;
73 dest->z = z;
74 }
75
M_SetVec3(v3double_t * dest,fixed_t x,fixed_t y,fixed_t z)76 void M_SetVec3(v3double_t *dest, fixed_t x, fixed_t y, fixed_t z)
77 {
78 dest->x = FIXED2DOUBLE(x);
79 dest->y = FIXED2DOUBLE(y);
80 dest->z = FIXED2DOUBLE(z);
81 }
82
M_SetVec2Fixed(v2fixed_t * dest,double x,double y)83 void M_SetVec2Fixed(v2fixed_t *dest, double x, double y)
84 {
85 dest->x = DOUBLE2FIXED(x);
86 dest->y = DOUBLE2FIXED(y);
87 }
88
M_SetVec2Fixed(v2fixed_t * dest,fixed_t x,fixed_t y)89 void M_SetVec2Fixed(v2fixed_t *dest, fixed_t x, fixed_t y)
90 {
91 dest->x = x;
92 dest->y = y;
93 }
94
M_SetVec3Fixed(v3fixed_t * dest,double x,double y,double z)95 void M_SetVec3Fixed(v3fixed_t *dest, double x, double y, double z)
96 {
97 dest->x = DOUBLE2FIXED(x);
98 dest->y = DOUBLE2FIXED(y);
99 dest->z = DOUBLE2FIXED(z);
100 }
101
M_SetVec3Fixed(v3fixed_t * dest,fixed_t x,fixed_t y,fixed_t z)102 void M_SetVec3Fixed(v3fixed_t *dest, fixed_t x, fixed_t y, fixed_t z)
103 {
104 dest->x = x;
105 dest->y = y;
106 dest->z = z;
107 }
108
109
110 //
111 // M_ConvertVec3FixedToVec3f
112 //
113 // Converts the component values of src to floats and stores
114 // in dest
115 //
M_ConvertVec3FixedToVec3f(v3float_t * dest,const v3fixed_t * src)116 void M_ConvertVec3FixedToVec3f(v3float_t *dest, const v3fixed_t *src)
117 {
118 M_SetVec3f(dest, src->x, src->y, src->z);
119 }
120
M_ConvertVec3FixedToVec3(v3double_t * dest,const v3fixed_t * src)121 void M_ConvertVec3FixedToVec3(v3double_t *dest, const v3fixed_t *src)
122 {
123 M_SetVec3(dest, src->x, src->y, src->z);
124 }
125
M_ConvertVec3fToVec3Fixed(v3fixed_t * dest,const v3float_t * src)126 void M_ConvertVec3fToVec3Fixed(v3fixed_t *dest, const v3float_t *src)
127 {
128 M_SetVec3Fixed(dest, double(src->x), double(src->y), double(src->z));
129 }
130
M_ConvertVec3ToVec3Fixed(v3fixed_t * dest,const v3double_t * src)131 void M_ConvertVec3ToVec3Fixed(v3fixed_t *dest, const v3double_t *src)
132 {
133 M_SetVec3Fixed(dest, src->x, src->y, src->z);
134 }
135
136
137 //
138 // M_IsZeroVec3f
139 //
140 // Returns true if the v is the zero or null vector (all components are 0)
141 //
M_IsZeroVec3f(const v3float_t * v)142 bool M_IsZeroVec3f(const v3float_t *v)
143 {
144 return fabs(v->x) == 0.0f && fabs(v->y) == 0.0f && fabs(v->z) == 0.0f;
145 }
146
M_IsZeroVec3(const v3double_t * v)147 bool M_IsZeroVec3(const v3double_t *v)
148 {
149 return fabs(v->x) == 0.0 && fabs(v->y) == 0.0 && fabs(v->z) == 0.0;
150 }
151
M_IsZeroVec2Fixed(const v2fixed_t * v)152 bool M_IsZeroVec2Fixed(const v2fixed_t *v)
153 {
154 return v->x == 0 && v->y == 0;
155 }
156
M_IsZeroVec3Fixed(const v3fixed_t * v)157 bool M_IsZeroVec3Fixed(const v3fixed_t *v)
158 {
159 return v->x == 0 && v->y == 0 && v->z == 0;
160 }
161
162
163 //
164 // M_ZeroVec3f
165 //
166 // Sets all components of v to 0
167 //
M_ZeroVec3f(v3float_t * v)168 void M_ZeroVec3f(v3float_t *v)
169 {
170 v->x = v->y = v->z = 0.0f;
171 }
172
M_ZeroVec3(v3double_t * v)173 void M_ZeroVec3(v3double_t *v)
174 {
175 v->x = v->y = v->z = 0.0;
176 }
177
M_ZeroVec2Fixed(v2fixed_t * v)178 void M_ZeroVec2Fixed(v2fixed_t *v)
179 {
180 v->x = v->y = 0;
181 }
182
M_ZeroVec3Fixed(v3fixed_t * v)183 void M_ZeroVec3Fixed(v3fixed_t *v)
184 {
185 v->x = v->y = v->z = 0;
186 }
187
188
189 //
190 // M_AddVec3f
191 //
192 // Adds v2 to v1 stores in dest
193 //
M_AddVec3f(v3float_t * dest,const v3float_t * v1,const v3float_t * v2)194 void M_AddVec3f(v3float_t *dest, const v3float_t *v1, const v3float_t *v2)
195 {
196 dest->x = v1->x + v2->x;
197 dest->y = v1->y + v2->y;
198 dest->z = v1->z + v2->z;
199 }
200
201
M_AddVec3(v3double_t * dest,const v3double_t * v1,const v3double_t * v2)202 void M_AddVec3(v3double_t *dest, const v3double_t *v1, const v3double_t *v2)
203 {
204 dest->x = v1->x + v2->x;
205 dest->y = v1->y + v2->y;
206 dest->z = v1->z + v2->z;
207 }
208
M_AddVec2Fixed(v2fixed_t * dest,const v2fixed_t * v1,const v2fixed_t * v2)209 void M_AddVec2Fixed(v2fixed_t *dest, const v2fixed_t *v1, const v2fixed_t *v2)
210 {
211 dest->x = v1->x + v2->x;
212 dest->y = v1->y + v2->y;
213 }
214
M_AddVec3Fixed(v3fixed_t * dest,const v3fixed_t * v1,const v3fixed_t * v2)215 void M_AddVec3Fixed(v3fixed_t *dest, const v3fixed_t *v1, const v3fixed_t *v2)
216 {
217 dest->x = v1->x + v2->x;
218 dest->y = v1->y + v2->y;
219 dest->z = v1->z + v2->z;
220 }
221
222
223 //
224 // M_SubVec3f
225 //
226 // Subtracts v2 from v1 stores in dest
227 //
M_SubVec3f(v3float_t * dest,const v3float_t * v1,const v3float_t * v2)228 void M_SubVec3f(v3float_t *dest, const v3float_t *v1, const v3float_t *v2)
229 {
230 dest->x = v1->x - v2->x;
231 dest->y = v1->y - v2->y;
232 dest->z = v1->z - v2->z;
233 }
234
M_SubVec3(v3double_t * dest,const v3double_t * v1,const v3double_t * v2)235 void M_SubVec3(v3double_t *dest, const v3double_t *v1, const v3double_t *v2)
236 {
237 dest->x = v1->x - v2->x;
238 dest->y = v1->y - v2->y;
239 dest->z = v1->z - v2->z;
240 }
241
M_SubVec2Fixed(v2fixed_t * dest,const v2fixed_t * v1,const v2fixed_t * v2)242 void M_SubVec2Fixed(v2fixed_t *dest, const v2fixed_t *v1, const v2fixed_t *v2)
243 {
244 dest->x = v1->x - v2->x;
245 dest->y = v1->y - v2->y;
246 }
247
M_SubVec3Fixed(v3fixed_t * dest,const v3fixed_t * v1,const v3fixed_t * v2)248 void M_SubVec3Fixed(v3fixed_t *dest, const v3fixed_t *v1, const v3fixed_t *v2)
249 {
250 dest->x = v1->x - v2->x;
251 dest->y = v1->y - v2->y;
252 dest->z = v1->z - v2->z;
253 }
254
255
256 //
257 // M_LengthVec3f
258 //
259 // Returns the length of a given vector (relative to the origin). Taken from
260 // Quake 2, added by CG.
261 //
M_LengthVec3f(const v3float_t * v)262 float M_LengthVec3f(const v3float_t *v)
263 {
264 return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z);
265 }
266
M_LengthVec3(const v3double_t * v)267 double M_LengthVec3(const v3double_t *v)
268 {
269 return sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
270 }
271
M_LengthVec2Fixed(const v2fixed_t * v)272 fixed_t M_LengthVec2Fixed(const v2fixed_t *v)
273 {
274 double fx = FIXED2DOUBLE(v->x);
275 double fy = FIXED2DOUBLE(v->y);
276
277 return DOUBLE2FIXED(sqrt(fx * fx + fy * fy));
278 }
279
M_LengthVec3Fixed(const v3fixed_t * v)280 fixed_t M_LengthVec3Fixed(const v3fixed_t *v)
281 {
282 double fx = FIXED2DOUBLE(v->x);
283 double fy = FIXED2DOUBLE(v->y);
284 double fz = FIXED2DOUBLE(v->z);
285
286 return DOUBLE2FIXED(sqrt(fx * fx + fy * fy + fz * fz));
287 }
288
289
290 //
291 // M_ScaleVec3f
292 //
293 // Multiplies each element in the vector by scalar value a
294 // and stores in dest
295 //
M_ScaleVec3f(v3float_t * dest,const v3float_t * v,float a)296 void M_ScaleVec3f(v3float_t *dest, const v3float_t *v, float a)
297 {
298 dest->x = v->x * a;
299 dest->y = v->y * a;
300 dest->z = v->z * a;
301 }
302
M_ScaleVec3(v3double_t * dest,const v3double_t * v,double a)303 void M_ScaleVec3(v3double_t *dest, const v3double_t *v, double a)
304 {
305 dest->x = v->x * a;
306 dest->y = v->y * a;
307 dest->z = v->z * a;
308 }
309
M_ScaleVec2Fixed(v2fixed_t * dest,const v2fixed_t * v,fixed_t a)310 void M_ScaleVec2Fixed(v2fixed_t *dest, const v2fixed_t *v, fixed_t a)
311 {
312 dest->x = FixedMul(v->x, a);
313 dest->y = FixedMul(v->y, a);
314 }
315
M_ScaleVec3Fixed(v3fixed_t * dest,const v3fixed_t * v,fixed_t a)316 void M_ScaleVec3Fixed(v3fixed_t *dest, const v3fixed_t *v, fixed_t a)
317 {
318 dest->x = FixedMul(v->x, a);
319 dest->y = FixedMul(v->y, a);
320 dest->z = FixedMul(v->z, a);
321 }
322
323
324 //
325 // M_ScaleVec3fToLength
326 //
327 // Scales each element in the vector such that the vector length equals a
328 // and stores the resulting vector in dest.
329 //
M_ScaleVec3fToLength(v3float_t * dest,const v3float_t * v,float a)330 void M_ScaleVec3fToLength(v3float_t* dest, const v3float_t* v, float a)
331 {
332 if (M_IsZeroVec3f(v))
333 M_ZeroVec3f(dest);
334 else
335 M_ScaleVec3f(dest, v, a / M_LengthVec3f(v));
336 }
337
M_ScaleVec3ToLength(v3double_t * dest,const v3double_t * v,double a)338 void M_ScaleVec3ToLength(v3double_t* dest, const v3double_t* v, double a)
339 {
340 if (M_IsZeroVec3(v))
341 M_ZeroVec3(dest);
342 else
343 M_ScaleVec3(dest, v, a / M_LengthVec3(v));
344 }
345
M_ScaleVec2FixedToLength(v2fixed_t * dest,const v2fixed_t * v,fixed_t a)346 void M_ScaleVec2FixedToLength(v2fixed_t* dest, const v2fixed_t* v, fixed_t a)
347 {
348 if (M_IsZeroVec2Fixed(v))
349 M_ZeroVec2Fixed(dest);
350 else
351 M_ScaleVec2Fixed(dest, v, FixedDiv(a, M_LengthVec2Fixed(v)));
352 }
353
M_ScaleVec3FixedToLength(v3fixed_t * dest,const v3fixed_t * v,fixed_t a)354 void M_ScaleVec3FixedToLength(v3fixed_t* dest, const v3fixed_t* v, fixed_t a)
355 {
356 if (M_IsZeroVec3Fixed(v))
357 M_ZeroVec3Fixed(dest);
358 else
359 M_ScaleVec3Fixed(dest, v, FixedDiv(a, M_LengthVec3Fixed(v)));
360 }
361
362
363 //
364 // M_DotVec3f
365 //
366 // Returns the dot product of v1 and v2
367 //
M_DotProductVec3f(const v3float_t * v1,const v3float_t * v2)368 float M_DotProductVec3f(const v3float_t *v1, const v3float_t *v2)
369 {
370 return (v1->x * v2->x) + (v1->y * v2->y) + (v1->z * v2->z);
371 }
372
M_DotProductVec3(const v3double_t * v1,const v3double_t * v2)373 double M_DotProductVec3(const v3double_t *v1, const v3double_t *v2)
374 {
375 return (v1->x * v2->x) + (v1->y * v2->y) + (v1->z * v2->z);
376 }
377
378
379 //
380 // M_CrossProduct3f
381 //
382 // Gets the cross product of v1 and v2 and stores in dest
383 //
M_CrossProductVec3f(v3float_t * dest,const v3float_t * v1,const v3float_t * v2)384 void M_CrossProductVec3f(v3float_t *dest, const v3float_t *v1, const v3float_t *v2)
385 {
386 dest->x = (v1->y * v2->z) - (v1->z * v2->y);
387 dest->y = (v1->z * v2->x) - (v1->x * v2->z);
388 dest->z = (v1->x * v2->y) - (v1->y * v2->x);
389 }
390
M_CrossProductVec3(v3double_t * dest,const v3double_t * v1,const v3double_t * v2)391 void M_CrossProductVec3(v3double_t *dest, const v3double_t *v1, const v3double_t *v2)
392 {
393 dest->x = (v1->y * v2->z) - (v1->z * v2->y);
394 dest->y = (v1->z * v2->x) - (v1->x * v2->z);
395 dest->z = (v1->x * v2->y) - (v1->y * v2->x);
396 }
397
398
399 //
400 // M_NormalizeVec3f
401 //
402 // Scales v so that its length is 1.0 and stores in dest
403 //
M_NormalizeVec3f(v3float_t * dest,const v3float_t * v)404 void M_NormalizeVec3f(v3float_t *dest, const v3float_t *v)
405 {
406 M_ScaleVec3fToLength(dest, v, 1.0f);
407 }
408
M_NormalizeVec3(v3double_t * dest,const v3double_t * v)409 void M_NormalizeVec3(v3double_t *dest, const v3double_t *v)
410 {
411 M_ScaleVec3ToLength(dest, v, 1.0);
412 }
413
M_NormalizeVec2Fixed(v2fixed_t * dest,const v2fixed_t * v)414 void M_NormalizeVec2Fixed(v2fixed_t *dest, const v2fixed_t *v)
415 {
416 M_ScaleVec2FixedToLength(dest, v, 1*FRACUNIT);
417 }
418
M_NormalizeVec3Fixed(v3fixed_t * dest,const v3fixed_t * v)419 void M_NormalizeVec3Fixed(v3fixed_t *dest, const v3fixed_t *v)
420 {
421 M_ScaleVec3FixedToLength(dest, v, 1*FRACUNIT);
422 }
423
424
425 //
426 // M_ActorToVec3f
427 //
428 // Stores thing's position in the vector dest
429 //
M_ActorPositionToVec3f(v3float_t * dest,const AActor * thing)430 void M_ActorPositionToVec3f(v3float_t *dest, const AActor *thing)
431 {
432 dest->x = FIXED2FLOAT(thing->x);
433 dest->y = FIXED2FLOAT(thing->y);
434 dest->z = FIXED2FLOAT(thing->z);
435 }
436
M_ActorPositionToVec3(v3double_t * dest,const AActor * thing)437 void M_ActorPositionToVec3(v3double_t *dest, const AActor *thing)
438 {
439 dest->x = FIXED2DOUBLE(thing->x);
440 dest->y = FIXED2DOUBLE(thing->y);
441 dest->z = FIXED2DOUBLE(thing->z);
442 }
443
M_ActorPositionToVec2Fixed(v2fixed_t * dest,const AActor * thing)444 void M_ActorPositionToVec2Fixed(v2fixed_t *dest, const AActor *thing)
445 {
446 dest->x = thing->x;
447 dest->y = thing->y;
448 }
449
M_ActorPositionToVec3Fixed(v3fixed_t * dest,const AActor * thing)450 void M_ActorPositionToVec3Fixed(v3fixed_t *dest, const AActor *thing)
451 {
452 dest->x = thing->x;
453 dest->y = thing->y;
454 dest->z = thing->z;
455 }
456
457
458 //
459 // M_ActorMomentumToVec3f
460 //
461 // Stores thing's momentum in the vector dest
462 //
M_ActorMomentumToVec3f(v3float_t * dest,const AActor * thing)463 void M_ActorMomentumToVec3f(v3float_t *dest, const AActor *thing)
464 {
465 dest->x = FIXED2FLOAT(thing->momx);
466 dest->y = FIXED2FLOAT(thing->momy);
467 dest->z = FIXED2FLOAT(thing->momz);
468 }
469
M_ActorMomentumToVec3(v3double_t * dest,const AActor * thing)470 void M_ActorMomentumToVec3(v3double_t *dest, const AActor *thing)
471 {
472 dest->x = FIXED2DOUBLE(thing->momx);
473 dest->y = FIXED2DOUBLE(thing->momy);
474 dest->z = FIXED2DOUBLE(thing->momz);
475 }
476
M_ActorMomentumToVec2Fixed(v2fixed_t * dest,const AActor * thing)477 void M_ActorMomentumToVec2Fixed(v2fixed_t *dest, const AActor *thing)
478 {
479 dest->x = thing->momx;
480 dest->y = thing->momy;
481 }
482
M_ActorMomentumToVec3Fixed(v3fixed_t * dest,const AActor * thing)483 void M_ActorMomentumToVec3Fixed(v3fixed_t *dest, const AActor *thing)
484 {
485 dest->x = thing->momx;
486 dest->y = thing->momy;
487 dest->z = thing->momz;
488 }
489
490
491 //
492 // M_AngleToVec3f
493 //
494 // Calculates the normalized direction vector from ang and pitch
495 //
M_AngleToVec3f(v3float_t * dest,angle_t ang,int pitch)496 void M_AngleToVec3f(v3float_t *dest, angle_t ang, int pitch)
497 {
498 dest->x = FIXED2FLOAT(finecosine[ang >> ANGLETOFINESHIFT]);
499 dest->y = FIXED2FLOAT(finesine[ang >> ANGLETOFINESHIFT]);
500 dest->z = FIXED2FLOAT(finetangent[FINEANGLES/4 - (pitch >> ANGLETOFINESHIFT)]);
501 M_NormalizeVec3f(dest, dest);
502 }
503
M_AngleToVec3(v3double_t * dest,angle_t ang,int pitch)504 void M_AngleToVec3(v3double_t *dest, angle_t ang, int pitch)
505 {
506 dest->x = FIXED2DOUBLE(finecosine[ang >> ANGLETOFINESHIFT]);
507 dest->y = FIXED2DOUBLE(finesine[ang >> ANGLETOFINESHIFT]) ;
508 dest->z = FIXED2DOUBLE(finetangent[FINEANGLES/4 - (pitch >> ANGLETOFINESHIFT)]);
509 M_NormalizeVec3(dest, dest);
510 }
511
512
513 //
514 // M_ProjectPointOnPlane
515 //
516 //
517 //
M_ProjectPointOnPlane(v3double_t * dest,const v3double_t * p,const v3double_t * normal)518 void M_ProjectPointOnPlane(v3double_t *dest, const v3double_t *p, const v3double_t *normal)
519 {
520 if (M_IsZeroVec3(normal))
521 {
522 // Assume that a normal of zero length is bad input and bail
523 M_ZeroVec3(dest);
524 return;
525 }
526
527 double inv_denom = 1.0 / M_DotProductVec3(normal, normal);
528 double d = M_DotProductVec3(normal, p) * inv_denom;
529
530 v3double_t n;
531 M_ScaleVec3(&n, normal, inv_denom * d);
532 M_SubVec3(dest, p, &n);
533 }
534
535 //
536 // M_PerpendicularVec3
537 //
538 // Assumes that src is a normalized vector
539 //
M_PerpendicularVec3(v3double_t * dest,const v3double_t * src)540 void M_PerpendicularVec3(v3double_t *dest, const v3double_t *src)
541 {
542 // find the smallest component of the vector src
543 v3double_t tempvec;
544 double minelem = src->x;
545 double *mincomponent = &(tempvec.x);
546 if (abs(src->y) < minelem)
547 {
548 minelem = abs(src->y);
549 mincomponent = &(tempvec.y);
550 }
551 if (abs(src->z) < minelem)
552 {
553 minelem = abs(src->z);
554 mincomponent = &(tempvec.z);
555 }
556
557 // make tempvec the identity vector along the axis of the smallest component
558 M_ZeroVec3(&tempvec);
559 *mincomponent = 1.0;
560
561 M_ProjectPointOnPlane(dest, &tempvec, src);
562 M_NormalizeVec3(dest, dest);
563 }
564
565
M_ConcatRotations(double out[3][3],const double in1[3][3],const double in2[3][3])566 static void M_ConcatRotations(double out[3][3], const double in1[3][3], const double in2[3][3])
567 {
568 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
569 in1[0][2] * in2[2][0];
570 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
571 in1[0][2] * in2[2][1];
572 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
573 in1[0][2] * in2[2][2];
574 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
575 in1[1][2] * in2[2][0];
576 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
577 in1[1][2] * in2[2][1];
578 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
579 in1[1][2] * in2[2][2];
580 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
581 in1[2][2] * in2[2][0];
582 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
583 in1[2][2] * in2[2][1];
584 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
585 in1[2][2] * in2[2][2];
586 }
587
588 #ifdef _MSC_VER
589 #pragma optimize( "", off )
590 #endif
591
M_RotatePointAroundVector(v3double_t * dest,const v3double_t * dir,const v3double_t * point,float degrees)592 void M_RotatePointAroundVector(v3double_t *dest, const v3double_t *dir, const v3double_t *point, float degrees)
593 {
594
595 double m[3][3], im[3][3], zrot[3][3], tmpmat[3][3], rot[3][3];
596 v3double_t vr, vup, vf;
597
598 vf.x = dir->x;
599 vf.y = dir->y;
600 vf.z = dir->z;
601
602 M_PerpendicularVec3(&vr, dir);
603 M_CrossProductVec3(&vup, &vr, &vf);
604
605 m[0][0] = vr.x;
606 m[1][0] = vr.y;
607 m[2][0] = vr.z;
608
609 m[0][1] = vup.x;
610 m[1][1] = vup.y;
611 m[2][1] = vup.z;
612
613 m[0][2] = vf.x;
614 m[1][2] = vf.y;
615 m[2][2] = vf.z;
616
617 memcpy( im, m, sizeof( im ) );
618
619 im[0][1] = m[1][0];
620 im[0][2] = m[2][0];
621 im[1][0] = m[0][1];
622 im[1][2] = m[2][1];
623 im[2][0] = m[0][2];
624 im[2][1] = m[1][2];
625
626 memset( zrot, 0, sizeof( zrot ) );
627 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0;
628
629 zrot[0][0] = (float)cos(DEG2RAD(degrees));
630 zrot[0][1] = (float)sin(DEG2RAD(degrees));
631 zrot[1][0] = (float)-sin(DEG2RAD(degrees));
632 zrot[1][1] = (float)cos(DEG2RAD(degrees));
633
634 M_ConcatRotations(tmpmat, m, zrot);
635 M_ConcatRotations(rot, tmpmat, im);
636
637 dest->x = rot[0][0] * point->x + rot[0][1] * point->y + rot[0][2] * point->z;
638 dest->y = rot[1][0] * point->x + rot[1][1] * point->y + rot[1][2] * point->z;
639 dest->z = rot[2][0] * point->x + rot[2][1] * point->y + rot[2][2] * point->z;
640 }
641
642 #ifdef _MSC_VER
643 #pragma optimize( "", on )
644 #endif
645
646 //
647 // M_TranslateVec3f
648 //
649 // Translates the given vector (in doom's coordinate system) to the camera
650 // space (in right-handed coordinate system) This function is used for slopes.
651 //
M_TranslateVec3f(v3float_t * vec,const v3float_t * origin,angle_t ang)652 void M_TranslateVec3f(v3float_t *vec, const v3float_t *origin, angle_t ang)
653 {
654 float tx, ty, tz;
655
656 float viewcosf = FIXED2FLOAT(finecosine[ang >> ANGLETOFINESHIFT]);
657 float viewsinf = FIXED2FLOAT(finesine[ang >> ANGLETOFINESHIFT]);
658
659 tx = vec->x - origin->x;
660 ty = origin->z - vec->y;
661 tz = vec->z - origin->y;
662
663 vec->x = (tx * viewcosf) - (tz * viewsinf);
664 vec->z = (tz * viewcosf) + (tx * viewsinf);
665 vec->y = ty;
666 }
667
M_TranslateVec3(v3double_t * vec,const v3double_t * origin,angle_t ang)668 void M_TranslateVec3 (v3double_t *vec, const v3double_t *origin, angle_t ang)
669 {
670 double tx, ty, tz;
671
672 double viewcosf = FIXED2DOUBLE(finecosine[ang >> ANGLETOFINESHIFT]);
673 double viewsinf = FIXED2DOUBLE(finesine[ang >> ANGLETOFINESHIFT]);
674
675 tx = vec->x - origin->x;
676 ty = origin->z - vec->y;
677 tz = vec->z - origin->y;
678
679 vec->x = (tx * viewcosf) - (tz * viewsinf);
680 vec->z = (tz * viewcosf) + (tx * viewsinf);
681 vec->y = ty;
682 }
683
684
685 VERSION_CONTROL (m_vectors_cpp, "$Id: m_vectors.cpp 4661 2014-03-21 19:14:21Z dr_sean $")
686
687