123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- //
- // The multimedia graphics platform GLScene https://github.com/glscene
- //
- unit Physics.SPIForces;
- interface
- uses
- System.Classes,
- Vcl.Dialogs,
- GLS.VectorTypes,
- GLS.XCollection,
- GLS.Scene,
- GLS.VectorGeometry,
- GLS.Behaviours,
- GLS.Coordinates,
- GLS.Strings;
- type
- TGLForce = class;
- TGLForceType = (ftHookes, ftGravitation, ftCustom);
- TOnCustomForce = procedure() of object;
- TGLForce = class(TXCollectionItem)
- private
- fObject1: TGLBaseSceneObject;
- fObject2: TGLBaseSceneObject;
- fposition1: TGLCoordinates;
- fposition2: TGLCoordinates;
- object1Name: String;
- object2Name: String;
- // fOnCustomForce: TOnCustomForce;
- protected
- procedure Loaded; override;
- procedure SetName(const val: String); override;
- (* Returns the TGLBaseSceneObject on which the behaviour should be applied.
- Does NOT check for nil owners *)
- // function OwnerBaseSceneObject : TGLBaseSceneObject;
- public
- (* constructor Create(Collection: TCollection);override; *)
- // Override this function to write subclass data.
- procedure WriteToFiler(writer: TWriter); override;
- // Override this function to read subclass data.
- procedure ReadFromFiler(reader: TReader); override;
- constructor Create(aOwner: TXCollection); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- class function FriendlyName: String; override;
- class function FriendlyDescription: String; override;
- class function UniqueItem: Boolean; override;
- procedure SetObject1(const val: TGLBaseSceneObject);
- procedure SetObject2(const val: TGLBaseSceneObject);
- procedure SetPosition1(const val: TGLCoordinates);
- procedure SetPosition2(const val: TGLCoordinates);
- function CalculateForce(): TAffineVector; virtual;
- published
- property Object1: TGLBaseSceneObject read fObject1 write SetObject1;
- property Object2: TGLBaseSceneObject read fObject2 write SetObject2;
- property Position1: TGLCoordinates read fposition1 write SetPosition1;
- property Position2: TGLCoordinates read fposition2 write SetPosition2;
- // property OnCustomForce:TOnCustomForce read fOnCustomForce write fOnCustomForce;
- end;
- TGLHookesSpring = class(TGLForce)
- private
- fNaturalLength: Real;
- fElasticity: Real;
- fLength: Real;
- fExtension: Real;
- fDamping: TGLDamping;
- public
- procedure WriteToFiler(writer: TWriter); override;
- procedure ReadFromFiler(reader: TReader); override;
- constructor Create(aOwner: TXCollection); override;
- destructor Destroy; override;
- class function FriendlyName: String; override;
- class function FriendlyDescription: String; override;
- class function UniqueItem: Boolean; override;
- procedure SetDamping(const val: TGLDamping);
- function CalculateForce(): TAffineVector; override;
- published
- property NaturalLength: Real read fNaturalLength write fNaturalLength;
- property Elasticity: Real read fElasticity write fElasticity;
- property Damping: TGLDamping read fDamping write SetDamping;
- // property Name;
- end;
- TGLHookesString = class(TGLHookesSpring)
- protected
- // procedure WriteToFiler(writer : TWriter); override;
- // procedure ReadFromFiler(reader : TReader); override;
- public
- constructor Create(aOwner: TXCollection); override;
- destructor Destroy; override;
- class function FriendlyName: String; override;
- class function FriendlyDescription: String; override;
- class function UniqueItem: Boolean; override;
- function CalculateForce(): TAffineVector; override;
- end;
- // --------------------------------------------------------------
- implementation
- // --------------------------------------------------------------
- uses
- Physics.SPIInertias,
- Physics.SPIManager;
- constructor TGLForce.Create(aOwner: TXCollection);
- begin
- inherited; // Create(aOwner)
- fposition1 := TGLCoordinates.CreateInitialized(Self, NullHmgVector, csVector);
- fposition2 := TGLCoordinates.CreateInitialized(Self, NullHmgVector, csVector);
- // fObject1:=TGLBaseSceneObject.Create(Self);
- // fObject2:=TGLBaseSceneObject.Create(Self);
- end;
- destructor TGLForce.Destroy;
- begin
- fposition1.Free();
- fposition2.Free();
- // SetObject1(nil);
- // SetObject2(nil);
- // fObject1.Free();
- // fObject2.Free();
- inherited Destroy;
- end;
- procedure TGLForce.Assign(Source: TPersistent);
- begin
- // inherited Assign(Source);
- fposition1.Assign(TGLForce(Source).fposition1);
- fposition2.Assign(TGLForce(Source).fposition2);
- Object1 := TGLForce(Source).Object1;
- Object2 := TGLForce(Source).Object2;
- inherited Assign(Source);
- end;
- procedure TGLForce.SetObject1(const val: TGLBaseSceneObject);
- begin
- // if val.Behaviours.IndexOfClass(TGLBaseInertia) >=0 then
- fObject1 := val
- // else
- // messagedlg('Object1 does not have an inertia behaviour',mtWarning,[mbOk],0);
- end;
- procedure TGLForce.SetObject2(const val: TGLBaseSceneObject);
- begin
- // if val.Behaviours.IndexOfClass(TGLBaseInertia) >=0 then
- fObject2 := val
- // else
- // messagedlg('Object2 does not have an inertia behaviour',mtWarning,[mbOk],0);
- end;
- procedure TGLForce.SetPosition1(const val: TGLCoordinates);
- begin
- fposition1.Assign(val); // DB101
- end;
- procedure TGLForce.SetPosition2(const val: TGLCoordinates);
- begin
- fposition2.Assign(val);
- end;
- procedure TGLForce.Loaded;
- var
- PhysMan: TGLSPIManager;
- begin
- inherited Loaded;
- // not nice, not nice at all!!!!!!
- // assumes owner is TGLForces belonging to TGLPhysicsManager
- PhysMan := TGLSPIManager(Self.Owner.Owner);
- if (object1Name <> '') then
- begin
- // PhysMan:=TGLPhysicsManager(Self.Owner.Owner);
- fObject1 := PhysMan.FindObjectByName(object1Name);
- // fObject1:=TGLBaseSceneObject(FindComponent(Object1Name));
- // Object1Name:='';
- end;
- if object2Name <> '' then
- begin
- fObject2 := PhysMan.FindObjectByName(object2Name);
- // Object2Name:='';
- end;
- end;
- class function TGLForce.FriendlyName: String;
- begin
- Result := 'Force';
- end;
- class function TGLForce.FriendlyDescription: String;
- begin
- Result := 'Physics Force';
- end;
- class function TGLForce.UniqueItem: Boolean;
- begin
- Result := false;
- end;
- procedure TGLForce.WriteToFiler(writer: TWriter);
- begin
- inherited WriteToFiler(writer);
- // messagedlg('Writing to filer'+GetNamePath,mtInformation,[mbOk],0);
- with writer do
- begin
- fposition1.WriteToFiler(writer);
- fposition2.WriteToFiler(writer);
- if Assigned(fObject1) then
- WriteString(fObject1.GetNamePath)
- else
- WriteString('');
- if Assigned(fObject2) then
- WriteString(fObject2.GetNamePath)
- else
- WriteString('');
- // WriteString(Object2Name);
- end;
- end;
- procedure TGLForce.ReadFromFiler(reader: TReader);
- begin
- // messagedlg('Reading from filer'+GetNamePath,mtInformation,[mbOk],0);
- inherited ReadFromFiler(reader);
- with reader do
- begin
- fposition1.ReadFromFiler(reader);
- fposition2.ReadFromFiler(reader);
- object1Name := ReadString;
- fObject1 := nil;
- object2Name := ReadString;
- fObject2 := nil;
- end;
- // Loaded;
- end;
- procedure TGLForce.SetName(const val: String);
- begin
- inherited SetName(val);
- // if Assigned(vGLBehaviourNameChangeEvent) then
- // vGLBehaviourNameChangeEvent(Self);
- end;
- function TGLForce.CalculateForce(): TAffineVector;
- begin
- //
- end;
- constructor TGLHookesSpring.Create(aOwner: TXCollection);
- begin
- inherited Create(aOwner);
- fNaturalLength := 1;
- fElasticity := 1;
- fDamping := TGLDamping.Create(Self);
- end;
- destructor TGLHookesSpring.Destroy;
- begin
- fDamping.Free;
- inherited Destroy;
- end;
- procedure TGLHookesSpring.WriteToFiler(writer: TWriter);
- begin
- inherited;
- with writer do
- begin
- WriteFloat(fNaturalLength); // :Real;
- WriteFloat(fElasticity); // :Real;
- WriteFloat(fLength); // :Real;
- WriteFloat(fExtension); // :Real;
- fDamping.WriteToFiler(writer);
- end;
- end;
- procedure TGLHookesSpring.ReadFromFiler(reader: TReader);
- begin
- inherited;
- with reader do
- begin
- fNaturalLength := ReadFloat(); // :Real;
- fElasticity := ReadFloat(); // :Real;
- fLength := ReadFloat(); // :Real;
- fExtension := ReadFloat(); // :Real;
- fDamping.ReadFromFiler(reader);
- end;
- end;
- procedure TGLHookesSpring.SetDamping(const val: TGLDamping);
- begin
- fDamping.Assign(val);
- end;
- function TGLHookesSpring.CalculateForce(): TAffineVector;
- var
- rvector, vvector: TAffineVector;
- Inertia1, Inertia2: TGLParticleInertia;
- begin
- if (fObject1 = nil) or (fObject2 = nil) then
- Exit;
- Inertia2 := TGLParticleInertia
- (Object2.Behaviours.GetByClass(TGLParticleInertia));
- Inertia1 := TGLParticleInertia
- (Object1.Behaviours.GetByClass(TGLParticleInertia));
- // rvector:=VectorSubtract({VectorAdd(Object2.Position.asAffineVector,}VectorTransform(Position2.AsAffineVector,Object2.Matrix{)}),
- // {VectorAdd(Object1.Position.asAffineVector,}VectorTransform(Position1.AsAffineVector,Object1.Matrix){)});
- rvector := VectorSubtract(Object2.LocalToAbsolute(Position2.AsAffineVector),
- Object1.LocalToAbsolute(Position1.AsAffineVector));
- (*
- rvector:=VectorSubtract(VectorAdd(Object2.Position.asAffineVector,VectorTransform(Position2.AsAffineVector,Object2.Matrix)),
- VectorAdd(Object1.Position.asAffineVector,VectorTransform(Position1.AsAffineVector,Object1.Matrix)));
- *)
- fLength := VectorLength(rvector);
- NormalizeVector(rvector);
- fExtension := fLength - fNaturalLength;
- // fDamping.Calculate();
- Result := VectorScale(rvector, fElasticity * fExtension / fNaturalLength);
- if Assigned(Inertia2) then
- Inertia2.ApplyForce(Position2.AsAffineVector, VectorNegate(Result));
- if Assigned(Inertia1) then
- Inertia1.ApplyForce(Position1.AsAffineVector, Result);
- // TGLInertia(Object1.Behaviours.GetByClass(TGLInertia)).ApplyForce(Position1.AsAffineVector,Result);
- end;
- class function TGLHookesSpring.FriendlyName: String;
- begin
- Result := 'Hookes Spring';
- end;
- class function TGLHookesSpring.FriendlyDescription: String;
- begin
- Result := 'A spring obeying Hookes Law';
- end;
- class function TGLHookesSpring.UniqueItem: Boolean;
- begin
- Result := false;
- end;
- constructor TGLHookesString.Create(aOwner: TXCollection);
- begin
- inherited Create(aOwner);
- end;
- destructor TGLHookesString.Destroy;
- begin
- inherited Destroy;
- end;
- class function TGLHookesString.FriendlyName: String;
- begin
- Result := 'Hookes String';
- end;
- class function TGLHookesString.FriendlyDescription: String;
- begin
- Result := 'A string (that can go slack) obeying Hookes Law';
- end;
- class function TGLHookesString.UniqueItem: Boolean;
- begin
- Result := false;
- end;
- function TGLHookesString.CalculateForce(): TAffineVector;
- var
- rvector: TAffineVector;
- Inertia1, Inertia2: TGLParticleInertia;
- begin
- if (Object1 = nil) or (Object2 = nil) then
- Exit;
- rvector := VectorSubtract(Object2.LocalToAbsolute(Position2.AsAffineVector),
- Object1.LocalToAbsolute(Position1.AsAffineVector));
- // VectorAdd(Object2.Position.asAffineVector,VectorTransform(Object2.Position2.AsAffineVector,Object2.Matrix)),
- // VectorAdd(Object1.Position.asAffineVector,VectorTransform(Position1.AsAffineVector,Object1.Matrix)));
- fLength := VectorLength(rvector);
- if (fLength < fNaturalLength) then
- Result := NullVector
- else
- begin
- NormalizeVector(rvector);
- fExtension := fLength - fNaturalLength;
- Result := VectorScale(rvector, fElasticity * fExtension / fNaturalLength);
- // TGLInertia(Object2.Behaviours.GetByClass(TGLInertia)).ApplyForce(Position2.AsAffineVector,VectorNegate(Result));
- // TGLInertia(Object1.Behaviours.GetByClass(TGLInertia)).ApplyForce(Position1.AsAffineVector,Result);
- Inertia2 := TGLParticleInertia
- (Object2.Behaviours.GetByClass(TGLParticleInertia));
- Inertia1 := TGLParticleInertia
- (Object1.Behaviours.GetByClass(TGLParticleInertia));
- if Assigned(Inertia2) then
- Inertia2.ApplyForce(Position2.AsAffineVector, VectorNegate(Result));
- if Assigned(Inertia1) then
- Inertia1.ApplyForce(Position1.AsAffineVector, Result);
- end;
- // Result:= inherited CalculateForce();
- // if (fLength < fNaturalLength) then Result:=NullVector;
- end;
- // =================================================================
- initialization
- // =================================================================
- RegisterXCollectionItemClass(TGLHookesSpring);
- RegisterXCollectionItemClass(TGLHookesString);
- end.
|