4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "npc_common.h"
 
 
2
#include "dynamics.h"                    
 
 
3
#include "npc_dummy.h"
 
 
4
#include "bh_track.h"
 
 
5
#include "fan.h"
 
 
6
#include "userprofile.h"
 
 
7
 
 
 
8
#define MINIMUM_BOUNDINGBOX_EXTENT 25
 
 
9
 
 
 
10
#define FLOOR_THRESHOLD 30000
 
 
11
#define NEARLYFLATFLOOR_THRESHOLD 60000
 
 
12
 
 
 
13
extern struct shapeheader* GetShapeData(int shapenum);
 
 
14
extern void GetMorphDisplay(MORPHDISPLAY *md, DISPLAYBLOCK *dptr);
 
 
15
extern int NumActiveBlocks;
 
 
16
extern DISPLAYBLOCK *ActiveBlockList[];
 
 
17
 
 
 
18
static void (*MakeStaticBoundingBoxForObject)(STRATEGYBLOCK *sbPtr);
 
 
19
 
 
 
20
#define AddScaledVectorToVector(v2,s,v1) { v1.vx += MUL_FIXED(v2.vx, s); v1.vy += MUL_FIXED(v2.vy, s); v1.vz += MUL_FIXED(v2.vz, s); }
 
 
21
#define SubScaledVectorFromVector(v2,s,v1) { v1.vx -= MUL_FIXED(v2.vx, s); v1.vy -= MUL_FIXED(v2.vy, s); v1.vz -= MUL_FIXED(v2.vz, s); }
 
 
22
 
 
 
23
#define COLLISION_GRANULARITY 10 // 40
 
 
24
#define RELOCATION_GRANULARITY 5 // 30
 
 
25
#define GRAVITY_DISPLACEMENT (COLLISION_GRANULARITY+1)
 
 
26
#define MAXIMUM_NUMBER_OF_COLLISIONPOLYS 3000
 
 
27
 
 
 
28
struct DynamicObjects
 
 
29
{
 
 
30
    STRATEGYBLOCK *sbptr;
 
 
31
    int valueOnWhichToSort;
 
 
32
};
 
 
33
 
 
 
34
static struct DynamicObjects DynamicObjectsList[MAX_NO_OF_DYNAMICS_BLOCKS];
 
 
35
 
 
 
36
int PlanarGravity = 1;
 
 
37
 
 
 
38
static int AccelDueToGravity;
 
 
39
static int NumberOfDynamicObjects = 0;
 
 
40
static int DistanceToStepUp;
 
 
41
static int NumberOfCollisionPolys;
 
 
42
static int NumberOfInterferencePolygons = 0;
 
 
43
 
 
 
44
static struct ColPolyTag CollisionPolysArray[MAXIMUM_NUMBER_OF_COLLISIONPOLYS];
 
 
45
static struct ColPolyTag *CollisionPolysPtr;
 
 
46
 
 
 
47
#define MAX_NUMBER_OF_INTERFERENCE_POLYGONS 100
 
 
48
static struct ColPolyTag InterferencePolygons[MAX_NUMBER_OF_INTERFERENCE_POLYGONS];
 
 
49
 
 
 
50
/* global storage of bounding box */
 
 
51
static int DBBMinX,DBBMaxX, DBBMinY,DBBMaxY, DBBMinZ,DBBMaxZ;
 
 
52
static int SBBMinX,SBBMaxX, SBBMinY,SBBMaxY, SBBMinZ,SBBMaxZ;
 
 
53
 
 
 
54
static const int CuboidVertexList[] = {0,1,5,4, 0,4,6,2, 0,2,3,1, 1,3,7,5, 4,5,7,6, 3,2,6,7};
 
 
55
 
 
 
56
extern VECTORCH MorphedPts[];
 
 
57
 
 
 
58
VECTORCH *ShapePointsPtr;
 
 
59
int *ShapeNormalsPtr;
 
 
60
int *Shape2NormalsPtr;
 
 
61
char ShapeIsMorphed;
 
 
62
int **ItemArrayPtr;
 
 
63
POLYHEADER *PolyheaderPtr;
 
 
64
 
 
 
65
static int SetupPolygonAccess(DISPLAYBLOCK *objectPtr)
 
 
66
{
 
 
67
    struct shapeheader* shape1Ptr;
 
 
68
 
 
 
69
    #if !IgnoreMorphing
 
 
70
      if (objectPtr->ObMorphCtrl) /* morphable object? */
 
 
71
    {
 
 
72
        VECTORCH *shape1PointsPtr;
 
 
73
        VECTORCH *shape2PointsPtr;
 
 
74
 
 
 
75
        GetMorphDisplay(&MorphDisplay, objectPtr);
 
 
76
 
 
 
77
        shape1Ptr = MorphDisplay.md_sptr1;
 
 
78
 
 
 
79
        switch(MorphDisplay.md_lerp)
 
 
80
        {
 
 
81
            case 0x0000:
 
 
82
            {
 
 
83
                ShapePointsPtr = (VECTORCH *)*shape1Ptr->points;
 
 
84
                ShapeNormalsPtr = (int *) *(shape1Ptr->sh_normals);
 
 
85
                ShapeIsMorphed = 0;
 
 
86
            }
 
 
87
            break;
 
 
88
            case 0xffff:
 
 
89
            {
 
 
90
                struct shapeheader* shape2Ptr = MorphDisplay.md_sptr2;
 
 
91
 
 
 
92
                ShapePointsPtr = (VECTORCH *)*shape2Ptr->points;    
 
 
93
                ShapeNormalsPtr = (int *) *(shape2Ptr->sh_normals);
 
 
94
                ShapeIsMorphed = 0;
 
 
95
            }
 
 
96
            break;
 
 
97
            default:
 
 
98
            {
 
 
99
                struct shapeheader* shape2Ptr = MorphDisplay.md_sptr2;
 
 
100
 
 
 
101
                shape1PointsPtr = (VECTORCH *)(*shape1Ptr->points);
 
 
102
                shape2PointsPtr = (VECTORCH *)(*shape2Ptr->points);
 
 
103
 
 
 
104
                /* you're going to need all the points so you might as well morph them all at once now */
 
 
105
                {
 
 
106
                    int numberOfPoints = shape1Ptr->numpoints;
 
 
107
                    VECTORCH *morphedPointsPtr = (VECTORCH *) MorphedPts;
 
 
108
 
 
 
109
                    while(numberOfPoints--)
 
 
110
                    {
 
 
111
                        VECTORCH vertex1 = *shape1PointsPtr;
 
 
112
                        VECTORCH vertex2 = *shape2PointsPtr;
 
 
113
 
 
 
114
                        if( (vertex1.vx == vertex2.vx && vertex1.vy == vertex2.vy && vertex1.vz == vertex2.vz) )
 
 
115
                        {
 
 
116
                            *morphedPointsPtr = vertex1;
 
 
117
                        }
 
 
118
                        else
 
 
119
                        {
 
 
120
                            /* KJL 15:27:20 05/22/97 - I've changed this to speed things up, If a vertex
 
 
121
                            component has a magnitude greater than 32768 things will go wrong. */
 
 
122
                            morphedPointsPtr->vx = vertex1.vx + (((vertex2.vx-vertex1.vx)*MorphDisplay.md_lerp)>>16);
 
 
123
                            morphedPointsPtr->vy = vertex1.vy + (((vertex2.vy-vertex1.vy)*MorphDisplay.md_lerp)>>16);
 
 
124
                            morphedPointsPtr->vz = vertex1.vz + (((vertex2.vz-vertex1.vz)*MorphDisplay.md_lerp)>>16);
 
 
125
                        }
 
 
126
 
 
 
127
                        shape1PointsPtr++;
 
 
128
                        shape2PointsPtr++;
 
 
129
                        morphedPointsPtr++;
 
 
130
                    }
 
 
131
                }
 
 
132
 
 
 
133
                ShapePointsPtr = (VECTORCH *)MorphedPts;
 
 
134
                ShapeNormalsPtr = (int *) *(shape1Ptr->sh_normals);
 
 
135
                Shape2NormalsPtr = (int *) *(shape2Ptr->sh_normals);
 
 
136
                ShapeIsMorphed = 1;
 
 
137
            }
 
 
138
        }
 
 
139
 
 
 
140
        ItemArrayPtr = (int **)shape1Ptr->items;
 
 
141
    }
 
 
142
      else /* not a morphing object */
 
 
143
      #endif
 
 
144
      {
 
 
145
        shape1Ptr = GetShapeData(objectPtr->ObShape);
 
 
146
 
 
 
147
        ShapePointsPtr  = (VECTORCH *)(*shape1Ptr->points);
 
 
148
        ShapeNormalsPtr = (int *)(*shape1Ptr->sh_normals);
 
 
149
        ItemArrayPtr = (int **)shape1Ptr->items;
 
 
150
        ShapeIsMorphed = 0;
 
 
151
    }
 
 
152
 
 
 
153
    {
 
 
154
        int *itemPtr = *ItemArrayPtr;
 
 
155
        PolyheaderPtr = (POLYHEADER *) itemPtr;
 
 
156
    }
 
 
157
 
 
 
158
return shape1Ptr->numitems;
 
 
159
}
 
 
160
 
 
 
161
static void VectorHomingForSurfaceAlign(VECTORCH *currentPtr, VECTORCH *targetPtr, VECTORCH *perpendicularPtr)
 
 
162
{
 
 
163
    int cos = DotProduct(currentPtr, targetPtr);
 
 
164
 
 
 
165
    if (cos <= -65000)
 
 
166
    {
 
 
167
        int a1 = NormalFrameTime*4;
 
 
168
 
 
 
169
        if (a1 > ONE_FIXED)
 
 
170
            a1 = ONE_FIXED;
 
 
171
        else if (a1<1024)
 
 
172
            a1 = 1024; 
 
 
173
 
 
 
174
        currentPtr->vx = currentPtr->vx+MUL_FIXED(perpendicularPtr->vx-currentPtr->vx, a1);
 
 
175
        currentPtr->vy = currentPtr->vy+MUL_FIXED(perpendicularPtr->vy-currentPtr->vy, a1);
 
 
176
        currentPtr->vz = currentPtr->vz+MUL_FIXED(perpendicularPtr->vz-currentPtr->vz, a1);
 
 
177
        Normalise(currentPtr);
 
 
178
    }
 
 
179
    else if (cos >= 65500)    /* if they're practically parallel just snap currentPtr to targetPtr */
 
 
180
    {
 
 
181
        currentPtr->vx = targetPtr->vx;
 
 
182
        currentPtr->vy = targetPtr->vy;
 
 
183
        currentPtr->vz = targetPtr->vz;
 
 
184
    }
 
 
185
    else
 
 
186
    {
 
 
187
        if (cos < 32768)
 
 
188
            cos = 32768;
 
 
189
 
 
 
190
          int a1 = MUL_FIXED(cos*8, NormalFrameTime);
 
 
191
//        int a1 = NormalFrameTime * 4;
 
 
192
 
 
 
193
        if (a1 > ONE_FIXED)
 
 
194
            a1 = ONE_FIXED;
 
 
195
        else if (a1 < 1024)
 
 
196
            a1 = 1024; 
 
 
197
 
 
 
198
        currentPtr->vx = currentPtr->vx+MUL_FIXED(targetPtr->vx-currentPtr->vx, a1);
 
 
199
        currentPtr->vy = currentPtr->vy+MUL_FIXED(targetPtr->vy-currentPtr->vy, a1);
 
 
200
        currentPtr->vz = currentPtr->vz+MUL_FIXED(targetPtr->vz-currentPtr->vz, a1);
 
 
201
        Normalise(currentPtr);
 
 
202
    }
 
 
203
}
 
 
204
 
 
 
205
static void AlignObjectToGravityDirection(DYNAMICSBLOCK *dynPtr)
 
 
206
{
 
 
207
    VECTORCH XVector;
 
 
208
    VECTORCH YVector;
 
 
209
    VECTORCH ZVector;
 
 
210
    int staticAxis;
 
 
211
 
 
 
212
    {
 
 
213
        int dotx = abs(DotProduct((VECTORCH*)&dynPtr->OrientMat.mat11, &dynPtr->GravityDirection));
 
 
214
        int doty = abs(DotProduct((VECTORCH*)&dynPtr->OrientMat.mat21, &dynPtr->GravityDirection));
 
 
215
        int dotz = abs(DotProduct((VECTORCH*)&dynPtr->OrientMat.mat31, &dynPtr->GravityDirection));
 
 
216
 
 
 
217
        staticAxis = (dotx < doty) ? ((dotx < dotz) ? ix : iz) : ((doty < dotz) ? iy : iz);
 
 
218
    }
 
 
219
 
 
 
220
     if (staticAxis == iz)
 
 
221
    {
 
 
222
        ZVector = *((VECTORCH*)&dynPtr->OrientMat.mat31);
 
 
223
         YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
 
 
224
          VectorHomingForSurfaceAlign(&YVector, &dynPtr->GravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat11));
 
 
225
        CrossProduct(&YVector, &ZVector, &XVector);
 
 
226
    }
 
 
227
     else if (staticAxis == ix)
 
 
