4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "system.h"
 
 
2
#include "stratdef.h"
 
 
3
#include "bh_types.h"
 
 
4
#include "track.h"
 
 
5
#include "psndplat.h"
 
 
6
#include <math.h>
 
 
7
#include <assert.h>
 
 
8
 
 
 
9
extern void MulQuat(QUAT *q1, QUAT *q2, QUAT *output);
 
 
10
 
 
 
11
extern void QNormalise(QUAT*);
 
 
12
extern int QDot(QUAT *, QUAT *);
 
 
13
 
 
 
14
static void TrackSlerp(TRACK_SECTION_DATA* tsd,int lerp,MATRIXCH* output_mat)
 
 
15
{
 
 
16
    int sclp,sclq;
 
 
17
 
 
 
18
    QUAT* input1 = &tsd->quat_start;
 
 
19
    QUAT* input2 = &tsd->quat_end;
 
 
20
    QUAT output;
 
 
21
 
 
 
22
    if(lerp < 0)
 
 
23
        lerp=0;
 
 
24
    else if(lerp > 65536)
 
 
25
        lerp = 65536;
 
 
26
 
 
 
27
    /* First check for special case. */
 
 
28
 
 
 
29
    if (tsd->omega == 2048)
 
 
30
    {
 
 
31
        int t1,t2;
 
 
32
 
 
 
33
        output.quatx=-input1->quaty;
 
 
34
        output.quaty=input1->quatx;
 
 
35
        output.quatz=-input1->quatw;
 
 
36
        output.quatw=input1->quatz;
 
 
37
 
 
 
38
        t1 = MUL_FIXED((ONE_FIXED-lerp),1024);
 
 
39
        sclp = GetSin(t1);
 
 
40
 
 
 
41
        t2 = MUL_FIXED(lerp,1024);
 
 
42
        sclq = GetSin(t2);
 
 
43
 
 
 
44
        output.quatx = (MUL_FIXED(input1->quatx,sclp))+(MUL_FIXED(output.quatx,sclq));
 
 
45
        output.quaty = (MUL_FIXED(input1->quaty,sclp))+(MUL_FIXED(output.quaty,sclq));
 
 
46
        output.quatz = (MUL_FIXED(input1->quatz,sclp))+(MUL_FIXED(output.quatz,sclq));
 
 
47
        output.quatw = (MUL_FIXED(input1->quatw,sclp))+(MUL_FIXED(output.quatw,sclq));
 
 
48
 
 
 
49
    }
 
 
50
    else
 
 
51
    {
 
 
52
        if ( !tsd->omega && !tsd->oneoversinomega)
 
 
53
        {
 
 
54
            sclp = ONE_FIXED-lerp;
 
 
55
            sclq = lerp;
 
 
56
        }
 
 
57
        else
 
 
58
        {
 
 
59
            int t1,t2;
 
 
60
 
 
 
61
            t1 = MUL_FIXED((ONE_FIXED-lerp),tsd->omega);
 
 
62
            t2 = GetSin(t1);
 
 
63
            sclp = MUL_FIXED(t2,tsd->oneoversinomega);
 
 
64
 
 
 
65
            t1 = MUL_FIXED(lerp,tsd->omega);
 
 
66
            t2 = GetSin(t1);
 
 
67
            sclq = MUL_FIXED(t2,tsd->oneoversinomega);
 
 
68
 
 
 
69
        }
 
 
70
 
 
 
71
        output.quatx = (MUL_FIXED(input1->quatx,sclp))+(MUL_FIXED(input2->quatx,sclq));
 
 
72
        output.quaty = (MUL_FIXED(input1->quaty,sclp))+(MUL_FIXED(input2->quaty,sclq));
 
 
73
        output.quatz = (MUL_FIXED(input1->quatz,sclp))+(MUL_FIXED(input2->quatz,sclq));
 
 
74
        output.quatw = (MUL_FIXED(input1->quatw,sclp))+(MUL_FIXED(input2->quatw,sclq));
 
 
75
    }
 
 
76
 
 
 
77
    QNormalise(&output);
 
 
78
    QuatToMat(&output,output_mat);
 
 
79
}
 
 
80
 
 
 
81
void Start_Track_Sound(TRACK_SOUND* ts, VECTORCH * location)
 
 
82
{
 
 
83
    SOUND3DDATA s3d;
 
 
84
 
 
 
85
    assert(ts);
 
 
86
 
 
 
87
    ts->playing = 1;
 
 
88
 
 
 
89
    if((ts->activ_no != SOUND_NOACTIVEINDEX) || (SID_NOSOUND == ts->sound_number))
 
 
90
        return;
 
 
91
 
 
 
92
    if(ts->loop)
 
 
93
    {
 
 
94
        //make sure track is close enough to be heard
 
 
95
        int dist = VectorDistance(&PlayerStatus.DisplayBlock->ObWorld, location);
 
 
96
 
 
 
97
        if(dist > ts->outer_range)
 
 
98
            return;
 
 
99
    }
 
 
100
 
 
 
101
    s3d.position = *location;
 
 
102
    s3d.inner_range = ts->inner_range;
 
 
103
    s3d.outer_range = ts->outer_range;
 
 
104
    s3d.velocity.vx = 0;
 
 
105
    s3d.velocity.vy = 0;
 
 
106
    s3d.velocity.vz = 0;
 
 
107
 
 
 
108
    Sound_Play ((SOUNDINDEX)ts->sound_number, (ts->loop ? "nvpel" : "nvpe"), &s3d, ts->max_volume, ts->pitch,
&ts->activ_no);
 
 
109
    //printf("Playing track sound \t%s\n", GameSounds[ts->sound_number].wavName);
 
 
110
}
 
 
111
 
 
 
