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