| This is from Archives but I don't remember where I founded. So take the code here: 
 
; fxWater Module by Danny van der Ark - dendanny@...
;
; (Heavily) inpired by samples by Reda Borchardt and Rob Cummings.
; use as you like - send me a sample would be cool.
;
; april '04
;
;
; Usage:
;
; 1. Create a water surface using: fxWater_Create( name$, xsize, zsize, dampening#, parent )
;    This function returns the 'type-handle' to the water surface wich you will need later.
;
; 2. Obtain the entity handle (to apply color, texture, alpha, etc) using the function
;	 fxWater_get_entity( typehandle) -> typehandle is the value returned by fxWater_Create()
;
; 3. Then simply call 'fxWater_Update()' every frame during your main loop.
;
;
; 4. To create a splah in the water use the fxWater_Dimple() function. The function needs the
;	 type handle that was returned by 'fxWater_Create', the coordinates of the splash, the
;	 force/strength of the splash and the 'range' or size of the splash.
;
;	 fxWater_Dimple( hand, x,z, force#=1.0, range#=1.0)
;
; 5. Freeing stuff not done yet because I want to alter it to use memory banks in stead of
;	 a large static array to store the vertex data - wich should give a more efficient use
;	 of memory...
;
; You can create as many surfaces of any size as you wish. If you wish surfaces larger than 100x100
; then adjust the fxwater_max_depth/width globals. If you want more than 5 surfaces at the same time
; adjust the fxwater_max accordingly. 
; 
; It is necesary To 'UpdateNormals' every frame to ensure the highlights are re-calculated every
; frame. Without this the ripples are there, but just not visible. This slows things down
; dramatically ofcourse. Any other ideas welcome....
;
; He ho, enjoy!
;
; ooo
; (_) Danny v.d. Ark
Global fxWATER_MAX = 5				;max number of active surfaces/effects at one time
Global fxWATER_NUM = 0				;current number of active water effects.
Global FXWATER_MAX_WIDTH = 100		;max sub-division for water meshes
Global FXWATER_MAX_DEPTH = 100		;max sub-division for water meshes
Global FXWATER_MAX_BANKS = fxWATER_MAX * 2
Global FXWATER_NUM_BANKS = 0
Global DEMO_WATER_WIDTH	 = 40 	;--> Adjust these for different plane sizes / mesh resolution
Global DEMO_WATER_DEPTH  = 40
;reserve memory banks for vertice altitudes
Dim fxWaterBank#(FXWATER_MAX_BANKS, FXWATER_MAX_WIDTH, FXWATER_MAX_DEPTH )
Type fxWaterWave
	Field id
	Field name$
	
	Field active		;if not ripples then fx is not actiave
	
	Field parent		;parent entity (if any)
	Field entity		;water mesh
	Field surface		;water surface
	Field bank1			;pointers to array for mem storage
	Field bank2
	Field width			;width of plane / surface
	Field depth			;depth of plane / surface
	Field dampening#	;water dynamics
End Type
;Demo options
Global OPT_WIREFRAME = 0
Global OPT_REFRSH 	 = 0
Global OPT_BALLFREEZE= 0
Global OPT_CEILING	 = 1
;--------------------------------------------------------------------------------------------------
;Graphics3D 640,480,32,1
Graphics3D 640,480,0,2
; Camera + Light
Global campivot = CreatePivot()
Global camera = CreateCamera(campivot)
PositionEntity camera, 0, 0, -35
PointEntity camera, campivot
light = CreateLight(2)
PositionEntity light,-60,0,100
LightColor light,240,240,210
PointEntity light, campivot
light = CreateLight(2)
PositionEntity light,50,0,-50
LightColor light,150,150,180
PointEntity light, campivot
AmbientLight 40,40,40
;load texture
;tex = LoadTexture ("water.tga",1+64)
tex = create_noise_map()
;create water planes
Global w1 = fxWater_Create( "floor",  DEMO_WATER_WIDTH, DEMO_WATER_DEPTH, 0.025 )
water = fxWater_get_entity( w1 )
PositionEntity water, 0, -10, 0
EntityColor water, 30,50,200
EntityShininess water, 0.1
EntityTexture water,tex
Global w2 = fxWater_Create( "ceiling",  DEMO_WATER_WIDTH, DEMO_WATER_DEPTH, 0.025 )
water = fxWater_get_entity( w2 )
FlipMesh water ; flip it because the camera is underneath it
PositionEntity water, 0, 10, 0
EntityColor water, 250,100,100
EntityColor water, 140,130,20
EntityShininess water, 0.1
EntityTexture water,tex
;force refresh
fxWater_dimple( w1, 1,1, 0.001, 0.001)
fxWater_dimple( w2, 1,1, 0.001, 0.001)
;set random ball direction/speed
Global bx#=  0.2
Global by#= -1.75
Global bz#= -0.25
Global bmaxx# =  DEMO_WATER_WIDTH * 0.5	;half the width of the water plane
Global bmaxy# = 10.0
Global bmaxz# =  DEMO_WATER_DEPTH * 0.5	;half the depth of the water plane
;create ball
ball = CreateSphere(6)
EntityColor ball, 0,0,0
EntityShininess ball, 1.0
EntityTexture ball, tex
SeedRnd MilliSecs()
; Main Loop
tstart = MilliSecs() + 1000
frame = 0
Global lastx# = 0
Global lasty# = 0
Global lastz# = 0
tim = CreateTimer(50)
l$ = "WavyWaterFx by Danny van der Ark"
While Not KeyHit(1)
	;update bouncing ball
	update_ball( ball )
	
	;update fxWater
	fxWater_update()
	
	;render
    UpdateWorld
    RenderWorld
	;debug
	Color 000,000,000
	Text 2,1, l$
	Color 255,255,255
	Text 2,0, l$
	Color 100,100,100
	Text 2,12, "based on samples from Reda Borchardt And Rob Cummings."
	Color 20,140,255
	Text 2,454, "[ESC] to quit - [D] for fast but dirty refresh(" + OPT_REFRESH + ") - [W] To toggle WireFrame (" + OPT_WIREFRAME + ")"
	Text 2,466, "[P] To pause  - [B] to pause/reset ball - [C] to toggle ceiling"
	Color 250,250,220
	Text 10,220,"FPS  " + fps
	Text 10,232,"TRIS " + TrisRendered()
	;orbit camera
	;TurnEntity campivot, 0, 0.25, 0
	;check fps
	frame = frame + 1
	If MilliSecs() >= tstart Then
		fps = frame
		frame = 0
		tstart = MilliSecs() + 1000
	EndIf
	;toggle ceiling [C]
	If KeyHit(46) Then
		OPT_CEILING = 1 - OPT_CEILING
		If OPT_CEILING Then
			water = fxWater_Get_Entity(w2)
			ShowEntity water
		Else
			water = fxWater_Get_Entity(w2)
			HideEntity water
		EndIf
	EndIf
	
	;pause all [P]
	If KeyHit(25) Then
		FlushKeys
		While Not KeyHit(25) Wend
	EndIf
	;pause ball [B]
	If KeyHit(48) Then
		OPT_BALLFREEZE = 1 - OPT_BALLFREEZE
		If OPT_BALLFREEZE Then
			PositionEntity ball, 0,0,0
			bx# = 0
			by# = 0
			bz# = 0
		Else
			bx#=Rnd#(-1,1)
			by#=Rnd#(-2,2)
			bz#=Rnd#(-1,1)
		EndIf
	EndIf
	;wireframe [W]
	If KeyHit(17) Then
		OPT_WIREFRAME = 1 - OPT_WIREFRAME
		WireFrame OPT_WIREFRAME
	EndIf
	
	;Dirty refresh [D]
	If KeyHit(32) Then
		OPT_REFRESH = 1 - OPT_REFRESH
	EndIf	
	;check refresh mode
	If OPT_REFRESH Then
		;fast and dirty (pot noodle style)
	    Flip False
	Else
		;slow but clean
		Flip True
		WaitTimer(tim)
	EndIf
	If MouseHit(1) Then
		x = Rnd(1,DEMO_WATER_WIDTH)
		z = Rnd(1,DEMO_WATER_DEPTH)
		fxWater_Dimple( w1, x, z, 1, 5)
	EndIf
Wend
End
;--------------------------------------------------------------------------------------------------
Function update_ball( ent )
	;move the ball
	TranslateEntity ent, bx,by,bz
	DoDimple = False
	
	;check left/right walls
	If EntityX#(ent) >  bmaxx-2 Then bx# = bx# * -1
	If EntityX#(ent) < -bmaxx+2 Then bx# = bx# * -1
	;check ceiling bounce
	If EntityY#(ent) >  bmaxy-2 Then
		;reverse vertical direction
		by# = by# * -1.0
		;create dimple
		fxWater_Dimple(w2, EntityX(ent)+bmaxx,EntityZ(ent)+bmaxz, -1.0, 5.0)
		;slightly alter direction
		bx# = bx# + Rnd#(-0.25, 0.25)
		bz# = bz# + Rnd#(-0.25, 0.25)
	EndIf
	;check floor bounce
	If EntityY#(ent) < -bmaxy+2 Then
		;reverse vertical direction
		by# = by# * -1.0
		;create dimple
		fxWater_Dimple(w1, EntityX(ent)+bmaxx,EntityZ(ent)+bmaxz, 1.0, 5.0)
		;slightly alter direction
		bx# = bx# + Rnd#(-0.25, 0.25)
		bz# = bz# + Rnd#(-0.25, 0.25)
	EndIf
	;check front/back walls
	If EntityZ#(ent) >  bmaxz-2 Then bz# = bz# * -1
	If EntityZ#(ent) < -bmaxz+2 Then bz# = bz# * -1
End Function
;--------------------------------------------------------------------------------------------------
Function fxWater_Create( name$="", width=1, depth=1, damp#=0.01, parent=0 )
	;create new Wavy water effect plane
	w.fxWaterWave = New fxWaterWave
	w\id		= 1
	w\name$		= name$
	
	w\active	= True
	
	;create rectangular grid mesh
	w\width		= width
	w\depth		= depth
	w\dampening#= 1 - damp#
	
	w\parent	= parent
	w\entity	= create_mesh_plane( w\width, w\depth, False, parent )
	w\surface	= GetSurface(w\entity,1)
	
	;store handle for quick retrieval during collision
	NameEntity w\entity, Handle(w)
	
	;reserve memory banks to hold vertex energy
	w\bank1		= fxWater_Create_Buffer()
	w\bank2		= fxWater_Create_Buffer()
	
	;return mesh handle
	Return Handle(w)
	
End Function
;--------------------------------------------------------------------------------------------------
Function fxWater_update()
	For w.fxWaterWave = Each fxWaterWave
		;if the surface is perfectly flat then this value remains 0
		dyna# = 0
		
		;process water
	    For x = 1 To w\width-1
	        For z = 1 To w\depth-1
				fxWaterBank#(w\bank2,x,z) = (fxWaterBank#(w\bank1,x-1,z) + fxWaterBank#(w\bank1,x+1,z) + fxWaterBank#(w\bank1,x,z+1) + fxWaterBank#(w\bank1,x,z-1)) / 2.1-fxWaterBank#(w\bank2,x,z) 
				fxWaterBank#(w\bank2,x,z) = fxWaterBank#(w\bank2,x,z) * w\dampening#
				dyna# = dyna# + fxWaterBank#(w\bank2,x,z)
	        Next
	    Next
		;Only deform patch if necesary
		If dyna# <> 0 Then
		    ;PatchTransform
			k=0
			For i = 0 To w\depth
		        For j = 0 To w\width
					VertexCoords(w\surface,k,VertexX(w\surface,k),fxWaterBank#(w\bank2,j,i),VertexZ(w\surface,k))
		            k=k+1
		        Next
		    Next
		EndIf
		;should be optional - depending on type of texture (slows down seriously!)
		UpdateNormals w\entity
		
	    ;SwapWaterBuffer
		tmp = w\bank1
		w\bank1 = w\bank2
		w\bank2 = tmp
	Next
End Function
;--------------------------------------------------------------------------------------------------
Function fxWater_Dimple( hand, x,z, force#=1.0, range#=1.0)
	
	w.fxWaterWave = Object.fxWaterWave(hand)
	For xg = x - range# * 0.5 To x+range# * 0.5
		For zg = z - range# * 0.5 To z+range# * 0.5
			If xg> 0 And xg < w\width And zg>0 And zg<w\depth Then
				fxWaterBank#(w\bank2, xg,zg) = force#
			EndIf
		Next
	Next
End Function
;--------------------------------------------------------------------------------------------------
Function fxWater_get_surface( hand )
	w.fxWaterWave = Object.fxWaterWave( hand )
	Return w\surface
End Function
;--------------------------------------------------------------------------------------------------
Function fxWater_get_entity( hand )
	w.fxWaterWave = Object.fxWaterWave( hand )
	Return w\entity
End Function
;--------------------------------------------------------------------------------------------------
Function fxWater_Create_Buffer() ; xsize=1, zsize=1 )
	If FXWATER_NUM_BANKS >= FXWATER_MAX_BANKS Then 
		RuntimeError "[fxWater::Create_buffer] Max amount of fxWater memory banks reached!"
	Else
		;create a new memory bank and resize it to fit
		FXWATER_NUM_BANKS = FXWATER_NUM_BANKS + 1
		;NOTE: convert array into memory bank
	EndIf
	Return FXWATER_NUM_BANKS
	
End Function
;--------------------------------------------------------------------------------------------------
Function fxWater_Free_Buffers( )
;| Frees all buffers. Call as a part of when scene/level is removed from memory.
	;NOTE: resize memory banks to 0 (once implemented).
	Return 0
	
End Function
;--------------------------------------------------------------------------------------------------
;Creates a flat grid mesh
Function create_mesh_plane(width=1,depth=1,doublesided=False,parent=0)
	tot = width + (depth*width)
	mix#= (width+depth) * 0.5
	
	mesh=CreateMesh( parent )
	surf=CreateSurface( mesh )
	
	stx#=-.5
	sty#=stx
	stp#=Float(1)/Float(mix#)
	y#=sty#
	
	For a=0 To depth
		x#=stx
		v#=a/Float(depth)
		
		For b=0 To width
			u#=b/Float(width)
			AddVertex(surf,x,0,y,u,v)
			x=x+stp
		Next
		y=y+stp
	Next
	
	For a=0 To depth-1
		For b=0 To width-1
			v0=a*(width+1)+b:v1=v0+1
			v2=(a+1)*(width+1)+b+1:v3=v2-1
			AddTriangle( surf,v0,v2,v1 )
			AddTriangle( surf,v0,v3,v2 )
		Next
	Next
	
	UpdateNormals mesh
	If doublesided=True Then EntityFX mesh,16
	
	FitMesh mesh, -width*0.5, 0, -depth*0.5, width, 1, depth
	
	Return mesh
	
End Function
;--------------------------------------------------------------------------------------------------
Function create_noise_map()
; creates a noise map to be used as a generic reflection map
	sq = 128
	tex = CreateTexture(sq,sq,65,1)
	tbuf = TextureBuffer(tex)
	SetBuffer(tbuf)
	
	For x = 0 To sq-1
		For y = 0 To sq-1
			r = Rnd(100,120)
			g = Rnd(100,130)
			b = Rnd(190,240)
			Color r,g,b
			Rect x,y,1,1
		Next
	Next	
	
	SetBuffer(BackBuffer())
	
	Return tex
End Function
 
 |