GLS.PhysInertias.pas 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.PhysInertias;
  5. interface
  6. uses
  7. System.SysUtils,
  8. System.Classes,
  9. GLS.PersistentClasses,
  10. GLS.XCollection,
  11. GLS.BaseClasses,
  12. Stage.VectorGeometry,
  13. Stage.VectorTypes,
  14. GLS.PhysManager,
  15. GLS.Coordinates,
  16. Stage.Strings,
  17. GLS.Scene,
  18. GLS.Behaviours;
  19. type
  20. TGLParticleInertia = class(TGLBaseInertia)
  21. // modified from TGLBInertia
  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: TGLVector; 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):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: 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. (*
  349. dampingForce:=VectorScale(VectorNormalize(velocity),
  350. -(Damping.Constant+Damping.Linear*v+Damping.Quadratic*v*v));
  351. *)
  352. ApplyForce(dampingForce);
  353. end;
  354. procedure TGLParticleInertia.SetTranslationDamping(const val: TGLDamping);
  355. begin
  356. FTranslationDamping.Assign(val);
  357. end;
  358. class function TGLParticleInertia.FriendlyName: String;
  359. begin
  360. Result := 'Particle Inertia';
  361. end;
  362. class function TGLParticleInertia.FriendlyDescription: String;
  363. begin
  364. Result := 'A simple translation inertia';
  365. end;
  366. class function TGLParticleInertia.UniqueItem: Boolean;
  367. begin
  368. Result := True;
  369. end;
  370. function TGLParticleInertia.CalcLinearPositionDot(): TAffineVector;
  371. begin
  372. Result := VectorScale(LinearMomentum, 1 / FMass);
  373. // Result:=FTranslationSpeed.AsAffineVector;
  374. end;
  375. function TGLParticleInertia.CalcLinearMomentumDot(): TAffineVector;
  376. begin
  377. Result := fForce;
  378. end;
  379. procedure TGLParticleInertia.StateToArray(var StateArray: TStateArray;
  380. StatePos: Integer);
  381. begin
  382. // SetLength(Result,StateSize);
  383. StateArray[StatePos] := LinearPosition.X; // position
  384. StateArray[StatePos + 1] := LinearPosition.Y;
  385. StateArray[StatePos + 2] := LinearPosition.Z;
  386. StateArray[StatePos + 3] := LinearMomentum.X; // momentum
  387. StateArray[StatePos + 4] := LinearMomentum.Y;
  388. StateArray[StatePos + 5] := LinearMomentum.Z;
  389. end;
  390. procedure TGLParticleInertia.ArrayToState(StateArray: TStateArray;
  391. StatePos: Integer);
  392. begin
  393. LinearPosition.X := StateArray[StatePos];
  394. LinearPosition.Y := StateArray[StatePos + 1];
  395. LinearPosition.Z := StateArray[StatePos + 2];
  396. LinearMomentum.X := StateArray[StatePos + 3];
  397. LinearMomentum.Y := StateArray[StatePos + 4];
  398. LinearMomentum.Z := StateArray[StatePos + 5];
  399. // TODO change?
  400. (* OwnerBaseSceneObject.position.x:=StateArray[StatePos];//position
  401. OwnerBaseSceneObject.position.y:=StateArray[StatePos+1];
  402. OwnerBaseSceneObject.position.z:=StateArray[StatePos+2];
  403. FTranslationSpeed.X:=StateArray[StatePos+3]/fMass;//velocity
  404. FTranslationSpeed.Y:=StateArray[StatePos+4]/fMass;
  405. FTranslationSpeed.Z:=StateArray[StatePos+5]/fMass;
  406. *)
  407. end;
  408. procedure TGLParticleInertia.CalcStateDot(var StateArray: TStateArray;
  409. StatePos: Integer);
  410. var
  411. LinPos, LinMom: TAffineVector;
  412. begin
  413. LinPos := CalcLinearPositionDot();
  414. LinMom := CalcLinearMomentumDot();
  415. StateArray[StatePos] := LinPos.X;
  416. StateArray[StatePos + 1] := LinPos.Y;
  417. StateArray[StatePos + 2] := LinPos.Z;
  418. StateArray[StatePos + 3] := LinMom.X;
  419. StateArray[StatePos + 4] := LinMom.Y;
  420. StateArray[StatePos + 5] := LinMom.Z;
  421. end;
  422. procedure TGLParticleInertia.MirrorTranslation;
  423. begin
  424. FTranslationSpeed.Invert;
  425. end;
  426. procedure TGLParticleInertia.SurfaceBounce(const surfaceNormal: TGLVector;
  427. restitution: Single);
  428. var
  429. f: Single;
  430. begin
  431. // does the current speed vector comply?
  432. f := VectorDotProduct(FTranslationSpeed.AsVector, surfaceNormal);
  433. if f < 0 then
  434. begin
  435. // remove the non-complying part of the speed vector
  436. FTranslationSpeed.AddScaledVector(-f / VectorNorm(surfaceNormal) *
  437. (1 + restitution), surfaceNormal);
  438. end;
  439. end;
  440. function GetOrCreateParticleInertia(behaviours: TGLBehaviours)
  441. : TGLParticleInertia;
  442. var
  443. i: Integer;
  444. begin
  445. i := behaviours.IndexOfClass(TGLParticleInertia);
  446. if i >= 0 then
  447. Result := TGLParticleInertia(behaviours[i])
  448. else
  449. Result := TGLParticleInertia.Create(behaviours);
  450. end;
  451. function GetOrCreateParticleInertia(obj: TGLBaseSceneObject)
  452. : TGLParticleInertia;
  453. begin
  454. Result := GetOrCreateParticleInertia(obj.behaviours);
  455. end;
  456. // -----------------------------------------------------------------------
  457. // ------------ TGLInertiaTensor
  458. // -----------------------------------------------------------------------
  459. constructor TGLInertiaTensor.Create(aOwner: TPersistent);
  460. begin
  461. inherited Create(aOwner);
  462. fm11 := 1;
  463. fm22 := 1;
  464. fm33 := 1;
  465. end;
  466. destructor TGLInertiaTensor.Destroy;
  467. begin
  468. inherited Destroy;
  469. end;
  470. procedure TGLInertiaTensor.Assign(Source: TPersistent);
  471. begin
  472. inherited;
  473. fm11 := TGLInertiaTensor(Source).fm11;
  474. fm12 := TGLInertiaTensor(Source).fm12;
  475. fm13 := TGLInertiaTensor(Source).fm13;
  476. fm21 := TGLInertiaTensor(Source).fm21;
  477. fm22 := TGLInertiaTensor(Source).fm22;
  478. fm23 := TGLInertiaTensor(Source).fm23;
  479. fm31 := TGLInertiaTensor(Source).fm31;
  480. fm32 := TGLInertiaTensor(Source).fm32;
  481. fm33 := TGLInertiaTensor(Source).fm33;
  482. end;
  483. procedure TGLInertiaTensor.WriteToFiler(writer: TWriter);
  484. begin
  485. inherited;
  486. with writer do
  487. begin
  488. WriteInteger(0); // Archive Version 0
  489. WriteFloat(fm11);
  490. WriteFloat(fm12);
  491. WriteFloat(fm13);
  492. WriteFloat(fm21);
  493. WriteFloat(fm22);
  494. WriteFloat(fm23);
  495. WriteFloat(fm31);
  496. WriteFloat(fm32);
  497. WriteFloat(fm33);
  498. end;
  499. end;
  500. procedure TGLInertiaTensor.ReadFromFiler(reader: TReader);
  501. begin
  502. inherited;
  503. with reader do
  504. begin
  505. ReadInteger(); // Archive Version 0
  506. fm11 := ReadFloat();
  507. fm12 := ReadFloat();
  508. fm13 := ReadFloat();
  509. fm21 := ReadFloat();
  510. fm22 := ReadFloat();
  511. fm23 := ReadFloat();
  512. fm31 := ReadFloat();
  513. fm32 := ReadFloat();
  514. fm33 := ReadFloat();
  515. end;
  516. end;
  517. //--------------------------
  518. // TGLRigidBodyInertia
  519. //--------------------------
  520. procedure TGLRigidBodyInertia.SetInertiaTensor(newVal: TGLInertiaTensor);
  521. begin
  522. fInertiaTensor := newVal;
  523. end;
  524. procedure TGLRigidBodyInertia.SetRotationSpeed(const val: TGLCoordinates);
  525. begin
  526. AngularMomentum := VectorTransform(val.AsAffineVector, fBodyInertiaTensor);
  527. fRotationSpeed.Assign(val);
  528. end;
  529. procedure TGLRigidBodyInertia.SetRotationDamping(const val: TGLDamping);
  530. begin
  531. FRotationDamping.Assign(val);
  532. end;
  533. procedure TGLRigidBodyInertia.ApplyImpulse(j, xpos, ypos, zpos, x, y, z: Real);
  534. begin
  535. // V2 = V1 + (j/M)n
  536. // V2.M = V1.M +j.n
  537. LinearMomentum.X := LinearMomentum.X + j * x;
  538. LinearMomentum.Y := LinearMomentum.Y + j * y;
  539. LinearMomentum.Z := LinearMomentum.Z + j * z;
  540. AngularMomentum.X := AngularMomentum.X + j * x * xpos;
  541. AngularMomentum.Y := AngularMomentum.Y + j * y * ypos;
  542. AngularMomentum.Z := AngularMomentum.Z + j * z * zpos;
  543. end;
  544. procedure TGLRigidBodyInertia.ApplyImpulse(j: Single;
  545. position, normal: TAffineVector);
  546. begin
  547. CombineVector(LinearMomentum, normal, j);
  548. CombineVector(AngularMomentum, VectorCrossProduct(position, normal), j); // ?
  549. end;
  550. procedure TGLRigidBodyInertia.ApplyDamping(damping: TGLDamping);
  551. var
  552. velocity, angularvelocity: TAffineVector;
  553. v, angularv: Real;
  554. dampingForce: TAffineVector;
  555. angulardampingForce: TAffineVector;
  556. begin
  557. velocity := VectorScale(LinearMomentum, 1 / Mass); // v = p/m
  558. // apply force in opposite direction to velocity
  559. v := VectorLength(velocity);
  560. // F = -Normalised(V)*( Constant + (Linear)*(V) + (Quadtratic)*(V)*(V) )
  561. dampingForce := VectorScale(VectorNormalize(velocity),
  562. -(damping.Constant + damping.Linear * v + damping.Quadratic * v * v));
  563. // ScaleVector(AngularMomentum,0.999);
  564. // ScaleVector(AngularVelocity,Damping.Constant);
  565. // dampingForce:=VectorScale(VectorNormalize(velocity),-(Damping.Constant+Damping.Linear*v+Damping.Quadratic*v*v));
  566. ApplyForce(dampingForce);
  567. angularvelocity := RotationSpeed.AsAffineVector; // v = p/m
  568. // apply force in opposite direction to velocity
  569. angularv := VectorLength(angularvelocity);
  570. // F = -Normalised(V)*( Constant + (Linear)*(V) + (Quadtratic)*(V)*(V) )
  571. angulardampingForce := VectorScale(VectorNormalize(angularvelocity),
  572. -(RotationDamping.Constant + RotationDamping.Linear * v +
  573. RotationDamping.Quadratic * v * v));
  574. // ScaleVector(AngularMomentum,0.999);
  575. // ScaleVector(AngularVelocity,Damping.Constant);
  576. // dampingForce:=VectorScale(VectorNormalize(velocity),-(Damping.Constant+Damping.Linear*v+Damping.Quadratic*v*v));
  577. ApplyTorque(angulardampingForce.X, angulardampingForce.Y, angulardampingForce.Z);
  578. end;
  579. procedure TGLRigidBodyInertia.CalcStateDot(var StateArray: TStateArray;
  580. StatePos: Integer);
  581. var
  582. LinPos, LinMom, AngMom: TAffineVector;
  583. AngPos: TQuaternion;
  584. begin
  585. LinPos := CalcLinearPositionDot();
  586. LinMom := CalcLinearMomentumDot();
  587. AngPos := CalcAngularOrientationDot();
  588. AngMom := CalcAngularVelocityDot();
  589. // SetLength(Result,StateSize);
  590. StateArray[StatePos] := LinPos.X;
  591. StateArray[StatePos + 1] := LinPos.Y;
  592. StateArray[StatePos + 2] := LinPos.Z;
  593. StateArray[StatePos + 3] := LinMom.X;
  594. StateArray[StatePos + 4] := LinMom.Y;
  595. StateArray[StatePos + 5] := LinMom.Z;
  596. StateArray[StatePos + 6] := AngPos.imagPart.X;
  597. StateArray[StatePos + 7] := AngPos.imagPart.Y;
  598. StateArray[StatePos + 8] := AngPos.imagPart.Z;
  599. StateArray[StatePos + 9] := AngPos.RealPart;
  600. StateArray[StatePos + 10] := AngMom.X;
  601. StateArray[StatePos + 11] := AngMom.Y;
  602. StateArray[StatePos + 12] := AngMom.Z;
  603. end;
  604. function TGLRigidBodyInertia.CalculateKE(): Real;
  605. begin
  606. // Result:= "Linear KE" + "Angular KE"
  607. // only linear part so far
  608. Result := 1 / (2 * Mass) * VectorNorm(LinearMomentum);
  609. end;
  610. function TGLRigidBodyInertia.CalculatePE(): Real;
  611. begin
  612. // need to find potentials due to fields acting on body
  613. // may be easier to do via forcefieldemitters?
  614. Result := 0;
  615. end;
  616. function TGLRigidBodyInertia.CalcAngularOrientationDot(): TQuaternion;
  617. var
  618. q1: TQuaternion;
  619. begin
  620. q1.imagPart := VectorScale(RotationSpeed.AsAffineVector, 1 / 2); // v1;
  621. q1.RealPart := 0;
  622. Result := QuaternionMultiply(q1, AngularOrientation);
  623. end;
  624. function TGLRigidBodyInertia.CalcAngularVelocityDot(): TAffineVector;
  625. begin
  626. Result := fTorque;
  627. end;
  628. function TGLRigidBodyInertia.QuaternionToString(Quat: TQuaternion): String;
  629. begin
  630. Result := '<Quaternion><imagPart>' + FloatToSTr(Quat.imagPart.X) + ',' +
  631. FloatToSTr(Quat.imagPart.Y) + ',' + FloatToSTr(Quat.imagPart.Z) +
  632. '</imagPart><realPart>' + FloatToSTr(Quat.RealPart) +
  633. '</realPart><Quaternion>';
  634. end;
  635. (*
  636. function TGLRigidBodyInertia.Star(Vector:TAffineVector):TGLMatrix;
  637. begin
  638. Result.X.X:=0; Result[0][1]:=-Vector[2]; Result[0][2]:=Vector[1]; Result[0][3]:=0;
  639. Result[1][0]:=Vector[2]; Result[1][1]:=0; Result[1][2]:=-Vector[0]; Result[1][3]:=0;
  640. Result[2][0]:=Vector[1]; Result[2][1]:=Vector[0]; Result[2][2]:=0; Result[2][3]:=0;
  641. Result[3][0]:=0; Result[3][1]:=0; Result[3][2]:=0; Result[3][3]:=1;
  642. end;
  643. *)
  644. procedure TGLRigidBodyInertia.SetTorque(x, y, z: Real);
  645. begin
  646. fTorque.X := x;
  647. fTorque.Y := y;
  648. fTorque.Z := z;
  649. end;
  650. procedure TGLRigidBodyInertia.ApplyTorque(x, y, z: Real);
  651. begin
  652. fTorque.X := fTorque.X + x;
  653. fTorque.Y := fTorque.Y + y;
  654. fTorque.Z := fTorque.Z + z;
  655. end;
  656. (*
  657. procedure TGLRigidBodyInertia.ApplyImpulse(x,y,z:Real);
  658. begin
  659. //
  660. end;
  661. *)
  662. procedure TGLRigidBodyInertia.RemoveForces();
  663. begin
  664. fForce := nullVector;
  665. fTorque := nullVector;
  666. end;
  667. procedure TGLRigidBodyInertia.ApplyForce(pos, Force: TVector3f);
  668. var
  669. abspos: TAffineVector;
  670. begin
  671. abspos := VectorTransform(pos, R);
  672. fTorque := VectorAdd(fTorque, VectorCrossProduct(abspos, Force));
  673. fForce := VectorAdd(fForce, Force);
  674. end;
  675. procedure TGLRigidBodyInertia.ApplyLocalForce(pos, Force: TVector3f);
  676. var
  677. abspos: TAffineVector;
  678. absForce: TAffineVector;
  679. begin
  680. abspos := VectorTransform(pos, R);
  681. absForce := VectorTransform(Force, R);
  682. fTorque := VectorAdd(fTorque, VectorCrossProduct(abspos, absForce));
  683. fForce := VectorAdd(fForce, absForce);
  684. end;
  685. procedure TGLRigidBodyInertia.ApplyLocalImpulse(xpos, ypos, zpos, x, y,
  686. z: Real);
  687. begin
  688. //
  689. end;
  690. procedure TGLRigidBodyInertia.SetUpStartingState();
  691. begin
  692. //
  693. inherited SetUpStartingState();
  694. fBodyInertiaTensor.X.X := InertiaTensor.fm11;
  695. fBodyInertiaTensor.X.Y := InertiaTensor.fm12;
  696. fBodyInertiaTensor.X.Z := InertiaTensor.fm13;
  697. fBodyInertiaTensor.Y.X := InertiaTensor.fm21;
  698. fBodyInertiaTensor.Y.Y := InertiaTensor.fm22;
  699. fBodyInertiaTensor.Y.Z := InertiaTensor.fm23;
  700. fBodyInertiaTensor.Z.X := InertiaTensor.fm31;
  701. fBodyInertiaTensor.Z.Y := InertiaTensor.fm32;
  702. fBodyInertiaTensor.Z.Z := InertiaTensor.fm33;
  703. fBodyInverseInertiaTensor := fBodyInertiaTensor;
  704. InvertMatrix(fBodyInverseInertiaTensor);
  705. // Write
  706. (*
  707. Messagedlg('setting BodyIit: '+ Format('%f,%f,%f,%f,%f,%f,%f,%f,%f',
  708. [fBodyInverseInertiaTensor[0][0],fBodyInverseInertiaTensor[0][1],fBodyInverseInertiaTensor[0][2],
  709. fBodyInverseInertiaTensor[1][0],fBodyInverseInertiaTensor[1][1],fBodyInverseInertiaTensor[1][2],
  710. fBodyInverseInertiaTensor[2][0],fBodyInverseInertiaTensor[2][1],
  711. fBodyInverseInertiaTensor[2][2]]),mtinformation,[mbok],0);
  712. *)
  713. AngularOrientation := IdentityQuaternion;
  714. AngularMomentum := VectorTransform(RotationSpeed.AsAffineVector,
  715. fBodyInertiaTensor);
  716. end;
  717. procedure TGLRigidBodyInertia.CalcAuxiliary();
  718. var
  719. IRt: TAffineMAtrix;
  720. Rt: TAffineMAtrix;
  721. Scale: TAffineVector;
  722. RMatrix: TGLMatrix;
  723. begin
  724. // TODO: sort this out
  725. fBodyInverseInertiaTensor := IdentityMatrix;
  726. // compute auxiliary variables
  727. R := QuaternionToAffineMatrix(AngularOrientation);
  728. Rt := R;
  729. TransposeMatrix(Rt);
  730. IRt := MatrixMultiply(fBodyInverseInertiaTensor, Rt);
  731. InverseInertiaTensor := MatrixMultiply(R, IRt);
  732. RotationSpeed.AsAffineVector := VectorTransform(AngularMomentum,
  733. InverseInertiaTensor);
  734. TranslationSpeed.AsAffineVector := VectorScale(LinearMomentum, 1 / Mass);
  735. Scale := OwnerBaseSceneObject.Scale.AsAffineVector;
  736. OwnerBaseSceneObject.BeginUpdate;
  737. SetMatrix(RMatrix, R);
  738. OwnerBaseSceneObject.SetMatrix(RMatrix);
  739. // OwnerBaseSceneObject.Matrix:=QuaternionToMatrix(AngularOrientation);
  740. OwnerBaseSceneObject.Scale.AsAffineVector := Scale;
  741. OwnerBaseSceneObject.position.x := LinearPosition.X; // position
  742. OwnerBaseSceneObject.position.y := LinearPosition.Y;
  743. OwnerBaseSceneObject.position.z := LinearPosition.Z;
  744. OwnerBaseSceneObject.EndUpdate;
  745. end;
  746. procedure TGLRigidBodyInertia.StateToArray(var StateArray: TStateArray;
  747. StatePos: Integer);
  748. begin
  749. // with State do
  750. begin
  751. // copy Linear Position
  752. StateArray[StatePos] := LinearPosition.X;
  753. StateArray[StatePos + 1] := LinearPosition.Y;
  754. StateArray[StatePos + 2] := LinearPosition.Z;
  755. // copy Linear Momentum
  756. StateArray[StatePos + 3] := LinearMomentum.X;
  757. StateArray[StatePos + 4] := LinearMomentum.Y;
  758. StateArray[StatePos + 5] := LinearMomentum.Z;
  759. // copy Angular Orientation
  760. StateArray[StatePos + 6] := AngularOrientation.imagPart.X;
  761. StateArray[StatePos + 7] := AngularOrientation.imagPart.Y;
  762. StateArray[StatePos + 8] := AngularOrientation.imagPart.Z;
  763. StateArray[StatePos + 9] := AngularOrientation.RealPart;
  764. // copy Angular Momentum
  765. StateArray[StatePos + 10] := AngularMomentum.X;
  766. StateArray[StatePos + 11] := AngularMomentum.Y;
  767. StateArray[StatePos + 12] := AngularMomentum.Z;
  768. end;
  769. end;
  770. procedure TGLRigidBodyInertia.ArrayToState( { var } StateArray: TStateArray;
  771. StatePos: Integer);
  772. begin
  773. // restore Linear Position
  774. LinearPosition.X := StateArray[StatePos];
  775. LinearPosition.Y := StateArray[StatePos + 1];
  776. LinearPosition.Z := StateArray[StatePos + 2];
  777. // restore Linear Momentum
  778. LinearMomentum.X := StateArray[StatePos + 3];
  779. LinearMomentum.Y := StateArray[StatePos + 4];
  780. LinearMomentum.Z := StateArray[StatePos + 5];
  781. // restore Angular Orientation
  782. AngularOrientation.imagPart.X := StateArray[StatePos + 6];
  783. AngularOrientation.imagPart.Y := StateArray[StatePos + 7];
  784. AngularOrientation.imagPart.Z := StateArray[StatePos + 8];
  785. AngularOrientation.RealPart := StateArray[StatePos + 9];
  786. // restore Angular Momentum
  787. AngularMomentum.X := StateArray[StatePos + 10];
  788. AngularMomentum.Y := StateArray[StatePos + 11];
  789. AngularMomentum.Z := StateArray[StatePos + 12];
  790. end;
  791. procedure TGLRigidBodyInertia.SetLinearDamping(const val: TGLDamping);
  792. begin
  793. // FLinearDamping.Assign(val);
  794. end;
  795. procedure TGLRigidBodyInertia.SetAngularDamping(const val: TGLDamping);
  796. begin
  797. // FAngularDamping.Assign(val);
  798. end;
  799. constructor TGLRigidBodyInertia.Create(aOwner: TXCollection);
  800. begin
  801. inherited Create(aOwner);
  802. Mass := 1;
  803. fDensity := 1;
  804. StateSize := 13;
  805. fInertiaTensor := TGLInertiaTensor.Create(Self);
  806. fRotationSpeed := TGLCoordinates.CreateInitialized(Self, VectorMake(0, 0, 0));
  807. // LinearPosition:=OwnerBaseSceneObject.Position.AsAffineVector;
  808. AngularOrientation := IdentityQuaternion; // fromAngleAxis(0,XVector);
  809. fTorque := nullVector;
  810. fForce := nullVector;
  811. // DampingEnabled:=False;
  812. // FTranslationDamping:=TGLDamping.Create(Self);
  813. FRotationDamping := TGLDamping.Create(Self);
  814. // RotationDamping:=TGLDamping.Create(Self);
  815. R := IdentityMatrix;
  816. InverseInertiaTensor := IdentityMatrix;
  817. // CalcAuxiliary();
  818. // SetDESolver(ssEuler);
  819. end;
  820. //---------------------------------------------------------------------------
  821. destructor TGLRigidBodyInertia.Destroy;
  822. begin
  823. // FLinearDamping.Free;
  824. // FAngularDamping.Free;
  825. fInertiaTensor.Free();
  826. fRotationSpeed.Free();
  827. FRotationDamping.Free;
  828. inherited Destroy;
  829. end;
  830. procedure TGLRigidBodyInertia.Assign(Source: TPersistent);
  831. begin
  832. if Source.ClassType = Self.ClassType then
  833. begin
  834. // FRigidBody.Assign(TGLRigidBodyInertia(Source));
  835. Mass := TGLRigidBodyInertia(Source).Mass;
  836. fDensity := TGLRigidBodyInertia(Source).fDensity;
  837. fBodyInertiaTensor := TGLRigidBodyInertia(Source).fBodyInertiaTensor;
  838. fBodyInverseInertiaTensor := TGLRigidBodyInertia(Source)
  839. .fBodyInverseInertiaTensor;
  840. InertiaTensor.Assign(TGLRigidBodyInertia(Source).InertiaTensor);
  841. LinearPosition := TGLRigidBodyInertia(Source).LinearPosition;
  842. AngularOrientation := TGLRigidBodyInertia(Source).AngularOrientation;
  843. LinearMomentum := TGLRigidBodyInertia(Source).LinearMomentum;
  844. AngularMomentum := TGLRigidBodyInertia(Source).AngularMomentum;
  845. // TranslationSpeed.AsAffineVector:=TGLRigidBodyInertia(Source).TranslationSpeed.AsAffineVector;
  846. RotationSpeed.Assign(TGLRigidBodyInertia(Source).RotationSpeed);
  847. // fForce:=TGLRigidBodyInertia(Source).fForce;
  848. fTorque := TGLRigidBodyInertia(Source).fTorque;
  849. // fInverseInertiaTensor:=TGLRigidBodyInertia(Source).fInverseInertiaTensor;
  850. // RigidBody.fTorque:=TGLRigidBodyInertia(Source).fTorque;
  851. // RigidBody.fForce:=TGLRigidBodyInertia(Source).fForce;
  852. FRotationDamping.Assign(TGLRigidBodyInertia(Source).FRotationDamping);
  853. // DampingEnabled:=TGLRigidBodyInertia(Source).DampingEnabled;
  854. // FTranslationDamping.Assign(TGLRigidBodyInertia(Source).LinearDamping);
  855. // FRotationDamping.Assign(TGLRigidBodyInertia(Source).AngularDamping);
  856. end;
  857. inherited Assign(Source);
  858. end;
  859. class function TGLRigidBodyInertia.FriendlyName: String;
  860. begin
  861. Result := 'Rigid Body Inertia';
  862. end;
  863. class function TGLRigidBodyInertia.FriendlyDescription: String;
  864. begin
  865. Result := 'An inertia model for rigid bodies';
  866. end;
  867. class function TGLRigidBodyInertia.UniqueItem: Boolean;
  868. begin
  869. Result := True;
  870. end;
  871. // **************************************************************************
  872. // ***************** DoProgress ************************************
  873. // **************************************************************************
  874. (*
  875. procedure TGLRigidBodyInertia.DoProgress(const progressTime : TProgressTimes);
  876. var
  877. TempScale:TaffineVector;
  878. UndampedLinearMomentum,DampedLinearMomentum:Real;
  879. UnDampedAngularMomentum,DampedAngularMomentum:Real;
  880. i:integer;
  881. begin
  882. // Write('Calculating next state...');
  883. with OwnerBaseSceneObject do
  884. with progressTime do
  885. begin
  886. if (DampingEnabled=true) then
  887. begin
  888. UndampedLinearMomentum:=VectorLength(LinearMomentum);
  889. DampedLinearMomentum:=TranslationDamping.Calculate(UndampedLinearMomentum,deltaTime);
  890. { if Stage.VectorGeometry.vSIMD=1 then
  891. // RigidBody.LinearMomentum:=VectorScale(VectorNormalize(RigidBody.LinearMomentum),DampedLinearMomentum)
  892. else
  893. } begin
  894. if Length(LinearMomentum)<>0 then
  895. LinearMomentum:=VectorScale(VectorNormalize(LinearMomentum),DampedLinearMomentum)
  896. else
  897. LinearMomentum:=NullVector; //line not required
  898. end;
  899. UndampedAngularMomentum:=VectorLength(AngularMomentum);
  900. DampedAngularMomentum:=RotationDamping.Calculate(UndampedAngularMomentum,deltaTime);
  901. AngularMomentum:=VectorScale(VectorNormalize(AngularMomentum),DampedAngularMomentum);
  902. // ApplyForce(VectorScale(RigidBody.LinearVelocity,-0.5)); //Either apply resistive force & torque
  903. // ApplyTorque(VectorLength(RigidBody.AngularVelocity)); //or use TGLDamping
  904. end;
  905. // Euler(RigidBody,deltaTime);
  906. // RungeKutta4(DeltaTime);
  907. //DESolver(RigidBody,DeltaTime);
  908. //update OwnerBaseSceneObject
  909. TempScale:=Scale.AsAffineVector;
  910. Matrix:=QuaternionToMatrix(AngularOrientation);
  911. position.AsAffineVector:=LinearPosition;
  912. Scale.AsAffineVector:=TempScale;
  913. //calc auxiliary variables for next iteration
  914. CalcAuxiliary();
  915. end;
  916. end;
  917. *)
  918. procedure TGLRigidBodyInertia.WriteToFiler(writer: TWriter);
  919. begin
  920. inherited WriteToFiler(writer);
  921. with writer do
  922. begin
  923. // WriteInteger(0); // Archive Version 0
  924. // FRigidBody.WriteToFiler(writer);
  925. // WriteFloat(fMass);
  926. WriteFloat(fDensity);
  927. Write(fBodyInertiaTensor, SizeOf(fBodyInertiaTensor));
  928. Write(fBodyInverseInertiaTensor, SizeOf(fBodyInverseInertiaTensor));
  929. fInertiaTensor.WriteToFiler(writer);
  930. Write(AngularOrientation, SizeOf(AngularOrientation));
  931. Write(AngularMomentum, SizeOf(AngularMomentum));
  932. // Write(LinearVelocity,SizeOf(LinearVelocity));
  933. RotationSpeed.WriteToFiler(writer);
  934. // Write(AngularVelocity,SizeOf(AngularVelocity));
  935. Write(fTorque, SizeOf(fTorque));
  936. // Write(fForce,SizeOf(fForce));
  937. FRotationDamping.WriteToFiler(writer);
  938. // WriteInteger(Integer(FDESolverType));
  939. // WriteBoolean(FDampingEnabled);
  940. // FLinearDamping.WriteToFiler(writer);
  941. // FAngularDamping.WriteToFiler(writer);
  942. end;
  943. end;
  944. procedure TGLRigidBodyInertia.ReadFromFiler(reader: TReader);
  945. begin
  946. inherited ReadFromFiler(reader);
  947. with reader do
  948. begin
  949. // ReadInteger; // ignore archiveVersion
  950. // FRigidBody.ReadFromFiler(Reader);
  951. // fMass:=ReadFloat;
  952. fDensity := ReadFloat;
  953. Read(fBodyInertiaTensor, SizeOf(fBodyInertiaTensor));
  954. Read(fBodyInverseInertiaTensor, SizeOf(fBodyInverseInertiaTensor));
  955. InertiaTensor.ReadFromFiler(reader);
  956. Read(AngularOrientation, SizeOf(AngularOrientation));
  957. Read(AngularMomentum, SizeOf(AngularMomentum));
  958. // Read(LinearVelocity,SizeOf(LinearVelocity));
  959. RotationSpeed.ReadFromFiler(reader);
  960. // Read(AngularVelocity,SizeOf(AngularVelocity));
  961. Read(fTorque, SizeOf(fTorque));
  962. // Read(fForce, SizeOf(fForce));
  963. FRotationDamping.ReadFromFiler(reader);
  964. // SetDESolver(TDESolverType(ReadInteger));
  965. // FDampingEnabled:=ReadBoolean;
  966. // FLinearDamping.ReadFromFiler(reader);
  967. // FAngularDamping.ReadFromFiler(reader);
  968. end;
  969. // SetDESolver(fDESolverType);
  970. // CalcAuxiliary();
  971. SetUpStartingState();
  972. end;
  973. function GetOrCreateRigidBodyInertia(behaviours: TGLBehaviours)
  974. : TGLRigidBodyInertia;
  975. var
  976. i: Integer;
  977. begin
  978. i := behaviours.IndexOfClass(TGLRigidBodyInertia);
  979. if i >= 0 then
  980. Result := TGLRigidBodyInertia(behaviours[i])
  981. else
  982. Result := TGLRigidBodyInertia.Create(behaviours);
  983. end;
  984. function GetOrCreateRigidBodyInertia(obj: TGLBaseSceneObject)
  985. : TGLRigidBodyInertia;
  986. begin
  987. Result := GetOrCreateRigidBodyInertia(obj.behaviours);
  988. end;
  989. // ------------------------------------------------------------------
  990. initialization
  991. // ------------------------------------------------------------------
  992. // class registrations
  993. RegisterXCollectionItemClass(TGLParticleInertia);
  994. RegisterXCollectionItemClass(TGLRigidBodyInertia);
  995. end.