123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- //
- // The graphics engine GLXEngine. The unit of GLScene for Delphi
- //
- unit GLS.PhysFields;
- interface
- uses
- System.Classes,
- Stage.VectorGeometry,
- GLS.XCollection,
- GLS.Coordinates,
- GLS.Scene,
- GLS.Behaviours,
- (* GLS.RigidBodyInertia *)
- GLS.PhysInertias,
- GLS.PhysManager;
- type
- TGLUniformGravityEmitter = class(TGLBaseForceFieldEmitter)
- private
- fGravity: TGLCoordinates;
- protected
- procedure SetGravity(const val: TGLCoordinates);
- public
- constructor Create(aOwner: TXCollection); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- procedure WriteToFiler(writer: TWriter); override;
- procedure ReadFromFiler(reader: TReader); override;
- class function FriendlyName: String; override;
- class function FriendlyDescription: String; override;
- class function UniqueItem: Boolean; override;
- function CalculateForceField(Body: TGLBaseSceneObject)
- : TAffineVector; override;
- published
- property Gravity: TGLCoordinates read fGravity write SetGravity;
- end;
- TGLRadialGravityEmitter = class(TGLBaseForceFieldEmitter)
- private
- fMass: Real;
- fMassOverG: Real;
- public
- constructor Create(aOwner: TXCollection); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- procedure WriteToFiler(writer: TWriter); override;
- procedure ReadFromFiler(reader: TReader); override;
- class function FriendlyName: String; override;
- class function FriendlyDescription: String; override;
- class function UniqueItem: Boolean; override;
- function CalculateForceField(Body: TGLBaseSceneObject)
- : TAffineVector; override;
- published
- property Mass: Real read fMass write fMass;
- end;
- TGLDampingFieldEmitter = class(TGLBaseForceFieldEmitter)
- private
- fDamping: TGLDamping;
- protected
- procedure SetDamping(const val: TGLDamping);
- public
- constructor Create(aOwner: TXCollection); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- procedure WriteToFiler(writer: TWriter); override;
- procedure ReadFromFiler(reader: TReader); override;
- class function FriendlyName: String; override;
- class function FriendlyDescription: String; override;
- class function UniqueItem: Boolean; override;
- function CalculateForceField(Body: TGLBaseSceneObject)
- : TAffineVector; override;
- published
- property Damping: TGLDamping read fDamping write SetDamping;
- end;
- const
- GravitationalConstant = 6.6726E-11;
- // ==================================================================
- implementation
- // ==================================================================
- // -------------------------------------
- // ---- TGLUniformGravityEmitter
- // -------------------------------------
- constructor TGLUniformGravityEmitter.Create(aOwner: TXCollection);
- begin
- inherited Create(aOwner);
- fGravity := TGLCoordinates.CreateInitialized(Self, nullHmgVector, csVector);
- end;
- destructor TGLUniformGravityEmitter.Destroy;
- begin
- fGravity.Free;
- inherited Destroy;
- end;
- procedure TGLUniformGravityEmitter.Assign(Source: TPersistent);
- begin
- if Source.ClassType = Self.ClassType then
- begin
- fGravity := TGLUniformGravityEmitter(Source).fGravity;
- end;
- end;
- class function TGLUniformGravityEmitter.FriendlyName: String;
- begin
- Result := 'Uniform Gravity';
- end;
- class function TGLUniformGravityEmitter.FriendlyDescription: String;
- begin
- Result := 'Uniform Gravity, appropriate near surface of planet';
- end;
- class function TGLUniformGravityEmitter.UniqueItem: Boolean;
- begin
- Result := false;
- end;
- procedure TGLUniformGravityEmitter.WriteToFiler(writer: TWriter);
- begin
- inherited;
- with writer do
- begin
- fGravity.WriteToFiler(writer);
- end;
- end;
- procedure TGLUniformGravityEmitter.ReadFromFiler(reader: TReader);
- begin
- inherited;
- with reader do
- begin
- fGravity.ReadFromFiler(reader);
- end;
- end;
- procedure TGLUniformGravityEmitter.SetGravity(const val: TGLCoordinates);
- begin
- fGravity.Assign(val);
- end;
- // CalculateForceField (TODO: ParticleInertia -> BaseInertia, add BaseInertia.ApplyAcceleration)
- function TGLUniformGravityEmitter.CalculateForceField(Body: TGLBaseSceneObject)
- : TAffineVector;
- var
- inertia1: TGLParticleInertia;
- begin
- inertia1 := TGLParticleInertia
- (Body.Behaviours.GetByClass(TGLParticleInertia));
- if Assigned(inertia1) then
- begin
- Result := VectorScale(fGravity.AsAffineVector, inertia1.Mass);
- inertia1.ApplyForce(Result);
- end
- else
- Result := nullVector;
- end;
- // ------------------------------------------------------------------------------
- // ------------------------------Radial Gravity Emitter -------------------------
- // ------------------------------------------------------------------------------
- constructor TGLRadialGravityEmitter.Create(aOwner: TXCollection);
- begin
- inherited Create(aOwner);
- end;
- destructor TGLRadialGravityEmitter.Destroy;
- begin
- inherited Destroy;
- end;
- procedure TGLRadialGravityEmitter.Assign(Source: TPersistent);
- begin
- if Source.ClassType = Self.ClassType then
- begin
- fMass := TGLRadialGravityEmitter(Source).fMass;
- end;
- end;
- class function TGLRadialGravityEmitter.FriendlyName: String;
- begin
- Result := 'Radial Gravity';
- end;
- class function TGLRadialGravityEmitter.FriendlyDescription: String;
- begin
- Result := 'Radial Gravity, can be applied anywhere (use for planets)';
- end;
- class function TGLRadialGravityEmitter.UniqueItem: Boolean;
- begin
- Result := false;
- end;
- procedure TGLRadialGravityEmitter.WriteToFiler(writer: TWriter);
- begin
- inherited;
- with writer do
- begin
- WriteFloat(fMass);
- end;
- end;
- procedure TGLRadialGravityEmitter.ReadFromFiler(reader: TReader);
- begin
- inherited;
- with reader do
- begin
- fMass := ReadFloat();;
- end;
- end;
- // CalculateForceField (TODO: ParticleInertia -> BaseInertia if possible)
- function TGLRadialGravityEmitter.CalculateForceField(Body: TGLBaseSceneObject)
- : TAffineVector;
- var
- inertia1: TGLParticleInertia;
- R: TAffineVector;
- L: Real;
- begin
- inertia1 := TGLParticleInertia
- (Body.Behaviours.GetByClass(TGLParticleInertia));
- if Assigned(inertia1) then
- begin
- R := VectorSubtract(Body.Position.AsAffineVector,
- Self.OwnerBaseSceneObject.Position.AsAffineVector);
- L := VectorLength(R);
- Result := VectorScale(R, -GravitationalConstant * (fMass / L));
- inertia1.ApplyForce(Result);
- end
- else
- Result := nullVector;
- end;
- // -----------------------------------------------------------------------------
- // ------------------------------Damping Field Emitter -------------------------
- // -----------------------------------------------------------------------------
- constructor TGLDampingFieldEmitter.Create(aOwner: TXCollection);
- begin
- inherited Create(aOwner);
- fDamping := TGLDamping.Create(Self);
- end;
- destructor TGLDampingFieldEmitter.Destroy;
- begin
- fDamping.Free;
- inherited Destroy;
- end;
- procedure TGLDampingFieldEmitter.Assign(Source: TPersistent);
- begin
- if Source.ClassType = Self.ClassType then
- begin
- fDamping := TGLDampingFieldEmitter(Source).fDamping;
- end;
- end;
- class function TGLDampingFieldEmitter.FriendlyName: String;
- begin
- Result := 'Damping Field';
- end;
- class function TGLDampingFieldEmitter.FriendlyDescription: String;
- begin
- Result := 'Damping Field, to approximate air/fluid resistance';
- end;
- class function TGLDampingFieldEmitter.UniqueItem: Boolean;
- begin
- Result := false;
- end;
- procedure TGLDampingFieldEmitter.WriteToFiler(writer: TWriter);
- begin
- inherited;
- with writer do
- begin
- fDamping.WriteToFiler(writer);
- end;
- end;
- procedure TGLDampingFieldEmitter.ReadFromFiler(reader: TReader);
- begin
- inherited;
- with reader do
- begin
- fDamping.ReadFromFiler(reader);
- end;
- end;
- procedure TGLDampingFieldEmitter.SetDamping(const val: TGLDamping);
- begin
- fDamping.Assign(val);
- end;
- // CalculateForceField (TODO: ParticleInertia -> BaseInertia, BaseInertia.ApplyDamping?)
- function TGLDampingFieldEmitter.CalculateForceField(Body: TGLBaseSceneObject)
- : TAffineVector;
- var
- inertia1: TGLParticleInertia;
- // velocity:TAffineVector;
- // v:Real;
- begin
- inertia1 := TGLParticleInertia
- (Body.Behaviours.GetByClass(TGLParticleInertia));
- if Assigned(inertia1) then
- inertia1.ApplyDamping(Damping);
- { Inertia1:=TGLParticleInertia(Body.Behaviours.GetByClass(TGLParticleInertia));
- if Assigned(inertia1) then
- begin
- velocity:=VectorScale(inertia1.LinearMomentum, 1/Inertia1.Mass); // v = p/m
- //apply force in opposite direction to velocity
- v:=VectorLength(velocity);
- // F = -Normalised(V)*( Constant + (Linear)*(V) + (Quadtratic)*(V)*(V) )
- Result:=VectorScale(VectorNormalize(velocity),-(fDamping.Constant+fDamping.Linear*v+fDamping.Quadratic*v*v));
- inertia1.ApplyForce(Result);
- end
- else
- Result:=nullvector;
- }
- end;
- // -------------------------------------------------------------------------
- initialization
- // -------------------------------------------------------------------------
- RegisterXCollectionItemClass(TGLUniformGravityEmitter);
- RegisterXCollectionItemClass(TGLRadialGravityEmitter);
- RegisterXCollectionItemClass(TGLDampingFieldEmitter);
- end.
|