112
void Stop_Track_Sound(TRACK_SOUND* ts)
 
 
113
{
 
 
114
    assert(ts);
 
 
115
 
 
 
116
    ts->playing = 0;
 
 
117
 
 
 
118
    if(ts->activ_no != SOUND_NOACTIVEINDEX)
 
 
119
        Sound_Stop(ts->activ_no);
 
 
120
}
 
 
121
 
 
 
122
void Update_Track_Sound(TRACK_SOUND* ts, VECTORCH * location)
 
 
123
{
 
 
124
    assert(ts);
 
 
125
 
 
 
126
    if(ts->playing)
 
 
127
    {
 
 
128
        if(ts->loop)
 
 
129
        {
 
 
130
            //check to see if sound is close enough to player
 
 
131
            int dist = VectorDistance(&PlayerStatus.DisplayBlock->ObWorld, location);
 
 
132
 
 
 
133
            if(dist > ts->outer_range)
 
 
134
            {
 
 
135
                //stop playing the sound for the moment
 
 
136
                if(ts->activ_no != SOUND_NOACTIVEINDEX)
 
 
137
                    Sound_Stop(ts->activ_no);
 
 
138
            }
 
 
139
            else
 
 
140
            {
 
 
141
                if(ts->activ_no == SOUND_NOACTIVEINDEX)
 
 
142
                {
 
 
143
                    //restart the sound
 
 
144
                    Start_Track_Sound(ts,location);
 
 
145
                }
 
 
146
                else
 
 
147
                {
 
 
148
                    //update the sound's location
 
 
149
                    SOUND3DDATA s3d;
 
 
150
                    s3d.position = *location;
 
 
151
                    s3d.inner_range = ts->inner_range;
 
 
152
                    s3d.outer_range = ts->outer_range;
 
 
153
                    s3d.velocity.vx = 0;
 
 
154
                    s3d.velocity.vy = 0;
 
 
155
                    s3d.velocity.vz = 0;
 
 
156
 
 
 
157
                    Sound_UpdateNew3d (ts->activ_no, &s3d);
 
 
158
                }
 
 
159
            }
 
 
160
        }
 
 
161
        else
 
 
162
        {
 
 
163
            if(ts->activ_no == SOUND_NOACTIVEINDEX)
 
 
164
            {
 
 
165
                //sound has stopped playing.
 
 
166
                ts->playing = 0;
 
 
167
            }
 
 
168
        }
 
 
169
    }
 
 
170
}
 
 
171
 
 
 
172
static void SmoothTrackPosition(TRACK_SECTION_DATA* trackPtr, int u, VECTORCH *outputPositionPtr)
 
 
173
{
 
 
174
    int u2 = MUL_FIXED(u, u);
 
 
175
    int u3 = MUL_FIXED(u2, u);
 
 
176
 
 
 
177
     {
 
 
178
        int a = (-trackPtr->pivot_0.vx+3*trackPtr->pivot_1.vx-3*trackPtr->pivot_2.vx+trackPtr->pivot_3.vx);
 
 
179
        int b = (2*trackPtr->pivot_0.vx-5*trackPtr->pivot_1.vx+4*trackPtr->pivot_2.vx-trackPtr->pivot_3.vx);
 
 
180
        int c = (-1*trackPtr->pivot_0.vx+trackPtr->pivot_2.vx);
 
 
181
        outputPositionPtr->vx = (MUL_FIXED(a,u3)+MUL_FIXED(b,u2)+MUL_FIXED(c,u))/2+trackPtr->pivot_1.vx;
 
 
182
    }
 
 
183
     {
 
 
184
        int a = (-trackPtr->pivot_0.vy+3*trackPtr->pivot_1.vy-3*trackPtr->pivot_2.vy+trackPtr->pivot_3.vy);
 
 
185
        int b = (2*trackPtr->pivot_0.vy-5*trackPtr->pivot_1.vy+4*trackPtr->pivot_2.vy-trackPtr->pivot_3.vy);
 
 
186
        int c = (-1*trackPtr->pivot_0.vy+trackPtr->pivot_2.vy);
 
 
187
        outputPositionPtr->vy = (MUL_FIXED(a,u3)+MUL_FIXED(b,u2)+MUL_FIXED(c,u))/2+trackPtr->pivot_1.vy;
 
 
188
    }
 
 
189
     {
 
 
190
        int a = (-trackPtr->pivot_0.vz+3*trackPtr->pivot_1.vz-3*trackPtr->pivot_2.vz+trackPtr->pivot_3.vz);
 
 
191
        int b = (2*trackPtr->pivot_0.vz-5*trackPtr->pivot_1.vz+4*trackPtr->pivot_2.vz-trackPtr->pivot_3.vz);
 
 
192
        int c = (-1*trackPtr->pivot_0.vz+trackPtr->pivot_2.vz);
 
 
193
        outputPositionPtr->vz = (MUL_FIXED(a,u3)+MUL_FIXED(b,u2)+MUL_FIXED(c,u))/2+trackPtr->pivot_1.vz;
 
 
194
    }
 
 
195
}
 
 
196
 
 
 
