00001
00002 #include "ReVolt.h"
00003
00004 #include "TypeDefs.h"
00005 #include "Geom.h"
00006 #include "Particle.h"
00007 #include "NewColl.h"
00008 #include "Body.h"
00009 #ifndef _PSX
00010 #include "Main.h"
00011 #endif
00012 #include "Gaussian.h"
00013 #ifndef _PSX
00014 #include "spark.h"
00015 #endif
00016
00017 int NThisBodySparks = 0;
00018 int NThisBodySmoke = 0;
00019
00020 NEWBODY BDY_MassiveBody;
00021
00022 #if USE_DEBUG_ROUTINES
00023 REAL DEBUG_MaxImpulseMag = ZERO;
00024 REAL DEBUG_MaxAngImpulseMag = ZERO;
00025 #endif
00026
00028
00029
00030
00031 static int BuildThisBodyCollList(NEWBODY *body);
00032
00033
00035
00036
00037
00038 void SetBodyPos(NEWBODY *body, VEC *pos, MAT *mat);
00039 void InitBodyDefault(NEWBODY *body);
00040 void PostProcessBodyColls(NEWBODY *body);
00041 void RemoveBodyColl(NEWBODY *body, COLLINFO_BODY *collInfo);
00042 COLLINFO_BODY *AddBodyColl(NEWBODY *body, COLLINFO_BODY *newHead);
00043
00044
00045 int DetectHullPolyColls(NEWBODY *body1, NEWBODY *body2);
00046 int DetectConvexHullPolyColls(NEWBODY *body, NEWCOLLPOLY *collPoly);
00047 void BuildCollisionEquations3(NEWBODY *body, BIGMAT *eqns, BIGVEC *residual);
00048
00049
00051
00052
00053
00055
00056 void InitBodyDefault(NEWBODY *body)
00057 {
00058 body->Centre.Mass = ZERO;
00059 body->Centre.InvMass = ZERO;
00060
00061 body->Centre.Hardness = ZERO;
00062 body->Centre.Resistance = ZERO;
00063 body->Centre.Grip = ZERO;
00064 body->Centre.StaticFriction = ZERO;
00065 body->Centre.KineticFriction =ZERO;
00066 body->Centre.Gravity = Real(2000);
00067
00068 SetMatUnit(&body->BodyInertia);
00069 SetMatUnit(&body->BodyInvInertia);
00070
00071 SetBodyConvex(body);
00072 body->CollSkin.Convex = NULL;
00073 body->CollSkin.WorldConvex = NULL;
00074 body->CollSkin.OldWorldConvex = NULL;
00075 body->CollSkin.Sphere = NULL;
00076 body->CollSkin.WorldSphere = NULL;
00077 body->CollSkin.OldWorldSphere = NULL;
00078 body->CollSkin.CollPoly = NULL;
00079 body->CollSkin.NConvex = 0;
00080 body->CollSkin.NSpheres = 0;
00081 body->CollSkin.NCollPolys = 0;
00082 body->CollSkin.AllowWorldColls = TRUE;
00083 body->CollSkin.AllowObjColls = TRUE;
00084 SetBBox(&body->CollSkin.TightBBox, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO);
00085
00086 body->DefaultAngRes = ZERO;
00087 body->AngResMod = ONE;
00088 body->AngResistance = ZERO;
00089
00090 body->AllowSparks = FALSE;
00091 body->ScrapeMaterial = MATERIAL_NONE;
00092
00093 body->Banged = FALSE;
00094 body->BangMag = ZERO;
00095 SetPlane(&body->BangPlane, ZERO, -ONE, ZERO, ZERO);
00096
00097 }
00098
00099
00101
00102
00103
00105
00106 void SetBodyPos(NEWBODY *body, VEC *pos, MAT *mat)
00107 {
00108
00109
00110 CopyVec(pos, &body->Centre.Pos);
00111 CopyVec(&body->Centre.Pos, &body->Centre.OldPos);
00112 CopyMatrix(mat, &body->Centre.WMatrix);
00113 CopyMat(&body->Centre.WMatrix, &body->Centre.OldWMatrix);
00114 MatToQuat(&body->Centre.WMatrix, &body->Centre.Quat);
00115 CopyQuat(&body->Centre.Quat, &body->Centre.OldQuat);
00116
00117
00118 SetVecZero(&body->Centre.Vel);
00119 SetVecZero(&body->Centre.Impulse);
00120 SetVecZero(&body->Centre.LastVel);
00121 SetVecZero(&body->AngVel);
00122 SetVecZero(&body->LastAngVel);
00123 SetVecZero(&body->AngImpulse);
00124 SetVecZero(&body->Centre.Shift);
00125
00126
00127 GetFrameInertia(&body->BodyInvInertia, &body->Centre.WMatrix, &body->WorldInvInertia);
00128 BuildWorldSkin(&body->CollSkin, &body->Centre.Pos, &body->Centre.WMatrix);
00129
00130
00131 body->IsJittering = FALSE;
00132 body->JitterCount = 0;
00133 body->JitterFrames = 0;
00134
00135
00136 body->NoContactTime = ZERO;
00137 body->Centre.Boost = ZERO;
00138 body->LastScrapeTime = 0;
00139 body->ScrapeMaterial = MATERIAL_NONE;
00140 }
00141
00143
00144
00145
00146
00148
00149 void ApplyBodyImpulse(NEWBODY *body, VEC *impulse, VEC *impPos)
00150 {
00151 VEC angImpulse;
00152
00153
00154 ApplyParticleImpulse(&body->Centre, impulse);
00155
00156
00157 CalcAngImpulse(impulse, impPos, &angImpulse);
00158 ApplyBodyAngImpulse(body, &angImpulse);
00159 }
00160
00161
00163
00164
00165
00166
00168
00169 void UpdateBody(NEWBODY *body, REAL dt)
00170 {
00171 REAL scale;
00172 CONVEX *tmpConvex;
00173 SPHERE *tmpSphere;
00174 QUATERNION tmpQuat;
00175
00176
00177 #if USE_DEBUG_ROUTINES
00178
00179 REAL impMag;
00180 impMag = VecLen(&body->Centre.Impulse);
00181 if (impMag > DEBUG_MaxImpulseMag) DEBUG_MaxImpulseMag = impMag;
00182 impMag = VecLen(&body->AngImpulse);
00183 if (impMag > DEBUG_MaxAngImpulseMag) DEBUG_MaxAngImpulseMag = impMag;
00184
00185 CopyVec(&body->Centre.Impulse, &DEBUG_Impulse);
00186 CopyVec(&body->AngImpulse, &DEBUG_AngImpulse);
00187
00188 #endif
00189
00190
00191 CopyVec(&body->AngVel, &body->LastAngVel);
00192
00193
00194 #if REMOVE_JITTER
00195 if (body->IsJittering) {
00196 VecMulScalar(&body->AngImpulse, HALF);
00197 }
00198 #endif
00199
00200
00201 UpdateParticle(&body->Centre, dt);
00202
00203
00204 MatMulVec(&body->WorldInvInertia, &body->AngImpulse, &body->AngAcc);
00205
00206
00207 VecPlusEqVec(&body->AngVel, &body->AngAcc);
00208
00209
00210 scale = MulScalar(body->AngResistance, MulScalar(dt, FRICTION_TIME_SCALE));
00211 VecMulScalar(&body->AngVel, ONE - scale);
00212
00213
00214 VecMulQuat(&body->AngVel, &body->Centre.Quat, &tmpQuat);
00215 scale = MulScalar(HALF, dt);
00216 QuatPlusEqScalarQuat(&body->Centre.Quat, scale, &tmpQuat);
00217 NormalizeQuat(&body->Centre.Quat);
00218 QuatToMat(&body->Centre.Quat, &body->Centre.WMatrix);
00219
00220
00221 GetFrameInertia(&body->BodyInvInertia, &body->Centre.WMatrix, &body->WorldInvInertia);
00222
00223
00224 tmpConvex = body->CollSkin.WorldConvex;
00225 body->CollSkin.WorldConvex = body->CollSkin.OldWorldConvex;
00226 body->CollSkin.OldWorldConvex = tmpConvex;
00227 tmpSphere = body->CollSkin.WorldSphere;
00228 body->CollSkin.WorldSphere = body->CollSkin.OldWorldSphere;
00229 body->CollSkin.OldWorldSphere = tmpSphere;
00230 BuildWorldSkin(&body->CollSkin, &body->Centre.Pos, &body->Centre.WMatrix);
00231
00232
00233 #if REMOVE_JITTER
00234 body->JitterFrames++;
00235 if (VecDotVec(&body->AngVel, &body->LastAngVel) < ZERO) {
00236 if (body->JitterFrames < body->JitterFramesMax) {
00237 body->JitterCount++;
00238 } else {
00239 body->JitterCount = 0;
00240 body->IsJittering = FALSE;
00241 }
00242 body->JitterFrames = 0;
00243
00244 if (body->JitterCount > body->JitterCountMax) {
00245 body->IsJittering = TRUE;
00246 }
00247 } else if (body->IsJittering) {
00248 if (body->JitterFrames > body->JitterFramesMax) {
00249 body->IsJittering = FALSE;
00250 }
00251 }
00252 #endif
00253
00254
00255 if (body->NWorldContacts == 0) {
00256 body->NoContactTime += dt;
00257 } else {
00258 body->NoContactTime = ZERO;
00259 }
00260
00261
00262 SetVecZero(&body->AngImpulse);
00263 }
00264
00265
00267
00268
00269
00271
00272 void BodyPointVel(NEWBODY *body, VEC *dR, VEC *vel)
00273 {
00274 VecCrossVec(&body->AngVel, dR, vel);
00275 VecPlusEqVec(vel, &body->Centre.Vel);
00276 }
00277
00278
00280
00281
00282
00283
00285
00286 void SetupMassiveBody()
00287 {
00288 SetVecZero(&BDY_MassiveBody.Centre.Pos);
00289 SetVecZero(&BDY_MassiveBody.Centre.OldPos);
00290 SetVecZero(&BDY_MassiveBody.Centre.Vel);
00291 SetVecZero(&BDY_MassiveBody.Centre.OldPos);
00292 SetVecZero(&BDY_MassiveBody.Centre.Acc);
00293 SetVecZero(&BDY_MassiveBody.Centre.Impulse);
00294 SetQuatUnit(&BDY_MassiveBody.Centre.Quat);
00295 SetQuatUnit(&BDY_MassiveBody.Centre.OldQuat);
00296 SetMatUnit(&BDY_MassiveBody.Centre.WMatrix);
00297 SetMatUnit(&BDY_MassiveBody.Centre.OldWMatrix);
00298 SetVecZero(&BDY_MassiveBody.Centre.Shift);
00299
00300 BDY_MassiveBody.Centre.Mass = ZERO;
00301 BDY_MassiveBody.Centre.InvMass = ZERO;
00302 SetMatZero(&BDY_MassiveBody.BodyInertia);
00303 SetMatZero(&BDY_MassiveBody.BodyInvInertia);
00304 SetMatZero(&BDY_MassiveBody.WorldInvInertia);
00305
00306 BDY_MassiveBody.Centre.StaticFriction = ONE;
00307 BDY_MassiveBody.Centre.KineticFriction = ONE;
00308 BDY_MassiveBody.Centre.Hardness = ZERO;
00309 BDY_MassiveBody.Centre.Resistance = ZERO;
00310 BDY_MassiveBody.Centre.Gravity = ZERO;
00311
00312 SetVecZero(&BDY_MassiveBody.AngVel);
00313 SetVecZero(&BDY_MassiveBody.AngAcc);
00314 SetVecZero(&BDY_MassiveBody.AngImpulse);
00315
00316 BDY_MassiveBody.CollSkin.Convex = NULL;
00317 BDY_MassiveBody.CollSkin.WorldConvex = NULL;
00318 BDY_MassiveBody.CollSkin.OldWorldConvex = NULL;
00319 BDY_MassiveBody.CollSkin.Sphere = NULL;
00320 BDY_MassiveBody.CollSkin.WorldSphere = NULL;
00321 BDY_MassiveBody.CollSkin.OldWorldSphere = NULL;
00322 BDY_MassiveBody.CollSkin.NConvex = 0;
00323 BDY_MassiveBody.CollSkin.NSpheres = 0;
00324 }
00325
00326
00328
00329
00330
00331
00333
00334 void SetBodyInertia(NEWBODY *body, MAT *inertia)
00335 {
00336 CopyMat(inertia, &body->BodyInertia);
00337 CopyMat(inertia, &body->BodyInvInertia);
00338 InvertMat(&body->BodyInvInertia);
00339 }
00340
00342
00343
00344
00345
00347
00348 void GetFrameInertia(MAT *bodyInvInertia, MAT *transform, MAT *worldInvInertia)
00349 {
00350 MAT tmpMat;
00351
00352 TransMatMulMat(transform, bodyInvInertia, &tmpMat);
00353 MatMulMat(&tmpMat, transform, worldInvInertia);
00354
00355 }
00356
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00370
00371 void BuildOneBodyColMat(NEWBODY *body, VEC *colPos, VEC *colPos2, MAT *colMat)
00372 {
00373
00374 MAT workMat;
00375
00376 VecCrossMat(colPos, &body->WorldInvInertia, &workMat);
00377 MatCrossVec(&workMat, colPos2, colMat);
00378
00379 colMat->m[XX] = body->Centre.InvMass - colMat->m[XX];
00380 colMat->m[XY] = -colMat->m[XY];
00381 colMat->m[XZ] = -colMat->m[XZ];
00382
00383 colMat->m[YX] = -colMat->m[YX];
00384 colMat->m[YY] = body->Centre.InvMass - colMat->m[YY];
00385 colMat->m[YZ] = -colMat->m[YZ];
00386
00387 colMat->m[ZX] = -colMat->m[ZX];
00388 colMat->m[ZY] = -colMat->m[ZY];
00389 colMat->m[ZZ] = body->Centre.InvMass - colMat->m[ZZ];
00390
00391 }
00392
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00406
00407 void BuildTwoBodyColMat(NEWBODY *body1, NEWBODY *body2, VEC *colPos1, VEC *relPos1, VEC *colPos2, VEC *relPos2, MAT *colMat)
00408 {
00409 MAT workMat1, workMat2;
00410
00411
00412 VecCrossMat(relPos1, &body1->WorldInvInertia, &workMat1);
00413 MatCrossVec(&workMat1, colPos1, colMat);
00414 VecCrossMat(relPos2, &body2->WorldInvInertia, &workMat1);
00415 MatCrossVec(&workMat1, colPos2, &workMat2);
00416 MatPlusEqMat(colMat, &workMat2);
00417
00418
00419 colMat->m[XX] = body1->Centre.InvMass + body2->Centre.InvMass - colMat->m[XX];
00420 colMat->m[XY] = -colMat->m[XY];
00421 colMat->m[XZ] = -colMat->m[XZ];
00422
00423 colMat->m[YX] = -colMat->m[YX];
00424 colMat->m[YY] = body1->Centre.InvMass + body2->Centre.InvMass - colMat->m[YY];
00425 colMat->m[YZ] = -colMat->m[YZ];
00426
00427 colMat->m[ZX] = -colMat->m[ZX];
00428 colMat->m[ZY] = -colMat->m[ZY];
00429 colMat->m[ZZ] = body1->Centre.InvMass + body2->Centre.InvMass - colMat->m[ZZ];
00430 }
00431
00432
00434
00435
00436
00437
00439
00440 REAL OneBodyZeroFrictionImpulse(NEWBODY *body,
00441 VEC *pos,
00442 VEC *normal,
00443 REAL deltaVel)
00444 {
00445 REAL impMag;
00446 VEC tmpVec1, tmpVec2;
00447
00448 VecCrossVec(pos, normal, &tmpVec1);
00449 MatMulVec(&body->WorldInvInertia, &tmpVec1, &tmpVec2);
00450 VecCrossVec(&tmpVec2, pos, &tmpVec1);
00451 impMag = body->Centre.InvMass + VecDotVec(&tmpVec1, normal);
00452
00453 return DivScalar(deltaVel, impMag);
00454
00455 }
00456
00457 void TwoBodyZeroFrictionImpulse(NEWBODY *body1, NEWBODY *body2,
00458 VEC *pos1, VEC *pos2,
00459 VEC *normal,
00460 REAL deltaVel,
00461 VEC *impulse)
00462 {
00463 REAL impMag;
00464 VEC tmpVec1, tmpVec2;
00465
00466 VecCrossVec(pos1, normal, &tmpVec1);
00467 MatMulVec(&body1->WorldInvInertia, &tmpVec1, &tmpVec2);
00468 VecCrossVec(&tmpVec2, pos1, &tmpVec1);
00469 impMag = body1->Centre.InvMass + VecDotVec(&tmpVec1, normal);
00470
00471 VecCrossVec(pos2, normal, &tmpVec1);
00472 MatMulVec(&body2->WorldInvInertia, &tmpVec1, &tmpVec2);
00473 VecCrossVec(&tmpVec2, pos2, &tmpVec1);
00474 impMag += body2->Centre.InvMass + VecDotVec(&tmpVec1, normal);
00475
00476 impMag = DivScalar(deltaVel, impMag);
00477
00478 VecEqScalarVec(impulse, impMag, normal);
00479
00480 }
00481
00482
00484
00485
00486
00487
00489
00490 void PreProcessBodyColls(NEWBODY *body)
00491 {
00492 bool keepGoing;
00493 VEC dR, dRW;
00494 REAL n1Dotn2, shiftMod;
00495 REAL dRLenSq, dRWLenSq;
00496 VEC *collPos1, *collPos2;
00497 REAL collDepth1;
00498 COLLINFO_BODY *collInfo1, *collInfo2;
00499
00500
00501 for (collInfo1 = body->BodyCollHead; collInfo1 != NULL; collInfo1 = collInfo1->Next) {
00502
00503 collPos1 = &collInfo1->Pos1;
00504 collDepth1 = collInfo1->Depth;
00505
00506 if (VecDotVec(&body->Centre.Shift, PlaneNormal(&collInfo1->Plane)) > -collDepth1) {
00507 RemoveBodyColl(body, collInfo1);
00508 continue;
00509 }
00510 }
00511
00512 collInfo1 = body->BodyCollHead;
00513 while (collInfo1 != NULL) {
00514
00515 collPos1 = &collInfo1->Pos1;
00516 collDepth1 = collInfo1->Depth;
00517
00518
00519 if (collInfo1->Depth < ZERO) {
00520
00521 shiftMod = collInfo1->Body1->Centre.InvMass + collInfo1->Body2->Centre.InvMass;
00522 if (shiftMod > SMALL_REAL) {
00523 shiftMod = collInfo1->Body1->Centre.InvMass / shiftMod;
00524 } else {
00525 shiftMod = ZERO;
00526 }
00527 ModifyShift(&body->Centre.Shift, -shiftMod * collDepth1, PlaneNormal(&collInfo1->Plane));
00528 }
00529
00530
00531 collInfo2 = collInfo1->Next;
00532 keepGoing = TRUE;
00533 while ((collInfo2 != NULL) && keepGoing) {
00534
00535 collPos2 = &collInfo2->Pos1;
00536
00537 VecMinusVec(collPos1, collPos2, &dR);
00538 dRLenSq = VecDotVec(&dR, &dR);
00539 VecMinusVec(&collInfo1->WorldPos, &collInfo2->WorldPos, &dRW);
00540 dRWLenSq = VecDotVec(&dRW, &dRW);
00541 n1Dotn2 = VecDotVec(PlaneNormal(&collInfo1->Plane), PlaneNormal(&collInfo2->Plane));
00542
00543 if (dRLenSq < CLOSE_BODY_COLL) {
00544 if (collInfo1->Depth < collInfo2->Depth) {
00545 RemoveBodyColl(body, collInfo2);
00546 } else {
00547 RemoveBodyColl(body, collInfo1);
00548 keepGoing = FALSE;
00549 }
00550 COL_NBodyDone++;
00551 }
00552 collInfo2 = collInfo2->Next;
00553 }
00554 collInfo1 = collInfo1->Next;
00555 }
00556
00557
00558
00559 }
00560
00561
00563
00564
00565
00566
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00600
00601
00602
00603
00605 #ifndef _PSX
00606 void BuildCollisionEquations(NEWBODY *body, COLLINFO_BODY **collInfoList, int nColls, BIGMAT *eqns, BIGVEC *residual)
00607 {
00608 int iColl, iColl2, iEqn, iImp, iImp2;
00609 int nEqns;
00610 REAL dVelNorm;
00611 VEC tmpVec, tmpVec2;
00612 MAT collAxes, collMat;
00613 COLLINFO_BODY *collInfo, *collInfo2;
00614
00615
00616 nEqns = 3 * nColls;
00617
00618
00619 SetBigMatSize(eqns, nEqns, nEqns);
00620 SetBigVecSize(residual, nEqns);
00621 ClearBigMat(eqns);
00622
00623
00624 iEqn = 0;
00625 for (iColl = 0; iColl < nColls; iColl++) {
00626 iImp = 3 * iColl;
00627 collInfo = collInfoList[iColl];
00628
00629
00630 CopyVec(PlaneNormal(&collInfo->Plane), &collAxes.mv[U]);
00631 BuildMatrixFromUp(&collAxes);
00632
00633
00634 eqns->m[iEqn][X + iImp] = collAxes.m[RX];
00635 eqns->m[iEqn][Y + iImp] = collAxes.m[RY];
00636 eqns->m[iEqn][Z + iImp] = collAxes.m[RZ];
00637 residual->v[iEqn] = ZERO;
00638 iEqn++;
00639
00640
00641 eqns->m[iEqn][X + iImp] = collAxes.m[LX];
00642 eqns->m[iEqn][Y + iImp] = collAxes.m[LY];
00643 eqns->m[iEqn][Z + iImp] = collAxes.m[LZ];
00644 residual->v[iEqn] = ZERO;
00645 iEqn++;
00646
00647
00648 for (iColl2 = 0; iColl2 < nColls; iColl2++) {
00649 iImp2 = 3 * iColl2;
00650 collInfo2 = collInfoList[iColl2];
00651 BuildOneBodyColMat(body, &collInfo->Pos1, &collInfo2->Pos1, &collMat);
00652
00653 eqns->m[iEqn][X + iImp2] = collMat.m[XX] * collAxes.m[UX] + collMat.m[YX] * collAxes.m[UY] + collMat.m[ZX] * collAxes.m[UZ];
00654 eqns->m[iEqn][Y + iImp2] = collMat.m[XY] * collAxes.m[UX] + collMat.m[YY] * collAxes.m[UY] + collMat.m[ZY] * collAxes.m[UZ];
00655 eqns->m[iEqn][Z + iImp2] = collMat.m[XZ] * collAxes.m[UX] + collMat.m[YZ] * collAxes.m[UY] + collMat.m[ZZ] * collAxes.m[UZ];
00656 }
00657 residual->v[iEqn] = -(ONE + collInfo->Restitution) * VecDotVec(&collInfo->Vel, &collAxes.mv[U]);
00658
00659 VecCrossVec(&body->AngImpulse, &collInfo->Pos1, &tmpVec);
00660 MatMulVec(&body->WorldInvInertia, &tmpVec, &tmpVec2);
00661 VecPlusEqScalarVec(&tmpVec2, body->Centre.InvMass, &body->Centre.Impulse);
00662 dVelNorm = VecDotVec(PlaneNormal(&collInfo->Plane), &tmpVec2);
00663 if (dVelNorm < residual->v[iEqn]) {
00664 residual->v[iEqn] -= dVelNorm;
00665 } else {
00666 residual->v[iEqn] = ZERO;
00667 }
00668 iEqn++;
00669 }
00670 }
00671 #endif
00672
00673 #ifndef _PSX
00674 void BuildCollisionEquations2(NEWBODY *body, COLLINFO_BODY **collInfoList, int nColls, BIGMAT *eqns, BIGVEC *residual)
00675 {
00676 int iColl, iColl2, iEqn, iImp, iImp2;
00677 int nEqns;
00678 MAT collMat;
00679 COLLINFO_BODY *collInfo, *collInfo2;
00680
00681
00682 nEqns = 3 * nColls;
00683
00684
00685 SetBigMatSize(eqns, nEqns, nEqns);
00686 SetBigVecSize(residual, nEqns);
00687 ClearBigMat(eqns);
00688
00689
00690 iEqn = 0;
00691 for (iColl = 0; iColl < nColls; iColl++) {
00692 iImp = 3 * iColl;
00693 iEqn = 3 * iColl;
00694 collInfo = collInfoList[iColl];
00695
00696
00697 for (iColl2 = 0; iColl2 < nColls; iColl2++) {
00698 iImp2 = 3 * iColl2;
00699 collInfo2 = collInfoList[iColl2];
00700 BuildOneBodyColMat(body, &collInfo->Pos1, &collInfo2->Pos1, &collMat);
00701
00702 eqns->m[iEqn][0 + iImp2] = collMat.m[XX];
00703 eqns->m[iEqn][1 + iImp2] = collMat.m[XY];
00704 eqns->m[iEqn][2 + iImp2] = collMat.m[XZ];
00705 residual->v[iEqn] = -(ONE + collInfo->Restitution) * collInfo->Vel.v[X];
00706
00707 eqns->m[iEqn + 1][0 + iImp2] = collMat.m[YX];
00708 eqns->m[iEqn + 1][1 + iImp2] = collMat.m[YY];
00709 eqns->m[iEqn + 1][2 + iImp2] = collMat.m[YZ];
00710 residual->v[iEqn + 1] = -(ONE + collInfo->Restitution) * collInfo->Vel.v[Y];
00711
00712 eqns->m[iEqn + 2][0 + iImp2] = collMat.m[ZX];
00713 eqns->m[iEqn + 2][1 + iImp2] = collMat.m[ZY];
00714 eqns->m[iEqn + 2][2 + iImp2] = collMat.m[ZZ];
00715 residual->v[iEqn + 2] = -(ONE + collInfo->Restitution) * collInfo->Vel.v[Z];
00716 }
00717 }
00718 }
00719 #endif
00720
00721 void BuildCollisionEquations3(NEWBODY *body, BIGMAT *eqns, BIGVEC *residual)
00722 {
00723 int iColl, iColl2, iEqn;
00724 REAL dVelNorm, tReal;
00725 VEC tmpVec, tmpVec2;
00726 MAT collMat;
00727 COLLINFO_BODY *collInfo, *collInfo2;
00728 int nColls = body->NBodyColls;
00729
00730
00731 SetBigMatSize(eqns, nColls, nColls);
00732 SetBigVecSize(residual, nColls);
00733 ClearBigMat(eqns);
00734
00735 iEqn = 0;
00736 collInfo = body->BodyCollHead;
00737 for (iColl = 0; iColl < nColls; iColl++) {
00738 Assert(collInfo != NULL);
00739
00740
00741 collInfo2 = body->BodyCollHead;
00742 for (iColl2 = 0; iColl2 < nColls; iColl2++) {
00743 Assert(collInfo2 != NULL);
00744
00745 if (iColl2 == iColl) {
00746 BuildTwoBodyColMat(collInfo->Body1, collInfo->Body2, &collInfo->Pos1, &collInfo2->Pos1, &collInfo->Pos2, &collInfo2->Pos2, &collMat);
00747 } else {
00748 if (body == collInfo->Body1) {
00749 BuildOneBodyColMat(collInfo->Body1, &collInfo->Pos1, &collInfo2->Pos1, &collMat);
00750 } else {
00751 BuildOneBodyColMat(collInfo->Body2, &collInfo->Pos2, &collInfo2->Pos2, &collMat);
00752 }
00753 }
00754 tReal =
00755 MulScalar(collMat.m[XX], collInfo2->Plane.v[X]) +
00756 MulScalar(collMat.m[XY], collInfo2->Plane.v[Y]) +
00757 MulScalar(collMat.m[XZ], collInfo2->Plane.v[Z]);
00758 eqns->m[iEqn][iColl2] = MulScalar(collInfo->Plane.v[X], tReal);
00759 tReal =
00760 MulScalar(collMat.m[YX], collInfo2->Plane.v[X]) +
00761 MulScalar(collMat.m[YY], collInfo2->Plane.v[Y]) +
00762 MulScalar(collMat.m[YZ], collInfo2->Plane.v[Z]);
00763 eqns->m[iEqn][iColl2] += MulScalar(collInfo->Plane.v[Y], tReal);
00764 tReal =
00765 MulScalar(collMat.m[ZX], collInfo2->Plane.v[X]) +
00766 MulScalar(collMat.m[ZY], collInfo2->Plane.v[Y]) +
00767 MulScalar(collMat.m[ZZ], collInfo2->Plane.v[Z]);
00768 eqns->m[iEqn][iColl2] += MulScalar(collInfo->Plane.v[Z], tReal);
00769
00770 collInfo2 = collInfo2->Next;
00771 }
00772 residual->v[iEqn] = -MulScalar((ONE + collInfo->Restitution), VecDotVec(&collInfo->Vel, PlaneNormal(&collInfo->Plane)));
00773
00774 VecCrossVec(&body->AngImpulse, &collInfo->Pos1, &tmpVec);
00775 MatMulVec(&body->WorldInvInertia, &tmpVec, &tmpVec2);
00776 VecPlusEqScalarVec(&tmpVec2, body->Centre.InvMass, &body->Centre.Impulse);
00777 dVelNorm = VecDotVec(PlaneNormal(&collInfo->Plane), &tmpVec2);
00778 if (dVelNorm < residual->v[iEqn]) {
00779 residual->v[iEqn] -= dVelNorm;
00780 } else {
00781 residual->v[iEqn] = ZERO;
00782 }
00783 iEqn++;
00784
00785 collInfo = collInfo->Next;
00786 }
00787 }
00788
00789
00790
00792
00793
00794
00796
00797 static BIGVEC Soln;
00798 static BIGMAT Coefficients;
00799 static BIGVEC Residual;
00800
00801 #if DEBUG_SOLVER
00802 static BIGMAT OrigCoefs;
00803 static BIGVEC OrigRes, NewRes;
00804 #endif
00805
00806 #if USE_DEBUG_ROUTINES
00807 int DEBUG_NIts = 0;
00808 bool DEBUG_Converged = TRUE;
00809 REAL DEBUG_Res = ZERO;
00810 #endif
00811
00812
00813
00814 void ProcessBodyColls3(NEWBODY *body)
00815 {
00816 int iColl, nIts, maxIts;
00817 REAL res, tol, knock;
00818 VEC tmpVec, collImpulse;
00819 VEC totImpulse = {ZERO, ZERO, ZERO};
00820 VEC totAngImpulse = {ZERO, ZERO, ZERO};
00821 COLLINFO_BODY *collInfo;
00822 #if DEBUG_SOLVER && FALSE
00823 char buf[256];
00824 #endif
00825
00826
00827 BuildCollisionEquations3(body, &Coefficients, &Residual);
00828
00829
00830 SetBigVecSize(&Soln, body->NBodyColls);
00831
00832 #if DEBUG_SOLVER
00833
00834 CopyBigMat(&Coefficients, &OrigCoefs);
00835 CopyBigVec(&Residual, &OrigRes);
00836 SetBigVecSize(&NewRes, body->NBodyColls);
00837 #endif
00838
00839
00840 maxIts = 5;
00841 tol = Real(0.001);
00842 if (body->NBodyColls > 1) {
00843 ConjGrad(&Coefficients, &Residual, tol, maxIts, &Soln, &res, &nIts);
00844 } else {
00845 Soln.v[0] = DivScalar(Residual.v[0], Coefficients.m[0][0]);
00846 res = ZERO;
00847 }
00848
00849 #if USE_DEBUG_ROUTINES
00850 DEBUG_NIts = nIts;
00851 DEBUG_Converged = TRUE;
00852 #endif
00853
00854
00855 if (abs(res) > 1000 * tol) {
00856
00857 #if DEBUG_SOLVER && defined(wsprintf) && (FALSE)
00858
00859 int ii, jj;
00860 wsprintf(buf, "\nCollision equations not converged\n");
00861 WriteLogEntry(buf);
00862 wsprintf(buf, "res = %d; tol = %d; its = %d\n\n", (int)(1.0e6 * res), (int)(1.0e6 * tol), nIts);
00863 WriteLogEntry(buf);
00864 for (ii = 0; ii < NRows(&OrigCoefs); ii++) {
00865 WriteLogEntry("| ");
00866 for (jj = 0; jj < NRows(&OrigCoefs); jj++) {
00867 wsprintf(buf, "%8d ", (int)(1.0e6 * OrigCoefs.m[ii][jj]));
00868 WriteLogEntry(buf);
00869 }
00870 wsprintf(buf, "| | %8d | %s | %8d |\n",
00871 (int)(1.0e6 * Soln.v[ii]),
00872 (ii == NRows(&OrigCoefs) / 2)? " = ": " ",
00873 (int)(1.0e6 * OrigRes.v[ii]));
00874 WriteLogEntry(buf);
00875 }
00876
00877 #endif
00878 #if USE_DEBUG_ROUTINES
00879
00880 DEBUG_Converged = FALSE;
00881 DEBUG_Res = res;
00882 #endif
00883 return;
00884
00885 } else {
00886
00887 #if USE_DEBUG_ROUTINES
00888 DEBUG_Converged = TRUE;
00889 #endif
00890
00891 }
00892
00893
00894 NThisBodySparks = 0;
00895 NThisBodySmoke = 0;
00896 body->Banged = TRUE;
00897
00898 collInfo = body->BodyCollHead;
00899 for (iColl = 0; iColl < body->NBodyColls; iColl++) {
00900 Assert(collInfo != NULL);
00901
00902
00903 if (body == collInfo->Body1) {
00904 VecEqScalarVec(&collImpulse, Soln.v[iColl], PlaneNormal(&collInfo->Plane));
00905 } else {
00906 VecEqScalarVec(&collImpulse, -Soln.v[iColl], PlaneNormal(&collInfo->Plane));
00907 }
00908
00909
00910 AddBodyFriction(body, &collImpulse, collInfo);
00911
00912
00913 VecPlusEqVec(&totImpulse, &collImpulse);
00914 CalcAngImpulse(&collImpulse, &collInfo->Pos1, &tmpVec);
00915 VecPlusEqVec(&totAngImpulse, &tmpVec);
00916
00917
00918 knock = MulScalar(abs(Soln.v[iColl]), body->Centre.InvMass);
00919 if (knock > body->BangMag) {
00920 body->BangMag = knock;
00921 CopyPlane(&collInfo->Plane, &body->BangPlane);
00922 }
00923
00924 collInfo = collInfo->Next;
00925 }
00926
00927
00928 ApplyBodyAngImpulse(body, &totAngImpulse);
00929 ApplyParticleImpulse(&body->Centre, &totImpulse);
00930
00931 }
00932
00933
00935
00936
00937
00938
00940
00941 void AddBodyFriction(NEWBODY *body, VEC *impulse, COLLINFO_BODY *collInfo)
00942 {
00943 REAL impDotNorm, velDotNorm, velTanLen, impTanLen, impTanMax, impTanMod;
00944 VEC impTan, velTan, sparkVel;
00945
00946 impDotNorm = VecDotVec(impulse, PlaneNormal(&collInfo->Plane));
00947 if (impDotNorm < ZERO) {
00948 return;
00949 }
00950 velDotNorm = VecDotVec(&collInfo->Vel, PlaneNormal(&collInfo->Plane));
00951 VecPlusScalarVec(&collInfo->Vel, -velDotNorm, PlaneNormal(&collInfo->Plane), &velTan);
00952
00953
00954 velTanLen = Length(&velTan);
00955
00956
00957 #ifndef _PSX
00958 if ((collInfo->Material != NULL) &&
00959 (velTanLen > MIN_SPARK_VEL) &&
00960 BodyAllowsSparks(body))
00961 {
00962 body->ScrapeMaterial = collInfo->Material - COL_MaterialInfo;
00963 body->LastScrapeTime = ZERO;
00964
00965 if (MaterialAllowsSparks(collInfo->Material) &&
00966 (NThisBodySparks < MAX_SPARKS_PER_BODY) &&
00967 (frand(ONE) < SparkProbability(velTanLen)))
00968 {
00969 NThisBodySparks++;
00970 #ifdef _PC
00971 VecEqScalarVec(&sparkVel, -HALF, &velTan);
00972 #endif
00973 #ifdef _N64
00974 VecEqScalarVec(&sparkVel, -0.1, &velTan);
00975 #endif
00976 CreateSpark(SPARK_SPARK, &collInfo->WorldPos, &sparkVel, HALF * velTanLen, 0);
00977 }
00978 }
00979 #endif
00980
00981
00982
00983 impTanLen = MulScalar(body->Centre.Grip, impDotNorm);
00984 CopyVec(&velTan, &impTan);
00985 VecMulScalar(&impTan, -impTanLen);
00986 impTanLen = MulScalar(impTanLen, velTanLen);
00987
00988
00989 impTanMax = MulScalar(MulScalar(HALF, TimeStep), MulScalar(body->Centre.Mass, body->Centre.Gravity));
00990 if (impTanLen > impTanMax) {
00991 impTanMod = DivScalar(impTanMax, impTanLen);
00992
00993 VecMulScalar(&impTan, impTanMod);
00994
00995 impTanLen = impTanMax;
00996
00997 }
00998 impTanMax = MulScalar(collInfo->StaticFriction, impDotNorm);
00999 if (impTanLen > impTanMax) {
01000 impTanMod = DivScalar(MulScalar(collInfo->KineticFriction, impDotNorm), impTanLen);
01001
01002 VecMulScalar(&impTan, impTanMod);
01003 }
01004
01005 VecPlusEqVec(impulse, &impTan);
01006 }
01007
01008
01009
01011
01012
01013
01014
01016
01017 void DetectBodyWorldColls(NEWBODY *body)
01018 {
01019 long iPoly;
01020 long nCollPolys;
01021 COLLGRID *collGrid;
01022
01023 #ifndef _PSX
01024 NEWCOLLPOLY **collPolyPtr;
01025 #endif
01026 NEWCOLLPOLY *collPoly;
01027
01028
01029 collGrid = PosToCollGrid(&body->Centre.Pos);
01030 if (collGrid == NULL) return;
01031
01032 #ifndef _PSX
01033 collPolyPtr = collGrid->CollPolyPtr;
01034 #endif
01035 nCollPolys = collGrid->NCollPolys;
01036
01037 for (iPoly = 0; iPoly < nCollPolys; iPoly++) {
01038
01039 #ifndef _PSX
01040 collPoly = collPolyPtr[iPoly];
01041 #else
01042 collPoly = &COL_WorldCollPoly[collGrid->CollPolyIndices[iPoly]];
01043 #endif
01044
01045 if (PolyCameraOnly(collPoly)) continue;
01046
01047
01048 DetectBodyPolyColls(body, collPoly);
01049
01050 }
01051 }
01052
01054
01055
01056
01057
01059
01060 void DetectBodyPolyColls(NEWBODY *body, NEWCOLLPOLY *collPoly)
01061 {
01062 DetectConvexHullPolyColls(body, collPoly);
01063 }
01064
01065 #ifdef _PSX
01066 extern int NPassed;
01067 #endif
01068 int DetectConvexHullPolyColls(NEWBODY *body, NEWCOLLPOLY *collPoly)
01069 {
01070 int iSphere;
01071 VERTEX *oldPos, *newPos;
01072 COLLINFO_BODY *collInfo;
01073 int nColls = 0;
01074
01075
01076 if (!BBTestYXZ(&collPoly->BBox, &body->CollSkin.BBox)) return 0;
01077
01078 #ifdef _PSX
01079 NPassed++;
01080 #endif
01081
01082
01083 for (iSphere = 0; iSphere < body->CollSkin.NSpheres; iSphere++) {
01084
01085
01086 if ((collInfo = NextBodyCollInfo()) == NULL) return nColls;
01087
01088 oldPos = &body->CollSkin.OldWorldSphere[iSphere].Pos;
01089 newPos = &body->CollSkin.WorldSphere[iSphere].Pos;
01090
01091
01092 if (!SphereCollPoly(oldPos, newPos, body->CollSkin.WorldSphere[iSphere].Radius, collPoly, &collInfo->Plane, &collInfo->Pos1, &collInfo->WorldPos, &collInfo->Depth, &collInfo->Time)) {
01093 continue;
01094 }
01095 VecPlusEqVec(&collInfo->Pos1, newPos);
01096 VecMinusEqVec(&collInfo->Pos1, &body->Centre.Pos);
01097
01098
01099 VecCrossVec(&body->AngVel, &collInfo->Pos1, &collInfo->Vel);
01100 VecPlusEqVec(&collInfo->Vel, &body->Centre.Vel);
01101 if (VecDotVec(&collInfo->Vel, PlaneNormal(&collPoly->Plane)) >= ZERO) {
01102 continue;
01103 }
01104
01105
01106
01107 collInfo->Body1 = body;
01108 collInfo->Body2 = &BDY_MassiveBody;
01109 SetVecZero(&collInfo->Pos2);
01110 CopyPlane(&collPoly->Plane, &collInfo->Plane);
01111 collInfo->Grip = MulScalar(body->Centre.Grip, COL_MaterialInfo[collPoly->Material].Gripiness);
01112 collInfo->StaticFriction = MulScalar(body->Centre.StaticFriction, COL_MaterialInfo[collPoly->Material].Roughness);
01113 collInfo->KineticFriction = MulScalar(body->Centre.KineticFriction, COL_MaterialInfo[collPoly->Material].Roughness);
01114 collInfo->Restitution = MulScalar(body->Centre.Hardness, COL_MaterialInfo[collPoly->Material].Hardness);
01115 collInfo->Material = &COL_MaterialInfo[collPoly->Material];
01116 if (abs(VecDotVec(PlaneNormal(&collInfo->Plane), &DownVec)) < 0.15f) {
01117 collInfo->StaticFriction = MulScalar(Real(0.1), collInfo->StaticFriction);
01118 collInfo->KineticFriction = MulScalar(Real(0.1), collInfo->KineticFriction);
01119 collInfo->Restitution = collInfo->Restitution + 0.1f;
01120 }
01121
01122
01123 AdjustBodyColl(collInfo, collInfo->Material);
01124
01125 AddBodyColl(body, collInfo);
01126 nColls++;
01127
01128 }
01129
01130 return nColls;
01131 }
01132
01133
01134
01136
01137
01138
01140
01141 int DetectBodyBodyColls(NEWBODY *body1, NEWBODY *body2)
01142 {
01143
01144 if (IsBodyConvex(body1)) {
01145 if (IsBodyPoly(body2)) {
01146
01147 return DetectHullPolyColls(body1, body2);
01148
01149 } else if (IsBodySphere(body2)) {
01150
01151 return DetectHullHullColls(body2, body1);
01152
01153 } else if (IsBodyConvex(body2)) {
01154
01155 return DetectHullHullColls(body1, body2);
01156
01157 }
01158 }
01159 else if (IsBodySphere(body1)) {
01160 if (IsBodyPoly(body2)) {
01161
01162 return DetectHullPolyColls(body1, body2);
01163
01164 } else if (IsBodySphere(body2)) {
01165
01166 return DetectSphereSphereColls(body1, body2);
01167
01168 } else if (IsBodyConvex(body2)) {
01169
01170 return DetectHullHullColls(body1, body2);
01171
01172 }
01173 }
01174 else if (IsBodyPoly(body1)) {
01175 if (IsBodyPoly(body2)) {
01176
01177 return 0;
01178
01179 } else if (IsBodySphere(body2)) {
01180
01181 return DetectHullPolyColls(body2, body1);
01182
01183 } else if (IsBodyConvex(body2)) {
01184
01185 return DetectHullPolyColls(body2, body1);
01186
01187 }
01188 }
01189
01190 return 0;
01191
01192 }
01193
01194 int DetectHullPolyColls(NEWBODY *body1, NEWBODY *body2)
01195 {
01196 int iSphere, iPoly;
01197 VERTEX *oldPos, *newPos;
01198 COLLINFO_BODY *collInfo;
01199 NEWCOLLPOLY *collPoly;
01200 int nColls = 0;
01201
01202 Assert(IsBodyPoly(body2) && !IsBodyPoly(body1));
01203
01204 if (!BBTestYXZ(&body1->CollSkin.BBox, &body2->CollSkin.BBox)) return 0;
01205
01206 for (iPoly = 0; iPoly < body2->CollSkin.NCollPolys; iPoly++) {
01207 collPoly = &body2->CollSkin.CollPoly[iPoly];
01208
01209
01210 if (!BBTestYXZ(&collPoly->BBox, &body1->CollSkin.BBox)) continue;
01211
01212
01213 for (iSphere = 0; iSphere < body1->CollSkin.NSpheres; iSphere++) {
01214
01215 if ((collInfo = NextBodyCollInfo()) == NULL) return nColls;
01216
01217 oldPos = &body1->CollSkin.OldWorldSphere[iSphere].Pos;
01218 newPos = &body1->CollSkin.WorldSphere[iSphere].Pos;
01219
01220
01221 if (!SphereCollPoly(oldPos, newPos, body1->CollSkin.WorldSphere[iSphere].Radius, collPoly, &collInfo->Plane, &collInfo->Pos1, &collInfo->WorldPos, &collInfo->Depth, &collInfo->Time)) {
01222 continue;
01223 }
01224 VecPlusEqVec(&collInfo->Pos1, newPos);
01225 VecMinusEqVec(&collInfo->Pos1, &body1->Centre.Pos);
01226
01227
01228 VecCrossVec(&body1->AngVel, &collInfo->Pos1, &collInfo->Vel);
01229 VecPlusEqVec(&collInfo->Vel, &body1->Centre.Vel);
01230 VecMinusEqVec(&collInfo->Vel, &body2->Centre.Vel);
01231 if (VecDotVec(&collInfo->Vel, PlaneNormal(&collPoly->Plane)) >= ZERO) {
01232 continue;
01233 }
01234
01235
01236
01237 collInfo->Body1 = body1;
01238 collInfo->Body2 = &BDY_MassiveBody;
01239 SetVecZero(&collInfo->Pos2);
01240 CopyPlane(&collPoly->Plane, &collInfo->Plane);
01241 collInfo->Grip = MulScalar(body1->Centre.Grip, COL_MaterialInfo[collPoly->Material].Gripiness);
01242 collInfo->StaticFriction = MulScalar(body1->Centre.StaticFriction, COL_MaterialInfo[collPoly->Material].Roughness);
01243 collInfo->KineticFriction = MulScalar(body1->Centre.KineticFriction, COL_MaterialInfo[collPoly->Material].Roughness);
01244 collInfo->Restitution = MulScalar(body1->Centre.Hardness, COL_MaterialInfo[collPoly->Material].Hardness);
01245 collInfo->Material = &COL_MaterialInfo[collPoly->Material];
01246 if (abs(VecDotVec(PlaneNormal(&collInfo->Plane), &DownVec)) < 0.15f) {
01247 collInfo->StaticFriction = MulScalar(Real(0.1), collInfo->StaticFriction);
01248 collInfo->KineticFriction = MulScalar(Real(0.1), collInfo->KineticFriction);
01249 }
01250
01251
01252 AdjustBodyColl(collInfo, collInfo->Material);
01253
01254 AddBodyColl(body1, collInfo);
01255 nColls++;
01256
01257 }
01258
01259 }
01260
01261 return nColls;
01262 }
01263
01264 int DetectSphereSphereColls(NEWBODY *body1, NEWBODY *body2)
01265 {
01266 REAL dRLen;
01267 VEC dR;
01268 COLLINFO_BODY *bodyColl1, *bodyColl2;
01269 SPHERE *sphere1, *sphere2;
01270
01271 sphere1 = &body1->CollSkin.WorldSphere[0];
01272 sphere2 = &body2->CollSkin.WorldSphere[0];
01273
01274 Assert(IsBodySphere(body1));
01275 Assert(IsBodySphere(body2));
01276
01277
01278 VecMinusVec(&sphere1->Pos, &sphere2->Pos, &dR);
01279 dRLen = VecLen(&dR);
01280
01281
01282 if (dRLen > sphere1->Radius + sphere2->Radius) return 0;
01283
01284 if ((bodyColl1 = NextBodyCollInfo()) == NULL) return 0;
01285 AddBodyColl(body1, bodyColl1);
01286 if ((bodyColl2 = NextBodyCollInfo()) == NULL) {
01287 RemoveBodyColl(body1, bodyColl1);
01288 return 0;
01289 }
01290 AddBodyColl(body2, bodyColl2);
01291
01292 bodyColl1->Body1 = body1;
01293 bodyColl1->Body2 = body2;
01294 bodyColl2->Body1 = body2;
01295 bodyColl2->Body2 = body1;
01296
01297 bodyColl1->Depth = (dRLen - sphere1->Radius - sphere2->Radius) * HALF;
01298 bodyColl2->Depth = bodyColl1->Depth;
01299
01300
01301 if (dRLen > SMALL_REAL) {
01302 CopyVec(&dR, PlaneNormal(&bodyColl1->Plane));
01303 VecDivScalar(PlaneNormal(&bodyColl1->Plane), dRLen);
01304 bodyColl1->Time = ONE - DivScalar(bodyColl1->Depth, dRLen);
01305 } else {
01306 SetVec(PlaneNormal(&bodyColl1->Plane), ONE, ZERO, ZERO);
01307 bodyColl1->Time = ONE;
01308 }
01309 FlipPlane(&bodyColl1->Plane, &bodyColl2->Plane);
01310 bodyColl2->Time = bodyColl1->Time;
01311
01312
01313 VecPlusScalarVec(&sphere1->Pos, sphere1->Radius, PlaneNormal(&bodyColl1->Plane), &bodyColl1->Pos1);
01314 VecPlusScalarVec(&sphere2->Pos, -sphere2->Radius, PlaneNormal(&bodyColl1->Plane), &bodyColl1->Pos2);
01315 VecMinusEqVec(&bodyColl1->Pos1, &body1->Centre.Pos);
01316 VecMinusEqVec(&bodyColl1->Pos2, &body2->Centre.Pos);
01317 VecPlusScalarVec(&sphere1->Pos, HALF, &dR, &bodyColl1->WorldPos);
01318 CopyVec(&bodyColl1->Pos2, &bodyColl2->Pos1);
01319 CopyVec(&bodyColl1->Pos1, &bodyColl2->Pos2);
01320 CopyVec(&bodyColl1->WorldPos, &bodyColl2->WorldPos);
01321
01322
01323 VecCrossVec(&body1->AngVel, &bodyColl1->Pos1, &bodyColl1->Vel);
01324 VecPlusEqVec(&bodyColl1->Vel, &body1->Centre.Vel);
01325 VecCrossVec(&body2->AngVel, &bodyColl2->Pos1, &bodyColl2->Vel);
01326 VecPlusEqVec(&bodyColl2->Vel, &body2->Centre.Vel);
01327 VecMinusEqVec(&bodyColl1->Vel, &bodyColl2->Vel);
01328 CopyVec(&bodyColl1->Vel, &bodyColl2->Vel);
01329 NegateVec(&bodyColl2->Vel);
01330
01331
01332
01333 bodyColl1->Grip = MulScalar(body1->Centre.Grip, body2->Centre.Grip);
01334 bodyColl1->StaticFriction = MulScalar(body1->Centre.StaticFriction, body2->Centre.StaticFriction);
01335 bodyColl1->KineticFriction = MulScalar(body1->Centre.KineticFriction, body2->Centre.KineticFriction);
01336 bodyColl1->Restitution = MulScalar(body1->Centre.Hardness, body2->Centre.Hardness);
01337 bodyColl1->Material = NULL;
01338
01339 bodyColl2->Grip = bodyColl1->Grip;
01340 bodyColl2->StaticFriction = bodyColl1->StaticFriction;
01341 bodyColl2->KineticFriction = bodyColl1->KineticFriction;
01342 bodyColl2->Restitution = bodyColl1->Restitution;
01343 bodyColl2->Material = NULL;
01344
01345 return 1;
01346
01347 }
01348
01349
01350 int DetectHullHullColls(NEWBODY *body1, NEWBODY *body2)
01351 {
01352 int iSkin, iSphere;
01353 int nColls;
01354 REAL radius;
01355 VEC *sPos, *ePos, dR, vel1, vel2;
01356 COLLINFO_BODY *bodyColl1, *bodyColl2;
01357
01358 Assert((body1 != NULL) && (body2 != NULL));
01359 Assert(IsBodyConvex(body2));
01360 Assert(IsBodySphere(body1) || IsBodyConvex(body1));
01361
01362
01363 VecMinusVec(&body1->Centre.Pos, &body2->Centre.Pos, &dR);
01364
01365
01366 if (!BBTestXZY(&body2->CollSkin.BBox, &body1->CollSkin.BBox)) return 0;
01367
01368 nColls = 0;
01369
01370 for (iSphere = 0; iSphere < body1->CollSkin.NSpheres; iSphere++) {
01371
01372 sPos = &body1->CollSkin.OldWorldSphere[iSphere].Pos;
01373 ePos = &body1->CollSkin.WorldSphere[iSphere].Pos;
01374 radius = body1->CollSkin.WorldSphere[iSphere].Radius;
01375
01376 for (iSkin = 0; iSkin < body2->CollSkin.NConvex; iSkin++) {
01377
01378 if ((bodyColl1 = NextBodyCollInfo()) == NULL) return nColls;
01379
01380
01381 if (!SphereConvex(
01382 ePos,
01383 radius,
01384 &body2->CollSkin.WorldConvex[iSkin],
01385 &bodyColl1->Pos1, &bodyColl1->Plane,
01386 &bodyColl1->Depth))
01387 {
01388 continue;
01389 }
01390 nColls++;
01391
01392
01393
01394 bodyColl1->Body1 = body1;
01395 bodyColl1->Body2 = body2;
01396
01397
01398 VecMinusEqVec(&bodyColl1->Pos1, &body1->Centre.Pos);
01399 VecPlusScalarVec(&body1->Centre.Pos, -(radius + bodyColl1->Depth), PlaneNormal(&bodyColl1->Plane), &bodyColl1->WorldPos);
01400 VecMinusVec(&bodyColl1->WorldPos, &body2->Centre.Pos, &bodyColl1->Pos2);
01401
01402
01403 VecCrossVec(&body1->AngVel, &bodyColl1->Pos1, &vel1);
01404 VecPlusEqVec(&vel1, &body1->Centre.Vel);
01405 VecCrossVec(&body2->AngVel, &bodyColl1->Pos2, &vel2);
01406 VecPlusEqVec(&vel2, &body2->Centre.Vel);
01407 VecMinusVec(&vel1, &vel2, &bodyColl1->Vel);
01408
01409 if (VecDotVec(&bodyColl1->Vel, PlaneNormal(&bodyColl1->Plane)) > ZERO) continue;
01410
01411
01412 AddBodyColl(body1, bodyColl1);
01413 if ((bodyColl2 = NextBodyCollInfo()) == NULL) {
01414 RemoveBodyColl(body1, bodyColl1);
01415 return nColls;
01416 }
01417 AddBodyColl(body2, bodyColl2);
01418
01419 bodyColl2->Body1 = body2;
01420 bodyColl2->Body2 = body1;
01421 CopyVec(&bodyColl1->Pos2, &bodyColl2->Pos1);
01422 CopyVec(&bodyColl1->Pos1, &bodyColl2->Pos2);
01423 CopyVec(&bodyColl1->Vel, &bodyColl2->Vel);
01424 NegateVec(&bodyColl2->Vel);
01425
01426 FlipPlane(&bodyColl1->Plane, &bodyColl2->Plane);
01427 bodyColl1->Depth = MulScalar(HALF, bodyColl1->Depth);
01428 bodyColl2->Depth = bodyColl1->Depth;
01429 bodyColl1->Time = ZERO;
01430 bodyColl2->Time = ZERO;
01431
01432 bodyColl1->Grip = MulScalar(body1->Centre.Grip, body2->Centre.Grip);
01433 bodyColl1->StaticFriction = MulScalar(body1->Centre.StaticFriction, body2->Centre.StaticFriction);
01434 bodyColl1->KineticFriction = MulScalar(body1->Centre.KineticFriction, body2->Centre.KineticFriction);
01435 bodyColl1->Restitution = MulScalar(body1->Centre.Hardness, body2->Centre.Hardness);
01436 bodyColl1->Material = NULL;
01437 bodyColl2->StaticFriction = bodyColl1->StaticFriction;
01438 bodyColl2->KineticFriction = bodyColl1->KineticFriction;
01439 bodyColl2->Restitution = bodyColl1->Restitution;
01440 bodyColl2->Grip = bodyColl1->Grip;
01441 bodyColl2->Material = NULL;
01442
01443 }
01444 }
01445
01446 return nColls;
01447
01448 }
01449
01450
01452
01453
01454
01456
01457 void BodyTurboBoost(NEWBODY *body)
01458 {
01459 REAL boostMag;
01460
01461 if (body->Centre.Boost < SMALL_REAL) return;
01462
01463 boostMag = MulScalar(MulScalar(TimeStep, body->Centre.Boost), body->Centre.Mass);
01464 VecPlusEqScalarVec(&body->Centre.Impulse, boostMag, &body->Centre.WMatrix.mv[L]);
01465 }
01466
01468
01469
01470
01472
01473 void PostProcessBodyColls(NEWBODY *body)
01474 {
01475
01476 }
01477
01478
01480
01481
01482
01484
01485 COLLINFO_BODY *AddBodyColl(NEWBODY *body, COLLINFO_BODY *newHead)
01486 {
01487 COLLINFO_BODY *oldHead = body->BodyCollHead;
01488
01489 body->BodyCollHead = newHead;
01490 newHead->Next = oldHead;
01491 newHead->Prev = NULL;
01492
01493 if (oldHead != NULL) {
01494 oldHead->Prev = newHead;
01495 }
01496
01497 newHead->Active = TRUE;
01498
01499 body->NBodyColls++;
01500 COL_NBodyColls++;
01501
01502 return newHead;
01503 }
01504
01506
01507
01508
01510
01511 void RemoveBodyColl(NEWBODY *body, COLLINFO_BODY *collInfo)
01512 {
01513 Assert(collInfo != NULL);
01514 Assert(collInfo->Active);
01515
01516 if (collInfo->Next != NULL) {
01517 (collInfo->Next)->Prev = collInfo->Prev;
01518 }
01519
01520 if (collInfo->Prev != NULL) {
01521 (collInfo->Prev)->Next = collInfo->Next;
01522 } else {
01523 body->BodyCollHead = collInfo->Next;
01524 }
01525
01526 collInfo->Active = FALSE;
01527
01528 body->NBodyColls--;
01529
01530 Assert((body->NBodyColls == 0)? (body->BodyCollHead == NULL): (body->BodyCollHead != NULL));
01531 }
01532