# Prerequisites!

# The wave function

The wave function we'll use in this article is:

f(x,y) = A*sin(1/L*r-v*t)

where:

- (x,y) = observation point
- A = amplitude
- L = wave length
- r = distance between wave center and observation point
- v = velocity of wave propagation
- t = time

In Delphi it simply becomes:

`function`

f(x,y : Double) : Double;
`begin`

f := Amplitude*Sin(1/Length*Sqrt(Sqr(x-PosX)+Sqr(y-PosY))-Speed*t);
`end`

;

*Note: It should be noted that this function simply gives us the state of equilibrium. We're completely ignoring starting scenarios and the fact that waves die out over time and distance.*

The screen shot below shows one wave:

#

Two waves interfering with each other:

And 4 waves while we're at it:

# Generating the mesh

In order to generate the mesh, we borrow the code from my previous article, and modify it slightly to give it a time parameter:

`procedure`

TForm1.GenerateWave(t : Double);
`function`

f(x,y : Double) : Double;
`var`

i : Integer;
`begin`

Result := 0;
`for`

i:=0 `to`

3 `do`

`with`

Wave[i] `do`

`if`

Enabled `then`

Result := Result+Amplitude*Sin(1/Length*Sqrt(Sqr(x-PosX)+Sqr(y-PosY))-Speed*t);
`end`

;
`const`

MaxX = 30;
MaxZ = 30;
`var`

u, v : Double;
px, py, pz : `array`

[0..3] `of`

Double;
d : Double;
NP, NI : Integer;
BMP : TBitmap;
k : Integer;
`begin`

d := 0.5;
NP := 0;
NI := 0;
Mesh1.Data.VertexBuffer.Length := Round(2*MaxX*2*MaxZ/d/d)*4;
Mesh1.Data.IndexBuffer.Length := Round(2*MaxX*2*MaxZ/d/d)*6;
BMP := TBitmap.Create(1,360);
`for`

k := 0 `to`

359 `do`

BMP.Pixels[0,k] := CorrectColor(HSLtoRGB(k/360,0.75,0.5));
u := -MaxX;
`while`

u < MaxX `do`

`begin`

v := -MaxZ;
`while`

v < MaxZ `do`

`begin`

px[0] := u;
pz[0] := v;
py[0] := f(px[0],pz[0]);
px[1] := u+d;
pz[1] := v;
py[1] := f(px[1],pz[1]);
px[2] := u+d;
pz[2] := v+d;
py[2] := f(px[2],pz[2]);
px[3] := u;
pz[3] := v+d;
py[3] := f(px[3],pz[3]);
`with`

Mesh1.Data `do`

`begin`

`with`

VertexBuffer `do`

`begin`

Vertices[NP+0] := Point3D(px[0],py[0],pz[0]);
Vertices[NP+1] := Point3D(px[1],py[1],pz[1]);
Vertices[NP+2] := Point3D(px[2],py[2],pz[2]);
Vertices[NP+3] := Point3D(px[3],py[3],pz[3]);
`end`

;
`with`

VertexBuffer `do`

`begin`

TexCoord0[NP+0] := PointF(0,(py[0]+35)/45);
TexCoord0[NP+1] := PointF(0,(py[1]+35)/45);
TexCoord0[NP+2] := PointF(0,(py[2]+35)/45);
TexCoord0[NP+3] := PointF(0,(py[3]+35)/45);
`end`

;
IndexBuffer[NI+0] := NP+1;
IndexBuffer[NI+1] := NP+2;
IndexBuffer[NI+2] := NP+3;
IndexBuffer[NI+3] := NP+3;
IndexBuffer[NI+4] := NP+0;
IndexBuffer[NI+5] := NP+1;
`end`

;
NP := NP+4;
NI := NI+6;
v := v+d;
`end`

;
u := u+d;
`end`

;
Mesh1.Material.Texture := BMP;
`end`

;

# Animating the mesh

The above code generates a "snap shot" of the wave interaction between 4 waves at any time *t*.

Animating the wave is simply a matter of using a timer to increment time and re-generating the mesh over and over again:

`procedure`

TForm1.Timer1Timer(Sender: TObject);
`begin`

GenerateWave(t);
t := t+0.1;
`end`

;

The waves are represented by this record:

`type`

TWave = `record`

Enabled : Boolean;
Amplitude : Double;
Length : Double;
PosX : Double;
PosY : Double;
Speed : Double;
`end`

;

In the demo project that accompanies this article, I have declared 4 starting waves like so:

`var`

Wave : `array`

[0..3] `of`

TWave = ((Enabled: False; Amplitude: 1; Length: 1; PosX: -20; PosY: -20; Speed: 1),
(Enabled: False; Amplitude: 1; Length: 1; PosX: +20; PosY: -20; Speed: 1),
(Enabled: False; Amplitude: 1; Length: 1; PosX: +20; PosY: +20; Speed: 1),
(Enabled: False; Amplitude: 1; Length: 1; PosX: -20; PosY: +20; Speed: 1));

Note that all 4 waves have the same properties, except that their origins are spread across the coordinate system. Specifically they're located in (-20,-20), (+20,-20), (+20,+20) and (-20,+20).

# Demo application

# Contact

Please feel free to email me with feedback to aohlsson at embarcadero dot com.

Connect with Us