GLS.PhysicsInertias.pas 37 KB

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