1 /* KJL 12:42:43 29/12/98 - this is effectively Dynamics V4.0. If you think this code looks bad,
2 you should have seen the previous versions. */
3
4 #include "3dc.h"
5 #include "module.h"
6 #include "inline.h"
7 #include "stratdef.h"
8 #include "gamedef.h"
9 #include "dynblock.h"
10 #include "dynamics.h"
11
12 #include "bh_types.h"
13 #include "comp_shp.h"
14 #include "avpview.h"
15 #include "pvisible.h"
16 #include "extents.h"
17
18 #include "bh_marin.h"
19 #include "bh_pred.h"
20 #include "bh_alien.h"
21 #include "showcmds.h"
22 #include "pldghost.h"
23 #include "weapons.h"
24
25 #include "bh_track.h"
26 #include "bh_fan.h"
27 #include "detaillevels.h"
28 #include "dxlog.h"
29 #include "avp_userprofile.h"
30 #include "pfarlocs.h"
31 #include "particle.h"
32
33 #define UseLocalAssert Yes
34 #include "ourasert.h"
35
36 #define TELEPORT_IF_OUTSIDE_ENV 1
37 #define MINIMUM_BOUNDINGBOX_EXTENT 25
38
39
40 #define FLOOR_THRESHOLD 30000
41 #define NEARLYFLATFLOOR_THRESHOLD 60000
42
43 #if 0
44 extern int GlobalFrameCounter;
45 #define LogInfo LOGDXFMT
46 #else
47 #define LogInfo(args) (void)0
48 #endif
49
50 extern MORPHDISPLAY MorphDisplay;
51 extern VECTORCH MorphedPts[];
52 extern VECTORCH *ShapePointsPtr;
53 extern int *ShapeNormalsPtr;
54 extern int *Shape2NormalsPtr;
55 extern char ShapeIsMorphed;
56 extern int **ItemArrayPtr;
57 extern POLYHEADER *PolyheaderPtr;
58 extern DAMAGE_PROFILE FlechetteDamage;
59 extern DAMAGE_PROFILE FallingDamage;
60 extern DAMAGE_PROFILE PredPistol_FlechetteDamage;
61
62 #define AccessNextPolygon()\
63 {\
64 int *itemPtr = *(ItemArrayPtr++);\
65 PolyheaderPtr = (POLYHEADER *) itemPtr;\
66 }
67
68 #define GetPolygonVertices(polyPtr)\
69 {\
70 int *vertexNumberPtr = &PolyheaderPtr->Poly1stPt;\
71 \
72 (polyPtr)->PolyPoint[0] = *(ShapePointsPtr + *vertexNumberPtr++);\
73 (polyPtr)->PolyPoint[1] = *(ShapePointsPtr + *vertexNumberPtr++);\
74 (polyPtr)->PolyPoint[2] = *(ShapePointsPtr + *vertexNumberPtr++);\
75 \
76 if (*vertexNumberPtr != Term)\
77 {\
78 (polyPtr)->PolyPoint[3] = *(ShapePointsPtr + *vertexNumberPtr);\
79 (polyPtr)->NumberOfVertices=4; \
80 }\
81 else\
82 {\
83 (polyPtr)->NumberOfVertices=3; \
84 }\
85 }
86 #define GetPolygonNormal(polyPtr)\
87 { \
88 if (ShapeIsMorphed)\
89 {\
90 VECTORCH n1Ptr = *(VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex);\
91 VECTORCH n2Ptr = *(VECTORCH*)(Shape2NormalsPtr + PolyheaderPtr->PolyNormalIndex);\
92 \
93 if( ((n1Ptr.vx == n2Ptr.vx)\
94 && (n1Ptr.vy == n2Ptr.vy)\
95 && (n1Ptr.vz == n2Ptr.vz))\
96 || (MorphDisplay.md_lerp == 0) )\
97 {\
98 (polyPtr)->PolyNormal = n1Ptr;\
99 }\
100 else if(MorphDisplay.md_lerp == 0xffff)\
101 {\
102 (polyPtr)->PolyNormal = n2Ptr;\
103 }\
104 else\
105 {\
106 VECTORCH *pointPtr[3];\
107 int *vertexNumPtr = &PolyheaderPtr->Poly1stPt;\
108 \
109 pointPtr[0] = (ShapePointsPtr + *vertexNumPtr++);\
110 pointPtr[1] = (ShapePointsPtr + *vertexNumPtr++);\
111 pointPtr[2] = (ShapePointsPtr + *vertexNumPtr);\
112 \
113 MakeNormal\
114 (\
115 pointPtr[0],\
116 pointPtr[1],\
117 pointPtr[2],\
118 &(polyPtr)->PolyNormal\
119 );\
120 }\
121 }\
122 else /* not morphed */\
123 {\
124 (polyPtr)->PolyNormal = *(VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex);\
125 }\
126 }
127 #define PolygonFlag (PolyheaderPtr->PolyFlags)
128
129 /*KJL****************************************************************************************
130 * P R O T O T Y P E S *
131 ****************************************************************************************KJL*/
132 extern void ObjectDynamics(void);
133
134 static void InitialiseDynamicObjectsList(void);
135 static void UpdateDisplayBlockData(STRATEGYBLOCK *sbPtr);
136
137 static void ApplyGravity(DYNAMICSBLOCK *dynPtr);
138 static void AlignObjectToGravityDirection(DYNAMICSBLOCK *dynPtr);
139 static void AlignObjectToStandardGravityDirection(DYNAMICSBLOCK *dynPtr);
140 static void VectorHomingForSurfaceAlign(VECTORCH *currentPtr, VECTORCH *targetPtr, VECTORCH *perpendicularPtr);
141
142 extern void DynamicallyRotateObject(DYNAMICSBLOCK *dynPtr);
143
144 static void FindLandscapePolygonsInObjectsPath(STRATEGYBLOCK *sbPtr);
145 static void FindObjectsToRelocateAgainst(STRATEGYBLOCK *sbPtr);
146 static void FindObjectPolygonsInObjectsPath(STRATEGYBLOCK *sbPtr);
147
148 static void MakeDynamicBoundingBoxForObject(STRATEGYBLOCK *sbPtr, VECTORCH *worldOffsetPtr);
149 static void TestShapeWithDynamicBoundingBox(DISPLAYBLOCK *objectPtr, DYNAMICSBLOCK *mainDynPtr);
150 static void TestObjectWithStaticBoundingBox(DISPLAYBLOCK *objectPtr);
151 static void TestShapeWithParticlesDynamicBoundingBox(DISPLAYBLOCK *objectPtr);
152
153
154 static void CreateSphereBBForObject(const STRATEGYBLOCK *sbPtr);
155 static signed int DistanceMovedBeforeSphereHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
156 static int SphereProjectOntoPoly(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, VECTORCH *projectedPosition);
157 static void MakeStaticBoundingBoxForSphere(STRATEGYBLOCK *sbPtr);
158 static int RelocateSphere(STRATEGYBLOCK *sbPtr);
159
160
161 static void CreateNRBBForObject(const STRATEGYBLOCK *sbPtr);
162 static signed int DistanceMovedBeforeNRBBHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
163 static int NRBBProjectsOntoPolygon(DYNAMICSBLOCK *dynPtr, int vertexToPlaneDist[], struct ColPolyTag *polyPtr, VECTORCH *projectionDirPtr);
164 static void MakeStaticBoundingBoxForNRBB(STRATEGYBLOCK *sbPtr);
165 static int RelocateNRBB(STRATEGYBLOCK *sbPtr);
166
167 static void FindLandscapePolygonsInObjectsVicinity(STRATEGYBLOCK *sbPtr);
168 #if 0
169 static signed int DistanceMovedBeforeNRBBHitsNegYPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
170 static signed int DistanceMovedBeforeNRBBHitsPosYPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
171 static signed int DistanceMovedBeforeNRBBHitsNegXPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
172 static signed int DistanceMovedBeforeNRBBHitsPosXPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
173 static signed int DistanceMovedBeforeNRBBHitsNegZPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
174 static signed int DistanceMovedBeforeNRBBHitsPosZPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
175 static void TestForValidMovement(STRATEGYBLOCK *sbPtr);
176 #endif
177 static int MoveObject(STRATEGYBLOCK *sbPtr);
178 static void TestForValidPlayerStandUp(STRATEGYBLOCK *sbPtr);
179 static int SteppingUpIsValid(STRATEGYBLOCK *sbPtr);
180 static void TestShapeWithStaticBoundingBox(DISPLAYBLOCK *objectPtr);
181 static int IsPolygonWithinDynamicBoundingBox(const struct ColPolyTag *polyPtr);
182 static int IsPolygonWithinStaticBoundingBox(const struct ColPolyTag *polyPtr);
183 static int WhichNRBBVertex(DYNAMICSBLOCK *dynPtr, VECTORCH *normalPtr);
184 static int DoesPolygonIntersectNRBB(struct ColPolyTag *polyPtr,VECTORCH *objectVertices);
185
186
187 static signed int (*DistanceMovedBeforeObjectHitsPolygon)(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
188 static void (*MakeStaticBoundingBoxForObject)(STRATEGYBLOCK *sbPtr);
189 static int (*RelocationIsValid)(STRATEGYBLOCK *sbPtr);
190
191 static void MovePlatformLift(STRATEGYBLOCK *sbPtr);
192 static void FindLandscapePolygonsInParticlesPath(PARTICLE *particlePtr, VECTORCH *displacementPtr);
193
194 VECTORCH *GetNearestModuleTeleportPoint(MODULE* thisModulePtr, VECTORCH* positionPtr);
195
196 /*KJL****************************************************************************************
197 * D E F I N E S *
198 ****************************************************************************************KJL*/
199
200 #define AddVectorToVector(v2,v1)\
201 { \
202 v1.vx += v2.vx; \
203 v1.vy += v2.vy; \
204 v1.vz += v2.vz; \
205 }
206 #define SubVectorFromVector(v2,v1)\
207 { \
208 v1.vx -= v2.vx; \
209 v1.vy -= v2.vy; \
210 v1.vz -= v2.vz; \
211 }
212
213 #define AddScaledVectorToVector(v2,s,v1) \
214 { \
215 v1.vx += MUL_FIXED(v2.vx, s); \
216 v1.vy += MUL_FIXED(v2.vy, s); \
217 v1.vz += MUL_FIXED(v2.vz, s); \
218 }
219 #define SubScaledVectorFromVector(v2,s,v1) \
220 { \
221 v1.vx -= MUL_FIXED(v2.vx, s); \
222 v1.vy -= MUL_FIXED(v2.vy, s); \
223 v1.vz -= MUL_FIXED(v2.vz, s); \
224 }
225
226
227
228 /*KJL****************************************************************************************
229 * G L O B A L S *
230 ****************************************************************************************KJL*/
231 extern int NumActiveStBlocks;
232 extern STRATEGYBLOCK *ActiveStBlockList[maxstblocks];
233 extern int NormalFrameTime;
234
235
236 #define COLLISION_GRANULARITY 10 // 40
237 #define RELOCATION_GRANULARITY 5 // 30
238 #define GRAVITY_DISPLACEMENT (COLLISION_GRANULARITY+1)
239 #define MAXIMUM_NUMBER_OF_COLLISIONPOLYS 3000
240 #define PLAYER_PICKUP_OBJECT_RADIUS 1600
241
242
243 static STRATEGYBLOCK *DynamicObjectsList[MAX_NO_OF_DYNAMICS_BLOCKS];
244 static int NumberOfDynamicObjects = 1;
245
246 static int AccelDueToGravity;
247 static int DistanceToStepUp;
248 static VECTORCH DirectionOfTravel;
249
250 static struct ColPolyTag CollisionPolysArray[MAXIMUM_NUMBER_OF_COLLISIONPOLYS];
251 static struct ColPolyTag *CollisionPolysPtr;
252 static int NumberOfCollisionPolys;
253
254 #define MAX_NUMBER_OF_INTERFERENCE_POLYGONS 100
255 static struct ColPolyTag InterferencePolygons[MAX_NUMBER_OF_INTERFERENCE_POLYGONS];
256 static int NumberOfInterferencePolygons = 0;
257
258 /* global storage of bounding box */
259 static int DBBMinX,DBBMaxX, DBBMinY,DBBMaxY, DBBMinZ,DBBMaxZ;
260 static int SBBMinX,SBBMaxX, SBBMinY,SBBMaxY, SBBMinZ,SBBMaxZ;
261
262 const static 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};
263 int PlanarGravity=1;
264
265 static int PlayersFallingSpeed;
266 int PlayersMaxHeightWhilstNotInContactWithGround;
267 /*KJL****************************************************************************************
268 * F U N C T I O N S *
269 ****************************************************************************************KJL*/
270
271 /* Entry point to dynamics system - this function handles the movement of all objects */
ObjectDynamics(void)272 extern void ObjectDynamics(void)
273 {
274 int i;
275 /* textprint("player Impulse at %d,%d,%d\n",
276 Player->ObStrategyBlock->DynPtr->LinImpulse.vx,
277 Player->ObStrategyBlock->DynPtr->LinImpulse.vy,
278 Player->ObStrategyBlock->DynPtr->LinImpulse.vz);
279 */
280 // if (TICKERTAPE_CHEATMODE)
281 // PlayerPheromoneTrail();
282
283 if (FREEFALL_CHEATMODE)
284 {
285 PlanarGravity = 0;
286 }
287 else
288 {
289 PlanarGravity = 1;
290 }
291 /* clear previous frame's collision reports */
292 InitialiseCollisionReports();
293
294 /* create ordered list of dynamic objects */
295 InitialiseDynamicObjectsList();
296
297 {
298 DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
299 LogInfo
300 ((
301 "Dynamics Logging: frame %d\nDL: player's Position %d,%d,%d\nDL: player's Displacement %d,%d,%d\nDL: NormalFrameTime %d\n",
302 GlobalFrameCounter,
303 dynPtr->Position.vx,dynPtr->Position.vy,dynPtr->Position.vz,
304 dynPtr->Displacement.vx,dynPtr->Displacement.vy,dynPtr->Displacement.vz,
305 NormalFrameTime
306 ));
307
308 }
309
310 i = NumberOfDynamicObjects;
311 /* scan through objects */
312 while(i--)
313 {
314 STRATEGYBLOCK *sbPtr = DynamicObjectsList[i];
315 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
316
317 GLOBALASSERT(dynPtr->Mass>0);
318
319 if (dynPtr->IsNetGhost || (dynPtr->IsPickupObject && !dynPtr->GravityOn))
320 {
321 #if 0
322 dynPtr->Position.vx += MUL_FIXED(dynPtr->LinVelocity.vx, NormalFrameTime);
323 dynPtr->Position.vy += MUL_FIXED(dynPtr->LinVelocity.vy, NormalFrameTime);
324 dynPtr->Position.vz += MUL_FIXED(dynPtr->LinVelocity.vz, NormalFrameTime);
325 AlignObjectToStandardGravityDirection(dynPtr);
326 #endif
327 UpdateDisplayBlockData(sbPtr);
328 continue;
329 }
330 /* setup function pointers */
331 switch(dynPtr->DynamicsType)
332 {
333 case DYN_TYPE_SPHERE_COLLISIONS:
334 {
335 DistanceMovedBeforeObjectHitsPolygon = DistanceMovedBeforeSphereHitsPolygon;
336 MakeStaticBoundingBoxForObject = MakeStaticBoundingBoxForSphere;
337 RelocationIsValid = RelocateSphere;
338 break;
339 }
340 case DYN_TYPE_NRBB_COLLISIONS:
341 {
342 DistanceMovedBeforeObjectHitsPolygon = DistanceMovedBeforeNRBBHitsPolygon;
343 MakeStaticBoundingBoxForObject = MakeStaticBoundingBoxForNRBB;
344 RelocationIsValid = RelocateNRBB;
345 break;
346 }
347 default:
348 {
349 /* oh dear, invalid collision shape */
350 GLOBALASSERT(0);
351 break;
352 }
353 }
354 if ((sbPtr->SBdptr == Player) && dynPtr->RequestsToStandUp)
355 TestForValidPlayerStandUp(sbPtr);
356 #if 0
357 if (dynPtr->OnlyCollideWithObjects)
358 {
359 /* initialise near polygons array */
360 CollisionPolysPtr = &CollisionPolysArray[0];
361 NumberOfCollisionPolys=0;
362 }
363 else
364 {
365 /* find which landscape polygons occupy the space
366 through which the object wishes to move */
367 FindLandscapePolygonsInObjectsPath(sbPtr);
368 }
369 #endif
370 if (dynPtr->OnlyCollideWithObjects)
371 {
372 /* initialise near polygons array */
373 CollisionPolysPtr = &CollisionPolysArray[0];
374 NumberOfCollisionPolys=0;
375 MovePlatformLift(sbPtr);
376 }
377 else if (dynPtr->StopOnCollision)
378 {
379 if (dynPtr->OnlyCollideWithObjects)
380 {
381 /* initialise near polygons array */
382 CollisionPolysPtr = &CollisionPolysArray[0];
383 NumberOfCollisionPolys=0;
384 FindObjectPolygonsInObjectsPath(sbPtr);
385 }
386 else
387 {
388 /* find which landscape polygons occupy the space
389 through which the object wishes to move */
390 FindLandscapePolygonsInObjectsPath(sbPtr);
391 if (!dynPtr->OnlyCollideWithEnvironment)
392 {
393 FindObjectPolygonsInObjectsPath(sbPtr);
394 }
395 }
396 while(dynPtr->DistanceLeftToMove && !MoveObject(sbPtr));
397 }
398 else
399 {
400 int noOfMoves=4;
401 int maxMoveLimit=10;
402
403 if (dynPtr->OnlyCollideWithObjects)
404 {
405 /* initialise near polygons array */
406 CollisionPolysPtr = &CollisionPolysArray[0];
407 NumberOfCollisionPolys=0;
408 FindObjectPolygonsInObjectsPath(sbPtr);
409 }
410 else
411 {
412 /* find which landscape polygons occupy the space
413 through which the object wishes to move */
414 FindLandscapePolygonsInObjectsPath(sbPtr);
415 if (!dynPtr->OnlyCollideWithEnvironment)
416 {
417 FindObjectPolygonsInObjectsPath(sbPtr);
418 }
419 }
420
421 while (dynPtr->DistanceLeftToMove && noOfMoves && maxMoveLimit)
422 {
423 int hitSomethingWhileMoving;
424
425 if (ShowDebuggingText.Dynamics) PrintDebuggingText("Displacement:%d,%d,%d\n",
426 dynPtr->Displacement.vx,
427 dynPtr->Displacement.vy,
428 dynPtr->Displacement.vz);
429
430 hitSomethingWhileMoving = MoveObject(sbPtr);
431
432 if(hitSomethingWhileMoving||DistanceToStepUp)
433 {
434 if (dynPtr->OnlyCollideWithObjects)
435 {
436 /* initialise near polygons array */
437 CollisionPolysPtr = &CollisionPolysArray[0];
438 NumberOfCollisionPolys=0;
439 FindObjectPolygonsInObjectsPath(sbPtr);
440 }
441 else
442 {
443 /* find which landscape polygons occupy the space
444 through which the object wishes to move */
445 FindLandscapePolygonsInObjectsPath(sbPtr);
446 if (!dynPtr->OnlyCollideWithEnvironment)
447 {
448 FindObjectPolygonsInObjectsPath(sbPtr);
449 }
450 }
451 }
452 if(hitSomethingWhileMoving&&!DistanceToStepUp)
453 {
454 noOfMoves--;
455 }
456
457 maxMoveLimit--;
458 }
459 }
460
461 /* friction */
462 #if 0
463 if (dynPtr->IsInContactWithFloor)
464 {
465 int scale = NormalFrameTime<<1;
466 if(scale>ONE_FIXED) scale = ONE_FIXED;
467 scale = ONE_FIXED;
468 dynPtr->LinImpulse.vx -= MUL_FIXED(scale,dynPtr->LinImpulse.vx);
469 dynPtr->LinImpulse.vz -= MUL_FIXED(scale,dynPtr->LinImpulse.vz);
470 }
471 #else
472 if (dynPtr->IsInContactWithFloor)
473 {
474 int k = NormalFrameTime<<1;
475 int dotted = DotProduct(&(dynPtr->LinImpulse),&(dynPtr->GravityDirection));
476
477 VECTORCH linParallel,linPerp;
478
479 linParallel.vx = MUL_FIXED(dotted,dynPtr->GravityDirection.vx);
480 linParallel.vy = MUL_FIXED(dotted,dynPtr->GravityDirection.vy);
481 linParallel.vz = MUL_FIXED(dotted,dynPtr->GravityDirection.vz);
482
483 linPerp.vx = dynPtr->LinImpulse.vx - linParallel.vx;
484 linPerp.vy = dynPtr->LinImpulse.vy - linParallel.vy;
485 linPerp.vz = dynPtr->LinImpulse.vz - linParallel.vz;
486
487 if (dynPtr->IsInContactWithNearlyFlatFloor)
488 {
489 if (Approximate3dMagnitude(&linPerp)<3000)
490 {
491 k*=16;
492 if (k>ONE_FIXED) k = ONE_FIXED;
493 }
494 }
495
496 dynPtr->LinImpulse.vx -= MUL_FIXED(k,linPerp.vx);
497 dynPtr->LinImpulse.vy -= MUL_FIXED(k,linPerp.vy);
498 dynPtr->LinImpulse.vz -= MUL_FIXED(k,linPerp.vz);
499 }
500 #endif
501
502 #if 0
503 if( (dynPtr->Position.vx != dynPtr->PrevPosition.vx)
504 ||(dynPtr->Position.vy != dynPtr->PrevPosition.vy)
505 ||(dynPtr->Position.vz != dynPtr->PrevPosition.vz))
506 #endif
507 {
508 // FindObjectsToRelocateAgainst(sbPtr);
509 // TestForValidMovement(sbPtr);
510 }
511 // RelocatedDueToFallout(dynPtr);
512 UpdateDisplayBlockData(sbPtr);
513 }
514 #if TELEPORT_IF_OUTSIDE_ENV
515 {
516 extern MODULE *playerPherModule;
517 DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
518 MODULE *newModule = (ModuleFromPosition(&(dynPtr->Position), playerPherModule));
519
520 if (!newModule)
521 {
522 /* hmm, player isn't in a module */
523 #if 0
524 if (playerPherModule)
525 {
526 dynPtr->Position.vx = playerPherModule->m_world.vx;
527 dynPtr->Position.vy = playerPherModule->m_world.vy;
528 dynPtr->Position.vz = playerPherModule->m_world.vz;
529 PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
530
531 dynPtr->PrevPosition = dynPtr->Position;
532 dynPtr->LinImpulse.vx = 0;
533 dynPtr->LinImpulse.vy = 0;
534 dynPtr->LinImpulse.vz = 0;
535 UpdateDisplayBlockData(Player->ObStrategyBlock);
536 }
537 else
538 #endif
539 {
540 if (playerPherModule)
541 {
542 VECTORCH newPosition = playerPherModule->m_aimodule->m_world;
543 VECTORCH *offsetPtr = GetNearestModuleTeleportPoint(playerPherModule, &dynPtr->Position);
544 if (offsetPtr)
545 {
546 newPosition.vx += offsetPtr->vx;
547 newPosition.vy += offsetPtr->vy;
548 newPosition.vz += offsetPtr->vz;
549 }
550
551 dynPtr->Position = newPosition;
552 dynPtr->PrevPosition = newPosition;
553 }
554 PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
555 dynPtr->LinImpulse.vx = 0;
556 dynPtr->LinImpulse.vy = 0;
557 dynPtr->LinImpulse.vz = 0;
558 UpdateDisplayBlockData(Player->ObStrategyBlock);
559 //NewOnScreenMessage("Relocated Player");
560 }
561
562 }
563 }
564 #endif
565 /* KJL 18:50:17 10/11/98 - Falling Damage */
566 if (AvP.PlayerType==I_Marine)
567 {
568 DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
569 if(dynPtr->IsInContactWithFloor)
570 {
571 #if 0
572 int damage = (PlayersFallingSpeed-15000)*160;
573 if (damage>0)
574 {
575 CauseDamageToObject(Player->ObStrategyBlock,&FallingDamage,damage,NULL);
576
577 }
578 //falling damage may be turned off in network games
579 BOOL fallingDamageDisabled = (!netGameData.fallingDamage && AvP.Network!=I_No_Network);
580 int damage = ((dynPtr->Position.vy - PlayersMaxHeightWhilstNotInContactWithGround - 4000))*256
581 ;
582 if (damage>0 && !fallingDamageDisabled)
583 {
584 CauseDamageToObject(Player->ObStrategyBlock,&FallingDamage,damage,NULL);
585 }
586 /* CDF 8/4/99 - end of jump sound... */
587 {
588 int distanceFallen = (dynPtr->Position.vy - PlayersMaxHeightWhilstNotInContactWithGround);
589
590 if ((distanceFallen>500)&&(distanceFallen<4000 || fallingDamageDisabled)) {
591 /* Make a sound. */
592 Sound_Play(SID_MARINE_SMALLLANDING,"h");
593 if(AvP.Network!=I_No_Network) netGameData.landingNoise=1;
594 }
595 }
596 #endif
597 BOOL fallingDamageDisabled = (!netGameData.fallingDamage && AvP.Network!=I_No_Network);
598 int damage = (PlayersFallingSpeed-15000)*256;
599 int distanceFallen = (dynPtr->Position.vy - PlayersMaxHeightWhilstNotInContactWithGround);
600
601 if (distanceFallen>5000 && damage>ONE_FIXED && !fallingDamageDisabled)
602 {
603 CauseDamageToObject(Player->ObStrategyBlock,&FallingDamage,damage,NULL);
604 }
605 else if (distanceFallen>1000)
606 {
607 Sound_Play(SID_MARINE_SMALLLANDING,"h");
608 if(AvP.Network!=I_No_Network) netGameData.landingNoise=1;
609 }
610
611
612
613 PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
614 }
615 else
616 {
617 if(dynPtr->LinImpulse.vy < 0)
618 {
619 PlayersMaxHeightWhilstNotInContactWithGround = 1000000;
620 }
621 else if(PlayersMaxHeightWhilstNotInContactWithGround>dynPtr->Position.vy)
622 {
623 PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
624 }
625 }
626 } else if (AvP.PlayerType==I_Predator) {
627 DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
628
629 if(dynPtr->IsInContactWithFloor)
630 {
631 /* CDF 8/4/99 - end of jump sound... */
632 {
633 int distanceFallen = (dynPtr->Position.vy - PlayersMaxHeightWhilstNotInContactWithGround);
634
635 if (distanceFallen>1000) {
636 /* Make a sound. */
637 Sound_Play(SID_PRED_SMALLLANDING,"h");
638 if(AvP.Network!=I_No_Network) netGameData.landingNoise=1;
639 }
640 }
641 PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
642 }
643 else
644 {
645 if(dynPtr->LinImpulse.vy < 0)
646 {
647 PlayersMaxHeightWhilstNotInContactWithGround = 1000000;
648 }
649 else if(PlayersMaxHeightWhilstNotInContactWithGround>dynPtr->Position.vy)
650 {
651 PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
652 }
653 }
654 }
655 /* Check for object pickup */
656 {
657 int i = NumberOfDynamicObjects;
658 DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
659
660 while(i--)
661 {
662 STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i];
663 // if((obstaclePtr->I_SBtype == I_BehaviourHierarchicalFragment)||(obstaclePtr->DynPtr->IsPickupObject))
664 if(obstaclePtr->DynPtr->IsPickupObject)
665 {
666 VECTORCH disp;
667 disp.vx = dynPtr->Position.vx-obstaclePtr->DynPtr->Position.vx;
668 disp.vy = dynPtr->Position.vy-obstaclePtr->DynPtr->Position.vy;
669 disp.vz = dynPtr->Position.vz-obstaclePtr->DynPtr->Position.vz;
670 if (Approximate3dMagnitude(&disp)<PLAYER_PICKUP_OBJECT_RADIUS)
671 {
672 /* create a report about the collision */
673 COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
674 if (reportPtr)
675 {
676 reportPtr->ObstacleSBPtr = obstaclePtr;
677 reportPtr->ObstacleNormal.vx = -dynPtr->GravityDirection.vx;
678 reportPtr->ObstacleNormal.vy = -dynPtr->GravityDirection.vy;
679 reportPtr->ObstacleNormal.vz = -dynPtr->GravityDirection.vz;
680 }
681 }
682 }
683 }
684 }
685 #if 0
686 {
687 COLLISIONREPORT *reportPtr = Player->ObStrategyBlock->DynPtr->CollisionReportPtr;
688
689 if (ShowDebuggingText.Dynamics) PrintDebuggingText("Player Impulse:%d,%d,%d\n",
690 Player->ObStrategyBlock->DynPtr->LinImpulse.vx,
691 Player->ObStrategyBlock->DynPtr->LinImpulse.vy,
692 Player->ObStrategyBlock->DynPtr->LinImpulse.vz);
693
694 if (ShowDebuggingText.Dynamics) PrintDebuggingText("Player Position:%d,%d,%d\n",
695 Player->ObStrategyBlock->DynPtr->Position.vx,
696 Player->ObStrategyBlock->DynPtr->Position.vy,
697 Player->ObStrategyBlock->DynPtr->Position.vz);
698
699 if (ShowDebuggingText.Dynamics) PrintDebuggingText("InContactWithFloor %d\n",Player->ObStrategyBlock->DynPtr->IsInContactWithFloor);
700 if (ShowDebuggingText.Dynamics) PrintDebuggingText("Player Gravity Direction:%d,%d,%d\n",
701 Player->ObStrategyBlock->DynPtr->GravityDirection.vx,
702 Player->ObStrategyBlock->DynPtr->GravityDirection.vy,
703 Player->ObStrategyBlock->DynPtr->GravityDirection.vz);
704
705 while (reportPtr) /* while there is a valid report */
706 {
707 if (ShowDebuggingText.Dynamics) PrintDebuggingText("Col Normal %d %d %d\n",reportPtr->ObstacleNormal.vx,reportPtr->ObstacleNormal.vy,reportPtr->ObstacleNormal.vz);
708 if (ShowDebuggingText.Dynamics) PrintDebuggingText("strategy ptr %p\n",reportPtr->ObstacleSBPtr);
709
710 /* skip to next report */
711 reportPtr = reportPtr->NextCollisionReportPtr;
712 }
713 PrintDebuggingText("���� ���\n");
714 if(!Player->ObStrategyBlock->DynPtr->IsInContactWithFloor)
715 NewOnScreenMessage("���� word ��� word ���� word �� word\n");
716 }
717 #endif
718 //NewTrailPoint(Player->ObStrategyBlock->DynPtr);
719 }
720
InitialiseDynamicObjectsList(void)721 static void InitialiseDynamicObjectsList(void)
722 {
723 STRATEGYBLOCK *unsortedDynamicObjectsList[MAX_NO_OF_DYNAMICS_BLOCKS];
724 signed int valueOnWhichToSort[MAX_NO_OF_DYNAMICS_BLOCKS];
725 AccelDueToGravity = MUL_FIXED(GRAVITY_STRENGTH,NormalFrameTime);
726
727 if (UNDERWATER_CHEATMODE)
728 {
729 AccelDueToGravity/=2;
730 }
731
732 /* scan through list of strategy blocks looking for ones
733 with dynamics blocks and collisions on */
734 {
735 int i = NumActiveStBlocks;
736 NumberOfDynamicObjects = 0;
737 while(i)
738 {
739 STRATEGYBLOCK *sbPtr = ActiveStBlockList[--i];
740 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
741 DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
742
743 if (dynPtr && dispPtr)
744 {
745 /* skip static objects */
746 if(dynPtr->IsStatic)
747 {
748 UpdateDisplayBlockData(sbPtr);
749 // CreateNRBBForObject(sbPtr);
750 }
751 /* should object simply move? */
752 else if (dynPtr->DynamicsType == DYN_TYPE_NO_COLLISIONS)
753 {
754 /* Apply gravity */
755 ApplyGravity(dynPtr);
756
757 dynPtr->Position.vx +=
758 MUL_FIXED(dynPtr->LinVelocity.vx+dynPtr->LinImpulse.vx, NormalFrameTime);
759 dynPtr->Position.vy +=
760 MUL_FIXED(dynPtr->LinVelocity.vy+dynPtr->LinImpulse.vy, NormalFrameTime);
761 dynPtr->Position.vz +=
762 MUL_FIXED(dynPtr->LinVelocity.vz+dynPtr->LinImpulse.vz, NormalFrameTime);
763 UpdateDisplayBlockData(sbPtr);
764 }
765 /* is it just static? */
766 else /* have to consider it properly */
767 {
768 /* Apply gravity */
769 ApplyGravity(dynPtr);
770 AddEffectsOfForceGenerators(&dynPtr->Position,&dynPtr->LinImpulse,dynPtr->Mass);
771 /* create a bb that surrounds the object */
772 // CreateExtentCuboidForObject(sbPtr);
773 switch(dynPtr->DynamicsType)
774 {
775 case DYN_TYPE_SPHERE_COLLISIONS:
776 {
777 dynPtr->CollisionRadius = 500;
778
779 CreateSphereBBForObject(sbPtr);
780 break;
781 }
782 case DYN_TYPE_NRBB_COLLISIONS:
783 {
784 #if 0
785 textprint
786 (
787 "%d %d, %d %d, %d %d\n"
788 ,sbPtr->SBdptr->ObMaxX,sbPtr->SBdptr->ObMinX
789 ,sbPtr->SBdptr->ObMaxY,sbPtr->SBdptr->ObMinY
790 ,sbPtr->SBdptr->ObMaxZ,sbPtr->SBdptr->ObMinZ
791 );
792 #endif
793 CreateNRBBForObject(sbPtr);
794 break;
795 }
796 default:
797 {
798 /* oh dear, invalid collision shape */
799 GLOBALASSERT(0);
800 break;
801 }
802 }
803
804 if (!dynPtr->IsNetGhost)
805 {
806 /* set previous position datum */
807 dynPtr->PrevPosition = dynPtr->Position;
808 //dynPtr->PrevOrientMat = dynPtr->OrientMat;
809
810 /* reset floor contact flag */
811 dynPtr->IsInContactWithFloor = 0;
812 dynPtr->IsInContactWithNearlyFlatFloor = 0;
813
814 /* calculate object's movement vector */
815 if (!dynPtr->UseDisplacement)
816 {
817 dynPtr->Displacement.vx = 0;
818 dynPtr->Displacement.vy = 0;
819 dynPtr->Displacement.vz = 0;
820 }
821
822
823 if (dynPtr->OnlyCollideWithObjects)
824 {
825 dynPtr->Displacement.vx += MUL_FIXED(dynPtr->LinVelocity.vx, NormalFrameTime);
826 dynPtr->Displacement.vy += MUL_FIXED(dynPtr->LinVelocity.vy, NormalFrameTime);
827 dynPtr->Displacement.vz += MUL_FIXED(dynPtr->LinVelocity.vz, NormalFrameTime);
828 }
829 else
830 {
831 dynPtr->Displacement.vx += MUL_FIXED(dynPtr->LinVelocity.vx+dynPtr->LinImpulse.vx, NormalFrameTime);
832 dynPtr->Displacement.vy += MUL_FIXED(dynPtr->LinVelocity.vy+dynPtr->LinImpulse.vy, NormalFrameTime);
833 dynPtr->Displacement.vz += MUL_FIXED(dynPtr->LinVelocity.vz+dynPtr->LinImpulse.vz, NormalFrameTime);
834
835 /* If moving in direction of gravity, add a little bit to make sure you will make contact
836 with the ground if your close */
837 if (dynPtr->GravityOn)
838 {
839 if (dynPtr->UseStandardGravity&&PlanarGravity) /* ie. in direction of +ve Y-axis */
840 {
841 if (dynPtr->Displacement.vy > 0)
842 dynPtr->Displacement.vy += GRAVITY_DISPLACEMENT;
843 }
844 else
845 {
846 if (DotProduct(&(dynPtr->Displacement),&(dynPtr->GravityDirection)) > 0)
847 dynPtr->Displacement.vx += MUL_FIXED(dynPtr->GravityDirection.vx, GRAVITY_DISPLACEMENT);
848 dynPtr->Displacement.vy += MUL_FIXED(dynPtr->GravityDirection.vy, GRAVITY_DISPLACEMENT);
849 dynPtr->Displacement.vz += MUL_FIXED(dynPtr->GravityDirection.vz, GRAVITY_DISPLACEMENT);
850 }
851 }
852
853 /* KJL 12:00:29 25/11/98 - resolve against last frames normals */
854 #if 0
855 {
856 COLLISIONREPORT *reportPtr = dynPtr->CollisionReportPtr;
857 while (reportPtr)
858 {
859 int magOfPerpVel;
860 // if (! ((reportPtr->ObstacleNormal.vx < 100 && reportPtr->ObstacleNormal.vx > -100)
861 // &&(reportPtr->ObstacleNormal.vz < 100 && reportPtr->ObstacleNormal.vz > -100) ))
862 if(reportPtr->ObstaclePoint.vx == 0x7fffffff &&
863 reportPtr->ObstaclePoint.vy == 0x7fffffff &&
864 reportPtr->ObstaclePoint.vz == 0x7fffffff)
865 {
866
867 // reportPtr->ObstacleNormal.vy = 0;
868 // Normalise(&reportPtr->ObstacleNormal);
869 magOfPerpVel = MUL_FIXED(66000,DotProduct(&reportPtr->ObstacleNormal,&(dynPtr->Displacement)));
870
871 // SubScaledVectorFromVector(reportPtr->ObstacleNormal, magOfPerpVel, (dynPtr->Displacement));
872 dynPtr->Displacement.vx -= MUL_FIXED(reportPtr->ObstacleNormal.vx,magOfPerpVel);
873 dynPtr->Displacement.vy -= MUL_FIXED(reportPtr->ObstacleNormal.vy,magOfPerpVel);
874 dynPtr->Displacement.vz -= MUL_FIXED(reportPtr->ObstacleNormal.vz,magOfPerpVel);
875 }
876 reportPtr = reportPtr->NextCollisionReportPtr;
877 }
878 }
879 #endif
880
881 }
882
883 dynPtr->DistanceLeftToMove = Magnitude(&dynPtr->Displacement);
884
885 if (dynPtr->DistanceLeftToMove>ONE_FIXED/8)
886 {
887 dynPtr->DistanceLeftToMove = ONE_FIXED/8;
888 Normalise(&dynPtr->Displacement);
889 dynPtr->Displacement.vx /= 8;
890 dynPtr->Displacement.vy /= 8;
891 dynPtr->Displacement.vz /= 8;
892 }
893 }
894
895 if(dynPtr->OnlyCollideWithObjects || dynPtr->IsNetGhost)
896 {
897 valueOnWhichToSort[NumberOfDynamicObjects] = 0x7fffffff;
898 }
899 else
900 {
901 valueOnWhichToSort[NumberOfDynamicObjects] = dynPtr->DistanceLeftToMove;
902 }
903
904 unsortedDynamicObjectsList[NumberOfDynamicObjects] = sbPtr;
905 NumberOfDynamicObjects++;
906
907 if (dispPtr == Player)
908 {
909 PlayersFallingSpeed = (dynPtr->LinVelocity.vy+dynPtr->LinImpulse.vy);
910 }
911 }
912
913 /* wipe previous collision records */
914 dynPtr->CollisionReportPtr =0;
915 }
916 }
917 }
918 /* possibly a good idea to sort objects so that the fastest is moved first */
919 {
920 /* extremely simple (and inefficient) selection sort */
921 int outer = NumberOfDynamicObjects;
922 while(outer > 0)
923 {
924 int inner = NumberOfDynamicObjects;
925 int highestValueFound = -1;
926 int indexOfFastestObject =0;
927 while(inner)
928 {
929 if (valueOnWhichToSort[--inner]>highestValueFound)
930 {
931 highestValueFound = valueOnWhichToSort[inner];
932 indexOfFastestObject = inner;
933 }
934 }
935
936 DynamicObjectsList[--outer] = unsortedDynamicObjectsList[indexOfFastestObject];
937 valueOnWhichToSort[indexOfFastestObject] = -1;
938 }
939 }
940 }
UpdateDisplayBlockData(STRATEGYBLOCK * sbPtr)941 static void UpdateDisplayBlockData(STRATEGYBLOCK *sbPtr)
942 {
943 /* If the object associated with this strategyblock has a valid displayblock
944 then update the data which has been changed by the objects movement. */
945 DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
946 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
947
948 if (dispPtr)
949 {
950 dispPtr->ObWorld = dynPtr->Position;
951
952 if (dynPtr->CollisionRadius)
953 {
954 int radius = dynPtr->CollisionRadius;
955 dispPtr->ObWorld.vy -= radius;
956 dispPtr->ObWorld.vx += MUL_FIXED(dynPtr->OrientMat.mat21,radius);
957 dispPtr->ObWorld.vy += MUL_FIXED(dynPtr->OrientMat.mat22,radius);
958 dispPtr->ObWorld.vz += MUL_FIXED(dynPtr->OrientMat.mat23,radius);
959 }
960 dispPtr->ObMat = dynPtr->OrientMat;
961 dispPtr->ObEuler = dynPtr->OrientEuler;
962
963 if (TICKERTAPE_CHEATMODE)
964 {
965 if (sbPtr)
966 {
967 if (sbPtr->I_SBtype == I_BehaviourAlien)
968 PlayerPheromoneTrail(dynPtr);
969 }
970 }
971 }
972 dynPtr->PrevOrientMat = dynPtr->OrientMat;
973 }
974
975
976
977
978
979
980
981
982 /* gravity code */
ApplyGravity(DYNAMICSBLOCK * dynPtr)983 static void ApplyGravity(DYNAMICSBLOCK *dynPtr)
984 {
985 if (dynPtr->GravityOn)
986 {
987 if (dynPtr->UseStandardGravity)
988 {
989 if (PlanarGravity)
990 {
991 /* ie. in direction of +ve Y-axis */
992 dynPtr->LinImpulse.vy += AccelDueToGravity;
993
994 /* KJL 11:47:04 03/26/97 - aliens need to be aligned */
995 if (dynPtr->ToppleForce == TOPPLE_FORCE_ALIEN)
996 {
997 AlignObjectToStandardGravityDirection(dynPtr);
998 }
999 }
1000 /* else if (RadialGravityModel) */
1001 else
1002 {
1003 extern int CloakingPhase;
1004 dynPtr->GravityDirection.vx = GetSin((CloakingPhase/16)&4095);
1005 dynPtr->GravityDirection.vy = GetCos((CloakingPhase/16)&4095);
1006 dynPtr->GravityDirection.vz = GetCos((CloakingPhase/19+400)&4095);
1007 Normalise(&(dynPtr->GravityDirection));
1008 AddScaledVectorToVector(dynPtr->GravityDirection,(AccelDueToGravity),dynPtr->LinImpulse);
1009 AlignObjectToGravityDirection(dynPtr);
1010 }
1011 }
1012 else
1013 {
1014 /* KJL 11:47:04 03/26/97 - aliens need to be aligned */
1015 if (dynPtr->ToppleForce == TOPPLE_FORCE_ALIEN)
1016 {
1017 COLLISIONREPORT *reportPtr = dynPtr->CollisionReportPtr;
1018 VECTORCH averageNormal= {0,0,0};
1019 int normalsFound=0;
1020
1021 if(dynPtr->TimeNotInContactWithFloor!=-1)
1022 {
1023 while (reportPtr) /* while there is a valid report */
1024 {
1025 // if (reportPtr->ObstacleSBPtr == 0)
1026 {
1027 averageNormal.vx -= reportPtr->ObstacleNormal.vx;
1028 averageNormal.vy -= reportPtr->ObstacleNormal.vy;
1029 averageNormal.vz -= reportPtr->ObstacleNormal.vz;
1030 normalsFound++;
1031 }
1032 /* skip to next report */
1033 reportPtr = reportPtr->NextCollisionReportPtr;
1034 }
1035 }
1036 if (normalsFound)
1037 {
1038 //averageNormal.vx /= normalsFound;
1039 //averageNormal.vy /= normalsFound;
1040 //averageNormal.vz /= normalsFound;
1041 if (averageNormal.vx==0 && averageNormal.vy==0 && averageNormal.vz==0)
1042 {
1043 // down boy down
1044 averageNormal.vy = ONE_FIXED;
1045 }
1046 else
1047 {
1048 Normalise(&averageNormal);
1049 }
1050 dynPtr->GravityDirection = averageNormal;
1051 dynPtr->TimeNotInContactWithFloor = TIME_BEFORE_GRAVITY_KICKS_IN;
1052 }
1053 else
1054 {
1055 if (dynPtr->TimeNotInContactWithFloor<=0)
1056 {
1057 if (PlanarGravity)
1058 {
1059 dynPtr->GravityDirection.vx = 0;
1060 dynPtr->GravityDirection.vy = 65536;
1061 dynPtr->GravityDirection.vz = 0;
1062 }
1063 /* else if (RadialGravityModel) */
1064 else
1065 {
1066 dynPtr->GravityDirection.vx = -dynPtr->Position.vx;
1067 dynPtr->GravityDirection.vy = -dynPtr->Position.vy;
1068 dynPtr->GravityDirection.vz = -dynPtr->Position.vz;
1069 Normalise(&(dynPtr->GravityDirection));
1070 }
1071 }
1072 else if (dynPtr->TimeNotInContactWithFloor == TIME_BEFORE_GRAVITY_KICKS_IN)
1073 {
1074 if (dynPtr->LinVelocity.vx==0 && dynPtr->LinVelocity.vy==0 && dynPtr->LinVelocity.vz==0)
1075 {
1076 // dynPtr->GravityDirection.vx = 0;
1077 // dynPtr->GravityDirection.vy = 65536;
1078 // dynPtr->GravityDirection.vz = 0;
1079 }
1080 else
1081 {
1082 /* code to enable going round 270 degree corners */
1083 #if 1
1084 Normalise(&dynPtr->LinVelocity);
1085 dynPtr->GravityDirection.vx -= (dynPtr->LinVelocity.vx*3)/4;
1086 dynPtr->GravityDirection.vy -= (dynPtr->LinVelocity.vy*3)/4;
1087 dynPtr->GravityDirection.vz -= (dynPtr->LinVelocity.vz*3)/4;
1088 Normalise(&dynPtr->GravityDirection);
1089 dynPtr->LinVelocity.vx = 0;
1090 dynPtr->LinVelocity.vy = 0;
1091 dynPtr->LinVelocity.vz = 0;
1092 #endif
1093 }
1094 }
1095 dynPtr->TimeNotInContactWithFloor-=NormalFrameTime;
1096 if (dynPtr->TimeNotInContactWithFloor<0)
1097 {
1098 dynPtr->TimeNotInContactWithFloor = 0;
1099 }
1100
1101 }
1102 AlignObjectToGravityDirection(dynPtr);
1103 }
1104 AddScaledVectorToVector(dynPtr->GravityDirection,AccelDueToGravity,dynPtr->LinImpulse);
1105 }
1106 }
1107 }
AlignObjectToGravityDirection(DYNAMICSBLOCK * dynPtr)1108 static void AlignObjectToGravityDirection(DYNAMICSBLOCK *dynPtr)
1109 {
1110 VECTORCH XVector;
1111 VECTORCH YVector;
1112 VECTORCH ZVector;
1113 int staticAxis;
1114
1115 {
1116 int dotx = Dot((VECTORCH*)&dynPtr->OrientMat.mat11, &dynPtr->GravityDirection);
1117 int doty = Dot((VECTORCH*)&dynPtr->OrientMat.mat21, &dynPtr->GravityDirection);
1118 int dotz = Dot((VECTORCH*)&dynPtr->OrientMat.mat31, &dynPtr->GravityDirection);
1119
1120 /* Get their absolute values */
1121 if(dotx < 0) dotx = -dotx;
1122 if(doty < 0) doty = -doty;
1123 if(dotz < 0) dotz = -dotz;
1124
1125 if (dotx<doty)
1126 {
1127 if (dotx<dotz)
1128 {
1129 staticAxis = ix;
1130 }
1131 else
1132 {
1133 staticAxis = iz;
1134 }
1135 }
1136 else
1137 {
1138 if (doty<dotz)
1139 {
1140 staticAxis = iy;
1141 }
1142 else
1143 {
1144 staticAxis = iz;
1145 }
1146 }
1147 }
1148 if (staticAxis == iz)
1149 {
1150 ZVector = *((VECTORCH*)&dynPtr->OrientMat.mat31);
1151 YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1152 VectorHomingForSurfaceAlign(&YVector, &dynPtr->GravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat11));
1153 CrossProduct(&YVector, &ZVector, &XVector);
1154 }
1155 else if (staticAxis == ix)
1156 {
1157 XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
1158 YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1159 VectorHomingForSurfaceAlign(&YVector, &dynPtr->GravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
1160 CrossProduct(&XVector, &YVector, &ZVector);
1161 }
1162 else if (staticAxis == iy)
1163 {
1164 XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
1165 YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1166 VectorHomingForSurfaceAlign(&YVector, &dynPtr->GravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
1167 CrossProduct(&XVector, &YVector, &ZVector);
1168 CrossProduct(&YVector, &ZVector, &XVector);
1169 }
1170 Normalise(&XVector);
1171 Normalise(&YVector);
1172 Normalise(&ZVector);
1173
1174 dynPtr->OrientMat.mat11 = XVector.vx;
1175 dynPtr->OrientMat.mat12 = XVector.vy;
1176 dynPtr->OrientMat.mat13 = XVector.vz;
1177
1178 dynPtr->OrientMat.mat21 = YVector.vx;
1179 dynPtr->OrientMat.mat22 = YVector.vy;
1180 dynPtr->OrientMat.mat23 = YVector.vz;
1181
1182 dynPtr->OrientMat.mat31 = ZVector.vx;
1183 dynPtr->OrientMat.mat32 = ZVector.vy;
1184 dynPtr->OrientMat.mat33 = ZVector.vz;
1185
1186 MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
1187 }
AlignObjectToStandardGravityDirection(DYNAMICSBLOCK * dynPtr)1188 static void AlignObjectToStandardGravityDirection(DYNAMICSBLOCK *dynPtr)
1189 {
1190 VECTORCH gravityDirection = {0,65536,0};
1191 VECTORCH XVector,YVector,ZVector;
1192 int staticAxis;
1193
1194 dynPtr->GravityDirection = gravityDirection;
1195
1196 {
1197 int dotx = dynPtr->OrientMat.mat12;
1198 int doty = dynPtr->OrientMat.mat22;
1199 int dotz = dynPtr->OrientMat.mat32;
1200
1201 /* Get their absolute values */
1202 if(dotx < 0) dotx = -dotx;
1203 if(doty < 0) doty = -doty;
1204 if(dotz < 0) dotz = -dotz;
1205
1206 if (dotx<doty)
1207 {
1208 if (dotx<dotz)
1209 {
1210 staticAxis = ix;
1211 }
1212 else
1213 {
1214 staticAxis = iz;
1215 }
1216 }
1217 else
1218 {
1219 if (doty<dotz)
1220 {
1221 staticAxis = iy;
1222 }
1223 else
1224 {
1225 staticAxis = iz;
1226 }
1227 }
1228 }
1229 if (staticAxis == iz)
1230 {
1231 ZVector = *((VECTORCH*)&dynPtr->OrientMat.mat31);
1232 YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1233 VectorHomingForSurfaceAlign(&YVector, &gravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat11));
1234 CrossProduct(&YVector, &ZVector, &XVector);
1235 }
1236 else if (staticAxis == ix)
1237 {
1238 XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
1239 YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1240 VectorHomingForSurfaceAlign(&YVector, &gravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
1241 CrossProduct(&XVector, &YVector, &ZVector);
1242 }
1243 else if (staticAxis == iy)
1244 {
1245 XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
1246 YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1247 VectorHomingForSurfaceAlign(&YVector, &gravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
1248 CrossProduct(&XVector, &YVector, &ZVector);
1249 CrossProduct(&YVector, &ZVector, &XVector);
1250 }
1251 Normalise(&XVector);
1252 Normalise(&YVector);
1253 Normalise(&ZVector);
1254
1255 dynPtr->OrientMat.mat11 = XVector.vx;
1256 dynPtr->OrientMat.mat12 = XVector.vy;
1257 dynPtr->OrientMat.mat13 = XVector.vz;
1258
1259 dynPtr->OrientMat.mat21 = YVector.vx;
1260 dynPtr->OrientMat.mat22 = YVector.vy;
1261 dynPtr->OrientMat.mat23 = YVector.vz;
1262
1263 dynPtr->OrientMat.mat31 = ZVector.vx;
1264 dynPtr->OrientMat.mat32 = ZVector.vy;
1265 dynPtr->OrientMat.mat33 = ZVector.vz;
1266
1267 MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
1268 }
VectorHomingForSurfaceAlign(VECTORCH * currentPtr,VECTORCH * targetPtr,VECTORCH * perpendicularPtr)1269 static void VectorHomingForSurfaceAlign(VECTORCH *currentPtr, VECTORCH *targetPtr, VECTORCH *perpendicularPtr)
1270 {
1271 int cos = Dot(currentPtr, targetPtr);
1272
1273 if (cos<=-65000)
1274 {
1275 int a1 = NormalFrameTime*4;
1276 if (a1>ONE_FIXED) a1=ONE_FIXED;
1277 else if (a1<1024) a1=1024;
1278
1279 currentPtr->vx = currentPtr->vx+MUL_FIXED(perpendicularPtr->vx-currentPtr->vx, a1);
1280 currentPtr->vy = currentPtr->vy+MUL_FIXED(perpendicularPtr->vy-currentPtr->vy, a1);
1281 currentPtr->vz = currentPtr->vz+MUL_FIXED(perpendicularPtr->vz-currentPtr->vz, a1);
1282 Normalise(currentPtr);
1283 return;
1284 }
1285 else if (cos>=65500) /* if they're practically parallel just snap currentPtr to targetPtr */
1286 {
1287 currentPtr->vx = targetPtr->vx;
1288 currentPtr->vy = targetPtr->vy;
1289 currentPtr->vz = targetPtr->vz;
1290 return;
1291 }
1292
1293 if (cos<32768) cos = 32768;
1294
1295 {
1296 int a1 = MUL_FIXED(cos*8,NormalFrameTime);
1297 // int a1 = NormalFrameTime*4;
1298 if (a1>ONE_FIXED) a1=ONE_FIXED;
1299 else if (a1<1024) a1=1024;
1300
1301 currentPtr->vx = currentPtr->vx+MUL_FIXED(targetPtr->vx-currentPtr->vx, a1);
1302 currentPtr->vy = currentPtr->vy+MUL_FIXED(targetPtr->vy-currentPtr->vy, a1);
1303 currentPtr->vz = currentPtr->vz+MUL_FIXED(targetPtr->vz-currentPtr->vz, a1);
1304 Normalise(currentPtr);
1305 }
1306 return;
1307 }
1308
DynamicallyRotateObject(DYNAMICSBLOCK * dynPtr)1309 extern void DynamicallyRotateObject(DYNAMICSBLOCK *dynPtr)
1310 {
1311 extern int NormalFrameTime;
1312
1313 MATRIXCH mat;
1314 EULER euler;
1315 euler.EulerX = MUL_FIXED(NormalFrameTime,dynPtr->AngVelocity.EulerX);
1316 euler.EulerX &= wrap360;
1317
1318 euler.EulerY = MUL_FIXED(NormalFrameTime,dynPtr->AngVelocity.EulerY);
1319 euler.EulerY &= wrap360;
1320
1321 euler.EulerZ = MUL_FIXED(NormalFrameTime,dynPtr->AngVelocity.EulerZ);
1322 euler.EulerZ &= wrap360;
1323
1324 CreateEulerMatrix(&euler, &mat);
1325 TransposeMatrixCH(&mat);
1326
1327 MatrixMultiply(&dynPtr->OrientMat,&mat,&dynPtr->OrientMat);
1328 MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
1329 }
1330
1331 static int InterferenceAt(int lambda, DYNAMICSBLOCK *dynPtr);
1332
1333 /* Move an object. At this stage, we have a list of the polygons in the
1334 environment with which the object the may collide. */
MoveObject(STRATEGYBLOCK * sbPtr)1335 static int MoveObject(STRATEGYBLOCK *sbPtr)
1336 {
1337 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1338
1339 int lowestBoundary = 0;
1340 int highestBoundary = ONE_FIXED;
1341 int testValue = ONE_FIXED;
1342 int hitSomething = 0;
1343
1344 DirectionOfTravel = dynPtr->Displacement;
1345 Normalise(&DirectionOfTravel);
1346
1347 {
1348 int maxDistanceAllowed=dynPtr->ObjectVertices[0].vz-dynPtr->ObjectVertices[7].vz;
1349 if (maxDistanceAllowed>dynPtr->ObjectVertices[0].vx-dynPtr->ObjectVertices[7].vx)
1350 maxDistanceAllowed=dynPtr->ObjectVertices[0].vx-dynPtr->ObjectVertices[7].vx;
1351 if (maxDistanceAllowed>dynPtr->ObjectVertices[0].vy-dynPtr->ObjectVertices[7].vy)
1352 maxDistanceAllowed=dynPtr->ObjectVertices[0].vy-dynPtr->ObjectVertices[7].vy;
1353
1354 if (maxDistanceAllowed<10)
1355 {
1356 LOCALASSERT("Object's bounding box is too small. Suspicious."==0);
1357 }
1358
1359 if (dynPtr->DistanceLeftToMove>maxDistanceAllowed)
1360 {
1361 testValue = DIV_FIXED(maxDistanceAllowed,dynPtr->DistanceLeftToMove);
1362 highestBoundary = testValue;
1363 }
1364 }
1365
1366 if (InterferenceAt(testValue,dynPtr))
1367 {
1368 testValue /= 2;
1369 do
1370 {
1371 if (InterferenceAt(testValue,dynPtr))
1372 {
1373 highestBoundary = testValue;
1374 testValue = (lowestBoundary+highestBoundary)/2;
1375 }
1376 else
1377 {
1378 lowestBoundary = testValue;
1379 testValue = (lowestBoundary+highestBoundary)/2;
1380 }
1381 if (MUL_FIXED(highestBoundary-lowestBoundary,dynPtr->DistanceLeftToMove)<=16)
1382 {
1383 InterferenceAt(highestBoundary,dynPtr);
1384 break;
1385 }
1386 }
1387 while(1);
1388 testValue = lowestBoundary;
1389 hitSomething = 1;
1390 }
1391
1392 {
1393 VECTORCH displacement;
1394 displacement.vx = MUL_FIXED(dynPtr->Displacement.vx,testValue);
1395 displacement.vy = MUL_FIXED(dynPtr->Displacement.vy,testValue);
1396 displacement.vz = MUL_FIXED(dynPtr->Displacement.vz,testValue);
1397
1398 AddVectorToVector(displacement, dynPtr->Position);
1399 SubVectorFromVector(displacement, dynPtr->Displacement);
1400 {
1401 VECTORCH *vertexPtr = dynPtr->ObjectVertices;
1402 int i=8;
1403 do
1404 {
1405 vertexPtr->vx += displacement.vx;
1406 vertexPtr->vy += displacement.vy;
1407 vertexPtr->vz += displacement.vz;
1408 vertexPtr++;
1409 }
1410 while(--i);
1411 }
1412
1413 }
1414
1415 if (hitSomething)
1416 {
1417 int wentUpStep = 0;
1418 VECTORCH obstacleNormal = {0,0,0};
1419 int n = NumberOfInterferencePolygons;
1420 VECTORCH objectCentre = {0,0,0};
1421 int leastSoFar = 1000000;
1422 struct ColPolyTag *polygonPtr=0;
1423
1424 {
1425 if (DirectionOfTravel.vx>0)
1426 {
1427 objectCentre.vx = dynPtr->ObjectVertices[0].vx-COLLISION_GRANULARITY;
1428 }
1429 else if (DirectionOfTravel.vx<0)
1430 {
1431 objectCentre.vx = dynPtr->ObjectVertices[7].vx+COLLISION_GRANULARITY;
1432 }
1433 else
1434 {
1435 objectCentre.vx = (dynPtr->ObjectVertices[0].vx+dynPtr->ObjectVertices[7].vx)/2;
1436 }
1437 #if 1
1438 if (DirectionOfTravel.vy>0)
1439 {
1440 objectCentre.vy = dynPtr->ObjectVertices[0].vy-COLLISION_GRANULARITY;
1441 }
1442 else if (DirectionOfTravel.vy<0)
1443 {
1444 objectCentre.vy = dynPtr->ObjectVertices[7].vy+COLLISION_GRANULARITY;
1445 }
1446 else
1447 #endif
1448 {
1449 objectCentre.vy = (dynPtr->ObjectVertices[0].vy+dynPtr->ObjectVertices[7].vy)/2;
1450 }
1451 if (DirectionOfTravel.vz>0)
1452 {
1453 objectCentre.vz = dynPtr->ObjectVertices[0].vz-COLLISION_GRANULARITY;
1454 }
1455 else if (DirectionOfTravel.vz<0)
1456 {
1457 objectCentre.vz = dynPtr->ObjectVertices[7].vz+COLLISION_GRANULARITY;
1458 }
1459 else
1460 {
1461 objectCentre.vz = (dynPtr->ObjectVertices[0].vz+dynPtr->ObjectVertices[7].vz)/2;
1462 }
1463
1464 }
1465 #if 0
1466 PrintDebuggingText("Test point %d,%d,%d\n",objectCentre.vx,objectCentre.vy,objectCentre.vz);
1467 #endif
1468 while(n--)
1469 {
1470 #if 1
1471 VECTORCH r;
1472 int d;
1473
1474 r.vx = objectCentre.vx - InterferencePolygons[n].PolyPoint[0].vx;
1475 r.vy = objectCentre.vy - InterferencePolygons[n].PolyPoint[0].vy;
1476 r.vz = objectCentre.vz - InterferencePolygons[n].PolyPoint[0].vz;
1477 d = DotProduct(&r,&InterferencePolygons[n].PolyNormal);
1478
1479 if (d<0) d+=1000000;
1480 {
1481 if (d<leastSoFar)
1482 {
1483 obstacleNormal = InterferencePolygons[n].PolyNormal;
1484 leastSoFar = d;
1485 polygonPtr = &InterferencePolygons[n];
1486 }
1487 }
1488 #else
1489 VECTORCH r;
1490 int d;
1491
1492 d = DotProduct(&DirectionOfTravel,&InterferencePolygons[n].PolyNormal);
1493
1494 if (d<0)
1495 {
1496 if (d<leastSoFar)
1497 {
1498 obstacleNormal = InterferencePolygons[n].PolyNormal;
1499 leastSoFar = d;
1500 polygonPtr = &InterferencePolygons[n];
1501 }
1502 }
1503 #endif
1504
1505 }
1506 #if 0
1507 if (obstacleNormal.vx==0 && obstacleNormal.vy==0 && obstacleNormal.vz==0)
1508 {
1509 obstacleNormal.vy = -ONE_FIXED;
1510 }
1511 else
1512 {
1513 Normalise(&obstacleNormal);
1514 }
1515 #endif
1516 if(!polygonPtr)
1517 {
1518 dynPtr->DistanceLeftToMove = 0;
1519 LOCALASSERT(0);
1520 return 0;
1521 }
1522 else
1523 {
1524 #if 0
1525 PrintDebuggingText("POLY NORMAL IS %d %d %d\n",(polygonPtr->PolyNormal).vx,(polygonPtr->PolyNormal).vy,(polygonPtr->PolyNormal).vz);
1526 PrintDebuggingText("POLY NO OF VERTICES %d\n",(polygonPtr->NumberOfVertices));
1527 PrintDebuggingText("POLY POINT[0] IS %d %d %d\n",(polygonPtr->PolyPoint[0]).vx,(polygonPtr->PolyPoint[0]).vy,(polygonPtr->PolyPoint[0]).vz);
1528 PrintDebuggingText("POLY POINT[1] IS %d %d %d\n",(polygonPtr->PolyPoint[1]).vx,(polygonPtr->PolyPoint[1]).vy,(polygonPtr->PolyPoint[1]).vz);
1529 PrintDebuggingText("POLY POINT[2] IS %d %d %d\n",(polygonPtr->PolyPoint[2]).vx,(polygonPtr->PolyPoint[2]).vy,(polygonPtr->PolyPoint[2]).vz);
1530 #endif
1531 }
1532 /* test for a 'step' in front of object */
1533 if ( (dynPtr->CanClimbStairs)
1534 /* check to see that polygon is vertical */
1535 &&(polygonPtr->PolyNormal.vy>-250)
1536 &&(polygonPtr->PolyNormal.vy<250) )
1537 {
1538 int heightOfStep,topOfStep;
1539 {
1540 int vertexNum=polygonPtr->NumberOfVertices-1;
1541
1542 topOfStep = polygonPtr->PolyPoint[0].vy;
1543 do
1544 {
1545 int y = polygonPtr->PolyPoint[vertexNum].vy;
1546
1547 if (y < topOfStep) topOfStep = y;
1548 }
1549 while(--vertexNum);
1550 }
1551
1552 heightOfStep = dynPtr->ObjectVertices[0].vy - topOfStep; /* y-axis is +ve downwards, remember */
1553 //textprint("found step %d\n",heightOfStep);
1554 if (heightOfStep>0 && heightOfStep < MAXIMUM_STEP_HEIGHT) /* we've hit a 'step' - move player upwards */
1555 {
1556 DistanceToStepUp=heightOfStep+COLLISION_GRANULARITY;
1557 wentUpStep = SteppingUpIsValid(sbPtr);
1558 #if 0
1559 if (wentUpStep)
1560 {
1561 PrintDebuggingText("Found a valid step.\n");
1562 }
1563 else
1564 {
1565 PrintDebuggingText("Found a step but couldn't go up it.\n");
1566 }
1567 #endif
1568
1569 }
1570 }
1571
1572 if (!wentUpStep)
1573 {
1574 STRATEGYBLOCK *obstacleSBPtr = 0;
1575
1576 if (polygonPtr->ParentObject)
1577 if (polygonPtr->ParentObject->ObStrategyBlock)
1578 {
1579 obstacleSBPtr = polygonPtr->ParentObject->ObStrategyBlock;
1580 }
1581
1582 DistanceToStepUp = 0;
1583
1584 /* resolve player's movement vector against the collision plane */
1585 /* awkward problem here to do with non-exact normals */
1586 {
1587 // int magOfPerpVel = DotProduct(&obstacleNormal,&(dynPtr->Displacement));
1588 int magOfPerpVel = MUL_FIXED(66000,DotProduct(&obstacleNormal,&(dynPtr->Displacement)));
1589 SubScaledVectorFromVector(obstacleNormal, magOfPerpVel, (dynPtr->Displacement));
1590 }
1591
1592 /* collision - elasticity */
1593 {
1594 int magOfPerpImp = MUL_FIXED
1595 (
1596 DotProduct(&obstacleNormal,&dynPtr->LinImpulse),
1597 65536 + dynPtr->Elasticity
1598 );
1599 SubScaledVectorFromVector(obstacleNormal, magOfPerpImp, dynPtr->LinImpulse);
1600 }
1601 /* momentum test */
1602 /* OnlyCollideWithObjects flag indicates a platform lift etc. which should not be involved with momentum transfer */
1603 if (obstacleSBPtr && (obstacleSBPtr->DynPtr))
1604 if (!(dynPtr->OnlyCollideWithObjects
1605 ||obstacleSBPtr->DynPtr->OnlyCollideWithObjects
1606 ||obstacleSBPtr->DynPtr->IsStatic
1607 ||dynPtr->IsInanimate
1608 ||obstacleSBPtr->DynPtr->IsInanimate))
1609 {
1610 DYNAMICSBLOCK *obsDynPtr = obstacleSBPtr->DynPtr;
1611 int totalMass = (obsDynPtr->Mass + dynPtr->Mass)*4;
1612 int diffMass = (dynPtr->Mass-obsDynPtr->Mass)/2;
1613
1614 obsDynPtr->LinImpulse.vx +=
1615 WideMulNarrowDiv
1616 (
1617 dynPtr->LinImpulse.vx + dynPtr->LinVelocity.vx,
1618 dynPtr->Mass,
1619 totalMass
1620 );
1621 obsDynPtr->LinImpulse.vy +=
1622 WideMulNarrowDiv
1623 (
1624 dynPtr->LinImpulse.vy + dynPtr->LinVelocity.vy,
1625 dynPtr->Mass,
1626 totalMass
1627 );
1628 obsDynPtr->LinImpulse.vz +=
1629 WideMulNarrowDiv
1630 (
1631 dynPtr->LinImpulse.vz + dynPtr->LinVelocity.vz,
1632 dynPtr->Mass,
1633 totalMass
1634 );
1635
1636 dynPtr->LinImpulse.vx +=
1637 WideMulNarrowDiv
1638 (
1639 dynPtr->LinImpulse.vx + dynPtr->LinVelocity.vx,
1640 diffMass,
1641 totalMass
1642 );
1643 dynPtr->LinImpulse.vy +=
1644 WideMulNarrowDiv
1645 (
1646 dynPtr->LinImpulse.vy + dynPtr->LinVelocity.vy,
1647 diffMass,
1648 totalMass
1649 );
1650 dynPtr->LinImpulse.vz +=
1651 WideMulNarrowDiv
1652 (
1653 dynPtr->LinImpulse.vz + dynPtr->LinVelocity.vz,
1654 diffMass,
1655 totalMass
1656 );
1657
1658 }
1659 /* see if object has hit the 'floor' */
1660 if (dynPtr->GravityOn)
1661 {
1662 if (dynPtr->UseStandardGravity&&PlanarGravity)
1663 {
1664 if (obstacleNormal.vy < -FLOOR_THRESHOLD)
1665 {
1666 dynPtr->IsInContactWithFloor = 1;
1667 if (obstacleNormal.vy < -NEARLYFLATFLOOR_THRESHOLD) dynPtr->IsInContactWithNearlyFlatFloor = 1;
1668 }
1669 }
1670 else
1671 {
1672 int angle = DotProduct(&obstacleNormal,&dynPtr->GravityDirection);
1673 if (angle < -FLOOR_THRESHOLD)
1674 {
1675 /* we've hit something that's against the direction of gravity */
1676 dynPtr->IsInContactWithFloor = 1;
1677 if (angle < -NEARLYFLATFLOOR_THRESHOLD) dynPtr->IsInContactWithNearlyFlatFloor = 1;
1678 }
1679 }
1680 }
1681
1682 /* create a report about the collision */
1683 {
1684 {
1685 COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
1686 if (reportPtr)
1687 {
1688 reportPtr->ObstacleSBPtr = obstacleSBPtr;
1689 reportPtr->ObstacleNormal = obstacleNormal;
1690 reportPtr->ObstaclePoint = dynPtr->Position;
1691 }
1692 }
1693 if (obstacleSBPtr&&obstacleSBPtr->DynPtr)
1694 {
1695 COLLISIONREPORT *reportPtr = AllocateCollisionReport(obstacleSBPtr->DynPtr);
1696 if (reportPtr)
1697 {
1698 reportPtr->ObstacleSBPtr = sbPtr;
1699 reportPtr->ObstacleNormal.vx = -obstacleNormal.vx;
1700 reportPtr->ObstacleNormal.vy = -obstacleNormal.vy;
1701 reportPtr->ObstacleNormal.vz = -obstacleNormal.vz;
1702 reportPtr->ObstaclePoint = dynPtr->Position;
1703 }
1704 }
1705 }
1706 }
1707 dynPtr->DistanceLeftToMove = Magnitude(&dynPtr->Displacement);
1708 if (dynPtr->DistanceLeftToMove<=16)
1709 {
1710 dynPtr->DistanceLeftToMove = 0;
1711 }
1712 return 1;
1713 }
1714 else
1715 {
1716 dynPtr->DistanceLeftToMove = Magnitude(&dynPtr->Displacement);
1717 if (dynPtr->DistanceLeftToMove<=16)
1718 {
1719 dynPtr->DistanceLeftToMove = 0;
1720 }
1721 return 0;
1722 }
1723
1724 }
1725
InterferenceAt(int lambda,DYNAMICSBLOCK * dynPtr)1726 static int InterferenceAt(int lambda, DYNAMICSBLOCK *dynPtr)
1727 {
1728 VECTORCH objectVertices[8];
1729 int polysLeft;
1730 struct ColPolyTag *polyPtr;
1731
1732 {
1733 int vertexNum=8;
1734
1735 VECTORCH disp;
1736 disp.vx = MUL_FIXED(dynPtr->Displacement.vx,lambda);
1737 disp.vy = MUL_FIXED(dynPtr->Displacement.vy,lambda);
1738 disp.vz = MUL_FIXED(dynPtr->Displacement.vz,lambda);
1739
1740 do
1741 {
1742 vertexNum--;
1743 objectVertices[vertexNum] = dynPtr->ObjectVertices[vertexNum];
1744 objectVertices[vertexNum].vx += disp.vx;
1745 objectVertices[vertexNum].vy += disp.vy;
1746 objectVertices[vertexNum].vz += disp.vz;
1747 }
1748 while(vertexNum);
1749 }
1750
1751 polysLeft = NumberOfCollisionPolys;
1752 polyPtr = CollisionPolysArray;
1753
1754 NumberOfInterferencePolygons = 0;
1755
1756 while(polysLeft)
1757 {
1758 {
1759 if(DotProduct(&DirectionOfTravel,&polyPtr->PolyNormal)<0)
1760 if (DoesPolygonIntersectNRBB(polyPtr,objectVertices))
1761 {
1762 InterferencePolygons[NumberOfInterferencePolygons++] = *polyPtr;
1763 if (NumberOfInterferencePolygons==MAX_NUMBER_OF_INTERFERENCE_POLYGONS) break;
1764 }
1765 }
1766 polyPtr++;
1767 polysLeft--;
1768 }
1769 return NumberOfInterferencePolygons;
1770 }
1771
1772
1773
1774
1775
1776
MovePlatformLift(STRATEGYBLOCK * sbPtr)1777 static void MovePlatformLift(STRATEGYBLOCK *sbPtr)
1778 {
1779 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1780 int polysLeft;
1781 struct ColPolyTag *nearPolysPtr;
1782 int distanceToMove;
1783
1784 VECTORCH obstacleNormal;
1785 STRATEGYBLOCK *obstacleSBPtr = 0;
1786
1787 DirectionOfTravel = dynPtr->Displacement;
1788 Normalise(&DirectionOfTravel);
1789
1790 /* ugh */
1791 distanceToMove = dynPtr->DistanceLeftToMove;
1792
1793 /* make list of platform's polygons */
1794 {
1795 VECTORCH zero = {0,0,0};
1796 MakeDynamicBoundingBoxForObject(sbPtr, &(dynPtr->Position));
1797 TestShapeWithDynamicBoundingBox(sbPtr->SBdptr,dynPtr);
1798 MakeDynamicBoundingBoxForObject(sbPtr, &zero);
1799 }
1800
1801 // textprint("polys on lift %d\n",NumberOfCollisionPolys);
1802 DirectionOfTravel.vx = -DirectionOfTravel.vx;
1803 DirectionOfTravel.vy = -DirectionOfTravel.vy;
1804 DirectionOfTravel.vz = -DirectionOfTravel.vz;
1805 {
1806 int i = NumberOfDynamicObjects;
1807 while(i--)
1808 {
1809
1810 STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i];
1811
1812 /* check whether collision is even possible */
1813 {
1814 if (sbPtr==obstaclePtr)
1815 continue;
1816 {
1817 VECTORCH *objectVerticesPtr = obstaclePtr->DynPtr->ObjectVertices;
1818 if (!( ( (DBBMaxX >= objectVerticesPtr[7].vx) && (DBBMinX <= objectVerticesPtr[0].vx) )
1819 &&( (DBBMaxY >= objectVerticesPtr[7].vy) && (DBBMinY <= objectVerticesPtr[0].vy) )
1820 &&( (DBBMaxZ >= objectVerticesPtr[7].vz) && (DBBMinZ <= objectVerticesPtr[0].vz) ) ))
1821 continue;
1822 }
1823 }
1824
1825 //textprint("found an object\n");
1826
1827 polysLeft = NumberOfCollisionPolys;
1828 nearPolysPtr = CollisionPolysArray;
1829
1830 distanceToMove = dynPtr->DistanceLeftToMove;
1831
1832 /* check against the landscape */
1833 while(polysLeft)
1834 {
1835 signed int distanceToObstacle;
1836
1837 distanceToObstacle = DistanceMovedBeforeObjectHitsPolygon(obstaclePtr->DynPtr,nearPolysPtr,distanceToMove);
1838
1839 if (distanceToObstacle>=0)
1840 {
1841
1842 distanceToMove = distanceToObstacle;
1843 obstacleNormal = nearPolysPtr->PolyNormal;
1844 obstacleSBPtr = obstaclePtr;
1845 }
1846 nearPolysPtr++;
1847 polysLeft--;
1848 }
1849
1850 if (distanceToMove!=dynPtr->DistanceLeftToMove)
1851 {
1852 if (dynPtr->Displacement.vy<0)
1853 {
1854 VECTORCH displacement;
1855 // displacement.vx = -MUL_FIXED(DirectionOfTravel.vx, dynPtr->DistanceLeftToMove-distanceToMove+COLLISION_GRANULARITY);
1856 displacement.vx = displacement.vz = 0;
1857 displacement.vy = -(dynPtr->DistanceLeftToMove-distanceToMove+COLLISION_GRANULARITY);
1858 // displacement.vz = -MUL_FIXED(DirectionOfTravel.vz, dynPtr->DistanceLeftToMove-distanceToMove+COLLISION_GRANULARITY);
1859 AddVectorToVector(displacement, obstaclePtr->DynPtr->Position);
1860 obstaclePtr->DynPtr->PrevPosition = obstaclePtr->DynPtr->Position;
1861 {
1862 VECTORCH *vertexPtr = obstaclePtr->DynPtr->ObjectVertices;
1863 int i=8;
1864 do
1865 {
1866 vertexPtr->vy += displacement.vy;
1867 vertexPtr++;
1868 }
1869 while(--i);
1870 }
1871 if (obstaclePtr->SBdptr == Player)
1872 {
1873 /* look for polygons inside this volume */
1874 FindLandscapePolygonsInObjectsVicinity(obstaclePtr);
1875 FindObjectsToRelocateAgainst(obstaclePtr);
1876
1877 {
1878 int polysLeft;
1879 struct ColPolyTag *polyPtr;
1880
1881 polysLeft = NumberOfCollisionPolys;
1882 polyPtr = CollisionPolysArray;
1883
1884 while(polysLeft)
1885 {
1886 if(DoesPolygonIntersectNRBB(polyPtr,obstaclePtr->DynPtr->ObjectVertices))
1887 {
1888 int greatestDistance;
1889
1890 {
1891 VECTORCH vertex = obstaclePtr->DynPtr->ObjectVertices[WhichNRBBVertex(obstaclePtr->DynPtr,&(polyPtr->PolyNormal))];
1892 vertex.vx -= polyPtr->PolyPoint[0].vx;
1893 vertex.vy -= polyPtr->PolyPoint[0].vy;
1894 vertex.vz -= polyPtr->PolyPoint[0].vz;
1895 greatestDistance = -DotProduct(&vertex,&(polyPtr->PolyNormal));
1896 }
1897
1898 if (greatestDistance>0)
1899 {
1900 /* sorry, no room! */
1901 SubVectorFromVector(displacement, obstaclePtr->DynPtr->Position);
1902 obstaclePtr->DynPtr->PrevPosition = obstaclePtr->DynPtr->Position;
1903 {
1904 VECTORCH *vertexPtr = obstaclePtr->DynPtr->ObjectVertices;
1905 int i=8;
1906 do
1907 {
1908 vertexPtr->vy -= displacement.vy;
1909 vertexPtr++;
1910 }
1911 while(--i);
1912 }
1913
1914 return;
1915 }
1916 }
1917 polyPtr++;
1918 polysLeft--;
1919 }
1920
1921 }
1922 }
1923 if (obstaclePtr->DynPtr->Displacement.vy>0)
1924 {
1925 obstaclePtr->DynPtr->Displacement.vy=0;
1926 obstaclePtr->DynPtr->DistanceLeftToMove = Magnitude(&obstaclePtr->DynPtr->Displacement);
1927 }
1928 if (obstaclePtr->DynPtr->LinImpulse.vy>0)
1929 {
1930 obstaclePtr->DynPtr->LinImpulse.vy=0;
1931 }
1932
1933 }
1934 {
1935 COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
1936
1937 if (reportPtr)
1938 {
1939 reportPtr->ObstacleSBPtr = obstacleSBPtr;
1940 reportPtr->ObstacleNormal.vx = -obstacleNormal.vx;
1941 reportPtr->ObstacleNormal.vy = -obstacleNormal.vy;
1942 reportPtr->ObstacleNormal.vz = -obstacleNormal.vz;
1943 }
1944 }
1945 if (obstacleSBPtr) //&& !(obstacleSBPtr->DynPtr->StopOnCollision))
1946 /* give obstacle a report too */
1947 {
1948 COLLISIONREPORT *reportPtr = AllocateCollisionReport(obstacleSBPtr->DynPtr);
1949
1950 if (reportPtr)
1951 {
1952 reportPtr->ObstacleSBPtr = sbPtr;
1953 reportPtr->ObstacleNormal.vx = obstacleNormal.vx;
1954 reportPtr->ObstacleNormal.vy = obstacleNormal.vy;
1955 reportPtr->ObstacleNormal.vz = obstacleNormal.vz;
1956 }
1957 /* see if object has hit the 'floor' */
1958 if (obstacleSBPtr->DynPtr->GravityOn)
1959 {
1960 if (obstacleSBPtr->DynPtr->UseStandardGravity&&PlanarGravity)
1961 {
1962 if (obstacleNormal.vy < -FLOOR_THRESHOLD)
1963 {
1964 obstacleSBPtr->DynPtr->IsInContactWithFloor = 1;
1965 if (obstacleNormal.vy < -NEARLYFLATFLOOR_THRESHOLD) obstacleSBPtr->DynPtr->IsInContactWithNearlyFlatFloor = 1;
1966 }
1967 }
1968 else
1969 {
1970 int angle = DotProduct(&obstacleNormal,&obstacleSBPtr->DynPtr->GravityDirection);
1971 if (angle < -FLOOR_THRESHOLD)
1972 {
1973 /* we've hit something that's against the direction of gravity */
1974 obstacleSBPtr->DynPtr->IsInContactWithFloor = 1;
1975 if (angle < -NEARLYFLATFLOOR_THRESHOLD) obstacleSBPtr->DynPtr->IsInContactWithNearlyFlatFloor = 1;
1976 }
1977 }
1978 }
1979
1980 }
1981 }
1982 }
1983 // textprint("moving %d out of %d\n",distanceToMove,dynPtr->DistanceLeftToMove);
1984
1985 /* move object */
1986
1987 // textprint("disp %d %d %d\n",displacement.vx,displacement.vy,displacement.vz);
1988
1989 }
1990 if (dynPtr->Displacement.vy>0 && dynPtr->CollisionReportPtr)
1991 {
1992 }
1993 else
1994 {
1995 AddVectorToVector(dynPtr->Displacement, dynPtr->Position);
1996 }
1997
1998 #if 0
1999 if (distanceToMove!=dynPtr->DistanceLeftToMove)
2000 {
2001 /* create a report about the collision */
2002 {
2003 COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
2004
2005 if (reportPtr)
2006 {
2007 reportPtr->ObstacleSBPtr = obstacleSBPtr;
2008 reportPtr->ObstacleNormal.vx = -obstacleNormal.vx;
2009 reportPtr->ObstacleNormal.vy = -obstacleNormal.vy;
2010 reportPtr->ObstacleNormal.vz = -obstacleNormal.vz;
2011 }
2012 }
2013
2014 if (obstacleSBPtr) //&& !(obstacleSBPtr->DynPtr->StopOnCollision))
2015 /* give obstacle a report too */
2016 {
2017 COLLISIONREPORT *reportPtr = AllocateCollisionReport(obstacleSBPtr->DynPtr);
2018
2019 if (reportPtr)
2020 {
2021 reportPtr->ObstacleSBPtr = sbPtr;
2022 reportPtr->ObstacleNormal.vx = obstacleNormal.vx;
2023 reportPtr->ObstacleNormal.vy = obstacleNormal.vy;
2024 reportPtr->ObstacleNormal.vz = obstacleNormal.vz;
2025 }
2026 }
2027 }
2028 #endif
2029
2030
2031 }
2032
2033
2034
2035
2036
TestForValidPlayerStandUp(STRATEGYBLOCK * sbPtr)2037 static void TestForValidPlayerStandUp(STRATEGYBLOCK *sbPtr)
2038 {
2039 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2040
2041 /* make a collision volume corresponding to a standing character */
2042 {
2043 COLLISION_EXTENTS *extentsPtr = 0;
2044
2045 switch(AvP.PlayerType)
2046 {
2047 default:
2048 LOCALASSERT(0);
2049 /* if no debug then fall through to marine */
2050 case I_Marine:
2051 extentsPtr = &CollisionExtents[CE_MARINE];
2052 break;
2053
2054 case I_Alien:
2055 extentsPtr = &CollisionExtents[CE_ALIEN];
2056 break;
2057
2058 case I_Predator:
2059 extentsPtr = &CollisionExtents[CE_PREDATOR];
2060 break;
2061
2062 }
2063
2064 /* max X */
2065 dynPtr->ObjectVertices[0].vx = extentsPtr->CollisionRadius;
2066 dynPtr->ObjectVertices[1].vx = extentsPtr->CollisionRadius;
2067 dynPtr->ObjectVertices[2].vx = extentsPtr->CollisionRadius;
2068 dynPtr->ObjectVertices[3].vx = extentsPtr->CollisionRadius;
2069
2070 /* max Z */
2071 dynPtr->ObjectVertices[0].vz = extentsPtr->CollisionRadius;
2072 dynPtr->ObjectVertices[2].vz = extentsPtr->CollisionRadius;
2073 dynPtr->ObjectVertices[4].vz = extentsPtr->CollisionRadius;
2074 dynPtr->ObjectVertices[6].vz = extentsPtr->CollisionRadius;
2075
2076 /* min X */
2077 dynPtr->ObjectVertices[4].vx = -extentsPtr->CollisionRadius;
2078 dynPtr->ObjectVertices[5].vx = -extentsPtr->CollisionRadius;
2079 dynPtr->ObjectVertices[6].vx = -extentsPtr->CollisionRadius;
2080 dynPtr->ObjectVertices[7].vx = -extentsPtr->CollisionRadius;
2081
2082 /* min Z */
2083 dynPtr->ObjectVertices[1].vz = -extentsPtr->CollisionRadius;
2084 dynPtr->ObjectVertices[3].vz = -extentsPtr->CollisionRadius;
2085 dynPtr->ObjectVertices[5].vz = -extentsPtr->CollisionRadius;
2086 dynPtr->ObjectVertices[7].vz = -extentsPtr->CollisionRadius;
2087
2088 /* max Y */
2089 dynPtr->ObjectVertices[0].vy = extentsPtr->Bottom;
2090 dynPtr->ObjectVertices[1].vy = extentsPtr->Bottom;
2091 dynPtr->ObjectVertices[4].vy = extentsPtr->Bottom;
2092 dynPtr->ObjectVertices[5].vy = extentsPtr->Bottom;
2093
2094 /* min Y */
2095 dynPtr->ObjectVertices[2].vy = extentsPtr->StandingTop;
2096 dynPtr->ObjectVertices[3].vy = extentsPtr->StandingTop;
2097 dynPtr->ObjectVertices[6].vy = extentsPtr->StandingTop;
2098 dynPtr->ObjectVertices[7].vy = extentsPtr->StandingTop;
2099
2100 /* translate cuboid into world space */
2101 {
2102 VECTORCH *vertexPtr = dynPtr->ObjectVertices;
2103
2104 int vertexNum=8;
2105 do
2106 {
2107 vertexPtr->vx += dynPtr->Position.vx;
2108 vertexPtr->vy += dynPtr->Position.vy;
2109 vertexPtr->vz += dynPtr->Position.vz;
2110 vertexPtr++;
2111 }
2112 while(--vertexNum);
2113 }
2114
2115 }
2116
2117 /* look for polygons inside this volume */
2118 FindLandscapePolygonsInObjectsVicinity(sbPtr);
2119 FindObjectsToRelocateAgainst(sbPtr);
2120
2121
2122 {
2123
2124 int polysLeft;
2125 struct ColPolyTag *polyPtr;
2126
2127 polysLeft = NumberOfCollisionPolys;
2128 polyPtr = CollisionPolysArray;
2129
2130 while(polysLeft)
2131 {
2132 if(DoesPolygonIntersectNRBB(polyPtr,dynPtr->ObjectVertices))
2133 {
2134 int greatestDistance;
2135
2136 {
2137 VECTORCH vertex = dynPtr->ObjectVertices[WhichNRBBVertex(dynPtr,&(polyPtr->PolyNormal))];
2138 vertex.vx -= polyPtr->PolyPoint[0].vx;
2139 vertex.vy -= polyPtr->PolyPoint[0].vy;
2140 vertex.vz -= polyPtr->PolyPoint[0].vz;
2141 greatestDistance = -DotProduct(&vertex,&(polyPtr->PolyNormal));
2142 }
2143
2144 if (greatestDistance>0)
2145 {
2146 /* sorry, no standing room */
2147 CreateNRBBForObject(sbPtr);
2148 return;
2149 }
2150 }
2151 polyPtr++;
2152 polysLeft--;
2153 }
2154
2155 }
2156
2157 /* standing up is ok */
2158 {
2159 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
2160
2161 /* set player state */
2162 playerStatusPtr->ShapeState = PMph_Standing;
2163
2164 /* if player is an alien, cancel his ability to walk on walls */
2165 if (AvP.PlayerType == I_Alien)
2166 {
2167 dynPtr->UseStandardGravity=1;
2168 }
2169 }
2170
2171 }
SteppingUpIsValid(STRATEGYBLOCK * sbPtr)2172 static int SteppingUpIsValid(STRATEGYBLOCK *sbPtr)
2173 {
2174 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2175 VECTORCH displacement;
2176
2177 displacement.vx = MUL_FIXED(DirectionOfTravel.vx, COLLISION_GRANULARITY*2);
2178 displacement.vy = - DistanceToStepUp;
2179 displacement.vz = MUL_FIXED(DirectionOfTravel.vz, COLLISION_GRANULARITY*2);
2180
2181
2182
2183 {
2184 int i=8;
2185 VECTORCH *vertexPtr = dynPtr->ObjectVertices;
2186 do
2187 {
2188 vertexPtr->vx += displacement.vx;
2189 vertexPtr->vy += displacement.vy;
2190 vertexPtr->vz += displacement.vz;
2191 vertexPtr++;
2192 }
2193 while(--i);
2194 dynPtr->Position.vx += displacement.vx;
2195 dynPtr->Position.vy += displacement.vy;
2196 dynPtr->Position.vz += displacement.vz;
2197 }
2198
2199 /* look for polygons inside this volume */
2200 FindLandscapePolygonsInObjectsVicinity(sbPtr);
2201 FindObjectsToRelocateAgainst(sbPtr);
2202
2203
2204 {
2205
2206 int polysLeft;
2207 struct ColPolyTag *polyPtr;
2208
2209 polysLeft = NumberOfCollisionPolys;
2210 polyPtr = CollisionPolysArray;
2211
2212 while(polysLeft)
2213 {
2214 if(DoesPolygonIntersectNRBB(polyPtr,dynPtr->ObjectVertices))
2215 {
2216 #if 0
2217 int greatestDistance;
2218
2219 {
2220 VECTORCH vertex = dynPtr->ObjectVertices[WhichNRBBVertex(dynPtr,&(polyPtr->PolyNormal))];
2221 vertex.vx -= polyPtr->PolyPoint[0].vx;
2222 vertex.vy -= polyPtr->PolyPoint[0].vy;
2223 vertex.vz -= polyPtr->PolyPoint[0].vz;
2224 greatestDistance = -DotProduct(&vertex,&(polyPtr->PolyNormal));
2225 }
2226
2227 if (greatestDistance>0)
2228 #endif
2229 {
2230 /* sorry, there's a polygon in the way */
2231 //textprint("no step %d\n",greatestDistance);
2232 {
2233 int i=8;
2234 VECTORCH *vertexPtr = dynPtr->ObjectVertices;
2235 do
2236 {
2237 vertexPtr->vx -= displacement.vx;
2238 vertexPtr->vy -= displacement.vy;
2239 vertexPtr->vz -= displacement.vz;
2240 vertexPtr++;
2241 }
2242 while(--i);
2243 dynPtr->Position.vx -= displacement.vx;
2244 dynPtr->Position.vy -= displacement.vy;
2245 dynPtr->Position.vz -= displacement.vz;
2246 }
2247 return 0;
2248 }
2249 }
2250 polyPtr++;
2251 polysLeft--;
2252 }
2253
2254 }
2255
2256 /* steping up is ok */
2257 {
2258 //textprint("step ok\n");
2259 return 1;
2260 }
2261
2262 }
2263
FindLandscapePolygonsInObjectsPath(STRATEGYBLOCK * sbPtr)2264 static void FindLandscapePolygonsInObjectsPath(STRATEGYBLOCK *sbPtr)
2265 {
2266 extern int NumActiveBlocks;
2267 extern DISPLAYBLOCK *ActiveBlockList[];
2268
2269 /* initialise near polygons array */
2270 CollisionPolysPtr = &CollisionPolysArray[0];
2271 NumberOfCollisionPolys=0;
2272
2273 /* scan through ActiveBlockList for modules */
2274 {
2275 int numberOfObjects = NumActiveBlocks;
2276 while(numberOfObjects)
2277 {
2278 DISPLAYBLOCK* objectPtr = ActiveBlockList[--numberOfObjects];
2279 char isStaticObject=0;
2280
2281 GLOBALASSERT(objectPtr);
2282 if(objectPtr->ObStrategyBlock)
2283 if(objectPtr->ObStrategyBlock->DynPtr)
2284 {
2285 if(((objectPtr->ObStrategyBlock->DynPtr->IsStatic)
2286 ||(objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithObjects))
2287 &&(!objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithEnvironment))
2288 isStaticObject=1;
2289 }
2290
2291 if (objectPtr->ObMyModule)
2292 {
2293 MakeDynamicBoundingBoxForObject(sbPtr, &(objectPtr->ObWorld));
2294
2295 /* if the bounding box intersects with the object, investigate */
2296 if (( (DBBMaxX >= objectPtr->ObMinX) && (DBBMinX <= objectPtr->ObMaxX) )
2297 &&( (DBBMaxY >= objectPtr->ObMinY) && (DBBMinY <= objectPtr->ObMaxY) )
2298 &&( (DBBMaxZ >= objectPtr->ObMinZ) && (DBBMinZ <= objectPtr->ObMaxZ) ))
2299 TestShapeWithDynamicBoundingBox(objectPtr,sbPtr->DynPtr);
2300 }
2301 else if (isStaticObject)
2302 {
2303 MakeDynamicBoundingBoxForObject(sbPtr, &(objectPtr->ObWorld));
2304
2305 /* if the bounding box intersects with the object, investigate */
2306 if (( (DBBMaxX >= -objectPtr->ObRadius) && (DBBMinX <= objectPtr->ObRadius) )
2307 &&( (DBBMaxY >= -objectPtr->ObRadius) && (DBBMinY <= objectPtr->ObRadius) )
2308 &&( (DBBMaxZ >= -objectPtr->ObRadius) && (DBBMinZ <= objectPtr->ObRadius) ))
2309 TestShapeWithDynamicBoundingBox(objectPtr,sbPtr->DynPtr);
2310 }
2311 }
2312 }
2313 }
FindObjectPolygonsInObjectsPath(STRATEGYBLOCK * sbPtr)2314 static void FindObjectPolygonsInObjectsPath(STRATEGYBLOCK *sbPtr)
2315 {
2316 DYNAMICSBLOCK *dynPtr=sbPtr->DynPtr;
2317 /* check against other objects */
2318 {
2319 VECTORCH zero = {0,0,0};
2320 int i = NumberOfDynamicObjects;
2321 MakeDynamicBoundingBoxForObject(sbPtr, &zero);
2322 while(i--)
2323 {
2324
2325 STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i];
2326 VECTORCH *objectVerticesPtr = obstaclePtr->DynPtr->ObjectVertices;
2327
2328 /* check whether collision is even possible */
2329 {
2330 if (sbPtr==obstaclePtr)
2331 continue;
2332
2333 /* can it be seen? */
2334 if(obstaclePtr->SBdptr->ObFlags&ObFlag_NotVis) continue;
2335
2336 /* two sprites */
2337 if((dynPtr->DynamicsType == DYN_TYPE_SPRITE_COLLISIONS)
2338 &&(obstaclePtr->DynPtr->DynamicsType == DYN_TYPE_SPRITE_COLLISIONS) )
2339 continue;
2340
2341 if ( (dynPtr->IgnoreSameObjectsAsYou || obstaclePtr->DynPtr->IgnoreSameObjectsAsYou)
2342 &&(sbPtr->I_SBtype == obstaclePtr->I_SBtype) )
2343 continue;
2344
2345 if (obstaclePtr->DynPtr->OnlyCollideWithObjects)
2346 continue;
2347
2348 if (obstaclePtr->DynPtr->OnlyCollideWithEnvironment)
2349 continue;
2350
2351 if ( ((obstaclePtr->SBdptr == Player) && dynPtr->IgnoreThePlayer)
2352 ||((sbPtr->SBdptr == Player) && obstaclePtr->DynPtr->IgnoreThePlayer) )
2353 continue;
2354
2355 if( (sbPtr->SBdptr==Player)
2356 &&( (obstaclePtr->I_SBtype == I_BehaviourHierarchicalFragment)
2357 ||(obstaclePtr->DynPtr->IsPickupObject))
2358 )
2359 {
2360 continue;
2361 }
2362
2363 if (!( ( (DBBMaxX >= objectVerticesPtr[7].vx) && (DBBMinX <= objectVerticesPtr[0].vx) )
2364 &&( (DBBMaxY >= objectVerticesPtr[7].vy) && (DBBMinY <= objectVerticesPtr[0].vy) )
2365 &&( (DBBMaxZ >= objectVerticesPtr[7].vz) && (DBBMinZ <= objectVerticesPtr[0].vz) ) ))
2366 continue;
2367 }
2368
2369 {
2370 const int *vertexIndexPtr=&CuboidVertexList[0];
2371 int face=6;
2372
2373 do
2374 {
2375 struct ColPolyTag poly;
2376 poly.NumberOfVertices=4;
2377 poly.ParentObject = obstaclePtr->SBdptr;
2378
2379 poly.PolyPoint[0]=objectVerticesPtr[*vertexIndexPtr++];
2380 poly.PolyPoint[1]=objectVerticesPtr[*vertexIndexPtr++];
2381 poly.PolyPoint[2]=objectVerticesPtr[*vertexIndexPtr++];
2382 poly.PolyPoint[3]=objectVerticesPtr[*vertexIndexPtr++];
2383
2384
2385 if (IsPolygonWithinDynamicBoundingBox(&poly))
2386 {
2387 {
2388 switch(face)
2389 {
2390 case 6: /* all points are on max y face */
2391 {
2392 poly.PolyNormal.vx = 0;
2393 poly.PolyNormal.vy = ONE_FIXED;
2394 poly.PolyNormal.vz = 0;
2395 break;
2396 }
2397 case 5: /* all points are on max z face */
2398 {
2399 poly.PolyNormal.vx = 0;
2400 poly.PolyNormal.vy = 0;
2401 poly.PolyNormal.vz = ONE_FIXED;
2402 break;
2403 }
2404 case 4: /* all points are on max x face */
2405 {
2406 poly.PolyNormal.vx = ONE_FIXED;
2407 poly.PolyNormal.vy = 0;
2408 poly.PolyNormal.vz = 0;
2409 break;
2410 }
2411 case 3: /* all points are on min z face */
2412 {
2413 poly.PolyNormal.vx = 0;
2414 poly.PolyNormal.vy = 0;
2415 poly.PolyNormal.vz = -ONE_FIXED;
2416 break;
2417 }
2418 case 2: /* all points are on min x face */
2419 {
2420 poly.PolyNormal.vx = -ONE_FIXED;
2421 poly.PolyNormal.vy = 0;
2422 poly.PolyNormal.vz = 0;
2423 break;
2424 }
2425 case 1: /* all points are on min y face */
2426 {
2427 poly.PolyNormal.vx = 0;
2428 poly.PolyNormal.vy = -ONE_FIXED;
2429 poly.PolyNormal.vz = 0;
2430 break;
2431 }
2432 }
2433 }
2434
2435 #if 0
2436 polyDistance = DistanceMovedBeforeObjectHitsPolygon(dynPtr,&poly,distanceToMove);
2437 if (polyDistance>=0)
2438 {
2439 /* If the player moves into a weapon/ammo/etc, report the collision but
2440 don't stop the player. (ie. let him walk through it) */
2441 if( (sbPtr->SBdptr==Player)
2442 &&( (obstaclePtr->I_SBtype == I_BehaviourHierarchicalFragment)
2443 ||(obstaclePtr->DynPtr->IsPickupObject))
2444 )
2445 {
2446 /* create a report about the collision */
2447 COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
2448 if (reportPtr)
2449 {
2450 reportPtr->ObstacleSBPtr = obstaclePtr;
2451 reportPtr->ObstacleNormal = poly.PolyNormal;
2452 }
2453 }
2454 else
2455 {
2456 distanceToMove = polyDistance;
2457 obstacleNormal = poly.PolyNormal;
2458 obstaclePoint = poly.PolyPoint[0];
2459 obstacleSBPtr = obstaclePtr;
2460 LOCALASSERT(obstaclePtr);
2461 topOfStep = -2000000000;
2462 }
2463 }
2464 #endif
2465 *CollisionPolysPtr = poly;
2466
2467 CollisionPolysPtr++;
2468 NumberOfCollisionPolys++;
2469
2470 }
2471 face--;
2472 }
2473 while(face);
2474
2475 }
2476 }
2477 }
2478 }
2479
FindLandscapePolygonsInObjectsVicinity(STRATEGYBLOCK * sbPtr)2480 static void FindLandscapePolygonsInObjectsVicinity(STRATEGYBLOCK *sbPtr)
2481 {
2482 extern int NumActiveBlocks;
2483 extern DISPLAYBLOCK *ActiveBlockList[];
2484
2485 /* intialise near polygons array */
2486 CollisionPolysPtr = &CollisionPolysArray[0];
2487 NumberOfCollisionPolys=0;
2488
2489 /* scan through ActiveBlockList for modules */
2490 {
2491 int numberOfObjects = NumActiveBlocks;
2492 while(numberOfObjects)
2493 {
2494 DISPLAYBLOCK* objectPtr = ActiveBlockList[--numberOfObjects];
2495 char isStaticObject=0;
2496
2497 GLOBALASSERT(objectPtr);
2498 if(objectPtr->ObStrategyBlock)
2499 if(objectPtr->ObStrategyBlock->DynPtr)
2500 {
2501 if(((objectPtr->ObStrategyBlock->DynPtr->IsStatic)
2502 ||(objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithObjects))
2503 &&(!objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithEnvironment))
2504 isStaticObject=1;
2505 }
2506
2507 if (objectPtr->ObMyModule) /* is object a module or static? */
2508 {
2509 MakeStaticBoundingBoxForObject(sbPtr);
2510
2511 /* translate SBB into space of landscape module */
2512 SBBMinX -= objectPtr->ObWorld.vx;
2513 SBBMaxX -= objectPtr->ObWorld.vx;
2514
2515 SBBMinY -= objectPtr->ObWorld.vy;
2516 SBBMaxY -= objectPtr->ObWorld.vy;
2517
2518 SBBMinZ -= objectPtr->ObWorld.vz;
2519 SBBMaxZ -= objectPtr->ObWorld.vz;
2520
2521 /* if the bounding box intersects with the object, investigate */
2522 if (( (SBBMaxX >= objectPtr->ObMinX) && (SBBMinX <= objectPtr->ObMaxX) )
2523 &&( (SBBMaxY >= objectPtr->ObMinY) && (SBBMinY <= objectPtr->ObMaxY) )
2524 &&( (SBBMaxZ >= objectPtr->ObMinZ) && (SBBMinZ <= objectPtr->ObMaxZ) ))
2525 TestShapeWithStaticBoundingBox(objectPtr);
2526 }
2527 else if (isStaticObject)
2528 {
2529 MakeStaticBoundingBoxForObject(sbPtr);
2530
2531 /* translate SBB into space of landscape module */
2532 SBBMinX -= objectPtr->ObWorld.vx;
2533 SBBMaxX -= objectPtr->ObWorld.vx;
2534
2535 SBBMinY -= objectPtr->ObWorld.vy;
2536 SBBMaxY -= objectPtr->ObWorld.vy;
2537
2538 SBBMinZ -= objectPtr->ObWorld.vz;
2539 SBBMaxZ -= objectPtr->ObWorld.vz;
2540
2541 /* if the bounding box intersects with the object, investigate */
2542 if (( (SBBMaxX >= objectPtr->ObMinX) && (SBBMinX <= objectPtr->ObMaxX) )
2543 &&( (SBBMaxY >= objectPtr->ObMinY) && (SBBMinY <= objectPtr->ObMaxY) )
2544 &&( (SBBMaxZ >= objectPtr->ObMinZ) && (SBBMinZ <= objectPtr->ObMaxZ) ))
2545 TestShapeWithStaticBoundingBox(objectPtr);
2546 }
2547
2548 }
2549 }
2550 }
2551
FindObjectsToRelocateAgainst(STRATEGYBLOCK * sbPtr)2552 static void FindObjectsToRelocateAgainst(STRATEGYBLOCK *sbPtr)
2553 {
2554 MakeStaticBoundingBoxForObject(sbPtr);
2555 {
2556 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2557 int i = NumberOfDynamicObjects;
2558 while(i--)
2559 {
2560 STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i];
2561
2562 /* check whether collision is even possible */
2563 if (sbPtr==obstaclePtr)
2564 continue;
2565
2566 /* ignore platform lifts */
2567 if(obstaclePtr->DynPtr->OnlyCollideWithObjects)
2568 continue;
2569
2570 /* ignore things that only collide with environment */
2571 if (obstaclePtr->DynPtr->OnlyCollideWithEnvironment)
2572 continue;
2573
2574 /* don't relocate against ammo and stuff */
2575 if (sbPtr->SBdptr==Player)
2576 {
2577 if(obstaclePtr->DynPtr->IsPickupObject)
2578 {
2579 continue;
2580 }
2581 }
2582
2583 /* two sprites */
2584 if((dynPtr->DynamicsType == DYN_TYPE_SPRITE_COLLISIONS)
2585 &&(obstaclePtr->DynPtr->DynamicsType == DYN_TYPE_SPRITE_COLLISIONS) )
2586 continue;
2587
2588 if (dynPtr->IgnoreSameObjectsAsYou
2589 &&(sbPtr->I_SBtype == obstaclePtr->I_SBtype) )
2590 continue;
2591
2592 TestObjectWithStaticBoundingBox(obstaclePtr->SBdptr);
2593 }
2594 }
2595 }
2596
MakeDynamicBoundingBoxForObject(STRATEGYBLOCK * sbPtr,VECTORCH * worldOffsetPtr)2597 static void MakeDynamicBoundingBoxForObject(STRATEGYBLOCK *sbPtr, VECTORCH *worldOffsetPtr)
2598 {
2599 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2600
2601 DBBMaxX = dynPtr->ObjectVertices[0].vx - worldOffsetPtr->vx + COLLISION_GRANULARITY;
2602 DBBMinX = dynPtr->ObjectVertices[7].vx - worldOffsetPtr->vx - COLLISION_GRANULARITY;
2603
2604 DBBMaxY = dynPtr->ObjectVertices[0].vy - worldOffsetPtr->vy + COLLISION_GRANULARITY;
2605 DBBMinY = dynPtr->ObjectVertices[7].vy - worldOffsetPtr->vy - COLLISION_GRANULARITY;
2606
2607 DBBMaxZ = dynPtr->ObjectVertices[0].vz - worldOffsetPtr->vz + COLLISION_GRANULARITY;
2608 DBBMinZ = dynPtr->ObjectVertices[7].vz - worldOffsetPtr->vz - COLLISION_GRANULARITY;
2609
2610 if (dynPtr->Displacement.vx > 0)
2611 {
2612 DBBMaxX += dynPtr->Displacement.vx;
2613 }
2614 else
2615 {
2616 DBBMinX += dynPtr->Displacement.vx;
2617 }
2618
2619 if (dynPtr->Displacement.vy > 0)
2620 {
2621 DBBMaxY += dynPtr->Displacement.vy;
2622 }
2623 else
2624 {
2625 DBBMinY += dynPtr->Displacement.vy;
2626 }
2627
2628 if (dynPtr->Displacement.vz > 0)
2629 {
2630 DBBMaxZ += dynPtr->Displacement.vz;
2631 }
2632 else
2633 {
2634 DBBMinZ += dynPtr->Displacement.vz;
2635 }
2636
2637 }
2638
MakeStaticBoundingBoxForSphere(STRATEGYBLOCK * sbPtr)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 }
MakeStaticBoundingBoxForNRBB(STRATEGYBLOCK * sbPtr)2651 static void MakeStaticBoundingBoxForNRBB(STRATEGYBLOCK *sbPtr)
2652 {
2653 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2654 SBBMinX = dynPtr->ObjectVertices[7].vx - COLLISION_GRANULARITY*16;
2655 SBBMaxX = dynPtr->ObjectVertices[0].vx + COLLISION_GRANULARITY*16;
2656
2657 SBBMinY = dynPtr->ObjectVertices[7].vy - COLLISION_GRANULARITY*16;
2658 SBBMaxY = dynPtr->ObjectVertices[0].vy + COLLISION_GRANULARITY*16;
2659
2660 SBBMinZ = dynPtr->ObjectVertices[7].vz - COLLISION_GRANULARITY*16;
2661 SBBMaxZ = dynPtr->ObjectVertices[0].vz + COLLISION_GRANULARITY*16;
2662 }
2663
TestShapeWithDynamicBoundingBox(DISPLAYBLOCK * objectPtr,DYNAMICSBLOCK * mainDynPtr)2664 static void TestShapeWithDynamicBoundingBox(DISPLAYBLOCK *objectPtr, DYNAMICSBLOCK *mainDynPtr)
2665 {
2666 int numberOfItems;
2667 int needToRotate = 0;
2668
2669 /* KJL 10:58:22 24/11/98 - If the object is a static object rather than a module,
2670 we'll need to rotate the polygons into world-space */
2671 if (objectPtr->ObStrategyBlock)
2672 {
2673 DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
2674
2675 if (dynPtr)
2676 {
2677 if (dynPtr->IsStatic)
2678 {
2679 needToRotate = 1;
2680 }
2681 }
2682 }
2683
2684
2685 /* okay, let's setup the shape's data and access the first poly */
2686 numberOfItems = SetupPolygonAccess(objectPtr);
2687
2688 /* go through polys looking for those which intersect with the bounding box */
2689 while(numberOfItems--)
2690 {
2691 AccessNextPolygon();
2692
2693 if (mainDynPtr->IgnoresNotVisPolys && (PolygonFlag & iflag_notvis) && !(PolygonFlag & iflag_mirror)) continue;
2694
2695 GetPolygonVertices(CollisionPolysPtr);
2696
2697 if (needToRotate)
2698 {
2699 int i = CollisionPolysPtr->NumberOfVertices;
2700 VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
2701
2702
2703 do
2704 {
2705 RotateVector(polyVertexPtr,&objectPtr->ObMat);
2706 polyVertexPtr++;
2707 }
2708 while(--i);
2709 }
2710
2711 {
2712 VECTORCH *vertices = CollisionPolysPtr->PolyPoint;
2713 if (CollisionPolysPtr->NumberOfVertices==4)
2714 {
2715 if (vertices[0].vy < DBBMinY)
2716 if (vertices[1].vy < DBBMinY)
2717 if (vertices[2].vy < DBBMinY)
2718 if (vertices[3].vy < DBBMinY)
2719 continue;
2720
2721 if (vertices[0].vx < DBBMinX)
2722 if (vertices[1].vx < DBBMinX)
2723 if (vertices[2].vx < DBBMinX)
2724 if (vertices[3].vx < DBBMinX)
2725 continue;
2726
2727 if (vertices[0].vx > DBBMaxX)
2728 if (vertices[1].vx > DBBMaxX)
2729 if (vertices[2].vx > DBBMaxX)
2730 if (vertices[3].vx > DBBMaxX)
2731 continue;
2732
2733 if (vertices[0].vz < DBBMinZ)
2734 if (vertices[1].vz < DBBMinZ)
2735 if (vertices[2].vz < DBBMinZ)
2736 if (vertices[3].vz < DBBMinZ)
2737 continue;
2738
2739 if (vertices[0].vz > DBBMaxZ)
2740 if (vertices[1].vz > DBBMaxZ)
2741 if (vertices[2].vz > DBBMaxZ)
2742 if (vertices[3].vz > DBBMaxZ)
2743 continue;
2744
2745 if (vertices[0].vy > DBBMaxY)
2746 if (vertices[1].vy > DBBMaxY)
2747 if (vertices[2].vy > DBBMaxY)
2748 if (vertices[3].vy > DBBMaxY)
2749 continue;
2750
2751 }
2752 else
2753 {
2754 if (vertices[0].vy < DBBMinY)
2755 if (vertices[1].vy < DBBMinY)
2756 if (vertices[2].vy < DBBMinY)
2757 continue;
2758
2759 if (vertices[0].vx < DBBMinX)
2760 if (vertices[1].vx < DBBMinX)
2761 if (vertices[2].vx < DBBMinX)
2762 continue;
2763
2764 if (vertices[0].vx > DBBMaxX)
2765 if (vertices[1].vx > DBBMaxX)
2766 if (vertices[2].vx > DBBMaxX)
2767 continue;
2768
2769 if (vertices[0].vz < DBBMinZ)
2770 if (vertices[1].vz < DBBMinZ)
2771 if (vertices[2].vz < DBBMinZ)
2772 continue;
2773
2774 if (vertices[0].vz > DBBMaxZ)
2775 if (vertices[1].vz > DBBMaxZ)
2776 if (vertices[2].vz > DBBMaxZ)
2777 continue;
2778
2779 if (vertices[0].vy > DBBMaxY)
2780 if (vertices[1].vy > DBBMaxY)
2781 if (vertices[2].vy > DBBMaxY)
2782 continue;
2783
2784 }
2785 }
2786
2787 /* add object's world space coords to vertices */
2788 {
2789 int i = CollisionPolysPtr->NumberOfVertices;
2790 VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
2791
2792
2793 do
2794 {
2795 polyVertexPtr->vx += objectPtr->ObWorld.vx;
2796 polyVertexPtr->vy += objectPtr->ObWorld.vy;
2797 polyVertexPtr->vz += objectPtr->ObWorld.vz;
2798 polyVertexPtr++;
2799 }
2800 while(--i);
2801 }
2802
2803 /* get the poly's normal */
2804 GetPolygonNormal(CollisionPolysPtr);
2805 if (needToRotate)
2806 {
2807 RotateVector(&CollisionPolysPtr->PolyNormal,&objectPtr->ObMat);
2808 }
2809 CollisionPolysPtr->ParentObject = objectPtr;
2810
2811 CollisionPolysPtr++;
2812 NumberOfCollisionPolys++;
2813 /* ran out of space? */
2814 LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
2815
2816 if (PolygonFlag & iflag_no_bfc)
2817 {
2818 CollisionPolysPtr->NumberOfVertices = (CollisionPolysPtr-1)->NumberOfVertices;
2819 if(CollisionPolysPtr->NumberOfVertices==3)
2820 {
2821 CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[2];
2822 CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[1];
2823 CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[0];
2824 }
2825 else
2826 {
2827 CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[3];
2828 CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[2];
2829 CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[1];
2830 CollisionPolysPtr->PolyPoint[3] = (CollisionPolysPtr-1)->PolyPoint[0];
2831 }
2832
2833 CollisionPolysPtr->PolyNormal.vx = -(CollisionPolysPtr-1)->PolyNormal.vx;
2834 CollisionPolysPtr->PolyNormal.vy = -(CollisionPolysPtr-1)->PolyNormal.vy;
2835 CollisionPolysPtr->PolyNormal.vz = -(CollisionPolysPtr-1)->PolyNormal.vz;
2836 CollisionPolysPtr->ParentObject = objectPtr;
2837
2838 CollisionPolysPtr++;
2839 NumberOfCollisionPolys++;
2840 /* ran out of space? */
2841 LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
2842 }
2843 }
2844
2845 return;
2846 }
TestShapeWithParticlesDynamicBoundingBox(DISPLAYBLOCK * objectPtr)2847 static void TestShapeWithParticlesDynamicBoundingBox(DISPLAYBLOCK *objectPtr)
2848 {
2849 int numberOfItems;
2850 int needToRotate = 0;
2851
2852 /* KJL 10:58:22 24/11/98 - If the object is a static object rather than a module,
2853 we'll need to rotate the polygons into world-space */
2854 if (objectPtr->ObStrategyBlock)
2855 {
2856 DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
2857
2858 if (dynPtr)
2859 {
2860 if (dynPtr->IsStatic)
2861 {
2862 needToRotate = 1;
2863 }
2864 }
2865 }
2866
2867
2868 /* okay, let's setup the shape's data and access the first poly */
2869 numberOfItems = SetupPolygonAccess(objectPtr);
2870
2871 /* go through polys looking for those which intersect with the bounding box */
2872 while(numberOfItems--)
2873 {
2874 AccessNextPolygon();
2875
2876 if (PolygonFlag & iflag_notvis) continue;
2877
2878 GetPolygonVertices(CollisionPolysPtr);
2879 if (needToRotate)
2880 {
2881 int i = CollisionPolysPtr->NumberOfVertices;
2882 VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
2883
2884
2885 do
2886 {
2887 RotateVector(polyVertexPtr,&objectPtr->ObMat);
2888 polyVertexPtr++;
2889 }
2890 while(--i);
2891 }
2892
2893 {
2894 VECTORCH *vertices = CollisionPolysPtr->PolyPoint;
2895 if (CollisionPolysPtr->NumberOfVertices==4)
2896 {
2897 if (vertices[0].vy < DBBMinY)
2898 if (vertices[1].vy < DBBMinY)
2899 if (vertices[2].vy < DBBMinY)
2900 if (vertices[3].vy < DBBMinY)
2901 continue;
2902
2903 if (vertices[0].vx < DBBMinX)
2904 if (vertices[1].vx < DBBMinX)
2905 if (vertices[2].vx < DBBMinX)
2906 if (vertices[3].vx < DBBMinX)
2907 continue;
2908
2909 if (vertices[0].vx > DBBMaxX)
2910 if (vertices[1].vx > DBBMaxX)
2911 if (vertices[2].vx > DBBMaxX)
2912 if (vertices[3].vx > DBBMaxX)
2913 continue;
2914
2915 if (vertices[0].vz < DBBMinZ)
2916 if (vertices[1].vz < DBBMinZ)
2917 if (vertices[2].vz < DBBMinZ)
2918 if (vertices[3].vz < DBBMinZ)
2919 continue;
2920
2921 if (vertices[0].vz > DBBMaxZ)
2922 if (vertices[1].vz > DBBMaxZ)
2923 if (vertices[2].vz > DBBMaxZ)
2924 if (vertices[3].vz > DBBMaxZ)
2925 continue;
2926
2927 if (vertices[0].vy > DBBMaxY)
2928 if (vertices[1].vy > DBBMaxY)
2929 if (vertices[2].vy > DBBMaxY)
2930 if (vertices[3].vy > DBBMaxY)
2931 continue;
2932
2933 }
2934 else
2935 {
2936 if (vertices[0].vy < DBBMinY)
2937 if (vertices[1].vy < DBBMinY)
2938 if (vertices[2].vy < DBBMinY)
2939 continue;
2940
2941 if (vertices[0].vx < DBBMinX)
2942 if (vertices[1].vx < DBBMinX)
2943 if (vertices[2].vx < DBBMinX)
2944 continue;
2945
2946 if (vertices[0].vx > DBBMaxX)
2947 if (vertices[1].vx > DBBMaxX)
2948 if (vertices[2].vx > DBBMaxX)
2949 continue;
2950
2951 if (vertices[0].vz < DBBMinZ)
2952 if (vertices[1].vz < DBBMinZ)
2953 if (vertices[2].vz < DBBMinZ)
2954 continue;
2955
2956 if (vertices[0].vz > DBBMaxZ)
2957 if (vertices[1].vz > DBBMaxZ)
2958 if (vertices[2].vz > DBBMaxZ)
2959 continue;
2960
2961 if (vertices[0].vy > DBBMaxY)
2962 if (vertices[1].vy > DBBMaxY)
2963 if (vertices[2].vy > DBBMaxY)
2964 continue;
2965
2966 }
2967 }
2968
2969 /* add object's world space coords to vertices */
2970 {
2971 int i = CollisionPolysPtr->NumberOfVertices;
2972 VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
2973
2974 do
2975 {
2976 polyVertexPtr->vx += objectPtr->ObWorld.vx;
2977 polyVertexPtr->vy += objectPtr->ObWorld.vy;
2978 polyVertexPtr->vz += objectPtr->ObWorld.vz;
2979 polyVertexPtr++;
2980 }
2981 while(--i);
2982 }
2983
2984 /* get the poly's normal */
2985 GetPolygonNormal(CollisionPolysPtr);
2986 if (needToRotate)
2987 {
2988 RotateVector(&CollisionPolysPtr->PolyNormal,&objectPtr->ObMat);
2989 }
2990 CollisionPolysPtr->ParentObject = objectPtr;
2991
2992 CollisionPolysPtr++;
2993 NumberOfCollisionPolys++;
2994 /* ran out of space? */
2995 LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
2996
2997 if (PolygonFlag & iflag_no_bfc)
2998 {
2999 CollisionPolysPtr->NumberOfVertices = (CollisionPolysPtr-1)->NumberOfVertices;
3000 if(CollisionPolysPtr->NumberOfVertices==3)
3001 {
3002 CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[2];
3003 CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[1];
3004 CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[0];
3005 }
3006 else
3007 {
3008 CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[3];
3009 CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[2];
3010 CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[1];
3011 CollisionPolysPtr->PolyPoint[3] = (CollisionPolysPtr-1)->PolyPoint[0];
3012 }
3013
3014 CollisionPolysPtr->PolyNormal.vx = -(CollisionPolysPtr-1)->PolyNormal.vx;
3015 CollisionPolysPtr->PolyNormal.vy = -(CollisionPolysPtr-1)->PolyNormal.vy;
3016 CollisionPolysPtr->PolyNormal.vz = -(CollisionPolysPtr-1)->PolyNormal.vz;
3017 CollisionPolysPtr->ParentObject = objectPtr;
3018
3019 CollisionPolysPtr++;
3020 NumberOfCollisionPolys++;
3021 /* ran out of space? */
3022 LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
3023 }
3024 }
3025
3026 return;
3027 }
3028
TestShapeWithStaticBoundingBox(DISPLAYBLOCK * objectPtr)3029 static void TestShapeWithStaticBoundingBox(DISPLAYBLOCK *objectPtr)
3030 {
3031 int numberOfItems;
3032 int needToRotate = 0;
3033
3034 /* KJL 10:58:22 24/11/98 - If the object is a static object rather than a module,
3035 we'll need to rotate the polygons into world-space */
3036 if (objectPtr->ObStrategyBlock)
3037 {
3038 DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
3039
3040 if (dynPtr)
3041 {
3042 if (dynPtr->IsStatic)
3043 {
3044 needToRotate = 1;
3045 }
3046 }
3047 }
3048
3049 /* okay, let's setup the shape's data and access the first poly */
3050 numberOfItems = SetupPolygonAccess(objectPtr);
3051
3052 /* go through polys looking for those which intersect with the bounding box */
3053 while(numberOfItems--)
3054 {
3055 AccessNextPolygon();
3056
3057 // if (PolygonFlag & iflag_notvis) continue;
3058
3059 GetPolygonVertices(CollisionPolysPtr);
3060 if (needToRotate)
3061 {
3062 int i = CollisionPolysPtr->NumberOfVertices;
3063 VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
3064
3065
3066 do
3067 {
3068 RotateVector(polyVertexPtr,&objectPtr->ObMat);
3069 polyVertexPtr++;
3070 }
3071 while(--i);
3072 }
3073
3074 if(IsPolygonWithinStaticBoundingBox(CollisionPolysPtr))
3075 {
3076 /* add object's world space coords to vertices */
3077 {
3078 int i = CollisionPolysPtr->NumberOfVertices;
3079 VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
3080
3081 do
3082 {
3083 polyVertexPtr->vx += objectPtr->ObWorld.vx;
3084 polyVertexPtr->vy += objectPtr->ObWorld.vy;
3085 polyVertexPtr->vz += objectPtr->ObWorld.vz;
3086 polyVertexPtr++;
3087 }
3088 while(--i);
3089 }
3090
3091 /* get the poly's normal */
3092 GetPolygonNormal(CollisionPolysPtr);
3093 if (needToRotate)
3094 {
3095 RotateVector(&CollisionPolysPtr->PolyNormal,&objectPtr->ObMat);
3096 }
3097
3098 CollisionPolysPtr++;
3099 NumberOfCollisionPolys++;
3100
3101 /* ran out of space? */
3102 LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
3103 if (PolygonFlag & iflag_no_bfc)
3104 {
3105 CollisionPolysPtr->NumberOfVertices = (CollisionPolysPtr-1)->NumberOfVertices;
3106 if(CollisionPolysPtr->NumberOfVertices==3)
3107 {
3108 CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[2];
3109 CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[1];
3110 CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[0];
3111 }
3112 else
3113 {
3114 CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[3];
3115 CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[2];
3116 CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[1];
3117 CollisionPolysPtr->PolyPoint[3] = (CollisionPolysPtr-1)->PolyPoint[0];
3118 }
3119
3120 CollisionPolysPtr->PolyNormal.vx = -(CollisionPolysPtr-1)->PolyNormal.vx;
3121 CollisionPolysPtr->PolyNormal.vy = -(CollisionPolysPtr-1)->PolyNormal.vy;
3122 CollisionPolysPtr->PolyNormal.vz = -(CollisionPolysPtr-1)->PolyNormal.vz;
3123
3124 CollisionPolysPtr++;
3125 NumberOfCollisionPolys++;
3126 /* ran out of space? */
3127 LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
3128 }
3129 }
3130
3131 }
3132
3133 return;
3134 }
TestObjectWithStaticBoundingBox(DISPLAYBLOCK * objectPtr)3135 static void TestObjectWithStaticBoundingBox(DISPLAYBLOCK *objectPtr)
3136 {
3137
3138 DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
3139 // VECTORCH *objectPositionPtr = &(dynPtr->Position);
3140 /* if the bounding box does not intersect with the object at all just return */
3141 VECTORCH *objectVerticesPtr = dynPtr->ObjectVertices;
3142
3143 if (!( ( (SBBMaxX >= objectVerticesPtr[7].vx) && (SBBMinX <= objectVerticesPtr[0].vx) )
3144 &&( (SBBMaxY >= objectVerticesPtr[7].vy) && (SBBMinY <= objectVerticesPtr[0].vy) )
3145 &&( (SBBMaxZ >= objectVerticesPtr[7].vz) && (SBBMinZ <= objectVerticesPtr[0].vz) ) ))
3146 return;
3147
3148 /* okay, let's access the objects polys */
3149 {
3150 const int *vertexIndexPtr=&CuboidVertexList[0];
3151 int face=6;
3152
3153 do
3154 {
3155 CollisionPolysPtr->NumberOfVertices = 4;
3156 CollisionPolysPtr->PolyPoint[0]=objectVerticesPtr[*vertexIndexPtr++];
3157 CollisionPolysPtr->PolyPoint[1]=objectVerticesPtr[*vertexIndexPtr++];
3158 CollisionPolysPtr->PolyPoint[2]=objectVerticesPtr[*vertexIndexPtr++];
3159 CollisionPolysPtr->PolyPoint[3]=objectVerticesPtr[*vertexIndexPtr++];
3160
3161 if(IsPolygonWithinStaticBoundingBox(CollisionPolysPtr))
3162 {
3163 if(dynPtr->DynamicsType == DYN_TYPE_CUBOID_COLLISIONS)
3164 {
3165 switch(face)
3166 {
3167 case 6: /* all points are on max y face */
3168 {
3169 CollisionPolysPtr->PolyNormal.vx = dynPtr->OrientMat.mat21;
3170 CollisionPolysPtr->PolyNormal.vy = dynPtr->OrientMat.mat22;
3171 CollisionPolysPtr->PolyNormal.vz = dynPtr->OrientMat.mat23;
3172 break;
3173 }
3174 case 5: /* all points are on max z face */
3175 {
3176 CollisionPolysPtr->PolyNormal.vx = dynPtr->OrientMat.mat31;
3177 CollisionPolysPtr->PolyNormal.vy = dynPtr->OrientMat.mat32;
3178 CollisionPolysPtr->PolyNormal.vz = dynPtr->OrientMat.mat33;
3179 break;
3180 }
3181 case 4: /* all points are on max x face */
3182 {
3183 CollisionPolysPtr->PolyNormal.vx = dynPtr->OrientMat.mat11;
3184 CollisionPolysPtr->PolyNormal.vy = dynPtr->OrientMat.mat12;
3185 CollisionPolysPtr->PolyNormal.vz = dynPtr->OrientMat.mat13;
3186 break;
3187 }
3188 case 3: /* all points are on min z face */
3189 {
3190 CollisionPolysPtr->PolyNormal.vx = -dynPtr->OrientMat.mat31;
3191 CollisionPolysPtr->PolyNormal.vy = -dynPtr->OrientMat.mat32;
3192 CollisionPolysPtr->PolyNormal.vz = -dynPtr->OrientMat.mat33;
3193 break;
3194 }
3195 case 2: /* all points are on min x face */
3196 {
3197 CollisionPolysPtr->PolyNormal.vx = -dynPtr->OrientMat.mat11;
3198 CollisionPolysPtr->PolyNormal.vy = -dynPtr->OrientMat.mat12;
3199 CollisionPolysPtr->PolyNormal.vz = -dynPtr->OrientMat.mat13;
3200 break;
3201 }
3202 case 1: /* all points are on min y face */
3203 {
3204 CollisionPolysPtr->PolyNormal.vx = -dynPtr->OrientMat.mat21;
3205 CollisionPolysPtr->PolyNormal.vy = -dynPtr->OrientMat.mat22;
3206 CollisionPolysPtr->PolyNormal.vz = -dynPtr->OrientMat.mat23;
3207 break;
3208 }
3209 }
3210 }
3211 else
3212 {
3213 switch(face)
3214 {
3215 case 6: /* all points are on max y face */
3216 {
3217 CollisionPolysPtr->PolyNormal.vx = 0;
3218 CollisionPolysPtr->PolyNormal.vy = ONE_FIXED;
3219 CollisionPolysPtr->PolyNormal.vz = 0;
3220 break;
3221 }
3222 case 5: /* all points are on max z face */
3223 {
3224 CollisionPolysPtr->PolyNormal.vx = 0;
3225 CollisionPolysPtr->PolyNormal.vy = 0;
3226 CollisionPolysPtr->PolyNormal.vz = ONE_FIXED;
3227 break;
3228 }
3229 case 4: /* all points are on max x face */
3230 {
3231 CollisionPolysPtr->PolyNormal.vx = ONE_FIXED;
3232 CollisionPolysPtr->PolyNormal.vy = 0;
3233 CollisionPolysPtr->PolyNormal.vz = 0;
3234 break;
3235 }
3236 case 3: /* all points are on min z face */
3237 {
3238 CollisionPolysPtr->PolyNormal.vx = 0;
3239 CollisionPolysPtr->PolyNormal.vy = 0;
3240 CollisionPolysPtr->PolyNormal.vz = -ONE_FIXED;
3241 break;
3242 }
3243 case 2: /* all points are on min x face */
3244 {
3245 CollisionPolysPtr->PolyNormal.vx = -ONE_FIXED;
3246 CollisionPolysPtr->PolyNormal.vy = 0;
3247 CollisionPolysPtr->PolyNormal.vz = 0;
3248 break;
3249 }
3250 case 1: /* all points are on min y face */
3251 {
3252 CollisionPolysPtr->PolyNormal.vx = 0;
3253 CollisionPolysPtr->PolyNormal.vy = -ONE_FIXED;
3254 CollisionPolysPtr->PolyNormal.vz = 0;
3255 break;
3256 }
3257 }
3258 }
3259 CollisionPolysPtr++;
3260 NumberOfCollisionPolys++;
3261
3262 /* ran out of space? */
3263 LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
3264 }
3265 }
3266 while(--face);
3267
3268 }
3269 return;
3270 }
3271
3272
IsPolygonWithinDynamicBoundingBox(const struct ColPolyTag * polyPtr)3273 static int IsPolygonWithinDynamicBoundingBox(const struct ColPolyTag *polyPtr)
3274 {
3275 VECTORCH *vertices = polyPtr->PolyPoint;
3276
3277 if (polyPtr->NumberOfVertices==4)
3278 {
3279 if (vertices[0].vy < DBBMinY)
3280 if (vertices[1].vy < DBBMinY)
3281 if (vertices[2].vy < DBBMinY)
3282 if (vertices[3].vy < DBBMinY)
3283 return 0;
3284
3285 if (vertices[0].vx < DBBMinX)
3286 if (vertices[1].vx < DBBMinX)
3287 if (vertices[2].vx < DBBMinX)
3288 if (vertices[3].vx < DBBMinX)
3289 return 0;
3290
3291 if (vertices[0].vx > DBBMaxX)
3292 if (vertices[1].vx > DBBMaxX)
3293 if (vertices[2].vx > DBBMaxX)
3294 if (vertices[3].vx > DBBMaxX)
3295 return 0;
3296
3297 if (vertices[0].vz < DBBMinZ)
3298 if (vertices[1].vz < DBBMinZ)
3299 if (vertices[2].vz < DBBMinZ)
3300 if (vertices[3].vz < DBBMinZ)
3301 return 0;
3302
3303 if (vertices[0].vz > DBBMaxZ)
3304 if (vertices[1].vz > DBBMaxZ)
3305 if (vertices[2].vz > DBBMaxZ)
3306 if (vertices[3].vz > DBBMaxZ)
3307 return 0;
3308
3309 if (vertices[0].vy > DBBMaxY)
3310 if (vertices[1].vy > DBBMaxY)
3311 if (vertices[2].vy > DBBMaxY)
3312 if (vertices[3].vy > DBBMaxY)
3313 return 0;
3314
3315 }
3316 else
3317 {
3318 if (vertices[0].vy < DBBMinY)
3319 if (vertices[1].vy < DBBMinY)
3320 if (vertices[2].vy < DBBMinY)
3321 return 0;
3322
3323 if (vertices[0].vx < DBBMinX)
3324 if (vertices[1].vx < DBBMinX)
3325 if (vertices[2].vx < DBBMinX)
3326 return 0;
3327
3328 if (vertices[0].vx > DBBMaxX)
3329 if (vertices[1].vx > DBBMaxX)
3330 if (vertices[2].vx > DBBMaxX)
3331 return 0;
3332
3333 if (vertices[0].vz < DBBMinZ)
3334 if (vertices[1].vz < DBBMinZ)
3335 if (vertices[2].vz < DBBMinZ)
3336 return 0;
3337
3338 if (vertices[0].vz > DBBMaxZ)
3339 if (vertices[1].vz > DBBMaxZ)
3340 if (vertices[2].vz > DBBMaxZ)
3341 return 0;
3342
3343 if (vertices[0].vy > DBBMaxY)
3344 if (vertices[1].vy > DBBMaxY)
3345 if (vertices[2].vy > DBBMaxY)
3346 return 0;
3347
3348 }
3349
3350
3351 return 1;
3352 }
3353
IsPolygonWithinStaticBoundingBox(const struct ColPolyTag * polyPtr)3354 static int IsPolygonWithinStaticBoundingBox(const struct ColPolyTag *polyPtr)
3355 {
3356 VECTORCH *vertices = polyPtr->PolyPoint;
3357
3358 if (polyPtr->NumberOfVertices==4)
3359 {
3360 if (vertices[0].vy < SBBMinY)
3361 if (vertices[1].vy < SBBMinY)
3362 if (vertices[2].vy < SBBMinY)
3363 if (vertices[3].vy < SBBMinY)
3364 return 0;
3365
3366 if (vertices[0].vx < SBBMinX)
3367 if (vertices[1].vx < SBBMinX)
3368 if (vertices[2].vx < SBBMinX)
3369 if (vertices[3].vx < SBBMinX)
3370 return 0;
3371
3372 if (vertices[0].vx > SBBMaxX)
3373 if (vertices[1].vx > SBBMaxX)
3374 if (vertices[2].vx > SBBMaxX)
3375 if (vertices[3].vx > SBBMaxX)
3376 return 0;
3377
3378 if (vertices[0].vz < SBBMinZ)
3379 if (vertices[1].vz < SBBMinZ)
3380 if (vertices[2].vz < SBBMinZ)
3381 if (vertices[3].vz < SBBMinZ)
3382 return 0;
3383
3384 if (vertices[0].vz > SBBMaxZ)
3385 if (vertices[1].vz > SBBMaxZ)
3386 if (vertices[2].vz > SBBMaxZ)
3387 if (vertices[3].vz > SBBMaxZ)
3388 return 0;
3389
3390 if (vertices[0].vy > SBBMaxY)
3391 if (vertices[1].vy > SBBMaxY)
3392 if (vertices[2].vy > SBBMaxY)
3393 if (vertices[3].vy > SBBMaxY)
3394 return 0;
3395
3396 }
3397 else
3398 {
3399 if (vertices[0].vy < SBBMinY)
3400 if (vertices[1].vy < SBBMinY)
3401 if (vertices[2].vy < SBBMinY)
3402 return 0;
3403
3404 if (vertices[0].vx < SBBMinX)
3405 if (vertices[1].vx < SBBMinX)
3406 if (vertices[2].vx < SBBMinX)
3407 return 0;
3408
3409 if (vertices[0].vx > SBBMaxX)
3410 if (vertices[1].vx > SBBMaxX)
3411 if (vertices[2].vx > SBBMaxX)
3412 return 0;
3413
3414 if (vertices[0].vz < SBBMinZ)
3415 if (vertices[1].vz < SBBMinZ)
3416 if (vertices[2].vz < SBBMinZ)
3417 return 0;
3418
3419 if (vertices[0].vz > SBBMaxZ)
3420 if (vertices[1].vz > SBBMaxZ)
3421 if (vertices[2].vz > SBBMaxZ)
3422 return 0;
3423
3424 if (vertices[0].vy > SBBMaxY)
3425 if (vertices[1].vy > SBBMaxY)
3426 if (vertices[2].vy > SBBMaxY)
3427 return 0;
3428
3429 }
3430
3431
3432 return 1;
3433 }
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444 /*KJL****************************************************************************
3445 * A function which takes a plane's normal and decides which axis to ignore when *
3446 * projecting points on the plane into a 2D space. *
3447 ****************************************************************************KJL*/
AxisToIgnore(VECTORCH * normal)3448 static int AxisToIgnore(VECTORCH *normal)
3449 {
3450 VECTORCH absNormal = *normal;
3451 if (absNormal.vx<0) absNormal.vx=-absNormal.vx;
3452 if (absNormal.vy<0) absNormal.vy=-absNormal.vy;
3453 if (absNormal.vz<0) absNormal.vz=-absNormal.vz;
3454
3455 if (absNormal.vx > absNormal.vy)
3456 {
3457 if (absNormal.vx > absNormal.vz)
3458 {
3459 return ix;
3460 }
3461 else
3462 {
3463 return iz;
3464 }
3465 }
3466 else
3467 {
3468 if (absNormal.vy > absNormal.vz)
3469 {
3470 return iy;
3471 }
3472 else
3473 {
3474 return iz;
3475 }
3476 }
3477 }
3478
3479 #if 0
3480 static void TestForValidMovement(STRATEGYBLOCK *sbPtr)
3481 {
3482 #if 1
3483 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
3484
3485 /* I'm a platform lift - leave me alone */
3486 if(dynPtr->OnlyCollideWithObjects)
3487 return;
3488
3489 if(RelocationIsValid(sbPtr))
3490 {
3491 /* movement ok */
3492 }
3493 else
3494 {
3495 /* cancel movement */
3496 //PrintDebuggingText("Relocate!");
3497 dynPtr->Position=dynPtr->PrevPosition;
3498 dynPtr->LinVelocity.vx = 0;
3499 dynPtr->LinVelocity.vy = 0;
3500 dynPtr->LinVelocity.vz = 0;
3501 }
3502 #endif
3503 }
3504 #endif
3505
RelocateSphere(STRATEGYBLOCK * sbPtr)3506 static int RelocateSphere(STRATEGYBLOCK *sbPtr)
3507 {
3508 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
3509 VECTORCH objectPosition = dynPtr->Position;
3510 VECTORCH objectVertices[8];
3511
3512 int polysLeft;
3513 struct ColPolyTag *polyPtr;
3514
3515 polysLeft = NumberOfCollisionPolys;
3516 polyPtr = CollisionPolysArray;
3517
3518 {
3519 int vertexNum=8;
3520 do
3521 {
3522 vertexNum--;
3523 objectVertices[vertexNum] = dynPtr->ObjectVertices[vertexNum];
3524 }
3525 while(vertexNum);
3526 }
3527
3528 /* first pass relocate */
3529 while(polysLeft)
3530 {
3531 VECTORCH planeNormal = polyPtr->PolyNormal;
3532 VECTORCH pointOnPlane = polyPtr->PolyPoint[0];
3533 int distance;
3534
3535 {
3536 VECTORCH planeToObject;
3537
3538 planeToObject.vx = objectPosition.vx - pointOnPlane.vx;
3539 planeToObject.vy = objectPosition.vy - pointOnPlane.vy;
3540 planeToObject.vz = objectPosition.vz - pointOnPlane.vz;
3541
3542 distance = dynPtr->CollisionRadius - Dot(&planeToObject,&planeNormal);
3543 }
3544
3545 if (distance>0 && DoesPolygonIntersectNRBB(polyPtr,objectVertices))
3546 {
3547 VECTORCH displacement;
3548
3549 displacement.vx = MUL_FIXED(planeNormal.vx,distance+RELOCATION_GRANULARITY);
3550 displacement.vy = MUL_FIXED(planeNormal.vy,distance+RELOCATION_GRANULARITY);
3551 displacement.vz = MUL_FIXED(planeNormal.vz,distance+RELOCATION_GRANULARITY);
3552
3553 AddVectorToVector(displacement,objectPosition);
3554 {
3555 int vertexNum=8;
3556 VECTORCH *vertexPtr = objectVertices;
3557
3558 do
3559 {
3560 vertexPtr->vx += displacement.vx;
3561 vertexPtr->vy += displacement.vy;
3562 vertexPtr->vz += displacement.vz;
3563 vertexPtr++;
3564 }
3565 while(--vertexNum);
3566 }
3567
3568 }
3569
3570 polyPtr++;
3571 polysLeft--;
3572 }
3573
3574 /* did we move at all? */
3575 if ( (objectPosition.vx == dynPtr->Position.vx)
3576 &&(objectPosition.vy == dynPtr->Position.vy)
3577 &&(objectPosition.vz == dynPtr->Position.vz) )
3578 return 1;
3579
3580 /* pass test if okay */
3581 polysLeft = NumberOfCollisionPolys;
3582 polyPtr = CollisionPolysArray;
3583
3584 {
3585 int stillIntersectingSomething = 0;
3586 while(polysLeft)
3587 {
3588 {
3589 VECTORCH planeNormal = polyPtr->PolyNormal;
3590 VECTORCH pointOnPlane = polyPtr->PolyPoint[0];
3591 int distance;
3592
3593 {
3594 VECTORCH planeToObject;
3595
3596 planeToObject.vx = objectPosition.vx - pointOnPlane.vx;
3597 planeToObject.vy = objectPosition.vy - pointOnPlane.vy;
3598 planeToObject.vz = objectPosition.vz - pointOnPlane.vz;
3599
3600 distance = dynPtr->CollisionRadius - Dot(&planeToObject,&planeNormal);
3601 }
3602
3603 if (distance>0 && DoesPolygonIntersectNRBB(polyPtr,objectVertices))
3604 {
3605 stillIntersectingSomething = 1;
3606 }
3607 }
3608 polyPtr++;
3609 polysLeft--;
3610 }
3611
3612 if (stillIntersectingSomething)
3613 {
3614 return 0;
3615 }
3616 else
3617 {
3618 int vertexNum=8;
3619 do
3620 {
3621 vertexNum--;
3622 dynPtr->ObjectVertices[vertexNum] = objectVertices[vertexNum];
3623 }
3624 while(vertexNum);
3625 dynPtr->Position = objectPosition;
3626 return 1;
3627 }
3628 }
3629 }
3630
RelocateNRBB(STRATEGYBLOCK * sbPtr)3631 static int RelocateNRBB(STRATEGYBLOCK *sbPtr)
3632 {
3633 int noProblems = 1;
3634 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
3635 VECTORCH objectPosition = dynPtr->Position;
3636 VECTORCH objectVertices[8];
3637 int polysLeft;
3638 struct ColPolyTag *polyPtr;
3639
3640 polysLeft = NumberOfCollisionPolys;
3641 polyPtr = CollisionPolysArray;
3642
3643 {
3644 int vertexNum=8;
3645 do
3646 {
3647 vertexNum--;
3648 objectVertices[vertexNum] = dynPtr->ObjectVertices[vertexNum];
3649 }
3650 while(vertexNum);
3651 }
3652
3653 while(polysLeft)
3654 {
3655 VECTORCH planeNormal = polyPtr->PolyNormal;
3656 VECTORCH pointOnPlane = polyPtr->PolyPoint[0];
3657
3658 {
3659 VECTORCH planeToObject;
3660
3661 planeToObject.vx = objectPosition.vx - pointOnPlane.vx;
3662 planeToObject.vy = objectPosition.vy - pointOnPlane.vy;
3663 planeToObject.vz = objectPosition.vz - pointOnPlane.vz;
3664
3665 if (DotProduct(&planeToObject,&planeNormal) < 0)
3666 {
3667 polyPtr++;
3668 polysLeft--;
3669 continue;
3670 }
3671 }
3672 {
3673 int greatestDistance;
3674
3675 {
3676 VECTORCH vertex = objectVertices[WhichNRBBVertex(dynPtr,&planeNormal)];
3677 vertex.vx -= pointOnPlane.vx;
3678 vertex.vy -= pointOnPlane.vy;
3679 vertex.vz -= pointOnPlane.vz;
3680 greatestDistance = -DotProduct(&vertex,&planeNormal);
3681 }
3682
3683 if ((greatestDistance>0) && DoesPolygonIntersectNRBB(polyPtr,objectVertices))
3684 {
3685 #if 0
3686 VECTORCH displacement;
3687
3688 displacement.vx = MUL_FIXED(planeNormal.vx,greatestDistance+RELOCATION_GRANULARITY);
3689 displacement.vy = MUL_FIXED(planeNormal.vy,greatestDistance+RELOCATION_GRANULARITY);
3690 displacement.vz = MUL_FIXED(planeNormal.vz,greatestDistance+RELOCATION_GRANULARITY);
3691
3692 AddVectorToVector(displacement,objectPosition);
3693 {
3694 int vertexNum=8;
3695 VECTORCH *vertexPtr = objectVertices;
3696
3697 do
3698 {
3699 vertexPtr->vx += displacement.vx;
3700 vertexPtr->vy += displacement.vy;
3701 vertexPtr->vz += displacement.vz;
3702 vertexPtr++;
3703 }
3704 while(--vertexNum);
3705 }
3706 #endif
3707 /* create a report about the collision */
3708 {
3709 COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
3710
3711 if (reportPtr)
3712 {
3713 reportPtr->ObstacleSBPtr = 0;//obstacleSBPtr;
3714 reportPtr->ObstacleNormal = planeNormal;
3715
3716 reportPtr->ObstaclePoint = pointOnPlane;
3717 // reportPtr->ObstaclePoint.vx = 0x7fffffff;
3718 // reportPtr->ObstaclePoint.vy = 0x7fffffff;
3719 // reportPtr->ObstaclePoint.vz = 0x7fffffff;
3720 }
3721 }
3722 noProblems = 0;
3723
3724 }
3725 }
3726 polyPtr++;
3727 polysLeft--;
3728 }
3729 #if 0
3730 /* did we move at all? */
3731 if ( (objectPosition.vx == dynPtr->Position.vx)
3732 &&(objectPosition.vy == dynPtr->Position.vy)
3733 &&(objectPosition.vz == dynPtr->Position.vz) )
3734 return noProblems;
3735
3736
3737 /* pass test if okay */
3738 polysLeft = NumberOfCollisionPolys;
3739 polyPtr = CollisionPolysArray;
3740
3741 {
3742 while(polysLeft)
3743 {
3744 if(DoesPolygonIntersectNRBB(polyPtr,objectVertices))
3745 {
3746 VECTORCH planeNormal = polyPtr->PolyNormal;
3747 VECTORCH pointOnPlane = polyPtr->PolyPoint[0];
3748 int greatestDistance;
3749
3750 {
3751 VECTORCH vertex = objectVertices[WhichNRBBVertex(dynPtr,&planeNormal)];
3752 vertex.vx -= pointOnPlane.vx;
3753 vertex.vy -= pointOnPlane.vy;
3754 vertex.vz -= pointOnPlane.vz;
3755 greatestDistance = -DotProduct(&vertex,&planeNormal);
3756 }
3757
3758 if (greatestDistance>0)
3759 {
3760 /* still intersecting something */
3761 return noProblems;
3762 }
3763 }
3764 polyPtr++;
3765 polysLeft--;
3766 }
3767
3768 {
3769 int vertexNum=8;
3770 do
3771 {
3772 vertexNum--;
3773 dynPtr->ObjectVertices[vertexNum] = objectVertices[vertexNum];
3774 }
3775 while(vertexNum);
3776 dynPtr->Position = objectPosition;
3777 return 1;
3778 }
3779 }
3780 #endif
3781 if (!noProblems) PrintDebuggingText("RECOMMEND RELOCATE\n");
3782 return noProblems;
3783 }
3784
3785
DoesPolygonIntersectNRBB(struct ColPolyTag * polyPtr,VECTORCH * objectVertices)3786 static int DoesPolygonIntersectNRBB(struct ColPolyTag *polyPtr,VECTORCH *objectVertices)
3787 {
3788 VECTORCH *minVertexPtr = &objectVertices[7];
3789 VECTORCH *vertices = polyPtr->PolyPoint;
3790
3791 /* trivial rejection tests */
3792 if (polyPtr->NumberOfVertices==4)
3793 {
3794 if (vertices[0].vx < minVertexPtr->vx)
3795 if (vertices[1].vx < minVertexPtr->vx)
3796 if (vertices[2].vx < minVertexPtr->vx)
3797 if (vertices[3].vx < minVertexPtr->vx)
3798 return 0;
3799
3800 if (vertices[0].vz < minVertexPtr->vz)
3801 if (vertices[1].vz < minVertexPtr->vz)
3802 if (vertices[2].vz < minVertexPtr->vz)
3803 if (vertices[3].vz < minVertexPtr->vz)
3804 return 0;
3805
3806 if (vertices[0].vy < minVertexPtr->vy)
3807 if (vertices[1].vy < minVertexPtr->vy)
3808 if (vertices[2].vy < minVertexPtr->vy)
3809 if (vertices[3].vy < minVertexPtr->vy)
3810 return 0;
3811
3812
3813 if (vertices[0].vx > objectVertices->vx)
3814 if (vertices[1].vx > objectVertices->vx)
3815 if (vertices[2].vx > objectVertices->vx)
3816 if (vertices[3].vx > objectVertices->vx)
3817 return 0;
3818
3819 if (vertices[0].vz > objectVertices->vz)
3820 if (vertices[1].vz > objectVertices->vz)
3821 if (vertices[2].vz > objectVertices->vz)
3822 if (vertices[3].vz > objectVertices->vz)
3823 return 0;
3824
3825 if (vertices[0].vy > objectVertices->vy)
3826 if (vertices[1].vy > objectVertices->vy)
3827 if (vertices[2].vy > objectVertices->vy)
3828 if (vertices[3].vy > objectVertices->vy)
3829 return 0;
3830
3831 }
3832 else
3833 {
3834 if (vertices[0].vx < minVertexPtr->vx)
3835 if (vertices[1].vx < minVertexPtr->vx)
3836 if (vertices[2].vx < minVertexPtr->vx)
3837 return 0;
3838
3839 if (vertices[0].vz < minVertexPtr->vz)
3840 if (vertices[1].vz < minVertexPtr->vz)
3841 if (vertices[2].vz < minVertexPtr->vz)
3842 return 0;
3843
3844 if (vertices[0].vy < minVertexPtr->vy)
3845 if (vertices[1].vy < minVertexPtr->vy)
3846 if (vertices[2].vy < minVertexPtr->vy)
3847 return 0;
3848
3849
3850 if (vertices[0].vx > objectVertices->vx)
3851 if (vertices[1].vx > objectVertices->vx)
3852 if (vertices[2].vx > objectVertices->vx)
3853 return 0;
3854
3855 if (vertices[0].vz > objectVertices->vz)
3856 if (vertices[1].vz > objectVertices->vz)
3857 if (vertices[2].vz > objectVertices->vz)
3858 return 0;
3859
3860 if (vertices[0].vy > objectVertices->vy)
3861 if (vertices[1].vy > objectVertices->vy)
3862 if (vertices[2].vy > objectVertices->vy)
3863 return 0;
3864 }
3865
3866 /* are any of the poly's vertices inside the object's bounding box? */
3867 {
3868 if (vertices[0].vy >= minVertexPtr->vy)
3869 if (vertices[0].vy <= objectVertices->vy)
3870 if (vertices[0].vx >= minVertexPtr->vx)
3871 if (vertices[0].vx <= objectVertices->vx)
3872 if (vertices[0].vz >= minVertexPtr->vz)
3873 if (vertices[0].vz <= objectVertices->vz)
3874 return 1;
3875 if (vertices[1].vy >= minVertexPtr->vy)
3876 if (vertices[1].vy <= objectVertices->vy)
3877 if (vertices[1].vx >= minVertexPtr->vx)
3878 if (vertices[1].vx <= objectVertices->vx)
3879 if (vertices[1].vz >= minVertexPtr->vz)
3880 if (vertices[1].vz <= objectVertices->vz)
3881 return 1;
3882 if (vertices[2].vy >= minVertexPtr->vy)
3883 if (vertices[2].vy <= objectVertices->vy)
3884 if (vertices[2].vx >= minVertexPtr->vx)
3885 if (vertices[2].vx <= objectVertices->vx)
3886 if (vertices[2].vz >= minVertexPtr->vz)
3887 if (vertices[2].vz <= objectVertices->vz)
3888 return 1;
3889 }
3890 if (polyPtr->NumberOfVertices==4)
3891 {
3892 if (vertices[3].vy >= minVertexPtr->vy)
3893 if (vertices[3].vy <= objectVertices->vy)
3894 if (vertices[3].vx >= minVertexPtr->vx)
3895 if (vertices[3].vx <= objectVertices->vx)
3896 if (vertices[3].vz >= minVertexPtr->vz)
3897 if (vertices[3].vz <= objectVertices->vz)
3898 return 1;
3899 }
3900
3901 /* okay, it's not that simple then. Let's see if any of the poly's edges
3902 intersect the objects bounding box */
3903 {
3904 int vertexA = polyPtr->NumberOfVertices;
3905 do
3906 {
3907 VECTORCH alpha,beta;
3908 int vertexB;
3909 vertexA--;
3910 vertexB = (vertexA+1)%(polyPtr->NumberOfVertices);
3911
3912 alpha = vertices[vertexA];
3913 beta.vx = vertices[vertexB].vx - alpha.vx;
3914 beta.vy = vertices[vertexB].vy - alpha.vy;
3915 beta.vz = vertices[vertexB].vz - alpha.vz;
3916
3917 /* edge is the line segment 'alpha + lambda*beta' where lambda is between 0 and 1 */
3918 if (beta.vy!=0)
3919 {
3920 {
3921 /* box edge 1: y=minVertexPtr->vy; normal is (0,-1,0) */
3922 int lambda;
3923
3924 f2i(lambda,(float)(minVertexPtr->vy - alpha.vy)/(float)beta.vy*65536.0f);
3925
3926 /* eliminate the divides? */
3927 if (lambda>=0 && lambda <= 65536)
3928 {
3929 int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
3930 if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
3931 {
3932 int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
3933 if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
3934 return 1;
3935 }
3936 }
3937 }
3938 {
3939 /* box edge 2: y=objectVertices->vy; normal is (0,1,0) */
3940 int lambda;// = DIV_FIXED(objectVertices->vy - (alpha.vy),(beta.vy) );
3941 f2i(lambda,(float)(objectVertices->vy - alpha.vy)/(float)beta.vy*65536.0f);
3942 /* eliminate the divides? */
3943 if (lambda>=0 && lambda <= 65536)
3944 {
3945 int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
3946 if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
3947 {
3948 int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
3949 if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
3950 return 1;
3951 }
3952 }
3953 }
3954 }
3955 if (beta.vx!=0)
3956 {
3957 {
3958 /* box edge 3: x=minVertexPtr->vx; normal is (-1,0,0) */
3959 int lambda;// = DIV_FIXED(minVertexPtr->vx - (alpha.vx),(beta.vx) );
3960 f2i(lambda,(float)(minVertexPtr->vx - alpha.vx)/(float)beta.vx*65536.0f);
3961 /* eliminate the divides? */
3962 if (lambda>=0 && lambda <= 65536)
3963 {
3964 int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
3965 if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
3966 {
3967 int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
3968 if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
3969 return 1;
3970 }
3971 }
3972 }
3973 {
3974 /* box edge 4: x=objectVertices->vx; normal is (1,0,0) */
3975 int lambda;// = DIV_FIXED(objectVertices->vx - (alpha.vx),(beta.vx) );
3976 f2i(lambda,(float)(objectVertices->vx - alpha.vx)/(float)beta.vx*65536.0f);
3977 /* eliminate the divides? */
3978 if (lambda>=0 && lambda <= 65536)
3979 {
3980 int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
3981 if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
3982 {
3983 int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
3984 if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
3985 return 1;
3986 }
3987 }
3988 }
3989 }
3990 if (beta.vz!=0)
3991 {
3992 {
3993 /* box edge 5: z=minVertexPtr->vz; normal is (0,0,-1) */
3994 int lambda;// = DIV_FIXED(minVertexPtr->vz - (alpha.vz),(beta.vz));
3995 f2i(lambda,(float)(minVertexPtr->vz - alpha.vz)/(float)beta.vz*65536.0f);
3996 /* eliminate the divides? */
3997 if (lambda>=0 && lambda <= 65536)
3998 {
3999 int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
4000 if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
4001 {
4002 int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
4003 if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
4004 return 1;
4005 }
4006 }
4007 }
4008 {
4009 /* box edge 6: z=objectVertices->vz; normal is (0,0,1) */
4010 int lambda;// = DIV_FIXED(objectVertices->vz - (alpha.vz),(beta.vz));
4011 f2i(lambda,(float)(objectVertices->vz - alpha.vz)/(float)beta.vz*65536.0f);
4012 /* eliminate the divides? */
4013 if (lambda>=0 && lambda <= 65536)
4014 {
4015 int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
4016 if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
4017 {
4018 int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
4019 if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
4020 return 1;
4021 }
4022 }
4023 }
4024 }
4025
4026 }
4027 while(vertexA);
4028 }
4029 /* Still here? Damn. Okay, we'll have to check to see if a cuboid's diagonal intersect the polygon */
4030 {
4031 VECTORCH alpha,beta;
4032 int dottedNormals;
4033 int lambda;
4034
4035 if ((polyPtr->PolyNormal).vx > 0)
4036 {
4037 alpha.vx = minVertexPtr->vx;
4038 beta.vx = objectVertices->vx - alpha.vx;
4039 }
4040 else
4041 {
4042 alpha.vx = objectVertices->vx;
4043 beta.vx = minVertexPtr->vx - alpha.vx;
4044 }
4045
4046 if ((polyPtr->PolyNormal).vy > 0)
4047 {
4048 alpha.vy = minVertexPtr->vy;
4049 beta.vy = objectVertices->vy - alpha.vy;
4050 }
4051 else
4052 {
4053 alpha.vy = objectVertices->vy;
4054 beta.vy = minVertexPtr->vy - alpha.vy;
4055 }
4056
4057 if ((polyPtr->PolyNormal).vz > 0)
4058 {
4059 alpha.vz = minVertexPtr->vz;
4060 beta.vz = objectVertices->vz - alpha.vz;
4061 }
4062 else
4063 {
4064 alpha.vz = objectVertices->vz;
4065 beta.vz = minVertexPtr->vz - alpha.vz;
4066 }
4067
4068 dottedNormals = DotProduct(&(polyPtr->PolyNormal),&beta);
4069 #if 1//debug
4070 if (!dottedNormals)
4071 {
4072 #if 0
4073 char buffer[200];
4074 sprintf(buffer,"POLY NORMAL IS %d %d %d\n",(polyPtr->PolyNormal).vx,(polyPtr->PolyNormal).vy,(polyPtr->PolyNormal).vz);
4075 NewOnScreenMessage(buffer);
4076 sprintf(buffer,"POLY NO OF VERTICES %d\n",(polyPtr->NumberOfVertices));
4077 NewOnScreenMessage(buffer);
4078 sprintf(buffer,"POLY POINT IS %d %d %d\n",(polyPtr->PolyPoint[0]).vx,(polyPtr->PolyPoint[0]).vy,(polyPtr->PolyPoint[0]).vz);
4079 NewOnScreenMessage(buffer);
4080 #endif
4081 LOGDXFMT(( "POLY NORMAL IS %d %d %d\n",(polyPtr->PolyNormal).vx,(polyPtr->PolyNormal).vy,(polyPtr->PolyNormal).vz));
4082 LOGDXFMT(( "POLY NO OF VERTICES %d\n",polyPtr->NumberOfVertices));
4083 LOGDXFMT(( "POLY POINT IS %d %d %d\n",(polyPtr->PolyPoint[0]).vx,(polyPtr->PolyPoint[0]).vy,(polyPtr->PolyPoint[0]).vz ));
4084 LOCALASSERT("Found normal which may be incorrect"==0);
4085 return 0;
4086 }
4087 #endif
4088 {
4089 VECTORCH cornerToPlane;
4090 cornerToPlane.vx = vertices[0].vx - alpha.vx;
4091 cornerToPlane.vy = vertices[0].vy - alpha.vy;
4092 cornerToPlane.vz = vertices[0].vz - alpha.vz;
4093 lambda = DIV_FIXED
4094 (
4095 DotProduct(&(polyPtr->PolyNormal),&cornerToPlane),
4096 dottedNormals
4097 );
4098 }
4099
4100 if (lambda >= 0 && lambda <= 65536)
4101 {
4102 int axis1,axis2;
4103 /* decide which 2d plane to project onto */
4104 {
4105 VECTORCH absNormal = (polyPtr->PolyNormal);
4106 if (absNormal.vx<0) absNormal.vx=-absNormal.vx;
4107 if (absNormal.vy<0) absNormal.vy=-absNormal.vy;
4108 if (absNormal.vz<0) absNormal.vz=-absNormal.vz;
4109
4110 if (absNormal.vx > absNormal.vy)
4111 {
4112 if (absNormal.vx > absNormal.vz)
4113 {
4114 axis1=iy;
4115 axis2=iz;
4116 }
4117 else
4118 {
4119 axis1=ix;
4120 axis2=iy;
4121 }
4122 }
4123 else
4124 {
4125 if (absNormal.vy > absNormal.vz)
4126 {
4127 axis1=ix;
4128 axis2=iz;
4129 }
4130 else
4131 {
4132 axis1=ix;
4133 axis2=iy;
4134 }
4135 }
4136 }
4137
4138
4139 {
4140 int projectedPolyVertex[20];
4141 int projectedPointOnPlane[2];
4142
4143 projectedPointOnPlane[0]=*((int*)&alpha+axis1) + MUL_FIXED(lambda,*((int*)&beta+axis1));
4144 projectedPointOnPlane[1]=*((int*)&alpha+axis2) + MUL_FIXED(lambda,*((int*)&beta+axis2));
4145
4146 {
4147 VECTORCH *vertexPtr = &vertices[0];
4148 int *projectedVertexPtr= &projectedPolyVertex[0];
4149 int noOfVertices = polyPtr->NumberOfVertices;
4150
4151 do
4152 {
4153 *projectedVertexPtr++ = *((int*)vertexPtr + axis1);
4154 *projectedVertexPtr++ = *((int*)vertexPtr + axis2);
4155
4156 vertexPtr++;
4157 }
4158 while(--noOfVertices);
4159
4160 }
4161
4162
4163 if (PointInPolygon(&projectedPointOnPlane[0],&projectedPolyVertex[0],polyPtr->NumberOfVertices,2))
4164 return 1;
4165 }
4166 }
4167 }
4168 /* after all that we can be sure that the polygon isn't intersecting the object */
4169 return 0;
4170 }
4171
4172
WhichNRBBVertex(DYNAMICSBLOCK * dynPtr,VECTORCH * normalPtr)4173 static int WhichNRBBVertex(DYNAMICSBLOCK *dynPtr, VECTORCH *normalPtr)
4174 {
4175 VECTORCH dir;
4176
4177 dir.vx = -normalPtr->vx;
4178 dir.vy = -normalPtr->vy;
4179 dir.vz = -normalPtr->vz;
4180
4181 if (dir.vx>=0)
4182 {
4183 if (dir.vy>=0)
4184 {
4185 if (dir.vz>=0)
4186 {
4187 /* +ve x +ve y +ve z */
4188 return 0;
4189 }
4190 else
4191 {
4192 /* +ve x +ve y -ve z */
4193 return 1;
4194 }
4195 }
4196 else
4197 {
4198 if (dir.vz>=0)
4199 {
4200 /* +ve x -ve y +ve z */
4201 return 2;
4202 }
4203 else
4204 {
4205 /* +ve x -ve y -ve z */
4206 return 3;
4207 }
4208 }
4209 }
4210 else
4211 {
4212 if (dir.vy>=0)
4213 {
4214 if (dir.vz>=0)
4215 {
4216 /* -ve x +ve y +ve z */
4217 return 4;
4218 }
4219 else
4220 {
4221 /* -ve x +ve y -ve z */
4222 return 5;
4223 }
4224 }
4225 else
4226 {
4227 if (dir.vz>=0)
4228 {
4229 /* -ve x -ve y +ve z */
4230 return 6;
4231 }
4232 else
4233 {
4234 /* -ve x -ve y -ve z */
4235 return 7;
4236 }
4237 }
4238 }
4239 }
4240
4241
4242
4243
4244
4245
4246
DistanceMovedBeforeSphereHitsPolygon(DYNAMICSBLOCK * dynPtr,struct ColPolyTag * polyPtr,int distanceToMove)4247 static signed int DistanceMovedBeforeSphereHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4248 {
4249 int dottedNormals;
4250 int sphereToPolyDist;
4251
4252 LOCALASSERT(polyPtr);
4253
4254 dottedNormals = -DotProduct(&DirectionOfTravel,&(polyPtr->PolyNormal));
4255
4256 /* reject if polygon does not face against direction of sphere's travel */
4257 if (dottedNormals<=0)
4258 {
4259 return -1;
4260 }
4261
4262 /* calculate distance each vertex is from poly's plane along direction of motion */
4263 {
4264 VECTORCH sphereToPoly;
4265
4266 sphereToPoly.vx = dynPtr->Position.vx - polyPtr->PolyPoint[0].vx;
4267 sphereToPoly.vy = dynPtr->Position.vy - polyPtr->PolyPoint[0].vy;
4268 sphereToPoly.vz = dynPtr->Position.vz - polyPtr->PolyPoint[0].vz;
4269
4270 sphereToPolyDist = DotProduct(&sphereToPoly,&(polyPtr->PolyNormal))-dynPtr->CollisionRadius;
4271 }
4272 /* reject if polygon is 'behind' sphere */
4273 if (sphereToPolyDist<0)
4274 {
4275 #if 0
4276 if (sphereToPolyDist>-dynPtr->CollisionRadius)
4277 {
4278 VECTORCH projectedPosition;
4279
4280 projectedPosition.vx = dynPtr->Position.vx + MUL_FIXED(sphereToPolyDist,polyPtr->PolyNormal.vx);
4281 projectedPosition.vy = dynPtr->Position.vy + MUL_FIXED(sphereToPolyDist,polyPtr->PolyNormal.vy);
4282 projectedPosition.vz = dynPtr->Position.vz + MUL_FIXED(sphereToPolyDist,polyPtr->PolyNormal.vz);
4283
4284 if (DoesSphereProjectOntoPoly(dynPtr, polyPtr, &projectedPosition))
4285 {
4286 textprint("RELOCATION CASE\n");
4287 }
4288 }
4289 #endif
4290 return -2;
4291 }
4292
4293 /* calculate distance along direction of travel */
4294
4295 sphereToPolyDist = DIV_FIXED(sphereToPolyDist,dottedNormals);
4296
4297 if (sphereToPolyDist>=distanceToMove)
4298 {
4299 return -4;
4300 }
4301
4302 /* test if sphere's projected path intersect polygon */
4303 {
4304 VECTORCH projectedPosition;
4305 projectedPosition.vx = dynPtr->Position.vx + MUL_FIXED(DirectionOfTravel.vx, sphereToPolyDist) - MUL_FIXED(dynPtr->CollisionRadius,polyPtr->PolyNormal.vx);
4306 projectedPosition.vy = dynPtr->Position.vy + MUL_FIXED(DirectionOfTravel.vy, sphereToPolyDist) - MUL_FIXED(dynPtr->CollisionRadius,polyPtr->PolyNormal.vy);
4307 projectedPosition.vz = dynPtr->Position.vz + MUL_FIXED(DirectionOfTravel.vz, sphereToPolyDist) - MUL_FIXED(dynPtr->CollisionRadius,polyPtr->PolyNormal.vz);
4308
4309
4310 if (SphereProjectOntoPoly(dynPtr, polyPtr, &projectedPosition))
4311 {
4312 return sphereToPolyDist;
4313 }
4314 }
4315 /* polygon not in way of sphere */
4316 return -5;
4317 }
4318
4319
SphereProjectOntoPoly(DYNAMICSBLOCK * dynPtr,struct ColPolyTag * polyPtr,VECTORCH * projectedPosition)4320 static int SphereProjectOntoPoly(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, VECTORCH *projectedPosition)
4321 {
4322 /* decide which 2d plane to project onto */
4323 int axisToIgnore = AxisToIgnore(&polyPtr->PolyNormal);
4324
4325 if (axisToIgnore!=ix)
4326 {
4327 int polyMax,polyMin;
4328
4329 /* search x-coords of poly vertices for min and max */
4330 {
4331 int vertexNum=polyPtr->NumberOfVertices;
4332
4333 polyMax = polyMin = polyPtr->PolyPoint[0].vx;
4334 do
4335 {
4336 int x;
4337 vertexNum--;
4338 x = polyPtr->PolyPoint[vertexNum].vx;
4339 if (x > polyMax) polyMax = x;
4340 else if (x < polyMin) polyMin = x;
4341 }
4342 while(vertexNum);
4343 }
4344
4345 /* test to see if object & polygon overlap */
4346 if (projectedPosition->vx+dynPtr->CollisionRadius < polyMin || projectedPosition->vx-dynPtr->CollisionRadius > polyMax)
4347 return 0;
4348 }
4349 if (axisToIgnore!=iz)
4350 {
4351 int polyMax,polyMin;
4352
4353 /* search z-coords of poly vertices for min and max */
4354 {
4355 int vertexNum=polyPtr->NumberOfVertices;
4356
4357 polyMax = polyMin = polyPtr->PolyPoint[0].vz;
4358 do
4359 {
4360 int z;
4361 vertexNum--;
4362 z = polyPtr->PolyPoint[vertexNum].vz;
4363 if (z > polyMax) polyMax = z;
4364 else if (z < polyMin) polyMin = z;
4365 }
4366 while(vertexNum);
4367 }
4368
4369 /* test to see if object & polygon overlap */
4370 if (projectedPosition->vz+dynPtr->CollisionRadius < polyMin || projectedPosition->vz-dynPtr->CollisionRadius > polyMax)
4371 return 0;
4372 }
4373 if (axisToIgnore!=iy)
4374 {
4375 int polyMax,polyMin;
4376
4377 /* search y-coords of poly vertices for min and max */
4378 {
4379 int vertexNum=polyPtr->NumberOfVertices;
4380
4381 polyMax = polyMin = polyPtr->PolyPoint[0].vy;
4382 do
4383 {
4384 int y;
4385 vertexNum--;
4386
4387 y = polyPtr->PolyPoint[vertexNum].vy;
4388 if (y > polyMax) polyMax = y;
4389 else if (y < polyMin) polyMin = y;
4390 }
4391 while(vertexNum);
4392 }
4393
4394 /* test to see if object & polygon overlap */
4395 if (projectedPosition->vy+dynPtr->CollisionRadius < polyMin || projectedPosition->vy-dynPtr->CollisionRadius > polyMax)
4396 return 0;
4397
4398 #if 1
4399 /* test for a 'step' in front of object */
4400 {
4401 int heightOfStep = projectedPosition->vy+dynPtr->CollisionRadius - polyMin; /* y-axis is +ve downwards, remember */
4402 if (heightOfStep < MAXIMUM_STEP_HEIGHT) /* we've hit a 'step' - move player upwards */
4403 {
4404 DistanceToStepUp=heightOfStep+COLLISION_GRANULARITY;
4405 LOCALASSERT(heightOfStep>0);
4406 }
4407 }
4408 #endif
4409 }
4410
4411
4412 return 1;
4413 }
4414
4415
DistanceMovedBeforeNRBBHitsPolygon(DYNAMICSBLOCK * dynPtr,struct ColPolyTag * polyPtr,int distanceToMove)4416 static signed int DistanceMovedBeforeNRBBHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4417 {
4418 VECTORCH polyNormal;
4419 int dottedNormals;
4420 int obstacleDistance= 0x7fffffff;
4421 int vertexToPlaneDist[8];
4422
4423 LOCALASSERT(polyPtr);
4424
4425 polyNormal = polyPtr->PolyNormal;
4426
4427 #if 0
4428 if (polyNormal.vy<=-65500)
4429 return DistanceMovedBeforeNRBBHitsNegYPolygon(dynPtr, polyPtr, distanceToMove);
4430 else if (polyNormal.vy>=65500)
4431 return DistanceMovedBeforeNRBBHitsPosYPolygon(dynPtr, polyPtr, distanceToMove);
4432 else if (polyNormal.vx>=65500)
4433 return DistanceMovedBeforeNRBBHitsPosXPolygon(dynPtr, polyPtr, distanceToMove);
4434 else if (polyNormal.vx<=-65500)
4435 return DistanceMovedBeforeNRBBHitsNegXPolygon(dynPtr, polyPtr, distanceToMove);
4436 else if (polyNormal.vz>=65500)
4437 return DistanceMovedBeforeNRBBHitsPosZPolygon(dynPtr, polyPtr, distanceToMove);
4438 else if (polyNormal.vz<=-65500)
4439 return DistanceMovedBeforeNRBBHitsNegZPolygon(dynPtr, polyPtr, distanceToMove);
4440 #endif
4441
4442 dottedNormals = -DotProduct(&DirectionOfTravel,&polyNormal);
4443 if (dottedNormals<=0) return -1; /* reject poly */
4444
4445 /* calculate distance each vertex is from poly's plane along direction of motion */
4446 {
4447 VECTORCH polyPoint = polyPtr->PolyPoint[0];
4448 int originToPlaneDist = DotProduct(&polyPoint,&polyNormal);
4449
4450 {
4451 int vertexNum=8;
4452 do
4453 {
4454 vertexNum--;
4455
4456 vertexToPlaneDist[vertexNum] =
4457 DotProduct(&dynPtr->ObjectVertices[vertexNum],&polyNormal) - originToPlaneDist;
4458
4459 if (vertexToPlaneDist[vertexNum] < 0) return -1;
4460 }
4461 while(vertexNum);
4462 }
4463
4464
4465 {
4466 int vertexNum=8;
4467 int *distancePtr = vertexToPlaneDist;
4468 do
4469 {
4470 *distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4471
4472 if(*distancePtr < obstacleDistance)
4473 obstacleDistance = *distancePtr;
4474
4475 distancePtr++;
4476 }
4477 while(--vertexNum);
4478
4479 }
4480 }
4481 if (obstacleDistance>=distanceToMove)
4482 return -2;
4483
4484 /* test if any vertices projected paths intersect polygons */
4485 if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4486 {
4487 return obstacleDistance;
4488 }
4489
4490 return -3;
4491 }
4492 #if 0
4493 static signed int DistanceMovedBeforeNRBBHitsNegYPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4494 {
4495 int dottedNormals;
4496 int obstacleDistance= 0x7fffffff;
4497 int vertexToPlaneDist[8];
4498
4499 LOCALASSERT(polyPtr);
4500
4501 dottedNormals = DirectionOfTravel.vy;
4502 if (dottedNormals<=0) return -1; /* reject poly */
4503
4504 /* calculate distance each vertex is from poly's plane along direction of motion */
4505 {
4506 int originToPlaneDist = -polyPtr->PolyPoint[0].vy;
4507
4508 {
4509 int vertexNum=8;
4510 do
4511 {
4512 vertexNum--;
4513
4514 vertexToPlaneDist[vertexNum] = -dynPtr->ObjectVertices[vertexNum].vy - originToPlaneDist;
4515
4516 if (vertexToPlaneDist[vertexNum] < 0)
4517 {
4518 return -1;
4519 }
4520 }
4521 while(vertexNum);
4522 }
4523
4524
4525 {
4526 int vertexNum=8;
4527 int *distancePtr = vertexToPlaneDist;
4528 do
4529 {
4530 *distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4531
4532 if(*distancePtr < obstacleDistance)
4533 obstacleDistance = *distancePtr;
4534
4535 distancePtr++;
4536 }
4537 while(--vertexNum);
4538
4539 }
4540 }
4541 if (obstacleDistance>=distanceToMove)
4542 return -2;
4543
4544 /* test if any vertices projected paths intersect polygons */
4545 if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4546 {
4547 return obstacleDistance;
4548 }
4549
4550 return -3;
4551 }
4552
4553 static signed int DistanceMovedBeforeNRBBHitsPosYPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4554 {
4555 int dottedNormals;
4556 int obstacleDistance= 0x7fffffff;
4557 int vertexToPlaneDist[8];
4558
4559 LOCALASSERT(polyPtr);
4560
4561 dottedNormals = -DirectionOfTravel.vy;
4562 if (dottedNormals<=0) return -1; /* reject poly */
4563
4564 /* calculate distance each vertex is from poly's plane along direction of motion */
4565 {
4566 int originToPlaneDist = polyPtr->PolyPoint[0].vy;
4567
4568 {
4569 int vertexNum=8;
4570 do
4571 {
4572 vertexNum--;
4573
4574 vertexToPlaneDist[vertexNum] = dynPtr->ObjectVertices[vertexNum].vy - originToPlaneDist;
4575
4576 if (vertexToPlaneDist[vertexNum] < 0)
4577 {
4578 return -1;
4579 }
4580 }
4581 while(vertexNum);
4582 }
4583
4584 {
4585 int vertexNum=8;
4586 int *distancePtr = vertexToPlaneDist;
4587 do
4588 {
4589 *distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4590
4591 if(*distancePtr < obstacleDistance)
4592 obstacleDistance = *distancePtr;
4593
4594 distancePtr++;
4595 }
4596 while(--vertexNum);
4597
4598 }
4599 }
4600 if (obstacleDistance>=distanceToMove)
4601 return -2;
4602
4603 /* test if any vertices projected paths intersect polygons */
4604 if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4605 {
4606 return obstacleDistance;
4607 }
4608
4609 return -3;
4610 }
4611 static signed int DistanceMovedBeforeNRBBHitsPosXPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4612 {
4613 int dottedNormals;
4614 int obstacleDistance= 0x7fffffff;
4615 int vertexToPlaneDist[8];
4616
4617 LOCALASSERT(polyPtr);
4618
4619 dottedNormals = -DirectionOfTravel.vx;
4620 if (dottedNormals<=0) return -1; /* reject poly */
4621
4622 /* calculate distance each vertex is from poly's plane along direction of motion */
4623 {
4624 int originToPlaneDist = polyPtr->PolyPoint[0].vx;
4625
4626 {
4627 int vertexNum=8;
4628 do
4629 {
4630 vertexNum--;
4631
4632 vertexToPlaneDist[vertexNum] = dynPtr->ObjectVertices[vertexNum].vx - originToPlaneDist;
4633
4634 if (vertexToPlaneDist[vertexNum] < 0) return -1;
4635 }
4636 while(vertexNum);
4637 }
4638
4639
4640 {
4641 int vertexNum=8;
4642 int *distancePtr = vertexToPlaneDist;
4643 do
4644 {
4645 *distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4646
4647 if(*distancePtr < obstacleDistance)
4648 obstacleDistance = *distancePtr;
4649
4650 distancePtr++;
4651 }
4652 while(--vertexNum);
4653
4654 }
4655 }
4656 if (obstacleDistance>=distanceToMove)
4657 return -2;
4658
4659 /* test if any vertices projected paths intersect polygons */
4660 if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4661 {
4662 return obstacleDistance;
4663 }
4664
4665 return -3;
4666 }
4667 static signed int DistanceMovedBeforeNRBBHitsNegXPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4668 {
4669 int dottedNormals;
4670 int obstacleDistance= 0x7fffffff;
4671 int vertexToPlaneDist[8];
4672
4673 LOCALASSERT(polyPtr);
4674
4675 dottedNormals = DirectionOfTravel.vx;
4676 if (dottedNormals<=0) return -1; /* reject poly */
4677
4678 /* calculate distance each vertex is from poly's plane along direction of motion */
4679 {
4680 int originToPlaneDist = -polyPtr->PolyPoint[0].vx;
4681
4682 {
4683 int vertexNum=8;
4684 do
4685 {
4686 vertexNum--;
4687
4688 vertexToPlaneDist[vertexNum] = -dynPtr->ObjectVertices[vertexNum].vx - originToPlaneDist;
4689
4690 if (vertexToPlaneDist[vertexNum] < 0) return -1;
4691 }
4692 while(vertexNum);
4693 }
4694
4695 {
4696 int vertexNum=8;
4697 int *distancePtr = vertexToPlaneDist;
4698 do
4699 {
4700 *distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4701
4702 if(*distancePtr < obstacleDistance)
4703 obstacleDistance = *distancePtr;
4704
4705 distancePtr++;
4706 }
4707 while(--vertexNum);
4708
4709 }
4710 }
4711 if (obstacleDistance>=distanceToMove)
4712 return -2;
4713
4714 /* test if any vertices projected paths intersect polygons */
4715 if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4716 {
4717 return obstacleDistance;
4718 }
4719
4720 return -3;
4721 }
4722 static signed int DistanceMovedBeforeNRBBHitsPosZPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4723 {
4724 int dottedNormals;
4725 int obstacleDistance= 0x7fffffff;
4726 int vertexToPlaneDist[8];
4727
4728 LOCALASSERT(polyPtr);
4729
4730 dottedNormals = -DirectionOfTravel.vz;
4731 if (dottedNormals<=0) return -1; /* reject poly */
4732
4733 /* calculate distance each vertex is from poly's plane along direction of motion */
4734 {
4735 int originToPlaneDist = polyPtr->PolyPoint[0].vz;
4736
4737 {
4738 int vertexNum=8;
4739 do
4740 {
4741 vertexNum--;
4742
4743 vertexToPlaneDist[vertexNum] = dynPtr->ObjectVertices[vertexNum].vz - originToPlaneDist;
4744
4745 if (vertexToPlaneDist[vertexNum] < 0) return -1;
4746 }
4747 while(vertexNum);
4748 }
4749
4750 {
4751 int vertexNum=8;
4752 int *distancePtr = vertexToPlaneDist;
4753 do
4754 {
4755 *distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4756
4757 if(*distancePtr < obstacleDistance)
4758 obstacleDistance = *distancePtr;
4759
4760 distancePtr++;
4761 }
4762 while(--vertexNum);
4763
4764 }
4765 }
4766 if (obstacleDistance>=distanceToMove)
4767 return -2;
4768
4769 /* test if any vertices projected paths intersect polygons */
4770 if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4771 {
4772 return obstacleDistance;
4773 }
4774
4775 return -3;
4776 }
4777 static signed int DistanceMovedBeforeNRBBHitsNegZPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4778 {
4779 int dottedNormals;
4780 int obstacleDistance= 0x7fffffff;
4781 int vertexToPlaneDist[8];
4782
4783 LOCALASSERT(polyPtr);
4784
4785 dottedNormals = DirectionOfTravel.vz;
4786 if (dottedNormals<=0) return -1; /* reject poly */
4787
4788 /* calculate distance each vertex is from poly's plane along direction of motion */
4789 {
4790 int originToPlaneDist = -polyPtr->PolyPoint[0].vz;
4791
4792 {
4793 int vertexNum=8;
4794 do
4795 {
4796 vertexNum--;
4797
4798 vertexToPlaneDist[vertexNum] = -dynPtr->ObjectVertices[vertexNum].vz - originToPlaneDist;
4799
4800 if (vertexToPlaneDist[vertexNum] < 0) return -1;
4801 }
4802 while(vertexNum);
4803 }
4804
4805
4806 {
4807 int vertexNum=8;
4808 int *distancePtr = vertexToPlaneDist;
4809 do
4810 {
4811 *distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4812
4813 if(*distancePtr < obstacleDistance)
4814 obstacleDistance = *distancePtr;
4815
4816 distancePtr++;
4817 }
4818 while(--vertexNum);
4819
4820 }
4821 }
4822 if (obstacleDistance>=distanceToMove)
4823 return -2;
4824
4825 /* test if any vertices projected paths intersect polygons */
4826 if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4827 {
4828 return obstacleDistance;
4829 }
4830
4831 return -3;
4832 }
4833 #endif
NRBBProjectsOntoPolygon(DYNAMICSBLOCK * dynPtr,int vertexToPlaneDist[],struct ColPolyTag * polyPtr,VECTORCH * projectionDirPtr)4834 static int NRBBProjectsOntoPolygon(DYNAMICSBLOCK *dynPtr, int vertexToPlaneDist[], struct ColPolyTag *polyPtr, VECTORCH *projectionDirPtr)
4835 {
4836 /* decide which 2d plane to project onto */
4837 int axisToIgnore = AxisToIgnore(&polyPtr->PolyNormal);
4838 int objMaxX,objMinX,objMaxY,objMinY,objMaxZ,objMinZ;
4839
4840 if (axisToIgnore!=ix)
4841 {
4842 int polyMax,polyMin;
4843
4844 /* search x-coords of poly vertices for min and max */
4845 {
4846 int vertexNum=polyPtr->NumberOfVertices;
4847
4848 polyMax = polyMin = polyPtr->PolyPoint[0].vx;
4849 do
4850 {
4851 int x;
4852 vertexNum--;
4853 x = polyPtr->PolyPoint[vertexNum].vx;
4854 if (x > polyMax) polyMax = x;
4855 else if (x < polyMin) polyMin = x;
4856 }
4857 while(vertexNum);
4858 }
4859 /* search x-coords of object vertices for min and max */
4860 {
4861 int i=7; /* 8 vertices in a cuboid */
4862
4863 objMaxX = objMinX = dynPtr->ObjectVertices[0].vx + MUL_FIXED(vertexToPlaneDist[0],projectionDirPtr->vx);
4864 do
4865 {
4866 int x;
4867 x = dynPtr->ObjectVertices[i].vx + MUL_FIXED(vertexToPlaneDist[i],projectionDirPtr->vx);
4868 if (x > objMaxX) objMaxX = x;
4869 else if (x < objMinX) objMinX = x;
4870 i--;
4871 }
4872 while(i);
4873 }
4874
4875 /* test to see if object & polygon overlap */
4876 if (objMaxX < polyMin || objMinX > polyMax)
4877 return 0;
4878 }
4879 if (axisToIgnore!=iz)
4880 {
4881 int polyMax,polyMin;
4882
4883 /* search z-coords of poly vertices for min and max */
4884 {
4885 int vertexNum=polyPtr->NumberOfVertices;
4886
4887 polyMax = polyMin = polyPtr->PolyPoint[0].vz;
4888 do
4889 {
4890 int z;
4891 vertexNum--;
4892 z = polyPtr->PolyPoint[vertexNum].vz;
4893 if (z > polyMax) polyMax = z;
4894 else if (z < polyMin) polyMin = z;
4895 }
4896 while(vertexNum);
4897 }
4898 /* search z-coords of object vertices for min and max */
4899 {
4900 int i=7; /* 8 vertices in a cuboid */
4901
4902 objMaxZ = objMinZ = dynPtr->ObjectVertices[0].vz + MUL_FIXED(vertexToPlaneDist[0],projectionDirPtr->vz);
4903 do
4904 {
4905 int z;
4906 z = dynPtr->ObjectVertices[i].vz + MUL_FIXED(vertexToPlaneDist[i],projectionDirPtr->vz);
4907 if (z > objMaxZ) objMaxZ = z;
4908 else if (z < objMinZ) objMinZ = z;
4909 i--;
4910 }
4911 while(i);
4912 }
4913
4914 /* test to see if object & polygon overlap */
4915 if (objMaxZ < polyMin || objMinZ > polyMax)
4916 return 0;
4917 }
4918 if (axisToIgnore!=iy)
4919 {
4920 int polyMax,polyMin;
4921
4922 /* search y-coords of poly vertices for min and max */
4923 {
4924 int vertexNum=polyPtr->NumberOfVertices;
4925
4926 polyMax = polyMin = polyPtr->PolyPoint[0].vy;
4927 do
4928 {
4929 int y;
4930 vertexNum--;
4931
4932 y = polyPtr->PolyPoint[vertexNum].vy;
4933 if (y > polyMax) polyMax = y;
4934 else if (y < polyMin) polyMin = y;
4935 }
4936 while(vertexNum);
4937 }
4938 /* search y-coords of object vertices for min and max */
4939 {
4940 int i=7; /* 8 vertices in a cuboid */
4941
4942 objMaxY = objMinY = dynPtr->ObjectVertices[0].vy + MUL_FIXED(vertexToPlaneDist[0],projectionDirPtr->vy);
4943 do
4944 {
4945 int y;
4946
4947 y = dynPtr->ObjectVertices[i].vy + MUL_FIXED(vertexToPlaneDist[i],projectionDirPtr->vy);
4948 if (y > objMaxY) objMaxY = y;
4949 else if (y < objMinY) objMinY = y;
4950 i--;
4951 }
4952 while(i);
4953 }
4954
4955 /* test to see if object & polygon overlap */
4956 if (objMaxY < polyMin || objMinY > polyMax)
4957 return 0;
4958
4959 }
4960
4961 /* test for triangle/rectangle overlap */
4962 /* traingle vertices are stored anticlockwise! */
4963 if (polyPtr->NumberOfVertices == 3)
4964 {
4965 if(axisToIgnore==ix)
4966 {
4967 VECTORCH n;
4968
4969 n.vy = (polyPtr->PolyPoint[1].vz-polyPtr->PolyPoint[0].vz);
4970 n.vz = -(polyPtr->PolyPoint[1].vy-polyPtr->PolyPoint[0].vy);
4971 if(polyPtr->PolyNormal.vx<0)
4972 {
4973 n.vy = -n.vy;
4974 n.vz = -n.vz;
4975 }
4976 {
4977 int d1,d2,d3,d4;
4978 d1 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
4979 d2 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
4980 d3 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
4981 d4 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
4982
4983 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
4984 }
4985
4986 n.vy = (polyPtr->PolyPoint[2].vz-polyPtr->PolyPoint[1].vz);
4987 n.vz = -(polyPtr->PolyPoint[2].vy-polyPtr->PolyPoint[1].vy);
4988 if(polyPtr->PolyNormal.vx<0)
4989 {
4990 n.vy = -n.vy;
4991 n.vz = -n.vz;
4992 }
4993 {
4994 int d1,d2,d3,d4;
4995 d1 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
4996 d2 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
4997 d3 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
4998 d4 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
4999
5000 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5001 }
5002
5003 n.vy = (polyPtr->PolyPoint[0].vz-polyPtr->PolyPoint[2].vz);
5004 n.vz = -(polyPtr->PolyPoint[0].vy-polyPtr->PolyPoint[2].vy);
5005 if(polyPtr->PolyNormal.vx<0)
5006 {
5007 n.vy = -n.vy;
5008 n.vz = -n.vz;
5009 }
5010 {
5011 int d1,d2,d3,d4;
5012 d1 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5013 d2 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5014 d3 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5015 d4 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5016
5017 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5018 }
5019
5020 }
5021 else if(axisToIgnore==iy)
5022 {
5023 VECTORCH n;
5024
5025 n.vx = (polyPtr->PolyPoint[1].vz-polyPtr->PolyPoint[0].vz);
5026 n.vz = -(polyPtr->PolyPoint[1].vx-polyPtr->PolyPoint[0].vx);
5027 if(polyPtr->PolyNormal.vy>0)
5028 {
5029 n.vx = -n.vx;
5030 n.vz = -n.vz;
5031 }
5032 {
5033 int d1,d2,d3,d4;
5034 d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5035 d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5036 d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5037 d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5038
5039 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5040 }
5041
5042 n.vx = (polyPtr->PolyPoint[2].vz-polyPtr->PolyPoint[1].vz);
5043 n.vz = -(polyPtr->PolyPoint[2].vx-polyPtr->PolyPoint[1].vx);
5044 if(polyPtr->PolyNormal.vy>0)
5045 {
5046 n.vx = -n.vx;
5047 n.vz = -n.vz;
5048 }
5049 {
5050 int d1,d2,d3,d4;
5051 d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5052 d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5053 d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5054 d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5055
5056 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5057 }
5058
5059 n.vx = (polyPtr->PolyPoint[0].vz-polyPtr->PolyPoint[2].vz);
5060 n.vz = -(polyPtr->PolyPoint[0].vx-polyPtr->PolyPoint[2].vx);
5061 if(polyPtr->PolyNormal.vy>0)
5062 {
5063 n.vx = -n.vx;
5064 n.vz = -n.vz;
5065 }
5066 {
5067 int d1,d2,d3,d4;
5068 d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5069 d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5070 d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5071 d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5072
5073 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5074 }
5075 }
5076 else if(axisToIgnore==iz)
5077 {
5078 VECTORCH n;
5079
5080 n.vx = (polyPtr->PolyPoint[1].vy-polyPtr->PolyPoint[0].vy);
5081 n.vy = -(polyPtr->PolyPoint[1].vx-polyPtr->PolyPoint[0].vx);
5082 if(polyPtr->PolyNormal.vz<0)
5083 {
5084 n.vx = -n.vx;
5085 n.vy = -n.vy;
5086 }
5087 {
5088 int d1,d2,d3,d4;
5089 d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
5090 d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
5091 d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
5092 d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
5093
5094 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5095 }
5096
5097 n.vx = (polyPtr->PolyPoint[2].vy-polyPtr->PolyPoint[1].vy);
5098 n.vy = -(polyPtr->PolyPoint[2].vx-polyPtr->PolyPoint[1].vx);
5099 if(polyPtr->PolyNormal.vz<0)
5100 {
5101 n.vx = -n.vx;
5102 n.vy = -n.vy;
5103 }
5104 {
5105 int d1,d2,d3,d4;
5106 d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
5107 d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
5108 d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
5109 d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
5110
5111 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5112 }
5113
5114 n.vx = (polyPtr->PolyPoint[0].vy-polyPtr->PolyPoint[2].vy);
5115 n.vy = -(polyPtr->PolyPoint[0].vx-polyPtr->PolyPoint[2].vx);
5116 if(polyPtr->PolyNormal.vz<0)
5117 {
5118 n.vx = -n.vx;
5119 n.vy = -n.vy;
5120 }
5121 {
5122 int d1,d2,d3,d4;
5123 d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
5124 d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
5125 d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
5126 d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
5127
5128 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5129 }
5130 }
5131 }
5132 else
5133 {
5134 if(axisToIgnore==ix)
5135 {
5136 VECTORCH n;
5137
5138 n.vy = (polyPtr->PolyPoint[1].vz-polyPtr->PolyPoint[0].vz);
5139 n.vz = -(polyPtr->PolyPoint[1].vy-polyPtr->PolyPoint[0].vy);
5140 if(polyPtr->PolyNormal.vx<0)
5141 {
5142 n.vy = -n.vy;
5143 n.vz = -n.vz;
5144 }
5145 {
5146 int d1,d2,d3,d4;
5147 d1 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5148 d2 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5149 d3 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5150 d4 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5151
5152 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5153 }
5154
5155 n.vy = (polyPtr->PolyPoint[2].vz-polyPtr->PolyPoint[1].vz);
5156 n.vz = -(polyPtr->PolyPoint[2].vy-polyPtr->PolyPoint[1].vy);
5157 if(polyPtr->PolyNormal.vx<0)
5158 {
5159 n.vy = -n.vy;
5160 n.vz = -n.vz;
5161 }
5162 {
5163 int d1,d2,d3,d4;
5164 d1 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5165 d2 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5166 d3 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5167 d4 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5168
5169 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5170 }
5171
5172 n.vy = (polyPtr->PolyPoint[3].vz-polyPtr->PolyPoint[2].vz);
5173 n.vz = -(polyPtr->PolyPoint[3].vy-polyPtr->PolyPoint[2].vy);
5174 if(polyPtr->PolyNormal.vx<0)
5175 {
5176 n.vy = -n.vy;
5177 n.vz = -n.vz;
5178 }
5179 {
5180 int d1,d2,d3,d4;
5181 d1 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5182 d2 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5183 d3 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5184 d4 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5185
5186 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5187 }
5188
5189 n.vy = (polyPtr->PolyPoint[0].vz-polyPtr->PolyPoint[3].vz);
5190 n.vz = -(polyPtr->PolyPoint[0].vy-polyPtr->PolyPoint[3].vy);
5191 if(polyPtr->PolyNormal.vx<0)
5192 {
5193 n.vy = -n.vy;
5194 n.vz = -n.vz;
5195 }
5196 {
5197 int d1,d2,d3,d4;
5198 d1 = (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
5199 d2 = (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
5200 d3 = (objMinY-polyPtr->PolyPoint[3].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
5201 d4 = (objMinY-polyPtr->PolyPoint[3].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
5202
5203 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5204 }
5205 }
5206 else if(axisToIgnore==iy)
5207 {
5208 VECTORCH n;
5209
5210 n.vx = (polyPtr->PolyPoint[1].vz-polyPtr->PolyPoint[0].vz);
5211 n.vz = -(polyPtr->PolyPoint[1].vx-polyPtr->PolyPoint[0].vx);
5212 if(polyPtr->PolyNormal.vy>0)
5213 {
5214 n.vx = -n.vx;
5215 n.vz = -n.vz;
5216 }
5217 {
5218 int d1,d2,d3,d4;
5219 d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5220 d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5221 d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5222 d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5223
5224 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5225 }
5226
5227 n.vx = (polyPtr->PolyPoint[2].vz-polyPtr->PolyPoint[1].vz);
5228 n.vz = -(polyPtr->PolyPoint[2].vx-polyPtr->PolyPoint[1].vx);
5229 if(polyPtr->PolyNormal.vy>0)
5230 {
5231 n.vx = -n.vx;
5232 n.vz = -n.vz;
5233 }
5234 {
5235 int d1,d2,d3,d4;
5236 d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5237 d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5238 d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5239 d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5240
5241 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5242 }
5243
5244 n.vx = (polyPtr->PolyPoint[3].vz-polyPtr->PolyPoint[2].vz);
5245 n.vz = -(polyPtr->PolyPoint[3].vx-polyPtr->PolyPoint[2].vx);
5246 if(polyPtr->PolyNormal.vy>0)
5247 {
5248 n.vx = -n.vx;
5249 n.vz = -n.vz;
5250 }
5251 {
5252 int d1,d2,d3,d4;
5253 d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5254 d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5255 d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5256 d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5257
5258 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5259 }
5260
5261 n.vx = (polyPtr->PolyPoint[0].vz-polyPtr->PolyPoint[3].vz);
5262 n.vz = -(polyPtr->PolyPoint[0].vx-polyPtr->PolyPoint[3].vx);
5263 if(polyPtr->PolyNormal.vy>0)
5264 {
5265 n.vx = -n.vx;
5266 n.vz = -n.vz;
5267 }
5268 {
5269 int d1,d2,d3,d4;
5270 d1 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
5271 d2 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
5272 d3 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
5273 d4 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
5274
5275 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5276 }
5277
5278 }
5279 else if(axisToIgnore==iz)
5280 {
5281 VECTORCH n;
5282
5283 n.vx = (polyPtr->PolyPoint[1].vy-polyPtr->PolyPoint[0].vy);
5284 n.vy = -(polyPtr->PolyPoint[1].vx-polyPtr->PolyPoint[0].vx);
5285 if(polyPtr->PolyNormal.vz<0)
5286 {
5287 n.vx = -n.vx;
5288 n.vy = -n.vy;
5289 }
5290 {
5291 int d1,d2,d3,d4;
5292 d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
5293 d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
5294 d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
5295 d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
5296
5297 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5298 }
5299
5300 n.vx = (polyPtr->PolyPoint[2].vy-polyPtr->PolyPoint[1].vy);
5301 n.vy = -(polyPtr->PolyPoint[2].vx-polyPtr->PolyPoint[1].vx);
5302 if(polyPtr->PolyNormal.vz<0)
5303 {
5304 n.vx = -n.vx;
5305 n.vy = -n.vy;
5306 }
5307 {
5308 int d1,d2,d3,d4;
5309 d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
5310 d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
5311 d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
5312 d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
5313
5314 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5315 }
5316
5317 n.vx = (polyPtr->PolyPoint[3].vy-polyPtr->PolyPoint[2].vy);
5318 n.vy = -(polyPtr->PolyPoint[3].vx-polyPtr->PolyPoint[2].vx);
5319 if(polyPtr->PolyNormal.vz<0)
5320 {
5321 n.vx = -n.vx;
5322 n.vy = -n.vy;
5323 }
5324 {
5325 int d1,d2,d3,d4;
5326 d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
5327 d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
5328 d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
5329 d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
5330
5331 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5332 }
5333
5334 n.vx = (polyPtr->PolyPoint[0].vy-polyPtr->PolyPoint[3].vy);
5335 n.vy = -(polyPtr->PolyPoint[0].vx-polyPtr->PolyPoint[3].vx);
5336 if(polyPtr->PolyNormal.vz<0)
5337 {
5338 n.vx = -n.vx;
5339 n.vy = -n.vy;
5340 }
5341 {
5342 int d1,d2,d3,d4;
5343 d1 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy;
5344 d2 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinY-polyPtr->PolyPoint[3].vy)*n.vy;
5345 d3 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy;
5346 d4 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinY-polyPtr->PolyPoint[3].vy)*n.vy;
5347
5348 if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5349 }
5350 }
5351 }
5352 return 1;
5353 }
5354
CreateNRBBForObject(const STRATEGYBLOCK * sbPtr)5355 static void CreateNRBBForObject(const STRATEGYBLOCK *sbPtr)
5356 {
5357 VECTORCH *objectVertices = sbPtr->DynPtr->ObjectVertices;
5358 COLLISION_EXTENTS *extentsPtr = 0;
5359 int objectIsCrouching = 0;
5360 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5361
5362 dynPtr->CollisionRadius = 0;
5363
5364
5365 switch (sbPtr->I_SBtype)
5366 {
5367 case I_BehaviourMarinePlayer:
5368 {
5369 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
5370
5371 /* set player state */
5372 objectIsCrouching = (playerStatusPtr->ShapeState != PMph_Standing);
5373
5374 switch(AvP.PlayerType)
5375 {
5376 case I_Marine:
5377 extentsPtr = &CollisionExtents[CE_MARINE];
5378 dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5379 break;
5380
5381 case I_Alien:
5382 extentsPtr = &CollisionExtents[CE_ALIEN];
5383 dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5384 break;
5385
5386 case I_Predator:
5387 extentsPtr = &CollisionExtents[CE_PREDATOR];
5388 dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5389 break;
5390 }
5391 break;
5392 }
5393
5394 case I_BehaviourAlien:
5395 {
5396 ALIEN_STATUS_BLOCK *alienStatusPtr = (ALIEN_STATUS_BLOCK *)sbPtr->SBdataptr;
5397 objectIsCrouching = alienStatusPtr->IAmCrouched;
5398
5399 extentsPtr = &CollisionExtents[CE_ALIEN];
5400 dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5401 sbPtr->SBdptr->ObRadius = 2000;
5402 break;
5403 }
5404 case I_BehaviourPredator:
5405 {
5406 PREDATOR_STATUS_BLOCK *predatorStatusPtr = (PREDATOR_STATUS_BLOCK *)sbPtr->SBdataptr;
5407 objectIsCrouching = predatorStatusPtr->IAmCrouched;
5408
5409 sbPtr->SBdptr->ObRadius = 2000;
5410 extentsPtr = &CollisionExtents[CE_PREDATOR];
5411 // dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5412 break;
5413 }
5414 case I_BehaviourMarine:
5415 {
5416 MARINE_STATUS_BLOCK *marineStatusPtr = (MARINE_STATUS_BLOCK *)sbPtr->SBdataptr;
5417 objectIsCrouching = marineStatusPtr->IAmCrouched;
5418
5419 sbPtr->SBdptr->ObRadius = 2000;
5420 extentsPtr = &CollisionExtents[CE_MARINE];
5421 // dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5422 break;
5423 }
5424 case I_BehaviourFaceHugger:
5425 {
5426 extentsPtr = &CollisionExtents[CE_FACEHUGGER];
5427 dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5428 break;
5429 }
5430 case I_BehaviourXenoborg:
5431 {
5432 extentsPtr = &CollisionExtents[CE_XENOBORG];
5433 break;
5434 }
5435 case I_BehaviourPredatorAlien:
5436 {
5437 extentsPtr = &CollisionExtents[CE_PREDATORALIEN];
5438 break;
5439 }
5440
5441 case I_BehaviourQueenAlien:
5442 extentsPtr = &CollisionExtents[CE_QUEEN];
5443 break;
5444 case I_BehaviourSeal:
5445 extentsPtr = &CollisionExtents[CE_MARINE];
5446 break;
5447
5448 case I_BehaviourNetCorpse:
5449 extentsPtr = &CollisionExtents[CE_CORPSE];
5450 sbPtr->SBdptr->ObRadius = 700;
5451 break;
5452
5453 case I_BehaviourNetGhost:
5454 {
5455 NETGHOSTDATABLOCK *ghostData;
5456
5457 ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
5458 LOCALASSERT(ghostData);
5459
5460 switch(ghostData->type)
5461 {
5462 case I_BehaviourAlienPlayer:
5463 {
5464 extentsPtr = &CollisionExtents[CE_ALIEN];
5465 dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5466 sbPtr->SBdptr->ObRadius = 700;
5467 break;
5468 }
5469 case I_BehaviourPredatorPlayer:
5470 {
5471 extentsPtr = &CollisionExtents[CE_PREDATOR];
5472 sbPtr->SBdptr->ObRadius = 700;
5473 break;
5474 }
5475 case I_BehaviourMarinePlayer:
5476 {
5477 extentsPtr = &CollisionExtents[CE_MARINE];
5478 sbPtr->SBdptr->ObRadius = 700;
5479 break;
5480 }
5481
5482 case I_BehaviourAlien:
5483 {
5484 #if 0
5485 ALIEN_STATUS_BLOCK *alienStatusPtr = (ALIEN_STATUS_BLOCK *)sbPtr->SBdataptr;
5486 objectIsCrouching = alienStatusPtr->IAmCrouched;
5487 #endif
5488 extentsPtr = &CollisionExtents[CE_ALIEN];
5489 dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5490 sbPtr->SBdptr->ObRadius = 2000;
5491 break;
5492 }
5493
5494 case I_BehaviourNetCorpse:
5495 extentsPtr = &CollisionExtents[CE_MARINE];
5496 sbPtr->SBdptr->ObRadius = 700;
5497 break;
5498 default:
5499 break;
5500 }
5501 }
5502
5503 default:
5504 break;
5505 }
5506
5507 if (extentsPtr)
5508 {
5509 /* max X */
5510 objectVertices[0].vx = extentsPtr->CollisionRadius;
5511 objectVertices[1].vx = extentsPtr->CollisionRadius;
5512 objectVertices[2].vx = extentsPtr->CollisionRadius;
5513 objectVertices[3].vx = extentsPtr->CollisionRadius;
5514
5515 /* max Z */
5516 objectVertices[0].vz = extentsPtr->CollisionRadius;
5517 objectVertices[2].vz = extentsPtr->CollisionRadius;
5518 objectVertices[4].vz = extentsPtr->CollisionRadius;
5519 objectVertices[6].vz = extentsPtr->CollisionRadius;
5520
5521 /* min X */
5522 objectVertices[4].vx = -extentsPtr->CollisionRadius;
5523 objectVertices[5].vx = -extentsPtr->CollisionRadius;
5524 objectVertices[6].vx = -extentsPtr->CollisionRadius;
5525 objectVertices[7].vx = -extentsPtr->CollisionRadius;
5526
5527 /* min Z */
5528 objectVertices[1].vz = -extentsPtr->CollisionRadius;
5529 objectVertices[3].vz = -extentsPtr->CollisionRadius;
5530 objectVertices[5].vz = -extentsPtr->CollisionRadius;
5531 objectVertices[7].vz = -extentsPtr->CollisionRadius;
5532
5533 /* max Y */
5534 objectVertices[0].vy = extentsPtr->Bottom;
5535 objectVertices[1].vy = extentsPtr->Bottom;
5536 objectVertices[4].vy = extentsPtr->Bottom;
5537 objectVertices[5].vy = extentsPtr->Bottom;
5538
5539 /* min Y */
5540 if(objectIsCrouching)
5541 {
5542 objectVertices[2].vy = extentsPtr->CrouchingTop;
5543 objectVertices[3].vy = extentsPtr->CrouchingTop;
5544 objectVertices[6].vy = extentsPtr->CrouchingTop;
5545 objectVertices[7].vy = extentsPtr->CrouchingTop;
5546 }
5547 else
5548 {
5549 objectVertices[2].vy = extentsPtr->StandingTop;
5550 objectVertices[3].vy = extentsPtr->StandingTop;
5551 objectVertices[6].vy = extentsPtr->StandingTop;
5552 objectVertices[7].vy = extentsPtr->StandingTop;
5553 }
5554 }
5555 else
5556 /* make a cuboid from the shape's extent data */
5557 {
5558 {
5559 int shapeMaxX = sbPtr->SBdptr->ObMaxX;
5560 if (shapeMaxX < MINIMUM_BOUNDINGBOX_EXTENT) shapeMaxX = MINIMUM_BOUNDINGBOX_EXTENT;
5561 objectVertices[0].vx = shapeMaxX;
5562 objectVertices[1].vx = shapeMaxX;
5563 objectVertices[2].vx = shapeMaxX;
5564 objectVertices[3].vx = shapeMaxX;
5565 }
5566 {
5567 int shapeMinX = sbPtr->SBdptr->ObMinX;
5568 if (shapeMinX > -MINIMUM_BOUNDINGBOX_EXTENT) shapeMinX = -MINIMUM_BOUNDINGBOX_EXTENT;
5569 objectVertices[4].vx = shapeMinX;
5570 objectVertices[5].vx = shapeMinX;
5571 objectVertices[6].vx = shapeMinX;
5572 objectVertices[7].vx = shapeMinX;
5573 }
5574 {
5575 int shapeMaxY = sbPtr->SBdptr->ObMaxY;
5576 if (shapeMaxY < MINIMUM_BOUNDINGBOX_EXTENT) shapeMaxY = MINIMUM_BOUNDINGBOX_EXTENT;
5577 objectVertices[0].vy = shapeMaxY;
5578 objectVertices[1].vy = shapeMaxY;
5579 objectVertices[4].vy = shapeMaxY;
5580 objectVertices[5].vy = shapeMaxY;
5581 }
5582 {
5583 int shapeMinY = sbPtr->SBdptr->ObMinY;
5584 if (shapeMinY > -MINIMUM_BOUNDINGBOX_EXTENT) shapeMinY = -MINIMUM_BOUNDINGBOX_EXTENT;
5585 objectVertices[2].vy = shapeMinY;
5586 objectVertices[3].vy = shapeMinY;
5587 objectVertices[6].vy = shapeMinY;
5588 objectVertices[7].vy = shapeMinY;
5589 }
5590 {
5591 int shapeMaxZ = sbPtr->SBdptr->ObMaxZ;
5592 if (shapeMaxZ < MINIMUM_BOUNDINGBOX_EXTENT) shapeMaxZ = MINIMUM_BOUNDINGBOX_EXTENT;
5593 objectVertices[0].vz = shapeMaxZ;
5594 objectVertices[2].vz = shapeMaxZ;
5595 objectVertices[4].vz = shapeMaxZ;
5596 objectVertices[6].vz = shapeMaxZ;
5597 }
5598 {
5599 int shapeMinZ = sbPtr->SBdptr->ObMinZ;
5600 if (shapeMinZ > -MINIMUM_BOUNDINGBOX_EXTENT) shapeMinZ = -MINIMUM_BOUNDINGBOX_EXTENT;
5601 objectVertices[1].vz = shapeMinZ;
5602 objectVertices[3].vz = shapeMinZ;
5603 objectVertices[5].vz = shapeMinZ;
5604 objectVertices[7].vz = shapeMinZ;
5605 }
5606 }
5607
5608 /* translate cuboid into world space */
5609 {
5610 VECTORCH *vertexPtr = objectVertices;
5611 VECTORCH objectPosition = sbPtr->DynPtr->Position;
5612
5613 int vertexNum=8;
5614 do
5615 {
5616 vertexPtr->vx += objectPosition.vx;
5617 vertexPtr->vy += objectPosition.vy;
5618 vertexPtr->vz += objectPosition.vz;
5619 vertexPtr++;
5620 }
5621 while(--vertexNum);
5622
5623 }
5624 }
CreateSphereBBForObject(const STRATEGYBLOCK * sbPtr)5625 static void CreateSphereBBForObject(const STRATEGYBLOCK *sbPtr)
5626 {
5627 VECTORCH *objectVertices = sbPtr->DynPtr->ObjectVertices;
5628 /* make a cuboid from the sphere's radius */
5629 {
5630 int radius = sbPtr->DynPtr->CollisionRadius;
5631
5632 objectVertices[0].vx = radius;
5633 objectVertices[1].vx = radius;
5634 objectVertices[2].vx = radius;
5635 objectVertices[3].vx = radius;
5636 objectVertices[0].vy = radius;
5637 objectVertices[1].vy = radius;
5638 objectVertices[4].vy = radius;
5639 objectVertices[5].vy = radius;
5640 objectVertices[0].vz = radius;
5641 objectVertices[2].vz = radius;
5642 objectVertices[4].vz = radius;
5643 objectVertices[6].vz = radius;
5644
5645 radius = -radius;
5646
5647 objectVertices[4].vx = radius;
5648 objectVertices[5].vx = radius;
5649 objectVertices[6].vx = radius;
5650 objectVertices[7].vx = radius;
5651 objectVertices[2].vy = radius;
5652 objectVertices[3].vy = radius;
5653 objectVertices[6].vy = radius;
5654 objectVertices[7].vy = radius;
5655 objectVertices[1].vz = radius;
5656 objectVertices[3].vz = radius;
5657 objectVertices[5].vz = radius;
5658 objectVertices[7].vz = radius;
5659 }
5660
5661 /* translate cuboid into world space */
5662 {
5663 VECTORCH *vertexPtr = objectVertices;
5664 VECTORCH objectPosition = sbPtr->DynPtr->Position;
5665
5666 int vertexNum=8;
5667 do
5668 {
5669 vertexPtr->vx += objectPosition.vx;
5670 vertexPtr->vy += objectPosition.vy;
5671 vertexPtr->vz += objectPosition.vz;
5672 vertexPtr++;
5673 }
5674 while(--vertexNum);
5675
5676 }
5677 }
5678
5679
5680
5681
5682 #if 0
5683 static int RelocatedDueToFallout(DYNAMICSBLOCK *dynPtr)
5684 {
5685 /* If the object is outside ALL of the modules in the
5686 ActiveBlockList, move it back to its previous position. */
5687
5688 {
5689 extern int NumActiveBlocks;
5690 extern DISPLAYBLOCK *ActiveBlockList[];
5691
5692 /* scan through modules and stop if object is inside any of them */
5693 {
5694 int objectInsideSomething = 0;
5695
5696 int numberOfObjects = NumActiveBlocks;
5697 while(numberOfObjects)
5698 {
5699 DISPLAYBLOCK* objectPtr = ActiveBlockList[--numberOfObjects];
5700 GLOBALASSERT(objectPtr);
5701 if (objectPtr->ObMyModule) /* is object a module ? */
5702 {
5703 VECTORCH position = dynPtr->Position;
5704 position.vx -= objectPtr->ObWorld.vx;
5705 position.vy -= objectPtr->ObWorld.vy;
5706 position.vz -= objectPtr->ObWorld.vz;
5707
5708 if (position.vx >= objectPtr->ObMinX)
5709 if (position.vx <= objectPtr->ObMaxX)
5710 if (position.vz >= objectPtr->ObMinZ)
5711 if (position.vz <= objectPtr->ObMaxZ)
5712 if (position.vy >= objectPtr->ObMinY)
5713 if (position.vy <= objectPtr->ObMaxY)
5714 {
5715 objectInsideSomething = 1;
5716 break;
5717 }
5718 }
5719 }
5720
5721 if (!objectInsideSomething)
5722 {
5723 dynPtr->Position=dynPtr->PrevPosition;
5724 // NewOnScreenMessage("DEBUG: WENT OUTSIDE ENV");
5725 }
5726
5727 return !objectInsideSomething;
5728 }
5729 }
5730
5731 }
5732 #endif
5733
5734
5735
5736
5737
5738
5739 /* KJL 10:43:28 8/20/97 - stuff to add to bh_near.c */
5740 #if 0
5741
5742 textprint("alien vel %d %d %d\n",sbPtr->DynPtr->LinVelocity.vx,sbPtr->DynPtr->LinVelocity.vy,sbPtr->DynPtr->LinVelocity.vz);
5743 #if 1
5744 if(alienStatusPtr->IAmCrouched)
5745 {
5746 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5747 LOCALASSERT(dynPtr);
5748
5749 dynPtr->DynamicsType = DYN_TYPE_SPHERE_COLLISIONS;
5750 }
5751 else
5752 {
5753 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5754 LOCALASSERT(dynPtr);
5755
5756 dynPtr->DynamicsType = DYN_TYPE_NRBB_COLLISIONS;
5757 }
5758 #endif
5759 #endif
5760
5761 static signed int DistanceMovedBeforeParticleHitsPolygon(PARTICLE *particlePtr, struct ColPolyTag *polyPtr, int distanceToMove);
5762
5763 #if 1
5764
5765 /*KJL****************
5766 * PARTICLE DYNAMICS *
5767 ****************KJL*/
5768
ParticleDynamics(PARTICLE * particlePtr,VECTORCH * obstacleNormalPtr,int * moduleIndexPtr)5769 int ParticleDynamics(PARTICLE *particlePtr, VECTORCH *obstacleNormalPtr, int *moduleIndexPtr)
5770 {
5771 VECTORCH prevPosition = particlePtr->Position;
5772 DISPLAYBLOCK *hitModule = 0;
5773 int polysLeft;
5774 struct ColPolyTag *nearPolysPtr;
5775 int distanceToMove;
5776 VECTORCH displacement;
5777 int hitObstacle=0;
5778
5779 displacement.vx = MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
5780 displacement.vy = MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
5781 displacement.vz = MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
5782 distanceToMove = Magnitude(&displacement);
5783
5784 if (distanceToMove<COLLISION_GRANULARITY) return 0;
5785
5786 DirectionOfTravel = particlePtr->Velocity;
5787 Normalise(&DirectionOfTravel);
5788
5789 if (!LocalDetailLevels.BloodCollidesWithEnvironment
5790 &&(particlePtr->ParticleID==PARTICLE_ALIEN_BLOOD
5791 ||particlePtr->ParticleID==PARTICLE_HUMAN_BLOOD
5792 ||particlePtr->ParticleID==PARTICLE_PREDATOR_BLOOD))
5793 {
5794 CollisionPolysPtr = &CollisionPolysArray[0];
5795 NumberOfCollisionPolys=0;
5796 }
5797 else
5798 {
5799 FindLandscapePolygonsInParticlesPath(particlePtr, &displacement);
5800 }
5801
5802 polysLeft = NumberOfCollisionPolys;
5803 nearPolysPtr = CollisionPolysArray;
5804
5805 /* check against selected polys */
5806 while(polysLeft)
5807 {
5808 signed int distanceToObstacle;
5809
5810 distanceToObstacle = DistanceMovedBeforeParticleHitsPolygon(particlePtr,nearPolysPtr,distanceToMove);
5811
5812 if (distanceToObstacle>=0)
5813 {
5814 hitObstacle=1;
5815 distanceToMove = distanceToObstacle;
5816 *obstacleNormalPtr = nearPolysPtr->PolyNormal;
5817 if ( (nearPolysPtr->ParentObject)
5818 &&(nearPolysPtr->ParentObject->ObMyModule) )
5819 {
5820 *moduleIndexPtr = nearPolysPtr->ParentObject->ObMyModule->m_index;
5821 hitModule = nearPolysPtr->ParentObject;
5822 }
5823 else
5824 {
5825 *moduleIndexPtr = -1;
5826 hitModule=0;
5827 if (particlePtr->ParticleID==PARTICLE_FLECHETTE && nearPolysPtr->ParentObject)
5828 {
5829 if (nearPolysPtr->ParentObject->ObStrategyBlock)
5830 {
5831 CauseDamageToObject(nearPolysPtr->ParentObject->ObStrategyBlock,&FlechetteDamage,ONE_FIXED,&(particlePtr->Velocity));
5832 }
5833 } else if (particlePtr->ParticleID==PARTICLE_PREDPISTOL_FLECHETTE && nearPolysPtr->ParentObject)
5834 {
5835 if (nearPolysPtr->ParentObject->ObStrategyBlock)
5836 {
5837 CauseDamageToObject(nearPolysPtr->ParentObject->ObStrategyBlock,&PredPistol_FlechetteDamage,ONE_FIXED,&(particlePtr->Velocity));
5838 }
5839 }
5840
5841 }
5842 }
5843 nearPolysPtr++;
5844 polysLeft--;
5845 }
5846
5847
5848 if (distanceToMove>COLLISION_GRANULARITY)
5849 {
5850 distanceToMove-=COLLISION_GRANULARITY;
5851 particlePtr->Position.vx += MUL_FIXED(DirectionOfTravel.vx,distanceToMove);
5852 particlePtr->Position.vy += MUL_FIXED(DirectionOfTravel.vy,distanceToMove);
5853 particlePtr->Position.vz += MUL_FIXED(DirectionOfTravel.vz,distanceToMove);
5854 }
5855
5856 if (hitObstacle)
5857 {
5858 int magOfPerpImp = DotProduct(obstacleNormalPtr,&(particlePtr->Velocity));
5859 int magnitude = Magnitude(&particlePtr->Velocity);
5860 particlePtr->Velocity.vx -= MUL_FIXED(obstacleNormalPtr->vx, magOfPerpImp);
5861 particlePtr->Velocity.vy -= MUL_FIXED(obstacleNormalPtr->vy, magOfPerpImp);
5862 particlePtr->Velocity.vz -= MUL_FIXED(obstacleNormalPtr->vz, magOfPerpImp);
5863 if(particlePtr->Velocity.vx || particlePtr->Velocity.vy || particlePtr->Velocity.vz)
5864 {
5865 Normalise(&particlePtr->Velocity);
5866 particlePtr->Velocity.vx = MUL_FIXED(particlePtr->Velocity.vx,magnitude/2);
5867 particlePtr->Velocity.vy = MUL_FIXED(particlePtr->Velocity.vy,magnitude/2);
5868 particlePtr->Velocity.vz = MUL_FIXED(particlePtr->Velocity.vz,magnitude/2);
5869 }
5870 }
5871
5872 /* test to see if you've hit any objects */
5873 {
5874 int i = NumberOfDynamicObjects;
5875 {
5876 if (prevPosition.vx > particlePtr->Position.vx)
5877 {
5878 DBBMinX = particlePtr->Position.vx;
5879 DBBMaxX = prevPosition.vx;
5880 }
5881 else
5882 {
5883 DBBMinX = prevPosition.vx;
5884 DBBMaxX = particlePtr->Position.vx;
5885 }
5886
5887 if (prevPosition.vy > particlePtr->Position.vy)
5888 {
5889 DBBMinY = particlePtr->Position.vy;
5890 DBBMaxY = prevPosition.vy;
5891 }
5892 else
5893 {
5894 DBBMinY = prevPosition.vy;
5895 DBBMaxY = particlePtr->Position.vy;
5896 }
5897
5898 if (prevPosition.vz > particlePtr->Position.vz)
5899 {
5900 DBBMinZ = particlePtr->Position.vz;
5901 DBBMaxZ = prevPosition.vz;
5902 }
5903 else
5904 {
5905 DBBMinZ = prevPosition.vz;
5906 DBBMaxZ = particlePtr->Position.vz;
5907 }
5908
5909 }
5910 /* scan through objects */
5911 while(i--)
5912 {
5913 STRATEGYBLOCK *sbPtr = DynamicObjectsList[i];
5914 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5915 DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
5916
5917 if (dispPtr)
5918 if (DBBMinX<dynPtr->ObjectVertices[0].vx && DBBMaxX>dynPtr->ObjectVertices[7].vx)
5919 if (DBBMinY<dynPtr->ObjectVertices[0].vy && DBBMaxY>dynPtr->ObjectVertices[7].vy)
5920 if (DBBMinZ<dynPtr->ObjectVertices[0].vz && DBBMaxZ>dynPtr->ObjectVertices[7].vz)
5921 {
5922 /* blam! particle hit something */
5923 if (particlePtr->ParticleID==PARTICLE_ALIEN_BLOOD)
5924 {
5925 if ((dispPtr==Player)||(sbPtr->I_SBtype==I_BehaviourMarine)) {
5926 CauseDamageToObject(sbPtr,&TemplateAmmo[AMMO_ALIEN_FRAG].MaxDamage[AvP.Difficulty], NormalFrameTime,NULL);
5927 }
5928 }
5929 else if (particlePtr->ParticleID==PARTICLE_FLAME
5930 ||particlePtr->ParticleID==PARTICLE_PARGEN_FLAME
5931 ||particlePtr->ParticleID==PARTICLE_MOLOTOVFLAME)
5932 {
5933 BOOL ignoreDamage = FALSE;
5934 if ((dispPtr==Player)||(dispPtr->HModelControlBlock))
5935 {
5936
5937 if(AvP.Network != I_No_Network)
5938 {
5939 //If friendly fire has been disabled , we may need to ignore this option
5940 if(particlePtr->ParticleID==PARTICLE_FLAME)
5941 {
5942 if (netGameData.disableFriendlyFire && (netGameData.gameType==NGT_CoopDeathmatch || netGameData.gameType==NGT_Coop))
5943 {
5944 //okay , friendly fire is off , so flamethrower particles , can't harm
5945 //marines.
5946 //in coop games it shouldn't harm predators either
5947 if(sbPtr->I_SBtype==I_BehaviourNetGhost)
5948 {
5949 NETGHOSTDATABLOCK *ghostData=(NETGHOSTDATABLOCK *) sbPtr->SBdataptr;
5950 GLOBALASSERT(ghostData);
5951 if (ghostData->type==I_BehaviourMarinePlayer)
5952 {
5953 ignoreDamage = TRUE;
5954 }
5955 else if (ghostData->type==I_BehaviourPredatorPlayer && netGameData.gameType==NGT_Coop)
5956 {
5957 ignoreDamage = TRUE;
5958 }
5959 }
5960 if(dispPtr==Player)
5961 {
5962 if(AvP.PlayerType == I_Marine)
5963 {
5964 ignoreDamage = TRUE;
5965 }
5966 else if (AvP.PlayerType == I_Predator && netGameData.gameType==NGT_Coop)
5967 {
5968 ignoreDamage = TRUE;
5969 }
5970 }
5971
5972 }
5973 }
5974
5975 if(!ignoreDamage)
5976 {
5977 if(dispPtr==Player)
5978 {
5979 extern DPID myIgniterId;
5980 myIgniterId=0; //the player hasn't been set alight by a network opponent
5981 }
5982 else if(sbPtr->I_SBtype==I_BehaviourAlien)
5983 {
5984 //note that the alien has been set on fire locally
5985 ALIEN_STATUS_BLOCK *alienStatus = (ALIEN_STATUS_BLOCK *)sbPtr->SBdataptr;
5986 if(particlePtr->ParticleID==PARTICLE_FLAME)
5987 {
5988 extern DPID AVPDPNetID;
5989 alienStatus->aliensIgniterId=AVPDPNetID;
5990 }
5991 else
5992 {
5993 //no credit for aliens killed by molotov particles , or
5994 //particle generator particles.
5995 alienStatus->aliensIgniterId=0;
5996 }
5997 }
5998 }
5999 }
6000 if(!ignoreDamage)
6001 {
6002 if(sbPtr->I_SBtype==I_BehaviourNetGhost)
6003 {
6004
6005 /*
6006 Don't let molotov particles damage netghosts. Each machine in a net game will be generating
6007 its own molotov particles.
6008 Similary for PARTICLE_PARGEN_FLAME
6009 */
6010 if(particlePtr->ParticleID==PARTICLE_FLAME)
6011 {
6012 NETGHOSTDATABLOCK *ghostData=(NETGHOSTDATABLOCK *) sbPtr->SBdataptr;
6013 GLOBALASSERT(ghostData);
6014
6015
6016 //just add up the number of particles that have hit the ghost
6017 //so the damage message can be sent in one block
6018 ghostData->FlameHitCount++;
6019 sbPtr->SBDamageBlock.IsOnFire = 1;
6020 }
6021 }
6022 else
6023 {
6024 CauseDamageToObject(sbPtr,&TemplateAmmo[AMMO_FLAMETHROWER].MaxDamage[AvP.Difficulty], ONE_FIXED/400,NULL);
6025 sbPtr->SBDamageBlock.IsOnFire = 1;
6026 }
6027 }
6028 }
6029 if (dispPtr==Player && !ignoreDamage)
6030 {
6031 PlayerStatusPtr->fireTimer=PLAYER_ON_FIRE_TIME;
6032 }
6033 }
6034 else if (particlePtr->ParticleID==PARTICLE_FLECHETTE)
6035 {
6036 if(sbPtr->I_SBtype==I_BehaviourNetGhost)
6037 {
6038 //for net ghosts add up all the flechettes that hit it this frame , and send as one
6039 //damage message
6040 NETGHOSTDATABLOCK *ghostData=(NETGHOSTDATABLOCK *) sbPtr->SBdataptr;
6041 GLOBALASSERT(ghostData);
6042 ghostData->FlechetteHitCount++;
6043
6044 }
6045 else
6046 {
6047 CauseDamageToObject(sbPtr,&FlechetteDamage,ONE_FIXED,&(particlePtr->Velocity));
6048 }
6049 }
6050 else if (particlePtr->ParticleID==PARTICLE_PREDPISTOL_FLECHETTE)
6051 {
6052 CauseDamageToObject(sbPtr,&PredPistol_FlechetteDamage,particlePtr->LifeTime,&(particlePtr->Velocity));
6053 }
6054 }
6055 }
6056 }
6057
6058 if (*moduleIndexPtr != -1)
6059 {
6060 if(hitModule)
6061 {
6062 char stickWhereYouAre = 0;
6063
6064 if (hitModule->ObStrategyBlock)
6065 {
6066 if (hitModule->ObMyModule && (!hitModule->ObMorphCtrl))
6067 {
6068 stickWhereYouAre=1;
6069 }
6070 }
6071 else
6072 {
6073 stickWhereYouAre = 1;
6074 }
6075
6076 if (!stickWhereYouAre) *moduleIndexPtr = -1;
6077
6078 return hitObstacle;
6079 }
6080 return hitObstacle;
6081 }
6082 else return 0;
6083 }
6084
FindLandscapePolygonsInParticlesPath(PARTICLE * particlePtr,VECTORCH * displacementPtr)6085 static void FindLandscapePolygonsInParticlesPath(PARTICLE *particlePtr, VECTORCH *displacementPtr)
6086 {
6087 extern int NumActiveBlocks;
6088 extern DISPLAYBLOCK *ActiveBlockList[];
6089
6090 /* initialise near polygons array */
6091 CollisionPolysPtr = &CollisionPolysArray[0];
6092 NumberOfCollisionPolys=0;
6093
6094 /* scan through ActiveBlockList for modules */
6095 {
6096 int numberOfObjects = NumActiveBlocks;
6097 while(numberOfObjects)
6098 {
6099 DISPLAYBLOCK* objectPtr = ActiveBlockList[--numberOfObjects];
6100 char isStaticObject=0;
6101
6102 GLOBALASSERT(objectPtr);
6103 if(objectPtr->ObStrategyBlock)
6104 if(objectPtr->ObStrategyBlock->DynPtr)
6105 {
6106 if(((objectPtr->ObStrategyBlock->DynPtr->IsStatic)
6107 ||(objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithObjects))
6108 &&(!objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithEnvironment))
6109 isStaticObject=1;
6110 }
6111
6112 if (objectPtr->ObMyModule) /* is object a module or static? */
6113 {
6114 {
6115 DBBMaxX = particlePtr->Position.vx - objectPtr->ObWorld.vx + COLLISION_GRANULARITY;
6116 DBBMinX = particlePtr->Position.vx - objectPtr->ObWorld.vx - COLLISION_GRANULARITY;
6117
6118 DBBMaxY = particlePtr->Position.vy - objectPtr->ObWorld.vy + COLLISION_GRANULARITY;
6119 DBBMinY = particlePtr->Position.vy - objectPtr->ObWorld.vy - COLLISION_GRANULARITY;
6120
6121 DBBMaxZ = particlePtr->Position.vz - objectPtr->ObWorld.vz + COLLISION_GRANULARITY;
6122 DBBMinZ = particlePtr->Position.vz - objectPtr->ObWorld.vz - COLLISION_GRANULARITY;
6123
6124 if (displacementPtr->vx > 0)
6125 {
6126 DBBMaxX += displacementPtr->vx;
6127 }
6128 else
6129 {
6130 DBBMinX += displacementPtr->vx;
6131 }
6132
6133 if (displacementPtr->vy > 0)
6134 {
6135 DBBMaxY += displacementPtr->vy;
6136 }
6137 else
6138 {
6139 DBBMinY += displacementPtr->vy;
6140 }
6141
6142 if (displacementPtr->vz > 0)
6143 {
6144 DBBMaxZ += displacementPtr->vz;
6145 }
6146 else
6147 {
6148 DBBMinZ += displacementPtr->vz;
6149 }
6150
6151 }
6152 LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
6153
6154 /* if the bounding box intersects with the object, investigate */
6155 if (( (DBBMaxX >= objectPtr->ObMinX) && (DBBMinX <= objectPtr->ObMaxX) )
6156 &&( (DBBMaxY >= objectPtr->ObMinY) && (DBBMinY <= objectPtr->ObMaxY) )
6157 &&( (DBBMaxZ >= objectPtr->ObMinZ) && (DBBMinZ <= objectPtr->ObMaxZ) ))
6158 TestShapeWithParticlesDynamicBoundingBox(objectPtr);
6159 }
6160 else if (isStaticObject)
6161 {
6162 {
6163 DBBMaxX = particlePtr->Position.vx - objectPtr->ObWorld.vx + COLLISION_GRANULARITY;
6164 DBBMinX = particlePtr->Position.vx - objectPtr->ObWorld.vx - COLLISION_GRANULARITY;
6165
6166 DBBMaxY = particlePtr->Position.vy - objectPtr->ObWorld.vy + COLLISION_GRANULARITY;
6167 DBBMinY = particlePtr->Position.vy - objectPtr->ObWorld.vy - COLLISION_GRANULARITY;
6168
6169 DBBMaxZ = particlePtr->Position.vz - objectPtr->ObWorld.vz + COLLISION_GRANULARITY;
6170 DBBMinZ = particlePtr->Position.vz - objectPtr->ObWorld.vz - COLLISION_GRANULARITY;
6171
6172 if (displacementPtr->vx > 0)
6173 {
6174 DBBMaxX += displacementPtr->vx;
6175 }
6176 else
6177 {
6178 DBBMinX += displacementPtr->vx;
6179 }
6180
6181 if (displacementPtr->vy > 0)
6182 {
6183 DBBMaxY += displacementPtr->vy;
6184 }
6185 else
6186 {
6187 DBBMinY += displacementPtr->vy;
6188 }
6189
6190 if (displacementPtr->vz > 0)
6191 {
6192 DBBMaxZ += displacementPtr->vz;
6193 }
6194 else
6195 {
6196 DBBMinZ += displacementPtr->vz;
6197 }
6198
6199 }
6200 LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
6201
6202 /* if the bounding box intersects with the object, investigate */
6203 if (( (DBBMaxX >= -objectPtr->ObRadius) && (DBBMinX <= objectPtr->ObRadius) )
6204 &&( (DBBMaxY >= -objectPtr->ObRadius) && (DBBMinY <= objectPtr->ObRadius) )
6205 &&( (DBBMaxZ >= -objectPtr->ObRadius) && (DBBMinZ <= objectPtr->ObRadius) ))
6206 TestShapeWithParticlesDynamicBoundingBox(objectPtr);
6207
6208 }
6209 }
6210 }
6211 }
6212
DistanceMovedBeforeParticleHitsPolygon(PARTICLE * particlePtr,struct ColPolyTag * polyPtr,int distanceToMove)6213 static signed int DistanceMovedBeforeParticleHitsPolygon(PARTICLE *particlePtr, struct ColPolyTag *polyPtr, int distanceToMove)
6214 {
6215 VECTORCH pointOnPlane;
6216 int lambda;
6217 int axis1;
6218 int axis2;
6219
6220 {
6221 int normDotBeta = DotProduct(&(polyPtr->PolyNormal),&DirectionOfTravel);
6222
6223 /* trivial rejection of poly if it is not facing LOS */
6224 if (normDotBeta>-500)
6225 {
6226 return -1;
6227 }
6228
6229 /* calculate coords of plane-line intersection */
6230 {
6231 int d;
6232 {
6233 /* get a pt in the poly */
6234 VECTORCH pop=polyPtr->PolyPoint[0];
6235 pop.vx -= particlePtr->Position.vx;
6236 pop.vy -= particlePtr->Position.vy;
6237 pop.vz -= particlePtr->Position.vz;
6238
6239 d = DotProduct(&(polyPtr->PolyNormal),&pop);
6240 }
6241 if (d>=0)
6242 {
6243 return -1;
6244 }
6245 lambda = DIV_FIXED(d,normDotBeta);
6246 if (lambda>=distanceToMove)
6247 {
6248 return -1;
6249 }
6250 pointOnPlane.vx = particlePtr->Position.vx + MUL_FIXED(lambda,DirectionOfTravel.vx);
6251 pointOnPlane.vy = particlePtr->Position.vy + MUL_FIXED(lambda,DirectionOfTravel.vy);
6252 pointOnPlane.vz = particlePtr->Position.vz + MUL_FIXED(lambda,DirectionOfTravel.vz);
6253
6254 }
6255
6256 /* decide which 2d plane to project onto */
6257
6258 {
6259 VECTORCH absNormal = (polyPtr->PolyNormal);
6260 if (absNormal.vx<0) absNormal.vx=-absNormal.vx;
6261 if (absNormal.vy<0) absNormal.vy=-absNormal.vy;
6262 if (absNormal.vz<0) absNormal.vz=-absNormal.vz;
6263
6264 if (absNormal.vx > absNormal.vy)
6265 {
6266 if (absNormal.vx > absNormal.vz)
6267 {
6268 axis1=iy;
6269 axis2=iz;
6270 }
6271 else
6272 {
6273 axis1=ix;
6274 axis2=iy;
6275 }
6276 }
6277 else
6278 {
6279 if (absNormal.vy > absNormal.vz)
6280 {
6281 axis1=ix;
6282 axis2=iz;
6283 }
6284 else
6285 {
6286 axis1=ix;
6287 axis2=iy;
6288 }
6289 }
6290 }
6291
6292 }
6293 {
6294 int projectedPolyVertex[20];
6295 int projectedPointOnPlane[2];
6296 int *popPtr = &pointOnPlane.vx;
6297
6298 projectedPointOnPlane[0]=*(popPtr+axis1);
6299 projectedPointOnPlane[1]=*(popPtr+axis2);
6300
6301 {
6302 VECTORCH *vertexPtr = polyPtr->PolyPoint;
6303 int *projectedVertexPtr= projectedPolyVertex;
6304 int noOfVertices = polyPtr->NumberOfVertices;
6305
6306 do
6307 {
6308 *projectedVertexPtr++ = *((int*)vertexPtr + axis1);
6309 *projectedVertexPtr++ = *((int*)vertexPtr + axis2);
6310
6311 vertexPtr++;
6312 noOfVertices--;
6313 }
6314 while(noOfVertices);
6315
6316 }
6317
6318
6319 if (PointInPolygon(&projectedPointOnPlane[0],&projectedPolyVertex[0],polyPtr->NumberOfVertices,2))
6320 {
6321 return lambda;
6322 }
6323 }
6324
6325 return -1;
6326 }
6327
AddEffectsOfForceGenerators(VECTORCH * positionPtr,VECTORCH * impulsePtr,int mass)6328 void AddEffectsOfForceGenerators(VECTORCH *positionPtr, VECTORCH *impulsePtr, int mass)
6329 {
6330 extern int NumActiveBlocks;
6331 extern DISPLAYBLOCK *ActiveBlockList[];
6332 int numOfObjects = NumActiveBlocks;
6333 while(numOfObjects)
6334 {
6335 DISPLAYBLOCK *objectPtr = ActiveBlockList[--numOfObjects];
6336 STRATEGYBLOCK *sbPtr = objectPtr->ObStrategyBlock;
6337
6338 if (sbPtr && sbPtr->I_SBtype==I_BehaviourFan)
6339 {
6340 FAN_BEHAV_BLOCK *fanPtr;
6341 fanPtr = (FAN_BEHAV_BLOCK*)sbPtr->SBdataptr;
6342
6343 if (fanPtr->wind_speed)
6344 {
6345 int mag;
6346 VECTORCH disp = sbPtr->DynPtr->Position;
6347 disp.vx -= positionPtr->vx;
6348 disp.vy -= positionPtr->vy;
6349 disp.vz -= positionPtr->vz;
6350
6351 mag = 16384 - Approximate3dMagnitude(&disp);
6352
6353 if (mag<0) continue;
6354 if(MagnitudeOfCrossProduct(&disp,&fanPtr->fan_wind_direction)>objectPtr->ObRadius+200) continue;
6355 mag=MUL_FIXED(MUL_FIXED(mag*32*4*32,fanPtr->wind_speed),NormalFrameTime)/mass;
6356
6357 impulsePtr->vx += MUL_FIXED(fanPtr->fan_wind_direction.vx,mag);
6358 impulsePtr->vy += MUL_FIXED(fanPtr->fan_wind_direction.vy,mag);
6359 impulsePtr->vz += MUL_FIXED(fanPtr->fan_wind_direction.vz,mag);
6360 }
6361 // PrintDebuggingText("Fan acting upon object %d\n",fanPtr->wind_speed);
6362 }
6363 }
6364 }
6365
6366 #endif
6367
6368
6369
GetNearestModuleTeleportPoint(MODULE * thisModulePtr,VECTORCH * positionPtr)6370 VECTORCH *GetNearestModuleTeleportPoint(MODULE* thisModulePtr, VECTORCH* positionPtr)
6371 {
6372 extern FARENTRYPOINTSHEADER *FALLP_EntryPoints;
6373 int numEps;
6374 FARENTRYPOINT *epList;
6375 FARENTRYPOINT *thisEp = (FARENTRYPOINT *)0;
6376 int tmIndex = thisModulePtr->m_aimodule->m_index;
6377 int distance = 0x7fffffff;
6378
6379 numEps = FALLP_EntryPoints[tmIndex].numEntryPoints;
6380 epList = FALLP_EntryPoints[tmIndex].entryPointsList;
6381
6382 while((numEps>0))
6383 {
6384 VECTORCH p = *positionPtr;
6385 int d;
6386
6387 p.vx -= thisModulePtr->m_aimodule->m_world.vx + epList->position.vx;
6388 p.vy -= thisModulePtr->m_aimodule->m_world.vy + epList->position.vy;
6389 p.vz -= thisModulePtr->m_aimodule->m_world.vz + epList->position.vz;
6390
6391 d = Approximate3dMagnitude(&p);
6392
6393 if (d<distance)
6394 {
6395 distance = d;
6396 thisEp = epList;
6397 }
6398
6399 epList++;
6400 numEps--;
6401 }
6402
6403 if(!thisEp)
6404 {
6405 return 0;
6406 }
6407 else
6408 {
6409 return &(thisEp->position);
6410 }
6411 }
6412