197
static void BasicSlerp(QUAT *input1,QUAT *input2,QUAT *output,int lerp)
 
 
198
{
 
 
199
    int sclp,sclq;
 
 
200
    int omega, sinom;
 
 
201
    int cosom = QDot(input1, input2);
 
 
202
 
 
 
203
    if (cosom > 0)
 
 
204
    {
 
 
205
        *output = *input2;
 
 
206
    }
 
 
207
    else
 
 
208
    {
 
 
209
        output->quatx =- input2->quatx;
 
 
210
        output->quaty =- input2->quaty;
 
 
211
        output->quatz =- input2->quatz;
 
 
212
        output->quatw =- input2->quatw;
 
 
213
        cosom =- cosom;
 
 
214
    }
 
 
215
 
 
 
216
    if(cosom < 65500)
 
 
217
    {
 
 
218
        omega = ArcCos(cosom);
 
 
219
        sinom = GetSin(omega);
 
 
220
 
 
 
221
        /* healthy paranoia */
 
 
222
        assert(sinom != 0);
 
 
223
 
 
 
224
        sclp = DIV_FIXED ( GetSin ( MUL_FIXED((ONE_FIXED-lerp),omega) ), sinom );
 
 
225
        sclq = DIV_FIXED ( GetSin ( MUL_FIXED(lerp, omega) ), sinom );
 
 
226
    }
 
 
227
    else
 
 
228
    {
 
 
229
        sclp = ONE_FIXED-lerp;
 
 
230
        sclq = lerp;
 
 
231
    }
 
 
232
 
 
 
233
 
 
 
234
    output->quatx = (MUL_FIXED(input1->quatx,sclp))+(MUL_FIXED(output->quatx,sclq));
 
 
235
    output->quaty = (MUL_FIXED(input1->quaty,sclp))+(MUL_FIXED(output->quaty,sclq));
 
 
236
    output->quatz = (MUL_FIXED(input1->quatz,sclp))+(MUL_FIXED(output->quatz,sclq));
 
 
237
    output->quatw = (MUL_FIXED(input1->quatw,sclp))+(MUL_FIXED(output->quatw,sclq));
 
 
238
      QNormalise(output);
 
 
239
}
 
 
240
 
 
 
241
static void SmoothTrackOrientation(TRACK_SECTION_DATA* trackPtr, int lerp, MATRIXCH* outputMatrixPtr)
 
 
242
{
 
 
243
    QUAT q1,q2,q3;
 
 
244
 
 
 
245
    if(lerp < 0)
 
 
246
        lerp = 0;
 
 
247
    else if(lerp > 65536)
 
 
248
        lerp = 65536;
 
 
249
 
 
 
250
      BasicSlerp(&trackPtr->quat_start,&trackPtr->quat_end, &q1, lerp);
 
 
251
     BasicSlerp(&trackPtr->quat_start_control,&trackPtr->quat_end_control, &q2, lerp);
 
 
252
 
 
 
253
     lerp = MUL_FIXED(ONE_FIXED-lerp,2*lerp);
 
 
254
 
 
 
255
    if(lerp < 0)
 
 
256
        lerp = 0;
 
 
257
    else if(lerp > 65536)
 
 
258
        lerp = 65536;
 
 
259
 
 
 
260
      BasicSlerp(&q1, &q2, &q3, lerp);
 
 
261
 
 
 
262
    QuatToMat(&q3,outputMatrixPtr);
 
 
263
}
 
 
264
 
 
 
