4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "system.h"
 
 
2
#include "prototyp.h"
 
 
3
#include <stdio.h>
 
 
4
#include <stdlib.h>
 
 
5
#include <math.h>
 
 
6
#include <sys/time.h>
 
 
7
 
 
 
8
#define deg22pt5 256
 
 
9
#define deg45 512
 
 
10
#define deg90 1024
 
 
11
 
 
 
12
#define Cosine45 46341           /* 46340.95001 cosine(45deg)*/
 
 
13
 
 
 
14
extern int16_t ArcCosTable[];
 
 
15
extern int16_t ArcSineTable[];
 
 
16
extern int16_t ArcTanTable[];
 
 
17
static int oneoversin[4096];
 
 
18
 
 
 
19
int min(int a, int b) { return a < b ? a : b; }
 
 
20
int max(int a, int b) { return a < b ? b : a; }
 
 
21
 
 
 
22
/* Fixed Point Divide - returns a / b */
 
 
23
 
 
 
24
int DIV_FIXED(const int a, const int b)
 
 
25
{
 
 
26
    return (((int64_t)a << 16) / b);
 
 
27
}
 
 
28
 
 
 
29
/*
 
 
30
 Fixed Point Multiply.
 
 
31
 
 
 
32
 16.16 * 16.16 -> 16.16
 
 
33
 or
 
 
34
 16.16 * 0.32 -> 0.32
 
 
35
 
 
 
36
 A proper version of this function ought to read
 
 
37
 16.16 * 16.16 -> 32.16
 
 
38
 but this would require a long long result
 
 
39
 
 
 
40
 Algorithm:
 
 
41
 
 
 
42
 Take the mid 32 bits of the 64 bit result
 
 
43
*/
 
 
44
 
 
 
45
int MUL_FIXED(const int a, const int b)
 
 
46
{
 
 
47
    return (((int64_t)a * (int64_t)b) >> 16);
 
 
48
}
 
 
49
 
 
 
50
void ConstructOneOverSinTable() 
 
 
51
{
 
 
52
    int a = 0;
 
 
53
 
 
 
54
    for (; a < 4096; a++) 
 
 
55
    {
 
 
56
        int sin = GetSin(a);
 
 
57
 
 
 
58
        if (sin != 0) 
 
 
59
        {
 
 
60
            oneoversin[a] = DIV_FIXED(ONE_FIXED, sin);
 
 
61
        }
 
 
62
        else
 
 
63
        {
 
 
64
            sin = 100;
 
 
65
            oneoversin[a] = DIV_FIXED(ONE_FIXED, sin);
 
 
66
        }
 
 
67
    }
 
 
68
}
 
 
69
 
 
 
70
int GetOneOverSin(int a) 
 
 
71
{
 
 
72
    return oneoversin[a & wrap360];
 
 
73
}
 
 
74
 
 
 
75
int DotProduct(const VECTORCH *vptr1, const VECTORCH *vptr2)
 
 
76
{
 
 
77
    return MUL_FIXED(vptr1->vx, vptr2->vx) + MUL_FIXED(vptr1->vy, vptr2->vy)+ MUL_FIXED(vptr1->vz, vptr2->vz);
 
 
78
}
 
 
79
 
 
 
80
int Magnitude(const VECTORCH *v)
 
 
81
{
 
 
82
    float x = v->vx;
 
 
83
    float y = v->vy;
 
 
84
    float z = v->vz;
 
 
85
 
 
 
86
    return sqrt((x * x) + (y * y) + (z * z));
 
 
87
}
 
 
88
 
 
 
89
int VectorDistance(const VECTORCH *v1, const VECTORCH *v2)
 
 
90
{
 
 
91
    float x = v1->vx - v2->vx;
 
 
92
    float y = v1->vy - v2->vy;
 
 
93
    float z = v1->vz - v2->vz;
 
 
94
 
 
 
95
        return sqrt((x * x) + (y * y) + (z * z));
 
 
96
}
 
 
97
 
 
 
98
/*
 
 
99
 
 
 
100
 Create Matrix from Euler Angles
 
 
101
 
 
 
102
 It requires a pointer to some euler angles and a pointer to a matrix
 
 
103
 
 
 
104
 Construct the matrix elements using the following formula
 
 
105
 
 
 
106
 Formula for ZXY Matrix
 
 
107
 
 
 
108
 m11 = cy*cz + sx*sy*sz    m12 = -cy*sz + sx*sy*cz   m13 = cx*sy
 
 
109
 m21 = cx*sz               m22 = cx*cz               m23 = -sx
 
 
110
 m31 = -sy*cz + sx*cy*sz   m32 = sy*sz + sx*cy*cz    m33 = cx*cy
 
 
111
 
 
 
112
*/
 
 
113
 
 
 
114
void CreateEulerMatrix(EULER *e, MATRIXCH *m1)
 
 
115
{
 
 
116
    int sx = GetSin(e->EulerX);
 
 
117
    int sy = GetSin(e->EulerY);
 
 
118
    int sz = GetSin(e->EulerZ);
 
 
119
 
 
 
120
    int cx = GetCos(e->EulerX);
 
 
121
    int cy = GetCos(e->EulerY);
 
 
122
    int cz = GetCos(e->EulerZ);
 
 
123
 
 
 
124
    int sx_sy = MUL_FIXED(sx, sy);
 
 
125
    int sx_cy = MUL_FIXED(sx, cy);
 
 
126
 
 
 
127
    /* m11 = cy*cz + sx*sy*sz */
 
 
128
 
 
 
129
    m1->mat11 = MUL_FIXED(cy, cz) + MUL_FIXED(sx_sy, sz);
 
 
130
 
 
 
131
    /* m12 = -cy*sz + sx*sy*cz */
 
 
132
 
 
 
133
    m1->mat12 = MUL_FIXED(-cy, sz) + MUL_FIXED(sx_sy, cz);
 
 
134
 
 
 
135
    /* m13 = cx*sy */
 
 
136
 
 
 
137
    m1->mat13 = MUL_FIXED(cx, sy);
 
 
138
 
 
 
139
    /* m21 = cx*sz */
 
 
140
 
 
 
141
    m1->mat21 = MUL_FIXED(cx, sz);
 
 
142
 
 
 
143
    /* m22 = cx*cz */
 
 
144
 
 
 
145
    m1->mat22 = MUL_FIXED(cx, cz);
 
 
146
 
 
 
147
    /* m23 = -sx */
 
 
148
 
 
 
149
    m1->mat23 = -sx;
 
 
150
 
 
 
151
    /* m31 = -sy*cz + sx*cy*sz */
 
 
152
 
 
 
153
    m1->mat31 = MUL_FIXED(-sy, cz) + MUL_FIXED(sx_cy, sz);
 
 
154
 
 
 
155
    /* m32 = sy*sz + sx*cy*cz */
 
 
156
 
 
 
157
    m1->mat32 = MUL_FIXED(sy,sz) + MUL_FIXED(sx_cy, cz);
 
 
158
 
 
 
159
    /* m33 = cx*cy */
 
 
160
 
 
 
161
    m1->mat33 = MUL_FIXED(cx,cy);
 
 
162
}
 
 
163
 
 
 
