2
0

GXS.PhysManager.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. //
  2. // The graphics engine GXScene
  3. //
  4. unit GXS.PhysManager;
  5. (* The Manager for Scene Physics Interactions (Phys) *)
  6. interface
  7. uses
  8. System.Classes,
  9. System.SysUtils,
  10. GXS.XCollection,
  11. Stage.VectorGeometry,
  12. GXS.Scene,
  13. GXS.PhysForces,
  14. GXS.Behaviours;
  15. type
  16. // only ssEuler is usable at the moment
  17. TDESolverType = (ssEuler, ssRungeKutta4, ssVerlet);
  18. // TDESolver = procedure((*RigidBody:TgxRigidBody;*)DeltaTime:Real) of object;
  19. TStateArray = array of Real;
  20. TgxPhysManager = class;
  21. (*
  22. ***Euler***, EulerImproved, EulerModified, MidPoint
  23. RungeKutta2, ***RungeKutta4***, RungKutta4Adaptive
  24. State Variables: Position, Velocity
  25. Verlet
  26. State Variables: Position, Old Position
  27. *)
  28. // need to have state array(s) seperate from inertias to allow for implicit & explicit methods
  29. TDESolver = class(TObject)
  30. public
  31. StateSize: Integer;
  32. StateArray: TStateArray;
  33. Owner: TgxPhysManager;
  34. function StateToArray(): TStateArray; virtual;
  35. procedure ArrayToState(StateArray: TStateArray); virtual;
  36. procedure Solve(DeltaTime: Real); virtual; abstract;
  37. constructor Create(aOwner: TgxPhysManager); // override; //abstract;
  38. destructor Destroy; override;
  39. // procedure Assign(Source: TPersistent); override;
  40. end;
  41. // explicit e.g. Euler, Mid-point, Runge-Kutta integration
  42. TDESolverExplicit = class(TDESolver)
  43. public
  44. StateArrayDot: TStateArray; // Velocity stored
  45. function CalcStateDot(): TStateArray; virtual;
  46. end;
  47. TDESolverEuler = class(TDESolverExplicit)
  48. public
  49. procedure Solve(DeltaTime: Real); override;
  50. end;
  51. TDESolverRungeKutta4 = class(TDESolverExplicit)
  52. public
  53. procedure Solve(DeltaTime: Real); override;
  54. end;
  55. // implicit e.g. Verlet Integration
  56. TDESolverImplicit = class(TDESolver)
  57. public
  58. LastStateArray: TStateArray; // Last state stored
  59. end;
  60. TDESolverVerlet = class(TDESolverImplicit)
  61. public
  62. end;
  63. TgxForces = class;
  64. TgxBaseForceFieldEmitter = class;
  65. // TgxPhysManager = class;
  66. (* purpose of TgxBaseInertia is to allow for inertias that may be constrained
  67. to 1 or 2 dimensions
  68. Shouldn't be used directly, instead use TgxParticleInertia (for a 3D particle)
  69. TgxRigidBodyInertia (for a 3D rigid-body) or define a new sub-class
  70. e.g. Tgx1DParticleInertia, this will allow for faster speed *)
  71. TgxBaseInertia = class(TgxBehaviour)
  72. private
  73. FDampingEnabled: Boolean;
  74. FManager: TgxPhysManager;
  75. FManagerName: String; // NOT persistent, temporarily used for persistence
  76. protected
  77. procedure Loaded; override;
  78. procedure WriteToFiler(writer: TWriter); override;
  79. procedure ReadFromFiler(reader: TReader); override;
  80. public
  81. StateSize: Integer; // don't re-declare this in sub-classes
  82. // just initialise it in constructor
  83. procedure StateToArray(var StateArray: TStateArray;
  84. StatePos: Integer); virtual;
  85. procedure ArrayToState( { var } StateArray: TStateArray;
  86. StatePos: Integer); virtual;
  87. procedure CalcStateDot(var StateArray: TStateArray;
  88. StatePos: Integer); virtual;
  89. procedure RemoveForces(); virtual;
  90. procedure CalculateForceFieldForce(ForceFieldEmitter
  91. : TgxBaseForceFieldEmitter); virtual;
  92. procedure CalcAuxiliary(); virtual;
  93. procedure SetUpStartingState(); virtual;
  94. function CalculateKE(): Real; virtual;
  95. function CalculatePE(): Real; virtual;
  96. constructor Create(aOwner: TXCollection); override; // abstract;
  97. destructor Destroy; override;
  98. procedure Assign(Source: TPersistent); override;
  99. procedure SetManager(const val: TgxPhysManager);
  100. published
  101. property DampingEnabled: Boolean read FDampingEnabled write FDampingEnabled;
  102. property Manager: TgxPhysManager read FManager write SetManager;
  103. end;
  104. (* A base for different types of force-field behaviours *)
  105. TgxBaseForceFieldEmitter = class(TgxBehaviour)
  106. private
  107. FManager: TgxPhysManager;
  108. FManagerName: String; // NOT persistent, temporarily used for persistence
  109. protected
  110. procedure Loaded; override;
  111. procedure WriteToFiler(writer: TWriter); override;
  112. procedure ReadFromFiler(reader: TReader); override;
  113. public
  114. constructor Create(aOwner: TXCollection); override; // abstract;
  115. destructor Destroy; override;
  116. procedure Assign(Source: TPersistent); override;
  117. procedure SetManager(const val: TgxPhysManager);
  118. function CalculateForceField(Body: TgxBaseSceneObject): TAffineVector; virtual;
  119. published
  120. property Manager: TgxPhysManager read FManager write SetManager;
  121. end;
  122. (* The Simple Physics Interaction (SPI) manager can only deal with objects from one scene
  123. More than one physics manager can be assigned to a scene *)
  124. TgxPhysManager = class(TComponent)
  125. // StateSize:Integer;
  126. protected
  127. fInertias: TList; // list of all inertias with manager = self
  128. fForceFieldEmitters: TList; // list of all forcefield emitters
  129. fForces: TgxForces; // Collection of forces acting on/between objects
  130. fDESolverType: TDESolverType;
  131. DESolver: TDESolver;
  132. fScene: TgxScene;
  133. protected
  134. procedure Loaded; override;
  135. procedure DefineProperties(Filer: TFiler); override;
  136. procedure WriteForces(stream: TStream);
  137. procedure ReadForces(stream: TStream);
  138. procedure SetForces(const val: TgxForces);
  139. function GetForces: TgxForces;
  140. procedure SetInertias(const val: TList);
  141. procedure SetForceFieldEmitters(const val: TList);
  142. procedure SetScene(const val: TgxScene);
  143. public
  144. procedure RegisterInertia(aInertia: TgxBaseInertia);
  145. procedure DeRegisterInertia(aInertia: TgxBaseInertia);
  146. procedure DeRegisterAllInertias;
  147. procedure RegisterForceFieldEmitter(aForceField: TgxBaseForceFieldEmitter);
  148. procedure DeRegisterForceFieldEmitter(aForceField: TgxBaseForceFieldEmitter);
  149. procedure DeRegisterAllForceFieldEmitters;
  150. procedure Notification(AComponent: TComponent;
  151. Operation: TOperation); override;
  152. constructor Create(aOwner: TComponent); override;
  153. destructor Destroy; override;
  154. procedure Assign(Source: TPersistent); override;
  155. procedure CalculateNextState(DeltaTime: Real);
  156. function CalculateKE(): Real;
  157. function CalculatePE(): Real;
  158. procedure SetDESolver(SolverType: TDESolverType);
  159. function FindObjectByName(Name: String): TgxBaseSceneObject;
  160. function FindForceFieldEmitterByName(Name: String): TgxBaseSceneObject;
  161. property Inertias: TList read fInertias write SetInertias; // stored False;
  162. property ForceFieldEmitters: TList read fForceFieldEmitters
  163. write SetForceFieldEmitters; // stored False;
  164. published
  165. property Forces: TgxForces read GetForces write SetForces; // stored False;
  166. property Solver: TDESolverType read fDESolverType write SetDESolver;
  167. property Scene: TgxScene read fScene write SetScene;
  168. end;
  169. TgxForces = class(TXCollection)
  170. protected
  171. function GetForce(index: Integer): TgxForce;
  172. public
  173. constructor Create(aOwner: TPersistent); override;
  174. // destructor Destroy;override;
  175. class function ItemsClass: TXCollectionItemClass; override;
  176. property Force[index: Integer]: TgxForce read GetForce; default;
  177. function CanAdd(aClass: TXCollectionItemClass): Boolean; override;
  178. end;
  179. implementation // ------------------------------------------------------------
  180. procedure TgxPhysManager.Notification(AComponent: TComponent;
  181. Operation: TOperation);
  182. begin
  183. (* if Operation=opRemove then
  184. begin
  185. if AComponent=FScene then FScene:=nil;
  186. end;
  187. *)
  188. end;
  189. procedure TgxPhysManager.DefineProperties(Filer: TFiler);
  190. begin
  191. inherited DefineProperties(Filer);
  192. Filer.DefineBinaryProperty('ForcesData', ReadForces, WriteForces,
  193. (Assigned(fForces) and (fForces.Count > 0)));
  194. end;
  195. procedure TgxPhysManager.Loaded;
  196. begin
  197. inherited Loaded;
  198. if Assigned(fForces) then
  199. fForces.Loaded;
  200. end;
  201. function TgxPhysManager.FindObjectByName(Name: String): TgxBaseSceneObject;
  202. var
  203. i: Integer;
  204. begin
  205. Result := nil;
  206. for i := 0 to fInertias.Count - 1 do
  207. begin
  208. if (TgxBaseInertia(fInertias.Items[i]).OwnerBaseSceneObject.GetNamePath =
  209. Name) then
  210. begin
  211. Result := TgxBaseInertia(fInertias.Items[i]).OwnerBaseSceneObject;
  212. end
  213. else if Owner.FindComponent(Name) <> nil then
  214. begin
  215. Result := TgxBaseSceneObject(Owner.FindComponent(Name));
  216. end;
  217. end;
  218. end;
  219. function TgxPhysManager.FindForceFieldEmitterByName(Name: String)
  220. : TgxBaseSceneObject;
  221. var
  222. i: Integer;
  223. begin
  224. Result := nil;
  225. for i := 0 to fForceFieldEmitters.Count - 1 do
  226. begin
  227. if (TgxBaseForceFieldEmitter(fForceFieldEmitters.Items[i])
  228. .OwnerBaseSceneObject.GetNamePath = Name) then
  229. begin
  230. Result := TgxBaseForceFieldEmitter(fForceFieldEmitters.Items[i])
  231. .OwnerBaseSceneObject;
  232. end;
  233. end;
  234. end;
  235. procedure TgxPhysManager.WriteForces(stream: TStream);
  236. var
  237. writer: TWriter;
  238. begin
  239. // Writing forces
  240. writer := TWriter.Create(stream, 16384);
  241. try
  242. Forces.WriteToFiler(writer);
  243. finally
  244. writer.Free;
  245. end;
  246. end;
  247. procedure TgxPhysManager.ReadForces(stream: TStream);
  248. var
  249. reader: TReader;
  250. begin
  251. reader := TReader.Create(stream, 16384);
  252. try
  253. Forces.ReadFromFiler(reader);
  254. finally
  255. reader.Free;
  256. end;
  257. end;
  258. procedure TgxPhysManager.SetForces(const val: TgxForces);
  259. begin
  260. Forces.Assign(val);
  261. end;
  262. procedure TgxPhysManager.SetInertias(const val: TList);
  263. begin
  264. fInertias.Assign(val);
  265. end;
  266. procedure TgxPhysManager.SetForceFieldEmitters(const val: TList);
  267. begin
  268. fForceFieldEmitters.Assign(val);
  269. end;
  270. procedure TgxPhysManager.SetScene(const val: TgxScene);
  271. begin
  272. // fScene:=val;
  273. if fScene <> val then
  274. begin
  275. if Assigned(fScene) then
  276. fScene.RemoveFreeNotification(Self);
  277. fScene := val;
  278. if Assigned(fScene) then
  279. fScene.FreeNotification(Self);
  280. end;
  281. end;
  282. function TgxPhysManager.GetForces: TgxForces;
  283. begin
  284. if not Assigned(fForces) then
  285. fForces := TgxForces.Create(Self);
  286. Result := fForces;
  287. end;
  288. // Not accurate yet, because Forces should be re-calculated for each KVector.
  289. // Since forces will depend on distances between objects, then this will require
  290. // a central physics manager, that calculates KVector for all objects, then calculate forces
  291. // between objects for this new estimated state.
  292. //
  293. function TDESolver.StateToArray(): TStateArray;
  294. var
  295. i { ,j } : Integer;
  296. currentpos: Integer;
  297. // state:TStateArray;
  298. begin
  299. currentpos := 0;
  300. for i := 0 to Owner.fInertias.Count - 1 do
  301. begin
  302. TgxBaseInertia(Owner.fInertias.Items[i]).StateToArray(StateArray,
  303. currentpos);
  304. currentpos := currentpos + TgxBaseInertia(Owner.fInertias.Items[i])
  305. .StateSize;
  306. end;
  307. Result := StateArray;
  308. end;
  309. procedure TDESolver.ArrayToState(StateArray: TStateArray);
  310. var
  311. i: Integer;
  312. currentpos: Integer;
  313. begin
  314. currentpos := 0;
  315. for i := 0 to Owner.fInertias.Count - 1 do
  316. begin
  317. TgxBaseInertia(Owner.fInertias.Items[i]).ArrayToState(StateArray,
  318. currentpos);
  319. currentpos := currentpos + TgxBaseInertia(Owner.fInertias.Items[i])
  320. .StateSize;
  321. end;
  322. end;
  323. constructor TDESolver.Create(aOwner: TgxPhysManager);
  324. begin
  325. Self.Owner := aOwner;
  326. end;
  327. destructor TDESolver.Destroy;
  328. begin
  329. //
  330. end;
  331. function TDESolverExplicit.CalcStateDot(): TStateArray;
  332. var
  333. i { ,j } : Integer;
  334. currentpos: Integer;
  335. state: TStateArray;
  336. begin
  337. //
  338. SetLength(state, StateSize);
  339. for i := 0 to StateSize - 1 do
  340. state[i] := StateArray[i];
  341. // state:=StateArray;
  342. currentpos := 0;
  343. for i := 0 to Owner.fInertias.Count - 1 do
  344. begin
  345. TgxBaseInertia(Owner.fInertias.Items[i]).CalcStateDot(state, currentpos);
  346. currentpos := currentpos + TgxBaseInertia(Owner.fInertias.Items[i])
  347. .StateSize;
  348. end;
  349. Result := state;
  350. end;
  351. procedure TDESolverRungeKutta4.Solve(DeltaTime: Real);
  352. var
  353. // X,X0:TStateArray;
  354. Kvectors: array [0 .. 3] of TStateArray;
  355. n: Integer;
  356. StateArray0: TStateArray;
  357. tempStateArray: TStateArray;
  358. // tempState:TgxBInertia;
  359. begin
  360. // tempState:=TgxBInertia.Create(nil);
  361. // tempState.Assign(Self);
  362. tempStateArray := StateToArray();
  363. StateArray0 := tempStateArray;
  364. for n := 0 to 3 do
  365. SetLength(Kvectors[n], Length(StateArray0));
  366. Kvectors[0] := CalcStateDot();
  367. for n := 0 to StateSize - 1 do
  368. tempStateArray[n] := tempStateArray[n] + DeltaTime / 2 * Kvectors[0][n];
  369. ArrayToState(tempStateArray);
  370. Kvectors[1] := CalcStateDot();
  371. for n := 0 to StateSize - 1 do
  372. tempStateArray[n] := tempStateArray[n] + DeltaTime / 2 * Kvectors[1][n];
  373. ArrayToState(tempStateArray);
  374. Kvectors[2] := CalcStateDot();
  375. for n := 0 to StateSize - 1 do
  376. tempStateArray[n] := tempStateArray[n] + DeltaTime / 2 * Kvectors[2][n];
  377. ArrayToState(tempStateArray);
  378. Kvectors[3] := CalcStateDot();
  379. for n := 0 to StateSize - 1 do
  380. begin
  381. tempStateArray[n] := StateArray0[n] + DeltaTime / 6 *
  382. (Kvectors[0][n] + 2 * Kvectors[1][n] + 2 * Kvectors[2][n] +
  383. Kvectors[3][n]);
  384. end;
  385. ArrayToState(tempStateArray);
  386. // NormalizeQuaternion(AngularOrientation);
  387. // tempState.Free();
  388. end;
  389. procedure TDESolverEuler.Solve(DeltaTime: Real);
  390. var
  391. i, j: Integer;
  392. tempState, tempStateDot: TStateArray;
  393. // force1:TAffineVector;
  394. Inertia1: TgxBaseInertia;
  395. tempForce: TAffineVector;
  396. // UnDampedMomentum,DampedMomentum:Real;
  397. begin
  398. {$IFDEF DEBUG}
  399. Write('Euler integration');
  400. {$ENDIF}
  401. for i := 0 to Owner.fInertias.Count - 1 do
  402. begin
  403. Inertia1 := TgxBaseInertia(Owner.fInertias.Items[i]);
  404. // TgxRigidBodyInertia(FObjects.Items[i]).SetTorque(0,0,0);
  405. for j := 0 to Owner.fForceFieldEmitters.Count - 1 do
  406. begin
  407. Inertia1.CalculateForceFieldForce
  408. (TgxBaseForceFieldEmitter(Owner.fForceFieldEmitters.Items[j]));
  409. // Inertia1.ApplyForce(TgxForceFieldEmitter(FForceFieldEmitters.Items[j]).CalculateForceField(Inertia1.OwnerBaseSceneObject));
  410. end;
  411. end;
  412. for i := 0 to Owner.Forces.Count - 1 do
  413. begin
  414. { force1:= } Owner.Forces.Force[i].CalculateForce();
  415. end;
  416. tempState := StateToArray();
  417. tempStateDot := CalcStateDot();
  418. for i := 0 to StateSize - 1 do
  419. tempState[i] := tempState[i] + DeltaTime * tempStateDot[i];
  420. ArrayToState(tempState);
  421. for i := 0 to Owner.fInertias.Count - 1 do
  422. begin
  423. // TGLInertia(FObjects.Items[i]).SetForce(0,0,0);
  424. Inertia1 := TgxBaseInertia(Owner.fInertias.Items[i]);
  425. if Inertia1.DampingEnabled = true then
  426. begin
  427. // UnDampedMomentum:=VectorLength(Inertia1.TranslationSpeed.AsAffineVector);
  428. // DampedMomentum:= Inertia1.TranslationDamping.Calculate(UnDampedMomentum,deltaTime);
  429. // if UnDampedMomentum<>0 then
  430. begin
  431. // ScaleVector(Inertia1.TranslationSpeed.AsAffineVector,DampedMomentum/UnDampedMomentum);
  432. // ScaleVector(Inertia1.LinearMomentum,DampedMomentum/UnDampedMomentum);
  433. end;
  434. // Inertia1.TranslationDamping.Calculate(VectorLength(Inertia1.LinearMomentum),deltaTime);
  435. end;
  436. Inertia1.CalcAuxiliary();
  437. Inertia1.RemoveForces();
  438. end;
  439. // NormalizeQuaternion(AngularOrientation);
  440. end;
  441. constructor TgxPhysManager.Create(aOwner: TComponent);
  442. begin
  443. inherited Create(aOwner);
  444. fInertias := TList.Create();
  445. fForceFieldEmitters := TList.Create();
  446. fForces := TgxForces.Create(Self);
  447. SetDESolver(ssEuler);
  448. ///RegisterManager(Self);
  449. end;
  450. destructor TgxPhysManager.Destroy;
  451. begin
  452. // fScene:=nil;
  453. DeRegisterAllInertias();
  454. DeRegisterAllForceFieldEmitters();
  455. /// DeRegisterManager(Self);
  456. fInertias.Free();
  457. fForceFieldEmitters.Free();
  458. fForces.Free();
  459. inherited Destroy;
  460. end;
  461. procedure TgxPhysManager.Assign(Source: TPersistent);
  462. begin
  463. inherited Assign(Source);
  464. end;
  465. procedure TgxPhysManager.SetDESolver(SolverType: TDESolverType);
  466. var
  467. tempSolver: TDESolver;
  468. begin
  469. if Assigned(DESolver) then
  470. begin
  471. if (fDESolverType <> SolverType) then
  472. case SolverType of
  473. ssRungeKutta4:
  474. begin
  475. // DESolver:=RungeKutta4;
  476. end;
  477. ssEuler:
  478. begin
  479. // DESolver:=Euler;
  480. end;
  481. end;
  482. end
  483. else
  484. begin
  485. // if (fDESolverType<>SolverType) then
  486. case SolverType of
  487. ssRungeKutta4:
  488. begin
  489. DESolver := TDESolverRungeKutta4.Create(Self);
  490. end;
  491. ssEuler:
  492. begin
  493. DESolver := TDESolverEuler.Create(Self);
  494. end;
  495. end;
  496. fDESolverType := SolverType;
  497. end;
  498. end;
  499. procedure TgxPhysManager.RegisterInertia(aInertia: TgxBaseInertia);
  500. begin
  501. if Assigned(aInertia) then
  502. if fInertias.IndexOf(aInertia) < 0 then
  503. begin
  504. fInertias.Add(aInertia);
  505. aInertia.FManager := Self;
  506. DESolver.StateSize := DESolver.StateSize + aInertia.StateSize;
  507. SetLength(DESolver.StateArray, DESolver.StateSize);
  508. end;
  509. end;
  510. procedure TgxPhysManager.DeRegisterInertia(aInertia: TgxBaseInertia);
  511. begin
  512. if Assigned(aInertia) then
  513. begin
  514. aInertia.FManager := nil;
  515. fInertias.Remove(aInertia);
  516. DESolver.StateSize := DESolver.StateSize - aInertia.StateSize;
  517. SetLength(DESolver.StateArray, DESolver.StateSize);
  518. end;
  519. end;
  520. procedure TgxPhysManager.DeRegisterAllInertias;
  521. var
  522. i: Integer;
  523. begin
  524. // Fast deregistration
  525. for i := 0 to fInertias.Count - 1 do
  526. TgxBaseInertia(fInertias[i]).FManager := nil;
  527. fInertias.Clear;
  528. DESolver.StateSize := 0;
  529. // SetLEngth(StateArray,0);
  530. end;
  531. procedure TgxPhysManager.RegisterForceFieldEmitter
  532. (aForceField: TgxBaseForceFieldEmitter);
  533. begin
  534. if Assigned(aForceField) then
  535. if fForceFieldEmitters.IndexOf(aForceField) < 0 then
  536. begin
  537. fForceFieldEmitters.Add(aForceField);
  538. aForceField.FManager := Self;
  539. end;
  540. end;
  541. procedure TgxPhysManager.DeRegisterForceFieldEmitter
  542. (aForceField: TgxBaseForceFieldEmitter);
  543. begin
  544. if Assigned(aForceField) then
  545. begin
  546. aForceField.FManager := nil;
  547. fForceFieldEmitters.Remove(aForceField);
  548. end;
  549. end;
  550. procedure TgxPhysManager.DeRegisterAllForceFieldEmitters;
  551. var
  552. i: Integer;
  553. begin
  554. // Fast deregistration
  555. for i := 0 to fForceFieldEmitters.Count - 1 do
  556. TgxBaseForceFieldEmitter(fForceFieldEmitters[i]).FManager := nil;
  557. fForceFieldEmitters.Clear;
  558. end;
  559. function TgxPhysManager.CalculateKE(): Real;
  560. var
  561. Total: Real;
  562. i: Integer;
  563. begin
  564. Total := 0;
  565. for i := 0 to fInertias.Count - 1 do
  566. begin
  567. // calculate fInertias[i] KE
  568. Total := Total + TgxBaseInertia(fInertias.Items[i]).CalculateKE();
  569. end;
  570. Result := Total;
  571. end;
  572. function TgxPhysManager.CalculatePE(): Real;
  573. var
  574. Total: Real;
  575. i: Integer;
  576. begin
  577. Total := 0;
  578. for i := 0 to fInertias.Count - 1 do
  579. begin
  580. // calculate fobject[i] PE
  581. Total := Total + TgxBaseInertia(fInertias.Items[i]).CalculatePE();
  582. end;
  583. Result := Total;
  584. end;
  585. procedure TgxPhysManager.CalculateNextState(DeltaTime: Real);
  586. begin
  587. if Assigned(DESolver) then
  588. DESolver.Solve(DeltaTime);
  589. end;
  590. constructor TgxForces.Create(aOwner: TPersistent);
  591. begin
  592. // Assert(aOwner is TgxBaseSceneObject);
  593. inherited Create(aOwner);
  594. end;
  595. { destructor TgxForces.Destroy;
  596. begin
  597. inherited Destroy;
  598. end;
  599. }
  600. class function TgxForces.ItemsClass: TXCollectionItemClass;
  601. begin
  602. Result := TgxForce;
  603. end;
  604. function TgxForces.GetForce(index: Integer): TgxForce;
  605. begin
  606. Result := TgxForce(Items[index]);
  607. end;
  608. function TgxForces.CanAdd(aClass: TXCollectionItemClass): Boolean;
  609. begin
  610. Result := { (not aClass.InheritsFrom(TGLEffect)) and }
  611. (inherited CanAdd(aClass));
  612. end;
  613. // -----------------------------------------------------------------------------
  614. procedure TgxBaseInertia.SetManager(const val: TgxPhysManager);
  615. begin
  616. if val <> FManager then
  617. begin
  618. if Assigned(FManager) then
  619. FManager.DeRegisterInertia(Self);
  620. if Assigned(val) then
  621. val.RegisterInertia(Self);
  622. // Write(val.GetNamePath);
  623. end;
  624. end;
  625. procedure TgxBaseInertia.Loaded;
  626. var
  627. mng: TComponent;
  628. begin
  629. inherited;
  630. if FManagerName <> '' then
  631. begin
  632. ///? mng := FindManager(TgxPhysManager, FManagerName);
  633. if Assigned(mng) then
  634. Manager := TgxPhysManager(mng);
  635. FManagerName := '';
  636. end;
  637. end;
  638. procedure TgxBaseInertia.WriteToFiler(writer: TWriter);
  639. begin
  640. inherited;
  641. with writer do
  642. begin
  643. WriteInteger(0); // Archive Version 0
  644. WriteBoolean(FDampingEnabled);
  645. if Assigned(FManager) then
  646. WriteString(FManager.GetNamePath)
  647. else
  648. WriteString('');
  649. end;
  650. end;
  651. procedure TgxBaseInertia.ReadFromFiler(reader: TReader);
  652. begin
  653. inherited;
  654. with reader do
  655. begin
  656. ReadInteger; // ignore archiveVersion
  657. FDampingEnabled := ReadBoolean;
  658. FManagerName := ReadString;
  659. Manager := nil;
  660. end;
  661. // Loaded; //DB100
  662. end;
  663. constructor TgxBaseInertia.Create(aOwner: TXCollection);
  664. begin
  665. inherited Create(aOwner);
  666. FDampingEnabled := true;
  667. end;
  668. destructor TgxBaseInertia.Destroy;
  669. begin
  670. SetManager(nil);
  671. inherited Destroy;
  672. end;
  673. procedure TgxBaseInertia.Assign(Source: TPersistent);
  674. begin
  675. if Source.ClassType = Self.ClassType then
  676. begin
  677. StateSize := TgxBaseInertia(Source).StateSize;
  678. FDampingEnabled := TgxBaseInertia(Source).DampingEnabled;
  679. Manager := TgxBaseInertia(Source).Manager;
  680. end;
  681. inherited Assign(Source);
  682. end;
  683. procedure TgxBaseInertia.StateToArray(var StateArray: TStateArray;
  684. StatePos: Integer);
  685. begin
  686. end;
  687. procedure TgxBaseInertia.ArrayToState( { var } StateArray: TStateArray;
  688. StatePos: Integer);
  689. begin
  690. end;
  691. procedure TgxBaseInertia.CalcStateDot(var StateArray: TStateArray;
  692. StatePos: Integer);
  693. begin
  694. end;
  695. procedure TgxBaseInertia.RemoveForces();
  696. begin
  697. end;
  698. procedure TgxBaseInertia.CalculateForceFieldForce(ForceFieldEmitter
  699. : TgxBaseForceFieldEmitter);
  700. begin
  701. end;
  702. function TgxBaseInertia.CalculateKE(): Real;
  703. begin
  704. Result := 0;
  705. end;
  706. function TgxBaseInertia.CalculatePE(): Real;
  707. begin
  708. Result := 0;
  709. end;
  710. procedure TgxBaseInertia.CalcAuxiliary();
  711. begin
  712. end;
  713. procedure TgxBaseInertia.SetUpStartingState();
  714. begin
  715. end;
  716. // -----------------------------------------------------------------------------
  717. procedure TgxBaseForceFieldEmitter.SetManager(const val: TgxPhysManager);
  718. begin
  719. if val <> FManager then
  720. begin
  721. if Assigned(FManager) then
  722. FManager.DeRegisterForceFieldEmitter(Self);
  723. if Assigned(val) then
  724. val.RegisterForceFieldEmitter(Self);
  725. end;
  726. end;
  727. procedure TgxBaseForceFieldEmitter.Loaded;
  728. var
  729. mng: TComponent;
  730. begin
  731. inherited;
  732. if FManagerName <> '' then
  733. begin
  734. ///? mng := FindManager(TgxPhysManager, FManagerName);
  735. if Assigned(mng) then
  736. Manager := TgxPhysManager(mng);
  737. FManagerName := '';
  738. end;
  739. end;
  740. procedure TgxBaseForceFieldEmitter.WriteToFiler(writer: TWriter);
  741. begin
  742. inherited; // Dan Bartlett
  743. with writer do
  744. begin
  745. WriteInteger(0); // Archive Version 0
  746. if Assigned(FManager) then
  747. WriteString(FManager.GetNamePath)
  748. else
  749. WriteString('');
  750. end;
  751. end;
  752. procedure TgxBaseForceFieldEmitter.ReadFromFiler(reader: TReader);
  753. begin
  754. inherited;
  755. with reader do
  756. begin
  757. ReadInteger; // ignore archiveVersion
  758. FManagerName := ReadString;
  759. Manager := nil;
  760. end;
  761. // Loaded; //DB100
  762. end;
  763. constructor TgxBaseForceFieldEmitter.Create(aOwner: TXCollection);
  764. begin
  765. inherited Create(aOwner);
  766. end;
  767. destructor TgxBaseForceFieldEmitter.Destroy;
  768. begin
  769. SetManager(nil);
  770. inherited Destroy;
  771. end;
  772. procedure TgxBaseForceFieldEmitter.Assign(Source: TPersistent);
  773. begin
  774. if Source.ClassType = Self.ClassType then
  775. begin
  776. Manager := TgxBaseForceFieldEmitter(Source).Manager;
  777. end;
  778. inherited Assign(Source);
  779. end;
  780. // CalculateForceField
  781. function TgxBaseForceFieldEmitter.CalculateForceField(Body: TgxBaseSceneObject)
  782. : TAffineVector;
  783. begin
  784. Result := nullVector;
  785. end;
  786. initialization // ------------------------------------------------------------
  787. // RegisterClasses([TgxForces]);
  788. // RegisterClasses([TgxPhysManager, TgxBaseInertia, TgxBaseForceFieldEmitter]);
  789. // RegisterXCollectionItemClass(TgxBaseInertia);
  790. // RegisterXCollectionItemClass(TgxBaseForceFieldEmitter);
  791. // RegisterXCollectionItemClass(TGLPhysicsForce);
  792. // ------------------------------------------------------------------
  793. end.