265
void Update_Track_Position_Only(TRACK_CONTROLLER* tc)
 
 
266
{
 
 
267
    assert(tc);
 
 
268
 
 
 
269
    assert(tc->sbptr);
 
 
270
    assert(tc->sections);
 
 
271
 
 
 
272
    DYNAMICSBLOCK* dynptr = tc->sbptr->DynPtr;
 
 
273
    assert(dynptr);
 
 
274
 
 
 
275
    TRACK_SECTION_DATA* cur_tsd = &tc->sections[tc->current_section];
 
 
276
 
 
 
277
    //adjust timer until time lies within a section
 
 
278
    while(tc->timer>cur_tsd->time_for_section || tc->timer < 0)
 
 
279
    {
 
 
280
        if(tc->timer>cur_tsd->time_for_section)
 
 
281
        {
 
 
282
            tc->timer -= cur_tsd->time_for_section;
 
 
283
 
 
 
284
            if(tc->current_section == (tc->num_sections-1) && !tc->loop)
 
 
285
            {
 
 
286
                if(tc->loop_backandforth)
 
 
287
                {
 
 
288
                    //turn around
 
 
289
                    tc->reverse = 1;
 
 
290
                    tc->timer = cur_tsd->time_for_section-tc->timer;
 
 
291
                }
 
 
292
                else
 
 
293
                {
 
 
294
                    //reached end of track
 
 
295
                    tc->timer = cur_tsd->time_for_section;
 
 
296
                    tc->playing = 0;
 
 
297
                    tc->reverse = 1; 
 
 
298
                }
 
 
299
            }
 
 
300
            else
 
 
301
            {
 
 
302
                tc->current_section++;
 
 
303
 
 
 
304
                if(tc->current_section == tc->num_sections)
 
 
305
                    tc->current_section=0;
 
 
306
 
 
 
307
                cur_tsd = &tc->sections[tc->current_section];
 
 
308
            }
 
 
309
 
 
 
310
        }
 
 
311
        else
 
 
312
        {
 
 
313
            if(!tc->current_section && !tc->loop)
 
 
314
            {
 
 
315
                if(tc->loop_backandforth)
 
 
316
                {
 
 
317
                    //turn around
 
 
318
                    tc->reverse = 0;
 
 
319
                    tc->timer = -tc->timer;
 
 
320
                }
 
 
321
                else
 
 
322
                {
 
 
323
                    //reached end of track
 
 
324
                      tc->timer = 0;
 
 
325
                      tc->playing = 0;
 
 
326
                      tc->reverse = 0; 
 
 
327
                }
 
 
328
 
 
 
329
            }
 
 
330
            else
 
 
331
            {
 
 
332
                tc->current_section--;
 
 
333
 
 
 
334
                if(tc->current_section < 0)
 
 
335
                    tc->current_section = tc->num_sections-1;
 
 
336
 
 
 
337
                cur_tsd = &tc->sections[tc->current_section];
 
 
338
                tc->timer += cur_tsd->time_for_section;
 
 
339
            }
 
 
340
 
 
 
341
        }
 
 
342
 
 
 
343
    }
 
 
344
 
 
 
345
    // now work out the object position at this time
 
 
346
 
 
 
347
    /* KJL 14:47:44 24/03/98 - check for smoothing; if you've
 
 
348
    less than 3 points then smoothing is a bit pointless */
 
 
349
    if (tc->use_smoothing && tc->num_sections >= 3)
 
 
350
    {
 
 
351
        int lerp = MUL_FIXED(tc->timer,cur_tsd->oneovertime);
 
 
352
        SmoothTrackOrientation(cur_tsd, lerp, &dynptr->OrientMat);
 
 
353
        SmoothTrackPosition(cur_tsd, lerp, &dynptr->Position);
 
 
354
    }
 
 
355
    else
 
 
356
    {
 
 
357
        if(tc->no_rotation)
 
 
358
        {
 
 
359
            int lerp = MUL_FIXED(tc->timer, cur_tsd->oneovertime);
 
 
360
            VECTORCH pivot_pos = cur_tsd->pivot_start;
 
 
361
 
 
 
362
            pivot_pos.vx += MUL_FIXED(cur_tsd->pivot_travel.vx, lerp);
 
 
363
            pivot_pos.vy += MUL_FIXED(cur_tsd->pivot_travel.vy, lerp);
 
 
364
            pivot_pos.vz += MUL_FIXED(cur_tsd->pivot_travel.vz, lerp);
 
 
365
 
 
 
366
            dynptr->Position = pivot_pos;
 
 
367
        }
 
 
368
        else
 
 
369
        {
 
 
370
            int lerp = MUL_FIXED(tc->timer,cur_tsd->oneovertime);
 
 
371
            MATRIXCH orient;
 
 
372
            VECTORCH pivot_pos = cur_tsd->pivot_start;
 
 
373
            VECTORCH object_pos = cur_tsd->object_offset;
 
 
374
 
 
 
375
              TrackSlerp(cur_tsd,lerp,&orient);
 
 
376
 
 
 
377
            pivot_pos.vx += MUL_FIXED(cur_tsd->pivot_travel.vx,lerp);
 
 
378
            pivot_pos.vy += MUL_FIXED(cur_tsd->pivot_travel.vy,lerp);
 
 
379
            pivot_pos.vz += MUL_FIXED(cur_tsd->pivot_travel.vz,lerp);
 
 
380
 
 
 
381
            RotateVector(&object_pos, &orient);
 
 
382
 
 
 
383
            object_pos.vx += pivot_pos.vx;
 
 
384
            object_pos.vy += pivot_pos.vy;
 
 
385
            object_pos.vz += pivot_pos.vz;
 
 
386
 
 
 
387
            dynptr->OrientMat = orient;
 
 
388
            dynptr->Position = object_pos;
 
 
389
        }
 
 
390
    }
 
 
391
}
 
 
392
 
 
 