164
/*
 
 
165
 Matrix Multiply Function
 
 
166
 
 
 
167
 A 3x3 Matrix is represented here as
 
 
168
 
 
 
169
 m11 m12 m13
 
 
170
 m21 m22 m23
 
 
171
 m31 m32 m33
 
 
172
 
 
 
173
 Row #1 (r1) of the matrix is m11 m12 m13
 
 
174
 Column #1 (c1) of the matrix is m11 m32 m31
 
 
175
 
 
 
176
 Under multiplication
 
 
177
 
 
 
178
 m'' = m x m'
 
 
179
 
 
 
180
 where
 
 
181
 
 
 
182
 m11'' = c1.r1'
 
 
183
 m12'' = c2.r1'
 
 
184
 m13'' = c3.r1'
 
 
185
 
 
 
186
 m21'' = c1.r2'
 
 
187
 m22'' = c2.r2'
 
 
188
 m23'' = c3.r2'
 
 
189
 
 
 
190
 m31'' = c1.r3'
 
 
191
 m32'' = c2.r3'
 
 
192
 m33'' = c3.r3'
 
 
193
*/
 
 
194
 
 
 
195
void MatrixMultiply(const MATRIXCH *m1, const MATRIXCH *m2,  MATRIXCH *m3)
 
 
196
{
 
 
197
    int mat11 = MUL_FIXED(m1->mat11, m2->mat11) + MUL_FIXED(m1->mat21, m2->mat12) + MUL_FIXED(m1->mat31, m2->mat13);
 
 
198
    int mat12 = MUL_FIXED(m1->mat12, m2->mat11) + MUL_FIXED(m1->mat22, m2->mat12) + MUL_FIXED(m1->mat32, m2->mat13);
 
 
199
    int mat13 = MUL_FIXED(m1->mat13, m2->mat11) + MUL_FIXED(m1->mat23, m2->mat12) + MUL_FIXED(m1->mat33, m2->mat13);
 
 
200
    int mat21 = MUL_FIXED(m1->mat11, m2->mat21) + MUL_FIXED(m1->mat21, m2->mat22) + MUL_FIXED(m1->mat31, m2->mat23);
 
 
201
    int mat22 = MUL_FIXED(m1->mat12, m2->mat21) + MUL_FIXED(m1->mat22, m2->mat22) + MUL_FIXED(m1->mat32, m2->mat23);
 
 
202
    int mat23 = MUL_FIXED(m1->mat13, m2->mat21) + MUL_FIXED(m1->mat23, m2->mat22) + MUL_FIXED(m1->mat33, m2->mat23);
 
 
203
    int mat31 = MUL_FIXED(m1->mat11, m2->mat31) + MUL_FIXED(m1->mat21, m2->mat32) + MUL_FIXED(m1->mat31, m2->mat33);
 
 
204
    int mat32 = MUL_FIXED(m1->mat12, m2->mat31) + MUL_FIXED(m1->mat22, m2->mat32) + MUL_FIXED(m1->mat32, m2->mat33);
 
 
205
    int mat33 = MUL_FIXED(m1->mat13, m2->mat31) + MUL_FIXED(m1->mat23, m2->mat32) + MUL_FIXED(m1->mat33, m2->mat33);
 
 
206
 
 
 
207
    m3->mat11 = mat11;
 
 
208
    m3->mat12 = mat12;
 
 
209
    m3->mat13 = mat13;
 
 
210
    m3->mat21 = mat21;
 
 
211
    m3->mat22 = mat22;
 
 
212
    m3->mat23 = mat23;
 
 
213
    m3->mat31 = mat31;
 
 
214
    m3->mat32 = mat32;
 
 
215
    m3->mat33 = mat33;
 
 
216
}
 
 
217
 
 
 
218
void TransposeMatrixCH(MATRIXCH *m1)
 
 
219
{
 
 
220
    int temp = m1->mat12;
 
 
221
 
 
 
222
    m1->mat12 = m1->mat21;
 
 
223
    m1->mat21 = temp;
 
 
224
 
 
 
225
    temp = m1->mat13;
 
 
226
    m1->mat13 = m1->mat31;
 
 
227
    m1->mat31 = temp;
 
 
228
 
 
 
229
    temp = m1->mat23;
 
 
230
    m1->mat23 = m1->mat32;
 
 
231
    m1->mat32 = temp;
 
 
232
}
 
 
233
 
 
 
234
/*
 
 
235
 Matrix Rotatation of a Vector
 
 
236
 
 
 
237
 Overwrite the Source Vector with the Rotated Vector
 
 
238
 
 
 
239
 x' = v.c1
 
 
240
 y' = v.c2
 
 
241
 z' = v.c3
 
 
242
*/
 
 
243
 
 
 
244
void RotateVector(VECTORCH *v, const MATRIXCH*  m)
 
 
245
{
 
 
246
    int x = MUL_FIXED(m->mat11, v->vx) + MUL_FIXED(m->mat21, v->vy) + MUL_FIXED(m->mat31, v->vz);
 
 
247
    int y = MUL_FIXED(m->mat12, v->vx) + MUL_FIXED(m->mat22, v->vy) + MUL_FIXED(m->mat32, v->vz);
 
 
248
    int z = MUL_FIXED(m->mat13, v->vx) + MUL_FIXED(m->mat23, v->vy) + MUL_FIXED(m->mat33, v->vz);
 
 
249
 
 
 
250
    v->vx = x;
 
 
251
    v->vy = y;
 
 
252
    v->vz = z;
 
 
253
}
 
 
254
 
 
 
255
/*
 
 
256
 Matrix Rotation of a Source Vector using a Matrix
 
 
257
 Copying to a Destination Vector
 
 
258
 
 
 
259
 x' = v.c1
 
 
260
 y' = v.c2
 
 
261
 z' = v.c3
 
 
262
*/
 
 
263
 
 
 
264
void RotateAndCopyVector(const VECTORCH *v1, VECTORCH *v2, const MATRIXCH *m)
 
 
265
{
 
 
266
    v2->vx = MUL_FIXED(m->mat11, v1->vx) + MUL_FIXED(m->mat21, v1->vy) + MUL_FIXED(m->mat31, v1->vz);
 
 
267
    v2->vy = MUL_FIXED(m->mat12, v1->vx) + MUL_FIXED(m->mat22, v1->vy) + MUL_FIXED(m->mat32, v1->vz);
 
 
268
    v2->vz = MUL_FIXED(m->mat13, v1->vx) + MUL_FIXED(m->mat23, v1->vy) + MUL_FIXED(m->mat33, v1->vz);
 
 
269
}
 
 
270
 
 
 
