123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- unit GBE.PlaneExtend;
- (*
- Om:
- GBEPlaneExtend implements a rectangular mesh with oe source of sin wave
- Extended TWaveRec to calc amplitude and pitch
- Added excessive comments to help understanding Gregorys code
- *)
- interface
- uses
- System.SysUtils,
- System.Classes,
- System.Generics.Collections,
- System.Threading,
- System.Math.Vectors,
- System.RTLConsts,
- FMX.Types,
- FMX.Controls3D,
- FMX.Objects3D,
- FMX.Types3D,
- FMX.MaterialSources;
- type
- TWaveRec = record // calculates sin() wave amplitude at a given P (x,y)
- P, // wave origin
- D: TPoint3D;
- // wave params D = Point3D( MaxAmplitude, WaveLenght, WaveSpeed )
- function Wave(aSum, aX, aY, aT: single): single;
- function calcWaveAmplitudeAndPitch(aCap, aX, aY, aT: single;
- var aSumAmplitude, aSumDerivative: single): boolean;
- end;
- TGBEPlaneExtend = class(TPlane)
- private
- fAmplitude, fLongueur, fVitesse: single; // wave 1
- fOrigine: TPoint3D;
- procedure CalcWaves(D: TPoint3D); // D = Point3D(fAmplitude, fLongueur, fVitesse)
- protected
- fTime: single; // Om: movd stuff to protected
- fNbMesh: integer; // number of tiles in the mesh
- fActiveWaves, fShowlines, fUseTasks: boolean;
- fMaterialLignes: TColorMaterialSource;
- fCenter: TPoint3D;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Render; override;
- // Property Data; //om: public
- function Altura(P: TPoint3D): single; // Om: calc wave amplitude on a point
- published
- property ActiveWaves: boolean read fActiveWaves write fActiveWaves;
- property Origine: TPoint3D read fOrigine write fOrigine;
- property Amplitude: single read fAmplitude write fAmplitude;
- property Longueur: single read fLongueur write fLongueur;
- property Vitesse: single read fVitesse write fVitesse;
- property ShowLines: boolean read fShowlines write fShowlines;
- property UseTasks: boolean read fUseTasks write fUseTasks;
- property MaterialLines: TColorMaterialSource read fMaterialLignes
- write fMaterialLignes;
- end;
- procedure Register;
- implementation //--------------------------------------------------------------
- // TWaveRec
- // wave world is x,y . z is the wave height ( amplitude )
- // /y
- // +---------/---------+
- // / ^ ^ / ^ ^ /
- // /---------+---------+----x
- // / ^ / ^ /
- // +---------/---------+
- //
- function TWaveRec.Wave(aSum, aX, aY, aT: single): single;
- // sums. Here aX,aY are in div units ( not m )
- var
- L, Ph: single;
- begin
- L := P.Distance(Point3d(aX, aY, 0)); // L= dist to sin wave origin
- Result := aSum;
- // start w/ previous sum, so we add wave amplitudes of different waves
- // D.x = MaxAmplitude in div ?
- // D.y = WaveLenght in div
- // D.z = WaveSpeed in div/s
- if (D.Y > 0) and (D.x > 0) then
- // ignore if wave length<=0 Om: ..or Amplitude=0 ( which produces no effect )
- begin
- Ph := L / D.Y - D.z * aT; // calc wave phase at the point
- Result := Result + D.x * sin(Ph) * 0.001;
- // sum sin() wave amplitude / 1000 ( result inside +- MaxAmplitude*0.001 )
- end;
- end;
- // here wave world is in x,y z is the wave height ( amplitude )
- function TWaveRec.calcWaveAmplitudeAndPitch(aCap, aX, aY, aT: single;
- var aSumAmplitude, aSumDerivative: single): boolean;
- var
- L, L0, L1, Ph, Ph0, Ph1, aAng, aAmp, aAmp0, aAmp1, aDeriv, DzaT: single;
- aP, P0, P1, DP: TPoint3D;
- begin
- Result := true; // always
- aP := Point3d(aX, aY, 0); // requested coordinate
- L := P.Distance(aP); // L= dist to sin wave origin P
- if (D.Y > 0) and (D.x > 0) then
- // ignore if wave length D.Y <= 0 or Amplitude D.x <=0
- begin
- Result := true;
- DzaT := D.z * aT; // memoise speed*DT (=wave displacement)
- Ph := L / D.Y - DzaT; // calc wave phase at the point P
- aAmp := D.x * sin(Ph) * 0.001;
- // add sin() wave amplitude / 1000 ( result inside +- MaxAmplitude*0.001 )
- // P.z := aAmp; //dont do that !
- // calc directional derivative
- aAng := -aCap * Pi / 180; // cap to radians
- DP := Point3d(sin(aAng), cos(aAng), 0) / 2;
- // semi displacement vector in boat direction dir
- // P0=pt 1/2 div before
- P0 := aP - DP; // move .5 unit in -cap direction
- L0 := P.Distance(P0); // calc amplitude for P0
- Ph0 := L0 / D.Y - DzaT;
- aAmp0 := D.x * sin(Ph0) * 0.001;
- // add sin() wave amplitude / 1000 ( result inside +- MaxAmplitude*0.001 )
- // P1=pt 1/2 div after
- P1 := aP + DP / 2; // move 0.5 unit in cap direction
- L1 := P.Distance(P1); // calc amplitude for P1
- Ph1 := L1 / D.Y - DzaT;
- aAmp1 := D.x * sin(Ph1) * 0.001;
- // derivative calculated from -0.5 to +0.5 div
- aDeriv := (aAmp1 - aAmp0); // directional derivative calculated in P0-P1
- // add amplitude to sum
- aSumAmplitude := aSumAmplitude + aAmp; // accumulate
- aSumDerivative := aSumDerivative + aDeriv;
- // derivative of sum = sum of derivatives
- end;
- end;
- // TGBEPlaneExtend
- procedure TGBEPlaneExtend.CalcWaves(D: TPoint3D);
- // D = Point3D(Amplitude, Longueur, Vitesse)
- var
- M: TMeshData;
- x, Y: integer;
- somme: single;
- front, back: PPoint3D;
- waveRec: TWaveRec;
- begin
- M := self.Data;
- // init waveRec
- waveRec.P := Point3d(SubdivisionsWidth, SubdivisionsHeight, 0) * 0.5 +
- fOrigine * fCenter;
- waveRec.D := D;
- for Y := 0 to SubdivisionsHeight do // 0..30 ( 30 divisions )
- for x := 0 to SubdivisionsWidth do
- begin
- front := M.VertexBuffer.VerticesPtr[x + (Y * (SubdivisionsWidth + 1))];
- back := M.VertexBuffer.VerticesPtr
- [fNbMesh + x + (Y * (SubdivisionsWidth + 1))];
- somme := 0;
- somme := waveRec.Wave(somme, x, Y, fTime);
- somme := somme * 100;
- front^.z := somme;
- back^.z := somme;
- end;
- M.CalcTangentBinormals;
- fTime := fTime + 0.01;
- // adv wave time by 0.01 seg. Should be 0.2s ? ( the animation speed )
- end;
- function TGBEPlaneExtend.Altura(P: TPoint3D): single; // Om:
- var
- M: TMeshData;
- x, Y: integer;
- front, back: PPoint3D;
- begin
- M := self.Data;
- x := Round(P.x);
- Y := Round(P.Y);
- if (x >= 0) and (x < SubdivisionsWidth) and (Y > 0) and
- (Y < SubdivisionsHeight) then
- begin
- front := M.VertexBuffer.VerticesPtr[x + (Y * (SubdivisionsWidth + 1))];
- back := M.VertexBuffer.VerticesPtr
- [fNbMesh + x + (Y * (SubdivisionsWidth + 1))];
- Result := (front^.z + back^.z) / 2; // ??
- end
- else
- Result := 0;
- end;
- constructor TGBEPlaneExtend.Create(AOwner: TComponent);
- begin
- inherited;
- fTime := 0; // wave time
- fAmplitude := 1; // wave params
- fLongueur := 1; // Om: only 1 ?
- fVitesse := 5; //
- self.SubdivisionsHeight := 30; // plane subdivisions
- self.SubdivisionsWidth := 30;
- fOrigine := Point3d(self.SubdivisionsWidth / self.Width,
- self.SubdivisionsHeight / self.Height, 2);
- fNbMesh := (SubdivisionsWidth + 1) * (SubdivisionsHeight + 1);
- // fCenter = SubD / width ( unit div/m )
- fCenter := Point3d(SubdivisionsWidth / self.Width,
- SubdivisionsHeight / self.Height, 0);
- fUseTasks := true; // default= using tasks
- end;
- destructor TGBEPlaneExtend.Destroy;
- begin
- inherited;
- end;
- procedure TGBEPlaneExtend.Render;
- var
- W1: TPoint3D;
- begin
- inherited;
- if fActiveWaves then
- begin
- W1 := Point3d(fAmplitude, fLongueur, fVitesse);
- if fUseTasks then
- begin
- TTask.Create(
- procedure
- begin
- CalcWaves(W1); // recalc mesh
- end).start;
- end
- else
- begin
- CalcWaves(W1);
- end;
- end;
- if ShowLines then
- Context.DrawLines(self.Data.VertexBuffer, self.Data.IndexBuffer,
- TMaterialSource.ValidMaterial(fMaterialLignes), 1);
- end;
- procedure Register;
- begin
- RegisterComponents('GXScene GBE', [TGBEPlaneExtend]);
- end;
- end.
|