393
void Update_Track_Position(TRACK_CONTROLLER* tc)
 
 
394
{
 
 
395
    assert(tc);
 
 
396
 
 
 
397
    if(!tc->playing)
 
 
398
        return;
 
 
399
 
 
 
400
    assert(tc->sbptr);
 
 
401
    assert(tc->sections);
 
 
402
 
 
 
403
    DYNAMICSBLOCK* dynptr = tc->sbptr->DynPtr;
 
 
404
    assert(dynptr);
 
 
405
 
 
 
406
    if(tc->playing_start_sound)
 
 
407
    {
 
 
408
        Update_Track_Sound(tc->start_sound,&dynptr->Position);
 
 
409
 
 
 
410
        if(tc->start_sound->playing)
 
 
411
            return;
 
 
412
 
 
 
413
        tc->playing_start_sound = 0;
 
 
414
 
 
 
415
        if(tc->sound)
 
 
416
            Start_Track_Sound(tc->sound,&tc->sbptr->DynPtr->Position);
 
 
417
    }
 
 
418
 
 
 
419
    //update timer and current section number
 
 
420
    if(tc->reverse)
 
 
421
        tc->timer -= tc->use_speed_mult ? MUL_FIXED(NormalFrameTime, tc->speed_mult) : NormalFrameTime;
 
 
422
    else
 
 
423
        tc->timer += tc->use_speed_mult ? MUL_FIXED(NormalFrameTime, tc->speed_mult) : NormalFrameTime;
 
 
424
 
 
 
425
    Update_Track_Position_Only(tc);
 
 
426
 
 
 
427
    if(tc->sound)
 
 
428
    {
 
 
429
        if(tc->playing)
 
 
430
        {
 
 
431
            Update_Track_Sound(tc->sound, &dynptr->Position);
 
 
432
        }
 
 
433
        else
 
 
434
        {
 
 
435
            Stop_Track_Sound(tc->sound);
 
 
436
 
 
 
437
            if(tc->end_sound)
 
 
438
                Start_Track_Sound(tc->end_sound,&tc->sbptr->DynPtr->Position);
 
 
439
        }
 
 
440
    }
 
 
441
}
 
 
442
 
 
 
443
static void LnQuat(QUAT *q)
 
 
444
{
 
 
445
    float theta;
 
 
446
       float m,x,y,z;
 
 
447
 
 
 
448
       x = q->quatx;
 
 
449
       y = q->quaty;
 
 
450
       z = q->quatz;
 
 
451
 
 
 
452
    if (x == 0 && y == 0 && z == 0)
 
 
453
    {
 
 
454
        q->quatw = 0;
 
 
455
        q->quatx = 0;    
 
 
456
        q->quaty = 0;
 
 
457
        q->quatz = 0;
 
 
458
        return;
 
 
459
 
 
 
460
    }
 
 
461
       {
 
 
462
           double cosine = (q->quatw/65536.0);
 
 
463
 
 
 
464
        if (cosine > 1.0)
 
 
465
            cosine = 1.0;
 
 
466
        else if (cosine < -1.0)
 
 
467
            cosine = -1.0;
 
 
468
 
 
 
469
 
 
 
470
        theta = (float)acos(cosine);
 
 
471
    }
 
 
472
 
 
 
473
    m = (65536.0/sqrt((x*x) + (y*y) + (z*z)) );
 
 
474
 
 
 
475
    x *= m;
 
 
476
    y *= m;
 
 
477
    z *= m;
 
 
478
 
 
 
479
    q->quatw = 0;
 
 
480
    q->quatx = (int)(x*theta);    
 
 
481
    q->quaty = (int)(y*theta);
 
 
482
    q->quatz = (int)(z*theta);
 
 
483
}
 
 
484
 
 
 
485
static void ExpPurelyImaginaryQuat(QUAT *q)
 
 
486
{
 
 
487
    float x,y,z;
 
 
488
    int theta;
 
 
489
 
 
 
490
    x = q->quatx;
 
 
491
    y = q->quaty;
 
 
492
       z = q->quatz;
 
 
493
 
 
 
494
    if (x != 0||y != 0||z != 0)
 
 
495
    {
 
 
496
        float m = sqrt((x*x) + (y*y) + (z*z));
 
 
497
        x /= m;
 
 
498
        y /= m;
 
 
499
        z /= m;
 
 
500
 
 
 
501
        theta = (int)((m / 16.0) / 6.28318530718);
 
 
502
 
 
 
503
        q->quatx = (int)(x*(float)GetSin(theta));    
 
 
504
        q->quaty = (int)(y*(float)GetSin(theta));    
 
 
505
        q->quatz = (int)(z*(float)GetSin(theta));    
 
 
506
        q->quatw = GetCos(theta);
 
 
507
    }
 
 
508
    else
 
 
509
    {
 
 
510
        q->quatx = 0;    
 
 
511
        q->quaty = 0;    
 
 
512
        q->quatz = 0;    
 
 
513
        q->quatw = ONE_FIXED;
 
 
514
    }
 
 
515
    QNormalise(q);
 
 
516
}
 
 
517
 
 
 
518
static void MakeControlQuat(QUAT *control, QUAT *q0, QUAT *q1, QUAT *q2)
 
 
519
{
 
 
520
    QUAT a;
 
 
521
    QUAT b,c;
 
 
522
 
 
 
523
    a.quatx = -q1->quatx;
 
 
524
    a.quaty = -q1->quaty;
 
 
525
    a.quatz = -q1->quatz;
 
 
526
    a.quatw = q1->quatw;
 
 
527
 
 
 
528
    MulQuat(&a,q2, &b);
 
 
529
    MulQuat(&a,q0, &c);
 
 
530
 
 
 
531
    LnQuat(&b);
 
 
532
    LnQuat(&c);
 
 
533
 
 
 
534
    a.quatx = -(b.quatx+c.quatx)/4;
 
 
535
    a.quaty = -(b.quaty+c.quaty)/4;
 
 
536
    a.quatz = -(b.quatz+c.quatz)/4;
 
 
537
 
 
 
538
    ExpPurelyImaginaryQuat(&a);
 
 
539
    MulQuat(q1,&a, control);
 
 
540
}
 
 
541
 
 
 