271
/*
 
 
272
 
 
 
273
 Matrix to Euler Angles
 
 
274
 
 
 
275
 Maths overflow is a real problem for this function. To prevent overflows
 
 
276
 the matrix Sines and Cosines are calculated using values scaled down by 4.
 
 
277
 
 
 
278
 
 
 
279
 sinx    =    -M23
 
 
280
 
 
 
281
 cosx    =    sqr ( 1 - sinx^2 )
 
 
282
 
 
 
283
 
 
 
284
 siny    =    M13 / cosx
 
 
285
 
 
 
286
 cosy    =    M33 / cosx
 
 
287
 
 
 
288
 
 
 
289
 sinz    =    M21 / cosx
 
 
290
 
 
 
291
 cosz    =    M22 / cosx
 
 
292
 
 
 
293
 
 
 
294
*/
 
 
295
 
 
 
296
int SqRoot32(int A)
 
 
297
{
 
 
298
    return sqrt( (float)A );
 
 
299
}
 
 
300
 
 
 
301
/* This function performs a Widening Multiply followed by a Narrowing Divide.  */
 
 
302
 
 
 
303
int WideMulNarrowDiv(const int a, const int b, const int c)
 
 
304
{
 
 
305
    return (int64_t)a * (int64_t)b /c;
 
 
306
}
 
 
307
 
 
 
308
#define m2e_scale 2
 
 
309
#define ONE_FIXED_S ((ONE_FIXED >> m2e_scale) - 1)
 
 
310
#define m2e_shift 14
 
 
311
 
 
 
312
#define j_and_r_change 1 
 
 
313
 
 
 
