00001
00002 #include "ReVolt.h"
00003 #include "NewColl.h"
00004 #include "Particle.h"
00005 #include "Body.h"
00006 #include "Geom.h"
00007 #ifndef _PSX
00008 #include "Main.h"
00009 #include "Level.h"
00010 #endif
00011 #include "Field.h"
00012 #ifdef _PC
00013 #include "EdField.h"
00014 #endif
00015
00016 #if MSCOMPILER_FUDGE_OPTIMISATIONS
00017 #pragma optimize("", off)
00018 #endif
00019
00021
00022
00023 FORCE_FIELD *FLD_GravityField = NULL;
00024 REAL FLD_Gravity = TO_ACC(Real(2200));
00025 BBOX FLD_GlobalBBox = {-LARGEDIST, LARGEDIST, -LARGEDIST, LARGEDIST, -LARGEDIST, LARGEDIST};
00026 VEC FLD_GlobalSize = {LARGEDIST, LARGEDIST, LARGEDIST};
00027
00028
00030
00031
00032 FORCE_FIELD FLD_ForceField[MAX_FIELDS];
00033 int FLD_NForceFields = 0;
00034
00035 FORCE_FIELD *FLD_FieldHead;
00036 FORCE_FIELD *FLD_EmptyFieldHead;
00037
00038
00040
00041
00042 static FORCE_FIELD *AddField(void);
00043
00044
00045 void FreeForceFields();
00046 void InitFields(void);
00047 void RemoveField(FORCE_FIELD *field);
00048 FORCE_FIELD *FirstField(void);
00049 FORCE_FIELD *NextField(FORCE_FIELD *field);
00050 void AllFieldImpulses(FIELD_DATA *data, VEC *imp, VEC *angImp);
00051
00052 FORCE_FIELD *AddLinearField(long parentID, long priority, VEC *posPtr, MAT *matPtr, BBOX *bBox, VEC *size, VEC *dir, REAL mag, REAL damping);
00053 bool LinearFieldCollTest(FORCE_FIELD *field, VEC *pos);
00054 void LinearFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp);
00055
00056 FORCE_FIELD *AddLinearTwistField(long parentID, long priority, VEC *posPtr, MAT *matPtr, BBOX *bBox, VEC *size, VEC *dir, REAL mag, VEC *torque, REAL damping);
00057 bool LinearTwistFieldCollTest(FORCE_FIELD *field, VEC *pos);
00058 void LinearTwistFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp);
00059
00060 FORCE_FIELD *AddLocalField(long parentID, long priority, VEC *posPtr, MAT *matPtr, BBOX *bBox, VEC *size, VEC *dir, REAL mag, REAL damping);
00061 bool LocalFieldCollTest(FORCE_FIELD *field, VEC *pos);
00062 void LocalFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp);
00063
00064 FORCE_FIELD *AddVelocityField(long parentID, long priority, VEC *posPtr, MAT *matPtr, BBOX *bBox, VEC *size, VEC *dir, REAL mag);
00065 bool VelocityFieldCollTest(FORCE_FIELD *field, VEC *pos);
00066 void VelocityFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp);
00067
00068 FORCE_FIELD *AddSphericalField(long parentID, long priority, VEC *posPtr, REAL rStart, REAL rEnd, REAL gStart, REAL gEnd);
00069 bool SphericalFieldCollTest(FORCE_FIELD *field, VEC *pos);
00070 void SphericalFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp);
00071
00072 FORCE_FIELD *AddCylindricalField(long parentID, long priority, VEC *posPtr, VEC *dir, REAL rStart, REAL rEnd, REAL gStart, REAL gEnd);
00073 bool CylindricalFieldCollTest(FORCE_FIELD *field, VEC *pos);
00074 void CylindricalFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp);
00075
00076 FORCE_FIELD *AddVortexField(long parentID, long priority, VEC *posPtr, MAT *matPtr, BBOX *bBox, VEC *size, VEC *dir, REAL mag, REAL rMin, REAL rMax);
00077 bool VortexFieldCollTest(FORCE_FIELD *field, VEC *pos);
00078 void VortexFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp);
00079
00080 FORCE_FIELD *AddOrientationField(long parentID, long priority, VEC *posPtr, MAT *matPtr, BBOX *bBox, VEC *size, VEC *dir, REAL mag, REAL damping);
00081 bool OrientationFieldCollTest(FORCE_FIELD *field, VEC *pos);
00082 void OrientationFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp);
00083
00084
00086
00087
00088
00090
00091 void InitFields(void)
00092 {
00093 int iField;
00094
00095
00096 FLD_NForceFields = 0;
00097
00098 FLD_ForceField[0].Prev = NULL;
00099
00100 for (iField = 1; iField < MAX_FIELDS - 1; iField++) {
00101
00102 FLD_ForceField[iField - 1].Next = &FLD_ForceField[iField];
00103 FLD_ForceField[iField].Prev = &FLD_ForceField[iField - 1];
00104 FLD_ForceField[iField].Next = &FLD_ForceField[iField + 1];
00105
00106 }
00107
00108 FLD_ForceField[MAX_FIELDS - 1].Prev = &FLD_ForceField[MAX_FIELDS - 2];
00109 FLD_ForceField[MAX_FIELDS - 1].Next = NULL;
00110
00111 FLD_FieldHead = NULL;
00112 FLD_EmptyFieldHead = &FLD_ForceField[0];
00113
00114 }
00115
00116
00118
00119
00120
00121
00123
00124 FORCE_FIELD *AddField(void)
00125 {
00126 FORCE_FIELD *oldFirstField;
00127 FORCE_FIELD *oldNextEmpty;
00128
00129
00130 if (FLD_EmptyFieldHead == NULL) {
00131 return NULL;
00132 }
00133
00134
00135 oldFirstField = FLD_FieldHead;
00136 oldNextEmpty = FLD_EmptyFieldHead->Next;
00137
00138
00139 FLD_FieldHead = FLD_EmptyFieldHead;
00140 FLD_FieldHead->Next = oldFirstField;
00141 FLD_FieldHead->Prev = NULL;
00142 if (oldFirstField != NULL) {
00143 oldFirstField->Prev = FLD_FieldHead;
00144 }
00145
00146
00147 FLD_EmptyFieldHead = oldNextEmpty;
00148
00149
00150 FLD_NForceFields++;
00151
00152
00153 FLD_FieldHead->PosPtr = NULL;
00154 FLD_FieldHead->MatPtr = NULL;
00155
00156 return FLD_FieldHead;
00157
00158 }
00159
00160 void RemoveField(FORCE_FIELD *field)
00161 {
00162
00163 if (field->Prev != NULL) {
00164 (field->Prev)->Next = field->Next;
00165 } else {
00166 FLD_FieldHead = field->Next;
00167 }
00168 if (field->Next != NULL) {
00169 (field->Next)->Prev = field->Prev;
00170 }
00171
00172
00173 field->Next = FLD_EmptyFieldHead;
00174 FLD_EmptyFieldHead = field;
00175
00176
00177 FLD_NForceFields--;
00178
00179 }
00180
00181
00183
00184
00185
00187
00188 FORCE_FIELD *FirstField(void)
00189 {
00190 return FLD_FieldHead;
00191 }
00192
00193
00195
00196
00197
00199
00200 FORCE_FIELD *NextField(FORCE_FIELD *field)
00201 {
00202 Assert(field != NULL);
00203 return field->Next;
00204 }
00205
00206
00208
00209
00210
00212
00213 FORCE_FIELD *AddLinearField(long parentID, long priority, VEC *pos, MAT *mat, BBOX *bBox, VEC *size, VEC *dir, REAL mag, REAL damping)
00214 {
00215 FORCE_FIELD *field;
00216 LINEAR_FIELD_PARAMS *params;
00217
00218 field = AddField();
00219 params = &field->Params.LinearParams;
00220
00221 field->Type = FIELD_LINEAR;
00222 field->ParentID = parentID;
00223 field->Priority = priority;
00224 field->PosPtr = pos;
00225 field->MatPtr = mat;
00226 field->FieldCollTest = LinearFieldCollTest;
00227 field->AddFieldImpulse = LinearFieldImpulse;
00228
00229 CopyBBox(bBox, &field->BBox);
00230 CopyVec(size, ¶ms->Size);
00231 CopyVec(dir, ¶ms->Dir);
00232 params->Mag = mag;
00233 params->Damping = damping;
00234
00235 return field;
00236 }
00237
00238 bool LinearFieldCollTest(FORCE_FIELD *field, VEC *pos)
00239 {
00240 int iFace;
00241 VEC dR;
00242 LINEAR_FIELD_PARAMS *params = &field->Params.LinearParams;
00243
00244 VecMinusVec(pos, field->PosPtr, &dR);
00245
00246
00247 if (!PointInBBox(&dR, &field->BBox)) {
00248 return FALSE;
00249 }
00250
00251
00252 for (iFace = 0; iFace < 3; iFace++) {
00253 if (abs(VecDotVec(&dR, &field->MatPtr->mv[iFace])) > params->Size.v[iFace]) {
00254 return FALSE;
00255 }
00256 }
00257
00258 return TRUE;
00259
00260 }
00261
00262 void LinearFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp)
00263 {
00264 REAL scale;
00265 LINEAR_FIELD_PARAMS *params = &field->Params.LinearParams;
00266
00267 scale = params->Mag - MulScalar(params->Damping, VecDotVec(¶ms->Dir, data->Vel));
00268 scale = MulScalar(scale, MulScalar(TimeStep, data->Mass));
00269
00270
00271 VecPlusEqScalarVec(imp, scale, ¶ms->Dir);
00272
00273 }
00274
00276
00277
00278
00280
00281 FORCE_FIELD *AddLinearTwistField(long parentID, long priority, VEC *pos, MAT *mat, BBOX *bBox, VEC *size, VEC *dir, REAL mag, VEC * twist, REAL damping)
00282 {
00283 FORCE_FIELD *field;
00284 LINEARTWIST_FIELD_PARAMS *params;
00285
00286 field = AddField();
00287 params = &field->Params.LinearTwistParams;
00288
00289 field->Type = FIELD_LINEARTWIST;
00290 field->ParentID = parentID;
00291 field->Priority = priority;
00292 field->PosPtr = pos;
00293 field->MatPtr = mat;
00294 field->FieldCollTest = LinearTwistFieldCollTest;
00295 field->AddFieldImpulse = LinearTwistFieldImpulse;
00296
00297 CopyBBox(bBox, &field->BBox);
00298 CopyVec(size, ¶ms->Size);
00299 CopyVec(dir, ¶ms->Dir);
00300 params->Mag = mag;
00301 params->Damping = damping;
00302 CopyVec(twist, ¶ms->Torque);
00303
00304 return field;
00305 }
00306
00307 bool LinearTwistFieldCollTest(FORCE_FIELD *field, VEC *pos)
00308 {
00309 int iFace;
00310 VEC dR;
00311 LINEARTWIST_FIELD_PARAMS *params = &field->Params.LinearTwistParams;
00312
00313 VecMinusVec(pos, field->PosPtr, &dR);
00314
00315
00316 if (!PointInBBox(&dR, &field->BBox)) {
00317 return FALSE;
00318 }
00319
00320
00321 for (iFace = 0; iFace < 3; iFace++) {
00322 if (abs(VecDotVec(&dR, &field->MatPtr->mv[iFace])) > params->Size.v[iFace]) {
00323 return FALSE;
00324 }
00325 }
00326
00327 return TRUE;
00328
00329 }
00330
00331 void LinearTwistFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp)
00332 {
00333 REAL scale;
00334 LINEARTWIST_FIELD_PARAMS *params = &field->Params.LinearTwistParams;
00335
00336 scale = params->Mag - MulScalar(params->Damping, VecDotVec(¶ms->Dir, data->Vel));
00337 scale = MulScalar(scale, MulScalar(TimeStep, data->Mass));
00338 VecPlusEqScalarVec(imp, scale, ¶ms->Dir);
00339
00340 VecEqScalarVec(angImp, TimeStep, ¶ms->Torque);
00341
00342 }
00343
00345
00346
00347
00349
00350 FORCE_FIELD *AddVelocityField(long parentID, long priority, VEC *pos, MAT *mat, BBOX *bBox, VEC *size, VEC *dir, REAL mag)
00351 {
00352 FORCE_FIELD *field;
00353 VELOCITY_FIELD_PARAMS *params;
00354
00355 field = AddField();
00356 params = &field->Params.VelocityParams;
00357
00358 field->Type = FIELD_VELOCITY;
00359 field->ParentID = parentID;
00360 field->Priority = priority;
00361 field->PosPtr = pos;
00362 field->MatPtr = mat;
00363 field->FieldCollTest = VelocityFieldCollTest;
00364 field->AddFieldImpulse = VelocityFieldImpulse;
00365
00366 CopyBBox(bBox, &field->BBox);
00367 CopyVec(size, ¶ms->Size);
00368 CopyVec(dir, ¶ms->Dir);
00369 params->Mag = mag;
00370
00371 return field;
00372 }
00373
00374 bool VelocityFieldCollTest(FORCE_FIELD *field, VEC *pos)
00375 {
00376 int iFace;
00377 VEC dR;
00378 VELOCITY_FIELD_PARAMS *params = &field->Params.VelocityParams;
00379
00380 VecMinusVec(pos, field->PosPtr, &dR);
00381
00382
00383 if (!PointInBBox(&dR, &field->BBox)) {
00384 return FALSE;
00385 }
00386
00387
00388 for (iFace = 0; iFace < 3; iFace++) {
00389 if (abs(VecDotVec(&dR, &field->MatPtr->mv[iFace])) > params->Size.v[iFace]) {
00390 return FALSE;
00391 }
00392 }
00393
00394 return TRUE;
00395
00396 }
00397
00398 void VelocityFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp)
00399 {
00400 REAL mag;
00401 VELOCITY_FIELD_PARAMS *params = &field->Params.VelocityParams;
00402
00403 mag = params->Mag - VecDotVec(¶ms->Dir, data->Vel);
00404 mag = MulScalar(mag, TimeStep);
00405
00406 VecPlusEqScalarVec(imp, mag, ¶ms->Dir);
00407
00408 }
00409
00410
00412
00413
00414
00416
00417 FORCE_FIELD *AddSphericalField(long parentID, long priority, VEC *pos, REAL rStart, REAL rEnd, REAL gStart, REAL gEnd)
00418 {
00419
00420 FORCE_FIELD *field;
00421 SPHERICAL_FIELD_PARAMS *params;
00422
00423 field = AddField();
00424 params = &field->Params.SphericalParams;
00425
00426 field->Type = FIELD_SPHERICAL;
00427 field->ParentID = parentID;
00428 field->Priority = priority;
00429 field->PosPtr = pos;
00430 field->MatPtr = &Identity;
00431 field->FieldCollTest = SphericalFieldCollTest;
00432 field->AddFieldImpulse = SphericalFieldImpulse;
00433 SetBBox(&field->BBox, -rEnd, rEnd, -rEnd, rEnd, -rEnd, rEnd);
00434
00435 params->RadStart = rStart;
00436 params->RadEnd = rEnd;
00437 params->GradStart = gStart;
00438 params->GradEnd = gEnd;
00439
00440 return field;
00441 }
00442
00443
00444 bool SphericalFieldCollTest(FORCE_FIELD *field, VEC *pos)
00445 {
00446 VEC dR;
00447 REAL dRLenSq;
00448 SPHERICAL_FIELD_PARAMS *params = &field->Params.SphericalParams;
00449
00450 VecMinusVec(pos, field->PosPtr, &dR);
00451 dRLenSq = VecDotVec(&dR, &dR);
00452
00453 if (dRLenSq < MulScalar(params->RadEnd, params->RadEnd)) {
00454 return TRUE;
00455 }
00456
00457 return FALSE;
00458 }
00459
00460 void SphericalFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp)
00461 {
00462 VEC dR;
00463 REAL dRLen, gradient;
00464 SPHERICAL_FIELD_PARAMS *params = &field->Params.SphericalParams;
00465
00466 VecMinusVec(data->Pos, field->PosPtr, &dR);
00467 dRLen = (REAL)sqrt(VecDotVec(&dR, &dR));
00468
00469
00470 if (dRLen > params->RadStart && dRLen < params->RadEnd) {
00471
00472 gradient = DivScalar((dRLen - params->RadStart), (params->RadEnd - params->RadStart));
00473 gradient = params->GradStart + MulScalar(gradient, (params->GradEnd - params->GradStart));
00474 gradient = DivScalar(MulScalar(gradient, TimeStep), dRLen);
00475 VecMulScalar(&dR, gradient);
00476
00477 VecPlusEqScalarVec(imp, data->Mass, &dR);
00478 }
00479
00480 }
00481
00482
00483
00485
00486
00487
00489
00490 FORCE_FIELD *AddCylindricalField(long parentID, long priority, VEC *pos, VEC *dir, REAL rStart, REAL rEnd, REAL gStart, REAL gEnd)
00491 {
00492
00493 FORCE_FIELD *field;
00494 CYLINDRICAL_FIELD_PARAMS *params;
00495
00496 field = AddField();
00497 params = &field->Params.CylindricalParams;
00498
00499 field->Type = FIELD_SPHERICAL;
00500 field->ParentID = parentID;
00501 field->Priority = priority;
00502 field->PosPtr = pos;
00503 field->MatPtr = &Identity;
00504 field->FieldCollTest = CylindricalFieldCollTest;
00505 field->AddFieldImpulse = CylindricalFieldImpulse;
00506 SetBBox(&field->BBox, -rEnd, rEnd, -rEnd, rEnd, -rEnd, rEnd);
00507
00508 CopyVec(dir, ¶ms->Dir);
00509 params->RadStart = rStart;
00510 params->RadEnd = rEnd;
00511 params->GradStart = gStart;
00512 params->GradEnd = gEnd;
00513
00514 return field;
00515 }
00516
00517
00518 bool CylindricalFieldCollTest(FORCE_FIELD *field, VEC *pos)
00519 {
00520 VEC dR;
00521 REAL dRLenSq;
00522 CYLINDRICAL_FIELD_PARAMS *params = &field->Params.CylindricalParams;
00523
00524 VecMinusVec(pos, field->PosPtr, &dR);
00525 dRLenSq = VecDotVec(&dR, &dR);
00526
00527 if (dRLenSq < MulScalar(params->RadEnd, params->RadEnd)) {
00528 return TRUE;
00529 }
00530
00531 return FALSE;
00532 }
00533
00534 void CylindricalFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp)
00535 {
00536 VEC dR;
00537 REAL dRLen, gradient, dRDir;
00538 CYLINDRICAL_FIELD_PARAMS *params = &field->Params.CylindricalParams;
00539
00540 VecMinusVec(data->Pos, field->PosPtr, &dR);
00541 dRDir = VecDotVec(&dR, ¶ms->Dir);
00542 VecPlusEqScalarVec(&dR, -dRDir, ¶ms->Dir);
00543 dRLen = VecLen(&dR);
00544
00545 if (dRLen > params->RadStart && dRLen < params->RadEnd) {
00546
00547 gradient = DivScalar((dRLen - params->RadStart), (params->RadEnd - params->RadStart));
00548 gradient = params->GradStart + MulScalar(gradient, (params->GradEnd - params->GradStart));
00549
00550
00551 VecMulScalar(&dR, gradient);
00552
00553 VecPlusEqVec(imp, &dR);
00554 }
00555
00556 }
00557
00558
00559
00561
00562
00563
00564
00566
00567 FORCE_FIELD *AddOrientationField(long parentID, long priority, VEC *pos, MAT *mat, BBOX *bBox, VEC *size, VEC *dir, REAL mag, REAL damping)
00568 {
00569 FORCE_FIELD *field;
00570 ORIENTATION_FIELD_PARAMS *params;
00571
00572 field = AddField();
00573 params = &field->Params.OrientationParams;
00574
00575 field->Type = FIELD_ORIENTATION;
00576 field->ParentID = parentID;
00577 field->Priority = priority;
00578 field->PosPtr = pos;
00579 field->MatPtr = mat;
00580 field->FieldCollTest = OrientationFieldCollTest;
00581 field->AddFieldImpulse = NULL;
00582
00583 CopyBBox(bBox, &field->BBox);
00584 CopyVec(size, ¶ms->Size);
00585 CopyVec(dir, ¶ms->Dir);
00586 params->Mag = mag;
00587 params->Damping = damping;
00588
00589 return field;
00590 }
00591
00592 bool OrientationFieldCollTest(FORCE_FIELD *field, VEC *pos)
00593 {
00594 int iFace;
00595 VEC dR;
00596 ORIENTATION_FIELD_PARAMS *params = &field->Params.OrientationParams;
00597
00598 VecMinusVec(pos, field->PosPtr, &dR);
00599
00600
00601 if (!PointInBBox(&dR, &field->BBox)) {
00602 return FALSE;
00603 }
00604
00605
00606 for (iFace = 0; iFace < 3; iFace++) {
00607 if (abs(VecDotVec(&dR, &field->MatPtr->mv[iFace])) > params->Size.v[iFace]) {
00608 return FALSE;
00609 }
00610 }
00611
00612 return TRUE;
00613
00614 }
00615
00616 void OrientationFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp)
00617 {
00618 VEC torque;
00619 REAL scale;
00620 ORIENTATION_FIELD_PARAMS *params = &field->Params.OrientationParams;
00621
00622 VecCrossVec(¶ms->Dir, &data->Mat->mv[U], &torque);
00623 scale = (ONE - MulScalar(params->Damping, VecDotVec(&torque, data->AngVel)));
00624 scale = MulScalar(TimeStep, MulScalar(params->Mag, scale));
00625 VecMulScalar(&torque, scale);
00626
00627 VecPlusEqVec(angImp, &torque);
00628 }
00629
00630
00631
00633
00634
00635
00636
00638
00639 FORCE_FIELD *AddVortexField(long parentID, long priority, VEC *pos, MAT *mat, BBOX *bBox, VEC *size, VEC *dir, REAL mag, REAL rMin, REAL rMax)
00640 {
00641 FORCE_FIELD *field;
00642 VORTEX_FIELD_PARAMS *params;
00643
00644 field = AddField();
00645 params = &field->Params.VortexParams;
00646
00647 field->Type = FIELD_VORTEX;
00648 field->ParentID = parentID;
00649 field->Priority = priority;
00650 field->PosPtr = pos;
00651 field->MatPtr = mat;
00652 field->FieldCollTest = VortexFieldCollTest;
00653 field->AddFieldImpulse = VortexFieldImpulse;
00654
00655 CopyBBox(bBox, &field->BBox);
00656 CopyVec(size, ¶ms->Size);
00657 CopyVec(dir, ¶ms->Dir);
00658 params->Mag = mag;
00659 params->RMin = rMin;
00660 params->RMax = rMax;
00661
00662 return field;
00663 }
00664
00665 bool VortexFieldCollTest(FORCE_FIELD *field, VEC *pos)
00666 {
00667 int iFace;
00668 VEC dR;
00669 ORIENTATION_FIELD_PARAMS *params = &field->Params.OrientationParams;
00670
00671 VecMinusVec(pos, field->PosPtr, &dR);
00672
00673
00674 if (!PointInBBox(&dR, &field->BBox)) {
00675 return FALSE;
00676 }
00677
00678
00679 for (iFace = 0; iFace < 3; iFace++) {
00680 if (abs(VecDotVec(&dR, &field->MatPtr->mv[iFace])) > params->Size.v[iFace]) {
00681 return FALSE;
00682 }
00683 }
00684
00685 return TRUE;
00686
00687 }
00688
00689 void VortexFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp)
00690 {
00691 VEC dR;
00692 VEC impulse;
00693 REAL scale, perpLen;
00694 VORTEX_FIELD_PARAMS *params = &field->Params.VortexParams;
00695
00696 VecMinusVec(data->Pos, field->PosPtr, &dR);
00697 VecCrossVec(&dR, ¶ms->Dir, &impulse);
00698 perpLen = VecLen(&impulse);
00699
00700 if ((perpLen > params->RMin) && (perpLen < params->RMax)) {
00701
00702 scale = params->Mag - DivScalar(VecDotVec(data->Vel, &impulse), (perpLen));
00703 scale = DivScalar(MulScalar(scale, TimeStep), perpLen);
00704 VecMulScalar(&impulse, scale);
00705
00706 VecPlusEqVec(imp, &impulse);
00707 }
00708 }
00709
00710
00711
00713
00714
00715
00716
00718
00719 void AllFieldImpulses(FIELD_DATA *data, VEC *imp, VEC *angImp)
00720 {
00721 FORCE_FIELD *field;
00722
00723 SetVecZero(imp);
00724 SetVecZero(angImp);
00725
00726 for (field = FirstField(); field != NULL; field = NextField(field)) {
00727
00728
00729 if ((field->ParentID != FIELD_PARENT_NONE) && (field->ParentID == data->ObjectID)) continue;
00730
00731
00732 if (!FieldPriorityTest(field->Priority, data->Priority)) continue;
00733
00734
00735 if (field->AddFieldImpulse != NULL) {
00736 if ((*field->FieldCollTest)(field, data->Pos)) {
00737 (*field->AddFieldImpulse)(field, data, imp, angImp);
00738 }
00739 }
00740
00741 }
00742
00743 }
00744
00745
00747
00748
00749
00751
00752 FORCE_FIELD *AddLocalField(long parentID, long priority, VEC *pos, MAT *mat, BBOX *bBox, VEC *size, VEC *dir, REAL mag, REAL damping)
00753 {
00754 FORCE_FIELD *field;
00755 LOCAL_FIELD_PARAMS *params;
00756
00757 field = AddField();
00758 params = &field->Params.LocalParams;
00759
00760 field->Type = FIELD_LOCAL;
00761 field->ParentID = parentID;
00762 field->Priority = priority;
00763 field->PosPtr = pos;
00764 field->MatPtr = mat;
00765 field->FieldCollTest = LocalFieldCollTest;
00766 field->AddFieldImpulse = LocalFieldImpulse;
00767
00768 CopyBBox(bBox, &field->BBox);
00769 CopyVec(size, ¶ms->Size);
00770 params->DirPtr = dir;
00771 params->Mag = mag;
00772 params->Damping = damping;
00773
00774 return field;
00775 }
00776
00777 bool LocalFieldCollTest(FORCE_FIELD *field, VEC *pos)
00778 {
00779 int iFace;
00780 VEC dR;
00781 LOCAL_FIELD_PARAMS *params = &field->Params.LocalParams;
00782
00783 VecMinusVec(pos, field->PosPtr, &dR);
00784
00785
00786 if (!PointInBBox(&dR, &field->BBox)) {
00787 return FALSE;
00788 }
00789
00790
00791 for (iFace = 0; iFace < 3; iFace++) {
00792 if (abs(VecDotVec(&dR, &field->MatPtr->mv[iFace])) > params->Size.v[iFace]) {
00793 return FALSE;
00794 }
00795
00796 }
00797
00798 return TRUE;
00799
00800 }
00801
00802 void LocalFieldImpulse(FORCE_FIELD *field, FIELD_DATA *data, VEC *imp, VEC *angImp)
00803 {
00804 REAL scale;
00805 LOCAL_FIELD_PARAMS *params = &field->Params.LocalParams;
00806
00807 scale = (params->Mag - MulScalar(params->Damping, VecDotVec(params->DirPtr, data->Vel)));
00808 scale = MulScalar(MulScalar(scale, data->Mass), TimeStep);
00809
00810 VecPlusEqScalarVec(imp, scale, params->DirPtr);
00811
00812 }
00813
00814
00815
00817
00818
00819
00821
00822 void FreeForceFields()
00823 {
00824 #ifndef _PSX
00825 free(LEV_LevelFieldPos);
00826 free(LEV_LevelFieldMat);
00827 LEV_LevelFieldPos = NULL;
00828 LEV_LevelFieldMat = NULL;
00829 #endif
00830 }
00831
00832
00833
00834 #if MSCOMPILER_FUDGE_OPTIMISATIONS
00835 #pragma optimize("", on)
00836 #endif