123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- //
- // The graphics engine GXScene
- //
- unit GXS.PhysForces;
- interface
- uses
- System.Classes,
- Stage.VectorTypes,
- GXS.XCollection,
- Stage.VectorGeometry,
- GXS.Coordinates,
- Stage.Strings,
-
- GXS.Scene,
- GXS.Behaviours;
- type
- TgxForce = class;
- TgxForceType = (ftHookes, ftGravitation, ftCustom);
- TOnCustomForce = procedure() of object;
- TgxForce = class(TXCollectionItem)
- private
- fObject1: TgxBaseSceneObject;
- fObject2: TgxBaseSceneObject;
- fposition1: TgxCoordinates;
- fposition2: TgxCoordinates;
- object1Name: String;
- object2Name: String;
- // fOnCustomForce: TOnCustomForce;
- protected
- procedure Loaded; override;
- procedure SetName(const val: String); override;
- (* Returns the TgxBaseSceneObject on which the behaviour should be applied.
- Does NOT check for nil owners *)
- // function OwnerBaseSceneObject : TgxBaseSceneObject;
- 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: TgxBaseSceneObject);
- procedure SetObject2(const val: TgxBaseSceneObject);
- procedure SetPosition1(const val: TgxCoordinates);
- procedure SetPosition2(const val: TgxCoordinates);
- function CalculateForce(): TAffineVector; virtual;
- published
- property Object1: TgxBaseSceneObject read fObject1 write SetObject1;
- property Object2: TgxBaseSceneObject read fObject2 write SetObject2;
- property Position1: TgxCoordinates read fposition1 write SetPosition1;
- property Position2: TgxCoordinates read fposition2 write SetPosition2;
- // property OnCustomForce:TOnCustomForce read fOnCustomForce write fOnCustomForce;
- end;
- TgxHookesSpring = class(TgxForce)
- private
- fNaturalLength: Real;
- fElasticity: Real;
- fLength: Real;
- fExtension: Real;
- fDamping: TgxDamping;
- 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: TgxDamping);
- function CalculateForce(): TAffineVector; override;
- published
- property NaturalLength: Real read fNaturalLength write fNaturalLength;
- property Elasticity: Real read fElasticity write fElasticity;
- property Damping: TgxDamping read fDamping write SetDamping;
- // property Name;
- end;
- TgxHookesString = class(TgxHookesSpring)
- 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
- GXS.PhysInertias,
- GXS.PhysManager;
- constructor TgxForce.Create(aOwner: TXCollection);
- begin
- inherited; // Create(aOwner)
- fposition1 := TgxCoordinates.CreateInitialized(Self, NullHmgVector, csVector);
- fposition2 := TgxCoordinates.CreateInitialized(Self, NullHmgVector, csVector);
- // fObject1:=TgxBaseSceneObject.Create(Self);
- // fObject2:=TgxBaseSceneObject.Create(Self);
- end;
- destructor TgxForce.Destroy;
- begin
- fposition1.Free();
- fposition2.Free();
- // SetObject1(nil);
- // SetObject2(nil);
- // fObject1.Free();
- // fObject2.Free();
- inherited Destroy;
- end;
- procedure TgxForce.Assign(Source: TPersistent);
- begin
- // inherited Assign(Source);
- fposition1.Assign(TgxForce(Source).fposition1);
- fposition2.Assign(TgxForce(Source).fposition2);
- Object1 := TgxForce(Source).Object1;
- Object2 := TgxForce(Source).Object2;
- inherited Assign(Source);
- end;
- procedure TgxForce.SetObject1(const val: TgxBaseSceneObject);
- begin
- if val.Behaviours.IndexOfClass(TgxBaseInertia) >=0 then
- fObject1 := val
- else
- Write('Object1 does not have an inertia behaviour');
- end;
- procedure TgxForce.SetObject2(const val: TgxBaseSceneObject);
- begin
- if val.Behaviours.IndexOfClass(TgxBaseInertia) >=0 then
- fObject2 := val
- else
- Write('Object2 does not have an inertia behaviour');
- end;
- procedure TgxForce.SetPosition1(const val: TgxCoordinates);
- begin
- fposition1.Assign(val); // DB101
- end;
- procedure TgxForce.SetPosition2(const val: TgxCoordinates);
- begin
- fposition2.Assign(val);
- end;
- procedure TgxForce.Loaded;
- var
- PhysMan: TgxPhysManager;
- begin
- inherited Loaded;
- // not nice at all!!!
- // assumes owner is TgxForces belonging to TGLPhysicsManager
- PhysMan := TgxPhysManager(Self.Owner.Owner);
- if (object1Name <> '') then
- begin
- // PhysMan:=TGLPhysicsManager(Self.Owner.Owner);
- fObject1 := PhysMan.FindObjectByName(object1Name);
- // fObject1:=TgxBaseSceneObject(FindComponent(Object1Name));
- // Object1Name:='';
- end;
- if object2Name <> '' then
- begin
- fObject2 := PhysMan.FindObjectByName(object2Name);
- // Object2Name:='';
- end;
- end;
- class function TgxForce.FriendlyName: String;
- begin
- Result := 'Force';
- end;
- class function TgxForce.FriendlyDescription: String;
- begin
- Result := 'Physics Force';
- end;
- class function TgxForce.UniqueItem: Boolean;
- begin
- Result := false;
- end;
- procedure TgxForce.WriteToFiler(writer: TWriter);
- begin
- inherited WriteToFiler(writer);
- // Write('Writing to filer'+GetNamePath);
- 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 TgxForce.ReadFromFiler(reader: TReader);
- begin
- // Read('Reading from filer'+GetNamePath);
- 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 TgxForce.SetName(const val: String);
- begin
- inherited SetName(val);
- (*
- if Assigned(vGLBehaviourNameChangeEvent)
- then
- vGLBehaviourNameChangeEvent(Self);
- *)
- end;
- function TgxForce.CalculateForce(): TAffineVector;
- begin
- //
- end;
- constructor TgxHookesSpring.Create(aOwner: TXCollection);
- begin
- inherited Create(aOwner);
- fNaturalLength := 1;
- fElasticity := 1;
- fDamping := TgxDamping.Create(Self);
- end;
- destructor TgxHookesSpring.Destroy;
- begin
- fDamping.Free;
- inherited Destroy;
- end;
- procedure TgxHookesSpring.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 TgxHookesSpring.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 TgxHookesSpring.SetDamping(const val: TgxDamping);
- begin
- fDamping.Assign(val);
- end;
- function TgxHookesSpring.CalculateForce(): TAffineVector;
- var
- rvector, vvector: TAffineVector;
- Inertia1, Inertia2: TgxParticleInertia;
- begin
- if (fObject1 = nil) or (fObject2 = nil) then
- Exit;
- Inertia2 := TgxParticleInertia
- (Object2.Behaviours.GetByClass(TgxParticleInertia));
- Inertia1 := TgxParticleInertia
- (Object1.Behaviours.GetByClass(TgxParticleInertia));
- // 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 TgxHookesSpring.FriendlyName: String;
- begin
- Result := 'Hookes Spring';
- end;
- class function TgxHookesSpring.FriendlyDescription: String;
- begin
- Result := 'A spring obeying Hookes Law';
- end;
- class function TgxHookesSpring.UniqueItem: Boolean;
- begin
- Result := false;
- end;
- constructor TgxHookesString.Create(aOwner: TXCollection);
- begin
- inherited Create(aOwner);
- end;
- destructor TgxHookesString.Destroy;
- begin
- inherited Destroy;
- end;
- class function TgxHookesString.FriendlyName: String;
- begin
- Result := 'Hookes String';
- end;
- class function TgxHookesString.FriendlyDescription: String;
- begin
- Result := 'A string (that can go slack) obeying Hookes Law';
- end;
- class function TgxHookesString.UniqueItem: Boolean;
- begin
- Result := false;
- end;
- function TgxHookesString.CalculateForce(): TAffineVector;
- var
- rvector: TAffineVector;
- Inertia1, Inertia2: TgxParticleInertia;
- 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 := TgxParticleInertia
- (Object2.Behaviours.GetByClass(TgxParticleInertia));
- Inertia1 := TgxParticleInertia
- (Object1.Behaviours.GetByClass(TgxParticleInertia));
- 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(TgxHookesSpring);
- RegisterXCollectionItemClass(TgxHookesString);
- end.
|