2
0

GXS.PhysInertias.pas 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. //
  2. // The graphics engine GXScene
  3. //
  4. unit GXS.PhysInertias;
  5. interface
  6. uses
  7. System.SysUtils,
  8. System.Classes,
  9. GXS.XCollection,
  10. Stage.VectorGeometry,
  11. Stage.VectorTypes,
  12. Stage.Strings,
  13. GXS.Coordinates,
  14. GXS.BaseClasses,
  15. GXS.PersistentClasses,
  16. GXS.PhysManager,
  17. GXS.Scene,
  18. GXS.Behaviours;
  19. type
  20. TgxParticleInertia = class(TgxBaseInertia)
  21. // modified from TgxBInertia
  22. private
  23. FMass: Single;
  24. FTranslationSpeed: TgxCoordinates;
  25. FTranslationDamping: TgxDamping;
  26. protected
  27. function CalcLinearPositionDot(): TAffineVector;
  28. function CalcLinearMomentumDot(): TAffineVector;
  29. procedure SetTranslationSpeed(const val: TgxCoordinates);
  30. procedure SetTranslationDamping(const val: TgxDamping);
  31. public
  32. fForce: TAffineVector;
  33. LinearPosition: TAffineVector;
  34. LinearMomentum: TAffineVector;
  35. procedure StateToArray(var StateArray: TStateArray; StatePos: Integer); override;
  36. procedure ArrayToState( { var } StateArray: TStateArray; StatePos: Integer); override;
  37. procedure CalcStateDot(var StateArray: TStateArray; StatePos: Integer); override;
  38. procedure RemoveForces(); override;
  39. procedure CalculateForceFieldForce(ForceFieldEmitter
  40. : TgxBaseForceFieldEmitter); override;
  41. procedure CalcAuxiliary(); override;
  42. procedure SetUpStartingState(); override;
  43. function CalculateKE(): Real; override;
  44. function CalculatePE(): Real; override;
  45. procedure SetForce(x, y, z: Real); virtual;
  46. procedure ApplyForce(x, y, z: Real); overload; virtual;
  47. procedure ApplyForce(Force: TAffineVector); overload; virtual;
  48. procedure ApplyForce(pos, Force: TAffineVector); overload; virtual;
  49. procedure ApplyLocalForce(pos, Force: TAffineVector); virtual;
  50. procedure ApplyImpulse(j, x, y, z: Real); overload; virtual;
  51. procedure ApplyImpulse(j: Single; normal: TAffineVector); overload; virtual;
  52. procedure ApplyDamping(damping: TgxDamping); virtual;
  53. constructor Create(aOwner: TXCollection); override;
  54. destructor Destroy; override;
  55. procedure Assign(Source: TPersistent); override;
  56. procedure WriteToFiler(writer: TWriter); override;
  57. procedure ReadFromFiler(reader: TReader); override;
  58. class function FriendlyName: String; override;
  59. class function FriendlyDescription: String; override;
  60. class function UniqueItem: Boolean; override;
  61. // Inverts the translation vector
  62. procedure MirrorTranslation;
  63. (* Bounce speed as if hitting a surface.
  64. restitution is the coefficient of restituted energy (1=no energy loss,
  65. 0=no bounce). The normal is NOT assumed to be normalized. *)
  66. procedure SurfaceBounce(const surfaceNormal: TGLVector; restitution: Single);
  67. published
  68. property Mass: Single read FMass write FMass;
  69. property TranslationSpeed: TgxCoordinates read FTranslationSpeed
  70. write SetTranslationSpeed;
  71. (* Enable/Disable damping (damping has a high cpu-cycle cost).
  72. Damping is enabled by default. *)
  73. // property DampingEnabled : Boolean read FDampingEnabled write FDampingEnabled;
  74. (* Damping applied to translation speed.<br>
  75. Note that it is not "exactly" applied, ie. if damping would stop
  76. your object after 0.5 time unit, and your progression steps are
  77. of 1 time unit, there will be an integration error of 0.5 time unit. *)
  78. property TranslationDamping: TgxDamping read FTranslationDamping
  79. write SetTranslationDamping;
  80. end;
  81. TgxRigidBodyInertia = class;
  82. (* Stores Inertia Tensor for TgxRigidBodyInertia model *)
  83. TgxInertiaTensor = class(TgxUpdateAbleObject)
  84. private
  85. fm11, fm12, fm13, fm21, fm22, fm23, fm31, fm32, fm33: Single;
  86. public
  87. constructor Create(aOwner: TPersistent); override;
  88. destructor Destroy; override;
  89. procedure Assign(Source: TPersistent); override;
  90. procedure WriteToFiler(writer: TWriter);
  91. procedure ReadFromFiler(reader: TReader);
  92. published
  93. property m11: Single read fm11 write fm11;
  94. property m12: Single read fm12 write fm12;
  95. property m13: Single read fm13 write fm13;
  96. property m21: Single read fm21 write fm21;
  97. property m22: Single read fm22 write fm22;
  98. property m23: Single read fm23 write fm23;
  99. property m31: Single read fm31 write fm31;
  100. property m32: Single read fm32 write fm32;
  101. property m33: Single read fm33 write fm33;
  102. end;
  103. (* A more complex model than TgxBInertia for Inertia *)
  104. TgxRigidBodyInertia = class(TgxParticleInertia)
  105. private
  106. fDensity: Real;
  107. fBodyInertiaTensor: TAffineMAtrix;
  108. fBodyInverseInertiaTensor: TAffineMAtrix;
  109. fInertiaTensor: TgxInertiaTensor;
  110. InverseInertiaTensor: TAffineMAtrix;
  111. // LinearVelocity:TAffineVector;
  112. fRotationSpeed: TgxCoordinates;
  113. /// AngularVelocity:TAffineVector; //rotation about axis, magnitude=speed
  114. // damping properties
  115. FRotationDamping: TgxDamping;
  116. protected
  117. // torques
  118. fTorque: TAffineVector;
  119. procedure SetLinearDamping(const val: TgxDamping);
  120. procedure SetAngularDamping(const val: TgxDamping);
  121. public
  122. AngularOrientation: TQuaternion; // As Quat will help improve accuracy
  123. R: TMatrix3f; // corresponds to AngularOrientation
  124. AngularMomentum: TAffineVector;
  125. procedure StateToArray(var StateArray: TStateArray;
  126. StatePos: Integer); override;
  127. procedure ArrayToState( (* var *) StateArray: TStateArray;
  128. StatePos: Integer); override;
  129. procedure CalcStateDot(var StateArray: TStateArray;
  130. StatePos: Integer); override;
  131. procedure ApplyImpulse(j, xpos, ypos, zpos, x, y, z: Real); overload;
  132. procedure ApplyImpulse(j: Single; position, normal: TAffineVector);
  133. overload;
  134. procedure ApplyDamping(damping: TgxDamping); override;
  135. // function CalcLinearPositionDot():TAffineVector;
  136. // function CalcLinearMomentumDot():TAffineVector;
  137. function CalcAngularOrientationDot(): TQuaternion;
  138. function CalcAngularVelocityDot(): TAffineVector;
  139. function CalculateKE(): Real; override;
  140. function CalculatePE(): Real; override;
  141. procedure CalcAuxiliary(); override;
  142. procedure SetUpStartingState(); override;
  143. constructor Create(aOwner: TXCollection); override;
  144. destructor Destroy; override;
  145. procedure Assign(Source: TPersistent); override;
  146. procedure WriteToFiler(writer: TWriter); override;
  147. procedure ReadFromFiler(reader: TReader); override;
  148. class function FriendlyName: String; override;
  149. class function FriendlyDescription: String; override;
  150. class function UniqueItem: Boolean; override;
  151. // function Star(Vector:TAffineVector):TGLMatrix;
  152. function QuaternionToString(Quat: TQuaternion): String;
  153. procedure RemoveForces(); override;
  154. procedure SetTorque(x, y, z: Real);
  155. procedure ApplyTorque(x, y, z: Real);
  156. procedure ApplyForce(pos, Force: TAffineVector); override;
  157. procedure ApplyLocalForce(pos, Force: TVector3f); override;
  158. procedure ApplyLocalImpulse(xpos, ypos, zpos, x, y, z: Real);
  159. procedure SetInertiaTensor(newVal: TgxInertiaTensor);
  160. procedure SetRotationSpeed(const val: TgxCoordinates);
  161. procedure SetRotationDamping(const val: TgxDamping);
  162. published
  163. property Density: Real read fDensity write fDensity;
  164. property InertiaTensor: TgxInertiaTensor read fInertiaTensor
  165. write SetInertiaTensor;
  166. property RotationSpeed: TgxCoordinates read fRotationSpeed
  167. write SetRotationSpeed;
  168. property RotationDamping: TgxDamping read FRotationDamping
  169. write SetRotationDamping;
  170. end;
  171. (* Returns or creates the TgxParticleInertia within the given behaviours.
  172. This helper function is convenient way to access a TgxParticleInertia. *)
  173. function GetOrCreateParticleInertia(behaviours: TgxBehaviours): TgxParticleInertia; overload;
  174. (* Returns or creates the TgxParticleInertia within the given object's behaviours.
  175. This helper function is convenient way to access a TgxParticleInertia. *)
  176. function GetOrCreateParticleInertia(obj: TgxBaseSceneObject): TgxParticleInertia; overload;
  177. (* Returns or creates the TgxRigidBodyInertia within the given behaviours.
  178. This helper function is convenient way to access a TgxRigidBodyInertia. *)
  179. function GetOrCreateRigidBodyInertia(behaviours: TgxBehaviours): TgxRigidBodyInertia; overload;
  180. (* Returns or creates the TgxRigidBodyInertia within the given object's behaviours.
  181. This helper function is convenient way to access a TgxRigidBodyInertia. *)
  182. function GetOrCreateRigidBodyInertia(obj: TgxBaseSceneObject): TgxRigidBodyInertia; overload;
  183. const
  184. DebugMode = false;
  185. implementation //-----------------------------------------------------------
  186. // ------------------
  187. // ------------------ TgxParticleInertia ------------------
  188. // ------------------
  189. constructor TgxParticleInertia.Create(aOwner: TXCollection);
  190. begin
  191. inherited Create(aOwner);
  192. FMass := 1;
  193. StateSize := 6;
  194. FTranslationSpeed := TgxCoordinates.CreateInitialized(Self, NullHmgVector, csVector);
  195. LinearPosition := OwnerBaseSceneObject.position.AsAffineVector;
  196. LinearMomentum := FTranslationSpeed.AsAffineVector;
  197. FTranslationDamping := TgxDamping.Create(Self);
  198. end;
  199. destructor TgxParticleInertia.Destroy;
  200. begin
  201. FTranslationDamping.Free;
  202. FTranslationSpeed.Free;
  203. inherited Destroy;
  204. end;
  205. procedure TgxParticleInertia.Assign(Source: TPersistent);
  206. begin
  207. if Source.ClassType = Self.ClassType then
  208. begin
  209. FMass := TgxParticleInertia(Source).FMass;
  210. FTranslationSpeed.Assign(TgxParticleInertia(Source).FTranslationSpeed);
  211. LinearPosition := TgxParticleInertia(Source).LinearPosition;
  212. LinearMomentum := TgxParticleInertia(Source).LinearMomentum;
  213. // FDampingEnabled:=TGLInertia(Source).DampingEnabled;
  214. FTranslationDamping.Assign(TgxParticleInertia(Source).TranslationDamping);
  215. // FRotationDamping.Assign(TgxBInertia(Source).RotationDamping);
  216. end;
  217. inherited Assign(Source);
  218. end;
  219. procedure TgxParticleInertia.WriteToFiler(writer: TWriter);
  220. begin
  221. inherited;
  222. with writer do
  223. begin
  224. WriteInteger(0); // Archive Version 0
  225. WriteFloat(FMass);
  226. Write(LinearPosition, SizeOf(LinearPosition));
  227. Write(LinearMomentum, SizeOf(LinearMomentum));
  228. Write(fForce, SizeOf(fForce));
  229. FTranslationSpeed.WriteToFiler(writer);
  230. FTranslationDamping.WriteToFiler(writer);
  231. end;
  232. end;
  233. procedure TgxParticleInertia.ReadFromFiler(reader: TReader);
  234. begin
  235. inherited;
  236. with reader do
  237. begin
  238. ReadInteger; // ignore archiveVersion
  239. FMass := ReadFloat;
  240. Read(LinearPosition, SizeOf(LinearPosition));
  241. Read(LinearMomentum, SizeOf(LinearMomentum));
  242. Read(fForce, SizeOf(fForce));
  243. FTranslationSpeed.ReadFromFiler(reader);
  244. FTranslationDamping.ReadFromFiler(reader);
  245. end;
  246. // Loaded;
  247. SetUpStartingState();
  248. end;
  249. procedure TgxParticleInertia.SetTranslationSpeed(const val: TgxCoordinates);
  250. begin
  251. FTranslationSpeed.Assign(val);
  252. LinearMomentum := VectorScale(FTranslationSpeed.AsAffineVector, FMass);
  253. end;
  254. procedure TgxParticleInertia.SetUpStartingState();
  255. begin
  256. LinearPosition := OwnerBaseSceneObject.position.AsAffineVector;
  257. LinearMomentum := VectorScale(TranslationSpeed.AsAffineVector, Mass);
  258. end;
  259. procedure TgxParticleInertia.CalcAuxiliary( { RBody:TgxRigidBody } );
  260. begin
  261. TranslationSpeed.AsAffineVector := VectorScale(LinearMomentum, 1 / Mass);
  262. // OwnerBaseSceneObject.Matrix:=QuaternionToMatrix(AngularOrientation);
  263. OwnerBaseSceneObject.position.AsAffineVector := LinearPosition; // position
  264. // OwnerBaseSceneObject.position.x:=LinearPosition[0];//position
  265. // OwnerBaseSceneObject.position.y:=LinearPosition[1];
  266. // OwnerBaseSceneObject.position.z:=LinearPosition[2];
  267. end;
  268. procedure TgxParticleInertia.RemoveForces();
  269. begin
  270. fForce := nullVector;
  271. end;
  272. procedure TgxParticleInertia.CalculateForceFieldForce(ForceFieldEmitter
  273. : TgxBaseForceFieldEmitter);
  274. begin
  275. ForceFieldEmitter.CalculateForceField(Self.OwnerBaseSceneObject);
  276. end;
  277. function TgxParticleInertia.CalculateKE(): Real;
  278. begin
  279. Result := 1 / (2 * Mass) * VectorNorm(LinearMomentum);
  280. end;
  281. function TgxParticleInertia.CalculatePE(): Real;
  282. begin
  283. // need to find potentials due to fields acting on body
  284. // may be easier to do via ForceFieldEmitters?
  285. Result := 0;
  286. end;
  287. procedure TgxParticleInertia.SetForce(x, y, z: Real);
  288. begin
  289. fForce.x := x;
  290. fForce.y := y;
  291. fForce.z := z;
  292. end;
  293. procedure TgxParticleInertia.ApplyForce(x, y, z: Real);
  294. begin
  295. fForce.X := fForce.X + x;
  296. fForce.Y := fForce.Y + y;
  297. fForce.Z := fForce.Z + z;
  298. end;
  299. procedure TgxParticleInertia.ApplyForce(Force: TAffineVector);
  300. begin
  301. fForce := VectorAdd(fForce, Force);
  302. end;
  303. procedure TgxParticleInertia.ApplyForce(pos, Force: TAffineVector);
  304. // var
  305. // abspos:TAffineVector;
  306. begin
  307. fForce := VectorAdd(fForce, Force);
  308. // abspos:=VectorTransform(pos,R);
  309. // fTorque:=VectorAdd(fTorque,VectorCrossProduct(abspos,force));
  310. // fForce:=VectorAdd(fForce,force);
  311. end;
  312. procedure TgxParticleInertia.ApplyLocalForce(pos, Force: TAffineVector);
  313. // var
  314. // abspos:TAffineVector;
  315. // absForce:TAffineVector;
  316. begin
  317. // abspos:=VectorTransform(pos,R);
  318. // absForce:=VectorTransform(Force,R);
  319. // fTorque:=VectorAdd(fTorque,VectorCrossProduct(abspos,absforce));
  320. fForce := VectorAdd(fForce, Force);
  321. end;
  322. procedure TgxParticleInertia.ApplyImpulse(j, x, y, z: Real);
  323. begin
  324. // V2 = V1 + (j/M)n
  325. // V2.M = V1.M +j.n
  326. LinearMomentum.X := LinearMomentum.X + j * x;
  327. LinearMomentum.Y := LinearMomentum.Y + j * y;
  328. LinearMomentum.Z := LinearMomentum.Z + j * z;
  329. end;
  330. procedure TgxParticleInertia.ApplyImpulse(j: Single; normal: TAffineVector);
  331. begin
  332. CombineVector(LinearMomentum, normal, j);
  333. end;
  334. procedure TgxParticleInertia.ApplyDamping(damping: TgxDamping);
  335. var
  336. velocity: TAffineVector;
  337. v: Real;
  338. dampingForce: TAffineVector;
  339. begin
  340. velocity := VectorScale(LinearMomentum, 1 / Mass); // v = p/m
  341. // apply force in opposite direction to velocity
  342. v := VectorLength(velocity);
  343. // F = -Normalised(V)*( Constant + (Linear)*(V) + (Quadtratic)*(V)*(V) )
  344. dampingForce := VectorScale(VectorNormalize(velocity),
  345. -(damping.Constant + damping.Linear * v + damping.Quadratic * v * v));
  346. (*
  347. dampingForce:=VectorScale(VectorNormalize(velocity),
  348. -(Damping.Constant+Damping.Linear*v+Damping.Quadratic*v*v));
  349. *)
  350. ApplyForce(dampingForce);
  351. end;
  352. procedure TgxParticleInertia.SetTranslationDamping(const val: TgxDamping);
  353. begin
  354. FTranslationDamping.Assign(val);
  355. end;
  356. class function TgxParticleInertia.FriendlyName: String;
  357. begin
  358. Result := 'Particle Inertia';
  359. end;
  360. class function TgxParticleInertia.FriendlyDescription: String;
  361. begin
  362. Result := 'A simple translation inertia';
  363. end;
  364. class function TgxParticleInertia.UniqueItem: Boolean;
  365. begin
  366. Result := True;
  367. end;
  368. function TgxParticleInertia.CalcLinearPositionDot(): TAffineVector;
  369. begin
  370. Result := VectorScale(LinearMomentum, 1 / FMass);
  371. // Result:=FTranslationSpeed.AsAffineVector;
  372. end;
  373. function TgxParticleInertia.CalcLinearMomentumDot(): TAffineVector;
  374. begin
  375. Result := fForce;
  376. end;
  377. procedure TgxParticleInertia.StateToArray(var StateArray: TStateArray;
  378. StatePos: Integer);
  379. begin
  380. // SetLength(Result,StateSize);
  381. StateArray[StatePos] := LinearPosition.X; // position
  382. StateArray[StatePos + 1] := LinearPosition.Y;
  383. StateArray[StatePos + 2] := LinearPosition.Z;
  384. StateArray[StatePos + 3] := LinearMomentum.X; // momentum
  385. StateArray[StatePos + 4] := LinearMomentum.Y;
  386. StateArray[StatePos + 5] := LinearMomentum.Z;
  387. end;
  388. procedure TgxParticleInertia.ArrayToState(StateArray: TStateArray;
  389. StatePos: Integer);
  390. begin
  391. LinearPosition.X := StateArray[StatePos];
  392. LinearPosition.Y := StateArray[StatePos + 1];
  393. LinearPosition.Z := StateArray[StatePos + 2];
  394. LinearMomentum.X := StateArray[StatePos + 3];
  395. LinearMomentum.Y := StateArray[StatePos + 4];
  396. LinearMomentum.Z := StateArray[StatePos + 5];
  397. // TODO change?
  398. (* OwnerBaseSceneObject.position.x:=StateArray[StatePos];//position
  399. OwnerBaseSceneObject.position.y:=StateArray[StatePos+1];
  400. OwnerBaseSceneObject.position.z:=StateArray[StatePos+2];
  401. FTranslationSpeed.X:=StateArray[StatePos+3]/fMass;//velocity
  402. FTranslationSpeed.Y:=StateArray[StatePos+4]/fMass;
  403. FTranslationSpeed.Z:=StateArray[StatePos+5]/fMass;
  404. *)
  405. end;
  406. procedure TgxParticleInertia.CalcStateDot(var StateArray: TStateArray;
  407. StatePos: Integer);
  408. var
  409. LinPos, LinMom: TAffineVector;
  410. begin
  411. LinPos := CalcLinearPositionDot();
  412. LinMom := CalcLinearMomentumDot();
  413. StateArray[StatePos] := LinPos.X;
  414. StateArray[StatePos + 1] := LinPos.Y;
  415. StateArray[StatePos + 2] := LinPos.Z;
  416. StateArray[StatePos + 3] := LinMom.X;
  417. StateArray[StatePos + 4] := LinMom.Y;
  418. StateArray[StatePos + 5] := LinMom.Z;
  419. end;
  420. procedure TgxParticleInertia.MirrorTranslation;
  421. begin
  422. FTranslationSpeed.Invert;
  423. end;
  424. procedure TgxParticleInertia.SurfaceBounce(const surfaceNormal: TGLVector;
  425. restitution: Single);
  426. var
  427. f: Single;
  428. begin
  429. // does the current speed vector comply?
  430. f := VectorDotProduct(FTranslationSpeed.AsVector, surfaceNormal);
  431. if f < 0 then
  432. begin
  433. // remove the non-complying part of the speed vector
  434. FTranslationSpeed.AddScaledVector(-f / VectorNorm(surfaceNormal) *
  435. (1 + restitution), surfaceNormal);
  436. end;
  437. end;
  438. function GetOrCreateParticleInertia(behaviours: TgxBehaviours)
  439. : TgxParticleInertia;
  440. var
  441. i: Integer;
  442. begin
  443. i := behaviours.IndexOfClass(TgxParticleInertia);
  444. if i >= 0 then
  445. Result := TgxParticleInertia(behaviours[i])
  446. else
  447. Result := TgxParticleInertia.Create(behaviours);
  448. end;
  449. function GetOrCreateParticleInertia(obj: TgxBaseSceneObject)
  450. : TgxParticleInertia;
  451. begin
  452. Result := GetOrCreateParticleInertia(obj.behaviours);
  453. end;
  454. // -----------------------------------------------------------------------
  455. // ------------ TgxInertiaTensor
  456. // -----------------------------------------------------------------------
  457. constructor TgxInertiaTensor.Create(aOwner: TPersistent);
  458. begin
  459. inherited Create(aOwner);
  460. fm11 := 1;
  461. fm22 := 1;
  462. fm33 := 1;
  463. end;
  464. destructor TgxInertiaTensor.Destroy;
  465. begin
  466. inherited Destroy;
  467. end;
  468. procedure TgxInertiaTensor.Assign(Source: TPersistent);
  469. begin
  470. inherited;
  471. fm11 := TgxInertiaTensor(Source).fm11;
  472. fm12 := TgxInertiaTensor(Source).fm12;
  473. fm13 := TgxInertiaTensor(Source).fm13;
  474. fm21 := TgxInertiaTensor(Source).fm21;
  475. fm22 := TgxInertiaTensor(Source).fm22;
  476. fm23 := TgxInertiaTensor(Source).fm23;
  477. fm31 := TgxInertiaTensor(Source).fm31;
  478. fm32 := TgxInertiaTensor(Source).fm32;
  479. fm33 := TgxInertiaTensor(Source).fm33;
  480. end;
  481. procedure TgxInertiaTensor.WriteToFiler(writer: TWriter);
  482. begin
  483. inherited;
  484. with writer do
  485. begin
  486. WriteInteger(0); // Archive Version 0
  487. WriteFloat(fm11);
  488. WriteFloat(fm12);
  489. WriteFloat(fm13);
  490. WriteFloat(fm21);
  491. WriteFloat(fm22);
  492. WriteFloat(fm23);
  493. WriteFloat(fm31);
  494. WriteFloat(fm32);
  495. WriteFloat(fm33);
  496. end;
  497. end;
  498. procedure TgxInertiaTensor.ReadFromFiler(reader: TReader);
  499. begin
  500. inherited;
  501. with reader do
  502. begin
  503. ReadInteger(); // Archive Version 0
  504. fm11 := ReadFloat();
  505. fm12 := ReadFloat();
  506. fm13 := ReadFloat();
  507. fm21 := ReadFloat();
  508. fm22 := ReadFloat();
  509. fm23 := ReadFloat();
  510. fm31 := ReadFloat();
  511. fm32 := ReadFloat();
  512. fm33 := ReadFloat();
  513. end;
  514. end;
  515. //--------------------------
  516. // TgxRigidBodyInertia
  517. //--------------------------
  518. procedure TgxRigidBodyInertia.SetInertiaTensor(newVal: TgxInertiaTensor);
  519. begin
  520. fInertiaTensor := newVal;
  521. end;
  522. procedure TgxRigidBodyInertia.SetRotationSpeed(const val: TgxCoordinates);
  523. begin
  524. AngularMomentum := VectorTransform(val.AsAffineVector, fBodyInertiaTensor);
  525. fRotationSpeed.Assign(val);
  526. end;
  527. procedure TgxRigidBodyInertia.SetRotationDamping(const val: TgxDamping);
  528. begin
  529. FRotationDamping.Assign(val);
  530. end;
  531. procedure TgxRigidBodyInertia.ApplyImpulse(j, xpos, ypos, zpos, x, y, z: Real);
  532. begin
  533. // V2 = V1 + (j/M)n
  534. // V2.M = V1.M +j.n
  535. LinearMomentum.X := LinearMomentum.X + j * x;
  536. LinearMomentum.Y := LinearMomentum.Y + j * y;
  537. LinearMomentum.Z := LinearMomentum.Z + j * z;
  538. AngularMomentum.X := AngularMomentum.X + j * x * xpos;
  539. AngularMomentum.Y := AngularMomentum.Y + j * y * ypos;
  540. AngularMomentum.Z := AngularMomentum.Z + j * z * zpos;
  541. end;
  542. procedure TgxRigidBodyInertia.ApplyImpulse(j: Single;
  543. position, normal: TAffineVector);
  544. begin
  545. CombineVector(LinearMomentum, normal, j);
  546. CombineVector(AngularMomentum, VectorCrossProduct(position, normal), j); // ?
  547. end;
  548. procedure TgxRigidBodyInertia.ApplyDamping(damping: TgxDamping);
  549. var
  550. velocity, angularvelocity: TAffineVector;
  551. v, angularv: Real;
  552. dampingForce: TAffineVector;
  553. angulardampingForce: TAffineVector;
  554. begin
  555. velocity := VectorScale(LinearMomentum, 1 / Mass); // v = p/m
  556. // apply force in opposite direction to velocity
  557. v := VectorLength(velocity);
  558. // F = -Normalised(V)*( Constant + (Linear)*(V) + (Quadtratic)*(V)*(V) )
  559. dampingForce := VectorScale(VectorNormalize(velocity),
  560. -(damping.Constant + damping.Linear * v + damping.Quadratic * v * v));
  561. // ScaleVector(AngularMomentum,0.999);
  562. // ScaleVector(AngularVelocity,Damping.Constant);
  563. // dampingForce:=VectorScale(VectorNormalize(velocity),-(Damping.Constant+Damping.Linear*v+Damping.Quadratic*v*v));
  564. ApplyForce(dampingForce);
  565. angularvelocity := RotationSpeed.AsAffineVector; // v = p/m
  566. // apply force in opposite direction to velocity
  567. angularv := VectorLength(angularvelocity);
  568. // F = -Normalised(V)*( Constant + (Linear)*(V) + (Quadtratic)*(V)*(V) )
  569. angulardampingForce := VectorScale(VectorNormalize(angularvelocity),
  570. -(RotationDamping.Constant + RotationDamping.Linear * v +
  571. RotationDamping.Quadratic * v * v));
  572. // ScaleVector(AngularMomentum,0.999);
  573. // ScaleVector(AngularVelocity,Damping.Constant);
  574. // dampingForce:=VectorScale(VectorNormalize(velocity),-(Damping.Constant+Damping.Linear*v+Damping.Quadratic*v*v));
  575. ApplyTorque(angulardampingForce.X, angulardampingForce.Y, angulardampingForce.Z);
  576. end;
  577. procedure TgxRigidBodyInertia.CalcStateDot(var StateArray: TStateArray;
  578. StatePos: Integer);
  579. var
  580. LinPos, LinMom, AngMom: TAffineVector;
  581. AngPos: TQuaternion;
  582. begin
  583. LinPos := CalcLinearPositionDot();
  584. LinMom := CalcLinearMomentumDot();
  585. AngPos := CalcAngularOrientationDot();
  586. AngMom := CalcAngularVelocityDot();
  587. // SetLength(Result,StateSize);
  588. StateArray[StatePos] := LinPos.X;
  589. StateArray[StatePos + 1] := LinPos.Y;
  590. StateArray[StatePos + 2] := LinPos.Z;
  591. StateArray[StatePos + 3] := LinMom.X;
  592. StateArray[StatePos + 4] := LinMom.Y;
  593. StateArray[StatePos + 5] := LinMom.Z;
  594. StateArray[StatePos + 6] := AngPos.imagPart.X;
  595. StateArray[StatePos + 7] := AngPos.imagPart.Y;
  596. StateArray[StatePos + 8] := AngPos.imagPart.Z;
  597. StateArray[StatePos + 9] := AngPos.RealPart;
  598. StateArray[StatePos + 10] := AngMom.X;
  599. StateArray[StatePos + 11] := AngMom.Y;
  600. StateArray[StatePos + 12] := AngMom.Z;
  601. end;
  602. function TgxRigidBodyInertia.CalculateKE(): Real;
  603. begin
  604. // Result:= "Linear KE" + "Angular KE"
  605. // only linear part so far
  606. Result := 1 / (2 * Mass) * VectorNorm(LinearMomentum);
  607. end;
  608. function TgxRigidBodyInertia.CalculatePE(): Real;
  609. begin
  610. // need to find potentials due to fields acting on body
  611. // may be easier to do via forcefieldemitters?
  612. Result := 0;
  613. end;
  614. function TgxRigidBodyInertia.CalcAngularOrientationDot(): TQuaternion;
  615. var
  616. q1: TQuaternion;
  617. begin
  618. q1.imagPart := VectorScale(RotationSpeed.AsAffineVector, 1 / 2); // v1;
  619. q1.RealPart := 0;
  620. Result := QuaternionMultiply(q1, AngularOrientation);
  621. end;
  622. function TgxRigidBodyInertia.CalcAngularVelocityDot(): TAffineVector;
  623. begin
  624. Result := fTorque;
  625. end;
  626. function TgxRigidBodyInertia.QuaternionToString(Quat: TQuaternion): String;
  627. begin
  628. Result := '<Quaternion><imagPart>' + FloatToSTr(Quat.imagPart.X) + ',' +
  629. FloatToSTr(Quat.imagPart.Y) + ',' + FloatToSTr(Quat.imagPart.Z) +
  630. '</imagPart><realPart>' + FloatToSTr(Quat.RealPart) +
  631. '</realPart><Quaternion>';
  632. end;
  633. (*
  634. function TgxRigidBodyInertia.Star(Vector:TAffineVector):TGLMatrix;
  635. begin
  636. Result.X.X:=0; Result[0][1]:=-Vector[2]; Result[0][2]:=Vector[1]; Result[0][3]:=0;
  637. Result[1][0]:=Vector[2]; Result[1][1]:=0; Result[1][2]:=-Vector[0]; Result[1][3]:=0;
  638. Result[2][0]:=Vector[1]; Result[2][1]:=Vector[0]; Result[2][2]:=0; Result[2][3]:=0;
  639. Result[3][0]:=0; Result[3][1]:=0; Result[3][2]:=0; Result[3][3]:=1;
  640. end;
  641. *)
  642. procedure TgxRigidBodyInertia.SetTorque(x, y, z: Real);
  643. begin
  644. fTorque.X := x;
  645. fTorque.Y := y;
  646. fTorque.Z := z;
  647. end;
  648. procedure TgxRigidBodyInertia.ApplyTorque(x, y, z: Real);
  649. begin
  650. fTorque.X := fTorque.X + x;
  651. fTorque.Y := fTorque.Y + y;
  652. fTorque.Z := fTorque.Z + z;
  653. end;
  654. (*
  655. procedure TgxRigidBodyInertia.ApplyImpulse(x,y,z:Real);
  656. begin
  657. //
  658. end;
  659. *)
  660. procedure TgxRigidBodyInertia.RemoveForces();
  661. begin
  662. fForce := nullVector;
  663. fTorque := nullVector;
  664. end;
  665. procedure TgxRigidBodyInertia.ApplyForce(pos, Force: TVector3f);
  666. var
  667. abspos: TAffineVector;
  668. begin
  669. abspos := VectorTransform(pos, R);
  670. fTorque := VectorAdd(fTorque, VectorCrossProduct(abspos, Force));
  671. fForce := VectorAdd(fForce, Force);
  672. end;
  673. procedure TgxRigidBodyInertia.ApplyLocalForce(pos, Force: TVector3f);
  674. var
  675. abspos: TAffineVector;
  676. absForce: TAffineVector;
  677. begin
  678. abspos := VectorTransform(pos, R);
  679. absForce := VectorTransform(Force, R);
  680. fTorque := VectorAdd(fTorque, VectorCrossProduct(abspos, absForce));
  681. fForce := VectorAdd(fForce, absForce);
  682. end;
  683. procedure TgxRigidBodyInertia.ApplyLocalImpulse(xpos, ypos, zpos, x, y,
  684. z: Real);
  685. begin
  686. //
  687. end;
  688. procedure TgxRigidBodyInertia.SetUpStartingState();
  689. begin
  690. //
  691. inherited SetUpStartingState();
  692. fBodyInertiaTensor.X.X := InertiaTensor.fm11;
  693. fBodyInertiaTensor.X.Y := InertiaTensor.fm12;
  694. fBodyInertiaTensor.X.Z := InertiaTensor.fm13;
  695. fBodyInertiaTensor.Y.X := InertiaTensor.fm21;
  696. fBodyInertiaTensor.Y.Y := InertiaTensor.fm22;
  697. fBodyInertiaTensor.Y.Z := InertiaTensor.fm23;
  698. fBodyInertiaTensor.Z.X := InertiaTensor.fm31;
  699. fBodyInertiaTensor.Z.Y := InertiaTensor.fm32;
  700. fBodyInertiaTensor.Z.Z := InertiaTensor.fm33;
  701. fBodyInverseInertiaTensor := fBodyInertiaTensor;
  702. InvertMatrix(fBodyInverseInertiaTensor);
  703. // Write
  704. (*
  705. Messagedlg('setting BodyIit: '+ Format('%f,%f,%f,%f,%f,%f,%f,%f,%f',
  706. [fBodyInverseInertiaTensor[0][0],fBodyInverseInertiaTensor[0][1],fBodyInverseInertiaTensor[0][2],
  707. fBodyInverseInertiaTensor[1][0],fBodyInverseInertiaTensor[1][1],fBodyInverseInertiaTensor[1][2],
  708. fBodyInverseInertiaTensor[2][0],fBodyInverseInertiaTensor[2][1],
  709. fBodyInverseInertiaTensor[2][2]]),mtinformation,[mbok],0);
  710. *)
  711. AngularOrientation := IdentityQuaternion;
  712. AngularMomentum := VectorTransform(RotationSpeed.AsAffineVector,
  713. fBodyInertiaTensor);
  714. end;
  715. procedure TgxRigidBodyInertia.CalcAuxiliary();
  716. var
  717. IRt: TAffineMAtrix;
  718. Rt: TAffineMAtrix;
  719. Scale: TAffineVector;
  720. RMatrix: TGLMatrix;
  721. begin
  722. // TODO: sort this out
  723. fBodyInverseInertiaTensor := IdentityMatrix;
  724. // compute auxiliary variables
  725. R := QuaternionToAffineMatrix(AngularOrientation);
  726. Rt := R;
  727. TransposeMatrix(Rt);
  728. IRt := MatrixMultiply(fBodyInverseInertiaTensor, Rt);
  729. InverseInertiaTensor := MatrixMultiply(R, IRt);
  730. RotationSpeed.AsAffineVector := VectorTransform(AngularMomentum,
  731. InverseInertiaTensor);
  732. TranslationSpeed.AsAffineVector := VectorScale(LinearMomentum, 1 / Mass);
  733. Scale := OwnerBaseSceneObject.Scale.AsAffineVector;
  734. OwnerBaseSceneObject.BeginUpdate;
  735. SetMatrix(RMatrix, R);
  736. OwnerBaseSceneObject.SetMatrix(RMatrix);
  737. // OwnerBaseSceneObject.Matrix:=QuaternionToMatrix(AngularOrientation);
  738. OwnerBaseSceneObject.Scale.AsAffineVector := Scale;
  739. OwnerBaseSceneObject.position.x := LinearPosition.X; // position
  740. OwnerBaseSceneObject.position.y := LinearPosition.Y;
  741. OwnerBaseSceneObject.position.z := LinearPosition.Z;
  742. OwnerBaseSceneObject.EndUpdate;
  743. end;
  744. procedure TgxRigidBodyInertia.StateToArray(var StateArray: TStateArray;
  745. StatePos: Integer);
  746. begin
  747. // with State do
  748. begin
  749. // copy Linear Position
  750. StateArray[StatePos] := LinearPosition.X;
  751. StateArray[StatePos + 1] := LinearPosition.Y;
  752. StateArray[StatePos + 2] := LinearPosition.Z;
  753. // copy Linear Momentum
  754. StateArray[StatePos + 3] := LinearMomentum.X;
  755. StateArray[StatePos + 4] := LinearMomentum.Y;
  756. StateArray[StatePos + 5] := LinearMomentum.Z;
  757. // copy Angular Orientation
  758. StateArray[StatePos + 6] := AngularOrientation.imagPart.X;
  759. StateArray[StatePos + 7] := AngularOrientation.imagPart.Y;
  760. StateArray[StatePos + 8] := AngularOrientation.imagPart.Z;
  761. StateArray[StatePos + 9] := AngularOrientation.RealPart;
  762. // copy Angular Momentum
  763. StateArray[StatePos + 10] := AngularMomentum.X;
  764. StateArray[StatePos + 11] := AngularMomentum.Y;
  765. StateArray[StatePos + 12] := AngularMomentum.Z;
  766. end;
  767. end;
  768. procedure TgxRigidBodyInertia.ArrayToState( { var } StateArray: TStateArray;
  769. StatePos: Integer);
  770. begin
  771. // restore Linear Position
  772. LinearPosition.X := StateArray[StatePos];
  773. LinearPosition.Y := StateArray[StatePos + 1];
  774. LinearPosition.Z := StateArray[StatePos + 2];
  775. // restore Linear Momentum
  776. LinearMomentum.X := StateArray[StatePos + 3];
  777. LinearMomentum.Y := StateArray[StatePos + 4];
  778. LinearMomentum.Z := StateArray[StatePos + 5];
  779. // restore Angular Orientation
  780. AngularOrientation.imagPart.X := StateArray[StatePos + 6];
  781. AngularOrientation.imagPart.Y := StateArray[StatePos + 7];
  782. AngularOrientation.imagPart.Z := StateArray[StatePos + 8];
  783. AngularOrientation.RealPart := StateArray[StatePos + 9];
  784. // restore Angular Momentum
  785. AngularMomentum.X := StateArray[StatePos + 10];
  786. AngularMomentum.Y := StateArray[StatePos + 11];
  787. AngularMomentum.Z := StateArray[StatePos + 12];
  788. end;
  789. procedure TgxRigidBodyInertia.SetLinearDamping(const val: TgxDamping);
  790. begin
  791. // FLinearDamping.Assign(val);
  792. end;
  793. procedure TgxRigidBodyInertia.SetAngularDamping(const val: TgxDamping);
  794. begin
  795. // FAngularDamping.Assign(val);
  796. end;
  797. constructor TgxRigidBodyInertia.Create(aOwner: TXCollection);
  798. begin
  799. inherited Create(aOwner);
  800. Mass := 1;
  801. fDensity := 1;
  802. StateSize := 13;
  803. fInertiaTensor := TgxInertiaTensor.Create(Self);
  804. fRotationSpeed := TgxCoordinates.CreateInitialized(Self, VectorMake(0, 0, 0));
  805. // LinearPosition:=OwnerBaseSceneObject.Position.AsAffineVector;
  806. AngularOrientation := IdentityQuaternion; // fromAngleAxis(0,XVector);
  807. fTorque := nullVector;
  808. fForce := nullVector;
  809. // DampingEnabled:=False;
  810. // FTranslationDamping:=TgxDamping.Create(Self);
  811. FRotationDamping := TgxDamping.Create(Self);
  812. // RotationDamping:=TgxDamping.Create(Self);
  813. R := IdentityMatrix;
  814. InverseInertiaTensor := IdentityMatrix;
  815. // CalcAuxiliary();
  816. // SetDESolver(ssEuler);
  817. end;
  818. //---------------------------------------------------------------------------
  819. destructor TgxRigidBodyInertia.Destroy;
  820. begin
  821. // FLinearDamping.Free;
  822. // FAngularDamping.Free;
  823. fInertiaTensor.Free();
  824. fRotationSpeed.Free();
  825. FRotationDamping.Free;
  826. inherited Destroy;
  827. end;
  828. procedure TgxRigidBodyInertia.Assign(Source: TPersistent);
  829. begin
  830. if Source.ClassType = Self.ClassType then
  831. begin
  832. // FRigidBody.Assign(TgxRigidBodyInertia(Source));
  833. Mass := TgxRigidBodyInertia(Source).Mass;
  834. fDensity := TgxRigidBodyInertia(Source).fDensity;
  835. fBodyInertiaTensor := TgxRigidBodyInertia(Source).fBodyInertiaTensor;
  836. fBodyInverseInertiaTensor := TgxRigidBodyInertia(Source)
  837. .fBodyInverseInertiaTensor;
  838. InertiaTensor.Assign(TgxRigidBodyInertia(Source).InertiaTensor);
  839. LinearPosition := TgxRigidBodyInertia(Source).LinearPosition;
  840. AngularOrientation := TgxRigidBodyInertia(Source).AngularOrientation;
  841. LinearMomentum := TgxRigidBodyInertia(Source).LinearMomentum;
  842. AngularMomentum := TgxRigidBodyInertia(Source).AngularMomentum;
  843. // TranslationSpeed.AsAffineVector:=TgxRigidBodyInertia(Source).TranslationSpeed.AsAffineVector;
  844. RotationSpeed.Assign(TgxRigidBodyInertia(Source).RotationSpeed);
  845. // fForce:=TgxRigidBodyInertia(Source).fForce;
  846. fTorque := TgxRigidBodyInertia(Source).fTorque;
  847. // fInverseInertiaTensor:=TgxRigidBodyInertia(Source).fInverseInertiaTensor;
  848. // RigidBody.fTorque:=TgxRigidBodyInertia(Source).fTorque;
  849. // RigidBody.fForce:=TgxRigidBodyInertia(Source).fForce;
  850. FRotationDamping.Assign(TgxRigidBodyInertia(Source).FRotationDamping);
  851. // DampingEnabled:=TgxRigidBodyInertia(Source).DampingEnabled;
  852. // FTranslationDamping.Assign(TgxRigidBodyInertia(Source).LinearDamping);
  853. // FRotationDamping.Assign(TgxRigidBodyInertia(Source).AngularDamping);
  854. end;
  855. inherited Assign(Source);
  856. end;
  857. class function TgxRigidBodyInertia.FriendlyName: String;
  858. begin
  859. Result := 'Rigid Body Inertia';
  860. end;
  861. class function TgxRigidBodyInertia.FriendlyDescription: String;
  862. begin
  863. Result := 'An inertia model for rigid bodies';
  864. end;
  865. class function TgxRigidBodyInertia.UniqueItem: Boolean;
  866. begin
  867. Result := True;
  868. end;
  869. // **************************************************************************
  870. // ***************** DoProgress ************************************
  871. // **************************************************************************
  872. (*
  873. procedure TgxRigidBodyInertia.DoProgress(const progressTime : TProgressTimes);
  874. var
  875. TempScale:TaffineVector;
  876. UndampedLinearMomentum,DampedLinearMomentum:Real;
  877. UnDampedAngularMomentum,DampedAngularMomentum:Real;
  878. i:integer;
  879. begin
  880. // Write('Calculating next state...');
  881. with OwnerBaseSceneObject do
  882. with progressTime do
  883. begin
  884. if (DampingEnabled=true) then
  885. begin
  886. UndampedLinearMomentum:=VectorLength(LinearMomentum);
  887. DampedLinearMomentum:=TranslationDamping.Calculate(UndampedLinearMomentum,deltaTime);
  888. { if Stage.VectorGeometry.vSIMD=1 then
  889. // RigidBody.LinearMomentum:=VectorScale(VectorNormalize(RigidBody.LinearMomentum),DampedLinearMomentum)
  890. else
  891. } begin
  892. if Length(LinearMomentum)<>0 then
  893. LinearMomentum:=VectorScale(VectorNormalize(LinearMomentum),DampedLinearMomentum)
  894. else
  895. LinearMomentum:=NullVector; //line not required
  896. end;
  897. UndampedAngularMomentum:=VectorLength(AngularMomentum);
  898. DampedAngularMomentum:=RotationDamping.Calculate(UndampedAngularMomentum,deltaTime);
  899. AngularMomentum:=VectorScale(VectorNormalize(AngularMomentum),DampedAngularMomentum);
  900. // ApplyForce(VectorScale(RigidBody.LinearVelocity,-0.5)); //Either apply resistive force & torque
  901. // ApplyTorque(VectorLength(RigidBody.AngularVelocity)); //or use TgxDamping
  902. end;
  903. // Euler(RigidBody,deltaTime);
  904. // RungeKutta4(DeltaTime);
  905. //DESolver(RigidBody,DeltaTime);
  906. //update OwnerBaseSceneObject
  907. TempScale:=Scale.AsAffineVector;
  908. Matrix:=QuaternionToMatrix(AngularOrientation);
  909. position.AsAffineVector:=LinearPosition;
  910. Scale.AsAffineVector:=TempScale;
  911. //calc auxiliary variables for next iteration
  912. CalcAuxiliary();
  913. end;
  914. end;
  915. *)
  916. procedure TgxRigidBodyInertia.WriteToFiler(writer: TWriter);
  917. begin
  918. inherited WriteToFiler(writer);
  919. with writer do
  920. begin
  921. // WriteInteger(0); // Archive Version 0
  922. // FRigidBody.WriteToFiler(writer);
  923. // WriteFloat(fMass);
  924. WriteFloat(fDensity);
  925. Write(fBodyInertiaTensor, SizeOf(fBodyInertiaTensor));
  926. Write(fBodyInverseInertiaTensor, SizeOf(fBodyInverseInertiaTensor));
  927. fInertiaTensor.WriteToFiler(writer);
  928. Write(AngularOrientation, SizeOf(AngularOrientation));
  929. Write(AngularMomentum, SizeOf(AngularMomentum));
  930. // Write(LinearVelocity,SizeOf(LinearVelocity));
  931. RotationSpeed.WriteToFiler(writer);
  932. // Write(AngularVelocity,SizeOf(AngularVelocity));
  933. Write(fTorque, SizeOf(fTorque));
  934. // Write(fForce,SizeOf(fForce));
  935. FRotationDamping.WriteToFiler(writer);
  936. // WriteInteger(Integer(FDESolverType));
  937. // WriteBoolean(FDampingEnabled);
  938. // FLinearDamping.WriteToFiler(writer);
  939. // FAngularDamping.WriteToFiler(writer);
  940. end;
  941. end;
  942. procedure TgxRigidBodyInertia.ReadFromFiler(reader: TReader);
  943. begin
  944. inherited ReadFromFiler(reader);
  945. with reader do
  946. begin
  947. // ReadInteger; // ignore archiveVersion
  948. // FRigidBody.ReadFromFiler(Reader);
  949. // fMass:=ReadFloat;
  950. fDensity := ReadFloat;
  951. Read(fBodyInertiaTensor, SizeOf(fBodyInertiaTensor));
  952. Read(fBodyInverseInertiaTensor, SizeOf(fBodyInverseInertiaTensor));
  953. InertiaTensor.ReadFromFiler(reader);
  954. Read(AngularOrientation, SizeOf(AngularOrientation));
  955. Read(AngularMomentum, SizeOf(AngularMomentum));
  956. // Read(LinearVelocity,SizeOf(LinearVelocity));
  957. RotationSpeed.ReadFromFiler(reader);
  958. // Read(AngularVelocity,SizeOf(AngularVelocity));
  959. Read(fTorque, SizeOf(fTorque));
  960. // Read(fForce, SizeOf(fForce));
  961. FRotationDamping.ReadFromFiler(reader);
  962. // SetDESolver(TDESolverType(ReadInteger));
  963. // FDampingEnabled:=ReadBoolean;
  964. // FLinearDamping.ReadFromFiler(reader);
  965. // FAngularDamping.ReadFromFiler(reader);
  966. end;
  967. // SetDESolver(fDESolverType);
  968. // CalcAuxiliary();
  969. SetUpStartingState();
  970. end;
  971. function GetOrCreateRigidBodyInertia(behaviours: TgxBehaviours)
  972. : TgxRigidBodyInertia;
  973. var
  974. i: Integer;
  975. begin
  976. i := behaviours.IndexOfClass(TgxRigidBodyInertia);
  977. if i >= 0 then
  978. Result := TgxRigidBodyInertia(behaviours[i])
  979. else
  980. Result := TgxRigidBodyInertia.Create(behaviours);
  981. end;
  982. function GetOrCreateRigidBodyInertia(obj: TgxBaseSceneObject)
  983. : TgxRigidBodyInertia;
  984. begin
  985. Result := GetOrCreateRigidBodyInertia(obj.behaviours);
  986. end;
  987. initialization // -----------------------------------------------------------
  988. // class registrations
  989. RegisterXCollectionItemClass(TgxParticleInertia);
  990. RegisterXCollectionItemClass(TgxRigidBodyInertia);
  991. end.