542
 
 
 
543
/*KJL*******************************************************************
 
 
544
*                                                                      *
 
 
545
* Smooth track system - this code overlays cubic splines over the lerp *
 
 
546
* and slerp code used by the original track system                     *
 
 
547
*                                                                      *
 
 
548
*******************************************************************KJL*/
 
 
549
static void Preprocess_Smooth_Track_Controller(TRACK_CONTROLLER* tc)
 
 
550
{
 
 
551
    int i;
 
 
552
    assert(tc->sections);
 
 
553
 
 
 
554
    for(i=0;i < tc->num_sections; i++)
 
 
555
    {
 
 
556
        TRACK_SECTION_DATA* tsd = &tc->sections[i];
 
 
557
        tsd->oneovertime = DIV_FIXED(ONE_FIXED,tsd->time_for_section);
 
 
558
 
 
 
559
        if (!i)
 
 
560
        {
 
 
561
            tsd->quat_prev = tsd->quat_start;
 
 
562
            tsd->pivot_0 = tsd->pivot_start;
 
 
563
            tsd->pivot_1 = tsd->pivot_start;
 
 
564
            tsd->pivot_2 = tc->sections[1].pivot_start;
 
 
565
            tsd->pivot_3 = tc->sections[2].pivot_start;
 
 
566
        }
 
 
567
        else if (i == tc->num_sections-1)
 
 
568
        {
 
 
569
            tsd->quat_prev = tc->sections[i-1].quat_start;
 
 
570
            tsd->pivot_0 = tc->sections[i-1].pivot_1;
 
 
571
            tsd->pivot_1 = tsd->pivot_start;
 
 
572
 
 
 
573
            tsd->pivot_2 = tsd->pivot_1;
 
 
574
            tsd->pivot_2.vx += tsd->pivot_travel.vx;
 
 
575
            tsd->pivot_2.vy += tsd->pivot_travel.vy;
 
 
576
            tsd->pivot_2.vz += tsd->pivot_travel.vz;
 
 
577
 
 
 
578
            tsd->pivot_3 = tsd->pivot_2;
 
 
579
        }
 
 
580
        else if (i == tc->num_sections-2)
 
 
581
        {
 
 
582
            tsd->quat_prev = tc->sections[i-1].quat_start;
 
 
583
            tsd->pivot_0 = tc->sections[i-1].pivot_1;
 
 
584
            tsd->pivot_1 = tsd->pivot_start;
 
 
585
            tsd->pivot_2 = tc->sections[i+1].pivot_start;
 
 
586
 
 
 
587
            tsd->pivot_3 = tsd->pivot_2;
 
 
588
            tsd->pivot_3.vx += tc->sections[i+1].pivot_travel.vx;
 
 
589
            tsd->pivot_3.vy += tc->sections[i+1].pivot_travel.vy;
 
 
590
            tsd->pivot_3.vz += tc->sections[i+1].pivot_travel.vz;
 
 
591
        }
 
 
592
        else
 
 
593
        {
 
 
594
            tsd->quat_prev = tc->sections[i-1].quat_start;
 
 
595
            tsd->pivot_0 = tc->sections[i-1].pivot_start;
 
 
596
            tsd->pivot_1 = tsd->pivot_start;
 
 
597
            tsd->pivot_2 = tc->sections[i+1].pivot_start;
 
 
598
            tsd->pivot_3 = tc->sections[i+2].pivot_start;
 
 
599
        }
 
 
600
    }
 
 
601
 
 
 
602
    for(i=0; i < tc->num_sections; i++)
 
 
603
    {
 
 
604
        TRACK_SECTION_DATA* tsd = &tc->sections[i];
 
 
605
 
 
 
606
        if (QDot(&tsd->quat_prev,&tsd->quat_start)<0)
 
 
607
        {
 
 
608
            tsd->quat_start.quatx =- tsd->quat_start.quatx;
 
 
609
            tsd->quat_start.quaty =- tsd->quat_start.quaty;
 
 
610
            tsd->quat_start.quatz =- tsd->quat_start.quatz;
 
 
611
            tsd->quat_start.quatw =- tsd->quat_start.quatw;
 
 
612
        }
 
 
613
 
 
 
614
        if (QDot(&tsd->quat_start,&tsd->quat_end)<0)
 
 
615
        {
 
 
616
            tsd->quat_end.quatx =- tsd->quat_end.quatx;
 
 
617
            tsd->quat_end.quaty =- tsd->quat_end.quaty;
 
 
618
            tsd->quat_end.quatz =- tsd->quat_end.quatz;
 
 
619
            tsd->quat_end.quatw =- tsd->quat_end.quatw;
 
 
620
        }
 
 
621
        MakeControlQuat ( &(tsd->quat_start_control), &(tsd->quat_prev), &(tsd->quat_start), &(tsd->quat_end) );
 
 
622
    }
 
 
623
 
 
 
624
    for(i=0; i < tc->num_sections-1; i++)
 
 
625
    {
 
 
626
        tc->sections[i].quat_end_control =  tc->sections[i+1].quat_start_control;
 
 
627
    }
 
 
628
 
 
 
629
    tc->sections[tc->num_sections-1].quat_end_control =  tc->sections[tc->num_sections-1].quat_end;
 
 
630
}
 
 
631
 
 
 
