Physics.SPIInertias.pas 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130
  1. //
  2. // The graphics engine GLScene https://github.com/glscene
  3. //
  4. unit Physics.SPIInertias;
  5. interface
  6. uses
  7. System.SysUtils,
  8. System.Classes,
  9. Vcl.Dialogs,
  10. GLS.PersistentClasses,
  11. GLS.XCollection,
  12. GLS.Scene,
  13. GLS.BaseClasses,
  14. GLS.VectorGeometry,
  15. GLS.VectorTypes,
  16. Physics.SPIManager,
  17. GLS.Coordinates,
  18. GLS.Strings,
  19. GLS.Behaviours;
  20. type
  21. TGLParticleInertia = class(TGLBaseInertia)
  22. // modified from TGLBInertia
  23. private
  24. FMass: Single;
  25. FTranslationSpeed: TGLCoordinates;
  26. FTranslationDamping: TGLDamping;
  27. protected
  28. function CalcLinearPositionDot(): TAffineVector;
  29. function CalcLinearMomentumDot(): TAffineVector;
  30. procedure SetTranslationSpeed(const val: TGLCoordinates);
  31. procedure SetTranslationDamping(const val: TGLDamping);
  32. public
  33. fForce: TAffineVector;
  34. LinearPosition: TAffineVector;
  35. LinearMomentum: TAffineVector;
  36. procedure StateToArray(var StateArray: TStateArray; StatePos: Integer); override;
  37. procedure ArrayToState( { var } StateArray: TStateArray; StatePos: Integer); override;
  38. procedure CalcStateDot(var StateArray: TStateArray; StatePos: Integer); override;
  39. procedure RemoveForces(); override;
  40. procedure CalculateForceFieldForce(ForceFieldEmitter
  41. : TGLBaseForceFieldEmitter); override;
  42. procedure CalcAuxiliary(); override;
  43. procedure SetUpStartingState(); override;
  44. function CalculateKE(): Real; override;
  45. function CalculatePE(): Real; override;
  46. procedure SetForce(x, y, z: Real); virtual;
  47. procedure ApplyForce(x, y, z: Real); overload; virtual;
  48. procedure ApplyForce(Force: TAffineVector); overload; virtual;
  49. procedure ApplyForce(pos, Force: TAffineVector); overload; virtual;
  50. procedure ApplyLocalForce(pos, Force: TAffineVector); virtual;
  51. procedure ApplyImpulse(j, x, y, z: Real); overload; virtual;
  52. procedure ApplyImpulse(j: Single; normal: TAffineVector); overload; virtual;
  53. procedure ApplyDamping(damping: TGLDamping); virtual;
  54. constructor Create(aOwner: TXCollection); override;
  55. destructor Destroy; override;
  56. procedure Assign(Source: TPersistent); override;
  57. procedure WriteToFiler(writer: TWriter); override;
  58. procedure ReadFromFiler(reader: TReader); override;
  59. class function FriendlyName: String; override;
  60. class function FriendlyDescription: String; override;
  61. class function UniqueItem: Boolean; override;
  62. // Inverts the translation vector
  63. procedure MirrorTranslation;
  64. (* Bounce speed as if hitting a surface.
  65. restitution is the coefficient of restituted energy (1=no energy loss,
  66. 0=no bounce). The normal is NOT assumed to be normalized. *)
  67. procedure SurfaceBounce(const surfaceNormal: TGLVector; restitution: Single);
  68. published
  69. property Mass: Single read FMass write FMass;
  70. property TranslationSpeed: TGLCoordinates read FTranslationSpeed
  71. write SetTranslationSpeed;
  72. (* Enable/Disable damping (damping has a high cpu-cycle cost).
  73. Damping is enabled by default. *)
  74. // property DampingEnabled : Boolean read FDampingEnabled write FDampingEnabled;
  75. (* Damping applied to translation speed.<br>
  76. Note that it is not "exactly" applied, ie. if damping would stop
  77. your object after 0.5 time unit, and your progression steps are
  78. of 1 time unit, there will be an integration error of 0.5 time unit. *)
  79. property TranslationDamping: TGLDamping read FTranslationDamping
  80. write SetTranslationDamping;
  81. end;
  82. TGLRigidBodyInertia = class;
  83. (* Stores Inertia Tensor for TGLRigidBodyInertia model *)
  84. TGLInertiaTensor = class(TGLUpdateAbleObject)
  85. private
  86. fm11, fm12, fm13, fm21, fm22, fm23, fm31, fm32, fm33: Single;
  87. public
  88. constructor Create(aOwner: TPersistent); override;
  89. destructor Destroy; override;
  90. procedure Assign(Source: TPersistent); override;
  91. procedure WriteToFiler(writer: TWriter);
  92. procedure ReadFromFiler(reader: TReader);
  93. published
  94. property m11: Single read fm11 write fm11;
  95. property m12: Single read fm12 write fm12;
  96. property m13: Single read fm13 write fm13;
  97. property m21: Single read fm21 write fm21;
  98. property m22: Single read fm22 write fm22;
  99. property m23: Single read fm23 write fm23;
  100. property m31: Single read fm31 write fm31;
  101. property m32: Single read fm32 write fm32;
  102. property m33: Single read fm33 write fm33;
  103. end;
  104. (* A more complex model than TGLBInertia for Inertia *)
  105. TGLRigidBodyInertia = class(TGLParticleInertia)
  106. private
  107. fDensity: Real;
  108. fBodyInertiaTensor: TAffineMAtrix;
  109. fBodyInverseInertiaTensor: TAffineMAtrix;
  110. fInertiaTensor: TGLInertiaTensor;
  111. InverseInertiaTensor: TAffineMAtrix;
  112. // LinearVelocity:TAffineVector;
  113. fRotationSpeed: TGLCoordinates;
  114. /// AngularVelocity:TAffineVector; //rotation about axis, magnitude=speed
  115. // damping properties
  116. FRotationDamping: TGLDamping;
  117. protected
  118. // torques
  119. fTorque: TAffineVector;
  120. procedure SetLinearDamping(const val: TGLDamping);
  121. procedure SetAngularDamping(const val: TGLDamping);
  122. public
  123. AngularOrientation: TQuaternion; // As Quat will help improve accuracy
  124. R: TMatrix3f; // corresponds to AngularOrientation
  125. AngularMomentum: TAffineVector;
  126. procedure StateToArray(var StateArray: TStateArray;
  127. StatePos: Integer); override;
  128. procedure ArrayToState( (* var *) StateArray: TStateArray;
  129. StatePos: Integer); override;
  130. procedure CalcStateDot(var StateArray: TStateArray;
  131. StatePos: Integer); override;
  132. procedure ApplyImpulse(j, xpos, ypos, zpos, x, y, z: Real); overload;
  133. procedure ApplyImpulse(j: Single; position, normal: TAffineVector);
  134. overload;
  135. procedure ApplyDamping(damping: TGLDamping); override;
  136. // function CalcLinearPositionDot():TAffineVector;
  137. // function CalcLinearMomentumDot():TAffineVector;
  138. function CalcAngularOrientationDot(): TQuaternion;
  139. function CalcAngularVelocityDot(): TAffineVector;
  140. function CalculateKE(): Real; override;
  141. function CalculatePE(): Real; override;
  142. procedure CalcAuxiliary(); override;
  143. procedure SetUpStartingState(); override;
  144. constructor Create(aOwner: TXCollection); override;
  145. destructor Destroy; override;
  146. procedure Assign(Source: TPersistent); override;
  147. procedure WriteToFiler(writer: TWriter); override;
  148. procedure ReadFromFiler(reader: TReader); override;
  149. class function FriendlyName: String; override;
  150. class function FriendlyDescription: String; override;
  151. class function UniqueItem: Boolean; override;
  152. // function Star(Vector:TAffineVector):TGLMatrix;
  153. function QuaternionToString(Quat: TQuaternion): String;
  154. procedure RemoveForces(); override;
  155. procedure SetTorque(x, y, z: Real);
  156. procedure ApplyTorque(x, y, z: Real);
  157. procedure ApplyForce(pos, Force: TAffineVector); override;
  158. procedure ApplyLocalForce(pos, Force: TVector3f); override;
  159. procedure ApplyLocalImpulse(xpos, ypos, zpos, x, y, z: Real);
  160. procedure SetInertiaTensor(newVal: TGLInertiaTensor);
  161. procedure SetRotationSpeed(const val: TGLCoordinates);
  162. procedure SetRotationDamping(const val: TGLDamping);
  163. published
  164. property Density: Real read fDensity write fDensity;
  165. property InertiaTensor: TGLInertiaTensor read fInertiaTensor
  166. write SetInertiaTensor;
  167. property RotationSpeed: TGLCoordinates read fRotationSpeed
  168. write SetRotationSpeed;
  169. property RotationDamping: TGLDamping read FRotationDamping
  170. write SetRotationDamping;
  171. end;
  172. (* Returns or creates the TGLParticleInertia within the given behaviours.
  173. This helper function is convenient way to access a TGLParticleInertia. *)
  174. function GetOrCreateParticleInertia(behaviours: TGLBehaviours): TGLParticleInertia; overload;
  175. (* Returns or creates the TGLParticleInertia within the given object's behaviours.
  176. This helper function is convenient way to access a TGLParticleInertia. *)
  177. function GetOrCreateParticleInertia(obj: TGLBaseSceneObject): TGLParticleInertia; overload;
  178. (* Returns or creates the TGLRigidBodyInertia within the given behaviours.
  179. This helper function is convenient way to access a TGLRigidBodyInertia. *)
  180. function GetOrCreateRigidBodyInertia(behaviours: TGLBehaviours): TGLRigidBodyInertia; overload;
  181. (* Returns or creates the TGLRigidBodyInertia within the given object's behaviours.
  182. This helper function is convenient way to access a TGLRigidBodyInertia. *)
  183. function GetOrCreateRigidBodyInertia(obj: TGLBaseSceneObject): TGLRigidBodyInertia; overload;
  184. const
  185. DebugMode = false;
  186. // ------------------------------------------------------------------
  187. implementation
  188. // ------------------------------------------------------------------
  189. // ------------------
  190. // ------------------ TGLParticleInertia ------------------
  191. // ------------------
  192. constructor TGLParticleInertia.Create(aOwner: TXCollection);
  193. begin
  194. inherited Create(aOwner);
  195. FMass := 1;
  196. StateSize := 6;
  197. FTranslationSpeed := TGLCoordinates.CreateInitialized(Self, NullHmgVector, csVector);
  198. LinearPosition := OwnerBaseSceneObject.position.AsAffineVector;
  199. LinearMomentum := FTranslationSpeed.AsAffineVector;
  200. FTranslationDamping := TGLDamping.Create(Self);
  201. end;
  202. destructor TGLParticleInertia.Destroy;
  203. begin
  204. FTranslationDamping.Free;
  205. FTranslationSpeed.Free;
  206. inherited Destroy;
  207. end;
  208. procedure TGLParticleInertia.Assign(Source: TPersistent);
  209. begin
  210. if Source.ClassType = Self.ClassType then
  211. begin
  212. FMass := TGLParticleInertia(Source).FMass;
  213. FTranslationSpeed.Assign(TGLParticleInertia(Source).FTranslationSpeed);
  214. LinearPosition := TGLParticleInertia(Source).LinearPosition;
  215. LinearMomentum := TGLParticleInertia(Source).LinearMomentum;
  216. // FDampingEnabled:=TGLInertia(Source).DampingEnabled;
  217. FTranslationDamping.Assign(TGLParticleInertia(Source).TranslationDamping);
  218. // FRotationDamping.Assign(TGLBInertia(Source).RotationDamping);
  219. end;
  220. inherited Assign(Source);
  221. end;
  222. procedure TGLParticleInertia.WriteToFiler(writer: TWriter);
  223. begin
  224. inherited;
  225. with writer do
  226. begin
  227. WriteInteger(0); // Archive Version 0
  228. WriteFloat(FMass);
  229. Write(LinearPosition, SizeOf(LinearPosition));
  230. Write(LinearMomentum, SizeOf(LinearMomentum));
  231. Write(fForce, SizeOf(fForce));
  232. FTranslationSpeed.WriteToFiler(writer);
  233. FTranslationDamping.WriteToFiler(writer);
  234. end;
  235. end;
  236. procedure TGLParticleInertia.ReadFromFiler(reader: TReader);
  237. begin
  238. inherited;
  239. with reader do
  240. begin
  241. ReadInteger; // ignore archiveVersion
  242. FMass := ReadFloat;
  243. Read(LinearPosition, SizeOf(LinearPosition));
  244. Read(LinearMomentum, SizeOf(LinearMomentum));
  245. Read(fForce, SizeOf(fForce));
  246. FTranslationSpeed.ReadFromFiler(reader);
  247. FTranslationDamping.ReadFromFiler(reader);
  248. end;
  249. // Loaded;
  250. SetUpStartingState();
  251. end;
  252. procedure TGLParticleInertia.SetTranslationSpeed(const val: TGLCoordinates);
  253. begin
  254. FTranslationSpeed.Assign(val);
  255. LinearMomentum := VectorScale(FTranslationSpeed.AsAffineVector, FMass);
  256. end;
  257. procedure TGLParticleInertia.SetUpStartingState();
  258. begin
  259. LinearPosition := OwnerBaseSceneObject.position.AsAffineVector;
  260. LinearMomentum := VectorScale(TranslationSpeed.AsAffineVector, Mass);
  261. end;
  262. procedure TGLParticleInertia.CalcAuxiliary( { RBody:TGLRigidBody } );
  263. begin
  264. TranslationSpeed.AsAffineVector := VectorScale(LinearMomentum, 1 / Mass);
  265. // OwnerBaseSceneObject.Matrix:=QuaternionToMatrix(AngularOrientation);
  266. OwnerBaseSceneObject.position.AsAffineVector := LinearPosition; // position
  267. // OwnerBaseSceneObject.position.x:=LinearPosition[0];//position
  268. // OwnerBaseSceneObject.position.y:=LinearPosition[1];
  269. // OwnerBaseSceneObject.position.z:=LinearPosition[2];
  270. end;
  271. procedure TGLParticleInertia.RemoveForces();
  272. begin
  273. fForce := nullVector;
  274. end;
  275. procedure TGLParticleInertia.CalculateForceFieldForce(ForceFieldEmitter
  276. : TGLBaseForceFieldEmitter);
  277. begin
  278. ForceFieldEmitter.CalculateForceField(Self.OwnerBaseSceneObject);
  279. end;
  280. function TGLParticleInertia.CalculateKE(): Real;
  281. begin
  282. Result := 1 / (2 * Mass) * VectorNorm(LinearMomentum);
  283. end;
  284. function TGLParticleInertia.CalculatePE(): Real;
  285. begin
  286. // need to find potentials due to fields acting on body
  287. // may be easier to do via ForceFieldEmitters?
  288. Result := 0;
  289. end;
  290. procedure TGLParticleInertia.SetForce(x, y, z: Real);
  291. begin
  292. fForce.x := x;
  293. fForce.y := y;
  294. fForce.z := z;
  295. end;
  296. procedure TGLParticleInertia.ApplyForce(x, y, z: Real);
  297. begin
  298. fForce.X := fForce.X + x;
  299. fForce.Y := fForce.Y + y;
  300. fForce.Z := fForce.Z + z;
  301. end;
  302. procedure TGLParticleInertia.ApplyForce(Force: TAffineVector);
  303. begin
  304. fForce := VectorAdd(fForce, Force);
  305. end;
  306. procedure TGLParticleInertia.ApplyForce(pos, Force: TAffineVector);
  307. // var
  308. // abspos:TAffineVector;
  309. begin
  310. fForce := VectorAdd(fForce, Force);
  311. // abspos:=VectorTransform(pos,R);
  312. // fTorque:=VectorAdd(fTorque,VectorCrossProduct(abspos,force));
  313. // fForce:=VectorAdd(fForce,force);
  314. end;
  315. procedure TGLParticleInertia.ApplyLocalForce(pos, Force: TAffineVector);
  316. // var
  317. // abspos:TAffineVector;
  318. // absForce:TAffineVector;
  319. begin
  320. // abspos:=VectorTransform(pos,R);
  321. // absForce:=VectorTransform(Force,R);
  322. // fTorque:=VectorAdd(fTorque,VectorCrossProduct(abspos,absforce));
  323. fForce := VectorAdd(fForce, Force);
  324. end;
  325. procedure TGLParticleInertia.ApplyImpulse(j, x, y, z: Real);
  326. begin
  327. // V2 = V1 + (j/M)n
  328. // V2.M = V1.M +j.n
  329. LinearMomentum.X := LinearMomentum.X + j * x;
  330. LinearMomentum.Y := LinearMomentum.Y + j * y;
  331. LinearMomentum.Z := LinearMomentum.Z + j * z;
  332. end;
  333. procedure TGLParticleInertia.ApplyImpulse(j: Single; normal: TAffineVector);
  334. begin
  335. CombineVector(LinearMomentum, normal, j);
  336. end;
  337. procedure TGLParticleInertia.ApplyDamping(damping: TGLDamping);
  338. var
  339. velocity: TAffineVector;
  340. v: Real;
  341. dampingForce: TAffineVector;
  342. begin
  343. velocity := VectorScale(LinearMomentum, 1 / Mass); // v = p/m
  344. // apply force in opposite direction to velocity
  345. v := VectorLength(velocity);
  346. // F = -Normalised(V)*( Constant + (Linear)*(V) + (Quadtratic)*(V)*(V) )
  347. dampingForce := VectorScale(VectorNormalize(velocity),
  348. -(damping.Constant + damping.Linear * v + damping.Quadratic * v * v));
  349. // dampingForce:=VectorScale(VectorNormalize(velocity),-(Damping.Constant+Damping.Linear*v+Damping.Quadratic*v*v));
  350. ApplyForce(dampingForce);
  351. end;
  352. procedure TGLParticleInertia.SetTranslationDamping(const val: TGLDamping);
  353. begin
  354. FTranslationDamping.Assign(val);
  355. end;
  356. class function TGLParticleInertia.FriendlyName: String;
  357. begin
  358. Result := 'Particle Inertia';
  359. end;
  360. class function TGLParticleInertia.FriendlyDescription: String;
  361. begin
  362. Result := 'A simple translation inertia';
  363. end;
  364. class function TGLParticleInertia.UniqueItem: Boolean;
  365. begin
  366. Result := True;
  367. end;
  368. function TGLParticleInertia.CalcLinearPositionDot(): TAffineVector;
  369. begin
  370. Result := VectorScale(LinearMomentum, 1 / FMass);
  371. // Result:=FTranslationSpeed.AsAffineVector;
  372. end;
  373. function TGLParticleInertia.CalcLinearMomentumDot(): TAffineVector;
  374. begin
  375. Result := fForce;
  376. end;
  377. procedure TGLParticleInertia.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 TGLParticleInertia.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 TGLParticleInertia.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 TGLParticleInertia.MirrorTranslation;
  421. begin
  422. FTranslationSpeed.Invert;
  423. end;
  424. procedure TGLParticleInertia.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: TGLBehaviours)
  439. : TGLParticleInertia;
  440. var
  441. i: Integer;
  442. begin
  443. i := behaviours.IndexOfClass(TGLParticleInertia);
  444. if i >= 0 then
  445. Result := TGLParticleInertia(behaviours[i])
  446. else
  447. Result := TGLParticleInertia.Create(behaviours);
  448. end;
  449. function GetOrCreateParticleInertia(obj: TGLBaseSceneObject)
  450. : TGLParticleInertia;
  451. begin
  452. Result := GetOrCreateParticleInertia(obj.behaviours);
  453. end;
  454. // -----------------------------------------------------------------------
  455. // ------------ TGLInertiaTensor
  456. // -----------------------------------------------------------------------
  457. constructor TGLInertiaTensor.Create(aOwner: TPersistent);
  458. begin
  459. inherited Create(aOwner);
  460. fm11 := 1;
  461. fm22 := 1;
  462. fm33 := 1;
  463. end;
  464. destructor TGLInertiaTensor.Destroy;
  465. begin
  466. inherited Destroy;
  467. end;
  468. procedure TGLInertiaTensor.Assign(Source: TPersistent);
  469. begin
  470. inherited;
  471. fm11 := TGLInertiaTensor(Source).fm11;
  472. fm12 := TGLInertiaTensor(Source).fm12;
  473. fm13 := TGLInertiaTensor(Source).fm13;
  474. fm21 := TGLInertiaTensor(Source).fm21;
  475. fm22 := TGLInertiaTensor(Source).fm22;
  476. fm23 := TGLInertiaTensor(Source).fm23;
  477. fm31 := TGLInertiaTensor(Source).fm31;
  478. fm32 := TGLInertiaTensor(Source).fm32;
  479. fm33 := TGLInertiaTensor(Source).fm33;
  480. end;
  481. procedure TGLInertiaTensor.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 TGLInertiaTensor.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. // TGLRigidBodyInertia
  517. //--------------------------
  518. procedure TGLRigidBodyInertia.SetInertiaTensor(newVal: TGLInertiaTensor);
  519. begin
  520. fInertiaTensor := newVal;
  521. end;
  522. procedure TGLRigidBodyInertia.SetRotationSpeed(const val: TGLCoordinates);
  523. begin
  524. AngularMomentum := VectorTransform(val.AsAffineVector, fBodyInertiaTensor);
  525. fRotationSpeed.Assign(val);
  526. end;
  527. procedure TGLRigidBodyInertia.SetRotationDamping(const val: TGLDamping);
  528. begin
  529. FRotationDamping.Assign(val);
  530. end;
  531. procedure TGLRigidBodyInertia.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 TGLRigidBodyInertia.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 TGLRigidBodyInertia.ApplyDamping(damping: TGLDamping);
  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 TGLRigidBodyInertia.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 TGLRigidBodyInertia.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 TGLRigidBodyInertia.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 TGLRigidBodyInertia.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 TGLRigidBodyInertia.CalcAngularVelocityDot(): TAffineVector;
  623. begin
  624. Result := fTorque;
  625. end;
  626. function TGLRigidBodyInertia.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 TGLRigidBodyInertia.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 TGLRigidBodyInertia.SetTorque(x, y, z: Real);
  643. begin
  644. fTorque.X := x;
  645. fTorque.Y := y;
  646. fTorque.Z := z;
  647. end;
  648. procedure TGLRigidBodyInertia.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 TGLRigidBodyInertia.ApplyImpulse(x,y,z:Real);
  656. begin
  657. //
  658. end;
  659. *)
  660. procedure TGLRigidBodyInertia.RemoveForces();
  661. begin
  662. fForce := nullVector;
  663. fTorque := nullVector;
  664. end;
  665. procedure TGLRigidBodyInertia.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 TGLRigidBodyInertia.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 TGLRigidBodyInertia.ApplyLocalImpulse(xpos, ypos, zpos, x, y,
  684. z: Real);
  685. begin
  686. //
  687. end;
  688. procedure TGLRigidBodyInertia.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. // 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);
  704. AngularOrientation := IdentityQuaternion;
  705. AngularMomentum := VectorTransform(RotationSpeed.AsAffineVector,
  706. fBodyInertiaTensor);
  707. end;
  708. procedure TGLRigidBodyInertia.CalcAuxiliary();
  709. var
  710. IRt: TAffineMAtrix;
  711. Rt: TAffineMAtrix;
  712. Scale: TAffineVector;
  713. RMatrix: TGLMatrix;
  714. begin
  715. // TODO: sort this out
  716. fBodyInverseInertiaTensor := IdentityMatrix;
  717. // compute auxiliary variables
  718. R := QuaternionToAffineMatrix(AngularOrientation);
  719. Rt := R;
  720. TransposeMatrix(Rt);
  721. IRt := MatrixMultiply(fBodyInverseInertiaTensor, Rt);
  722. InverseInertiaTensor := MatrixMultiply(R, IRt);
  723. RotationSpeed.AsAffineVector := VectorTransform(AngularMomentum,
  724. InverseInertiaTensor);
  725. TranslationSpeed.AsAffineVector := VectorScale(LinearMomentum, 1 / Mass);
  726. Scale := OwnerBaseSceneObject.Scale.AsAffineVector;
  727. OwnerBaseSceneObject.BeginUpdate;
  728. SetMatrix(RMatrix, R);
  729. OwnerBaseSceneObject.SetMatrix(RMatrix);
  730. // OwnerBaseSceneObject.Matrix:=QuaternionToMatrix(AngularOrientation);
  731. OwnerBaseSceneObject.Scale.AsAffineVector := Scale;
  732. OwnerBaseSceneObject.position.x := LinearPosition.X; // position
  733. OwnerBaseSceneObject.position.y := LinearPosition.Y;
  734. OwnerBaseSceneObject.position.z := LinearPosition.Z;
  735. OwnerBaseSceneObject.EndUpdate;
  736. end;
  737. procedure TGLRigidBodyInertia.StateToArray(var StateArray: TStateArray;
  738. StatePos: Integer);
  739. begin
  740. // with State do
  741. begin
  742. // copy Linear Position
  743. StateArray[StatePos] := LinearPosition.X;
  744. StateArray[StatePos + 1] := LinearPosition.Y;
  745. StateArray[StatePos + 2] := LinearPosition.Z;
  746. // copy Linear Momentum
  747. StateArray[StatePos + 3] := LinearMomentum.X;
  748. StateArray[StatePos + 4] := LinearMomentum.Y;
  749. StateArray[StatePos + 5] := LinearMomentum.Z;
  750. // copy Angular Orientation
  751. StateArray[StatePos + 6] := AngularOrientation.imagPart.X;
  752. StateArray[StatePos + 7] := AngularOrientation.imagPart.Y;
  753. StateArray[StatePos + 8] := AngularOrientation.imagPart.Z;
  754. StateArray[StatePos + 9] := AngularOrientation.RealPart;
  755. // copy Angular Momentum
  756. StateArray[StatePos + 10] := AngularMomentum.X;
  757. StateArray[StatePos + 11] := AngularMomentum.Y;
  758. StateArray[StatePos + 12] := AngularMomentum.Z;
  759. end;
  760. end;
  761. procedure TGLRigidBodyInertia.ArrayToState( { var } StateArray: TStateArray;
  762. StatePos: Integer);
  763. begin
  764. // restore Linear Position
  765. LinearPosition.X := StateArray[StatePos];
  766. LinearPosition.Y := StateArray[StatePos + 1];
  767. LinearPosition.Z := StateArray[StatePos + 2];
  768. // restore Linear Momentum
  769. LinearMomentum.X := StateArray[StatePos + 3];
  770. LinearMomentum.Y := StateArray[StatePos + 4];
  771. LinearMomentum.Z := StateArray[StatePos + 5];
  772. // restore Angular Orientation
  773. AngularOrientation.imagPart.X := StateArray[StatePos + 6];
  774. AngularOrientation.imagPart.Y := StateArray[StatePos + 7];
  775. AngularOrientation.imagPart.Z := StateArray[StatePos + 8];
  776. AngularOrientation.RealPart := StateArray[StatePos + 9];
  777. // restore Angular Momentum
  778. AngularMomentum.X := StateArray[StatePos + 10];
  779. AngularMomentum.Y := StateArray[StatePos + 11];
  780. AngularMomentum.Z := StateArray[StatePos + 12];
  781. end;
  782. procedure TGLRigidBodyInertia.SetLinearDamping(const val: TGLDamping);
  783. begin
  784. // FLinearDamping.Assign(val);
  785. end;
  786. procedure TGLRigidBodyInertia.SetAngularDamping(const val: TGLDamping);
  787. begin
  788. // FAngularDamping.Assign(val);
  789. end;
  790. constructor TGLRigidBodyInertia.Create(aOwner: TXCollection);
  791. begin
  792. inherited Create(aOwner);
  793. Mass := 1;
  794. fDensity := 1;
  795. StateSize := 13;
  796. fInertiaTensor := TGLInertiaTensor.Create(Self);
  797. fRotationSpeed := TGLCoordinates.CreateInitialized(Self, VectorMake(0, 0, 0));
  798. // LinearPosition:=OwnerBaseSceneObject.Position.AsAffineVector;
  799. AngularOrientation := IdentityQuaternion; // fromAngleAxis(0,XVector);
  800. fTorque := nullVector;
  801. fForce := nullVector;
  802. // DampingEnabled:=False;
  803. // FTranslationDamping:=TGLDamping.Create(Self);
  804. FRotationDamping := TGLDamping.Create(Self);
  805. // RotationDamping:=TGLDamping.Create(Self);
  806. R := IdentityMatrix;
  807. InverseInertiaTensor := IdentityMatrix;
  808. // CalcAuxiliary();
  809. // SetDESolver(ssEuler);
  810. end;
  811. destructor TGLRigidBodyInertia.Destroy;
  812. begin
  813. // FLinearDamping.Free;
  814. // FAngularDamping.Free;
  815. fInertiaTensor.Free();
  816. fRotationSpeed.Free();
  817. FRotationDamping.Free;
  818. inherited Destroy;
  819. end;
  820. procedure TGLRigidBodyInertia.Assign(Source: TPersistent);
  821. begin
  822. if Source.ClassType = Self.ClassType then
  823. begin
  824. // FRigidBody.Assign(TGLRigidBodyInertia(Source));
  825. Mass := TGLRigidBodyInertia(Source).Mass;
  826. fDensity := TGLRigidBodyInertia(Source).fDensity;
  827. fBodyInertiaTensor := TGLRigidBodyInertia(Source).fBodyInertiaTensor;
  828. fBodyInverseInertiaTensor := TGLRigidBodyInertia(Source)
  829. .fBodyInverseInertiaTensor;
  830. InertiaTensor.Assign(TGLRigidBodyInertia(Source).InertiaTensor);
  831. LinearPosition := TGLRigidBodyInertia(Source).LinearPosition;
  832. AngularOrientation := TGLRigidBodyInertia(Source).AngularOrientation;
  833. LinearMomentum := TGLRigidBodyInertia(Source).LinearMomentum;
  834. AngularMomentum := TGLRigidBodyInertia(Source).AngularMomentum;
  835. // TranslationSpeed.AsAffineVector:=TGLRigidBodyInertia(Source).TranslationSpeed.AsAffineVector;
  836. RotationSpeed.Assign(TGLRigidBodyInertia(Source).RotationSpeed);
  837. // fForce:=TGLRigidBodyInertia(Source).fForce;
  838. fTorque := TGLRigidBodyInertia(Source).fTorque;
  839. // fInverseInertiaTensor:=TGLRigidBodyInertia(Source).fInverseInertiaTensor;
  840. // RigidBody.fTorque:=TGLRigidBodyInertia(Source).fTorque;
  841. // RigidBody.fForce:=TGLRigidBodyInertia(Source).fForce;
  842. FRotationDamping.Assign(TGLRigidBodyInertia(Source).FRotationDamping);
  843. // DampingEnabled:=TGLRigidBodyInertia(Source).DampingEnabled;
  844. // FTranslationDamping.Assign(TGLRigidBodyInertia(Source).LinearDamping);
  845. // FRotationDamping.Assign(TGLRigidBodyInertia(Source).AngularDamping);
  846. end;
  847. inherited Assign(Source);
  848. end;
  849. class function TGLRigidBodyInertia.FriendlyName: String;
  850. begin
  851. Result := 'Rigid Body Inertia';
  852. end;
  853. class function TGLRigidBodyInertia.FriendlyDescription: String;
  854. begin
  855. Result := 'An inertia model for rigid bodies';
  856. end;
  857. class function TGLRigidBodyInertia.UniqueItem: Boolean;
  858. begin
  859. Result := True;
  860. end;
  861. // **************************************************************************
  862. // ***************** DoProgress ************************************
  863. // **************************************************************************
  864. (*
  865. procedure TGLRigidBodyInertia.DoProgress(const progressTime : TProgressTimes);
  866. var
  867. TempScale:TaffineVector;
  868. UndampedLinearMomentum,DampedLinearMomentum:Real;
  869. UnDampedAngularMomentum,DampedAngularMomentum:Real;
  870. i:integer;
  871. begin
  872. // messagedlg('Calculating next state...',mtinformation,[mbOk],0);
  873. with OwnerBaseSceneObject do
  874. with progressTime do
  875. begin
  876. if (DampingEnabled=true) then
  877. begin
  878. UndampedLinearMomentum:=VectorLength(LinearMomentum);
  879. DampedLinearMomentum:=TranslationDamping.Calculate(UndampedLinearMomentum,deltaTime);
  880. { if GLS.VectorGeometry.vSIMD=1 then
  881. // RigidBody.LinearMomentum:=VectorScale(VectorNormalize(RigidBody.LinearMomentum),DampedLinearMomentum)
  882. else
  883. } begin
  884. if Length(LinearMomentum)<>0 then
  885. LinearMomentum:=VectorScale(VectorNormalize(LinearMomentum),DampedLinearMomentum)
  886. else
  887. LinearMomentum:=NullVector; //line not required
  888. end;
  889. UndampedAngularMomentum:=VectorLength(AngularMomentum);
  890. DampedAngularMomentum:=RotationDamping.Calculate(UndampedAngularMomentum,deltaTime);
  891. AngularMomentum:=VectorScale(VectorNormalize(AngularMomentum),DampedAngularMomentum);
  892. // ApplyForce(VectorScale(RigidBody.LinearVelocity,-0.5)); //Either apply resistive force & torque
  893. // ApplyTorque(VectorLength(RigidBody.AngularVelocity)); //or use TGLDamping
  894. end;
  895. // Euler(RigidBody,deltaTime);
  896. // RungeKutta4(DeltaTime);
  897. //DESolver(RigidBody,DeltaTime);
  898. //update OwnerBaseSceneObject
  899. TempScale:=Scale.AsAffineVector;
  900. Matrix:=QuaternionToMatrix(AngularOrientation);
  901. position.AsAffineVector:=LinearPosition;
  902. Scale.AsAffineVector:=TempScale;
  903. //calc auxiliary variables for next iteration
  904. CalcAuxiliary();
  905. end;
  906. end;
  907. *)
  908. procedure TGLRigidBodyInertia.WriteToFiler(writer: TWriter);
  909. begin
  910. inherited WriteToFiler(writer);
  911. with writer do
  912. begin
  913. // WriteInteger(0); // Archive Version 0
  914. // FRigidBody.WriteToFiler(writer);
  915. // WriteFloat(fMass);
  916. WriteFloat(fDensity);
  917. Write(fBodyInertiaTensor, SizeOf(fBodyInertiaTensor));
  918. Write(fBodyInverseInertiaTensor, SizeOf(fBodyInverseInertiaTensor));
  919. fInertiaTensor.WriteToFiler(writer);
  920. Write(AngularOrientation, SizeOf(AngularOrientation));
  921. Write(AngularMomentum, SizeOf(AngularMomentum));
  922. // Write(LinearVelocity,SizeOf(LinearVelocity));
  923. RotationSpeed.WriteToFiler(writer);
  924. // Write(AngularVelocity,SizeOf(AngularVelocity));
  925. Write(fTorque, SizeOf(fTorque));
  926. // Write(fForce,SizeOf(fForce));
  927. FRotationDamping.WriteToFiler(writer);
  928. // WriteInteger(Integer(FDESolverType));
  929. // WriteBoolean(FDampingEnabled);
  930. // FLinearDamping.WriteToFiler(writer);
  931. // FAngularDamping.WriteToFiler(writer);
  932. end;
  933. end;
  934. procedure TGLRigidBodyInertia.ReadFromFiler(reader: TReader);
  935. begin
  936. inherited ReadFromFiler(reader);
  937. with reader do
  938. begin
  939. // ReadInteger; // ignore archiveVersion
  940. // FRigidBody.ReadFromFiler(Reader);
  941. // fMass:=ReadFloat;
  942. fDensity := ReadFloat;
  943. Read(fBodyInertiaTensor, SizeOf(fBodyInertiaTensor));
  944. Read(fBodyInverseInertiaTensor, SizeOf(fBodyInverseInertiaTensor));
  945. InertiaTensor.ReadFromFiler(reader);
  946. Read(AngularOrientation, SizeOf(AngularOrientation));
  947. Read(AngularMomentum, SizeOf(AngularMomentum));
  948. // Read(LinearVelocity,SizeOf(LinearVelocity));
  949. RotationSpeed.ReadFromFiler(reader);
  950. // Read(AngularVelocity,SizeOf(AngularVelocity));
  951. Read(fTorque, SizeOf(fTorque));
  952. // Read(fForce, SizeOf(fForce));
  953. FRotationDamping.ReadFromFiler(reader);
  954. // SetDESolver(TDESolverType(ReadInteger));
  955. // FDampingEnabled:=ReadBoolean;
  956. // FLinearDamping.ReadFromFiler(reader);
  957. // FAngularDamping.ReadFromFiler(reader);
  958. end;
  959. // SetDESolver(fDESolverType);
  960. // CalcAuxiliary();
  961. SetUpStartingState();
  962. end;
  963. function GetOrCreateRigidBodyInertia(behaviours: TGLBehaviours)
  964. : TGLRigidBodyInertia;
  965. var
  966. i: Integer;
  967. begin
  968. i := behaviours.IndexOfClass(TGLRigidBodyInertia);
  969. if i >= 0 then
  970. Result := TGLRigidBodyInertia(behaviours[i])
  971. else
  972. Result := TGLRigidBodyInertia.Create(behaviours);
  973. end;
  974. function GetOrCreateRigidBodyInertia(obj: TGLBaseSceneObject)
  975. : TGLRigidBodyInertia;
  976. begin
  977. Result := GetOrCreateRigidBodyInertia(obj.behaviours);
  978. end;
  979. // ------------------------------------------------------------------
  980. initialization
  981. // ------------------------------------------------------------------
  982. // class registrations
  983. RegisterXCollectionItemClass(TGLParticleInertia);
  984. RegisterXCollectionItemClass(TGLRigidBodyInertia);
  985. end.