314
void MatrixToEuler(const MATRIXCH *m, EULER *e)
 
 
315
{
 
 
316
    int x, siny,cosy, abs_cosy;
 
 
317
 
 
 
318
    if(m->mat32 > -65500 && m->mat32 < 65500)
 
 
319
    {
 
 
320
        int abs_cosx,  abs_cosz, sinx, cosx, sinz, cosz;
 
 
321
        int CosMatrixPitch, CosMatrixYaw, CosMatrixRoll;
 
 
322
        int SineMatrixPitch, SineMatrixYaw, SineMatrixRoll;
 
 
323
        /* Yaw */
 
 
324
        /* Pitch */
 
 
325
 
 
 
326
        #if j_and_r_change
 
 
327
        SineMatrixPitch = -m->mat32;
 
 
328
        #else
 
 
329
        SineMatrixPitch = -m->mat23;
 
 
330
        #endif
 
 
331
 
 
 
332
        SineMatrixPitch >>= m2e_scale;
 
 
333
 
 
 
334
        CosMatrixPitch = SineMatrixPitch * SineMatrixPitch;
 
 
335
        CosMatrixPitch >>= m2e_shift;
 
 
336
 
 
 
337
        CosMatrixPitch = -CosMatrixPitch;
 
 
338
        CosMatrixPitch += ONE_FIXED_S;
 
 
339
        CosMatrixPitch *= ONE_FIXED_S;
 
 
340
        CosMatrixPitch = SqRoot32(CosMatrixPitch);
 
 
341
 
 
 
342
        if(CosMatrixPitch) 
 
 
343
        {
 
 
344
            if(CosMatrixPitch > ONE_FIXED_S) 
 
 
345
                CosMatrixPitch = ONE_FIXED_S;
 
 
346
            else if(CosMatrixPitch < -ONE_FIXED_S)
 
 
347
                CosMatrixPitch = -ONE_FIXED_S;
 
 
348
        }
 
 
349
        else
 
 
350
            CosMatrixPitch = 1;
 
 
351
 
 
 
352
        SineMatrixYaw = WideMulNarrowDiv(
 
 
353
            #if j_and_r_change
 
 
354
            m->mat31 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
 
 
355
            #else
 
 
356
            m->mat13 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
 
 
357
            #endif
 
 
358
 
 
 
359
        CosMatrixYaw = WideMulNarrowDiv( m->mat33 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
 
 
360
 
 
 
361
        /* Roll */
 
 
362
 
 
 
363
        SineMatrixRoll = WideMulNarrowDiv(
 
 
364
            #if j_and_r_change
 
 
365
            m->mat12 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
 
 
366
            #else
 
 
367
            m->mat21 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
 
 
368
            #endif
 
 
369
 
 
 
370
        CosMatrixRoll = WideMulNarrowDiv( m->mat22 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
 
 
371
 
 
 
372
        /* Tables are for values +- 2^16 */
 
 
373
 
 
 
374
        sinx = SineMatrixPitch << m2e_scale;
 
 
375
        siny = SineMatrixYaw   << m2e_scale;
 
 
376
        sinz = SineMatrixRoll  << m2e_scale;
 
 
377
 
 
 
378
        cosx = CosMatrixPitch << m2e_scale;
 
 
379
        cosy = CosMatrixYaw   << m2e_scale;
 
 
380
        cosz = CosMatrixRoll  << m2e_scale;
 
 
381
 
 
 
382
        /* Absolute Cosines */
 
 
383
 
 
 
384
        abs_cosx = abs(cosx);
 
 
385
        abs_cosy = abs(cosy);
 
 
386
        abs_cosz = abs(cosz);
 
 
387
 
 
 
388
        /* Euler X */
 
 
389
 
 
 
390
        if(abs_cosx > Cosine45) 
 
 
391
        {
 
 
392
            x = ArcSin(sinx);
 
 
393
 
 
 
394
            if(cosx < 0)
 
 
395
            {
 
 
396
                x =  -x;
 
 
397
                x += deg180;
 
 
398
                x &= wrap360;
 
 
399
            }
 
 
400
        }
 
 
401
        else
 
 
402
        {
 
 
403
            x = ArcCos(cosx);
 
 
404
 
 
 
405
            if(sinx < 0)
 
 
406
            {
 
 
407
                x =  -x;
 
 
408
                x &= wrap360;            
 
 
409
            }
 
 
410
        }
 
 
411
 
 
 
412
        #if ( 0 == j_and_r_change )
 
 
413
        x = -x;
 
 
414
        x &= wrap360;
 
 
415
        #endif
 
 
416
 
 
 
417
        e->EulerX = x;
 
 
418
 
 
 
419
        /* Euler Y */
 
 
420
 
 
 
421
        if(abs_cosy > Cosine45)
 
 
422
        {
 
 
423
            x = ArcSin(siny);
 
 
424
 
 
 
425
            if(cosy < 0)
 
 
426
            {
 
 
427
                x =  -x;
 
 
428
                x += deg180;
 
 
429
                x &= wrap360;
 
 
430
            }
 
 
431
        }
 
 
432
        else 
 
 
433
        {
 
 
434
            x = ArcCos(cosy);
 
 
435
 
 
 
436
            if(siny < 0)
 
 
437
            {
 
 
438
                x =  -x;
 
 
439
                x &= wrap360;            
 
 
440
            }
 
 
441
        }
 
 
442
 
 
 
443
        #if ( 0 == j_and_r_change )
 
 
444
        x = -x;
 
 
445
        x &= wrap360;
 
 
446
        #endif
 
 
447
 
 
 
448
        e->EulerY = x;
 
 
449
 
 
 
450
        /* Euler Z */
 
 
451
 
 
 
452
        if(abs_cosz > Cosine45) 
 
 
453
        {
 
 
454
            x = ArcSin(sinz);
 
 
455
 
 
 
456
            if(cosz < 0) 
 
 
457
            {
 
 
458
                x =  -x;
 
 
459
                x += deg180;
 
 
460
                x &= wrap360;
 
 
461
            }
 
 
462
        }
 
 
463
        else 
 
 
464
        {
 
 
465
            x = ArcCos(cosz);
 
 
466
 
 
 
467
            if(sinz < 0)
 
 
468
            {
 
 
469
                x =  -x;
 
 
470
                x &= wrap360;            
 
 
471
            }
 
 
472
        }
 
 
473
 
 
 
474
        #if ( 0 == j_and_r_change )
 
 
475
        x =  -x;
 
 
476
        x &= wrap360;
 
 
477
        #endif
 
 
478
 
 
 
479
        e->EulerZ = x;
 
 
480
    }
 
 
481
    else //singularity case
 
 
482
    {
 
 
483
        e->EulerX = (m->mat32 > 0) ? 3072 : 1024;
 
 
484
        e->EulerZ = 0;
 
 
485
 
 
 
486
        /* Yaw */
 
 
487
 
 
 
488
        siny = -m->mat13 ;
 
 
489
        cosy =     m->mat11 ;
 
 
490
 
 
 
491
        abs_cosy = abs(cosy);
 
 
492
 
 
 
493
        if(abs_cosy > Cosine45) 
 
 
494
        {
 
 
495
            x = ArcSin(siny);
 
 
496
 
 
 
497
            if(cosy < 0) 
 
 
498
            {
 
 
499
                x =  -x;
 
 
500
                x += deg180;
 
 
501
                x &= wrap360;
 
 
502
            }
 
 
503
        }
 
 
504
        else
 
 
505
        {
 
 
506
            x = ArcCos(cosy);
 
 
507
 
 
 
508
            if(siny < 0) 
 
 
509
            {
 
 
510
                x =  -x;
 
 
511
                x &= wrap360;            
 
 
512
            }
 
 
513
        }
 
 
514
 
 
 
515
        #if ( 0 == j_and_r_change )
 
 
516
        x = -x;
 
 
517
        x &= wrap360;
 
 
518
        #endif
 
 
519
 
 
 
520
        e->EulerY = x;
 
 
521
    }
 
 
522
}
 
 
523
 
 
 
524
/*
 
 
525
 Normalise a Matrix
 
 
526
 
 
 
527
 Dot the three vectors together (XY, XZ, YZ) and take the two nearest to
 
 
528
 90Å™ from each other. Cross them to create a new third vector, then cross
 
 
529
 the first and third to create a new second.
 
 
530
*/
 
 
531
 
 
 
532
void MNormalise(MATRIXCH *m)
 
 
533
{
 
 
534
    VECTORCH *x = (VECTORCH *) &m->mat11;
 
 
535
    VECTORCH *y = (VECTORCH *) &m->mat21;
 
 
536
    VECTORCH *z = (VECTORCH *) &m->mat31;
 
 
537
    int dotxy = DotProduct(x, y);
 
 
538
    int dotxz = DotProduct(x, z);
 
 
539
    int dotyz = DotProduct(y, z);
 
 
540
    VECTORCH *s;
 
 
541
    VECTORCH *t;
 
 
542
    VECTORCH u;
 
 
543
    VECTORCH v;
 
 
544
    VECTORCH zero = {0, 0, 0};
 
 
545
 
 
 
546
    /* Find the two vectors nearest 90Å™ */
 
 
547
 
 
 
548
    if(dotxy > dotxz && dotxy > dotyz) 
 
 
549
    {
 
 
550
        /* xy are the closest to 90Å™ */
 
 
551
 
 
 
552
        /*printf("xy\n");*/
 
 
553
 
 
 
554
        s = x;
 
 
555
        t = y;
 
 
556
 
 
 
557
        MakeNormal(&zero, s, t, &u);        /* Cross them for a new 3rd vector */
 
 
558
 
 
 
559
        MakeNormal(&zero, s, &u, &v);        /* Cross 1st & 3rd for a new 2nd */
 
 
560
        v.vx = -v.vx;
 
 
561
        v.vy = -v.vy;
 
 
562
        v.vz = -v.vz;
 
 
563
 
 
 
564
        *z = u;
 
 
565
        *y = v;
 
 
566
    }
 
 
567
    else if(dotxz > dotxy && dotxz > dotyz) 
 
 
568
    {
 
 
569
        /* xz are the closest to 90Å™ */
 
 
570
 
 
 
571
        /*printf("xz\n");*/
 
 
572
 
 
 
573
        s = x;
 
 
574
        t = z;
 
 
575
 
 
 
576
        MakeNormal(&zero, s, t, &u);        /* Cross them for a new 3rd vector */
 
 
577
        u.vx = -u.vx;
 
 
578
        u.vy = -u.vy;
 
 
579
        u.vz = -u.vz;
 
 
580
 
 
 
581
        MakeNormal(&zero, s, &u, &v);        /* Cross 1st & 3rd for a new 2nd */
 
 
582
 
 
 
583
        *y = u;
 
 
584
        *z = v;
 
 
585
    }
 
 
586
    else
 
 
587
    {
 
 
588
        /* yz are the closest to 90Å™ */
 
 
589
 
 
 
590
        /*printf("yz\n");*/
 
 
591
 
 
 
592
        s = y;
 
 
593
        t = z;
 
 
594
 
 
 
595
        MakeNormal(&zero, s, t, &u);        /* Cross them for a new 3rd vector */
 
 
596
 
 
 
597
        MakeNormal(&zero, s, &u, &v);        /* Cross 1st & 3rd for a new 2nd */
 
 
598
        v.vx = -v.vx;
 
 
599
        v.vy = -v.vy;
 
 
600
        v.vz = -v.vz;
 
 
601
 
 
 
602
        *x = u;
 
 
603
        *z = v;
 
 
604
    }
 
 
605
}
 
 
606
 
 
 
607
/*
 
 
608
 
 
 
609
 ArcCos
 
 
610
 
 
 
611
 In:  COS value as -65,536 -> +65,536.
 
 
612
 Out: Angle in 0 -> 4095 form.
 
 
613
 
 
 
614
 Notes:
 
 
615
 
 
 
616
 The angle returned is in the range 0 -> 2,047 since the sign of SIN
 
 
617
 is not known.
 
 
618
 
 
 
619
 ArcSin(x) = ArcTan ( x, sqr ( 1-x*x ) )
 
 
620
 ArcCos(x) = ArcTan ( sqr ( 1-x*x ), x)
 
 
621
 
 
 
622
 -65,536 = 180 Degrees
 
 
623
 0      = 90 Degrees
 
 
624
 +65,536 = 0 Degrees
 
 
625
 
 
 
626
 The table has 4,096 entries.
 
 
627
 
 
 
628
*/
 
 
629
 
 
 
630
int ArcCos(int c)
 
 
631
{
 
 
632
    if(c < (-(ONE_FIXED - 1)))
 
 
633
        c = -(ONE_FIXED - 1);
 
 
634
    else if(c > (ONE_FIXED - 1))
 
 
635
        c = ONE_FIXED - 1;
 
 
636
 
 
 
637
    int16_t acos = ArcCosTable[(c >> 5) + 2048];
 
 
638
 
 
 
639
return (acos & wrap360);
 
 
640
}
 
 
641
 
 
 
642
/*
 
 
643
 
 
 
644
 ArcSin
 
 
645
 
 
 
646
 In:  SIN value in ax as -65,536 -> +65,536.
 
 
647
 Out: Angle in 0 -> 4095 form in ax.
 
 
648
 
 
 
649
 Notes:
 
 
650
 
 
 
651
 The angle returned is in the range -1,024 -> 1,023 since the sign of COS
 
 
652
 is not known.
 
 
653
 
 
 
654
 ArcSin(x) = ArcTan ( x, sqr ( 1-x*x ) )
 
 
655
 ArcCos(x) = ArcTan ( sqr ( 1-x*x ), x)
 
 
656
 
 
 
657
 -65,536 = 270 Degrees
 
 
658
 0      = 0 Degrees
 
 
659
 +65,536 = 90 Degrees
 
 
660
 
 
 
661
 The table has 4,096 entries.
 
 
662
 
 
 
663
*/
 
 
664
 
 
 
665
int ArcSin(int s)
 
 
666
{
 
 
667
    if(s < (-(ONE_FIXED - 1)))
 
 
668
        s = -(ONE_FIXED - 1);
 
 
669
    else if(s > (ONE_FIXED - 1))
 
 
670
        s = ONE_FIXED - 1;
 
 
671
 
 
 
672
    int16_t asin = ArcSineTable[(s >> 5) + 2048];
 
 
673
 
 
 
674
return (asin & wrap360);
 
 
675
}
 
 
676
 
 
 
677
 
 
 
678
/*
 
 
679
 
 
 
680
 ArcTan
 
 
681
 
 
 
682
 Pass (x,z)
 
 
683
 
 
 
684
 And ATN(x/z) is returned such that:
 
 
685
 
 
 
686
 000Å™ is Map North
 
 
687
 090Å™ is Map East
 
 
688
 180Å™ is Map South
 
 
689
 270Å™ is Map West
 
 
690
 
 
 
691
*/
 
 
692
 
 
 
693
int ArcTan(int height_x, int width_z)
 
 
694
{
 
 
695
    int abs_height_x, abs_width_z, angle, signsame = 0;
 
 
696
 
 
 
697
    int sign = 0;
 
 
698
 
 
 
699
    if((height_x < 0 && width_z < 0) || (height_x >=0 && width_z >= 0))
 
 
700
        signsame = 1;
 
 
701
 
 
 
702
    abs_height_x = abs(height_x);
 
 
703
    abs_width_z = abs(width_z);
 
 
704
 
 
 
705
    if(!width_z)
 
 
706
        angle = -deg90;
 
 
707
    else if(abs_width_z == abs_height_x)
 
 
708
        angle = deg45;
 
 
709
    else 
 
 
710
    {
 
 
711
        if(abs_width_z > abs_height_x)
 
 
712
        {
 
 
713
            int temp = abs_width_z;
 
 
714
            abs_width_z = abs_height_x;
 
 
715
            abs_height_x = temp;
 
 
716
            sign = -1;
 
 
717
        }
 
 
718
 
 
 
719
        if(abs_height_x != 0)
 
 
720
            angle = (abs_width_z << 8)/ abs_height_x;
 
 
721
        else
 
 
722
            angle = deg22pt5;
 
 
723
 
 
 
724
        angle = ArcTanTable[angle];
 
 
725
 
 
 
726
        if(sign >= 0) 
 
 
727
        {
 
 
728
            angle = -angle;
 
 
729
            angle += deg90;
 
 
730
        }
 
 
731
    }
 
 
732
 
 
 
733
    if(!signsame)
 
 
734
        angle = -angle;
 
 
735
 
 
 
736
    if(width_z <= 0)
 
 
737
        angle += deg180;
 
 
738
 
 
 
739
    angle &= wrap360;
 
 
740
 
 
 
741
return angle;
 
 
742
}
 
 
743
 
 
 
744
static int CMP_LL(int64_t *a, int64_t *b)
 
 
745
{
 
 
746
    return (a < b) ? -1 : (a > b);
 
 
747
}
 
 
748
 
 
 
749
/* 
 
 
750
 
 
 
751
"Yes" if "point" is inside "polygon"
 
 
752
 
 
 
753
 **************************************************
 
 
754
 
 
 
755
 WARNING!! Point and Polygon Data are OVERWRITTEN!!
 
 
756
 
 
 
757
 **************************************************
 
 
758
 
 
 
759
 The function requires point to be an integer array containing a single
 
 
760
 XY pair. The number of points must be passed too.
 
 
761
 
 
 
762
 Pass the size of the polygon point e.g. A Gouraud polygon has points X,Y,I
 
 
763
 so its point size would be 3.
 
 
764
 
 
 
765
 
 
 
766
 Item                                Polygon Point Size
 
 
767
 ----                                ------------------
 
 
768
 
 
 
769
 I_Polygon            2
 
 
770
 I_GouraudPolygon        3
 
 
771
 I_2dTexturedPolygon        4
 
 
772
 I_3dTexturedPolygon,        5
 
 
773
 I_Gouraud2dTexturedPolygon    5
 
 
774
 I_Polygon_ZBuffer        3
 
 
775
 I_GouraudPolygon_ZBuffer    4
 
 
776
 
 
 
777
 
 
 
778
 PASS ONLY POSITIVE COORDINATES!
 
 
779
 
 
 
780
*/
 
 
781
 
 
 
782
int PointInPolygon(int* point, int* polygon, int c, int ppsize)
 
 
783
{
 
 
784
  /* Tim's New Point In Polygon test-- hopefully much faster, */
 
 
785
  /* certainly much smaller. */
 
 
786
  /* Uses Half-Line test for point-in-2D-polygon test */
 
 
787
  /* Tests the half-line going from the point in the direction of positive z */
 
 
788
 
 
 
789
  int  x, z;        /* point */
 
 
790
  int  sx, sz;      /* vertex 1 */
 
 
791
  int *polyp;       /* vertex 2 pointer */
 
 
792
  int  t;
 
 
793
  int  dx = 0;      /* ABS(vertex 2 - vertex 1) */
 
 
794
  int  sgnx;        /* going left or going right */
 
 
795
  int  intersects = 0;  /* number of intersections so far discovered */
 
 
796
 
 
 
797
  /* reject lines and points */
 
 
798
  if (c < 3) 
 
 
799
    return 0;
 
 
800
 
 
 
801
  x = point[ix];
 
 
802
  z = point[iy];  /* ! */
 
 
803
 
 
 
804
  /* get last point */
 
 
805
  polyp = polygon + ((c - 1) * ppsize);
 
 
806
  sx = polyp[0];
 
 
807
  sz = polyp[1];
 
 
808
 
 
 
809
  /* go back to first point */
 
 
810
  polyp = polygon;
 
 
811
 
 
 
812
  /* for each point */
 
 
813
  while (0 != c)
 
 
814
  {
 
 
815
 
 
 
816
    /* is this line straddling the x co-ordinate of the point? */
 
 
817
    /* if not it is not worth testing for intersection with the half-line */
 
 
818
    /* we must be careful to get the strict and non-stict inequalities */
 
 
819
    /* correct, or we may count intersections with vertices the wrong number */
 
 
820
    /* of times. */
 
 
821
    sgnx = 0;
 
 
822
 
 
 
823
    if (sx < x && x <= polyp[0])
 
 
824
    {
 
 
825
      /* going right */
 
 
826
      sgnx = 1;
 
 
827
      dx = polyp[0] - sx;
 
 
828
    }
 
 
829
 
 
 
830
    if (polyp[0] < x && x <= sx)
 
 
831
    {
 
 
832
      /* going left */
 
 
833
      sgnx = -1;
 
 
834
      dx   = sx - polyp[0];
 
 
835
    }
 
 
836
 
 
 
837
    /* if sgnx is zero then neither of the above conditions are true, */
 
 
838
    /* hence the line does not straddle the point in x */
 
 
839
 
 
 
840
    if (0 != sgnx)
 
 
841
    {
 
 
842
      /* next do trivial cases of line totally above or below point */
 
 
843
      if (z < sz && z < polyp[1])
 
 
844
      {
 
 
845
        /* line totally above point -- intersection */
 
 
846
        intersects++;
 
 
847
      }
 
 
848
      else if (z <= sz || z <= polyp[1])
 
 
849
      {
 
 
850
        /* line straddles point in both x and z -- we must do interpolation */
 
 
851
 
 
 
852
        /* get absolute differences between line end z co-ordinates */
 
 
853
        int dz = (sz < polyp[1]) ? (polyp[1] - sz) : (sz - polyp[1]);
 
 
854
 
 
 
855
        /* B504 is the square root of 7FFFFFFF */
 
 
856
        if (0xB504L < dx || 0xB504L < dz)
 
 
857
        { 
 
 
858
          /* LARGE line -- use 64-bit values */
 
 
859
          /* interpolate z */
 
 
860
 
 
 
861
    int64_t a_ll = (polyp[1] - sz) * (x - sx);
 
 
862
    int64_t b_ll = (polyp[0] - sx) * (z - sz);
 
 
863
 
 
 
864
          if(CMP_LL(&a_ll, &b_ll) == sgnx)
 
 
865
        intersects++;
 
 
866
        }
 
 
867
        else
 
 
868
        {
 
 
869
          /* small line -- use 32-bit values */
 
 
870
          /* interpolate z */
 
 
871
 
 
 
872
          t = (polyp[1] - sz) * (x - sx) - (polyp[0] - sx) * (z - sz);
 
 
873
 
 
 
874
          if ((t < 0 && sgnx < 0) || (0 < t && 0 < sgnx))
 
 
875
            intersects++;
 
 
876
 
 
 
877
        }
 
 
878
      } /* (if line straddles point in z) */
 
 
879
    } /* (if line straddles point in x) */
 
 
880
 
 
 
881
    /* get next line : */
 
 
882
    /* new vertex 1 is old vertex 2 */
 
 
883
    sx = polyp[0];
 
 
884
    sz = polyp[1];
 
 
885
 
 
 
886
    /* new vertex 2 is next point */
 
 
887
    polyp += ppsize;
 
 
888
 
 
 
889
    /* next vertex */
 
 
890
  c--;
 
 
891
  }
 
 
892
 
 
 
893
// return 1, Odd number of intersections -- point is inside polygon
 
 
894
// return 0, even number of intersections -- point is outside polygon
 
 
895
return (intersects & 1);
 
 
896
}
 
 
897
 
 
 
898
/*
 
 
899
 #defines and statics required for Jamie's Most Excellent 
 
 
900
 random number generator
 
 
901
*/
 
 
902
 
 
 
903
#define DEG_3    31
 
 
904
#define SEP_3    3
 
 
905
 
 
 
906
static int32_t table [DEG_3] =
 
 
907
{
 
 
908
  -851904987, -43806228, -2029755270, 1390239686, -1912102820,
 
 
909
  -485608943, 1969813258, -1590463333, -1944053249, 455935928,
 
 
910
  508023712, -1714531963, 1800685987, -2015299881, 654595283,
 
 
911
  -1149023258, -1470005550, -1143256056, -1325577603, -1568001885,
 
 
912
  1275120390, -607508183, -205999574, -1696891592, 1492211999,
 
 
913
  -1528267240, -952028296, -189082757, 362343714, 1424981831,
 
 
914
  2039449641
 
 
915
};
 
 
916
 
 
 
917
#define TABLE_END (table + sizeof (table) / sizeof (table [0]))
 
 
918
 
 
 
919
static int32_t * front_ptr = table + SEP_3;
 
 
920
static int32_t * rear_ptr = table;
 
 
921
 
 
 
922
#define SEEDED_DEG_3    13
 
 
923
#define SEEDED_SEP_3    3
 
 
924
static int32_t seeded_table [SEEDED_DEG_3];
 
 
925
static int32_t * seeded_front_ptr = seeded_table + SEEDED_SEP_3;
 
 
926
static int32_t * seeded_rear_ptr = seeded_table;
 
 
927
 
 
 
928
/*a second copy of the random number generator for getting random numbers from a single seed*/
 
 
929
 
 
 
930
#define SEEDED_TABLE_END (seeded_table + sizeof (seeded_table) / sizeof (seeded_table [0]))
 
 
931
 
 
 
932
int SeededFastRandom()
 
 
933
{
 
 
934
    /*
 
 
935
    Discard least random bit.
 
 
936
    Shift as unsigned to avoid replicating sign bit.
 
 
937
    Faster than masking.
 
 
938
    */
 
 
939
 
 
 
940
    *seeded_front_ptr += *seeded_rear_ptr;
 
 
941
    int32_t i  = (int32_t) ((uint32_t) *seeded_front_ptr >> 1);
 
 
942
 
 
 
943
    /* `front_ptr' and `rear_ptr' can't wrap at the same time. */
 
 
944
 
 
 
945
    ++seeded_front_ptr;
 
 
946
 
 
 
947
    if(seeded_front_ptr < SEEDED_TABLE_END) 
 
 
948
    {
 
 
949
        ++seeded_rear_ptr;
 
 
950
 
 
 
951
        if (seeded_rear_ptr < SEEDED_TABLE_END) 
 
 
952
            return i;
 
 
953
 
 
 
954
        seeded_rear_ptr = seeded_table;
 
 
955
    }
 
 
956
    else
 
 
957
    {    
 
 
958
        /* front_ptr >= TABLE_END */
 
 
959
 
 
 
960
        seeded_front_ptr = seeded_table;
 
 
961
        ++seeded_rear_ptr;
 
 
962
    }
 
 
963
 
 
 
964
return i;
 
 
965
}
 
 
966
 
 
 
967
void SetSeededFastRandom(int seed)
 
 
968
{
 
 
969
    int i = 0;
 
 
970
    int32_t number = seed;
 
 
971
 
 
 
972
    for(; i < SEEDED_DEG_3; ++i) 
 
 
973
    {
 
 
974
        number   = 1103515145 * number + 12345;
 
 
975
        seeded_table[i] = number;
 
 
976
    }
 
 
977
 
 
 
978
    seeded_front_ptr = seeded_table + SEEDED_SEP_3;
 
 
979
    seeded_rear_ptr  = seeded_table;
 
 
980
 
 
 
981
    for(i = 0; i < 2 * SEEDED_DEG_3; ++i)
 
 
982
        SeededFastRandom ();
 
 
983
}
 
 
984
 
 
 
985
static struct timeval starttime;
 
 
986
 
 
 
987
void InitTimer()
 
 
988
{
 
 
989
    gettimeofday(&starttime, NULL);
 
 
990
}
 
 
991
 
 
 
992
/* time in miliseconds */
 
 
993
unsigned int timeGetTime()
 
 
994
{
 
 
995
    static struct timeval tv1;
 
 
996
 
 
 
997
    gettimeofday(&tv1, NULL);
 
 
998
 
 
 
999
    int secs = tv1.tv_sec - starttime.tv_sec;
 
 
1000
    int usecs = tv1.tv_usec - starttime.tv_usec;
 
 
1001
 
 
 
1002
    if (usecs < 0) 
 
 
1003
    {
 
 
1004
        usecs += 1000000;
 
 
1005
        secs--;
 
 
1006
    }
 
 
1007
 
 
 
1008
return secs * 1000 + (usecs / 1000);
 
 
1009
}
 
 
1010
 
 
 
1011
void SetFastRandom()
 
 
1012
{
 
 
1013
    int i = 0;
 
 
1014
    unsigned int number = timeGetTime();
 
 
1015
 
 
 
1016
    for(; i < DEG_3; ++i) 
 
 
1017
    {
 
 
1018
        number   = 1103515145 * number + 12345;
 
 
1019
        table[i] = number;
 
 
1020
    }
 
 
1021
 
 
 
1022
    front_ptr = table + SEP_3;
 
 
1023
    rear_ptr  = table;
 
 
1024
 
 
 
1025
    for(i = 0; i < 10 * DEG_3; ++i)
 
 
1026
        FastRandom();
 
 
1027
 
 
 
1028
    SetSeededFastRandom(FastRandom());
 
 
1029
}
 
 
1030
 
 
 
1031
int FastRandom()
 
 
1032
{
 
 
1033
    /*
 
 
1034
    Discard least random bit.
 
 
1035
    Shift as unsigned to avoid replicating sign bit.
 
 
1036
    Faster than masking.
 
 
1037
    */
 
 
1038
 
 
 
1039
    *front_ptr += *rear_ptr;
 
 
1040
    int32_t i = (int32_t) ((uint32_t) *front_ptr >> 1);
 
 
1041
 
 
 
1042
    /* `front_ptr' and `rear_ptr' can't wrap at the same time. */
 
 
1043
 
 
 
1044
    ++front_ptr;
 
 
1045
 
 
 
1046
    if(front_ptr < TABLE_END) 
 
 
1047
    {
 
 
1048
        ++rear_ptr;
 
 
1049
 
 
 
1050
        if (rear_ptr < TABLE_END)
 
 
1051
            return i;
 
 
1052
 
 
 
1053
        rear_ptr = table;
 
 
1054
    }
 
 
1055
    else
 
 
1056
    {
 
 
1057
        /* front_ptr >= TABLE_END */
 
 
1058
        front_ptr = table;
 
 
1059
        ++rear_ptr;
 
 
1060
    }
 
 
1061
 
 
 
1062
return i;
 
 
1063
}
 
 
1064
 
 
 
1065
int MagnitudeOfCrossProduct(const VECTORCH *a, const VECTORCH *b)
 
 
1066
{
 
 
1067
    float x = MUL_FIXED(a->vy, b->vz) - MUL_FIXED(a->vz, b->vy);
 
 
1068
    float y = MUL_FIXED(a->vz, b->vx) - MUL_FIXED(a->vx, b->vz);
 
 
1069
    float z = MUL_FIXED(a->vx, b->vy) - MUL_FIXED(a->vy, b->vx);
 
 
1070
 
 
 
1071
    return sqrt((x * x) + (y * y) + (z * z));
 
 
1072
}
 
 
1073
 
 
 
1074
void CrossProduct(const VECTORCH *a, const VECTORCH *b, VECTORCH *c)
 
 
1075
{
 
 
1076
    c->vx = MUL_FIXED(a->vy, b->vz) - MUL_FIXED(a->vz, b->vy);
 
 
1077
    c->vy = MUL_FIXED(a->vz, b->vx) - MUL_FIXED(a->vx, b->vz);
 
 
1078
    c->vz = MUL_FIXED(a->vx, b->vy) - MUL_FIXED(a->vy, b->vx);
 
 
1079
}
 
 
1080
 
 
 
1081
/*
 
 
1082
KJL 12:01:08 7/16/97 - returns the magnitude of a vector - max error about 13%, though average error
 
 
1083
less than half this. Very fast compared to other approaches.
 
 
1084
*/
 
 
1085
 
 
 
1086
int Approximate3dMagnitude(const VECTORCH *v)
 
 
1087
{
 
 
1088
    int dx = abs(v->vx);
 
 
1089
    int dy = abs(v->vy);
 
 
1090
    int dz = abs(v->vz);
 
 
1091
 
 
 
1092
    if (dx > dy)
 
 
1093
    {
 
 
1094
        if (dx > dz)
 
 
1095
            return dx + ((dy + dz) >> 2);
 
 
1096
        else
 
 
1097
            return dz + ((dy + dx) >> 2);
 
 
1098
    }
 
 
1099
    else
 
 
1100
    {
 
 
1101
        if (dy > dz)
 
 
1102
            return dy + ((dx + dz) >> 2);
 
 
1103
        else
 
 
1104
            return dz + ((dx + dy) >> 2);
 
 
1105
    }
 
 
1106
}
 
 
1107
 
 
 
1108
/*
 
 
1109
 
 
 
1110
 Quaternion to Matrix
 
 
1111
 
 
 
1112
 This is the column(row) matrix that is produced. Our matrices are
 
 
1113
 row(column) and so are a transpose of this.
 
 
1114
 
 
 
1115
   1 - 2yy - 2zz           2xy + 2wz             2xz - 2wy
 
 
1116
 
 
 
1117
   2xy - 2wz               1 - 2xx - 2zz         2yz + 2wx
 
 
1118
 
 
 
1119
   2xz + 2wy               2yz - 2wx             1 - 2xx - 2yy
 
 
1120
 
 
 
1121
*/
 
 
1122
 
 
 
1123
void QuatToMat(QUAT *q,MATRIXCH *m)
 
 
1124
{
 
 
1125
/*
 
 
1126
 The most efficient way to create the matrix is as follows 1 / Double x, y & z
 
 
1127
*/
 
 
1128
    int q_w = q->quatw;
 
 
1129
    int q_x = q->quatx;
 
 
1130
    int q_y = q->quaty;
 
 
1131
    int q_z = q->quatz;
 
 
1132
 
 
 
1133
    int q_2x = q_x * 2;
 
 
1134
    int q_2y = q_y * 2;
 
 
1135
    int q_2z = q_z * 2;
 
 
1136
 
 
 
1137
/*
 
 
1138
 2/ Form their products with w, x, y & z
 
 
1139
    These are
 
 
1140
 
 
 
1141
    (2x)w   (2y)w  (2z)w
 
 
1142
    (2x)x
 
 
1143
    (2x)y   (2y)y
 
 
1144
    (2x)z   (2y)z  (2z)z
 
 
1145
*/
 
 
1146
    int q_2xw = MUL_FIXED(q_2x, q_w);
 
 
1147
    int q_2yw = MUL_FIXED(q_2y, q_w);
 
 
1148
    int q_2zw = MUL_FIXED(q_2z, q_w);
 
 
1149
 
 
 
1150
    int q_2xx = MUL_FIXED(q_2x, q_x);
 
 
1151
 
 
 
1152
    int q_2xy = MUL_FIXED(q_2x, q_y);
 
 
1153
    int q_2yy = MUL_FIXED(q_2y, q_y);
 
 
1154
 
 
 
1155
    int q_2xz = MUL_FIXED(q_2x, q_z);
 
 
1156
    int q_2yz = MUL_FIXED(q_2y, q_z);
 
 
1157
    int q_2zz = MUL_FIXED(q_2z, q_z);
 
 
1158
 
 
 
1159
/* mat11 = 1 - 2y^2 - 2z^2     */
 
 
1160
 
 
 
1161
    m->mat11 = ONE_FIXED - q_2yy - q_2zz;
 
 
1162
 
 
 
1163
/* mat12 = 2xy - 2wz */
 
 
1164
 
 
 
1165
    m->mat12 = q_2xy - q_2zw;
 
 
1166
 
 
 
1167
/* mat13 = 2xz + 2wy */
 
 
1168
 
 
 
1169
    m->mat13 = q_2xz + q_2yw;
 
 
1170
 
 
 
1171
/* mat21 = 2xy + 2wz */
 
 
1172
 
 
 
1173
    m->mat21 = q_2xy + q_2zw;
 
 
1174
 
 
 
1175
/* mat22 = 1 - 2x^2 - 2z^2 */
 
 
1176
 
 
 
1177
    m->mat22 = ONE_FIXED - q_2xx - q_2zz;
 
 
1178
 
 
 
1179
/* mat23 = 2yz - 2wx     */
 
 
1180
 
 
 
1181
    m->mat23 = q_2yz - q_2xw;
 
 
1182
 
 
 
1183
/* mat31 = 2xz - 2wy */
 
 
1184
 
 
 
1185
    m->mat31 = q_2xz - q_2yw;
 
 
1186
 
 
 
1187
/* mat32 = 2yz + 2wx */
 
 
1188
 
 
 
1189
    m->mat32 = q_2yz + q_2xw;
 
 
1190
 
 
 
1191
/* mat33 = 1 - 2x^2 - 2y^2 */
 
 
1192
 
 
 
1193
    m->mat33 = ONE_FIXED - q_2xx - q_2yy;
 
 
1194
}
 
 
1195
 
 
 
1196
/*
 
 
1197
 Calculate Plane Normal from three POP's
 
 
1198
 
 
 
1199
 The three input vectors are treated as POP's and used to make two vectors.
 
 
1200
 These are then crossed to create the normal.
 
 
1201
 
 
 
1202
 Make two vectors; (2-1) & (3-1)
 
 
1203
 Cross them
 
 
1204
 Normalise the vector
 
 
1205
  Find the magnitude of the vector
 
 
1206
  Divide each component by the magnitude
 
 
1207
*/
 
 
1208
 
 
 
1209
void MakeNormal(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3, VECTORCH *v4)
 
 
1210
{
 
 
1211
    float vect0_x = v2->vx - v1->vx;
 
 
1212
    float vect0_y = v2->vy - v1->vy;
 
 
1213
    float vect0_z = v2->vz - v1->vz;
 
 
1214
 
 
 
1215
    float vect1_x = v3->vx - v1->vx;
 
 
1216
    float vect1_y = v3->vy - v1->vy;
 
 
1217
    float vect1_z = v3->vz - v1->vz;
 
 
1218
 
 
 
1219
    /* x = v0y.v1z - v0z.v1y */
 
 
1220
 
 
 
1221
    float x = (vect0_y * vect1_z) - (vect0_z * vect1_y);
 
 
1222
 
 
 
1223
    /* y = v0z.v1x - v0x.v1z */
 
 
1224
 
 
 
1225
    float y = (vect0_z * vect1_x) - (vect0_x * vect1_z);
 
 
1226
 
 
 
1227
    /* z = v0x.v1y - v0y.v1x */
 
 
1228
 
 
 
1229
    float z = (vect0_x * vect1_y) - (vect0_y * vect1_x);
 
 
1230
 
 
 
1231
    {
 
 
1232
        float m = sqrt((x * x) + (y * y) + (z * z));
 
 
1233
 
 
 
1234
        x /= m;
 
 
1235
        y /= m;
 
 
1236
        z /= m;
 
 
1237
    }
 
 
1238
 
 
 
1239
    v4->vx = (int)(x * ONE_FIXED);
 
 
1240
    v4->vy = (int)(y * ONE_FIXED);
 
 
1241
    v4->vz = (int)(z * ONE_FIXED);
 
 
1242
}
 
 
1243
 
 
 
1244
/*
 
 
1245
 
 
 
1246
 Normalise a vector.
 
 
1247
 
 
 
1248
 The returned vector is a fixed point unit vector.
 
 
1249
 
 
 
1250
 WARNING!
 
 
1251
 
 
 
1252
 The vector must be no larger than 2<<14 because of the square root.
 
 
1253
 Because this is an integer function, small components produce errors.
 
 
1254
 
 
 
1255
 e.g.
 
 
1256
 
 
 
1257
 (100,100,0)
 
 
1258
 
 
 
1259
 m=141 (141.42)
 
 
1260
 
 
 
1261
 nx = 100 * ONE_FIXED / m = 46,479
 
 
1262
 ny = 100 * ONE_FIXED / m = 46,479
 
 
1263
 nz = 0
 
 
1264
 
 
 
1265
 New m ought to be 65,536 but in fact is 65,731 i.e. 0.29% too large.
 
 
1266
 
 
 
1267
*/
 
 
1268
 
 
 
1269
void Normalise(VECTORCH *nvector)
 
 
1270
{
 
 
1271
    float x = nvector->vx;
 
 
1272
    float y = nvector->vy;
 
 
1273
    float z = nvector->vz;
 
 
1274
 
 
 
1275
    float m = 65536.0/sqrt((x * x) + (y * y) + (z * z));
 
 
1276
 
 
 
1277
    nvector->vx = (int)(x * m);
 
 
1278
    nvector->vy = (int)(y * m);
 
 
1279
    nvector->vz = (int)(z * m);
 
 
1280
}