632
void Preprocess_Track_Controller(TRACK_CONTROLLER* tc)
 
 
633
{
 
 
634
    int i;
 
 
635
    assert(tc->sections);
 
 
636
 
 
 
637
    /* KJL 14:47:44 24/03/98 - check for smoothing; if you've
 
 
638
    less than 3 points then smoothing is a bit pointless */
 
 
639
    if (tc->use_smoothing && tc->num_sections >= 3)
 
 
640
    {
 
 
641
        Preprocess_Smooth_Track_Controller(tc);
 
 
642
        return;
 
 
643
    }
 
 
644
 
 
 
645
    for(i=0; i < tc->num_sections; i++)
 
 
646
    {
 
 
647
 
 
 
648
        TRACK_SECTION_DATA* tsd = &tc->sections[i];
 
 
649
 
 
 
650
        tsd->oneovertime = DIV_FIXED(ONE_FIXED,tsd->time_for_section);
 
 
651
 
 
 
652
        if(!tc->no_rotation)
 
 
653
        {
 
 
654
            int sinom;
 
 
655
            int cosom = QDot(&tsd->quat_start,&tsd->quat_end);
 
 
656
 
 
 
657
            if (cosom < 0)
 
 
658
            {
 
 
659
                tsd->quat_end.quatx =- tsd->quat_end.quatx;
 
 
660
                tsd->quat_end.quaty =- tsd->quat_end.quaty;
 
 
661
                tsd->quat_end.quatz =- tsd->quat_end.quatz;
 
 
662
                tsd->quat_end.quatw =- tsd->quat_end.quatw;
 
 
663
                cosom = -cosom;
 
 
664
            }
 
 
665
 
 
 
666
 
 
 
667
            tsd->omega = ArcCos(cosom);
 
 
668
            sinom = GetSin(tsd->omega);
 
 
669
 
 
 
670
            if (sinom)
 
 
671
            {
 
 
672
                tsd->oneoversinomega = DIV_FIXED(ONE_FIXED,sinom);
 
 
673
            }
 
 
674
            else
 
 
675
            {
 
 
676
                tsd->omega = 0;
 
 
677
                tsd->oneoversinomega = 0;
 
 
678
            }
 
 
679
        }
 
 
680
    }
 
 
681
}
 
 
682
 
 
 
683
void Start_Track_Playing(TRACK_CONTROLLER* tc)
 
 
684
{
 
 
685
    assert(tc);
 
 
686
    assert(tc->sbptr);
 
 
687
    assert(tc->sbptr->DynPtr);
 
 
688
 
 
 
689
    if(tc->playing)
 
 
690
        return;
 
 
691
 
 
 
692
    tc->playing = 1;
 
 
693
 
 
 
694
    if(tc->start_sound)
 
 
695
    {
 
 
696
        tc->playing_start_sound = 1;
 
 
697
        Start_Track_Sound(tc->start_sound,&tc->sbptr->DynPtr->Position);
 
 
698
    }
 
 
699
    else if(tc->sound)
 
 
700
    {
 
 
701
        Start_Track_Sound(tc->sound,&tc->sbptr->DynPtr->Position);
 
 
702
    }
 
 
703
 
 
 
704
}
 
 
705
 
 
 
706
void Stop_Track_Playing(TRACK_CONTROLLER* tc)
 
 
707
{
 
 
708
    assert(tc);
 
 
709
    assert(tc->sbptr);
 
 
710
    assert(tc->sbptr->DynPtr);
 
 
711
 
 
 
712
    if(!tc->playing)
 
 
713
        return;
 
 
714
 
 
 
715
    tc->playing = 0;
 
 
716
    tc->playing_start_sound = 0;
 
 
717
 
 
 
718
    if(tc->sound)
 
 
719
        Stop_Track_Sound(tc->sound);
 
 
720
 
 
 
721
    if(tc->start_sound)
 
 
722
        Stop_Track_Sound(tc->sound);
 
 
723
 
 
 
724
    if(tc->end_sound)
 
 
725
        Start_Track_Sound(tc->end_sound,&tc->sbptr->DynPtr->Position);
 
 
726
}
 
 
727
 
 
 
728
void Reset_Track(TRACK_CONTROLLER* tc)
 
 
729
{
 
 
730
    assert(tc);
 
 
731
 
 
 
732
    if(tc->sound)
 
 
733
        Stop_Track_Sound(tc->sound);
 
 
734
 
 
 
735
    if(tc->start_sound)
 
 
736
        Stop_Track_Sound(tc->start_sound);
 
 
737
 
 
 
738
    if(tc->end_sound)
 
 
739
        Stop_Track_Sound(tc->end_sound);
 
 
740
 
 
 
741
    tc->timer = tc->initial_state_timer;
 
 
742
    tc->playing = tc->initial_state_playing;
 
 
743
    tc->reverse = tc->initial_state_reverse;
 
 
744
    tc->current_section = 0;    
 
 
745
 
 
 
746
    if(tc->playing && tc->sound)
 
 
747
        tc->sound->playing = 1;
 
 
748
}
 
 
749
 
 
 