228
    {
 
 
229
        XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
 
 
230
         YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
 
 
231
        VectorHomingForSurfaceAlign(&YVector, &dynPtr->GravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
 
 
232
        CrossProduct(&XVector, &YVector, &ZVector);
 
 
233
    }
 
 
234
    else if (staticAxis == iy)
 
 
235
    {
 
 
236
        XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
 
 
237
         YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
 
 
238
        VectorHomingForSurfaceAlign(&YVector, &dynPtr->GravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
 
 
239
        CrossProduct(&XVector, &YVector, &ZVector);
 
 
240
        CrossProduct(&YVector, &ZVector, &XVector);
 
 
241
    }
 
 
242
 
 
 
243
    Normalise(&XVector);
 
 
244
    Normalise(&YVector);
 
 
245
    Normalise(&ZVector);
 
 
246
 
 
 
247
    dynPtr->OrientMat.mat11 = XVector.vx;
 
 
248
       dynPtr->OrientMat.mat12 = XVector.vy;
 
 
249
    dynPtr->OrientMat.mat13 = XVector.vz;
 
 
250
 
 
 
251
    dynPtr->OrientMat.mat21 = YVector.vx;
 
 
252
    dynPtr->OrientMat.mat22 = YVector.vy;
 
 
253
    dynPtr->OrientMat.mat23 = YVector.vz;
 
 
254
 
 
 
255
    dynPtr->OrientMat.mat31 = ZVector.vx;
 
 
256
    dynPtr->OrientMat.mat32 = ZVector.vy;
 
 
257
    dynPtr->OrientMat.mat33 = ZVector.vz;
 
 
258
 
 
 
259
    MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
 
 
260
}
 
 
261
 
 
 
262
static void AlignObjectToStandardGravityDirection(DYNAMICSBLOCK *dynPtr)
 
 
263
{
 
 
264
    VECTORCH gravityDirection = {0,65536,0};
 
 
265
    VECTORCH XVector,YVector,ZVector;
 
 
266
    int staticAxis;
 
 
267
 
 
 
268
    dynPtr->GravityDirection = gravityDirection;
 
 
269
 
 
 
270
    {
 
 
271
        int dotx = abs(dynPtr->OrientMat.mat12);
 
 
272
        int doty = abs(dynPtr->OrientMat.mat22);
 
 
273
        int dotz = abs(dynPtr->OrientMat.mat32);
 
 
274
 
 
 
275
        staticAxis = (dotx < doty) ? ((dotx < dotz) ? ix : iz) : ((doty < dotz) ? iy : iz);
 
 
276
    }
 
 
277
 
 
 
278
     if (staticAxis == iz)
 
 
279
    {
 
 
280
        ZVector = *((VECTORCH*)&dynPtr->OrientMat.mat31);
 
 
281
         YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
 
 
282
          VectorHomingForSurfaceAlign(&YVector, &gravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat11));
 
 
283
        CrossProduct(&YVector, &ZVector, &XVector);
 
 
284
    }
 
 
285
     else if (staticAxis == ix)
 
 
286
    {
 
 
287
        XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
 
 
288
         YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
 
 
289
        VectorHomingForSurfaceAlign(&YVector, &gravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
 
 
290
        CrossProduct(&XVector, &YVector, &ZVector);
 
 
291
    }
 
 
292
    else if (staticAxis == iy)
 
 
293
    {
 
 
294
        XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
 
 
295
         YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
 
 
296
        VectorHomingForSurfaceAlign(&YVector, &gravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
 
 
297
        CrossProduct(&XVector, &YVector, &ZVector);
 
 
298
        CrossProduct(&YVector, &ZVector, &XVector);
 
 
299
    }
 
 
300
 
 
 
301
    Normalise(&XVector);
 
 
302
    Normalise(&YVector);
 
 
303
    Normalise(&ZVector);
 
 
304
 
 
 
305
    dynPtr->OrientMat.mat11 = XVector.vx;
 
 
306
       dynPtr->OrientMat.mat12 = XVector.vy;
 
 
307
    dynPtr->OrientMat.mat13 = XVector.vz;
 
 
308
 
 
 
309
    dynPtr->OrientMat.mat21 = YVector.vx;
 
 
310
    dynPtr->OrientMat.mat22 = YVector.vy;
 
 
311
    dynPtr->OrientMat.mat23 = YVector.vz;
 
 
312
 
 
 
313
    dynPtr->OrientMat.mat31 = ZVector.vx;
 
 
314
    dynPtr->OrientMat.mat32 = ZVector.vy;
 
 
315
    dynPtr->OrientMat.mat33 = ZVector.vz;
 
 
316
 
 
 
317
    MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
 
 
318
}
 
 
319
 
 
 
320
static void ApplyGravity(DYNAMICSBLOCK *dynPtr)
 
 
321
{
 
 
322
    if (dynPtr->GravityOn)
 
 
323
    {
 
 
324
        if (dynPtr->UseStandardGravity)
 
 
325
        {
 
 
326
            if (PlanarGravity)
 
 
327
            {
 
 
328
                /* ie. in direction of +ve Y-axis */
 
 
329
                   dynPtr->LinImpulse.vy += AccelDueToGravity;    
 
 
330
 
 
 
331
                /* KJL 11:47:04 03/26/97 - aliens need to be aligned */
 
 
332
                if (dynPtr->ToppleForce == TOPPLE_FORCE_ALIEN)
 
 
333
                    AlignObjectToStandardGravityDirection(dynPtr);
 
 
334
            }
 
 
335
            else
 
 
336
            {
 
 
337
                extern int CloakingPhase;
 
 
338
                dynPtr->GravityDirection.vx = GetSin((CloakingPhase/16) & 4095);
 
 
339
                dynPtr->GravityDirection.vy = GetCos((CloakingPhase/16) & 4095);
 
 
340
                dynPtr->GravityDirection.vz = GetCos((CloakingPhase/19 + 400) & 4095);
 
 
341
                Normalise(&dynPtr->GravityDirection);
 
 
342
                AddScaledVectorToVector(dynPtr->GravityDirection, AccelDueToGravity, dynPtr->LinImpulse);
 
 
343
                AlignObjectToGravityDirection(dynPtr);
 
 
344
            }
 
 
345
        }
 
 
346
        else
 
 
347
        {
 
 
348
            /* KJL 11:47:04 03/26/97 - aliens need to be aligned */
 
 
349
            if (dynPtr->ToppleForce == TOPPLE_FORCE_ALIEN)
 
 
350
            {
 
 
351
                int normalsFound = 0;
 
 
352
                VECTORCH averageNormal = {0,0,0};
 
 
353
 
 
 
354
                if(dynPtr->TimeNotInContactWithFloor != -1)
 
 
355
                {
 
 
356
                    COLLISIONREPORT *reportPtr = dynPtr->CollisionReportPtr;
 
 
357
 
 
 
358
                    while (reportPtr)
 
 
359
                    {
 
 
360
                        averageNormal.vx -= reportPtr->ObstacleNormal.vx;
 
 
361
                        averageNormal.vy -= reportPtr->ObstacleNormal.vy;
 
 
362
                        averageNormal.vz -= reportPtr->ObstacleNormal.vz;
 
 
363
                        normalsFound++;
 
 
364
                        reportPtr = reportPtr->NextCollisionReportPtr;
 
 
365
                    }
 
 
366
                }
 
 
367
 
 
 
368
                if (normalsFound)
 
 
369
                {
 
 
370
                    if (averageNormal.vx || averageNormal.vy || averageNormal.vz)
 
 
371
                        Normalise(&averageNormal);
 
 
372
                    else
 
 
373
                        averageNormal.vy = ONE_FIXED; // down boy down
 
 
374
 
 
 
375
                    dynPtr->GravityDirection = averageNormal;
 
 
376
                    dynPtr->TimeNotInContactWithFloor = TIME_BEFORE_GRAVITY_KICKS_IN;
 
 
377
                }
 
 
378
                else
 
 
379
                {
 
 
380
        //dynPtr->UseStandardGravity = 1;
 
 
381
            //int speed = Approximate3dMagnitude(&dynPtr->LinVelocity); // jadda
 
 
382
            //printf("SPEEEEEEEEEEEEEEEEEEEEEEED %d\n", speed);
 
 
383
                    if (dynPtr->TimeNotInContactWithFloor <= 0)
 
 
384
                    {
 
 
385
                        if (PlanarGravity)
 
 
386
                        {
 
 
387
                            dynPtr->GravityDirection.vx = dynPtr->GravityDirection.vz = 0;
 
 
388
                            dynPtr->GravityDirection.vy = 65536;
 
 
389
                        }
 
 
390
                        else
 
 
391
                        {
 
 
392
                            dynPtr->GravityDirection.vx = -dynPtr->Position.vx;
 
 
393
                            dynPtr->GravityDirection.vy = -dynPtr->Position.vy;
 
 
394
                            dynPtr->GravityDirection.vz = -dynPtr->Position.vz;
 
 
395
                            Normalise(&dynPtr->GravityDirection);
 
 
396
                        }
 
 
397
                    }
 
 
398
                    else if (dynPtr->TimeNotInContactWithFloor == TIME_BEFORE_GRAVITY_KICKS_IN)
 
 
399
                    {
 
 
400
                        //if(Keyboard_input_operate())
 
 
401
                        //if(speed < 9000)
 
 
402
                        //if(0)
 
 
403
                        if (dynPtr->LinVelocity.vx || dynPtr->LinVelocity.vy || dynPtr->LinVelocity.vz)
 
 
404
                        {
 
 
405
                            /* code to enable going round 270 degree corners */
 
 
406
                            Normalise(&dynPtr->LinVelocity);
 
 
407
                            dynPtr->GravityDirection.vx -= (dynPtr->LinVelocity.vx * 3)/4;
 
 
408
                            dynPtr->GravityDirection.vy -= (dynPtr->LinVelocity.vy * 3)/4;
 
 
409
                            dynPtr->GravityDirection.vz -= (dynPtr->LinVelocity.vz * 3)/4;
 
 
410
                            Normalise(&dynPtr->GravityDirection);
 
 
411
                            dynPtr->LinVelocity.vx = dynPtr->LinVelocity.vy = dynPtr->LinVelocity.vz = 0;
 
 
412
                        }
 
 
413
                    }
 
 
414
 
 
 
415
                    dynPtr->TimeNotInContactWithFloor -= NormalFrameTime;
 
 
416
 
 
 
417
                    if (dynPtr->TimeNotInContactWithFloor < 0)
 
 
418
                        dynPtr->TimeNotInContactWithFloor = 0;
 
 
419
                }
 
 
420
 
 
 
421
                AlignObjectToGravityDirection(dynPtr);
 
 
422
            }
 
 
423
 
 
 
424
            AddScaledVectorToVector(dynPtr->GravityDirection, AccelDueToGravity, dynPtr->LinImpulse);
 
 
425
        }
 
 
426
    }
 
 
427
}
 
 
428
 
 
 
429
static void CreateSphereBBForObject(const STRATEGYBLOCK *sbPtr)
 
 
430
{
 
 
431
    VECTORCH *objectVertices = sbPtr->DynPtr->ObjectVertices;
 
 
432
    /* make a cuboid from the sphere's radius */
 
 
433
    {
 
 
434
    int radius = sbPtr->DynPtr->CollisionRadius;    
 
 
435
 
 
 
436
        objectVertices[0].vx = radius;
 
 
437
        objectVertices[1].vx = radius;
 
 
438
        objectVertices[2].vx = radius;
 
 
439
        objectVertices[3].vx = radius;
 
 
440
        objectVertices[0].vy = radius;
 
 
441
        objectVertices[1].vy = radius;
 
 
442
        objectVertices[4].vy = radius;
 
 
443
        objectVertices[5].vy = radius;
 
 
444
    objectVertices[0].vz = radius;
 
 
445
        objectVertices[2].vz = radius;
 
 
446
        objectVertices[4].vz = radius;
 
 
447
        objectVertices[6].vz = radius;
 
 
448
 
 
 
449
    radius = -radius;
 
 
450
 
 
 
451
        objectVertices[4].vx = radius;
 
 
452
        objectVertices[5].vx = radius;
 
 
453
        objectVertices[6].vx = radius;
 
 
454
        objectVertices[7].vx = radius;
 
 
455
        objectVertices[2].vy = radius;
 
 
456
        objectVertices[3].vy = radius;
 
 
457
        objectVertices[6].vy = radius;
 
 
458
        objectVertices[7].vy = radius;
 
 
459
    objectVertices[1].vz = radius;
 
 
460
        objectVertices[3].vz = radius;
 
 
461
        objectVertices[5].vz = radius;
 
 
462
        objectVertices[7].vz = radius;
 
 
463
    }
 
 
464
 
 
 
465
    /* translate cuboid into world space */
 
 
466
    {
 
 
467
        VECTORCH *vertexPtr = objectVertices;
 
 
468
        VECTORCH objectPosition = sbPtr->DynPtr->Position;
 
 
469
 
 
 
470
        int vertexNum = 8;
 
 
471
 
 
 
472
        do
 
 
473
        {
 
 
474
            vertexPtr->vx += objectPosition.vx;
 
 
475
            vertexPtr->vy += objectPosition.vy;    
 
 
476
            vertexPtr->vz += objectPosition.vz;    
 
 
477
            vertexPtr++;
 
 
478
 
 
 
479
        } while(--vertexNum);
 
 
480
    }
 
 
481
}
 
 
482
 
 
 
483
static void CreateNRBBForObject(const STRATEGYBLOCK *sbPtr)
 
 
484
{
 
 
485
    VECTORCH *objectVertices = sbPtr->DynPtr->ObjectVertices;
 
 
486
    const COLLISION_EXTENTS *extentsPtr = NULL;
 
 
487
    int objectIsCrouching = 0;
 
 
488
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
489
    dynPtr->CollisionRadius = 0;
 
 
490
    int player = 0;
 
 
491
 
 
 
492
    if(I_BehaviourPlatform == sbPtr->type)
 
 
493
    {
 
 
494
    puts("LFIT DYNA");
 
 
495
    if(NULL == sbPtr->DisplayBlock)
 
 
496
    {
 
 
497
    printf("NULL NURGM %d\n", sbPtr->type);
 
 
498
    sleep(1);
 
 
499
    return;
 
 
500
    }
 
 
501
    }
 
 
502
 
 
 
503
    switch(sbPtr->type)
 
 
504
    {
 
 
505
           case I_BehaviourMarinePlayer:
 
 
506
            objectIsCrouching = PlayerStatus.Crouching;
 
 
507
            extentsPtr = &CollisionExtents[CE_MARINE];
 
 
508
            //dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
 
 
509
            PlayerStatus.DisplayBlock->extent.radius = extentsPtr->CollisionRadius;
 
 
510
player = 1;
 
 
511
        break;
 
 
512
        case I_BehaviourAlienPlayer:
 
 
513
            objectIsCrouching = PlayerStatus.Crouching;
 
 
514
            //extentsPtr = &CollisionExtents[(objectIsCrouching ? CE_ALIEN_CROUCH : CE_ALIEN)];
 
 
515
            extentsPtr = &CollisionExtents[CE_ALIEN];
 
 
516
            dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
 
 
517
        break;
 
 
518
        case I_BehaviourPredatorPlayer:
 
 
519
            objectIsCrouching = PlayerStatus.Crouching;
 
 
520
            extentsPtr = &CollisionExtents[CE_PREDATOR];
 
 
521
            dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
 
 
522
        break;    
 
 
523
        case I_BehaviourAlien:
 
 
524
        {
 
 
525
            ALIEN_STATUS_BLOCK *alienStatusPtr = (ALIEN_STATUS_BLOCK *)sbPtr->dataptr;
 
 
526
            objectIsCrouching = alienStatusPtr->IAmCrouched;
 
 
527
 
 
 
528
            switch(alienStatusPtr->Type)
 
 
529
            {
 
 
530
                default:
 
 
531
                case Standard:
 
 
532
                case Predalien:
 
 
533
                    //extentsPtr = &CollisionExtents[(objectIsCrouching ? CE_ALIEN_CROUCH : CE_ALIEN)];
 
 
534
                    extentsPtr = &CollisionExtents[CE_ALIEN];
 
 
535
                break;
 
 
536
                case Praetorian:
 
 
537
                    extentsPtr = &CollisionExtents[CE_PRAETORIAN];
 
 
538
            }
 
 
539
        }
 
 
540
        break;
 
 
541
        case I_BehaviourPredator:
 
 
542
        {
 
 
543
            PREDATOR_STATUS_BLOCK *predatorStatusPtr = (PREDATOR_STATUS_BLOCK *)sbPtr->dataptr;
 
 
544
            objectIsCrouching = predatorStatusPtr->IAmCrouched;
 
 
545
            extentsPtr = &CollisionExtents[CE_PREDATOR];
 
 
546
        }
 
 
547
        break;
 
 
548
        case I_BehaviourMarine:
 
 
549
        {
 
 
550
            MARINE_STATUS_BLOCK *marineStatusPtr = (MARINE_STATUS_BLOCK *)sbPtr->dataptr;
 
 
551
            objectIsCrouching = marineStatusPtr->IAmCrouched;
 
 
552
            extentsPtr = &CollisionExtents[CE_MARINE];
 
 
553
        }
 
 
554
        break;
 
 
555
        case I_BehaviourAutoGun:
 
 
556
            extentsPtr = &CollisionExtents[CE_SENTRYGUN];
 
 
557
        break;
 
 
558
        case I_BehaviourFaceHugger:
 
 
559
        {
 
 
560
            extentsPtr = &CollisionExtents[CE_FACEHUGGER];
 
 
561
            //dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
 
 
562
        }
 
 
563
        break;
 
 
564
        case I_BehaviourXenoborg:
 
 
565
            extentsPtr = &CollisionExtents[CE_XENOBORG];
 
 
566
        break;
 
 
567
        case I_BehaviourQueenAlien:
 
 
568
            extentsPtr = &CollisionExtents[CE_QUEEN];
 
 
569
        break;
 
 
570
        case I_BehaviourCorpse:
 
 
571
            extentsPtr = &CollisionExtents[CE_CORPSE];
 
 
572
        break;
 
 
573
           case I_BehaviourDummy:
 
 
574
        {
 
 
575
            DUMMY_STATUS_BLOCK *dummyStatus = (DUMMY_STATUS_BLOCK *)sbPtr->dataptr;
 
 
576
 
 
 
577
            switch(dummyStatus->PlayerType)
 
 
578
            {
 
 
579
                case I_Alien:
 
 
580
                    extentsPtr = &CollisionExtents[CE_ALIEN];
 
 
581
                break;
 
 
582
                case I_Marine:
 
 
583
                    extentsPtr = &CollisionExtents[CE_MARINE];
 
 
584
                break;
 
 
585
                case I_Predator:
 
 
586
                    extentsPtr = &CollisionExtents[CE_PREDATOR];
 
 
587
            }
 
 
588
        }
 
 
589
        break;
 
 
590
        case I_BehaviourNetGhost:
 
 
591
        {
 
 
592
            NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr;
 
 
593
            assert(ghostData);
 
 
594
 
 
 
595
            switch(ghostData->type)
 
 
596
            {
 
 
597
                   case I_BehaviourAlienPlayer:
 
 
598
                case I_BehaviourPredatorPlayer:
 
 
599
                {
 
 
600
                    extentsPtr = &CollisionExtents[CE_ALIEN];
 
 
601
                    dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
 
 
602
                    sbPtr->DisplayBlock->extent.radius = 700;
 
 
603
                }
 
 
604
                break;
 
 
605
                case I_BehaviourMarinePlayer:
 
 
606
                {
 
 
607
                    extentsPtr = &CollisionExtents[CE_MARINE];
 
 
608
                    sbPtr->DisplayBlock->extent.radius = 700;
 
 
609
                }
 
 
610
                break;
 
 
611
                   case I_BehaviourAlien:
 
 
612
                {
 
 
613
                    extentsPtr = &CollisionExtents[CE_ALIEN];
 
 
614
                    dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
 
 
615
                    sbPtr->DisplayBlock->extent.radius = 2000;
 
 
616
                }
 
 
617
                break;
 
 
618
                case I_BehaviourCorpse:
 
 
619
                    extentsPtr = &CollisionExtents[CE_MARINE];
 
 
620
                    sbPtr->DisplayBlock->extent.radius = 700;
 
 
621
                default:
 
 
622
                break;
 
 
623
            }
 
 
624
        }
 
 
625
        default:
 
 
626
        break;
 
 
627
    }
 
 
628
 
 
 
629
    if (extentsPtr)
 
 
630
    {
 
 
631
        dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
 
 
632
 
 
 
633
        /* max X */
 
 
634
        objectVertices[0].vx = extentsPtr->CollisionRadius;
 
 
635
        objectVertices[1].vx = extentsPtr->CollisionRadius;
 
 
636
        objectVertices[2].vx = extentsPtr->CollisionRadius;
 
 
637
        objectVertices[3].vx = extentsPtr->CollisionRadius;
 
 
638
 
 
 
639
        /* min X */
 
 
640
        objectVertices[4].vx = -extentsPtr->CollisionRadius;
 
 
641
        objectVertices[5].vx = -extentsPtr->CollisionRadius;
 
 
642
        objectVertices[6].vx = -extentsPtr->CollisionRadius;
 
 
643
        objectVertices[7].vx = -extentsPtr->CollisionRadius;
 
 
644
 
 
 
645
        /* max Y */
 
 
646
        objectVertices[0].vy = extentsPtr->Bottom;
 
 
647
        objectVertices[1].vy = extentsPtr->Bottom;
 
 
648
        objectVertices[4].vy = extentsPtr->Bottom;
 
 
649
        objectVertices[5].vy = extentsPtr->Bottom;
 
 
650
 
 
 
651
        /* min Y */
 
 
652
        if(objectIsCrouching)
 
 
653
        {
 
 
654
            objectVertices[2].vy = extentsPtr->CrouchingTop;
 
 
655
            objectVertices[3].vy = extentsPtr->CrouchingTop;
 
 
656
            objectVertices[6].vy = extentsPtr->CrouchingTop;
 
 
657
            objectVertices[7].vy = extentsPtr->CrouchingTop;
 
 
658
        }
 
 
659
        else
 
 
660
        {
 
 
661
            objectVertices[2].vy = extentsPtr->StandingTop;
 
 
662
            objectVertices[3].vy = extentsPtr->StandingTop;
 
 
663
            objectVertices[6].vy = extentsPtr->StandingTop;
 
 
664
            objectVertices[7].vy = extentsPtr->StandingTop;
 
 
665
        }
 
 
666
 
 
 
667
        /* max Z */
 
 
668
        objectVertices[0].vz = extentsPtr->CollisionRadius;
 
 
669
        objectVertices[2].vz = extentsPtr->CollisionRadius;
 
 
670
        objectVertices[4].vz = extentsPtr->CollisionRadius;
 
 
671
        objectVertices[6].vz = extentsPtr->CollisionRadius;
 
 
672
 
 
 
673
        /* min Z */
 
 
674
        objectVertices[1].vz = -extentsPtr->CollisionRadius;
 
 
675
        objectVertices[3].vz = -extentsPtr->CollisionRadius;
 
 
676
        objectVertices[5].vz = -extentsPtr->CollisionRadius;
 
 
677
        objectVertices[7].vz = -extentsPtr->CollisionRadius;
 
 
678
    }
 
 
679
    else if(player)
 
 
680
    {
 
 
681
        objectVertices[0].vx = 600;
 
 
682
        objectVertices[1].vx = 600;
 
 
683
        objectVertices[2].vx = 600;
 
 
684
        objectVertices[3].vx = 600;
 
 
685
 
 
 
686
        objectVertices[4].vx = -600;
 
 
687
        objectVertices[5].vx = -600;
 
 
688
        objectVertices[6].vx = -600;
 
 
689
        objectVertices[7].vx = -600;
 
 
690
 
 
 
691
        objectVertices[0].vz = 600;
 
 
692
        objectVertices[2].vz = 600;
 
 
693
        objectVertices[4].vz = 600;
 
 
694
        objectVertices[6].vz = 600;
 
 
695
 
 
 
696
        objectVertices[1].vz = -600;
 
 
697
        objectVertices[3].vz = -600;
 
 
698
        objectVertices[5].vz = -600;
 
 
699
        objectVertices[7].vz = -600;
 
 
700
 
 
 
701
        // top
 
 
702
        objectVertices[2].vy = -2000;
 
 
703
        objectVertices[3].vy = -2000;
 
 
704
        objectVertices[6].vy = -2000;
 
 
705
        objectVertices[7].vy = -2000;
 
 
706
 
 
 
707
        // bottom
 
 
708
        objectVertices[0].vy = 0;
 
 
709
        objectVertices[1].vy = 0;
 
 
710
        objectVertices[4].vy = 0;
 
 
711
        objectVertices[5].vy = 0;
 
 
712
 
 
 
713
    }
 
 
714
    else /* make a cuboid from the shape's extent data */
 
 
715
    {
 
 
716
        int shapeMin, shapeMax;
 
 
717
 
 
 
718
        shapeMax = sbPtr->DisplayBlock->extent.max_x;
 
 
719
 
 
 
720
        if (shapeMax < MINIMUM_BOUNDINGBOX_EXTENT)
 
 
721
            shapeMax = MINIMUM_BOUNDINGBOX_EXTENT;
 
 
722
 
 
 
723
        objectVertices[0].vx = shapeMax;
 
 
724
        objectVertices[1].vx = shapeMax;
 
 
725
        objectVertices[2].vx = shapeMax;
 
 
726
        objectVertices[3].vx = shapeMax;
 
 
727
 
 
 
728
        shapeMin = sbPtr->DisplayBlock->extent.min_x;
 
 
729
 
 
 
730
        if (shapeMin > -MINIMUM_BOUNDINGBOX_EXTENT)
 
 
731
            shapeMin = -MINIMUM_BOUNDINGBOX_EXTENT;
 
 
732
 
 
 
733
        objectVertices[4].vx = shapeMin;
 
 
734
        objectVertices[5].vx = shapeMin;
 
 
735
        objectVertices[6].vx = shapeMin;
 
 
736
        objectVertices[7].vx = shapeMin;
 
 
737
 
 
 
738
        shapeMax = sbPtr->DisplayBlock->extent.max_y;
 
 
739
 
 
 
740
        if (shapeMax < MINIMUM_BOUNDINGBOX_EXTENT)
 
 
741
            shapeMax = MINIMUM_BOUNDINGBOX_EXTENT;
 
 
742
 
 
 
743
        objectVertices[0].vy = shapeMax;
 
 
744
        objectVertices[1].vy = shapeMax;
 
 
745
        objectVertices[4].vy = shapeMax;
 
 
746
        objectVertices[5].vy = shapeMax;
 
 
747
 
 
 
748
        shapeMin = sbPtr->DisplayBlock->extent.min_y;
 
 
749
 
 
 
750
        if (shapeMin > -MINIMUM_BOUNDINGBOX_EXTENT)
 
 
751
            shapeMin = -MINIMUM_BOUNDINGBOX_EXTENT;
 
 
752
 
 
 
753
        objectVertices[2].vy = shapeMin;
 
 
754
        objectVertices[3].vy = shapeMin;
 
 
755
        objectVertices[6].vy = shapeMin;
 
 
756
        objectVertices[7].vy = shapeMin;
 
 
757
 
 
 
758
        shapeMax = sbPtr->DisplayBlock->extent.max_z;
 
 
759
 
 
 
760
        if (shapeMax < MINIMUM_BOUNDINGBOX_EXTENT)
 
 
761
            shapeMax = MINIMUM_BOUNDINGBOX_EXTENT;
 
 
762
 
 
 
763
        objectVertices[0].vz = shapeMax;
 
 
764
        objectVertices[2].vz = shapeMax;
 
 
765
        objectVertices[4].vz = shapeMax;
 
 
766
        objectVertices[6].vz = shapeMax;
 
 
767
 
 
 
768
        shapeMin = sbPtr->DisplayBlock->extent.min_z;
 
 
769
 
 
 
770
        if (shapeMin > -MINIMUM_BOUNDINGBOX_EXTENT)
 
 
771
            shapeMin = -MINIMUM_BOUNDINGBOX_EXTENT;
 
 
772
 
 
 
773
        objectVertices[1].vz = shapeMin;
 
 
774
        objectVertices[3].vz = shapeMin;
 
 
775
        objectVertices[5].vz = shapeMin;
 
 
776
        objectVertices[7].vz = shapeMin;
 
 
777
    }
 
 
778
 
 
 
779
    /* translate cuboid into world space */
 
 
780
    VECTORCH objectPosition = sbPtr->DynPtr->Position;
 
 
781
    int i;
 
 
782
 
 
 
783
    for(i=0; i < 8; i++)
 
 
784
    {
 
 
785
        objectVertices[i].vx += objectPosition.vx;
 
 
786
        objectVertices[i].vy += objectPosition.vy;
 
 
787
        objectVertices[i].vz += objectPosition.vz;
 
 
788
    }
 
 
789
}
 
 
790
 
 
 
791
void AddEffectsOfForceGenerators(VECTORCH *positionPtr, VECTORCH *impulsePtr, int mass)
 
 
792
{
 
 
793
    int i;
 
 
794
 
 
 
795
    for(i=0; i < NumActiveBlocks; i++)
 
 
796
    {
 
 
797
        DISPLAYBLOCK *objectPtr = ActiveBlockList[i];
 
 
798
        STRATEGYBLOCK *sbPtr = objectPtr->ObStrategyBlock;
 
 
799
 
 
 
800
        if (sbPtr && sbPtr->type == I_BehaviourFan)
 
 
801
        {
 
 
802
             FAN_BEHAV_BLOCK *fanPtr = (FAN_BEHAV_BLOCK*)sbPtr->dataptr;
 
 
803
 
 
 
804
            if (fanPtr->wind_speed)
 
 
805
            {
 
 
806
                VECTORCH disp = sbPtr->DynPtr->Position;
 
 
807
                disp.vx -= positionPtr->vx;
 
 
808
                disp.vy -= positionPtr->vy;
 
 
809
                disp.vz -= positionPtr->vz;
 
 
810
 
 
 
811
                int mag = 16384 - Approximate3dMagnitude(&disp);
 
 
812
 
 
 
813
                if (mag < 0)
 
 
814
                    continue;
 
 
815
 
 
 
816
                if(MagnitudeOfCrossProduct(&disp, &fanPtr->fan_wind_direction) > objectPtr->extent.radius + 200)
 
 
817
                    continue;
 
 
818
 
 
 
819
                mag = MUL_FIXED(MUL_FIXED(mag*32*4*32, fanPtr->wind_speed), NormalFrameTime)/mass;
 
 
820
 
 
 
821
                impulsePtr->vx += MUL_FIXED(fanPtr->fan_wind_direction.vx, mag);
 
 
822
                impulsePtr->vy += MUL_FIXED(fanPtr->fan_wind_direction.vy, mag);
 
 
823
                impulsePtr->vz += MUL_FIXED(fanPtr->fan_wind_direction.vz, mag);
 
 
824
            }
 
 
825
 
 
 
826
            //printf("Fan acting upon object %d\n", fanPtr->wind_speed);
 
 
827
        }
 
 
828
    }
 
 
829
}
 
 
830
 
 
 
831
static int sort_dynamicobjectslist(const void *void_a, const void *void_b)
 
 
832
{
 
 
833
    const struct DynamicObjects * a = void_a;
 
 
834
    const struct DynamicObjects * b = void_b;
 
 
835
 
 
 
836
    return (a->valueOnWhichToSort < b->valueOnWhichToSort) ? -1 : (a->valueOnWhichToSort > b->valueOnWhichToSort);
 
 
837
}
 
 
838
 
 
 
839
static void UpdateDisplayBlockData(STRATEGYBLOCK *sbPtr)
 
 
840
{
 
 
841
    /* If the object associated with this strategyblock has a valid displayblock
 
 
842
       then update the data which has been changed by the objects movement. */
 
 
843
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
844
    DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock;
 
 
845
 
 
 
846
    dispPtr->ObWorld = dynPtr->Position;
 
 
847
 
 
 
848
    if (dynPtr->CollisionRadius)
 
 
849
    {
 
 
850
        int radius = dynPtr->CollisionRadius;
 
 
851
        dispPtr->ObWorld.vy -= radius;
 
 
852
        dispPtr->ObWorld.vx += MUL_FIXED(dynPtr->OrientMat.mat21, radius);
 
 
853
        dispPtr->ObWorld.vy += MUL_FIXED(dynPtr->OrientMat.mat22, radius);
 
 
854
        dispPtr->ObWorld.vz += MUL_FIXED(dynPtr->OrientMat.mat23, radius);
 
 
855
    }
 
 
856
 
 
 
857
    dispPtr->ObMat = dynPtr->OrientMat;
 
 
858
    dispPtr->ObEuler = dynPtr->OrientEuler;
 
 
859
 
 
 
860
    if ((CHEATMODE_TICKERTAPE == UserProfile.active_bonus) && (sbPtr->type == I_BehaviourAlien))
 
 
861
        PlayerPheromoneTrail(sbPtr->DynPtr);
 
 
862
 
 
 
863
    dynPtr->PrevOrientMat = dynPtr->OrientMat;
 
 
864
}
 
 
865
 
 
 
866
static void MakeDynamicBoundingBoxForObject(STRATEGYBLOCK *sbPtr, VECTORCH *worldOffsetPtr)
 
 
867
{
 
 
868
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
869
 
 
 
870
    DBBMaxX = dynPtr->ObjectVertices[0].vx - worldOffsetPtr->vx + COLLISION_GRANULARITY; 
 
 
871
    DBBMinX = dynPtr->ObjectVertices[7].vx - worldOffsetPtr->vx - COLLISION_GRANULARITY;
 
 
872
 
 
 
873
    DBBMaxY = dynPtr->ObjectVertices[0].vy - worldOffsetPtr->vy + COLLISION_GRANULARITY; 
 
 
874
    DBBMinY = dynPtr->ObjectVertices[7].vy - worldOffsetPtr->vy - COLLISION_GRANULARITY;
 
 
875
 
 
 
876
    DBBMaxZ = dynPtr->ObjectVertices[0].vz - worldOffsetPtr->vz + COLLISION_GRANULARITY;
 
 
877
    DBBMinZ = dynPtr->ObjectVertices[7].vz - worldOffsetPtr->vz - COLLISION_GRANULARITY; 
 
 
878
 
 
 
879
    if (dynPtr->Displacement.vx > 0)
 
 
880
        DBBMaxX += dynPtr->Displacement.vx;
 
 
881
    else
 
 
882
        DBBMinX += dynPtr->Displacement.vx;
 
 
883
 
 
 
884
    if (dynPtr->Displacement.vy > 0)
 
 
885
        DBBMaxY += dynPtr->Displacement.vy;
 
 
886
    else
 
 
887
        DBBMinY += dynPtr->Displacement.vy;
 
 
888
 
 
 
889
    if (dynPtr->Displacement.vz > 0)
 
 
890
        DBBMaxZ += dynPtr->Displacement.vz;
 
 
891
    else
 
 
892
        DBBMinZ += dynPtr->Displacement.vz;
 
 
893
}
 
 
894
 
 
 
895
static void MakeStaticBoundingBoxForNRBB(STRATEGYBLOCK *sbPtr)
 
 
896
{
 
 
897
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
898
 
 
 
899
    SBBMinX = dynPtr->ObjectVertices[7].vx - COLLISION_GRANULARITY * 16;
 
 
900
    SBBMaxX = dynPtr->ObjectVertices[0].vx + COLLISION_GRANULARITY * 16;
 
 
901
    SBBMinY = dynPtr->ObjectVertices[7].vy - COLLISION_GRANULARITY * 16;
 
 
902
    SBBMaxY = dynPtr->ObjectVertices[0].vy + COLLISION_GRANULARITY * 16;
 
 
903
    SBBMinZ = dynPtr->ObjectVertices[7].vz - COLLISION_GRANULARITY * 16;
 
 
904
    SBBMaxZ = dynPtr->ObjectVertices[0].vz + COLLISION_GRANULARITY * 16;
 
 
905
}
 
 
906
 
 
 
907
/*KJL****************************************************************************
 
 
908
* A function which takes a plane's normal and decides which axis to ignore when *
 
 
909
* projecting points on the plane into a 2D space.                               *
 
 
910
****************************************************************************KJL*/
 
 
911
static int AxisToIgnore(VECTORCH *normal)
 
 
912
{                              
 
 
913
    int x = abs(normal->vx);
 
 
914
    int y = abs(normal->vy);
 
 
915
    int z = abs(normal->vz);
 
 
916
 
 
 
917
    return (x > y) ? ((x > z) ? ix : iz) : (y > z) ? iy : iz;
 
 
918
}
 
 
919
 
 
 
920
static int NRBBProjectsOntoPolygon(DYNAMICSBLOCK *dynPtr, int vertexToPlaneDist[], struct ColPolyTag *polyPtr, const VECTORCH *projectionDirPtr)
 
 
921
{
 
 
922
    /* decide which 2d plane to project onto */
 
 
923
    int axisToIgnore = AxisToIgnore(&polyPtr->PolyNormal);
 
 
924
    int objMaxX,objMinX,objMaxY,objMinY,objMaxZ,objMinZ;
 
 
925
 
 
 
926
    if (axisToIgnore != ix)
 
 
927
    {
 
 
928
        int polyMax,polyMin;
 
 
929
 
 
 
930
        /* search x-coords of poly vertices for min and max */
 
 
931
        {
 
 
932
            int vertexNum = polyPtr->NumberOfVertices;
 
 
933
 
 
 
934
            polyMax = polyMin = polyPtr->PolyPoint[0].vx;
 
 
935
 
 
 
936
                do
 
 
937
                {
 
 
938
                    int x = polyPtr->PolyPoint[vertexNum].vx;
 
 
939
                    vertexNum--;
 
 
940
 
 
 
941
                    if (x > polyMax)
 
 
942
                        polyMax = x;
 
 
943
                    else if (x < polyMin)
 
 
944
                        polyMin = x;
 
 
945
 
 
 
946
                } while(vertexNum);
 
 
947
        }
 
 
948
 
 
 
949
        /* search x-coords of object vertices for min and max */
 
 
950
        {
 
 
951
            int i = 7; /* 8 vertices in a cuboid */
 
 
952
 
 
 
953
            objMaxX = objMinX = dynPtr->ObjectVertices[0].vx + MUL_FIXED(vertexToPlaneDist[0],projectionDirPtr->vx);
 
 
954
 
 
 
955
            do
 
 
956
            {
 
 
957
                int x = dynPtr->ObjectVertices[i].vx + MUL_FIXED(vertexToPlaneDist[i],projectionDirPtr->vx);
 
 
958
 
 
 
959
                if (x > objMaxX)
 
 
960
                    objMaxX = x;
 
 
961
                else if (x < objMinX)
 
 
962
                    objMinX = x;
 
 
963
 
 
 
964
            } while(--i);
 
 
965
        }
 
 
966
 
 
 
967
        /* test to see if object & polygon overlap */
 
 
968
        if (objMaxX < polyMin || objMinX > polyMax)
 
 
969
            return 0;
 
 
970
    }
 
 
971
 
 
 
972
    if (axisToIgnore != iz)
 
 
973
    {
 
 
974
        int polyMax,polyMin;
 
 
975
 
 
 
976
        /* search z-coords of poly vertices for min and max */
 
 
977
        {
 
 
978
            int vertexNum = polyPtr->NumberOfVertices;
 
 
979
 
 
 
980
            polyMax = polyMin = polyPtr->PolyPoint[0].vz;
 
 
981
 
 
 
982
            do
 
 
983
            {
 
 
984
                int z = polyPtr->PolyPoint[vertexNum].vz;
 
 
985
                vertexNum--;
 
 
986
 
 
 
987
                if (z > polyMax)
 
 
988
                    polyMax = z;
 
 
989
                else if (z < polyMin)
 
 
990
                    polyMin = z;
 
 
991
 
 
 
992
            } while(vertexNum);
 
 
993
        }        
 
 
994
 
 
 
995
        /* search z-coords of object vertices for min and max */
 
 
996
        {
 
 
997
            int i = 7; /* 8 vertices in a cuboid */
 
 
998
 
 
 
999
            objMaxZ = objMinZ = dynPtr->ObjectVertices[0].vz + MUL_FIXED(vertexToPlaneDist[0],projectionDirPtr->vz);
 
 
1000
 
 
 
1001
            do
 
 
1002
            {
 
 
1003
                int z = dynPtr->ObjectVertices[i].vz + MUL_FIXED(vertexToPlaneDist[i],projectionDirPtr->vz);
 
 
1004
 
 
 
1005
                if (z > objMaxZ)
 
 
1006
                    objMaxZ = z;
 
 
1007
                else if (z < objMinZ)
 
 
1008
                    objMinZ = z;
 
 
1009
 
 
 
1010
            } while(--i);
 
 
1011
        }
 
 
1012
 
 
 
1013
        /* test to see if object & polygon overlap */
 
 
1014
        if (objMaxZ < polyMin || objMinZ > polyMax)
 
 
1015
            return 0;
 
 
1016
    }
 
 
1017
 
 
 
1018
    if (axisToIgnore != iy)
 
 
1019
    {
 
 
1020
        int polyMax,polyMin;
 
 
1021
 
 
 
1022
        /* search y-coords of poly vertices for min and max */
 
 
1023
        {
 
 
1024
            int vertexNum = polyPtr->NumberOfVertices;
 
 
1025
 
 
 
1026
            polyMax = polyMin = polyPtr->PolyPoint[0].vy;
 
 
1027
 
 
 
1028
            do
 
 
1029
            {
 
 
1030
                int y = polyPtr->PolyPoint[vertexNum].vy;
 
 
1031
                vertexNum--;
 
 
1032
 
 
 
1033
                if (y > polyMax)
 
 
1034
                    polyMax = y;
 
 
1035
                else if (y < polyMin)
 
 
1036
                    polyMin = y;
 
 
1037
 
 
 
1038
            } while(vertexNum);
 
 
1039
        }
 
 
1040
 
 
 
1041
        /* search y-coords of object vertices for min and max */
 
 
1042
        {
 
 
1043
            int i = 7; /* 8 vertices in a cuboid */
 
 
1044
 
 
 
1045
            objMaxY = objMinY = dynPtr->ObjectVertices[0].vy + MUL_FIXED(vertexToPlaneDist[0],projectionDirPtr->vy);
 
 
1046
 
 
 
1047
            do
 
 
1048
            {
 
 
1049
                int y = dynPtr->ObjectVertices[i].vy + MUL_FIXED(vertexToPlaneDist[i],projectionDirPtr->vy);
 
 
1050
 
 
 
1051
                if (y > objMaxY)
 
 
1052
                    objMaxY = y;
 
 
1053
                else if (y < objMinY)
 
 
1054
                    objMinY = y;
 
 
1055
 
 
 
1056
            } while(--i);
 
 
1057
        }
 
 
1058
 
 
 
1059
        /* test to see if object & polygon overlap */
 
 
1060
        if (objMaxY < polyMin || objMinY > polyMax)
 
 
1061
            return 0;
 
 
1062
    }
 
 
1063
 
 
 
1064
    /* test for triangle/rectangle overlap */
 
 
1065
    /* traingle vertices are stored anticlockwise! */
 
 
1066
    if (polyPtr->NumberOfVertices == 3)
 
 
1067
    {
 
 
1068
        if(axisToIgnore == ix)
 
 
1069
        {
 
 
1070
            VECTORCH n;
 
 
1071
 
 
 
1072
            n.vy = (polyPtr->PolyPoint[1].vz - polyPtr->PolyPoint[0].vz);
 
 
1073
            n.vz = -(polyPtr->PolyPoint[1].vy - polyPtr->PolyPoint[0].vy);
 
 
1074
 
 
 
1075
            if(polyPtr->PolyNormal.vx < 0)
 
 
1076
            {
 
 
1077
                n.vy = -n.vy;
 
 
1078
                n.vz = -n.vz;
 
 
1079
            }
 
 
1080
 
 
 
1081
            {
 
 
1082
                int d1 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1083
                int d2 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1084
                int d3 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1085
                int d4 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1086
 
 
 
1087
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1088
                    return 0;
 
 
1089
            }
 
 
1090
 
 
 
1091
            n.vy = (polyPtr->PolyPoint[2].vz - polyPtr->PolyPoint[1].vz);
 
 
1092
            n.vz = -(polyPtr->PolyPoint[2].vy - polyPtr->PolyPoint[1].vy);
 
 
1093
 
 
 
1094
            if(polyPtr->PolyNormal.vx < 0)
 
 
1095
            {
 
 
1096
                n.vy = -n.vy;
 
 
1097
                n.vz = -n.vz;
 
 
1098
            }
 
 
1099
 
 
 
1100
            {
 
 
1101
                int d1 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1102
                int d2 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1103
                int d3 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1104
                int d4 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1105
 
 
 
1106
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1107
                    return 0;
 
 
1108
            }
 
 
1109
 
 
 
1110
            n.vy = (polyPtr->PolyPoint[0].vz - polyPtr->PolyPoint[2].vz);
 
 
1111
            n.vz = -(polyPtr->PolyPoint[0].vy - polyPtr->PolyPoint[2].vy);
 
 
1112
 
 
 
1113
            if(polyPtr->PolyNormal.vx < 0)
 
 
1114
            {
 
 
1115
                n.vy = -n.vy;
 
 
1116
                n.vz = -n.vz;
 
 
1117
            }
 
 
1118
 
 
 
1119
            {
 
 
1120
                int d1 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1121
                int d2 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1122
                int d3 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1123
                int d4 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1124
 
 
 
1125
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1126
                    return 0;
 
 
1127
            }
 
 
1128
 
 
 
1129
        }
 
 
1130
        else if(axisToIgnore == iy)
 
 
1131
        {
 
 
1132
            VECTORCH n;
 
 
1133
 
 
 
1134
            n.vx = (polyPtr->PolyPoint[1].vz - polyPtr->PolyPoint[0].vz);
 
 
1135
            n.vz = -(polyPtr->PolyPoint[1].vx - polyPtr->PolyPoint[0].vx);
 
 
1136
 
 
 
1137
            if(polyPtr->PolyNormal.vy > 0)
 
 
1138
            {
 
 
1139
                n.vx = -n.vx;
 
 
1140
                n.vz = -n.vz;
 
 
1141
            }
 
 
1142
 
 
 
1143
            {
 
 
1144
                int d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1145
                int d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1146
                int d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1147
                int d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1148
 
 
 
1149
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1150
                    return 0;
 
 
1151
            }
 
 
1152
 
 
 
1153
            n.vx = (polyPtr->PolyPoint[2].vz - polyPtr->PolyPoint[1].vz);
 
 
1154
            n.vz = -(polyPtr->PolyPoint[2].vx - polyPtr->PolyPoint[1].vx);
 
 
1155
 
 
 
1156
            if(polyPtr->PolyNormal.vy > 0)
 
 
1157
            {
 
 
1158
                n.vx = -n.vx;
 
 
1159
                n.vz = -n.vz;
 
 
1160
            }
 
 
1161
 
 
 
1162
            {
 
 
1163
                int d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1164
                int d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1165
                int d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1166
                int d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1167
 
 
 
1168
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1169
                    return 0;
 
 
1170
            }
 
 
1171
 
 
 
1172
            n.vx = (polyPtr->PolyPoint[0].vz - polyPtr->PolyPoint[2].vz);
 
 
1173
            n.vz = -(polyPtr->PolyPoint[0].vx - polyPtr->PolyPoint[2].vx);
 
 
1174
 
 
 
1175
            if(polyPtr->PolyNormal.vy > 0)
 
 
1176
            {
 
 
1177
                n.vx = -n.vx;
 
 
1178
                n.vz = -n.vz;
 
 
1179
            }
 
 
1180
 
 
 
1181
            {
 
 
1182
                int d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1183
                int d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1184
                int d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1185
                int d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1186
 
 
 
1187
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1188
                    return 0;
 
 
1189
            }
 
 
1190
        }
 
 
1191
        else if(axisToIgnore == iz)
 
 
1192
        {
 
 
1193
            VECTORCH n;
 
 
1194
 
 
 
1195
            n.vx = (polyPtr->PolyPoint[1].vy - polyPtr->PolyPoint[0].vy);
 
 
1196
            n.vy = -(polyPtr->PolyPoint[1].vx - polyPtr->PolyPoint[0].vx);
 
 
1197
 
 
 
1198
            if(polyPtr->PolyNormal.vz < 0)
 
 
1199
            {
 
 
1200
                n.vx = -n.vx;
 
 
1201
                n.vy = -n.vy;
 
 
1202
            }
 
 
1203
 
 
 
1204
            {
 
 
1205
                int d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
 
 
1206
                int d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
 
 
1207
                int d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
 
 
1208
                int d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
 
 
1209
 
 
 
1210
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1211
                    return 0;
 
 
1212
            }
 
 
1213
 
 
 
1214
            n.vx = (polyPtr->PolyPoint[2].vy - polyPtr->PolyPoint[1].vy);
 
 
1215
            n.vy = -(polyPtr->PolyPoint[2].vx - polyPtr->PolyPoint[1].vx);
 
 
1216
 
 
 
1217
            if(polyPtr->PolyNormal.vz < 0)
 
 
1218
            {
 
 
1219
                n.vx = -n.vx;
 
 
1220
                n.vy = -n.vy;
 
 
1221
            }
 
 
1222
 
 
 
1223
            {
 
 
1224
                int d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
 
 
1225
                int d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
 
 
1226
                int d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
 
 
1227
                int d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
 
 
1228
 
 
 
1229
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1230
                    return 0;
 
 
1231
            }
 
 
1232
 
 
 
1233
            n.vx = (polyPtr->PolyPoint[0].vy - polyPtr->PolyPoint[2].vy);
 
 
1234
            n.vy = -(polyPtr->PolyPoint[0].vx - polyPtr->PolyPoint[2].vx);
 
 
1235
 
 
 
1236
            if(polyPtr->PolyNormal.vz < 0)
 
 
1237
            {
 
 
1238
                n.vx = -n.vx;
 
 
1239
                n.vy = -n.vy;
 
 
1240
            }
 
 
1241
 
 
 
1242
            {
 
 
1243
                int d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
 
 
1244
                int d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
 
 
1245
                int d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
 
 
1246
                int d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
 
 
1247
 
 
 
1248
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1249
                    return 0;
 
 
1250
            }
 
 
1251
        }
 
 
1252
    }
 
 
1253
    else
 
 
1254
    {
 
 
1255
        if(axisToIgnore == ix)
 
 
1256
        {
 
 
1257
            VECTORCH n;
 
 
1258
 
 
 
1259
            n.vy = (polyPtr->PolyPoint[1].vz - polyPtr->PolyPoint[0].vz);
 
 
1260
            n.vz = -(polyPtr->PolyPoint[1].vy - polyPtr->PolyPoint[0].vy);
 
 
1261
 
 
 
1262
            if(polyPtr->PolyNormal.vx < 0)
 
 
1263
            {
 
 
1264
                n.vy = -n.vy;
 
 
1265
                n.vz = -n.vz;
 
 
1266
            }
 
 
1267
 
 
 
1268
            {
 
 
1269
                int d1 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1270
                int d2 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1271
                int d3 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1272
                int d4 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1273
 
 
 
1274
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1275
                    return 0;
 
 
1276
            }
 
 
1277
 
 
 
1278
            n.vy = (polyPtr->PolyPoint[2].vz - polyPtr->PolyPoint[1].vz);
 
 
1279
            n.vz = -(polyPtr->PolyPoint[2].vy - polyPtr->PolyPoint[1].vy);
 
 
1280
 
 
 
1281
            if(polyPtr->PolyNormal.vx < 0)
 
 
1282
            {
 
 
1283
                n.vy = -n.vy;
 
 
1284
                n.vz = -n.vz;
 
 
1285
            }
 
 
1286
 
 
 
1287
            {
 
 
1288
                int d1 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1289
                int d2 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1290
                int d3 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1291
                int d4 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1292
 
 
 
1293
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1294
                    return 0;
 
 
1295
            }
 
 
1296
 
 
 
1297
            n.vy = (polyPtr->PolyPoint[3].vz - polyPtr->PolyPoint[2].vz);
 
 
1298
            n.vz = -(polyPtr->PolyPoint[3].vy - polyPtr->PolyPoint[2].vy);
 
 
1299
 
 
 
1300
            if(polyPtr->PolyNormal.vx < 0)
 
 
1301
            {
 
 
1302
                n.vy = -n.vy;
 
 
1303
                n.vz = -n.vz;
 
 
1304
            }
 
 
1305
 
 
 
1306
            {
 
 
1307
                int d1 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1308
                int d2 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1309
                int d3 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1310
                int d4 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1311
 
 
 
1312
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1313
                    return 0;
 
 
1314
            }
 
 
1315
 
 
 
1316
            n.vy = (polyPtr->PolyPoint[0].vz - polyPtr->PolyPoint[3].vz);
 
 
1317
            n.vz = -(polyPtr->PolyPoint[0].vy - polyPtr->PolyPoint[3].vy);
 
 
1318
 
 
 
1319
            if(polyPtr->PolyNormal.vx < 0)
 
 
1320
            {
 
 
1321
                n.vy = -n.vy;
 
 
1322
                n.vz = -n.vz;
 
 
1323
            }
 
 
1324
 
 
 
1325
            {
 
 
1326
                int d1 = (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
 
 
1327
                int d2 = (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
 
 
1328
                int d3 = (objMinY-polyPtr->PolyPoint[3].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
 
 
1329
                int d4 = (objMinY-polyPtr->PolyPoint[3].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
 
 
1330
 
 
 
1331
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1332
                    return 0;
 
 
1333
            }
 
 
1334
        }
 
 
1335
        else if(axisToIgnore == iy)
 
 
1336
        {
 
 
1337
            VECTORCH n;
 
 
1338
 
 
 
1339
            n.vx = (polyPtr->PolyPoint[1].vz - polyPtr->PolyPoint[0].vz);
 
 
1340
            n.vz = -(polyPtr->PolyPoint[1].vx - polyPtr->PolyPoint[0].vx);
 
 
1341
 
 
 
1342
            if(polyPtr->PolyNormal.vy > 0)
 
 
1343
            {
 
 
1344
                n.vx = -n.vx;
 
 
1345
                n.vz = -n.vz;
 
 
1346
            }
 
 
1347
 
 
 
1348
            {
 
 
1349
                int d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1350
                int d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1351
                int d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1352
                int d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
 
 
1353
 
 
 
1354
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1355
                    return 0;
 
 
1356
            }
 
 
1357
 
 
 
1358
            n.vx = (polyPtr->PolyPoint[2].vz - polyPtr->PolyPoint[1].vz);
 
 
1359
            n.vz = -(polyPtr->PolyPoint[2].vx - polyPtr->PolyPoint[1].vx);
 
 
1360
 
 
 
1361
            if(polyPtr->PolyNormal.vy > 0)
 
 
1362
            {
 
 
1363
                n.vx = -n.vx;
 
 
1364
                n.vz = -n.vz;
 
 
1365
            }
 
 
1366
 
 
 
1367
            {
 
 
1368
                int d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1369
                int d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1370
                int d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1371
                int d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
 
 
1372
 
 
 
1373
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1374
                    return 0;
 
 
1375
            }
 
 
1376
 
 
 
1377
            n.vx = (polyPtr->PolyPoint[3].vz - polyPtr->PolyPoint[2].vz);
 
 
1378
            n.vz = -(polyPtr->PolyPoint[3].vx - polyPtr->PolyPoint[2].vx);
 
 
1379
 
 
 
1380
            if(polyPtr->PolyNormal.vy > 0)
 
 
1381
            {
 
 
1382
                n.vx = -n.vx;
 
 
1383
                n.vz = -n.vz;
 
 
1384
            }
 
 
1385
 
 
 
1386
            {
 
 
1387
                int d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1388
                int d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1389
                int d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1390
                int d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
 
 
1391
 
 
 
1392
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1393
                    return 0;
 
 
1394
            }
 
 
1395
 
 
 
1396
            n.vx = (polyPtr->PolyPoint[0].vz - polyPtr->PolyPoint[3].vz);
 
 
1397
            n.vz = -(polyPtr->PolyPoint[0].vx - polyPtr->PolyPoint[3].vx);
 
 
1398
 
 
 
1399
            if(polyPtr->PolyNormal.vy > 0)
 
 
1400
            {
 
 
1401
                n.vx = -n.vx;
 
 
1402
                n.vz = -n.vz;
 
 
1403
            }
 
 
1404
 
 
 
1405
            {
 
 
1406
                int d1 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
 
 
1407
                int d2 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
 
 
1408
                int d3 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
 
 
1409
                int d4 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
 
 
1410
 
 
 
1411
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1412
                    return 0;
 
 
1413
            }
 
 
1414
        }
 
 
1415
        else if(axisToIgnore == iz)
 
 
1416
        {
 
 
1417
            VECTORCH n;
 
 
1418
 
 
 
1419
            n.vx = (polyPtr->PolyPoint[1].vy - polyPtr->PolyPoint[0].vy);
 
 
1420
            n.vy = -(polyPtr->PolyPoint[1].vx - polyPtr->PolyPoint[0].vx);
 
 
1421
 
 
 
1422
            if(polyPtr->PolyNormal.vz < 0)
 
 
1423
            {
 
 
1424
                n.vx = -n.vx;
 
 
1425
                n.vy = -n.vy;
 
 
1426
            }
 
 
1427
 
 
 
1428
            {
 
 
1429
                int d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
 
 
1430
                int d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
 
 
1431
                int d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
 
 
1432
                int d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
 
 
1433
 
 
 
1434
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1435
                    return 0;
 
 
1436
            }
 
 
1437
 
 
 
1438
            n.vx = (polyPtr->PolyPoint[2].vy - polyPtr->PolyPoint[1].vy);
 
 
1439
            n.vy = -(polyPtr->PolyPoint[2].vx - polyPtr->PolyPoint[1].vx);
 
 
1440
 
 
 
1441
            if(polyPtr->PolyNormal.vz < 0)
 
 
1442
            {
 
 
1443
                n.vx = -n.vx;
 
 
1444
                n.vy = -n.vy;
 
 
1445
            }
 
 
1446
 
 
 
1447
            {
 
 
1448
                int d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
 
 
1449
                int d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
 
 
1450
                int d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
 
 
1451
                int d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
 
 
1452
 
 
 
1453
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1454
                    return 0;
 
 
1455
            }
 
 
1456
 
 
 
1457
            n.vx = (polyPtr->PolyPoint[3].vy - polyPtr->PolyPoint[2].vy);
 
 
1458
            n.vy = -(polyPtr->PolyPoint[3].vx - polyPtr->PolyPoint[2].vx);
 
 
1459
 
 
 
1460
            if(polyPtr->PolyNormal.vz < 0)
 
 
1461
            {
 
 
1462
                n.vx = -n.vx;
 
 
1463
                n.vy = -n.vy;
 
 
1464
            }
 
 
1465
 
 
 
1466
            {
 
 
1467
                int d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
 
 
1468
                int d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
 
 
1469
                int d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
 
 
1470
                int d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
 
 
1471
 
 
 
1472
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1473
                    return 0;
 
 
1474
            }
 
 
1475
 
 
 
1476
            n.vx = (polyPtr->PolyPoint[0].vy - polyPtr->PolyPoint[3].vy);
 
 
1477
            n.vy = -(polyPtr->PolyPoint[0].vx - polyPtr->PolyPoint[3].vx);
 
 
1478
 
 
 
1479
            if(polyPtr->PolyNormal.vz < 0)
 
 
1480
            {
 
 
1481
                n.vx = -n.vx;
 
 
1482
                n.vy = -n.vy;
 
 
1483
            }
 
 
1484
 
 
 
1485
            {
 
 
1486
                int d1 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy;
 
 
1487
                int d2 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinY-polyPtr->PolyPoint[3].vy)*n.vy;
 
 
1488
                int d3 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy;
 
 
1489
                int d4 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinY-polyPtr->PolyPoint[3].vy)*n.vy;
 
 
1490
 
 
 
1491
                if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0)
 
 
1492
                    return 0;
 
 
1493
            }
 
 
1494
        }
 
 
1495
    }
 
 
1496
 
 
 
1497
return 1;
 
 
1498
}
 
 
1499
 
 
 
1500
static void TestShapeWithDynamicBoundingBox(DISPLAYBLOCK *objectPtr, DYNAMICSBLOCK *mainDynPtr)
 
 
1501
{
 
 
1502
    int needToRotate = 0;
 
 
1503
 
 
 
1504
    /* KJL 10:58:22 24/11/98 - If the object is a static object rather than a module,
 
 
1505
    we'll need to rotate the polygons into world-space */
 
 
1506
 
 
 
1507
       if (objectPtr->ObStrategyBlock)
 
 
1508
    {
 
 
1509
        DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
 
 
1510
 
 
 
1511
        if ((NULL != dynPtr) && dynPtr->IsStatic)
 
 
1512
            needToRotate = 1;
 
 
1513
    }
 
 
1514
 
 
 
1515
    /* okay, let's setup the shape's data and access the first poly */
 
 
1516
    int numberOfItems = SetupPolygonAccess(objectPtr);
 
 
1517
 
 
 
1518
    /* go through polys looking for those which intersect with the bounding box */
 
 
1519
      while(numberOfItems--)
 
 
1520
    {
 
 
1521
        int *itemPtr = *(ItemArrayPtr++);
 
 
1522
        PolyheaderPtr = (POLYHEADER *) itemPtr;
 
 
1523
 
 
 
1524
        if (mainDynPtr->IgnoresNotVisPolys && (PolyheaderPtr->PolyFlags & iflag_notvis) && !(PolyheaderPtr->PolyFlags &
iflag_mirror))
 
 
1525
                continue;
 
 
1526
 
 
 
1527
        GetPolygonVertices(CollisionPolysPtr);
 
 
1528
 
 
 
1529
        if (needToRotate)
 
 
1530
        {
 
 
1531
            int i = CollisionPolysPtr->NumberOfVertices;    
 
 
1532
            VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
 
 
1533
 
 
 
1534
            do
 
 
1535
            {    
 
 
1536
                RotateVector(polyVertexPtr, &objectPtr->ObMat);
 
 
1537
                polyVertexPtr++;
 
 
1538
 
 
 
1539
            } while(--i);
 
 
1540
        }
 
 
1541
 
 
 
1542
        {
 
 
1543
            VECTORCH *vertices = CollisionPolysPtr->PolyPoint;
 
 
1544
 
 
 
1545
            if (CollisionPolysPtr->NumberOfVertices == 4)
 
 
1546
            {
 
 
1547
                if (vertices[0].vy < DBBMinY)
 
 
1548
                    if (vertices[1].vy < DBBMinY) 
 
 
1549
                        if (vertices[2].vy < DBBMinY) 
 
 
1550
                            if (vertices[3].vy < DBBMinY) 
 
 
1551
                                continue;
 
 
1552
 
 
 
1553
                if (vertices[0].vx < DBBMinX)
 
 
1554
                    if (vertices[1].vx < DBBMinX)
 
 
1555
                        if (vertices[2].vx < DBBMinX)
 
 
1556
                            if (vertices[3].vx < DBBMinX) 
 
 
1557
                                continue;
 
 
1558
 
 
 
1559
                if (vertices[0].vx > DBBMaxX) 
 
 
1560
                    if (vertices[1].vx > DBBMaxX) 
 
 
1561
                        if (vertices[2].vx > DBBMaxX) 
 
 
1562
                            if (vertices[3].vx > DBBMaxX) 
 
 
1563
                                continue;
 
 
1564
 
 
 
1565
                if (vertices[0].vz < DBBMinZ) 
 
 
1566
                    if (vertices[1].vz < DBBMinZ) 
 
 
1567
                        if (vertices[2].vz < DBBMinZ) 
 
 
1568
                            if (vertices[3].vz < DBBMinZ) 
 
 
1569
                                continue;
 
 
1570
 
 
 
1571
                if (vertices[0].vz > DBBMaxZ) 
 
 
1572
                    if (vertices[1].vz > DBBMaxZ) 
 
 
1573
                        if (vertices[2].vz > DBBMaxZ) 
 
 
1574
                            if (vertices[3].vz > DBBMaxZ) 
 
 
1575
                                continue;
 
 
1576
 
 
 
1577
                if (vertices[0].vy > DBBMaxY) 
 
 
1578
                    if (vertices[1].vy > DBBMaxY) 
 
 
1579
                        if (vertices[2].vy > DBBMaxY) 
 
 
1580
                            if (vertices[3].vy > DBBMaxY) 
 
 
1581
                                continue;
 
 
1582
            }
 
 
1583
            else
 
 
1584
            {
 
 
1585
                if (vertices[0].vy < DBBMinY)
 
 
1586
                    if (vertices[1].vy < DBBMinY) 
 
 
1587
                        if (vertices[2].vy < DBBMinY) 
 
 
1588
                            continue;
 
 
1589
 
 
 
1590
                if (vertices[0].vx < DBBMinX) 
 
 
1591
                    if (vertices[1].vx < DBBMinX) 
 
 
1592
                        if (vertices[2].vx < DBBMinX) 
 
 
1593
                            continue;
 
 
1594
 
 
 
1595
                if (vertices[0].vx > DBBMaxX) 
 
 
1596
                    if (vertices[1].vx > DBBMaxX) 
 
 
1597
                            if (vertices[2].vx > DBBMaxX) 
 
 
1598
                            continue;
 
 
1599
 
 
 
1600
                if (vertices[0].vz < DBBMinZ) 
 
 
1601
                    if (vertices[1].vz < DBBMinZ) 
 
 
1602
                        if (vertices[2].vz < DBBMinZ) 
 
 
1603
                            continue;
 
 
1604
 
 
 
1605
                if (vertices[0].vz > DBBMaxZ) 
 
 
1606
                    if (vertices[1].vz > DBBMaxZ) 
 
 
1607
                            if (vertices[2].vz > DBBMaxZ) 
 
 
1608
                            continue;
 
 
1609
 
 
 
1610
                if (vertices[0].vy > DBBMaxY) 
 
 
1611
                    if (vertices[1].vy > DBBMaxY) 
 
 
1612
                        if (vertices[2].vy > DBBMaxY) 
 
 
1613
                            continue;
 
 
1614
            }
 
 
1615
        }
 
 
1616
 
 
 
1617
        /* add object's world space coords to vertices */
 
 
1618
        {
 
 
1619
            int i = CollisionPolysPtr->NumberOfVertices;    
 
 
1620
            VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
 
 
1621
 
 
 
1622
            do
 
 
1623
            {    
 
 
1624
                polyVertexPtr->vx += objectPtr->ObWorld.vx;
 
 
1625
                polyVertexPtr->vy += objectPtr->ObWorld.vy;
 
 
1626
                polyVertexPtr->vz += objectPtr->ObWorld.vz;
 
 
1627
                polyVertexPtr++;
 
 
1628
 
 
 
1629
            } while(--i);
 
 
1630
        }
 
 
1631
 
 
 
1632
        /* get the poly's normal */
 
 
1633
        GetPolygonNormal(CollisionPolysPtr);
 
 
1634
 
 
 
1635
        if (needToRotate)
 
 
1636
            RotateVector(&CollisionPolysPtr->PolyNormal, &objectPtr->ObMat);
 
 
1637
 
 
 
1638
        CollisionPolysPtr->ParentObject = objectPtr;
 
 
1639
 
 
 
1640
        CollisionPolysPtr++;
 
 
1641
        NumberOfCollisionPolys++;
 
 
1642
        /* ran out of space? */
 
 
1643
        assert(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
 
 
1644
 
 
 
1645
        if (PolyheaderPtr->PolyFlags & iflag_no_bfc)
 
 
1646
        {
 
 
1647
            CollisionPolysPtr->NumberOfVertices = (CollisionPolysPtr-1)->NumberOfVertices;
 
 
1648
 
 
 
1649
            if(CollisionPolysPtr->NumberOfVertices == 3)
 
 
1650
            {
 
 
1651
                CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[2];
 
 
1652
                CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[1];
 
 
1653
                CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[0];
 
 
1654
            }
 
 
1655
            else
 
 
1656
            {
 
 
1657
                CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[3];
 
 
1658
                CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[2];
 
 
1659
                CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[1];
 
 
1660
                CollisionPolysPtr->PolyPoint[3] = (CollisionPolysPtr-1)->PolyPoint[0];
 
 
1661
            }
 
 
1662
 
 
 
1663
            CollisionPolysPtr->PolyNormal.vx = -(CollisionPolysPtr-1)->PolyNormal.vx;
 
 
1664
            CollisionPolysPtr->PolyNormal.vy = -(CollisionPolysPtr-1)->PolyNormal.vy;
 
 
1665
            CollisionPolysPtr->PolyNormal.vz = -(CollisionPolysPtr-1)->PolyNormal.vz;
 
 
1666
            CollisionPolysPtr->ParentObject = objectPtr;
 
 
1667
 
 
 
1668
            CollisionPolysPtr++;
 
 
1669
            NumberOfCollisionPolys++;
 
 
1670
            /* ran out of space? */
 
 
1671
            assert(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
 
 
1672
        }
 
 
1673
    }
 
 
1674
}
 
 
1675
 
 
 
1676
static int SphereProjectOntoPoly(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, VECTORCH *projectedPosition)
 
 
1677
{
 
 
1678
    /* decide which 2d plane to project onto */
 
 
1679
    int axisToIgnore = AxisToIgnore(&polyPtr->PolyNormal);
 
 
1680
 
 
 
1681
    if (axisToIgnore != ix)
 
 
1682
    {
 
 
1683
        int vertexNum = polyPtr->NumberOfVertices;
 
 
1684
        int polyMax = polyPtr->PolyPoint[0].vx;
 
 
1685
        int polyMin = polyMax;
 
 
1686
 
 
 
1687
        /* search x-coords of poly vertices for min and max */
 
 
1688
        do
 
 
1689
        {
 
 
1690
            int x = polyPtr->PolyPoint[vertexNum].vx;
 
 
1691
            vertexNum--;
 
 
1692
 
 
 
1693
            if (x > polyMax)
 
 
1694
                polyMax = x;
 
 
1695
            else if (x < polyMin)
 
 
1696
                polyMin = x;
 
 
1697
 
 
 
1698
        } while(vertexNum);
 
 
1699
 
 
 
1700
        /* test to see if object & polygon overlap */
 
 
1701
        if (projectedPosition->vx + dynPtr->CollisionRadius < polyMin || projectedPosition->vx - dynPtr->CollisionRadius > polyMax)
 
 
1702
            return 0;
 
 
1703
    }
 
 
1704
 
 
 
1705
    if (axisToIgnore != iz)
 
 
1706
    {
 
 
1707
        int vertexNum = polyPtr->NumberOfVertices;
 
 
1708
        int polyMax = polyPtr->PolyPoint[0].vz;
 
 
1709
        int polyMin = polyMax;
 
 
1710
 
 
 
1711
        /* search z-coords of poly vertices for min and max */
 
 
1712
            do
 
 
1713
            {
 
 
1714
                int  z = polyPtr->PolyPoint[vertexNum].vz;
 
 
1715
            vertexNum--;
 
 
1716
 
 
 
1717
                if (z > polyMax)
 
 
1718
                polyMax = z;
 
 
1719
                else if (z < polyMin)
 
 
1720
                polyMin = z;
 
 
1721
 
 
 
1722
            } while(vertexNum);
 
 
1723
 
 
 
1724
        /* test to see if object & polygon overlap */
 
 
1725
        if (projectedPosition->vz + dynPtr->CollisionRadius < polyMin || projectedPosition->vz - dynPtr->CollisionRadius > polyMax)
 
 
1726
                return 0;
 
 
1727
    }
 
 
1728
 
 
 
1729
    if (axisToIgnore != iy)
 
 
1730
    {
 
 
1731
        int vertexNum = polyPtr->NumberOfVertices;
 
 
1732
        int polyMax = polyPtr->PolyPoint[0].vy;
 
 
1733
        int polyMin = polyMax;
 
 
1734
 
 
 
1735
        /* search y-coords of poly vertices for min and max */
 
 
1736
        do
 
 
1737
        {
 
 
1738
            int y = polyPtr->PolyPoint[vertexNum].vy;
 
 
1739
            vertexNum--;
 
 
1740
 
 
 
1741
            if (y > polyMax)
 
 
1742
                polyMax = y;
 
 
1743
            else if (y < polyMin)
 
 
1744
                polyMin = y;
 
 
1745
 
 
 
1746
        } while(vertexNum);
 
 
1747
 
 
 
1748
        /* test to see if object & polygon overlap */
 
 
1749
        if (projectedPosition->vy + dynPtr->CollisionRadius < polyMin || projectedPosition->vy - dynPtr->CollisionRadius > polyMax)
 
 
1750
                return 0;
 
 
1751
 
 
 
1752
        /* test for a 'step' in front of object */
 
 
1753
        {
 
 
1754
            int heightOfStep = projectedPosition->vy + dynPtr->CollisionRadius - polyMin;  /* y-axis is +ve downwards, remember */
 
 
1755
 
 
 
1756
            if (heightOfStep < MAXIMUM_STEP_HEIGHT) /* we've hit a 'step' - move player upwards */
 
 
1757
            {
 
 
1758
                DistanceToStepUp = heightOfStep + COLLISION_GRANULARITY;
 
 
1759
                assert(heightOfStep > 0);
 
 
1760
            }
 
 
1761
        }
 
 
1762
    }
 
 
1763
 
 
 
1764
return 1;
 
 
1765
}
 
 
1766
 
 
 
1767
static int DistanceMovedBeforeNRBBHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove, const VECTORCH *DirectionOfTravel)
 
 
1768
{
 
 
1769
    assert(polyPtr);
 
 
1770
    int obstacleDistance = 0x7fffffff;
 
 
1771
    int vertexToPlaneDist[8];
 
 
1772
 
 
 
1773
      VECTORCH polyNormal = polyPtr->PolyNormal;      
 
 
1774
    int dottedNormals = -DotProduct(DirectionOfTravel, &polyNormal);
 
 
1775
 
 
 
1776
    if (dottedNormals <= 0)
 
 
1777
        return -1; /* reject poly */
 
 
1778
 
 
 
1779
    /* calculate distance each vertex is from poly's plane along direction of motion */
 
 
1780
{
 
 
1781
    VECTORCH polyPoint = polyPtr->PolyPoint[0];
 
 
1782
    int originToPlaneDist = DotProduct(&polyPoint, &polyNormal);
 
 
1783
 
 
 
1784
    {
 
 
1785
        int vertexNum = 8;
 
 
1786
 
 
 
1787
        do
 
 
1788
        {
 
 
1789
            vertexNum--;
 
 
1790
            vertexToPlaneDist[vertexNum] = DotProduct(&dynPtr->ObjectVertices[vertexNum], &polyNormal) - originToPlaneDist;
 
 
1791
 
 
 
1792
            if (vertexToPlaneDist[vertexNum] < 0)
 
 
1793
                return -1;
 
 
1794
 
 
 
1795
        } while(vertexNum);
 
 
1796
    }
 
 
1797
 
 
 
1798
    {
 
 
1799
        int vertexNum = 8;
 
 
1800
        int *distancePtr = vertexToPlaneDist;
 
 
1801
 
 
 
1802
        do
 
 
1803
        {
 
 
1804
            *distancePtr = DIV_FIXED(*distancePtr, dottedNormals);
 
 
1805
 
 
 
1806
            if(*distancePtr < obstacleDistance)
 
 
1807
                obstacleDistance = *distancePtr;
 
 
1808
 
 
 
1809
            distancePtr++;
 
 
1810
 
 
 
1811
        } while(--vertexNum);
 
 
1812
    }
 
 
1813
}
 
 
1814
    if (obstacleDistance >= distanceToMove)
 
 
1815
        return -2;
 
 
1816
 
 
 
1817
    /* test if any vertices projected paths intersect polygons */
 
 
1818
    if (NRBBProjectsOntoPolygon(dynPtr, vertexToPlaneDist, polyPtr, DirectionOfTravel))
 
 
1819
        return obstacleDistance;
 
 
1820
 
 
 
1821
return -3;
 
 
1822
}
 
 
1823
 
 
 
1824
static int DistanceMovedBeforeSphereHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove, const VECTORCH *DirectionOfTravel)
 
 
1825
{
 
 
1826
    int sphereToPolyDist;
 
 
1827
 
 
 
1828
    assert(polyPtr);
 
 
1829
 
 
 
1830
    int dottedNormals = -DotProduct(DirectionOfTravel, &(polyPtr->PolyNormal));
 
 
1831
 
 
 
1832
    /* reject if polygon does not face against direction of sphere's travel */
 
 
1833
    if (dottedNormals <= 0)
 
 
1834
        return -1; 
 
 
1835
 
 
 
1836
    /* calculate distance each vertex is from poly's plane along direction of motion */
 
 
1837
    {
 
 
1838
        VECTORCH sphereToPoly;
 
 
1839
 
 
 
1840
        sphereToPoly.vx = dynPtr->Position.vx - polyPtr->PolyPoint[0].vx;
 
 
1841
        sphereToPoly.vy = dynPtr->Position.vy - polyPtr->PolyPoint[0].vy;
 
 
1842
        sphereToPoly.vz = dynPtr->Position.vz - polyPtr->PolyPoint[0].vz;
 
 
1843
 
 
 
1844
        sphereToPolyDist = DotProduct(&sphereToPoly,&(polyPtr->PolyNormal))-dynPtr->CollisionRadius;
 
 
1845
    }
 
 
1846
 
 
 
1847
    /* reject if polygon is 'behind' sphere */
 
 
1848
    if (sphereToPolyDist < 0)
 
 
1849
        return -2;
 
 
1850
 
 
 
1851
      /* calculate distance along direction of travel */
 
 
1852
 
 
 
1853
    sphereToPolyDist = DIV_FIXED(sphereToPolyDist, dottedNormals);
 
 
1854
 
 
 
1855
    if (sphereToPolyDist >= distanceToMove)
 
 
1856
        return -4;
 
 
1857
 
 
 
1858
    /* test if sphere's projected path intersect polygon */
 
 
1859
    {
 
 
1860
        VECTORCH projectedPosition;
 
 
1861
        projectedPosition.vx = dynPtr->Position.vx + MUL_FIXED(DirectionOfTravel->vx, sphereToPolyDist) -
MUL_FIXED(dynPtr->CollisionRadius,polyPtr->PolyNormal.vx);
 
 
1862
        projectedPosition.vy = dynPtr->Position.vy + MUL_FIXED(DirectionOfTravel->vy, sphereToPolyDist) -
MUL_FIXED(dynPtr->CollisionRadius,polyPtr->PolyNormal.vy);
 
 
1863
        projectedPosition.vz = dynPtr->Position.vz + MUL_FIXED(DirectionOfTravel->vz, sphereToPolyDist) -
MUL_FIXED(dynPtr->CollisionRadius,polyPtr->PolyNormal.vz);
 
 
1864
 
 
 
1865
        if (SphereProjectOntoPoly(dynPtr, polyPtr, &projectedPosition))
 
 
1866
            return sphereToPolyDist;
 
 
1867
    }
 
 
1868
 
 
 
1869
/* polygon not in way of sphere */
 
 
1870
return -5;
 
 
1871
}
 
 
1872
 
 
 
1873
static int IsPolygonWithinStaticBoundingBox(const struct ColPolyTag *polyPtr)
 
 
1874
{
 
 
1875
    const VECTORCH *vertices = polyPtr->PolyPoint;
 
 
1876
 
 
 
1877
    if (polyPtr->NumberOfVertices == 4)
 
 
1878
    {
 
 
1879
        if (vertices[0].vy < SBBMinY)
 
 
1880
            if (vertices[1].vy < SBBMinY) 
 
 
1881
                if (vertices[2].vy < SBBMinY) 
 
 
1882
                    if (vertices[3].vy < SBBMinY) 
 
 
1883
                        return 0;
 
 
1884
 
 
 
1885
        if (vertices[0].vx < SBBMinX)
 
 
1886
            if (vertices[1].vx < SBBMinX)
 
 
1887
                if (vertices[2].vx < SBBMinX)
 
 
1888
                    if (vertices[3].vx < SBBMinX) 
 
 
1889
                        return 0;
 
 
1890
 
 
 
1891
        if (vertices[0].vx > SBBMaxX) 
 
 
1892
            if (vertices[1].vx > SBBMaxX) 
 
 
1893
                if (vertices[2].vx > SBBMaxX) 
 
 
1894
                    if (vertices[3].vx > SBBMaxX) 
 
 
1895
                        return 0;
 
 
1896
 
 
 
1897
        if (vertices[0].vz < SBBMinZ) 
 
 
1898
            if (vertices[1].vz < SBBMinZ) 
 
 
1899
                if (vertices[2].vz < SBBMinZ) 
 
 
1900
                    if (vertices[3].vz < SBBMinZ) 
 
 
1901
                        return 0;
 
 
1902
 
 
 
1903
        if (vertices[0].vz > SBBMaxZ) 
 
 
1904
            if (vertices[1].vz > SBBMaxZ) 
 
 
1905
                if (vertices[2].vz > SBBMaxZ) 
 
 
1906
                    if (vertices[3].vz > SBBMaxZ) 
 
 
1907
                        return 0;
 
 
1908
 
 
 
1909
        if (vertices[0].vy > SBBMaxY) 
 
 
1910
            if (vertices[1].vy > SBBMaxY) 
 
 
1911
                if (vertices[2].vy > SBBMaxY) 
 
 
1912
                    if (vertices[3].vy > SBBMaxY) 
 
 
1913
                        return 0;
 
 
1914
    }
 
 
1915
    else
 
 
1916
    {
 
 
1917
        if (vertices[0].vy < SBBMinY)
 
 
1918
            if (vertices[1].vy < SBBMinY) 
 
 
1919
                if (vertices[2].vy < SBBMinY) 
 
 
1920
                    return 0;
 
 
1921
 
 
 
1922
        if (vertices[0].vx < SBBMinX) 
 
 
1923
            if (vertices[1].vx < SBBMinX) 
 
 
1924
                if (vertices[2].vx < SBBMinX) 
 
 
1925
                    return 0;
 
 
1926
 
 
 
1927
        if (vertices[0].vx > SBBMaxX) 
 
 
1928
            if (vertices[1].vx > SBBMaxX) 
 
 
1929
                    if (vertices[2].vx > SBBMaxX) 
 
 
1930
                    return 0;
 
 
1931
 
 
 
1932
        if (vertices[0].vz < SBBMinZ) 
 
 
1933
                if (vertices[1].vz < SBBMinZ) 
 
 
1934
                    if (vertices[2].vz < SBBMinZ) 
 
 
1935
                    return 0;
 
 
1936
 
 
 
1937
        if (vertices[0].vz > SBBMaxZ) 
 
 
1938
            if (vertices[1].vz > SBBMaxZ) 
 
 
1939
                    if (vertices[2].vz > SBBMaxZ) 
 
 
1940
                    return 0;
 
 
1941
 
 
 
1942
        if (vertices[0].vy > SBBMaxY) 
 
 
1943
            if (vertices[1].vy > SBBMaxY) 
 
 
1944
                if (vertices[2].vy > SBBMaxY) 
 
 
1945
                    return 0;
 
 
1946
    }
 
 
1947
 
 
 
1948
return 1;
 
 
1949
} 
 
 
1950
 
 
 
1951
static void TestShapeWithStaticBoundingBox(DISPLAYBLOCK *objectPtr)
 
 
1952
{
 
 
1953
    int needToRotate = 0;
 
 
1954
 
 
 
1955
    /* KJL 10:58:22 24/11/98 - If the object is a static object rather than a module,
 
 
1956
    we'll need to rotate the polygons into world-space */
 
 
1957
 
 
 
1958
       if (objectPtr->ObStrategyBlock)
 
 
1959
    {
 
 
1960
        DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
 
 
1961
 
 
 
1962
        if (dynPtr && dynPtr->IsStatic)
 
 
1963
            needToRotate = 1;
 
 
1964
    }
 
 
1965
 
 
 
1966
    /* okay, let's setup the shape's data and access the first poly */
 
 
1967
    int numberOfItems = SetupPolygonAccess(objectPtr);
 
 
1968
 
 
 
1969
    /* go through polys looking for those which intersect with the bounding box */
 
 
1970
 
 
 
1971
      while(numberOfItems--)
 
 
1972
    {
 
 
1973
        int *itemPtr = *(ItemArrayPtr++);
 
 
1974
        PolyheaderPtr = (POLYHEADER *) itemPtr;
 
 
1975
 
 
 
1976
        //if (PolyheaderPtr->PolyFlags & iflag_notvis) continue;
 
 
1977
 
 
 
1978
        GetPolygonVertices(CollisionPolysPtr);
 
 
1979
 
 
 
1980
        if (needToRotate)
 
 
1981
        {
 
 
1982
            int i = CollisionPolysPtr->NumberOfVertices;    
 
 
1983
            VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
 
 
1984
 
 
 
1985
            do
 
 
1986
            {    
 
 
1987
                RotateVector(polyVertexPtr, &objectPtr->ObMat);
 
 
1988
                polyVertexPtr++;
 
 
1989
 
 
 
1990
            } while(--i);
 
 
1991
        }
 
 
1992
 
 
 
1993
        if(IsPolygonWithinStaticBoundingBox(CollisionPolysPtr))
 
 
1994
        {
 
 
1995
            /* add object's world space coords to vertices */
 
 
1996
 
 
 
1997
            {
 
 
1998
                int i = CollisionPolysPtr->NumberOfVertices;    
 
 
1999
                VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
 
 
2000
 
 
 
2001
                do
 
 
2002
                {    
 
 
2003
                    polyVertexPtr->vx += objectPtr->ObWorld.vx;
 
 
2004
                    polyVertexPtr->vy += objectPtr->ObWorld.vy;
 
 
2005
                    polyVertexPtr->vz += objectPtr->ObWorld.vz;
 
 
2006
                    polyVertexPtr++;
 
 
2007
 
 
 
2008
                } while(--i);         
 
 
2009
            }
 
 
2010
 
 
 
2011
            /* get the poly's normal */
 
 
2012
            GetPolygonNormal(CollisionPolysPtr);
 
 
2013
 
 
 
2014
            if (needToRotate)
 
 
2015
                RotateVector(&CollisionPolysPtr->PolyNormal, &objectPtr->ObMat);
 
 
2016
 
 
 
2017
            CollisionPolysPtr++;
 
 
2018
            NumberOfCollisionPolys++;
 
 
2019
 
 
 
2020
            /* ran out of space? */
 
 
2021
            assert(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
 
 
2022
 
 
 
2023
            if (PolyheaderPtr->PolyFlags & iflag_no_bfc)
 
 
2024
            {
 
 
2025
                CollisionPolysPtr->NumberOfVertices = (CollisionPolysPtr-1)->NumberOfVertices;
 
 
2026
 
 
 
2027
                if(CollisionPolysPtr->NumberOfVertices == 3)
 
 
2028
                {
 
 
2029
                    CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[2];
 
 
2030
                    CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[1];
 
 
2031
                    CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[0];
 
 
2032
                }
 
 
2033
                else
 
 
2034
                {
 
 
2035
                    CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[3];
 
 
2036
                    CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[2];
 
 
2037
                    CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[1];
 
 
2038
                    CollisionPolysPtr->PolyPoint[3] = (CollisionPolysPtr-1)->PolyPoint[0];
 
 
2039
                }
 
 
2040
 
 
 
2041
                CollisionPolysPtr->PolyNormal.vx = -(CollisionPolysPtr-1)->PolyNormal.vx;
 
 
2042
                CollisionPolysPtr->PolyNormal.vy = -(CollisionPolysPtr-1)->PolyNormal.vy;
 
 
2043
                CollisionPolysPtr->PolyNormal.vz = -(CollisionPolysPtr-1)->PolyNormal.vz;
 
 
2044
 
 
 
2045
                CollisionPolysPtr++;
 
 
2046
                NumberOfCollisionPolys++;
 
 
2047
                /* ran out of space? */
 
 
2048
                assert(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
 
 
2049
            }
 
 
2050
        }
 
 
2051
    }
 
 
2052
}
 
 
2053
 
 
 
2054
static void TestObjectWithStaticBoundingBox(DISPLAYBLOCK *objectPtr)
 
 
2055
{
 
 
2056
    DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
 
 
2057
//    VECTORCH *objectPositionPtr = &dynPtr->Position;
 
 
2058
    /* if the bounding box does not intersect with the object at all just return */
 
 
2059
    VECTORCH *objectVerticesPtr = dynPtr->ObjectVertices;
 
 
2060
 
 
 
2061
       if (!( ( (SBBMaxX >= objectVerticesPtr[7].vx) && (SBBMinX <= objectVerticesPtr[0].vx) )
 
 
2062
            &&( (SBBMaxY >= objectVerticesPtr[7].vy) && (SBBMinY <= objectVerticesPtr[0].vy) )
 
 
2063
         &&( (SBBMaxZ >= objectVerticesPtr[7].vz) && (SBBMinZ <= objectVerticesPtr[0].vz) ) ))
 
 
2064
           return;
 
 
2065
 
 
 
2066
    /* okay, let's access the objects polys */
 
 
2067
    {
 
 
2068
        const int *vertexIndexPtr = &CuboidVertexList[0];
 
 
2069
        int face = 6;
 
 
2070
 
 
 
2071
        do
 
 
2072
        {
 
 
2073
            CollisionPolysPtr->NumberOfVertices = 4;
 
 
2074
            CollisionPolysPtr->PolyPoint[0] = objectVerticesPtr[*vertexIndexPtr++];
 
 
2075
            CollisionPolysPtr->PolyPoint[1] = objectVerticesPtr[*vertexIndexPtr++];
 
 
2076
            CollisionPolysPtr->PolyPoint[2] = objectVerticesPtr[*vertexIndexPtr++];
 
 
2077
            CollisionPolysPtr->PolyPoint[3] = objectVerticesPtr[*vertexIndexPtr++];
 
 
2078
 
 
 
2079
            if(IsPolygonWithinStaticBoundingBox(CollisionPolysPtr))
 
 
2080
            {
 
 
2081
                if(dynPtr->DynamicsType == DYN_TYPE_CUBOID_COLLISIONS)
 
 
2082
                {
 
 
2083
                    switch(face)
 
 
2084
                    {
 
 
2085
                        case 6: /* all points are on max y face */
 
 
2086
                        {
 
 
2087
                            CollisionPolysPtr->PolyNormal.vx = dynPtr->OrientMat.mat21;
 
 
2088
                            CollisionPolysPtr->PolyNormal.vy = dynPtr->OrientMat.mat22;
 
 
2089
                            CollisionPolysPtr->PolyNormal.vz = dynPtr->OrientMat.mat23;
 
 
2090
                        }
 
 
2091
                        break;
 
 
2092
                        case 5: /* all points are on max z face */
 
 
2093
                        {
 
 
2094
                            CollisionPolysPtr->PolyNormal.vx = dynPtr->OrientMat.mat31;
 
 
2095
                            CollisionPolysPtr->PolyNormal.vy = dynPtr->OrientMat.mat32;
 
 
2096
                            CollisionPolysPtr->PolyNormal.vz = dynPtr->OrientMat.mat33;
 
 
2097
                        }
 
 
2098
                        break;
 
 
2099
                        case 4: /* all points are on max x face */
 
 
2100
                        {
 
 
2101
                            CollisionPolysPtr->PolyNormal.vx = dynPtr->OrientMat.mat11;
 
 
2102
                            CollisionPolysPtr->PolyNormal.vy = dynPtr->OrientMat.mat12;
 
 
2103
                            CollisionPolysPtr->PolyNormal.vz = dynPtr->OrientMat.mat13;
 
 
2104
                        }
 
 
2105
                        break;
 
 
2106
                        case 3: /* all points are on min z face */
 
 
2107
                        {
 
 
2108
                            CollisionPolysPtr->PolyNormal.vx = -dynPtr->OrientMat.mat31;
 
 
2109
                            CollisionPolysPtr->PolyNormal.vy = -dynPtr->OrientMat.mat32;
 
 
2110
                            CollisionPolysPtr->PolyNormal.vz = -dynPtr->OrientMat.mat33;
 
 
2111
                        }
 
 
2112
                        break;
 
 
2113
                        case 2: /* all points are on min x face */
 
 
2114
                        {
 
 
2115
                            CollisionPolysPtr->PolyNormal.vx = -dynPtr->OrientMat.mat11;
 
 
2116
                            CollisionPolysPtr->PolyNormal.vy = -dynPtr->OrientMat.mat12;
 
 
2117
                            CollisionPolysPtr->PolyNormal.vz = -dynPtr->OrientMat.mat13;
 
 
2118
                        }
 
 
2119
                        break;
 
 
2120
                        case 1: /* all points are on min y face */
 
 
2121
                        {
 
 
2122
                            CollisionPolysPtr->PolyNormal.vx = -dynPtr->OrientMat.mat21;
 
 
2123
                            CollisionPolysPtr->PolyNormal.vy = -dynPtr->OrientMat.mat22;
 
 
2124
                            CollisionPolysPtr->PolyNormal.vz = -dynPtr->OrientMat.mat23;
 
 
2125
                        }
 
 
2126
                    }
 
 
2127
                }
 
 
2128
                else
 
 
2129
                {
 
 
2130
                    switch(face)
 
 
2131
                    {
 
 
2132
                        case 6: /* all points are on max y face */
 
 
2133
                        {
 
 
2134
                            CollisionPolysPtr->PolyNormal.vx = 0;
 
 
2135
                            CollisionPolysPtr->PolyNormal.vy = ONE_FIXED;
 
 
2136
                            CollisionPolysPtr->PolyNormal.vz = 0;
 
 
2137
                        }
 
 
2138
                        break;
 
 
2139
                        case 5: /* all points are on max z face */
 
 
2140
                        {
 
 
2141
                            CollisionPolysPtr->PolyNormal.vx = 0;
 
 
2142
                            CollisionPolysPtr->PolyNormal.vy = 0;
 
 
2143
                            CollisionPolysPtr->PolyNormal.vz = ONE_FIXED;
 
 
2144
                        }
 
 
2145
                        break;
 
 
2146
                        case 4: /* all points are on max x face */
 
 
2147
                        {
 
 
2148
                            CollisionPolysPtr->PolyNormal.vx = ONE_FIXED;
 
 
2149
                            CollisionPolysPtr->PolyNormal.vy = 0;
 
 
2150
                            CollisionPolysPtr->PolyNormal.vz = 0;
 
 
2151
                        }
 
 
2152
                        break;
 
 
2153
                        case 3: /* all points are on min z face */
 
 
2154
                        {
 
 
2155
                            CollisionPolysPtr->PolyNormal.vx = 0;
 
 
2156
                            CollisionPolysPtr->PolyNormal.vy = 0;
 
 
2157
                            CollisionPolysPtr->PolyNormal.vz = -ONE_FIXED;
 
 
2158
                        }
 
 
2159
                        break;
 
 
2160
                        case 2: /* all points are on min x face */
 
 
2161
                        {
 
 
2162
                            CollisionPolysPtr->PolyNormal.vx = -ONE_FIXED;
 
 
2163
                            CollisionPolysPtr->PolyNormal.vy = 0;
 
 
2164
                            CollisionPolysPtr->PolyNormal.vz = 0;
 
 
2165
                        }
 
 
2166
                        break;
 
 
2167
                        case 1: /* all points are on min y face */
 
 
2168
                        {                                       
 
 
2169
                            CollisionPolysPtr->PolyNormal.vx = 0;
 
 
2170
                            CollisionPolysPtr->PolyNormal.vy = -ONE_FIXED;
 
 
2171
                            CollisionPolysPtr->PolyNormal.vz = 0;
 
 
2172
                        }
 
 
2173
                    }
 
 
2174
                }
 
 
2175
 
 
 
2176
                CollisionPolysPtr++;
 
 
2177
                NumberOfCollisionPolys++;
 
 
2178
                /* ran out of space? */
 
 
2179
                assert(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
 
 
2180
            }
 
 
2181
 
 
 
2182
        } while(--face);
 
 
2183
    }
 
 
2184
}
 
 
2185
 
 
 
2186
static void FindLandscapePolygonsInObjectsVicinity(STRATEGYBLOCK *sbPtr)
 
 
2187
{
 
 
2188
    /* intialise near polygons array */
 
 
2189
    CollisionPolysPtr = CollisionPolysArray;
 
 
2190
    NumberOfCollisionPolys = 0;
 
 
2191
 
 
 
2192
       /* scan through ActiveBlockList for modules */
 
 
2193
    int numberOfObjects = NumActiveBlocks;
 
 
2194
 
 
 
2195
    while(numberOfObjects)
 
 
2196
    {
 
 
2197
        DISPLAYBLOCK* objectPtr = ActiveBlockList[--numberOfObjects];
 
 
2198
 
 
 
2199
        if (objectPtr->Module)
 
 
2200
        {
 
 
2201
            MakeStaticBoundingBoxForObject(sbPtr);
 
 
2202
        }
 
 
2203
        else if(objectPtr->ObStrategyBlock && objectPtr->ObStrategyBlock->DynPtr)
 
 
2204
        {
 
 
2205
            if(!objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithEnvironment
 
 
2206
            &&
 
 
2207
            (objectPtr->ObStrategyBlock->DynPtr->IsStatic || objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithObjects))
 
 
2208
            {
 
 
2209
                MakeStaticBoundingBoxForObject(sbPtr);
 
 
2210
            }
 
 
2211
            else
 
 
2212
            continue;
 
 
2213
        }
 
 
2214
        else
 
 
2215
        continue;
 
 
2216
 
 
 
2217
        /* translate SBB into space of landscape module */
 
 
2218
        SBBMinX -= objectPtr->ObWorld.vx;
 
 
2219
        SBBMaxX -= objectPtr->ObWorld.vx;
 
 
2220
 
 
 
2221
        SBBMinY -= objectPtr->ObWorld.vy;
 
 
2222
        SBBMaxY -= objectPtr->ObWorld.vy;
 
 
2223
 
 
 
2224
        SBBMinZ -= objectPtr->ObWorld.vz;
 
 
2225
        SBBMaxZ -= objectPtr->ObWorld.vz;
 
 
2226
 
 
 
2227
        /* if the bounding box intersects with the object, investigate */
 
 
2228
        if(
 
 
2229
        ((SBBMaxX >= objectPtr->extent.min_x) && (SBBMinX <= objectPtr->extent.max_x))
 
 
2230
        &&
 
 
2231
        ((SBBMaxY >= objectPtr->extent.min_y) && (SBBMinY <= objectPtr->extent.max_y))
 
 
2232
        &&
 
 
2233
        ((SBBMaxZ >= objectPtr->extent.min_z) && (SBBMinZ <= objectPtr->extent.max_z) ))
 
 
2234
            TestShapeWithStaticBoundingBox(objectPtr);
 
 
2235
    }
 
 
2236
 
 
 
2237
//static void FindObjectsToRelocateAgainst(STRATEGYBLOCK *sbPtr)
 
 
2238
if(0) // jadda
 
 
2239
{
 
 
2240
    MakeStaticBoundingBoxForObject(sbPtr);
 
 
2241
 
 
 
2242
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
2243
    int i = NumberOfDynamicObjects;
 
 
2244
 
 
 
2245
    while(i--)
 
 
2246
    {
 
 
2247
        const STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i].sbptr;
 
 
2248
 
 
 
2249
        /* check whether collision is even possible */
 
 
2250
        if (sbPtr == obstaclePtr)
 
 
2251
            continue;
 
 
2252
 
 
 
2253
        // ignore platform lifts, ignore things that only collide with environment
 
 
2254
        if(obstaclePtr->DynPtr->OnlyCollideWithObjects || obstaclePtr->DynPtr->OnlyCollideWithEnvironment)
 
 
2255
            continue;
 
 
2256
 
 
 
2257
        /* don't relocate against ammo and stuff */
 
 
2258
        if ((sbPtr->DisplayBlock == PlayerStatus.DisplayBlock) && obstaclePtr->DynPtr->IsPickupObject)
 
 
2259
            continue;
 
 
2260
 
 
 
2261
        if (dynPtr->IgnoreSameObjectsAsYou && (sbPtr->type == obstaclePtr->type))
 
 
2262
            continue;
 
 
2263
 
 
 
2264
        TestObjectWithStaticBoundingBox(obstaclePtr->DisplayBlock);
 
 
2265
    }
 
 
2266
}
 
 
2267
 
 
 
2268
}
 
 
2269
 
 
 
2270
static void InitialiseDynamicObjectsList()
 
 
2271
{
 
 
2272
    AccelDueToGravity = MUL_FIXED(GRAVITY_STRENGTH, NormalFrameTime);
 
 
2273
    NumberOfDynamicObjects = 0;
 
 
2274
    int i = NumActiveStBlocks;
 
 
2275
 
 
 
2276
    if (CHEATMODE_UNDERWATER == UserProfile.active_bonus)
 
 
2277
        AccelDueToGravity /= 2;
 
 
2278
 
 
 
2279
    /* scan through list of strategy blocks looking for ones with dynamics blocks and collisions on  */
 
 
2280
 
 
 
2281
    while(i--)
 
 
2282
    {
 
 
2283
        STRATEGYBLOCK *sbPtr = ActiveStBlockList[i];
 
 
2284
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
2285
 
 
 
2286
        if(I_BehaviourPlatform == sbPtr->type)
 
 
2287
            continue;
 
 
2288
 
 
 
2289
        if ((NULL != dynPtr) && (NULL != sbPtr->DisplayBlock))
 
 
2290
        {
 
 
2291
            if(dynPtr->IsStatic)
 
 
2292
            {
 
 
2293
                UpdateDisplayBlockData(sbPtr);
 
 
2294
            }
 
 
2295
            /* should object simply move? */
 
 
2296
            else if (dynPtr->DynamicsType == DYN_TYPE_NO_COLLISIONS)
 
 
2297
            {
 
 
2298
                ApplyGravity(dynPtr);
 
 
2299
 
 
 
2300
                dynPtr->Position.vx += MUL_FIXED(dynPtr->LinVelocity.vx + dynPtr->LinImpulse.vx, NormalFrameTime);
 
 
2301
                dynPtr->Position.vy += MUL_FIXED(dynPtr->LinVelocity.vy + dynPtr->LinImpulse.vy, NormalFrameTime);
 
 
2302
                dynPtr->Position.vz += MUL_FIXED(dynPtr->LinVelocity.vz + dynPtr->LinImpulse.vz, NormalFrameTime);
 
 
2303
                UpdateDisplayBlockData(sbPtr);
 
 
2304
            }
 
 
2305
            else /* have to consider it properly */
 
 
2306
            {
 
 
2307
                switch(sbPtr->type)
 
 
2308
                {
 
 
2309
                case I_BehaviourProximityDoor:
 
 
2310
                case I_BehaviourLiftDoor:
 
 
2311
                case I_BehaviourSwitchDoor:
 
 
2312
                case I_BehaviourSimpleAnimation:
 
 
2313
                case I_BehaviourBinarySwitch:
 
 
2314
                case I_BehaviourLift:
 
 
2315
                case I_BehaviourGenerator:
 
 
2316
                case I_BehaviourLinkSwitch:
 
 
2317
                case I_BehaviourXenoborgMorphRoom:
 
 
2318
                case I_BehaviourLightFX:
 
 
2319
                case I_BehaviourPlacedSound:
 
 
2320
                case I_BehaviourMissionComplete:
 
 
2321
                case I_BehaviourFan:
 
 
2322
                case I_BehaviourMessage:
 
 
2323
                case I_BehaviourPlacedLight:
 
 
2324
                case I_BehaviourDeathVolume:
 
 
2325
                case I_BehaviourSelfDestruct:
 
 
2326
                case I_BehaviourParticleGenerator:
 
 
2327
                //printf("type is %d\n", sbPtr->type);
 
 
2328
                //continue;
 
 
2329
                break;
 
 
2330
                default:
 
 
2331
                    AddEffectsOfForceGenerators(&dynPtr->Position, &dynPtr->LinImpulse, dynPtr->Mass);
 
 
2332
                    ApplyGravity(dynPtr);
 
 
2333
                }
 
 
2334
 
 
 
2335
                switch(dynPtr->DynamicsType)
 
 
2336
                {
 
 
2337
                    case DYN_TYPE_NRBB_COLLISIONS:
 
 
2338
                        CreateNRBBForObject(sbPtr);
 
 
2339
                    break;
 
 
2340
                    case DYN_TYPE_SPHERE_COLLISIONS:
 
 
2341
                        dynPtr->CollisionRadius = 500;
 
 
2342
                        CreateSphereBBForObject(sbPtr);
 
 
2343
                    default:
 
 
2344
                    break;
 
 
2345
                }
 
 
2346
 
 
 
2347
                if (!dynPtr->IsNetGhost)
 
 
2348
                {
 
 
2349
                    dynPtr->PrevPosition = dynPtr->Position;
 
 
2350
                    //dynPtr->PrevOrientMat = dynPtr->OrientMat;
 
 
2351
 
 
 
2352
                    /* reset floor contact flag */
 
 
2353
                    dynPtr->IsInContactWithFloor = 0;
 
 
2354
                    dynPtr->IsInContactWithNearlyFlatFloor = 0;
 
 
2355
 
 
 
2356
                    /* calculate object's movement vector */
 
 
2357
                    if (!dynPtr->UseDisplacement)
 
 
2358
                        dynPtr->Displacement.vx = dynPtr->Displacement.vy = dynPtr->Displacement.vz = 0;
 
 
2359
 
 
 
2360
                    if (dynPtr->OnlyCollideWithObjects)
 
 
2361
                    {
 
 
2362
                        dynPtr->Displacement.vx += MUL_FIXED(dynPtr->LinVelocity.vx, NormalFrameTime);
 
 
2363
                        dynPtr->Displacement.vy += MUL_FIXED(dynPtr->LinVelocity.vy, NormalFrameTime);
 
 
2364
                        dynPtr->Displacement.vz += MUL_FIXED(dynPtr->LinVelocity.vz, NormalFrameTime);
 
 
2365
                    }    
 
 
2366
                    else
 
 
2367
                    {
 
 
2368
                        dynPtr->Displacement.vx += MUL_FIXED(dynPtr->LinVelocity.vx + dynPtr->LinImpulse.vx, NormalFrameTime);
 
 
2369
                        dynPtr->Displacement.vy += MUL_FIXED(dynPtr->LinVelocity.vy + dynPtr->LinImpulse.vy, NormalFrameTime);
 
 
2370
                        dynPtr->Displacement.vz += MUL_FIXED(dynPtr->LinVelocity.vz + dynPtr->LinImpulse.vz, NormalFrameTime);
 
 
2371
 
 
 
2372
                        /* If moving in direction of gravity, add a little bit to make sure you will make contact with the ground if your close */
 
 
2373
 
 
 
2374
                        if (dynPtr->GravityOn)
 
 
2375
                        {
 
 
2376
                            if (dynPtr->UseStandardGravity && PlanarGravity) /* ie. in direction of +ve Y-axis */
 
 
2377
                            {
 
 
2378
                                if (dynPtr->Displacement.vy > 0)
 
 
2379
                                    dynPtr->Displacement.vy += GRAVITY_DISPLACEMENT;
 
 
2380
                            }
 
 
2381
                            else
 
 
2382
                            {
 
 
2383
                                if (DotProduct(&dynPtr->Displacement, &dynPtr->GravityDirection) > 0)
 
 
2384
                                    dynPtr->Displacement.vx += MUL_FIXED(dynPtr->GravityDirection.vx, GRAVITY_DISPLACEMENT);
 
 
2385
 
 
 
2386
                                dynPtr->Displacement.vy += MUL_FIXED(dynPtr->GravityDirection.vy, GRAVITY_DISPLACEMENT);
 
 
2387
                                dynPtr->Displacement.vz += MUL_FIXED(dynPtr->GravityDirection.vz, GRAVITY_DISPLACEMENT);
 
 
2388
                            }
 
 
2389
                        }
 
 
2390
                    }
 
 
2391
 
 
 
2392
                    dynPtr->DistanceLeftToMove = Magnitude(&dynPtr->Displacement);
 
 
2393
 
 
 
2394
                    if (dynPtr->DistanceLeftToMove > ONE_FIXED / 8)
 
 
2395
                    {
 
 
2396
                        dynPtr->DistanceLeftToMove = ONE_FIXED/8;
 
 
2397
                        Normalise(&dynPtr->Displacement);
 
 
2398
                        dynPtr->Displacement.vx /= 8;
 
 
2399
                        dynPtr->Displacement.vy /= 8;
 
 
2400
                        dynPtr->Displacement.vz /= 8;
 
 
2401
                    }
 
 
2402
                }
 
 
2403
 
 
 
2404
                if(dynPtr->OnlyCollideWithObjects || dynPtr->IsNetGhost)
 
 
2405
                    DynamicObjectsList[NumberOfDynamicObjects].valueOnWhichToSort = 0x7fffffff;
 
 
2406
                else
 
 
2407
                    DynamicObjectsList[NumberOfDynamicObjects].valueOnWhichToSort = dynPtr->DistanceLeftToMove;
 
 
2408
 
 
 
2409
                DynamicObjectsList[NumberOfDynamicObjects++].sbptr = sbPtr;
 
 
2410
            }
 
 
2411
 
 
 
2412
            /* wipe previous collision records */
 
 
2413
            dynPtr->CollisionReportPtr = NULL;
 
 
2414
        }
 
 
2415
    }
 
 
2416
 
 
 
2417
    /* possibly a good idea to sort objects so that the fastest is moved first */
 
 
2418
    qsort(DynamicObjectsList, NumberOfDynamicObjects, sizeof(struct DynamicObjects), sort_dynamicobjectslist);
 
 
2419
}
 
 
2420
 
 
 
2421
static void FindLandscapePolygonsInObjectsPath(STRATEGYBLOCK *sbPtr)
 
 
2422
{
 
 
2423
    int i;
 
 
2424
    /* initialise near polygons array */    
 
 
2425
    CollisionPolysPtr = CollisionPolysArray;
 
 
2426
    NumberOfCollisionPolys = 0;
 
 
2427
 
 
 
2428
    for(i=0; i < NumActiveBlocks; i++)
 
 
2429
    {
 
 
2430
        DISPLAYBLOCK* objectPtr = ActiveBlockList[i];
 
 
2431
 
 
 
2432
        if(objectPtr->ObStrategyBlock == sbPtr)
 
 
2433
            continue;
 
 
2434
 
 
 
2435
        if (objectPtr->Module)
 
 
2436
        {
 
 
2437
            MakeDynamicBoundingBoxForObject(sbPtr, &objectPtr->ObWorld);
 
 
2438
 
 
 
2439
            // if the bounding box intersects with the object, investigate
 
 
2440
            if (
 
 
2441
            ((DBBMaxX >= objectPtr->extent.min_x) && (DBBMinX <= objectPtr->extent.max_x))
 
 
2442
            &&
 
 
2443
            ((DBBMaxY >= objectPtr->extent.min_y) && (DBBMinY <= objectPtr->extent.max_y) )
 
 
2444
            &&
 
 
2445
            ((DBBMaxZ >= objectPtr->extent.min_z) && (DBBMinZ <= objectPtr->extent.max_z) ))
 
 
2446
            {
 
 
2447
                TestShapeWithDynamicBoundingBox(objectPtr, sbPtr->DynPtr);
 
 
2448
            }
 
 
2449
        }
 
 
2450
        else if(objectPtr->ObStrategyBlock && objectPtr->ObStrategyBlock->DynPtr)
 
 
2451
        {
 
 
2452
            if((objectPtr->ObStrategyBlock->DynPtr->IsStatic || objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithObjects)
 
 
2453
            && !objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithEnvironment)
 
 
2454
            {
 
 
2455
                MakeDynamicBoundingBoxForObject(sbPtr, &objectPtr->ObWorld);
 
 
2456
 
 
 
2457
                // if the bounding box intersects with the object, investigate
 
 
2458
                if (
 
 
2459
                ((DBBMaxX >= -objectPtr->extent.radius) && (DBBMinX <= objectPtr->extent.radius))
 
 
2460
                &&
 
 
2461
                ((DBBMaxY >= -objectPtr->extent.radius) && (DBBMinY <= objectPtr->extent.radius))
 
 
2462
                &&
 
 
2463
                ((DBBMaxZ >= -objectPtr->extent.radius) && (DBBMinZ <= objectPtr->extent.radius)))
 
 
2464
                {
 
 
2465
                    TestShapeWithDynamicBoundingBox(objectPtr, sbPtr->DynPtr);
 
 
2466
                }
 
 
2467
            }
 
 
2468
        }
 
 
2469
    }
 
 
2470
}
 
 
2471
 
 
 
2472
static int IsPolygonWithinDynamicBoundingBox(const struct ColPolyTag *polyPtr)
 
 
2473
{
 
 
2474
    const VECTORCH *vertices = polyPtr->PolyPoint;
 
 
2475
 
 
 
2476
    if (4 == polyPtr->NumberOfVertices)
 
 
2477
    {
 
 
2478
        if ((vertices[0].vy < DBBMinY) && (vertices[1].vy < DBBMinY) && (vertices[2].vy < DBBMinY) && (vertices[3].vy <
DBBMinY))
 
 
2479
                return 0;
 
 
2480
 
 
 
2481
        if ((vertices[0].vx < DBBMinX) && (vertices[1].vx < DBBMinX) && (vertices[2].vx < DBBMinX) && (vertices[3].vx <
DBBMinX))
 
 
2482
                return 0;
 
 
2483
 
 
 
2484
        if ((vertices[0].vx > DBBMaxX) && (vertices[1].vx > DBBMaxX) && (vertices[2].vx > DBBMaxX) && (vertices[3].vx >
DBBMaxX))
 
 
2485
                return 0;
 
 
2486
 
 
 
2487
        if ((vertices[0].vz < DBBMinZ) && (vertices[1].vz < DBBMinZ) && (vertices[2].vz < DBBMinZ) && (vertices[3].vz <
DBBMinZ))
 
 
2488
                return 0;
 
 
2489
 
 
 
2490
        if ((vertices[0].vz > DBBMaxZ) && (vertices[1].vz > DBBMaxZ) && (vertices[2].vz > DBBMaxZ) && (vertices[3].vz >
DBBMaxZ))
 
 
2491
                return 0;
 
 
2492
 
 
 
2493
        if ((vertices[0].vy > DBBMaxY) && (vertices[1].vy > DBBMaxY) && (vertices[2].vy > DBBMaxY) && (vertices[3].vy >
DBBMaxY))
 
 
2494
                return 0;
 
 
2495
    }
 
 
2496
    else
 
 
2497
    {
 
 
2498
        if ((vertices[0].vy < DBBMinY) && (vertices[1].vy < DBBMinY) && (vertices[2].vy < DBBMinY))
 
 
2499
            return 0;
 
 
2500
 
 
 
2501
        if ((vertices[0].vx < DBBMinX) && (vertices[1].vx < DBBMinX) && (vertices[2].vx < DBBMinX))
 
 
2502
            return 0;
 
 
2503
 
 
 
2504
        if ((vertices[0].vx > DBBMaxX) && (vertices[1].vx > DBBMaxX) && (vertices[2].vx > DBBMaxX))
 
 
2505
            return 0;
 
 
2506
 
 
 
2507
        if ((vertices[0].vz < DBBMinZ) && (vertices[1].vz < DBBMinZ) && (vertices[2].vz < DBBMinZ))
 
 
2508
            return 0;
 
 
2509
 
 
 
2510
        if ((vertices[0].vz > DBBMaxZ) && (vertices[1].vz > DBBMaxZ) && (vertices[2].vz > DBBMaxZ))
 
 
2511
            return 0;
 
 
2512
 
 
 
2513
        if ((vertices[0].vy > DBBMaxY) && (vertices[1].vy > DBBMaxY) && (vertices[2].vy > DBBMaxY))
 
 
2514
            return 0;
 
 
2515
    }
 
 
2516
 
 
 
2517
return 1;
 
 
2518
} 
 
 
2519
 
 
 
2520
static void FindObjectPolygonsInObjectsPath(STRATEGYBLOCK *sbPtr)
 
 
2521
{
 
 
2522
    VECTORCH zero = {0,0,0};
 
 
2523
    int i = NumberOfDynamicObjects;
 
 
2524
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
2525
    MakeDynamicBoundingBoxForObject(sbPtr, &zero);
 
 
2526
 
 
 
2527
    /* check against other objects */
 
 
2528
    while(i)
 
 
2529
    {
 
 
2530
        const STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[--i].sbptr;
 
 
2531
        VECTORCH *objectVerticesPtr = obstaclePtr->DynPtr->ObjectVertices;
 
 
2532
 
 
 
2533
        /* check whether collision is even possible */
 
 
2534
        {
 
 
2535
            if ((sbPtr == obstaclePtr) || (obstaclePtr->DisplayBlock->ObFlags & ObFlag_NotVis))
 
 
2536
                continue;
 
 
2537
 
 
 
2538
            if((sbPtr->type == obstaclePtr->type) && (dynPtr->IgnoreSameObjectsAsYou || obstaclePtr->DynPtr->IgnoreSameObjectsAsYou))
 
 
2539
                continue;
 
 
2540
 
 
 
2541
            if (obstaclePtr->DynPtr->OnlyCollideWithObjects || obstaclePtr->DynPtr->OnlyCollideWithEnvironment)
 
 
2542
                continue;
 
 
2543
 
 
 
2544
            if(PlayerStatus.sbptr == obstaclePtr)
 
 
2545
            {
 
 
2546
                if(dynPtr->IgnoreThePlayer)
 
 
2547
                    continue;
 
 
2548
            }
 
 
2549
            else
 
 
2550
            {
 
 
2551
                if ((PlayerStatus.sbptr == sbPtr)
 
 
2552
                && (obstaclePtr->DynPtr->IgnoreThePlayer
 
 
2553
                || (obstaclePtr->type == I_BehaviourHierarchicalFragment)
 
 
2554
                || (obstaclePtr->type == I_BehaviourProximityGrenade)
 
 
2555
                || obstaclePtr->DynPtr->IsPickupObject ))
 
 
2556
                {
 
 
2557
                    continue;
 
 
2558
                }
 
 
2559
            }
 
 
2560
 
 
 
2561
            if (!( ( (DBBMaxX >= objectVerticesPtr[7].vx) && (DBBMinX <= objectVerticesPtr[0].vx) )
 
 
2562
                 &&( (DBBMaxY >= objectVerticesPtr[7].vy) && (DBBMinY <= objectVerticesPtr[0].vy) )
 
 
2563
             &&( (DBBMaxZ >= objectVerticesPtr[7].vz) && (DBBMinZ <= objectVerticesPtr[0].vz) ) ))
 
 
2564
                continue;
 
 
2565
        }
 
 
2566
 
 
 
2567
        {
 
 
2568
            const int *vertexIndexPtr = &CuboidVertexList[0];
 
 
2569
            int face = 6;
 
 
2570
 
 
 
2571
            do
 
 
2572
            {
 
 
2573
                struct ColPolyTag poly;
 
 
2574
                poly.NumberOfVertices = 4;
 
 
2575
                poly.ParentObject = obstaclePtr->DisplayBlock;
 
 
2576
 
 
 
2577
                poly.PolyPoint[0] = objectVerticesPtr[*vertexIndexPtr++];
 
 
2578
                poly.PolyPoint[1] = objectVerticesPtr[*vertexIndexPtr++];
 
 
2579
                poly.PolyPoint[2] = objectVerticesPtr[*vertexIndexPtr++];
 
 
2580
                poly.PolyPoint[3] = objectVerticesPtr[*vertexIndexPtr++];
 
 
2581
 
 
 
2582
                if (IsPolygonWithinDynamicBoundingBox(&poly))
 
 
2583
                {
 
 
2584
                    switch(face)
 
 
2585
                    {
 
 
2586
                        case 6: /* all points are on max y face */
 
 
2587
                        {
 
 
2588
                            poly.PolyNormal.vx = 0;
 
 
2589
                            poly.PolyNormal.vy = ONE_FIXED;
 
 
2590
                            poly.PolyNormal.vz = 0;
 
 
2591
                        }
 
 
2592
                        break;
 
 
2593
                        case 5: /* all points are on max z face */
 
 
2594
                        {
 
 
2595
                            poly.PolyNormal.vx = 0;
 
 
2596
                            poly.PolyNormal.vy = 0;
 
 
2597
                            poly.PolyNormal.vz = ONE_FIXED;
 
 
2598
                        }
 
 
2599
                        break;
 
 
2600
                        case 4: /* all points are on max x face */
 
 
2601
                        {
 
 
2602
                            poly.PolyNormal.vx = ONE_FIXED;
 
 
2603
                            poly.PolyNormal.vy = 0;
 
 
2604
                            poly.PolyNormal.vz = 0;
 
 
2605
                        }
 
 
2606
                        break;
 
 
2607
                        case 3: /* all points are on min z face */
 
 
2608
                        {
 
 
2609
                            poly.PolyNormal.vx = 0;
 
 
2610
                            poly.PolyNormal.vy = 0;
 
 
2611
                            poly.PolyNormal.vz = -ONE_FIXED;
 
 
2612
                        }
 
 
2613
                        break;
 
 
2614
                        case 2: /* all points are on min x face */
 
 
2615
                        {
 
 
2616
                            poly.PolyNormal.vx = -ONE_FIXED;
 
 
2617
                            poly.PolyNormal.vy = 0;
 
 
2618
                            poly.PolyNormal.vz = 0;
 
 
2619
                        }
 
 
2620
                        break;
 
 
2621
                        case 1: /* all points are on min y face */
 
 
2622
                        {                                       
 
 
2623
                            poly.PolyNormal.vx = 0;
 
 
2624
                            poly.PolyNormal.vy = -ONE_FIXED;
 
 
2625
                            poly.PolyNormal.vz = 0;
 
 
2626
                        }
 
 
2627
                    }
 
 
2628
 
 
 
2629
                    *CollisionPolysPtr = poly;
 
 
2630
                    CollisionPolysPtr++;
 
 
2631
                    NumberOfCollisionPolys++;
 
 
2632
                }
 
 
2633
 
 
 
2634
            } while(--face);
 
 
2635
        }
 
 
2636
    }
 
 
2637
}
 
 
2638
 
 
 
2639
static void MakeStaticBoundingBoxForSphere(STRATEGYBLOCK *sbPtr)
 
 
2640
{
 
 
2641
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
2642
    int objectSize = dynPtr->CollisionRadius + COLLISION_GRANULARITY;
 
 
2643
 
 
 
2644
    SBBMinX = dynPtr->Position.vx - objectSize;
 
 
2645
    SBBMaxX = dynPtr->Position.vx + objectSize;
 
 
2646
    SBBMinY = dynPtr->Position.vy - objectSize;
 
 
2647
    SBBMaxY = dynPtr->Position.vy + objectSize;
 
 
2648
    SBBMinZ = dynPtr->Position.vz - objectSize;
 
 
2649
    SBBMaxZ = dynPtr->Position.vz + objectSize;
 
 
2650
}
 
 
2651
 
 
 
2652
static int DoesPolygonIntersectNRBB(struct ColPolyTag *polyPtr,VECTORCH *objectVertices)
 
 
2653
{
 
 
2654
    VECTORCH *minVertexPtr = &objectVertices[7];
 
 
2655
    VECTORCH *vertices = polyPtr->PolyPoint;
 
 
2656
 
 
 
2657
      /* trivial rejection tests */
 
 
2658
    if (4 == polyPtr->NumberOfVertices)
 
 
2659
    {
 
 
2660
        if (vertices[0].vx < minVertexPtr->vx)
 
 
2661
            if (vertices[1].vx < minVertexPtr->vx)
 
 
2662
                if (vertices[2].vx < minVertexPtr->vx)
 
 
2663
                    if (vertices[3].vx < minVertexPtr->vx) 
 
 
2664
                        return 0;
 
 
2665
 
 
 
2666
        if (vertices[0].vz < minVertexPtr->vz) 
 
 
2667
            if (vertices[1].vz < minVertexPtr->vz) 
 
 
2668
                if (vertices[2].vz < minVertexPtr->vz) 
 
 
2669
                    if (vertices[3].vz < minVertexPtr->vz) 
 
 
2670
                        return 0;
 
 
2671
 
 
 
2672
        if (vertices[0].vy < minVertexPtr->vy)
 
 
2673
            if (vertices[1].vy < minVertexPtr->vy) 
 
 
2674
                if (vertices[2].vy < minVertexPtr->vy) 
 
 
2675
                    if (vertices[3].vy < minVertexPtr->vy) 
 
 
2676
                        return 0;
 
 
2677
 
 
 
2678
        if (vertices[0].vx > objectVertices->vx) 
 
 
2679
            if (vertices[1].vx > objectVertices->vx) 
 
 
2680
                if (vertices[2].vx > objectVertices->vx) 
 
 
2681
                    if (vertices[3].vx > objectVertices->vx) 
 
 
2682
                        return 0;
 
 
2683
 
 
 
2684
        if (vertices[0].vz > objectVertices->vz) 
 
 
2685
            if (vertices[1].vz > objectVertices->vz) 
 
 
2686
                if (vertices[2].vz > objectVertices->vz) 
 
 
2687
                    if (vertices[3].vz > objectVertices->vz) 
 
 
2688
                        return 0;
 
 
2689
 
 
 
2690
        if (vertices[0].vy > objectVertices->vy) 
 
 
2691
            if (vertices[1].vy > objectVertices->vy) 
 
 
2692
                if (vertices[2].vy > objectVertices->vy) 
 
 
2693
                    if (vertices[3].vy > objectVertices->vy) 
 
 
2694
                        return 0;
 
 
2695
    }
 
 
2696
    else
 
 
2697
    {
 
 
2698
        if (vertices[0].vx < minVertexPtr->vx)
 
 
2699
            if (vertices[1].vx < minVertexPtr->vx)
 
 
2700
                if (vertices[2].vx < minVertexPtr->vx)
 
 
2701
                        return 0;
 
 
2702
 
 
 
2703
        if (vertices[0].vz < minVertexPtr->vz) 
 
 
2704
            if (vertices[1].vz < minVertexPtr->vz) 
 
 
2705
                if (vertices[2].vz < minVertexPtr->vz) 
 
 
2706
                        return 0;
 
 
2707
 
 
 
2708
        if (vertices[0].vy < minVertexPtr->vy)
 
 
2709
            if (vertices[1].vy < minVertexPtr->vy) 
 
 
2710
                if (vertices[2].vy < minVertexPtr->vy) 
 
 
2711
                        return 0;
 
 
2712
 
 
 
2713
        if (vertices[0].vx > objectVertices->vx) 
 
 
2714
            if (vertices[1].vx > objectVertices->vx) 
 
 
2715
                if (vertices[2].vx > objectVertices->vx) 
 
 
2716
                        return 0;
 
 
2717
 
 
 
2718
        if (vertices[0].vz > objectVertices->vz) 
 
 
2719
            if (vertices[1].vz > objectVertices->vz) 
 
 
2720
                if (vertices[2].vz > objectVertices->vz) 
 
 
2721
                        return 0;
 
 
2722
 
 
 
2723
        if (vertices[0].vy > objectVertices->vy) 
 
 
2724
            if (vertices[1].vy > objectVertices->vy) 
 
 
2725
                if (vertices[2].vy > objectVertices->vy) 
 
 
2726
                        return 0;
 
 
2727
    }
 
 
2728
 
 
 
2729
       /* are any of the poly's vertices inside the object's bounding box? */
 
 
2730
    {
 
 
2731
        if (vertices[0].vy >= minVertexPtr->vy)
 
 
2732
            if (vertices[0].vy <= objectVertices->vy) 
 
 
2733
                if (vertices[0].vx >= minVertexPtr->vx)
 
 
2734
                      if (vertices[0].vx <= objectVertices->vx) 
 
 
2735
                        if (vertices[0].vz >= minVertexPtr->vz) 
 
 
2736
                            if (vertices[0].vz <= objectVertices->vz) 
 
 
2737
                                       return 1;
 
 
2738
 
 
 
2739
        if (vertices[1].vy >= minVertexPtr->vy)
 
 
2740
            if (vertices[1].vy <= objectVertices->vy) 
 
 
2741
                if (vertices[1].vx >= minVertexPtr->vx)
 
 
2742
                      if (vertices[1].vx <= objectVertices->vx) 
 
 
2743
                        if (vertices[1].vz >= minVertexPtr->vz) 
 
 
2744
                            if (vertices[1].vz <= objectVertices->vz) 
 
 
2745
                                       return 1;
 
 
2746
 
 
 
2747
        if (vertices[2].vy >= minVertexPtr->vy)
 
 
2748
            if (vertices[2].vy <= objectVertices->vy) 
 
 
2749
                if (vertices[2].vx >= minVertexPtr->vx)
 
 
2750
                      if (vertices[2].vx <= objectVertices->vx) 
 
 
2751
                        if (vertices[2].vz >= minVertexPtr->vz) 
 
 
2752
                            if (vertices[2].vz <= objectVertices->vz) 
 
 
2753
                                       return 1;
 
 
2754
    }
 
 
2755
 
 
 
2756
    if (4 == polyPtr->NumberOfVertices)
 
 
2757
    {
 
 
2758
        if(
 
 
2759
        (vertices[3].vy >= minVertexPtr->vy)
 
 
2760
        &&
 
 
2761
        (vertices[3].vy <= objectVertices->vy)
 
 
2762
        &&
 
 
2763
            (vertices[3].vx >= minVertexPtr->vx)
 
 
2764
        &&
 
 
2765
        (vertices[3].vx <= objectVertices->vx)
 
 
2766
        &&
 
 
2767
            (vertices[3].vz >= minVertexPtr->vz)
 
 
2768
        &&
 
 
2769
        (vertices[3].vz <= objectVertices->vz)
 
 
2770
        )
 
 
2771
                   return 1;
 
 
2772
    }
 
 
2773
 
 
 
2774
    /* okay, it's not that simple then. Let's see if any of the poly's edges
 
 
2775
       intersect the objects bounding box */
 
 
2776
    {
 
 
2777
        int vertexA = polyPtr->NumberOfVertices;
 
 
2778
 
 
 
2779
        do
 
 
2780
        {
 
 
2781
            vertexA--;
 
 
2782
            int vertexB = (vertexA + 1) % polyPtr->NumberOfVertices;
 
 
2783
            VECTORCH alpha = vertices[vertexA];
 
 
2784
            VECTORCH beta;
 
 
2785
 
 
 
2786
            beta.vx = vertices[vertexB].vx - alpha.vx;
 
 
2787
            beta.vy = vertices[vertexB].vy - alpha.vy;
 
 
2788
            beta.vz = vertices[vertexB].vz - alpha.vz;
 
 
2789
 
 
 
2790
            /* edge is the line segment 'alpha + lambda*beta' where lambda is between 0 and 1 */
 
 
2791
            if (beta.vy)
 
 
2792
            {
 
 
2793
                {
 
 
2794
                    /* box edge 1:  y = minVertexPtr->vy; normal is (0,-1,0) */
 
 
2795
                       int lambda = ((float)(minVertexPtr->vy - alpha.vy) / (float)beta.vy*65536.0f);
 
 
2796
 
 
 
2797
                    /* eliminate the divides? */
 
 
2798
                    if (lambda >= 0 && lambda <= 65536)
 
 
2799
                    {
 
 
2800
                        int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
 
 
2801
 
 
 
2802
                        if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
 
 
2803
                        {
 
 
2804
                            int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
 
 
2805
 
 
 
2806
                            if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
 
 
2807
                                return 1;
 
 
2808
                        }
 
 
2809
                    }
 
 
2810
                }
 
 
2811
                {
 
 
2812
                    /* box edge 2:  y=objectVertices->vy; normal is (0,1,0) */
 
 
2813
                    //int lambda = DIV_FIXED(objectVertices->vy - (alpha.vy),(beta.vy) );
 
 
2814
                    int lambda = ((float)(objectVertices->vy - alpha.vy) / (float)beta.vy*65536.0f);
 
 
2815
 
 
 
2816
                    /* eliminate the divides? */
 
 
2817
                    if (lambda >= 0 && lambda <= 65536)
 
 
2818
                    {
 
 
2819
                        int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
 
 
2820
                        if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
 
 
2821
                        {
 
 
2822
                            int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
 
 
2823
                            if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
 
 
2824
                                return 1;
 
 
2825
                        }
 
 
2826
                    }
 
 
2827
                }
 
 
2828
            }
 
 
2829
 
 
 
2830
            if (beta.vx)
 
 
2831
            {
 
 
2832
                {
 
 
2833
                    /* box edge 3:  x=minVertexPtr->vx; normal is (-1,0,0) */
 
 
2834
                    //int lambda = DIV_FIXED(minVertexPtr->vx - (alpha.vx),(beta.vx) );
 
 
2835
                    int lambda = ((float)(minVertexPtr->vx - alpha.vx) / (float)beta.vx*65536.0f);
 
 
2836
 
 
 
2837
                    /* eliminate the divides? */
 
 
2838
                    if (lambda >= 0 && lambda <= 65536)
 
 
2839
                    {
 
 
2840
                        int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
 
 
2841
                        if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
 
 
2842
                        {
 
 
2843
                            int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
 
 
2844
                            if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
 
 
2845
                                return 1;
 
 
2846
                        }
 
 
2847
                    }
 
 
2848
                }
 
 
2849
                {
 
 
2850
                    /* box edge 4:  x=objectVertices->vx; normal is (1,0,0) */
 
 
2851
                    //int lambda = DIV_FIXED(objectVertices->vx - (alpha.vx),(beta.vx) );
 
 
2852
                    int lambda = ((float)(objectVertices->vx - alpha.vx) / (float)beta.vx*65536.0f);
 
 
2853
 
 
 
2854
                    /* eliminate the divides? */
 
 
2855
                    if (lambda >= 0 && lambda <= 65536)
 
 
2856
                    {
 
 
2857
                        int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
 
 
2858
                        if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
 
 
2859
                        {
 
 
2860
                            int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
 
 
2861
                            if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
 
 
2862
                                return 1;
 
 
2863
                        }
 
 
2864
                    }
 
 
2865
                }
 
 
2866
            }
 
 
2867
 
 
 
2868
            if (beta.vz)
 
 
2869
            {
 
 
2870
                {
 
 
2871
                    /* box edge 5:  z=minVertexPtr->vz; normal is (0,0,-1) */
 
 
2872
                    //int lambda = DIV_FIXED(minVertexPtr->vz - (alpha.vz),(beta.vz));
 
 
2873
                    int lambda = ((float)(minVertexPtr->vz - alpha.vz) / (float)beta.vz*65536.0f);
 
 
2874
 
 
 
2875
                    /* eliminate the divides? */
 
 
2876
                    if (lambda>=0 && lambda <= 65536)
 
 
2877
                    {
 
 
2878
                        int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
 
 
2879
                        if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
 
 
2880
                        {
 
 
2881
                            int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
 
 
2882
                            if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
 
 
2883
                                return 1;
 
 
2884
                        }
 
 
2885
                    }
 
 
2886
                }
 
 
2887
                {
 
 
2888
                    /* box edge 6:  z=objectVertices->vz; normal is (0,0,1) */
 
 
2889
                    //int lambda = DIV_FIXED(objectVertices->vz - (alpha.vz),(beta.vz));
 
 
2890
                    int lambda = ((float)(objectVertices->vz - alpha.vz) / (float)beta.vz*65536.0f);
 
 
2891
 
 
 
2892
                    /* eliminate the divides? */
 
 
2893
                    if (lambda>=0 && lambda <= 65536)
 
 
2894
                    {
 
 
2895
                        int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
 
 
2896
                        if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
 
 
2897
                        {
 
 
2898
                            int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
 
 
2899
                            if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
 
 
2900
                                return 1;
 
 
2901
                        }
 
 
2902
                    }
 
 
2903
                }
 
 
2904
            }
 
 
2905
 
 
 
2906
        } while(vertexA);
 
 
2907
    }
 
 
2908
 
 
 
2909
    /* Still here? Damn. Okay, we'll have to check to see if a cuboid's diagonal intersect the polygon */
 
 
2910
    {
 
 
2911
        VECTORCH alpha,beta;
 
 
2912
        int dottedNormals;
 
 
2913
        int lambda;
 
 
2914
 
 
 
2915
        if (polyPtr->PolyNormal.vx > 0)
 
 
2916
        {
 
 
2917
            alpha.vx = minVertexPtr->vx;
 
 
2918
            beta.vx = objectVertices->vx - alpha.vx;
 
 
2919
        }
 
 
2920
        else
 
 
2921
        {
 
 
2922
            alpha.vx = objectVertices->vx;
 
 
2923
            beta.vx = minVertexPtr->vx - alpha.vx;
 
 
2924
        }
 
 
2925
 
 
 
2926
        if (polyPtr->PolyNormal.vy > 0)
 
 
2927
        {
 
 
2928
            alpha.vy = minVertexPtr->vy;
 
 
2929
            beta.vy = objectVertices->vy - alpha.vy;
 
 
2930
        }
 
 
2931
        else
 
 
2932
        {
 
 
2933
            alpha.vy = objectVertices->vy;
 
 
2934
            beta.vy = minVertexPtr->vy - alpha.vy;
 
 
2935
        }
 
 
2936
 
 
 
2937
        if (polyPtr->PolyNormal.vz > 0)
 
 
2938
        {
 
 
2939
            alpha.vz = minVertexPtr->vz;
 
 
2940
            beta.vz = objectVertices->vz - alpha.vz;
 
 
2941
        }
 
 
2942
        else
 
 
2943
        {
 
 
2944
            alpha.vz = objectVertices->vz;
 
 
2945
            beta.vz = minVertexPtr->vz - alpha.vz;
 
 
2946
        }
 
 
2947
 
 
 
2948
        dottedNormals = DotProduct(&(polyPtr->PolyNormal),&beta);
 
 
2949
 
 
 
2950
        if (!dottedNormals)
 
 
2951
        {
 
 
2952
            printf( "POLY NORMAL IS %d %d %d\n",(polyPtr->PolyNormal).vx,(polyPtr->PolyNormal).vy,(polyPtr->PolyNormal).vz);
 
 
2953
            printf( "POLY NO OF VERTICES %d\n",polyPtr->NumberOfVertices);
 
 
2954
            printf( "POLY POINT IS %d %d %d\n",(polyPtr->PolyPoint[0]).vx,(polyPtr->PolyPoint[0]).vy,(polyPtr->PolyPoint[0]).vz );
 
 
2955
            assert("Found normal which may be incorrect"==0);
 
 
2956
            return 0;
 
 
2957
        }
 
 
2958
 
 
 
2959
        {
 
 
2960
            VECTORCH cornerToPlane;
 
 
2961
            cornerToPlane.vx = vertices[0].vx - alpha.vx;
 
 
2962
            cornerToPlane.vy = vertices[0].vy - alpha.vy;
 
 
2963
            cornerToPlane.vz = vertices[0].vz - alpha.vz;
 
 
2964
            lambda = DIV_FIXED ( DotProduct(&(polyPtr->PolyNormal),&cornerToPlane), dottedNormals);
 
 
2965
          }
 
 
2966
 
 
 
2967
        if (lambda >= 0 && lambda <= 65536)
 
 
2968
        {
 
 
2969
            int axis1,axis2;
 
 
2970
            /* decide which 2d plane to project onto */
 
 
2971
            {
 
 
2972
                int x = abs(polyPtr->PolyNormal.vx);
 
 
2973
                int y = abs(polyPtr->PolyNormal.vy);
 
 
2974
                int z = abs(polyPtr->PolyNormal.vz);
 
 
2975
 
 
 
2976
                if (x > y)
 
 
2977
                {
 
 
2978
                    if (x > z)
 
 
2979
                    {
 
 
2980
                        axis1 = iy;
 
 
2981
                        axis2 = iz;
 
 
2982
                    }
 
 
2983
                    else
 
 
2984
                    {
 
 
2985
                        axis1 = ix;
 
 
2986
                        axis2 = iy;
 
 
2987
                    }
 
 
2988
                }
 
 
2989
                else
 
 
2990
                {
 
 
2991
                    if (y > z)
 
 
2992
                    {
 
 
2993
                        axis1 = ix;
 
 
2994
                        axis2 = iz;
 
 
2995
                    }
 
 
2996
                    else
 
 
2997
                    {
 
 
2998
                        axis1 = ix;
 
 
2999
                        axis2 = iy;
 
 
3000
                    }
 
 
3001
                }
 
 
3002
            }
 
 
3003
 
 
 
3004
            {
 
 
3005
                int projectedPolyVertex[20];
 
 
3006
                int projectedPointOnPlane[2];
 
 
3007
 
 
 
3008
                projectedPointOnPlane[0]= *((int*)&alpha + axis1) + MUL_FIXED(lambda, *((int*)&beta + axis1));
 
 
3009
                 projectedPointOnPlane[1]= *((int*)&alpha + axis2) + MUL_FIXED(lambda, *((int*)&beta + axis2));
 
 
3010
 
 
 
3011
                 {
 
 
3012
                     VECTORCH *vertexPtr = &vertices[0];
 
 
3013
                     int* projectedVertexPtr= projectedPolyVertex;
 
 
3014
                    int noOfVertices = polyPtr->NumberOfVertices;
 
 
3015
 
 
 
3016
                    do
 
 
3017
                    {
 
 
3018
                         *projectedVertexPtr++ = *((int*)vertexPtr + axis1);
 
 
3019
                         *projectedVertexPtr++ = *((int*)vertexPtr + axis2);
 
 
3020
 
 
 
3021
                             vertexPtr++;
 
 
3022
 
 
 
3023
                     } while(--noOfVertices);
 
 
3024
 
 
 
3025
                 }
 
 
3026
 
 
 
3027
                if (PointInPolygon(projectedPointOnPlane, projectedPolyVertex, polyPtr->NumberOfVertices, 2))
 
 
3028
                    return 1;
 
 
3029
            }
 
 
3030
        }
 
 
3031
    }
 
 
3032
 
 
 
3033
/* after all that we can be sure that the polygon isn't intersecting the object */
 
 
3034
return 0;
 
 
3035
}
 
 
3036
 
 
 
3037
static int WhichNRBBVertex(VECTORCH *normalPtr)
 
 
3038
{
 
 
3039
    VECTORCH dir;
 
 
3040
 
 
 
3041
    dir.vx = -normalPtr->vx;
 
 
3042
    dir.vy = -normalPtr->vy;
 
 
3043
    dir.vz = -normalPtr->vz;
 
 
3044
 
 
 
3045
    if (dir.vx >= 0) 
 
 
3046
    {
 
 
3047
        if (dir.vy >= 0)
 
 
3048
        {
 
 
3049
            if (dir.vz >= 0)
 
 
3050
            {
 
 
3051
                /* +ve x +ve y +ve z */
 
 
3052
                return 0;
 
 
3053
            }
 
 
3054
            else
 
 
3055
            {
 
 
3056
                /* +ve x +ve y -ve z */
 
 
3057
                return 1;
 
 
3058
            } 
 
 
3059
        }
 
 
3060
        else
 
 
3061
        {
 
 
3062
            if (dir.vz >= 0)
 
 
3063
            {
 
 
3064
                /* +ve x -ve y +ve z */
 
 
3065
                return 2;
 
 
3066
            }
 
 
3067
            else
 
 
3068
            {
 
 
3069
                /* +ve x -ve y -ve z */
 
 
3070
                return 3;
 
 
3071
            } 
 
 
3072
        } 
 
 
3073
    }
 
 
3074
    else
 
 
3075
    {
 
 
3076
        if (dir.vy >= 0)
 
 
3077
        {
 
 
3078
            if (dir.vz >= 0)
 
 
3079
            {
 
 
3080
                /* -ve x +ve y +ve z */
 
 
3081
                return 4;
 
 
3082
            }
 
 
3083
            else
 
 
3084
            {
 
 
3085
                /* -ve x +ve y -ve z */
 
 
3086
                return 5;
 
 
3087
            } 
 
 
3088
        }
 
 
3089
        else
 
 
3090
        {
 
 
3091
            if (dir.vz >= 0)
 
 
3092
            {
 
 
3093
                /* -ve x -ve y +ve z */
 
 
3094
                return 6;
 
 
3095
            }
 
 
3096
            else
 
 
3097
            {
 
 
3098
                /* -ve x -ve y -ve z */
 
 
3099
                return 7;
 
 
3100
            } 
 
 
3101
        } 
 
 
3102
    }
 
 
3103
}
 
 
3104
 
 
 
3105
static int InterferenceAt(int lambda, DYNAMICSBLOCK *dynPtr, const VECTORCH *DirectionOfTravel)
 
 
3106
{
 
 
3107
    VECTORCH objectVertices[8];
 
 
3108
 
 
 
3109
    {
 
 
3110
        int vertexNum = 8;
 
 
3111
 
 
 
3112
        VECTORCH disp;
 
 
3113
        disp.vx = MUL_FIXED(dynPtr->Displacement.vx, lambda);
 
 
3114
        disp.vy = MUL_FIXED(dynPtr->Displacement.vy, lambda);
 
 
3115
        disp.vz = MUL_FIXED(dynPtr->Displacement.vz, lambda);
 
 
3116
 
 
 
3117
        do
 
 
3118
        {
 
 
3119
            vertexNum--;
 
 
3120
            objectVertices[vertexNum] = dynPtr->ObjectVertices[vertexNum];
 
 
3121
            objectVertices[vertexNum].vx += disp.vx;            
 
 
3122
            objectVertices[vertexNum].vy += disp.vy;            
 
 
3123
            objectVertices[vertexNum].vz += disp.vz;            
 
 
3124
 
 
 
3125
        } while(vertexNum);
 
 
3126
    }
 
 
3127
 
 
 
3128
    int polysLeft = NumberOfCollisionPolys;
 
 
3129
    struct ColPolyTag *polyPtr = CollisionPolysArray;
 
 
3130
    NumberOfInterferencePolygons = 0;
 
 
3131
 
 
 
3132
    while(polysLeft)
 
 
3133
    {
 
 
3134
        if((DotProduct(DirectionOfTravel, &polyPtr->PolyNormal) < 0) && DoesPolygonIntersectNRBB(polyPtr, objectVertices))
 
 
3135
        {
 
 
3136
            InterferencePolygons[NumberOfInterferencePolygons++] = *polyPtr;
 
 
3137
 
 
 
3138
            if (NumberOfInterferencePolygons == MAX_NUMBER_OF_INTERFERENCE_POLYGONS)
 
 
3139
                    break;
 
 
3140
        }
 
 
3141
 
 
 
3142
        polyPtr++;
 
 
3143
        polysLeft--;
 
 
3144
    }
 
 
3145
 
 
 
3146
return NumberOfInterferencePolygons;
 
 
3147
}
 
 
3148
 
 
 
3149
static int SteppingUpIsValid(STRATEGYBLOCK *sbPtr, const VECTORCH *DirectionOfTravel)
 
 
3150
{
 
 
3151
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
3152
    VECTORCH displacement;
 
 
3153
    int i;
 
 
3154
 
 
 
3155
    displacement.vx = MUL_FIXED(DirectionOfTravel->vx, COLLISION_GRANULARITY*2);
 
 
3156
    displacement.vy = - DistanceToStepUp;
 
 
3157
    displacement.vz = MUL_FIXED(DirectionOfTravel->vz, COLLISION_GRANULARITY*2);
 
 
3158
 
 
 
3159
    VECTORCH *vertexPtr = dynPtr->ObjectVertices;
 
 
3160
 
 
 
3161
    for(i=0; i < 8; i++)
 
 
3162
    {
 
 
3163
        vertexPtr->vx += displacement.vx;
 
 
3164
        vertexPtr->vy += displacement.vy;
 
 
3165
        vertexPtr->vz += displacement.vz;
 
 
3166
        vertexPtr++;
 
 
3167
    }
 
 
3168
 
 
 
3169
    dynPtr->Position.vx += displacement.vx;
 
 
3170
    dynPtr->Position.vy += displacement.vy;
 
 
3171
    dynPtr->Position.vz += displacement.vz;
 
 
3172
 
 
 
3173
    /* look for polygons inside this volume */
 
 
3174
    FindLandscapePolygonsInObjectsVicinity(sbPtr);
 
 
3175
 
 
 
3176
    {
 
 
3177
        int polysLeft = NumberOfCollisionPolys;
 
 
3178
        struct ColPolyTag *polyPtr = CollisionPolysArray;
 
 
3179
 
 
 
3180
        while(polysLeft)
 
 
3181
        {
 
 
3182
            if(DoesPolygonIntersectNRBB(polyPtr, dynPtr->ObjectVertices))
 
 
3183
            {
 
 
3184
                /* sorry, there's a polygon in the way */
 
 
3185
                //printf("no step\n");
 
 
3186
 
 
 
3187
                VECTORCH *vertexPtr = dynPtr->ObjectVertices;
 
 
3188
 
 
 
3189
                for(i=0; i < 8; i++)
 
 
3190
                {
 
 
3191
                    vertexPtr->vx -= displacement.vx;
 
 
3192
                    vertexPtr->vy -= displacement.vy;
 
 
3193
                    vertexPtr->vz -= displacement.vz;
 
 
3194
                    vertexPtr++;
 
 
3195
                }
 
 
3196
 
 
 
3197
                dynPtr->Position.vx -= displacement.vx;
 
 
3198
                dynPtr->Position.vy -= displacement.vy;
 
 
3199
                dynPtr->Position.vz -= displacement.vz;
 
 
3200
 
 
 
3201
                return 0;
 
 
3202
            }
 
 
3203
 
 
 
3204
            polyPtr++;
 
 
3205
            polysLeft--;
 
 
3206
        }
 
 
3207
    }
 
 
3208
 
 
 
3209
return 1;
 
 
3210
}
 
 
3211
 
 
 
3212
static int NumFreeCollisionReports = MAX_NO_OF_COLLISION_REPORTS;
 
 
3213
 
 
 
3214
static COLLISIONREPORT* AllocateCollisionReport(DYNAMICSBLOCK* dynPtr)
 
 
3215
{
 
 
3216
    static COLLISIONREPORT CollisionReportStorage[MAX_NO_OF_COLLISION_REPORTS];
 
 
3217
 
 
 
3218
    if (NumFreeCollisionReports) 
 
 
3219
    {
 
 
3220
        COLLISIONREPORT *newReportPtr = &CollisionReportStorage[--NumFreeCollisionReports];
 
 
3221
 
 
 
3222
        if (dynPtr->CollisionReportPtr) /* already some reports */
 
 
3223
        {
 
 
3224
            COLLISIONREPORT *reportPtr = dynPtr->CollisionReportPtr;
 
 
3225
 
 
 
3226
            /* search for the last report */
 
 
3227
            while(reportPtr->NextCollisionReportPtr)
 
 
3228
                reportPtr = reportPtr->NextCollisionReportPtr;
 
 
3229
 
 
 
3230
            reportPtr->NextCollisionReportPtr = newReportPtr;
 
 
3231
        } 
 
 
3232
        else /* object's first report */
 
 
3233
        {
 
 
3234
            dynPtr->CollisionReportPtr = newReportPtr;
 
 
3235
        }
 
 
3236
 
 
 
3237
        /* make report the end of the list */
 
 
3238
        newReportPtr->NextCollisionReportPtr = NULL;
 
 
3239
 
 
 
3240
        return newReportPtr;
 
 
3241
    }
 
 
3242
 
 
 
3243
/* unable to allocate a collision block I'm afraid */
 
 
3244
assert(1==0);
 
 
3245
return NULL;
 
 
3246
}
 
 
3247
/* Move an object. At this stage, we have a list of the polygons in the
 
 
3248
environment with which the object the may collide. */                                       
 
 
3249
 
 
 
3250
static int MoveObject(STRATEGYBLOCK *sbPtr, DYNAMICSBLOCK *dynPtr)
 
 
3251
{
 
 
3252
    int lowestBoundary = 0;
 
 
3253
    int highestBoundary = ONE_FIXED;
 
 
3254
    int testValue = ONE_FIXED;
 
 
3255
    int hitSomething = 0;
 
 
3256
 
 
 
3257
    VECTORCH DirectionOfTravel = dynPtr->Displacement;
 
 
3258
    Normalise(&DirectionOfTravel);
 
 
3259
 
 
 
3260
    {
 
 
3261
        int maxDistanceAllowed = dynPtr->ObjectVertices[0].vz - dynPtr->ObjectVertices[7].vz;
 
 
3262
 
 
 
3263
        if (maxDistanceAllowed > dynPtr->ObjectVertices[0].vx - dynPtr->ObjectVertices[7].vx)
 
 
3264
            maxDistanceAllowed = dynPtr->ObjectVertices[0].vx - dynPtr->ObjectVertices[7].vx;
 
 
3265
 
 
 
3266
        if (maxDistanceAllowed > dynPtr->ObjectVertices[0].vy - dynPtr->ObjectVertices[7].vy)
 
 
3267
            maxDistanceAllowed = dynPtr->ObjectVertices[0].vy - dynPtr->ObjectVertices[7].vy;
 
 
3268
 
 
 
3269
        #if DEBUG
 
 
3270
        if (maxDistanceAllowed < 10)
 
 
3271
        {
 
 
3272
            assert("Object's bounding box is too small. Suspicious."==0);
 
 
3273
        }
 
 
3274
        #endif
 
 
3275
 
 
 
3276
        if (dynPtr->DistanceLeftToMove > maxDistanceAllowed)
 
 
3277
        {
 
 
3278
            testValue = DIV_FIXED(maxDistanceAllowed, dynPtr->DistanceLeftToMove);
 
 
3279
            highestBoundary = testValue;
 
 
3280
        }
 
 
3281
    }
 
 
3282
 
 
 
3283
    if (InterferenceAt(testValue, dynPtr, &DirectionOfTravel))
 
 
3284
    {
 
 
3285
        testValue /= 2;
 
 
3286
 
 
 
3287
        do
 
 
3288
        {
 
 
3289
            if (InterferenceAt(testValue, dynPtr, &DirectionOfTravel))
 
 
3290
            {
 
 
3291
                highestBoundary = testValue;
 
 
3292
                testValue = (lowestBoundary + highestBoundary)/2;
 
 
3293
            }
 
 
3294
            else
 
 
3295
            {
 
 
3296
                lowestBoundary = testValue;
 
 
3297
                testValue = (lowestBoundary + highestBoundary)/2;
 
 
3298
            }
 
 
3299
 
 
 
3300
            if (MUL_FIXED(highestBoundary - lowestBoundary, dynPtr->DistanceLeftToMove) <= 16)
 
 
3301
            {
 
 
3302
                InterferenceAt(highestBoundary, dynPtr, &DirectionOfTravel);
 
 
3303
                break;
 
 
3304
            }
 
 
3305
 
 
 
3306
        } while(1);
 
 
3307
 
 
 
3308
        testValue = lowestBoundary;
 
 
3309
        hitSomething = 1;
 
 
3310
    }
 
 
3311
 
 
 
3312
    {
 
 
3313
        VECTORCH displacement;
 
 
3314
        displacement.vx = MUL_FIXED(dynPtr->Displacement.vx, testValue);
 
 
3315
        displacement.vy = MUL_FIXED(dynPtr->Displacement.vy, testValue);
 
 
3316
        displacement.vz = MUL_FIXED(dynPtr->Displacement.vz, testValue);
 
 
3317
 
 
 
3318
        dynPtr->Position.vx += displacement.vx;
 
 
3319
        dynPtr->Position.vy += displacement.vy;
 
 
3320
        dynPtr->Position.vz += displacement.vz;
 
 
3321
 
 
 
3322
        dynPtr->Displacement.vx -= displacement.vx;
 
 
3323
        dynPtr->Displacement.vy -= displacement.vy;
 
 
3324
        dynPtr->Displacement.vz -= displacement.vz;
 
 
3325
 
 
 
3326
        {
 
 
3327
            VECTORCH *vertexPtr = dynPtr->ObjectVertices;
 
 
3328
 
 
 
3329
            int i = 8;
 
 
3330
 
 
 
3331
            do
 
 
3332
            {
 
 
3333
                  vertexPtr->vx += displacement.vx;
 
 
3334
                vertexPtr->vy += displacement.vy;
 
 
3335
                vertexPtr->vz += displacement.vz;
 
 
3336
                vertexPtr++;
 
 
3337
 
 
 
3338
            } while(--i);
 
 
3339
        }
 
 
3340
    }
 
 
3341
 
 
 
3342
    if (hitSomething)
 
 
3343
    {
 
 
3344
        int wentUpStep = 0;
 
 
3345
        VECTORCH obstacleNormal = {0,0,0};
 
 
3346
        int n = NumberOfInterferencePolygons;
 
 
3347
        VECTORCH objectCentre;
 
 
3348
        int leastSoFar = 1000000;
 
 
3349
        struct ColPolyTag *polygonPtr = NULL;
 
 
3350
 
 
 
3351
        if (DirectionOfTravel.vx > 0)
 
 
3352
        {
 
 
3353
            objectCentre.vx = dynPtr->ObjectVertices[0].vx - COLLISION_GRANULARITY;
 
 
3354
        }
 
 
3355
        else if (DirectionOfTravel.vx < 0)
 
 
3356
        {
 
 
3357
            objectCentre.vx = dynPtr->ObjectVertices[7].vx + COLLISION_GRANULARITY;
 
 
3358
        }
 
 
3359
        else
 
 
3360
        {
 
 
3361
            objectCentre.vx = (dynPtr->ObjectVertices[0].vx + dynPtr->ObjectVertices[7].vx)/2;
 
 
3362
        }
 
 
3363
 
 
 
3364
        if (DirectionOfTravel.vy > 0)
 
 
3365
        {
 
 
3366
            objectCentre.vy = dynPtr->ObjectVertices[0].vy - COLLISION_GRANULARITY;
 
 
3367
        }
 
 
3368
        else if (DirectionOfTravel.vy < 0)
 
 
3369
        {
 
 
3370
            objectCentre.vy = dynPtr->ObjectVertices[7].vy + COLLISION_GRANULARITY;
 
 
3371
        }
 
 
3372
        else
 
 
3373
        {
 
 
3374
            objectCentre.vy = (dynPtr->ObjectVertices[0].vy + dynPtr->ObjectVertices[7].vy)/2;
 
 
3375
        }
 
 
3376
 
 
 
3377
        if (DirectionOfTravel.vz > 0)
 
 
3378
        {
 
 
3379
            objectCentre.vz = dynPtr->ObjectVertices[0].vz - COLLISION_GRANULARITY;
 
 
3380
        }
 
 
3381
        else if (DirectionOfTravel.vz < 0)
 
 
3382
        {
 
 
3383
            objectCentre.vz = dynPtr->ObjectVertices[7].vz + COLLISION_GRANULARITY;
 
 
3384
        }
 
 
3385
        else
 
 
3386
        {
 
 
3387
            objectCentre.vz = (dynPtr->ObjectVertices[0].vz + dynPtr->ObjectVertices[7].vz)/2;
 
 
3388
        }
 
 
3389
 
 
 
3390
        while(n--)
 
 
3391
        {    
 
 
3392
            VECTORCH r;
 
 
3393
 
 
 
3394
               r.vx = objectCentre.vx - InterferencePolygons[n].PolyPoint[0].vx;
 
 
3395
               r.vy = objectCentre.vy - InterferencePolygons[n].PolyPoint[0].vy;
 
 
3396
               r.vz = objectCentre.vz - InterferencePolygons[n].PolyPoint[0].vz;
 
 
3397
            int d = DotProduct(&r, &InterferencePolygons[n].PolyNormal);
 
 
3398
 
 
 
3399
            if (d < 0)
 
 
3400
                d += 1000000;
 
 
3401
 
 
 
3402
            if (d < leastSoFar)
 
 
3403
            {
 
 
3404
                obstacleNormal = InterferencePolygons[n].PolyNormal;
 
 
3405
                leastSoFar = d;
 
 
3406
                polygonPtr = &InterferencePolygons[n];
 
 
3407
            }
 
 
3408
        }
 
 
3409
 
 
 
3410
        if(!polygonPtr)
 
 
3411
        {    
 
 
3412
            assert(0);
 
 
3413
            return (dynPtr->DistanceLeftToMove = 0);
 
 
3414
        }
 
 
3415
 
 
 
3416
        /* test for a 'step' in front of object */
 
 
3417
        if (dynPtr->CanClimbStairs
 
 
3418
        /* check to see that polygon is vertical */
 
 
3419
          && (polygonPtr->PolyNormal.vy > -250) && (polygonPtr->PolyNormal.vy < 250) )
 
 
3420
        {
 
 
3421
            int vertexNum = polygonPtr->NumberOfVertices - 1;
 
 
3422
            int topOfStep = polygonPtr->PolyPoint[0].vy;
 
 
3423
 
 
 
3424
            do
 
 
3425
            {
 
 
3426
                int y = polygonPtr->PolyPoint[vertexNum].vy;
 
 
3427
 
 
 
3428
                if (y < topOfStep)
 
 
3429
                    topOfStep = y;
 
 
3430
 
 
 
3431
            } while(--vertexNum);
 
 
3432
 
 
 
3433
            int heightOfStep = dynPtr->ObjectVertices[0].vy - topOfStep;  /* y-axis is +ve downwards, remember */
 
 
3434
            //printf("found step %d\n", heightOfStep);
 
 
3435
    printf("found step %d %d\n", heightOfStep, polygonPtr->PolyNormal.vy);
 
 
3436
 
 
 
3437
            if (heightOfStep > 0 && heightOfStep < MAXIMUM_STEP_HEIGHT) /* we've hit a 'step' - move player upwards */
 
 
3438
            {
 
 
3439
                DistanceToStepUp = heightOfStep + COLLISION_GRANULARITY;
 
 
3440
                wentUpStep = SteppingUpIsValid(sbPtr, &DirectionOfTravel);
 
 
3441
            }
 
 
3442
            /*
 
 
3443
            else if(I_BehaviourAlien == sbPtr->type)
 
 
3444
            {
 
 
3445
                ALIEN_STATUS_BLOCK *alienStatus = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3446
                if(Praetorian != alienStatus->Type)
 
 
3447
                {
 
 
3448
                    dynPtr->UseStandardGravity = ((alienStatus->Wounds & section_flag_left_hand) || (alienStatus->Wounds &
section_flag_right_hand));
 
 
3449
                    alienStatus->IAmCrouched = !dynPtr->UseStandardGravity;
 
 
3450
                }
 
 
3451
            }
 
 
3452
            */
 
 
3453
        }
 
 
3454
 
 
 
3455
        if (!wentUpStep)
 
 
3456
        {
 
 
3457
            STRATEGYBLOCK *obstacleSBPtr = NULL;
 
 
3458
            int moduleIndex = -1;
 
 
3459
 
 
 
3460
            if (polygonPtr->ParentObject)
 
 
3461
            {
 
 
3462
                if(NULL != polygonPtr->ParentObject->Module)
 
 
3463
                {
 
 
3464
                    if(NULL == polygonPtr->ParentObject->ObMorphCtrl)
 
 
3465
                        moduleIndex = polygonPtr->ParentObject->Module->m_index;
 
 
3466
                }
 
 
3467
                else if(polygonPtr->ParentObject->ObStrategyBlock)
 
 
3468
                {
 
 
3469
                    obstacleSBPtr = polygonPtr->ParentObject->ObStrategyBlock;
 
 
3470
                    DYNAMICSBLOCK *obsDynPtr = obstacleSBPtr->DynPtr;
 
 
3471
 
 
 
3472
                    if (NULL != obsDynPtr)
 
 
3473
                    {
 
 
3474
                        if (!(dynPtr->OnlyCollideWithObjects
 
 
3475
                            || obsDynPtr->OnlyCollideWithObjects
 
 
3476
                            || obsDynPtr->IsStatic
 
 
3477
                            || dynPtr->IsInanimate
 
 
3478
                            || obsDynPtr->IsInanimate))
 
 
3479
                        {
 
 
3480
                            int totalMass = (obsDynPtr->Mass + dynPtr->Mass) * 4;
 
 
3481
                            int diffMass = (dynPtr->Mass - obsDynPtr->Mass) / 2;
 
 
3482
 
 
 
3483
                            obsDynPtr->LinImpulse.vx += WideMulNarrowDiv(dynPtr->LinImpulse.vx + dynPtr->LinVelocity.vx, dynPtr->Mass, totalMass);
 
 
3484
                            obsDynPtr->LinImpulse.vy += WideMulNarrowDiv(dynPtr->LinImpulse.vy + dynPtr->LinVelocity.vy, dynPtr->Mass, totalMass);
 
 
3485
                            obsDynPtr->LinImpulse.vz += WideMulNarrowDiv(dynPtr->LinImpulse.vz + dynPtr->LinVelocity.vz, dynPtr->Mass, totalMass);
 
 
3486
 
 
 
3487
                            dynPtr->LinImpulse.vx += WideMulNarrowDiv(dynPtr->LinImpulse.vx + dynPtr->LinVelocity.vx, diffMass, totalMass);
 
 
3488
                            dynPtr->LinImpulse.vy += WideMulNarrowDiv(dynPtr->LinImpulse.vy + dynPtr->LinVelocity.vy, diffMass, totalMass);
 
 
3489
                            dynPtr->LinImpulse.vz += WideMulNarrowDiv(dynPtr->LinImpulse.vz + dynPtr->LinVelocity.vz, diffMass, totalMass);
 
 
3490
                        }
 
 
3491
                    }
 
 
3492
                }
 
 
3493
            }
 
 
3494
 
 
 
3495
            DistanceToStepUp = 0;
 
 
3496
 
 
 
3497
            /* resolve player's movement vector against the collision plane */
 
 
3498
            /* awkward problem here to do with non-exact normals */
 
 
3499
            {
 
 
3500
                //int magOfPerpVel = DotProduct(&obstacleNormal, &dynPtr->Displacement);
 
 
3501
                int magOfPerpVel = MUL_FIXED(66000, DotProduct(&obstacleNormal, &dynPtr->Displacement));
 
 
3502
                SubScaledVectorFromVector(obstacleNormal, magOfPerpVel, dynPtr->Displacement);
 
 
3503
            }
 
 
3504
 
 
 
3505
            /* collision - elasticity */
 
 
3506
            {
 
 
3507
                int magOfPerpImp = MUL_FIXED(DotProduct(&obstacleNormal, &dynPtr->LinImpulse), 65536 + dynPtr->Elasticity);
 
 
3508
                SubScaledVectorFromVector(obstacleNormal, magOfPerpImp, dynPtr->LinImpulse);
 
 
3509
            }
 
 
3510
 
 
 
3511
            /* momentum test */
 
 
3512
            /* OnlyCollideWithObjects flag indicates a platform lift etc. which should not be involved with momentum transfer */
 
 
3513
 
 
 
3514
            /* see if object has hit the 'floor' */
 
 
3515
            if (dynPtr->GravityOn)
 
 
3516
            {
 
 
3517
                if (dynPtr->UseStandardGravity && PlanarGravity)
 
 
3518
                {
 
 
3519
                    if (obstacleNormal.vy < -FLOOR_THRESHOLD)
 
 
3520
                    {
 
 
3521
                        dynPtr->IsInContactWithFloor = 1;
 
 
3522
 
 
 
3523
                        if (obstacleNormal.vy < -NEARLYFLATFLOOR_THRESHOLD)
 
 
3524
                            dynPtr->IsInContactWithNearlyFlatFloor = 1;
 
 
3525
                    }
 
 
3526
                }
 
 
3527
                else
 
 
3528
                {
 
 
3529
                    int angle = DotProduct(&obstacleNormal, &dynPtr->GravityDirection);
 
 
3530
 
 
 
3531
                    if (angle < -FLOOR_THRESHOLD)
 
 
3532
                    {
 
 
3533
                        /* we've hit something that's against the direction of gravity */
 
 
3534
                        dynPtr->IsInContactWithFloor = 1;
 
 
3535
 
 
 
3536
                        if (angle < -NEARLYFLATFLOOR_THRESHOLD)
 
 
3537
                            dynPtr->IsInContactWithNearlyFlatFloor = 1;
 
 
3538
                    }
 
 
3539
                }
 
 
3540
            }
 
 
3541
 
 
 
3542
            /* create a report about the collision */
 
 
3543
            {
 
 
3544
                COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
 
 
3545
 
 
 
3546
                if (NULL != reportPtr)
 
 
3547
                {
 
 
3548
                    reportPtr->ObstacleSBPtr = obstacleSBPtr;
 
 
3549
                    reportPtr->ObstacleNormal = obstacleNormal;
 
 
3550
                    reportPtr->ObstaclePoint = dynPtr->Position;
 
 
3551
                    reportPtr->ModuleIndex = moduleIndex;
 
 
3552
                }
 
 
3553
            }
 
 
3554
 
 
 
3555
            if ((NULL != obstacleSBPtr) && (NULL != obstacleSBPtr->DynPtr))
 
 
3556
            {
 
 
3557
                COLLISIONREPORT *reportPtr = AllocateCollisionReport(obstacleSBPtr->DynPtr);
 
 
3558
 
 
 
3559
                if (NULL != reportPtr)
 
 
3560
                {
 
 
3561
                    reportPtr->ObstacleSBPtr = sbPtr;
 
 
3562
                    reportPtr->ObstacleNormal.vx = -obstacleNormal.vx;
 
 
3563
                    reportPtr->ObstacleNormal.vy = -obstacleNormal.vy;
 
 
3564
                    reportPtr->ObstacleNormal.vz = -obstacleNormal.vz;
 
 
3565
                    reportPtr->ObstaclePoint = dynPtr->Position;
 
 
3566
                    reportPtr->ModuleIndex = moduleIndex;
 
 
3567
                }
 
 
3568
            }
 
 
3569
        }
 
 
3570
    }
 
 
3571
 
 
 
3572
    dynPtr->DistanceLeftToMove = Magnitude(&dynPtr->Displacement);    
 
 
3573
 
 
 
3574
    if (dynPtr->DistanceLeftToMove <= 16)
 
 
3575
        dynPtr->DistanceLeftToMove = 0;
 
 
3576
 
 
 
3577
return hitSomething;
 
 
3578
}
 
 
3579
 
 
 
3580
void TestForValidPlayerStandUp(STRATEGYBLOCK *sbPtr)
 
 
3581
{
 
 
3582
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
3583
 
 
 
3584
    if(DYN_TYPE_NRBB_COLLISIONS == dynPtr->DynamicsType)
 
 
3585
        MakeStaticBoundingBoxForObject = MakeStaticBoundingBoxForNRBB;
 
 
3586
    else
 
 
3587
        MakeStaticBoundingBoxForObject = MakeStaticBoundingBoxForSphere;
 
 
3588
 
 
 
3589
    /* make a collision volume corresponding to a standing character */
 
 
3590
    {
 
 
3591
        const COLLISION_EXTENTS *extentsPtr = &CollisionExtents[AvP.PlayerType]; // jadda fix this
 
 
3592
 
 
 
3593
        /* max X */
 
 
3594
        dynPtr->ObjectVertices[0].vx = extentsPtr->CollisionRadius;
 
 
3595
        dynPtr->ObjectVertices[1].vx = extentsPtr->CollisionRadius;
 
 
3596
        dynPtr->ObjectVertices[2].vx = extentsPtr->CollisionRadius;
 
 
3597
        dynPtr->ObjectVertices[3].vx = extentsPtr->CollisionRadius;
 
 
3598
 
 
 
3599
        /* max Z */
 
 
3600
        dynPtr->ObjectVertices[0].vz = extentsPtr->CollisionRadius;
 
 
3601
        dynPtr->ObjectVertices[2].vz = extentsPtr->CollisionRadius;
 
 
3602
        dynPtr->ObjectVertices[4].vz = extentsPtr->CollisionRadius;
 
 
3603
        dynPtr->ObjectVertices[6].vz = extentsPtr->CollisionRadius;
 
 
3604
 
 
 
3605
        /* min X */
 
 
3606
        dynPtr->ObjectVertices[4].vx = -extentsPtr->CollisionRadius;
 
 
3607
        dynPtr->ObjectVertices[5].vx = -extentsPtr->CollisionRadius;
 
 
3608
        dynPtr->ObjectVertices[6].vx = -extentsPtr->CollisionRadius;
 
 
3609
        dynPtr->ObjectVertices[7].vx = -extentsPtr->CollisionRadius;
 
 
3610
 
 
 
3611
        /* min Z */
 
 
3612
        dynPtr->ObjectVertices[1].vz = -extentsPtr->CollisionRadius;
 
 
3613
        dynPtr->ObjectVertices[3].vz = -extentsPtr->CollisionRadius;
 
 
3614
        dynPtr->ObjectVertices[5].vz = -extentsPtr->CollisionRadius;
 
 
3615
        dynPtr->ObjectVertices[7].vz = -extentsPtr->CollisionRadius;
 
 
3616
 
 
 
3617
        /* max Y */
 
 
3618
           dynPtr->ObjectVertices[0].vy = extentsPtr->Bottom;
 
 
3619
        dynPtr->ObjectVertices[1].vy = extentsPtr->Bottom;
 
 
3620
        dynPtr->ObjectVertices[4].vy = extentsPtr->Bottom;
 
 
3621
        dynPtr->ObjectVertices[5].vy = extentsPtr->Bottom;
 
 
3622
 
 
 
3623
        /* min Y */
 
 
3624
           dynPtr->ObjectVertices[2].vy = extentsPtr->StandingTop;
 
 
3625
        dynPtr->ObjectVertices[3].vy = extentsPtr->StandingTop;
 
 
3626
        dynPtr->ObjectVertices[6].vy = extentsPtr->StandingTop;
 
 
3627
        dynPtr->ObjectVertices[7].vy = extentsPtr->StandingTop;
 
 
3628
 
 
 
3629
        /* translate cuboid into world space */
 
 
3630
        {                           
 
 
3631
            VECTORCH *vertexPtr = dynPtr->ObjectVertices;
 
 
3632
            int vertexNum = 8;
 
 
3633
 
 
 
3634
            do
 
 
3635
            {
 
 
3636
                vertexPtr->vx += dynPtr->Position.vx;
 
 
3637
                vertexPtr->vy += dynPtr->Position.vy;    
 
 
3638
                vertexPtr->vz += dynPtr->Position.vz;    
 
 
3639
                vertexPtr++;
 
 
3640
 
 
 
3641
            } while(--vertexNum);
 
 
3642
        }
 
 
3643
    }
 
 
3644
 
 
 
3645
    /* look for polygons inside this volume */
 
 
3646
    FindLandscapePolygonsInObjectsVicinity(sbPtr);
 
 
3647
 
 
 
3648
    {
 
 
3649
        int polysLeft = NumberOfCollisionPolys;
 
 
3650
        struct ColPolyTag *polyPtr = CollisionPolysArray;
 
 
3651
 
 
 
3652
        while(polysLeft)
 
 
3653
        {
 
 
3654
            if(DoesPolygonIntersectNRBB(polyPtr, dynPtr->ObjectVertices))
 
 
3655
            {
 
 
3656
                    VECTORCH vertex = dynPtr->ObjectVertices[WhichNRBBVertex(&polyPtr->PolyNormal)];
 
 
3657
                vertex.vx -= polyPtr->PolyPoint[0].vx;
 
 
3658
                vertex.vy -= polyPtr->PolyPoint[0].vy;
 
 
3659
                vertex.vz -= polyPtr->PolyPoint[0].vz;
 
 
3660
 
 
 
3661
                if (-DotProduct(&vertex, &polyPtr->PolyNormal) > 0)
 
 
3662
                    return;
 
 
3663
            }
 
 
3664
 
 
 
3665
            polyPtr++;
 
 
3666
            polysLeft--;
 
 
3667
        }
 
 
3668
    }
 
 
3669
 
 
 
3670
    PlayerStatus.Crouching = 0;
 
 
3671
    PlayerStatus.RequestsToStandUp = 0;
 
 
3672
    dynPtr->UseStandardGravity = 1;
 
 
3673
}
 
 
3674
 
 
 
3675
VECTORCH *GetNearestModuleTeleportPoint(MODULE* thisModulePtr, VECTORCH* positionPtr)
 
 
3676
{
 
 
3677
    FARENTRYPOINT *thisEp = NULL;
 
 
3678
    int tmIndex = thisModulePtr->m_aimodule->m_index;
 
 
3679
    int distance = 0x7fffffff;
 
 
3680
    int numEps = FALLP_EntryPoints[tmIndex].numEntryPoints;
 
 
3681
    FARENTRYPOINT *epList = FALLP_EntryPoints[tmIndex].entryPointsList;
 
 
3682
 
 
 
3683
    while(numEps > 0)
 
 
3684
    {
 
 
3685
        VECTORCH p = *positionPtr;
 
 
3686
 
 
 
3687
        p.vx -= thisModulePtr->m_aimodule->m_world.vx + epList->position.vx;
 
 
3688
        p.vy -= thisModulePtr->m_aimodule->m_world.vy + epList->position.vy;
 
 
3689
        p.vz -= thisModulePtr->m_aimodule->m_world.vz + epList->position.vz;
 
 
3690
 
 
 
3691
        int d = Approximate3dMagnitude(&p);
 
 
3692
 
 
 
3693
        if (d < distance)
 
 
3694
        {
 
 
3695
            distance = d;
 
 
3696
            thisEp = epList;
 
 
3697
        }
 
 
3698
 
 
 
3699
        epList++;
 
 
3700
        numEps--;
 
 
3701
    }
 
 
3702
 
 
 
3703
    return (NULL != thisEp) ? &thisEp->position : NULL;
 
 
3704
}
 
 
3705
 
 
 
3706
/* Entry point to dynamics system - this function handles the movement of all objects */
 
 
3707
void ObjectDynamics()
 
 
3708
{
 
 
3709
    /* clear previous frame's collision reports */
 
 
3710
    NumFreeCollisionReports = MAX_NO_OF_COLLISION_REPORTS;
 
 
3711
 
 
 
3712
    /* create ordered list of dynamic objects */
 
 
3713
    InitialiseDynamicObjectsList();
 
 
3714
    int i = NumberOfDynamicObjects;
 
 
3715
 
 
 
3716
    while(i--)
 
 
3717
    {
 
 
3718
        STRATEGYBLOCK *sbPtr = DynamicObjectsList[i].sbptr;
 
 
3719
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
3720
 
 
 
3721
        if (dynPtr->IsNetGhost || (dynPtr->IsPickupObject && !dynPtr->GravityOn))
 
 
3722
        {
 
 
3723
            UpdateDisplayBlockData(sbPtr);
 
 
3724
            continue;
 
 
3725
        }
 
 
3726
 
 
 
3727
        /* setup function pointers */
 
 
3728
        if(DYN_TYPE_NRBB_COLLISIONS == dynPtr->DynamicsType)
 
 
3729
            MakeStaticBoundingBoxForObject = MakeStaticBoundingBoxForNRBB;
 
 
3730
        else
 
 
3731
            MakeStaticBoundingBoxForObject = MakeStaticBoundingBoxForSphere;
 
 
3732
 
 
 
3733
        if (dynPtr->OnlyCollideWithObjects)
 
 
3734
        {
 
 
3735
        }
 
 
3736
        else
 
 
3737
        {
 
 
3738
            // find which landscape polygons occupy the space through which the object wishes to move
 
 
3739
            FindLandscapePolygonsInObjectsPath(sbPtr);
 
 
3740
 
 
 
3741
            if (!dynPtr->OnlyCollideWithEnvironment)
 
 
3742
                FindObjectPolygonsInObjectsPath(sbPtr);
 
 
3743
 
 
 
3744
            if (dynPtr->StopOnCollision)
 
 
3745
            {
 
 
3746
//if(0) // JADDA
 
 
3747
                while(dynPtr->DistanceLeftToMove && !MoveObject(sbPtr, dynPtr))
 
 
3748
                {
 
 
3749
                    // empty
 
 
3750
                }
 
 
3751
            }
 
 
3752
            else
 
 
3753
            {
 
 
3754
                int noOfMoves = 4;
 
 
3755
                int maxMoveLimit = 10;
 
 
3756
 
 
 
3757
                while (dynPtr->DistanceLeftToMove && noOfMoves && maxMoveLimit)
 
 
3758
                {    
 
 
3759
                    //printf("Displacement:%d,%d,%d\n", dynPtr->Displacement.vx, dynPtr->Displacement.vy, dynPtr->Displacement.vz);
 
 
3760
 
 
 
3761
                    if(MoveObject(sbPtr, dynPtr) || DistanceToStepUp)
 
 
3762
                    {
 
 
3763
                        /* find which landscape polygons occupy the space
 
 
3764
                        through which the object wishes to move */
 
 
3765
                        FindLandscapePolygonsInObjectsPath(sbPtr);
 
 
3766
 
 
 
3767
                        if (!dynPtr->OnlyCollideWithEnvironment)
 
 
3768
                            FindObjectPolygonsInObjectsPath(sbPtr);
 
 
3769
 
 
 
3770
                        if(!DistanceToStepUp)
 
 
3771
                            noOfMoves--;
 
 
3772
                    }
 
 
3773
 
 
 
3774
                    maxMoveLimit--;
 
 
3775
                }
 
 
3776
            }
 
 
3777
        }
 
 
3778
 
 
 
3779
        /* friction */
 
 
3780
        if (dynPtr->IsInContactWithFloor)
 
 
3781
        {
 
 
3782
            int k = NormalFrameTime << 1;
 
 
3783
            int dotted = DotProduct(&dynPtr->LinImpulse, &dynPtr->GravityDirection);
 
 
3784
 
 
 
3785
            VECTORCH linParallel,linPerp;
 
 
3786
 
 
 
3787
            linParallel.vx = MUL_FIXED(dotted, dynPtr->GravityDirection.vx);
 
 
3788
            linParallel.vy = MUL_FIXED(dotted, dynPtr->GravityDirection.vy);
 
 
3789
            linParallel.vz = MUL_FIXED(dotted, dynPtr->GravityDirection.vz);
 
 
3790
 
 
 
3791
            linPerp.vx = dynPtr->LinImpulse.vx - linParallel.vx;
 
 
3792
            linPerp.vy = dynPtr->LinImpulse.vy - linParallel.vy;
 
 
3793
            linPerp.vz = dynPtr->LinImpulse.vz - linParallel.vz;
 
 
3794
 
 
 
3795
            if (dynPtr->IsInContactWithNearlyFlatFloor)
 
 
3796
            {
 
 
3797
                if (Approximate3dMagnitude(&linPerp) < 3000)
 
 
3798
                {
 
 
3799
                    k *= 16;
 
 
3800
                    if (k > ONE_FIXED)
 
 
3801
                        k = ONE_FIXED;
 
 
3802
                }
 
 
3803
            }
 
 
3804
 
 
 
3805
            dynPtr->LinImpulse.vx -= MUL_FIXED(k,linPerp.vx);
 
 
3806
            dynPtr->LinImpulse.vy -= MUL_FIXED(k,linPerp.vy);
 
 
3807
            dynPtr->LinImpulse.vz -= MUL_FIXED(k,linPerp.vz);
 
 
3808
        }
 
 
3809
 
 
 
3810
        DISPLAYBLOCK* objectPtr = sbPtr->DisplayBlock;
 
 
3811
 
 
 
3812
        if(objectPtr->ObFlags3 & ObFlag3_DynamicModuleObject)
 
 
3813
        {
 
 
3814
            extern void FindVisibleModules(VMODULE *vptr, int flag);
 
 
3815
            sbPtr->containingModule = ModuleFromPosition(&dynPtr->Position, sbPtr->containingModule);
 
 
3816
 
 
 
3817
            if ((NULL != sbPtr->containingModule) && ModuleIsPhysical(sbPtr->containingModule))
 
 
3818
            {
 
 
3819
                if(!ModuleCurrVisArray[sbPtr->containingModule->m_index])
 
 
3820
                    ModuleCurrVisArray[sbPtr->containingModule->m_index] = 1;
 
 
3821
 
 
 
3822
                if(sbPtr->containingModule->m_vmptr)
 
 
3823
                    FindVisibleModules(sbPtr->containingModule->m_vmptr, 1);
 
 
3824
            }
 
 
3825
            else
 
 
3826
            {
 
 
3827
                extern void IdentifyObject(STRATEGYBLOCK *sbPtr);
 
 
3828
                extern int EmergencyRelocateObject(STRATEGYBLOCK *sbPtr);
 
 
3829
                printf("Calling Near EmergencyRelocateObject, On object %p, type %d!\n", (void*)sbPtr, sbPtr->type);
 
 
3830
                IdentifyObject(sbPtr);
 
 
3831
 
 
 
3832
                if(!EmergencyRelocateObject(sbPtr))
 
 
3833
                {
 
 
3834
                    printf("Relocate failed!\n");
 
 
3835
                    RemoveBehaviourStrategy(sbPtr);
 
 
3836
                    return;
 
 
3837
                }
 
 
3838
            }
 
 
3839
        }
 
 
3840
 
 
 
3841
        UpdateDisplayBlockData(sbPtr);
 
 
3842
    }
 
 
3843
 
 
 
3844
    #define TELEPORT_IF_OUTSIDE_ENV 1       
 
 
3845
    #if TELEPORT_IF_OUTSIDE_ENV
 
 
3846
    {
 
 
3847
        extern int PlayersMaxHeightWhilstNotInContactWithGround;
 
 
3848
        DYNAMICSBLOCK *dynPtr = PlayerStatus.sbptr->DynPtr;
 
 
3849
        MODULE *newModule = ModuleFromPosition(&dynPtr->Position, PlayerStatus.sbptr->containingModule);
 
 
3850
 
 
 
3851
        if (NULL == newModule)
 
 
3852
        {
 
 
3853
            if (PlayerStatus.sbptr->containingModule)
 
 
3854
            {
 
 
3855
                VECTORCH newPosition = PlayerStatus.sbptr->containingModule->m_aimodule->m_world;
 
 
3856
                VECTORCH *offsetPtr = GetNearestModuleTeleportPoint(PlayerStatus.sbptr->containingModule, &dynPtr->Position);
 
 
3857
 
 
 
3858
                if (offsetPtr)
 
 
3859
                {
 
 
3860
                    newPosition.vx += offsetPtr->vx;
 
 
3861
                    newPosition.vy += offsetPtr->vy;
 
 
3862
                    newPosition.vz += offsetPtr->vz;
 
 
3863
                }
 
 
3864
 
 
 
3865
                dynPtr->Position = newPosition;
 
 
3866
                dynPtr->PrevPosition = newPosition;
 
 
3867
            }
 
 
3868
 
 
 
3869
            PlayersMaxHeightWhilstNotInContactWithGround = dynPtr->Position.vy;
 
 
3870
            dynPtr->LinImpulse.vx = dynPtr->LinImpulse.vy = dynPtr->LinImpulse.vz = 0;
 
 
3871
            UpdateDisplayBlockData(PlayerStatus.sbptr);
 
 
3872
            printf("Relocated Player\n");
 
 
3873
        }
 
 
3874
    }
 
 
3875
    #endif
 
 
3876
}
 
 
3877
 
 
 
3878
void DynamicallyRotateObject(DYNAMICSBLOCK *dynPtr)
 
 
3879
{
 
 
3880
    MATRIXCH mat;
 
 
3881
    EULER euler;
 
 
3882
 
 
 
3883
    euler.EulerX = MUL_FIXED(NormalFrameTime, dynPtr->AngVelocity.EulerX);
 
 
3884
    euler.EulerX &= wrap360;
 
 
3885
 
 
 
3886
    euler.EulerY = MUL_FIXED(NormalFrameTime, dynPtr->AngVelocity.EulerY);
 
 
3887
    euler.EulerY &= wrap360;
 
 
3888
 
 
 
3889
    euler.EulerZ = MUL_FIXED(NormalFrameTime, dynPtr->AngVelocity.EulerZ);
 
 
3890
    euler.EulerZ &= wrap360;
 
 
3891
 
 
 
3892
    CreateEulerMatrix(&euler, &mat);
 
 
3893
    TransposeMatrixCH(&mat);
 
 
3894
 
 
 
3895
      MatrixMultiply(&dynPtr->OrientMat, &mat, &dynPtr->OrientMat);
 
 
3896
     MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
 
 
3897
}
 
 
3898
 
 
 
3899
static int DistanceMovedBeforeParticleHitsPolygon(PARTICLE *particlePtr, struct ColPolyTag *polyPtr, int distanceToMove, const VECTORCH *DirectionOfTravel)
 
 
3900
{
 
 
3901
    VECTORCH pointOnPlane;
 
 
3902
    int lambda;
 
 
3903
    int axis1;
 
 
3904
    int axis2;
 
 
3905
 
 
 
3906
    {
 
 
3907
        int normDotBeta = DotProduct(&polyPtr->PolyNormal, DirectionOfTravel);
 
 
3908
 
 
 
3909
        /* trivial rejection of poly if it is not facing LOS */
 
 
3910
        if (normDotBeta > -500)
 
 
3911
            return -1;
 
 
3912
 
 
 
3913
        /* calculate coords of plane-line intersection */
 
 
3914
        {
 
 
3915
            /* get a pt in the poly */
 
 
3916
            VECTORCH pop = polyPtr->PolyPoint[0];                                  
 
 
3917
            pop.vx -= particlePtr->Position.vx;
 
 
3918
            pop.vy -= particlePtr->Position.vy;
 
 
3919
            pop.vz -= particlePtr->Position.vz;
 
 
3920
 
 
 
3921
            int d = DotProduct(&polyPtr->PolyNormal, &pop);
 
 
3922
 
 
 
3923
            if (d >= 0)
 
 
3924
                return -1;
 
 
3925
 
 
 
3926
              lambda = DIV_FIXED(d, normDotBeta);
 
 
3927
 
 
 
3928
            if (lambda >= distanceToMove) 
 
 
3929
                return -1;
 
 
3930
 
 
 
3931
               pointOnPlane.vx    = particlePtr->Position.vx + MUL_FIXED(lambda, DirectionOfTravel->vx);
 
 
3932
               pointOnPlane.vy    = particlePtr->Position.vy + MUL_FIXED(lambda, DirectionOfTravel->vy);
 
 
3933
               pointOnPlane.vz    = particlePtr->Position.vz + MUL_FIXED(lambda, DirectionOfTravel->vz);
 
 
3934
          }
 
 
3935
 
 
 
3936
        /* decide which 2d plane to project onto */
 
 
3937
 
 
 
3938
        {
 
 
3939
            int x = abs(polyPtr->PolyNormal.vx);
 
 
3940
            int y = abs(polyPtr->PolyNormal.vy);
 
 
3941
            int z = abs(polyPtr->PolyNormal.vz);
 
 
3942
 
 
 
3943
            if (x > y)
 
 
3944
            {
 
 
3945
                if (x > z)
 
 
3946
                {
 
 
3947
                    axis1 = iy;
 
 
3948
                    axis2 = iz;
 
 
3949
                }
 
 
3950
                else
 
 
3951
                {
 
 
3952
                    axis1 = ix;
 
 
3953
                    axis2 = iy;
 
 
3954
                }
 
 
3955
            }
 
 
3956
            else
 
 
3957
            {
 
 
3958
                if (y > z)
 
 
3959
                {
 
 
3960
                    axis1 = ix;
 
 
3961
                    axis2 = iz;
 
 
3962
                }
 
 
3963
                else
 
 
3964
                {
 
 
3965
                    axis1 = ix;
 
 
3966
                    axis2 = iy;
 
 
3967
                }
 
 
3968
            }
 
 
3969
        }
 
 
3970
    }
 
 
3971
 
 
 
3972
    {
 
 
3973
        int projectedPolyVertex[20];
 
 
3974
        int projectedPointOnPlane[2];
 
 
3975
        int *popPtr = &pointOnPlane.vx;
 
 
3976
 
 
 
3977
        projectedPointOnPlane[0] = *(popPtr + axis1);
 
 
3978
         projectedPointOnPlane[1] = *(popPtr + axis2);
 
 
3979
 
 
 
3980
         {
 
 
3981
             VECTORCH *vertexPtr = polyPtr->PolyPoint;
 
 
3982
             int *projectedVertexPtr = projectedPolyVertex;
 
 
3983
            int noOfVertices = polyPtr->NumberOfVertices;
 
 
3984
 
 
 
3985
            do
 
 
3986
            {
 
 
3987
                 *projectedVertexPtr++ = *((int*)vertexPtr + axis1);
 
 
3988
                 *projectedVertexPtr++ = *((int*)vertexPtr + axis2);
 
 
3989
 
 
 
3990
                     vertexPtr++;
 
 
3991
 
 
 
3992
             } while(--noOfVertices);
 
 
3993
         }
 
 
3994
 
 
 
3995
        if (PointInPolygon(projectedPointOnPlane, projectedPolyVertex, polyPtr->NumberOfVertices, 2))
 
 
3996
            return lambda;
 
 
3997
    }
 
 
3998
 
 
 
3999
return -1;
 
 
4000
}
 
 
4001
 
 
 
4002
static void TestShapeWithParticlesDynamicBoundingBox(DISPLAYBLOCK *objectPtr)
 
 
4003
{
 
 
4004
    /* okay, let's setup the shape's data and access the first poly */
 
 
4005
    int numberOfItems = SetupPolygonAccess(objectPtr);
 
 
4006
 
 
 
4007
    /* go through polys looking for those which intersect with the bounding box */
 
 
4008
      while(numberOfItems--)
 
 
4009
    {
 
 
4010
        int *itemPtr = *(ItemArrayPtr++);
 
 
4011
        PolyheaderPtr = (POLYHEADER *) itemPtr;
 
 
4012
 
 
 
4013
        if (PolyheaderPtr->PolyFlags & iflag_notvis)
 
 
4014
            continue;
 
 
4015
 
 
 
4016
        GetPolygonVertices(CollisionPolysPtr);
 
 
4017
 
 
 
4018
        {
 
 
4019
            VECTORCH *vertices = CollisionPolysPtr->PolyPoint;
 
 
4020
 
 
 
4021
            if (CollisionPolysPtr->NumberOfVertices == 4)
 
 
4022
            {
 
 
4023
            if (vertices[0].vy < DBBMinY)
 
 
4024
                if (vertices[1].vy < DBBMinY) 
 
 
4025
                    if (vertices[2].vy < DBBMinY) 
 
 
4026
                        if (vertices[3].vy < DBBMinY) 
 
 
4027
                            continue;
 
 
4028
 
 
 
4029
            if (vertices[0].vx < DBBMinX)
 
 
4030
                if (vertices[1].vx < DBBMinX)
 
 
4031
                    if (vertices[2].vx < DBBMinX)
 
 
4032
                        if (vertices[3].vx < DBBMinX) 
 
 
4033
                            continue;
 
 
4034
 
 
 
4035
            if (vertices[0].vx > DBBMaxX) 
 
 
4036
                if (vertices[1].vx > DBBMaxX) 
 
 
4037
                    if (vertices[2].vx > DBBMaxX) 
 
 
4038
                        if (vertices[3].vx > DBBMaxX) 
 
 
4039
                            continue;
 
 
4040
 
 
 
4041
            if (vertices[0].vz < DBBMinZ) 
 
 
4042
                if (vertices[1].vz < DBBMinZ) 
 
 
4043
                    if (vertices[2].vz < DBBMinZ) 
 
 
4044
                        if (vertices[3].vz < DBBMinZ) 
 
 
4045
                            continue;
 
 
4046
 
 
 
4047
            if (vertices[0].vz > DBBMaxZ) 
 
 
4048
                if (vertices[1].vz > DBBMaxZ) 
 
 
4049
                    if (vertices[2].vz > DBBMaxZ) 
 
 
4050
                        if (vertices[3].vz > DBBMaxZ) 
 
 
4051
                            continue;
 
 
4052
 
 
 
4053
            if (vertices[0].vy > DBBMaxY) 
 
 
4054
                if (vertices[1].vy > DBBMaxY) 
 
 
4055
                    if (vertices[2].vy > DBBMaxY) 
 
 
4056
                        if (vertices[3].vy > DBBMaxY) 
 
 
4057
                            continue;
 
 
4058
            }
 
 
4059
            else
 
 
4060
            {
 
 
4061
            if (vertices[0].vy < DBBMinY)
 
 
4062
                if (vertices[1].vy < DBBMinY) 
 
 
4063
                    if (vertices[2].vy < DBBMinY) 
 
 
4064
                        continue;
 
 
4065
 
 
 
4066
            if (vertices[0].vx < DBBMinX) 
 
 
4067
                if (vertices[1].vx < DBBMinX) 
 
 
4068
                    if (vertices[2].vx < DBBMinX) 
 
 
4069
                        continue;
 
 
4070
 
 
 
4071
            if (vertices[0].vx > DBBMaxX) 
 
 
4072
                if (vertices[1].vx > DBBMaxX) 
 
 
4073
                        if (vertices[2].vx > DBBMaxX) 
 
 
4074
                        continue;
 
 
4075
 
 
 
4076
            if (vertices[0].vz < DBBMinZ) 
 
 
4077
                    if (vertices[1].vz < DBBMinZ) 
 
 
4078
                        if (vertices[2].vz < DBBMinZ) 
 
 
4079
                        continue;
 
 
4080
 
 
 
4081
            if (vertices[0].vz > DBBMaxZ) 
 
 
4082
                if (vertices[1].vz > DBBMaxZ) 
 
 
4083
                        if (vertices[2].vz > DBBMaxZ) 
 
 
4084
                        continue;
 
 
4085
 
 
 
4086
            if (vertices[0].vy > DBBMaxY) 
 
 
4087
                if (vertices[1].vy > DBBMaxY) 
 
 
4088
                    if (vertices[2].vy > DBBMaxY) 
 
 
4089
                        continue;
 
 
4090
            }
 
 
4091
        }
 
 
4092
 
 
 
4093
        /* add object's world space coords to vertices */
 
 
4094
        {
 
 
4095
            int i = CollisionPolysPtr->NumberOfVertices;    
 
 
4096
            VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
 
 
4097
 
 
 
4098
            do
 
 
4099
            {    
 
 
4100
                polyVertexPtr->vx += objectPtr->ObWorld.vx;
 
 
4101
                polyVertexPtr->vy += objectPtr->ObWorld.vy;
 
 
4102
                polyVertexPtr->vz += objectPtr->ObWorld.vz;
 
 
4103
                polyVertexPtr++;
 
 
4104
 
 
 
4105
            } while(--i);
 
 
4106
        }
 
 
4107
 
 
 
4108
        /* get the poly's normal */
 
 
4109
        GetPolygonNormal(CollisionPolysPtr);
 
 
4110
 
 
 
4111
        CollisionPolysPtr->ParentObject = objectPtr;
 
 
4112
 
 
 
4113
        CollisionPolysPtr++;
 
 
4114
        NumberOfCollisionPolys++;
 
 
4115
        /* ran out of space? */
 
 
4116
        assert(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
 
 
4117
 
 
 
4118
        if (PolyheaderPtr->PolyFlags & iflag_no_bfc)
 
 
4119
        {
 
 
4120
            CollisionPolysPtr->NumberOfVertices = (CollisionPolysPtr-1)->NumberOfVertices;
 
 
4121
 
 
 
4122
            if(CollisionPolysPtr->NumberOfVertices == 3)
 
 
4123
            {
 
 
4124
                CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[2];
 
 
4125
                CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[1];
 
 
4126
                CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[0];
 
 
4127
            }
 
 
4128
            else
 
 
4129
            {
 
 
4130
                CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[3];
 
 
4131
                CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[2];
 
 
4132
                CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[1];
 
 
4133
                CollisionPolysPtr->PolyPoint[3] = (CollisionPolysPtr-1)->PolyPoint[0];
 
 
4134
            }
 
 
4135
 
 
 
4136
            CollisionPolysPtr->PolyNormal.vx = -(CollisionPolysPtr-1)->PolyNormal.vx;
 
 
4137
            CollisionPolysPtr->PolyNormal.vy = -(CollisionPolysPtr-1)->PolyNormal.vy;
 
 
4138
            CollisionPolysPtr->PolyNormal.vz = -(CollisionPolysPtr-1)->PolyNormal.vz;
 
 
4139
            CollisionPolysPtr->ParentObject = objectPtr;
 
 
4140
 
 
 
4141
            CollisionPolysPtr++;
 
 
4142
            NumberOfCollisionPolys++;
 
 
4143
            /* ran out of space? */
 
 
4144
            assert(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
 
 
4145
        }
 
 
4146
    }
 
 
4147
}
 
 
4148
 
 
 
4149
static void FindPolygonsInParticlesPath(PARTICLE *particlePtr, VECTORCH *displacementPtr)
 
 
4150
{
 
 
4151
    int numberOfObjects = NumActiveBlocks;
 
 
4152
    /* initialise near polygons array */    
 
 
4153
    CollisionPolysPtr = CollisionPolysArray;
 
 
4154
    NumberOfCollisionPolys = 0;
 
 
4155
 
 
 
4156
    while(numberOfObjects--)
 
 
4157
    {
 
 
4158
        DISPLAYBLOCK* objectPtr = ActiveBlockList[numberOfObjects];
 
 
4159
        if(!objectPtr->Module)
 
 
4160
        continue;
 
 
4161
 
 
 
4162
        DBBMaxX = particlePtr->Position.vx - objectPtr->ObWorld.vx + COLLISION_GRANULARITY; 
 
 
4163
        DBBMinX = particlePtr->Position.vx - objectPtr->ObWorld.vx - COLLISION_GRANULARITY;
 
 
4164
 
 
 
4165
        DBBMaxY = particlePtr->Position.vy - objectPtr->ObWorld.vy + COLLISION_GRANULARITY; 
 
 
4166
        DBBMinY = particlePtr->Position.vy - objectPtr->ObWorld.vy - COLLISION_GRANULARITY;
 
 
4167
 
 
 
4168
        DBBMaxZ = particlePtr->Position.vz - objectPtr->ObWorld.vz + COLLISION_GRANULARITY;
 
 
4169
        DBBMinZ = particlePtr->Position.vz - objectPtr->ObWorld.vz - COLLISION_GRANULARITY; 
 
 
4170
 
 
 
4171
        if (displacementPtr->vx > 0)
 
 
4172
            DBBMaxX += displacementPtr->vx;
 
 
4173
        else
 
 
4174
            DBBMinX += displacementPtr->vx;
 
 
4175
 
 
 
4176
        if (displacementPtr->vy > 0)
 
 
4177
            DBBMaxY += displacementPtr->vy;
 
 
4178
        else
 
 
4179
            DBBMinY += displacementPtr->vy;
 
 
4180
 
 
 
4181
        if (displacementPtr->vz > 0)
 
 
4182
            DBBMaxZ += displacementPtr->vz;
 
 
4183
        else
 
 
4184
            DBBMinZ += displacementPtr->vz;
 
 
4185
 
 
 
4186
        assert(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
 
 
4187
 
 
 
4188
        if(((DBBMaxX >= objectPtr->extent.min_x) && (DBBMinX <= objectPtr->extent.max_x))
 
 
4189
        &&
 
 
4190
        ((DBBMaxY >= objectPtr->extent.min_y) && (DBBMinY <= objectPtr->extent.max_y) )
 
 
4191
        &&
 
 
4192
        ((DBBMaxZ >= objectPtr->extent.min_z) && (DBBMinZ <= objectPtr->extent.max_z) ))
 
 
4193
        {
 
 
4194
            TestShapeWithParticlesDynamicBoundingBox(objectPtr);
 
 
4195
        }
 
 
4196
    }
 
 
4197
}
 
 
4198
 
 
 
4199
int ParticleDynamics(PARTICLE *particlePtr, VECTORCH *obstacleNormalPtr, int *moduleIndexPtr)
 
 
4200
{
 
 
4201
    VECTORCH prevPosition = particlePtr->Position;
 
 
4202
    VECTORCH displacement;
 
 
4203
    DISPLAYBLOCK *hitModule = NULL;
 
 
4204
    int hitObstacle = 0;
 
 
4205
    *moduleIndexPtr = -1;
 
 
4206
 
 
 
4207
    displacement.vx = MUL_FIXED(particlePtr->Velocity.vx, NormalFrameTime);
 
 
4208
    displacement.vy = MUL_FIXED(particlePtr->Velocity.vy, NormalFrameTime);
 
 
4209
    displacement.vz = MUL_FIXED(particlePtr->Velocity.vz, NormalFrameTime);
 
 
4210
    int distanceToMove = Magnitude(&displacement);
 
 
4211
 
 
 
4212
    if (distanceToMove < COLLISION_GRANULARITY)
 
 
4213
        return 0;
 
 
4214
 
 
 
4215
    VECTORCH DirectionOfTravel = particlePtr->Velocity;
 
 
4216
    Normalise(&DirectionOfTravel);
 
 
4217
 
 
 
4218
    {
 
 
4219
        FindPolygonsInParticlesPath(particlePtr, &displacement);
 
 
4220
        int polysLeft = NumberOfCollisionPolys;
 
 
4221
        struct ColPolyTag *nearPolysPtr = CollisionPolysArray;
 
 
4222
 
 
 
4223
        /* check against selected polys */
 
 
4224
        while(polysLeft--)
 
 
4225
        {
 
 
4226
            int distanceToObstacle = DistanceMovedBeforeParticleHitsPolygon(particlePtr, nearPolysPtr, distanceToMove, &DirectionOfTravel);
 
 
4227
 
 
 
4228
            if (distanceToObstacle >= 0)
 
 
4229
            {
 
 
4230
                hitObstacle = 1;
 
 
4231
 
 
 
4232
                distanceToMove = distanceToObstacle;
 
 
4233
 
 
 
4234
                *obstacleNormalPtr = nearPolysPtr->PolyNormal;
 
 
4235
 
 
 
4236
                if (nearPolysPtr->ParentObject)
 
 
4237
                {
 
 
4238
                    if(nearPolysPtr->ParentObject->Module)
 
 
4239
                    {
 
 
4240
                        hitModule = nearPolysPtr->ParentObject;
 
 
4241
 
 
 
4242
                        if(NULL == nearPolysPtr->ParentObject->ObMorphCtrl)
 
 
4243
                            *moduleIndexPtr = nearPolysPtr->ParentObject->Module->m_index;
 
 
4244
                    }
 
 
4245
                /*
 
 
4246
                    else if(nearPolysPtr->ParentObject->ObStrategyBlock)
 
 
4247
                    {
 
 
4248
                        printf("damage type %d %d\n", nearPolysPtr->ParentObject->ObStrategyBlock->type, random());
 
 
4249
 
 
 
4250
                        switch(particlePtr->ParticleID)
 
 
4251
                        {
 
 
4252
                            case PARTICLE_EXPLOSIONFIRE:
 
 
4253
                                CauseDamageToObject(nearPolysPtr->ParentObject->ObStrategyBlock,
 
 
4254
                                &TemplateAmmo[EXPLOSIONFIRE_BLAST].MaxDamage, ONE_FIXED, &particlePtr->Velocity);
 
 
4255
                            break;
 
 
4256
                            case PARTICLE_FLECHETTE:
 
 
4257
                                CauseDamageToObject(nearPolysPtr->ParentObject->ObStrategyBlock, &damage_profiles[FLECHETTEDAMAGE], ONE_FIXED,
&particlePtr->Velocity);
 
 
4258
                            default:
 
 
4259
                            break;
 
 
4260
                        }
 
 
4261
                    }
 
 
4262
                */
 
 
4263
                }
 
 
4264
            }
 
 
4265
 
 
 
4266
            nearPolysPtr++;
 
 
4267
        }
 
 
4268
    }
 
 
4269
 
 
 
4270
    if (distanceToMove > COLLISION_GRANULARITY)
 
 
4271
    {
 
 
4272
        distanceToMove -= COLLISION_GRANULARITY;
 
 
4273
        particlePtr->Position.vx += MUL_FIXED(DirectionOfTravel.vx, distanceToMove);
 
 
4274
        particlePtr->Position.vy += MUL_FIXED(DirectionOfTravel.vy, distanceToMove);
 
 
4275
        particlePtr->Position.vz += MUL_FIXED(DirectionOfTravel.vz, distanceToMove);
 
 
4276
    }
 
 
4277
 
 
 
4278
    if (hitObstacle)
 
 
4279
    {
 
 
4280
        int magOfPerpImp = DotProduct(obstacleNormalPtr, &particlePtr->Velocity);
 
 
4281
        int magnitude = Magnitude(&particlePtr->Velocity);
 
 
4282
        particlePtr->Velocity.vx -= MUL_FIXED(obstacleNormalPtr->vx, magOfPerpImp);
 
 
4283
        particlePtr->Velocity.vy -= MUL_FIXED(obstacleNormalPtr->vy, magOfPerpImp);
 
 
4284
        particlePtr->Velocity.vz -= MUL_FIXED(obstacleNormalPtr->vz, magOfPerpImp);
 
 
4285
 
 
 
4286
        if(particlePtr->Velocity.vx || particlePtr->Velocity.vy || particlePtr->Velocity.vz)
 
 
4287
        {
 
 
4288
            Normalise(&particlePtr->Velocity);
 
 
4289
            particlePtr->Velocity.vx = MUL_FIXED(particlePtr->Velocity.vx, magnitude/2);
 
 
4290
            particlePtr->Velocity.vy = MUL_FIXED(particlePtr->Velocity.vy, magnitude/2);
 
 
4291
            particlePtr->Velocity.vz = MUL_FIXED(particlePtr->Velocity.vz, magnitude/2);
 
 
4292
        }
 
 
4293
    }
 
 
4294
 
 
 
4295
    /* test to see if you've hit any objects */
 
 
4296
    if(NULL == hitModule)
 
 
4297
    {
 
 
4298
        int i = NumberOfDynamicObjects;
 
 
4299
 
 
 
4300
        if (prevPosition.vx > particlePtr->Position.vx)
 
 
4301
        {
 
 
4302
            DBBMinX = particlePtr->Position.vx;
 
 
4303
            DBBMaxX = prevPosition.vx;
 
 
4304
        }    
 
 
4305
        else
 
 
4306
        {
 
 
4307
            DBBMinX = prevPosition.vx;
 
 
4308
            DBBMaxX = particlePtr->Position.vx;
 
 
4309
        }
 
 
4310
 
 
 
4311
        if (prevPosition.vy > particlePtr->Position.vy)
 
 
4312
        {
 
 
4313
            DBBMinY = particlePtr->Position.vy;
 
 
4314
            DBBMaxY = prevPosition.vy;
 
 
4315
        }    
 
 
4316
        else
 
 
4317
        {
 
 
4318
            DBBMinY = prevPosition.vy;
 
 
4319
            DBBMaxY = particlePtr->Position.vy;
 
 
4320
        }
 
 
4321
 
 
 
4322
        if (prevPosition.vz > particlePtr->Position.vz)
 
 
4323
        {
 
 
4324
            DBBMinZ = particlePtr->Position.vz;
 
 
4325
            DBBMaxZ = prevPosition.vz;
 
 
4326
        }    
 
 
4327
        else
 
 
4328
        {
 
 
4329
            DBBMinZ = prevPosition.vz;
 
 
4330
            DBBMaxZ = particlePtr->Position.vz;
 
 
4331
        }
 
 
4332
 
 
 
4333
        /* scan through objects */
 
 
4334
        while(i--)
 
 
4335
        {
 
 
4336
            STRATEGYBLOCK *sbPtr = DynamicObjectsList[i].sbptr;
 
 
4337
            DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
4338
 
 
 
4339
            if (((DBBMinX < dynPtr->ObjectVertices[0].vx) && (DBBMaxX > dynPtr->ObjectVertices[7].vx))
 
 
4340
            &&
 
 
4341
            ((DBBMinY < dynPtr->ObjectVertices[0].vy) && (DBBMaxY > dynPtr->ObjectVertices[7].vy))
 
 
4342
            &&
 
 
4343
            ((DBBMinZ < dynPtr->ObjectVertices[0].vz) && (DBBMaxZ > dynPtr->ObjectVertices[7].vz)))
 
 
4344
            {
 
 
4345
                /* blam! particle hit something */
 
 
4346
                switch(particlePtr->ParticleID)
 
 
4347
                {
 
 
4348
                    case PARTICLE_ALIEN_BLOOD:
 
 
4349
                    {
 
 
4350
                        switch(sbPtr->type)
 
 
4351
                        {
 
 
4352
                            case I_BehaviourMarinePlayer:
 
 
4353
                            case I_BehaviourPredatorPlayer:
 
 
4354
                            case I_BehaviourMarine:
 
 
4355
                            case I_BehaviourPredator:
 
 
4356
                            case I_BehaviourPlacedLight:
 
 
4357
                            case I_BehaviourAutoGun:
 
 
4358
                                CauseDamageToObject(sbPtr, &TemplateAmmo[AMMO_ALIEN_FRAG].MaxDamage, NormalFrameTime, &particlePtr->Velocity);
 
 
4359
                                particlePtr->LifeTime = 0;
 
 
4360
                            default:
 
 
4361
                            break;
 
 
4362
                        }
 
 
4363
                    }
 
 
4364
                    break;
 
 
4365
                    case PARTICLE_EXPLOSIONFIRE:
 
 
4366
                    {
 
 
4367
                        if(particlePtr->Velocity.vx || particlePtr->Velocity.vy || particlePtr->Velocity.vz)
 
 
4368
                            CauseDamageToObject(sbPtr, &TemplateAmmo[EXPLOSIONFIRE_BLAST].MaxDamage, NormalFrameTime, &particlePtr->Velocity);
 
 
4369
                        else
 
 
4370
                            CauseDamageToObject(sbPtr, &damage_profiles[AMMO_FIREDAMAGE], NormalFrameTime*2, NULL);
 
 
4371
                    }
 
 
4372
                    break;
 
 
4373
                    case PARTICLE_FLAME:
 
 
4374
                    case PARTICLE_MOLOTOVFLAME:
 
 
4375
                    {
 
 
4376
                        int ignoreDamage = 0;
 
 
4377
 
 
 
4378
                        if(SinglePlayer != AvP.PlayMode)
 
 
4379
                        {
 
 
4380
                            //If friendly fire has been disabled , we may need to ignore this option
 
 
4381
                            if(particlePtr->ParticleID == PARTICLE_FLAME)
 
 
4382
                            {
 
 
4383
                                if (netGameData.disableFriendlyFire && (netGameData.gameType == NGT_CoopDeathmatch || netGameData.gameType == NGT_Coop))
 
 
4384
                                {
 
 
4385
                                    //okay , friendly fire is off , so flamethrower particles , can't harm
 
 
4386
                                    //marines. In coop games it shouldn't harm predators either
 
 
4387
 
 
 
4388
                                    if(sbPtr->type == I_BehaviourNetGhost)
 
 
4389
                                    {
 
 
4390
                                        NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *) sbPtr->dataptr;
 
 
4391
 
 
 
4392
                                        if ((ghostData->type == I_BehaviourMarinePlayer)
 
 
4393
                                        || (ghostData->type == I_BehaviourPredatorPlayer && netGameData.gameType == NGT_Coop))
 
 
4394
                                        {
 
 
4395
                                            ignoreDamage = 1;
 
 
4396
                                        }
 
 
4397
                                    }
 
 
4398
 
 
 
4399
                                    if(sbPtr == PlayerStatus.sbptr)
 
 
4400
                                    {
 
 
4401
                                        if(AvP.PlayerType == I_Marine || (AvP.PlayerType == I_Predator && netGameData.gameType == NGT_Coop))
 
 
4402
                                            ignoreDamage = 1;
 
 
4403
                                    }
 
 
4404
                                }
 
 
4405
                            }
 
 
4406
 
 
 
4407
                            if(!ignoreDamage)
 
 
4408
                            {
 
 
4409
                                if(sbPtr == PlayerStatus.sbptr)
 
 
4410
                                {
 
 
4411
                                    extern int myIgniterId;
 
 
4412
                                    myIgniterId = 0; //the player hasn't been set alight by a network opponent
 
 
4413
                                }
 
 
4414
                                else if(sbPtr->type == I_BehaviourAlien)
 
 
4415
                                {
 
 
4416
                                    //note that the alien has been set on fire locally
 
 
4417
                                    ALIEN_STATUS_BLOCK *alienStatus = (ALIEN_STATUS_BLOCK *)sbPtr->dataptr;
 
 
4418
 
 
 
4419
                                    if(particlePtr->ParticleID == PARTICLE_FLAME)
 
 
4420
                                    {
 
 
4421
                                        extern int AVPDPNetID;
 
 
4422
                                        alienStatus->aliensIgniterId = AVPDPNetID;
 
 
4423
                                    }
 
 
4424
                                    else
 
 
4425
                                    {
 
 
4426
                                        //no credit for aliens killed by molotov particles , or
 
 
4427
                                        //particle generator particles.
 
 
4428
                                        alienStatus->aliensIgniterId = 0;
 
 
4429
                                    }
 
 
4430
                                }
 
 
4431
                            }
 
 
4432
                        }
 
 
4433
 
 
 
4434
                        if(!ignoreDamage)
 
 
4435
                        {
 
 
4436
                            if(sbPtr->type == I_BehaviourNetGhost)
 
 
4437
                            {
 
 
4438
                                /*
 
 
4439
                                Don't let molotov particles damage netghosts. Each machine in a net game will be generating
 
 
4440
                                its own molotov particles.
 
 
4441
                                */
 
 
4442
 
 
 
4443
                                if(particlePtr->ParticleID == PARTICLE_FLAME)
 
 
4444
                                {
 
 
4445
                                    NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *) sbPtr->dataptr;
 
 
4446
 
 
 
4447
                                    //just add up the number of particles that have hit the ghost 
 
 
4448
                                    //so the damage message can be sent in one block
 
 
4449
                                    ghostData->FlameHitCount++;
 
 
4450
                                    sbPtr->DamageBlock.IsOnFire = 1;
 
 
4451
                                }
 
 
4452
                            }
 
 
4453
                            else
 
 
4454
                            {
 
 
4455
                                //CauseDamageToObject(sbPtr, &TemplateAmmo[AMMO_FLAMETHROWER].MaxDamage, ONE_FIXED/400, &particlePtr->Velocity);
 
 
4456
                                CauseDamageToObject(sbPtr, &TemplateAmmo[AMMO_FLAMETHROWER].MaxDamage, ONE_FIXED/400, NULL);
 
 
4457
                            }
 
 
4458
                        }
 
 
4459
                    }
 
 
4460
                    break;
 
 
4461
                    case PARTICLE_ELECTRICALPLASMASPHERE:
 
 
4462
                    {
 
 
4463
                        CauseDamageToObject(sbPtr, &damage_profiles[AMMO_PRED_PISTOL_BLAST], ONE_FIXED, &particlePtr->Velocity);
 
 
4464
                    }
 
 
4465
                    break;
 
 
4466
                    case PARTICLE_FLECHETTE:
 
 
4467
                    {
 
 
4468
                        if(sbPtr->type == I_BehaviourNetGhost)
 
 
4469
                        {
 
 
4470
                            //for net ghosts add up all the flechettes that hit it this frame , and send as one
 
 
4471
                            //damage message
 
 
4472
                            NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *) sbPtr->dataptr;
 
 
4473
                            assert(ghostData);
 
 
4474
                            ghostData->FlechetteHitCount++;
 
 
4475
                        }
 
 
4476
                        else
 
 
4477
                        {
 
 
4478
                            CauseDamageToObject(sbPtr, &damage_profiles[FLECHETTEDAMAGE], ONE_FIXED, &particlePtr->Velocity);
 
 
4479
                        }
 
 
4480
                    }
 
 
4481
                    default:
 
 
4482
                    break;
 
 
4483
                }
 
 
4484
            }
 
 
4485
        }
 
 
4486
    }
 
 
4487
 
 
 
4488
return hitObstacle;
 
 
4489
}
 
 
4490
 
 
 
4491
#include "los.h"
 
 
4492
#include "targeting.h"
 
 
4493
 
 
 
4494
#define POLY_REJECT_RANGE 500
 
 
4495
 
 
 
4496
static VECTORCH *ViewpointDirectionPtr;
 
 
4497
static VECTORCH *ViewpointPositionPtr;
 
 
4498
 
 
 
4499
static void CheckForRayIntersectionWithObject(DISPLAYBLOCK *dPtr)
 
 
4500
{
 
 
4501
    VECTORCH viewVectorAlpha = *ViewpointPositionPtr;
 
 
4502
    VECTORCH viewVectorBeta = *ViewpointDirectionPtr;
 
 
4503
    int needToRotate = 0;
 
 
4504
 
 
 
4505
    if((dPtr->ObFlags & ObFlag_NotVis) || (!dPtr->ObShape && dPtr->SfxPtr))
 
 
4506
        return;
 
 
4507
 
 
 
4508
    /* any hierarchical models should have been split up by now */
 
 
4509
 
 
 
4510
    STRATEGYBLOCK* sbPtr = dPtr->ObStrategyBlock;
 
 
4511
 
 
 
4512
    /* test for objects we're not interested in */
 
 
4513
    if (sbPtr && sbPtr->DynPtr)
 
 
4514
    {
 
 
4515
        /* ignore it if it's a non-collideable object, eg. debris */
 
 
4516
        if(sbPtr->DynPtr->DynamicsType == DYN_TYPE_NO_COLLISIONS)
 
 
4517
            return;
 
 
4518
    }
 
 
4519
 
 
 
4520
    if((dPtr->ObWorld.vx > 1000000) || (dPtr->ObWorld.vx < -1000000)
 
 
4521
    || (dPtr->ObWorld.vy > 1000000) || (dPtr->ObWorld.vy < -1000000)
 
 
4522
    || (dPtr->ObWorld.vz > 1000000) || (dPtr->ObWorld.vz < -1000000))
 
 
4523
    {
 
 
4524
        printf("Pre assertions check for having processed the section...\n");
 
 
4525
        //printf("State of initialised flag: %x\n",(sectionDataPtr->flags & section_data_initialised));
 
 
4526
        //printf("Name of section: %s\n",sectionDataPtr->sempai->Section_Name);
 
 
4527
        //printf("It was playing sequence: %d,%d\n",sectionDataPtr->my_controller->Sequence_Type,
sectionDataPtr->my_controller->Sub_Sequence);
 
 
4528
 
 
 
4529
        printf("position %d,%d,%d is module %s ", dPtr->ObWorld.vx, dPtr->ObWorld.vy, dPtr->ObWorld.vz, (dPtr->Module ? "yes" :
"no"));
 
 
4530
 
 
 
4531
        if(NULL != sbPtr)
 
 
4532
        {
 
 
4533
            printf("type %d\n\n", sbPtr->type);
 
 
4534
 
 
 
4535
            if(I_BehaviourFragment == sbPtr->type)
 
 
4536
            {
 
 
4537
                sbPtr->please_destroy_me = 1;
 
 
4538
                return;
 
 
4539
            }
 
 
4540
        }
 
 
4541
        else
 
 
4542
        {
 
 
4543
            printf("has no strategyblock\n\n");
 
 
4544
            //DestroyActiveObject(&dPtr);
 
 
4545
            //return;
 
 
4546
        }
 
 
4547
 
 
 
4548
        //assert(sectionDataPtr->flags & section_data_initialised);
 
 
4549
        return;
 
 
4550
    }
 
 
4551
 
 
 
4552
    VECTORCH position = dPtr->ObWorld;
 
 
4553
 
 
 
4554
    /* transform view line into shape space */
 
 
4555
    viewVectorAlpha.vx -= position.vx;
 
 
4556
    viewVectorAlpha.vy -= position.vy;
 
 
4557
    viewVectorAlpha.vz -= position.vz;
 
 
4558
 
 
 
4559
    if(dPtr->ShapeData && (MagnitudeOfCrossProduct(&viewVectorAlpha, &viewVectorBeta) > dPtr->ShapeData->shaperadius))
 
 
4560
        return;
 
 
4561
 
 
 
4562
    /* if we're not dealing with a module, it's probably rotated */
 
 
4563
    if(!dPtr->Module)
 
 
4564
    {
 
 
4565
        needToRotate = 1;
 
 
4566
        MATRIXCH matrix = dPtr->ObMat;
 
 
4567
        TransposeMatrixCH(&matrix);
 
 
4568
        RotateVector(&viewVectorBeta, &matrix);
 
 
4569
        RotateVector(&viewVectorAlpha, &matrix);
 
 
4570
    }
 
 
4571
 
 
 
4572
    int numberOfItems = SetupPolygonAccess(dPtr);
 
 
4573
 
 
 
4574
    //if (!dPtr->ObShape) printf("polys %d\n", numberOfItems);
 
 
4575
 
 
 
4576
      while(numberOfItems--)
 
 
4577
    {
 
 
4578
        struct ColPolyTag polyData;
 
 
4579
        VECTORCH pointOnPlane;
 
 
4580
        VECTORCH polyNormal;
 
 
4581
        int lambda;
 
 
4582
        int axis1;
 
 
4583
        int axis2;
 
 
4584
 
 
 
4585
        /* scanning through polys */
 
 
4586
        int *itemPtr = *(ItemArrayPtr++);
 
 
4587
        PolyheaderPtr = (POLYHEADER *) itemPtr;
 
 
4588
 
 
 
4589
        if((PolyheaderPtr->PolyFlags & iflag_notvis) && !(PolyheaderPtr->PolyFlags & iflag_mirror))
 
 
4590
                continue;
 
 
4591
        {
 
 
4592
            GetPolygonNormal(&polyData);
 
 
4593
            polyNormal = polyData.PolyNormal;
 
 
4594
            int normDotBeta = DotProduct(&polyNormal, &viewVectorBeta);
 
 
4595
 
 
 
4596
            {
 
 
4597
                /* if the polygon is flagged as double-sided, and it's pointing
 
 
4598
                the wrong way, consider it to be flipped round */
 
 
4599
                //if((PolyheaderPtr->PolyFlags) & iflag_no_bfc)
 
 
4600
                /* KJL 16:06:11 10/07/98 - treat all polys as no bfc */
 
 
4601
                {
 
 
4602
                    if (normDotBeta > 0)
 
 
4603
                    {
 
 
4604
                        normDotBeta = -normDotBeta;
 
 
4605
                        polyNormal.vx = -polyNormal.vx;
 
 
4606
                        polyNormal.vy = -polyNormal.vy;
 
 
4607
                        polyNormal.vz = -polyNormal.vz;
 
 
4608
                    }
 
 
4609
                }
 
 
4610
            }
 
 
4611
 
 
 
4612
            /* trivial rejection of poly if it is not facing LOS */
 
 
4613
               if (normDotBeta > -POLY_REJECT_RANGE)
 
 
4614
                   continue;
 
 
4615
 
 
 
4616
            GetPolygonVertices(&polyData);
 
 
4617
 
 
 
4618
            /* calculate coords of plane-line intersection */
 
 
4619
            {
 
 
4620
                /* get a pt in the poly */
 
 
4621
                VECTORCH pop = polyData.PolyPoint[0];                                  
 
 
4622
                pop.vx -= viewVectorAlpha.vx;
 
 
4623
                pop.vy -= viewVectorAlpha.vy;
 
 
4624
                pop.vz -= viewVectorAlpha.vz;
 
 
4625
 
 
 
4626
                  int d = DotProduct(&polyNormal, &pop);
 
 
4627
 
 
 
4628
                if (d > 0)
 
 
4629
                    continue;
 
 
4630
 
 
 
4631
                  lambda = DIV_FIXED(d, normDotBeta);
 
 
4632
 
 
 
4633
                if (lambda >= LOS_Lambda) 
 
 
4634
                    continue;
 
 
4635
 
 
 
4636
                   pointOnPlane.vx    = viewVectorAlpha.vx + MUL_FIXED(lambda, viewVectorBeta.vx);
 
 
4637
                    pointOnPlane.vy    = viewVectorAlpha.vy + MUL_FIXED(lambda, viewVectorBeta.vy);
 
 
4638
                   pointOnPlane.vz    = viewVectorAlpha.vz + MUL_FIXED(lambda, viewVectorBeta.vz);
 
 
4639
              }
 
 
4640
 
 
 
4641
            /* decide which 2d plane to project onto */
 
 
4642
 
 
 
4643
            {
 
 
4644
                int x = abs(polyNormal.vx);
 
 
4645
                int y = abs(polyNormal.vy);
 
 
4646
                int z = abs(polyNormal.vz);
 
 
4647
 
 
 
4648
                if (x > y)
 
 
4649
                {
 
 
4650
                    if (x > z)
 
 
4651
                    {
 
 
4652
                        axis1 = iy;
 
 
4653
                        axis2 = iz;
 
 
4654
                    }
 
 
4655
                    else
 
 
4656
                    {
 
 
4657
                        axis1 = ix;
 
 
4658
                        axis2 = iy;
 
 
4659
                    }
 
 
4660
                }
 
 
4661
                else
 
 
4662
                {
 
 
4663
                    if (y > z)
 
 
4664
                    {
 
 
4665
                        axis1 = ix;
 
 
4666
                        axis2 = iz;
 
 
4667
                    }
 
 
4668
                    else
 
 
4669
                    {
 
 
4670
                        axis1 = ix;
 
 
4671
                        axis2 = iy;
 
 
4672
                    }
 
 
4673
                }
 
 
4674
            }
 
 
4675
        }
 
 
4676
 
 
 
4677
        {
 
 
4678
            int projectedPolyVertex[20];
 
 
4679
            int projectedPointOnPlane[2];
 
 
4680
            int *popPtr = &pointOnPlane.vx;
 
 
4681
 
 
 
4682
            projectedPointOnPlane[0] = *(popPtr + axis1);
 
 
4683
             projectedPointOnPlane[1] = *(popPtr + axis2);
 
 
4684
 
 
 
4685
             {
 
 
4686
                 VECTORCH *vertexPtr = &polyData.PolyPoint[0];
 
 
4687
                 int *projectedVertexPtr= projectedPolyVertex;
 
 
4688
                int noOfVertices = polyData.NumberOfVertices;
 
 
4689
 
 
 
4690
                do
 
 
4691
                {
 
 
4692
                     *projectedVertexPtr++ = *((int*)vertexPtr + axis1);
 
 
4693
                     *projectedVertexPtr++ = *((int*)vertexPtr + axis2);
 
 
4694
 
 
 
4695
                         vertexPtr++;
 
 
4696
 
 
 
4697
                 } while(--noOfVertices);
 
 
4698
             }
 
 
4699
 
 
 
4700
            if (PointInPolygon(projectedPointOnPlane, projectedPolyVertex, polyData.NumberOfVertices, 2))
 
 
4701
            {
 
 
4702
                /* rotate vector back into World Space if it's not a module */
 
 
4703
                LOS_ObjectNormal = polyNormal;
 
 
4704
 
 
 
4705
                if (needToRotate)
 
 
4706
                {
 
 
4707
                    MATRIXCH matrix = dPtr->ObMat;
 
 
4708
                    RotateVector(&pointOnPlane, &matrix);
 
 
4709
                    RotateVector(&LOS_ObjectNormal, &matrix);
 
 
4710
                }
 
 
4711
 
 
 
4712
                /* and translate origin */
 
 
4713
                pointOnPlane.vx += position.vx;
 
 
4714
                pointOnPlane.vy += position.vy;
 
 
4715
                pointOnPlane.vz += position.vz;
 
 
4716
 
 
 
4717
                LOS_Point = pointOnPlane;
 
 
4718
                LOS_ObjectHitPtr = dPtr;
 
 
4719
                LOS_Lambda = lambda;
 
 
4720
                LOS_HModel_Section = 0;
 
 
4721
            }
 
 
4722
        }
 
 
4723
    }
 
 
4724
}
 
 
4725
 
 
 
4726
extern const DISPLAYBLOCK Zero_Displayblock;
 
 
4727
 
 
 
4728
static void CheckForRayIntersectionWithHierarchy(DISPLAYBLOCK *objectPtr, SECTION_DATA *sectionDataPtr)
 
 
4729
{
 
 
4730
    if (sectionDataPtr)
 
 
4731
    {
 
 
4732
        SECTION *sectionPtr = sectionDataPtr->sempai;
 
 
4733
 
 
 
4734
        /* Unreal things can't be hit... */
 
 
4735
 
 
 
4736
        if (!(sectionDataPtr->flags & section_data_notreal) && (sectionPtr->Shape != NULL))
 
 
4737
        {
 
 
4738
            DISPLAYBLOCK dummy_displayblock = Zero_Displayblock;
 
 
4739
 
 
 
4740
            dummy_displayblock.ObShape = sectionPtr->ShapeNum;
 
 
4741
            dummy_displayblock.ShapeData = sectionPtr->Shape;
 
 
4742
            dummy_displayblock.ObWorld = sectionDataPtr->World_Offset;
 
 
4743
            dummy_displayblock.ObMat = sectionDataPtr->SecMat;
 
 
4744
            dummy_displayblock.ObStrategyBlock = objectPtr->ObStrategyBlock;
 
 
4745
 
 
 
4746
            CheckForRayIntersectionWithObject(&dummy_displayblock);
 
 
4747
 
 
 
4748
            if (LOS_ObjectHitPtr == &dummy_displayblock)
 
 
4749
            {
 
 
4750
                /* ah, we've hit this object */
 
 
4751
                LOS_ObjectHitPtr = objectPtr;
 
 
4752
                LOS_HModel_Section = sectionDataPtr;
 
 
4753
                return;
 
 
4754
            }
 
 
4755
        }
 
 
4756
 
 
 
4757
        if (sectionDataPtr->First_Child != NULL)
 
 
4758
        {
 
 
4759
            SECTION_DATA *childrenListPtr = sectionDataPtr->First_Child;
 
 
4760
 
 
 
4761
            while (childrenListPtr != NULL)
 
 
4762
            {
 
 
4763
                CheckForRayIntersectionWithHierarchy(objectPtr, childrenListPtr);
 
 
4764
                childrenListPtr = childrenListPtr->Next_Sibling;
 
 
4765
            }
 
 
4766
        }
 
 
4767
    }
 
 
4768
}
 
 
4769
 
 
 
4770
/*    KJL 15:26:08 14/05/98 - FindPolygonInLineOfSight
 
 
4771
 
 
 
4772
    Using either the Active or OnScreen Block list, find which polygon you would hit first
 
 
4773
    if a ray of light was cast out from a given point in world space (viewpointPositionPtr)
 
 
4774
    in a given direction (viewpointDirectionPtr).
 
 
4775
 
 
 
4776
    The following are set:
 
 
4777
 
 
 
4778
    LOS_ObjectHitPtr    - dispPtr of hit object (NULL if none found)
 
 
4779
    LOS_Lambda        - distance to hit polygon (or max if no hit)           
 
 
4780
    LOS_Point        - world space coords of intersection of ray & hit poly
 
 
4781
    LOS_ObjectNormal    - normal of the hit polygon
 
 
4782
    LOS_HModel_Section    - hierarchical section that was hit (or NULL if not hmodel)
 
 
4783
*/
 
 
4784
 
 
 
4785
int FindPolygonInLineOfSight(VECTORCH *viewpointDirectionPtr, VECTORCH *viewpointPositionPtr, DISPLAYBLOCK *objectToIgnorePtr)
 
 
4786
{
 
 
4787
       int numberOfObjects = NumActiveBlocks;
 
 
4788
    DISPLAYBLOCK **displayBlockList = ActiveBlockList;
 
 
4789
 
 
 
4790
      LOS_Lambda = 10000000;
 
 
4791
    LOS_ObjectHitPtr = NULL;
 
 
4792
    LOS_HModel_Section = NULL;
 
 
4793
    ViewpointPositionPtr = viewpointPositionPtr;
 
 
4794
    ViewpointDirectionPtr = viewpointDirectionPtr;
 
 
4795
 
 
 
4796
       while (numberOfObjects--)
 
 
4797
    {
 
 
4798
        DISPLAYBLOCK* objectPtr = displayBlockList[numberOfObjects];
 
 
4799
 
 
 
4800
        if (objectPtr != objectToIgnorePtr)
 
 
4801
        {
 
 
4802
            /* if hierarchical model, consider each object in the model separately */
 
 
4803
 
 
 
4804
            if (objectPtr->HModelControlBlock)
 
 
4805
                CheckForRayIntersectionWithHierarchy(objectPtr, objectPtr->HModelControlBlock->section_data);
 
 
4806
            else
 
 
4807
                CheckForRayIntersectionWithObject(objectPtr);
 
 
4808
        }
 
 
4809
    }
 
 
4810
 
 
 
4811
return NULL != LOS_ObjectHitPtr;
 
 
4812
}
 
 
4813
 
 
 
4814
int IsThisObjectVisibleFromThisPosition_WithIgnore(DISPLAYBLOCK *objectPtr, DISPLAYBLOCK *ignoredObjectPtr, VECTORCH *positionPtr)
 
 
4815
{
 
 
4816
    VECTORCH viewVector;  /* direction of view-line */
 
 
4817
 
 
 
4818
    assert(objectPtr);
 
 
4819
 
 
 
4820
    /* try to look at the centre of the object */
 
 
4821
    GetTargetingPointOfObject(objectPtr, &viewVector);
 
 
4822
 
 
 
4823
       viewVector.vx -= positionPtr->vx;
 
 
4824
    viewVector.vy -= positionPtr->vy;
 
 
4825
    viewVector.vz -= positionPtr->vz;
 
 
4826
    Normalise(&viewVector);
 
 
4827
 
 
 
4828
    FindPolygonInLineOfSight(&viewVector, positionPtr, ignoredObjectPtr);
 
 
4829
 
 
 
4830
return (LOS_ObjectHitPtr == objectPtr);
 
 
4831
}
 
 
4832
 
 
 
4833
int IsThisObjectVisibleFromThisPosition(DISPLAYBLOCK *objectPtr,VECTORCH *positionPtr)
 
 
4834
{     
 
 
4835
    VECTORCH viewVector;  /* direction of view-line */
 
 
4836
 
 
 
4837
    assert(objectPtr);
 
 
4838
 
 
 
4839
    /* try to look at the centre of the object */
 
 
4840
    GetTargetingPointOfObject(objectPtr, &viewVector);
 
 
4841
 
 
 
4842
       viewVector.vx -= positionPtr->vx;
 
 
4843
    viewVector.vy -= positionPtr->vy;
 
 
4844
    viewVector.vz -= positionPtr->vz;
 
 
4845
    Normalise(&viewVector);
 
 
4846
 
 
 
4847
    FindPolygonInLineOfSight(&viewVector, positionPtr,  0);
 
 
4848
 
 
 
4849
return (LOS_ObjectHitPtr == objectPtr);
 
 
4850
}
 
 
4851
 
 
 
4852
void CheckForVectorIntersectionWith3dObject(DISPLAYBLOCK *objectPtr, VECTORCH *viewVectorAlphaPtr, VECTORCH *viewVectorBetaPtr)
 
 
4853
{
 
 
4854
    ViewpointPositionPtr = viewVectorAlphaPtr;
 
 
4855
    ViewpointDirectionPtr = viewVectorBetaPtr;
 
 
4856
    LOS_ObjectHitPtr = NULL;
 
 
4857
    LOS_Lambda = NPC_MAX_VIEWRANGE;
 
 
4858
    LOS_HModel_Section = NULL;
 
 
4859
 
 
 
4860
    if (objectPtr->HModelControlBlock)
 
 
4861
          CheckForRayIntersectionWithHierarchy(objectPtr, objectPtr->HModelControlBlock->section_data);
 
 
4862
    else
 
 
4863
        CheckForRayIntersectionWithObject(objectPtr);
 
 
4864
}
 
 
4865
 
 
 
4866
/*-----------------------Patrick 1/12/96--------------------------
 
 
4867
  I have added this function to initialise polygon access for a
 
 
4868
  module based on the shape index specified in its mapblock....
 
 
4869
  Specifically, this is for setting up location data for modules
 
 
4870
  during game initialisation, and so doesn't support morphing.
 
 
4871
  ----------------------------------------------------------------*/
 
 
4872
int SetupPolygonAccessFromShapeIndex(int shapeIndex)
 
 
4873
{
 
 
4874
    struct shapeheader* shape1Ptr = GetShapeData(shapeIndex);
 
 
4875
 
 
 
4876
    ShapePointsPtr  = (VECTORCH *)(*shape1Ptr->points);
 
 
4877
    ShapeNormalsPtr = (int *)(*shape1Ptr->sh_normals);
 
 
4878
    ItemArrayPtr = (int **)shape1Ptr->items;
 
 
4879
    ShapeIsMorphed = 0;
 
 
4880
 
 
 
4881
    {
 
 
4882
        int *itemPtr = *ItemArrayPtr;
 
 
4883
        PolyheaderPtr = (POLYHEADER *) itemPtr;
 
 
4884
    }
 
 
4885
 
 
 
4886
return shape1Ptr->numitems;
 
 
4887
}
 
 
4888
 
 
 
4889
static int (*DistanceMovedBeforeObjectHitsPolygon)(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove, const VECTORCH *DirectionOfTravel);
 
 
4890
 
 
 
4891
void MovePlatformLift(STRATEGYBLOCK *sbPtr)
 
 
4892
{
 
 
4893
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
4894
    VECTORCH obstacleNormal;
 
 
4895
    STRATEGYBLOCK *obstacleSBPtr = NULL;
 
 
4896
    VECTORCH DirectionOfTravel = dynPtr->Displacement;
 
 
4897
 
 
 
4898
{
 
 
4899
    dynPtr->CollisionReportPtr = NULL;
 
 
4900
 
 
 
4901
    CreateNRBBForObject(sbPtr);
 
 
4902
 
 
 
4903
    dynPtr->PrevPosition = dynPtr->Position;
 
 
4904
    //dynPtr->PrevOrientMat = dynPtr->OrientMat;
 
 
4905
    //dynPtr->IsInContactWithFloor = 0;
 
 
4906
    //dynPtr->IsInContactWithNearlyFlatFloor = 0;
 
 
4907
 
 
 
4908
    dynPtr->Displacement.vx += MUL_FIXED(dynPtr->LinVelocity.vx, NormalFrameTime);
 
 
4909
    dynPtr->Displacement.vy += MUL_FIXED(dynPtr->LinVelocity.vy, NormalFrameTime);
 
 
4910
    dynPtr->Displacement.vz += MUL_FIXED(dynPtr->LinVelocity.vz, NormalFrameTime);
 
 
4911
    dynPtr->DistanceLeftToMove = Magnitude(&dynPtr->Displacement);
 
 
4912
 
 
 
4913
    if (dynPtr->DistanceLeftToMove > ONE_FIXED / 8)
 
 
4914
    {
 
 
4915
        dynPtr->DistanceLeftToMove = ONE_FIXED/8;
 
 
4916
        Normalise(&dynPtr->Displacement);
 
 
4917
        dynPtr->Displacement.vx /= 8;
 
 
4918
        dynPtr->Displacement.vy /= 8;
 
 
4919
        dynPtr->Displacement.vz /= 8;
 
 
4920
    }
 
 
4921
 
 
 
4922
    MakeStaticBoundingBoxForObject = MakeStaticBoundingBoxForNRBB;
 
 
4923
 
 
 
4924
    CollisionPolysPtr = CollisionPolysArray;
 
 
4925
    NumberOfCollisionPolys = 0;
 
 
4926
}
 
 
4927
 
 
 
4928
    Normalise(&DirectionOfTravel);
 
 
4929
 
 
 
4930
    /* make list of platform's polygons */
 
 
4931
    {
 
 
4932
        VECTORCH zero = {0,0,0};
 
 
4933
        MakeDynamicBoundingBoxForObject(sbPtr, &dynPtr->Position);
 
 
4934
        TestShapeWithDynamicBoundingBox(sbPtr->DisplayBlock, dynPtr);
 
 
4935
        MakeDynamicBoundingBoxForObject(sbPtr, &zero);
 
 
4936
    }
 
 
4937
 
 
 
4938
    // printf("polys on lift %d\n", NumberOfCollisionPolys);
 
 
4939
    DirectionOfTravel.vx = -DirectionOfTravel.vx;
 
 
4940
    DirectionOfTravel.vy = -DirectionOfTravel.vy;
 
 
4941
    DirectionOfTravel.vz = -DirectionOfTravel.vz;
 
 
4942
 
 
 
4943
    int i = NumberOfDynamicObjects;
 
 
4944
 
 
 
4945
    DistanceMovedBeforeObjectHitsPolygon = (DYN_TYPE_NRBB_COLLISIONS == dynPtr->DynamicsType) ? 
 
 
4946
    DistanceMovedBeforeNRBBHitsPolygon : DistanceMovedBeforeSphereHitsPolygon;
 
 
4947
 
 
 
4948
    while(i--)
 
 
4949
    {
 
 
4950
        STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i].sbptr;
 
 
4951
 
 
 
4952
        {
 
 
4953
            VECTORCH *objectVerticesPtr = obstaclePtr->DynPtr->ObjectVertices;
 
 
4954
 
 
 
4955
            if (!(
 
 
4956
            ((DBBMaxX >= objectVerticesPtr[7].vx) && (DBBMinX <= objectVerticesPtr[0].vx))
 
 
4957
            &&
 
 
4958
            ((DBBMaxY >= objectVerticesPtr[7].vy) && (DBBMinY <= objectVerticesPtr[0].vy))
 
 
4959
             &&
 
 
4960
            ((DBBMaxZ >= objectVerticesPtr[7].vz) && (DBBMinZ <= objectVerticesPtr[0].vz))))
 
 
4961
                continue;
 
 
4962
        }
 
 
4963
 
 
 
4964
        //printf("found an object type %d\n", obstaclePtr->type);
 
 
4965
        int polysLeft = NumberOfCollisionPolys;
 
 
4966
        int distanceToMove = dynPtr->DistanceLeftToMove;
 
 
4967
        struct ColPolyTag *nearPolysPtr = CollisionPolysArray;
 
 
4968
 
 
 
4969
        /* check against the landscape */
 
 
4970
 
 
 
4971
        while(polysLeft)
 
 
4972
        {
 
 
4973
            int distanceToObstacle = DistanceMovedBeforeObjectHitsPolygon(obstaclePtr->DynPtr, nearPolysPtr, distanceToMove, &DirectionOfTravel);
 
 
4974
 
 
 
4975
            if (distanceToObstacle >= 0)
 
 
4976
            {
 
 
4977
                distanceToMove = distanceToObstacle;
 
 
4978
                obstacleNormal = nearPolysPtr->PolyNormal;
 
 
4979
                obstacleSBPtr =    obstaclePtr;
 
 
4980
            }
 
 
4981
 
 
 
4982
            nearPolysPtr++;
 
 
4983
            polysLeft--;
 
 
4984
        }
 
 
4985
 
 
 
4986
        if (distanceToMove != dynPtr->DistanceLeftToMove)
 
 
4987
        {
 
 
4988
            if (dynPtr->Displacement.vy < 0)
 
 
4989
            {
 
 
4990
                VECTORCH displacement;
 
 
4991
                displacement.vx = displacement.vz = 0;
 
 
4992
                displacement.vy = -(dynPtr->DistanceLeftToMove - distanceToMove + COLLISION_GRANULARITY);
 
 
4993
 
 
 
4994
                obstaclePtr->DynPtr->Position.vx += displacement.vx;
 
 
4995
                obstaclePtr->DynPtr->Position.vy += displacement.vy;
 
 
4996
                obstaclePtr->DynPtr->Position.vz += displacement.vz;
 
 
4997
 
 
 
4998
                obstaclePtr->DynPtr->PrevPosition = obstaclePtr->DynPtr->Position;
 
 
4999
 
 
 
5000
                {
 
 
5001
                    VECTORCH *vertexPtr = obstaclePtr->DynPtr->ObjectVertices;
 
 
5002
                    int i=8;
 
 
5003
 
 
 
5004
                    do
 
 
5005
                    {
 
 
5006
                        vertexPtr->vy += displacement.vy;
 
 
5007
                        vertexPtr++;
 
 
5008
 
 
 
5009
                    } while(--i);
 
 
5010
                }
 
 
5011
 
 
 
5012
                /* look for polygons inside this volume */
 
 
5013
                FindLandscapePolygonsInObjectsVicinity(obstaclePtr);
 
 
5014
 
 
 
5015
                {
 
 
5016
                    int polysLeft = NumberOfCollisionPolys;
 
 
5017
                    struct ColPolyTag *polyPtr = CollisionPolysArray;
 
 
5018
 
 
 
5019
                    while(polysLeft)
 
 
5020
                    {
 
 
5021
                        if(DoesPolygonIntersectNRBB(polyPtr, obstaclePtr->DynPtr->ObjectVertices))
 
 
5022
                        {
 
 
5023
                                VECTORCH vertex = obstaclePtr->DynPtr->ObjectVertices[WhichNRBBVertex(&polyPtr->PolyNormal)];
 
 
5024
                                vertex.vx -= polyPtr->PolyPoint[0].vx;
 
 
5025
                                vertex.vy -= polyPtr->PolyPoint[0].vy;
 
 
5026
                                vertex.vz -= polyPtr->PolyPoint[0].vz;
 
 
5027
                                int greatestDistance = -DotProduct(&vertex, &polyPtr->PolyNormal);
 
 
5028
 
 
 
5029
                                if (greatestDistance > 0)
 
 
5030
                                {
 
 
5031
                                    /* sorry, no room! */
 
 
5032
 
 
 
5033
                                    obstaclePtr->DynPtr->Position.vx -= displacement.vx;
 
 
5034
                                    obstaclePtr->DynPtr->Position.vy -= displacement.vy;
 
 
5035
                                    obstaclePtr->DynPtr->Position.vz -= displacement.vz;
 
 
5036
                                    obstaclePtr->DynPtr->PrevPosition = obstaclePtr->DynPtr->Position;
 
 
5037
 
 
 
5038
                                    {
 
 
5039
                                        VECTORCH *vertexPtr = obstaclePtr->DynPtr->ObjectVertices;
 
 
5040
 
 
 
5041
                                        int i = 8;
 
 
5042
 
 
 
5043
                                        do
 
 
5044
                                        {
 
 
5045
                                            vertexPtr->vy -= displacement.vy;
 
 
5046
                                            vertexPtr++;
 
 
5047
 
 
 
5048
                                        } while(--i);
 
 
5049
                                    }
 
 
5050
 
 
 
5051
                                return;
 
 
5052
                                }
 
 
5053
                        }
 
 
5054
 
 
 
5055
                        polyPtr++;
 
 
5056
                        polysLeft--;
 
 
5057
                    }
 
 
5058
                }
 
 
5059
 
 
 
5060
                if (obstaclePtr->DynPtr->Displacement.vy > 0)
 
 
5061
                {
 
 
5062
                    obstaclePtr->DynPtr->Displacement.vy = 0;
 
 
5063
                    obstaclePtr->DynPtr->DistanceLeftToMove = Magnitude(&obstaclePtr->DynPtr->Displacement);
 
 
5064
                }
 
 
5065
 
 
 
5066
                if (obstaclePtr->DynPtr->LinImpulse.vy > 0)
 
 
5067
                    obstaclePtr->DynPtr->LinImpulse.vy = 0;
 
 
5068
            }
 
 
5069
 
 
 
5070
            {
 
 
5071
                COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
 
 
5072
 
 
 
5073
                if (NULL != reportPtr)
 
 
5074
                {
 
 
5075
                    reportPtr->ObstacleSBPtr = obstacleSBPtr;
 
 
5076
                    reportPtr->ObstacleNormal.vx = -obstacleNormal.vx;
 
 
5077
                    reportPtr->ObstacleNormal.vy = -obstacleNormal.vy;
 
 
5078
                    reportPtr->ObstacleNormal.vz = -obstacleNormal.vz;
 
 
5079
                    reportPtr->ModuleIndex = -1;
 
 
5080
                }
 
 
5081
            }
 
 
5082
 
 
 
5083
            if (NULL != obstacleSBPtr) /* give obstacle a report too */
 
 
5084
            {
 
 
5085
                COLLISIONREPORT *reportPtr = AllocateCollisionReport(obstacleSBPtr->DynPtr);
 
 
5086
 
 
 
5087
                if (NULL != reportPtr)
 
 
5088
                {
 
 
5089
                    reportPtr->ObstacleSBPtr = sbPtr;
 
 
5090
                    reportPtr->ObstacleNormal.vx = obstacleNormal.vx;
 
 
5091
                    reportPtr->ObstacleNormal.vy = obstacleNormal.vy;
 
 
5092
                    reportPtr->ObstacleNormal.vz = obstacleNormal.vz;
 
 
5093
                    reportPtr->ModuleIndex = -1;
 
 
5094
                }
 
 
5095
 
 
 
5096
                /* see if object has hit the 'floor' */
 
 
5097
                if (obstacleSBPtr->DynPtr->GravityOn)
 
 
5098
                {
 
 
5099
                    if (obstacleSBPtr->DynPtr->UseStandardGravity && PlanarGravity)
 
 
5100
                    {
 
 
5101
                        if (obstacleNormal.vy < -FLOOR_THRESHOLD)
 
 
5102
                        {
 
 
5103
                            obstacleSBPtr->DynPtr->IsInContactWithFloor = 1;
 
 
5104
 
 
 
5105
                            if (obstacleNormal.vy < -NEARLYFLATFLOOR_THRESHOLD)
 
 
5106
                                obstacleSBPtr->DynPtr->IsInContactWithNearlyFlatFloor = 1;
 
 
5107
                        }
 
 
5108
                    }
 
 
5109
                    else
 
 
5110
                    {
 
 
5111
                        int angle = DotProduct(&obstacleNormal, &obstacleSBPtr->DynPtr->GravityDirection);
 
 
5112
 
 
 
5113
                        if (angle < -FLOOR_THRESHOLD)
 
 
5114
                        {
 
 
5115
                            /* we've hit something that's against the direction of gravity */
 
 
5116
                            obstacleSBPtr->DynPtr->IsInContactWithFloor = 1;
 
 
5117
 
 
 
5118
                            if (angle < -NEARLYFLATFLOOR_THRESHOLD)
 
 
5119
                                obstacleSBPtr->DynPtr->IsInContactWithNearlyFlatFloor = 1;
 
 
5120
                        }
 
 
5121
                    }
 
 
5122
                }
 
 
5123
            }
 
 
5124
        }
 
 
5125
    }
 
 
5126
 
 
 
5127
    //printf("moving %d out of %d\n", distanceToMove, dynPtr->DistanceLeftToMove);
 
 
5128
     //printf("disp %d %d %d\n", displacement.vx, displacement.vy, displacement.vz);
 
 
5129
 
 
 
5130
    if (!((dynPtr->Displacement.vy > 0) && dynPtr->CollisionReportPtr))
 
 
5131
    {
 
 
5132
        dynPtr->Position.vx += dynPtr->Displacement.vx;
 
 
5133
        dynPtr->Position.vy += dynPtr->Displacement.vy;
 
 
5134
        dynPtr->Position.vz += dynPtr->Displacement.vz;
 
 
5135
    }
 
 
5136
 
 
 
5137
    UpdateDisplayBlockData(sbPtr);
 
 
5138
}