750
/*--------------------**
 
 
751
** Loading and Saving **
 
 
752
**--------------------*/
 
 
753
#include "savegame.h"
 
 
754
typedef struct track_save_block
 
 
755
{
 
 
756
    SAVE_BLOCK_HEADER header;
 
 
757
 
 
 
758
    int timer;
 
 
759
    int speed_mult;
 
 
760
    int current_section;
 
 
761
 
 
 
762
    unsigned int playing:1;
 
 
763
    unsigned int reverse:1;
 
 
764
    unsigned int no_rotation:1;
 
 
765
    unsigned int use_speed_mult:1;
 
 
766
 
 
 
767
    unsigned int start_sound_playing:1;
 
 
768
    unsigned int mid_sound_playing:1;
 
 
769
    unsigned int end_sound_playing:1;
 
 
770
 
 
 
771
} TRACK_SAVE_BLOCK;
 
 
772
 
 
 
773
//defines for load/save macros
 
 
774
#define SAVELOAD_BLOCK block
 
 
775
#define SAVELOAD_BEHAV tc
 
 
776
 
 
 
777
void LoadTrackPosition(SAVE_BLOCK_HEADER* header,TRACK_CONTROLLER* tc)
 
 
778
{
 
 
779
    TRACK_SAVE_BLOCK* block = (TRACK_SAVE_BLOCK*)header;
 
 
780
    if(!header || !tc)
 
 
781
        return;
 
 
782
 
 
 
783
    //check the size of the save block
 
 
784
    if(header->size != sizeof(*block))
 
 
785
        return;
 
 
786
 
 
 
787
    //start copying stuff
 
 
788
 
 
 
789
    COPYELEMENT_LOAD(timer)
 
 
790
    COPYELEMENT_LOAD(speed_mult)
 
 
791
    COPYELEMENT_LOAD(current_section)
 
 
792
 
 
 
793
    COPYELEMENT_LOAD(playing)
 
 
794
    COPYELEMENT_LOAD(reverse)
 
 
795
    COPYELEMENT_LOAD(no_rotation)
 
 
796
    COPYELEMENT_LOAD(use_speed_mult)
 
 
797
 
 
 
798
    Update_Track_Position_Only(tc);
 
 
799
 
 
 
800
    if(tc->start_sound)
 
 
801
        tc->start_sound->playing = block->start_sound_playing;
 
 
802
 
 
 
803
    if(tc->sound)
 
 
804
        tc->sound->playing = block->mid_sound_playing;
 
 
805
 
 
 
806
    if(tc->end_sound)
 
 
807
        tc->end_sound->playing = block->end_sound_playing;
 
 
808
 
 
 
809
    if(tc->start_sound)
 
 
810
        Load_SoundState(&tc->start_sound->activ_no);
 
 
811
 
 
 
812
    if(tc->sound)
 
 
813
        Load_SoundState(&tc->sound->activ_no);
 
 
814
 
 
 
815
    if(tc->end_sound)
 
 
816
        Load_SoundState(&tc->end_sound->activ_no);
 
 
817
}
 
 
818
 
 
 
819
void SaveTrackPosition(TRACK_CONTROLLER* tc)
 
 
820
{
 
 
821
    TRACK_SAVE_BLOCK* block;
 
 
822
    if(!tc)
 
 
823
        return;
 
 
824
 
 
 
825
    GET_SAVE_BLOCK_POINTER(block);
 
 
826
 
 
 
827
    //fill in header
 
 
828
    block->header.type = SaveBlock_Track;
 
 
829
    block->header.size = sizeof(*block);
 
 
830
 
 
 
831
    //start copying stuff
 
 
832
 
 
 
833
    COPYELEMENT_SAVE(timer)
 
 
834
    COPYELEMENT_SAVE(speed_mult)
 
 
835
    COPYELEMENT_SAVE(current_section)
 
 
836
 
 
 
837
    COPYELEMENT_SAVE(playing)
 
 
838
    COPYELEMENT_SAVE(reverse)
 
 
839
    COPYELEMENT_SAVE(no_rotation)
 
 
840
    COPYELEMENT_SAVE(use_speed_mult)
 
 
841
 
 
 
842
    if(tc->start_sound)
 
 
843
    {
 
 
844
        block->start_sound_playing = tc->start_sound->playing;
 
 
845
    }
 
 
846
    else
 
 
847
    {
 
 
848
        block->start_sound_playing = 0;
 
 
849
    }
 
 
850
 
 
 
851
    if(tc->sound)
 
 
852
    {
 
 
853
        block->mid_sound_playing = tc->sound->playing;
 
 
854
    }
 
 
855
    else
 
 
856
    {
 
 
857
        block->mid_sound_playing = 0;
 
 
858
    }
 
 
859
 
 
 
860
    if(tc->end_sound)
 
 
861
    {
 
 
862
        block->end_sound_playing = tc->end_sound->playing;
 
 
863
    }
 
 
864
    else
 
 
865
    {
 
 
866
        block->end_sound_playing = 0;
 
 
867
    }                           
 
 
868
 
 
 
869
    if(tc->start_sound)
 
 
870
        Save_SoundState(&tc->start_sound->activ_no);
 
 
871
 
 
 
872
    if(tc->sound)
 
 
873
        Save_SoundState(&tc->sound->activ_no);
 
 
874
 
 
 
875
    if(tc->end_sound)
 
 
876
        Save_SoundState(&tc->end_sound->activ_no);
 
 
877
}