Posted: 26th Sep 2003 2:40
Just a simple Water Wave Effect
It generates waves on bitmap while you moving mouse and pressing left button.
The code is"ver unoptimised" so it rather run slowly but still it someone may find it useful. Experiment with some variables and remember to load rather small bitmaps, I used 320x240 becouse larger couse it run very very slow.

+ Code Snippet
remstart
   Water Wave Effect
   by Mariusz Skowronski (2003)
remend

rem global vars
rem bitmap size and color depth
global g_bmpWidth as integer
global g_bmpHeight as integer
global g_bmpBpp as integer
global g_bytesPerPixel as integer

rem memblock pointers (for faster access)
global g_srcMemPtr as dword
global g_dstMemPtr as dword

rem screen dimensions
global g_scrWidth as integer
global g_scrHeight as integer

rem height array swap index (current and new)
global g_ch as integer
global g_nh as integer


rem properties
rem wave amplitude
global g_waveForce as integer
rem drop size
global g_dropRadius as integer
rem damping value (the smaller value the faster waves disappear) 1 - 100
global g_waveDamp as integer


rem init vars
g_scrWidth = 640
g_scrHeight = 480

g_waveForce = 300
g_dropRadius = 8
g_waveDamp = 20 : rem DON'T USE ZERO

rem begin
set display mode g_scrWidth, g_scrHeight, 16
sync rate 0: sync on

rem load bitmap (remember the smaller bitmap the faster it runs)
load bitmap "example1.jpg", 1
g_bmpWidth = bitmap width(1)
g_bmpHeight = bitmap height(1)
g_bmpBpp = bitmap depth(1)
g_bytesPerPixel = g_bmpBpp/8


rem create 2 bitmap memblocks
make memblock from bitmap 1, 1
make memblock from bitmap 2, 1

rem get memblock addresses
g_srcMemPtr = get memblock ptr(2)
g_dstMemPtr = get memblock ptr(1)

rem dont need this bitmap anymore
delete bitmap 1

rem allocate 2 height maps
dim g_heightMap(1, g_bmpWidth-1, g_bmpHeight-1) as integer
rem clear height maps
ClearHeights()

rem set current height map to 0
g_ch = 0: g_nh = 1

rem main loop
set current bitmap 0
do
   rem update heights
   UpdateHeights()
   rem update bitmap
   UpdateBitmap()
   rem uncomment following lie and rem this above to see it in greyscale
   rem DrawHeights()

   rem create bitmap form memblock
   make bitmap from memblock 0, 1

   sync

   if mouseclick()=1
      rem make wave at point mx, my
      MakeWave(mousex(), mousey(), g_dropRadius, g_waveForce)
   endif

loop

delete memblock 1
delete memblock 2
rem that's all
end

rem this clears height maps
function ClearHeights()
   local x, y

   for y=0 to g_bmpHeight-1
      for x=0 to g_bmpWidth-1
         g_heightMap(0, x, y) = 0
         g_heightMap(1, x, y) = 0
      next x
   next y
endfunction


rem this makes a new wave
function MakeWave(x, y, radius, mul)
   local u, v, sqru, sqrv, sqrr

   sqrr = radius*radius
   rem check if not out of bitmap boundary
   if (x>radius) and (x<g_bmpWidth-1-radius) and (y>radius) and (y<g_bmpHeight-1-radius)
      for v=y-radius to y+radius
         sqrv = (v-y)*(v-y)
         for u=x-radius to x+radius
            sqru = (u-x)*(u-x)
            rem for speed reasons check (dx^2 + dy^2) <= r^2
            rem instead of real formula: sqrt(dx^2 + dy^) < r
            if (sqru+sqrv)<=sqrr:
               g_heightMap(g_ch,u,v) = mul*int(radius - sqrt(sqru+sqrv)+1)
            endif
         next u
      next v
   endif

endfunction

rem this is only for debug (shows waves in grayscale)
function DrawHeights()
   local x, y, height, color
   local dstAddr as dword
   rem for each height
   for y=0 to g_bmpHeight-1
      for x=0 to g_bmpWidth-1
         height = g_heightMap(g_ch, x, y)/10
         rem prepare gray color
         color = rgb(height+128, height+128, height+128)
         rem dont need this if useing one color depth
         select g_bytesPerPixel
            case 2: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*2: endcase
            case 4: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*4: endcase
         endselect
         *dstAddr = color
      next x
   next y
endfunction


rem the meat. this updates height map
function UpdateHeights()
   local x, y,  height, temp

   rem we need skip bitmap edges couse we're making kind of area sampling
   for y=2 to g_bmpHeight-3
      for x=2 to g_bmpWidth-3

         rem calculate height difference
         rem read 12 height values surrounding (x,y), divide by 6 so we've got twice as much as average value
         rem and then subtract current height at (x, y)
         height = g_heightMap(g_ch,x-1,y)
         height = height + g_heightMap(g_ch,x-2,y)
         height = height + g_heightMap(g_ch,x+1,y)
         height = height + g_heightMap(g_ch,x+2,y)
         height = height + g_heightMap(g_ch,x,y-1)
         height = height + g_heightMap(g_ch,x,y-2)
         height = height + g_heightMap(g_ch,x,y+1)
         height = height + g_heightMap(g_ch,x,y+2)
         height = height + g_heightMap(g_ch,x-1,y-1)
         height = height + g_heightMap(g_ch,x+1,y-1)
         height = height + g_heightMap(g_ch,x-1,y+1)
         height = height + g_heightMap(g_ch,x+1,y+1)
         height = int(height/6) - g_heightMap(g_nh,x,y)

         rem add some dampig reducing amplitudes
         height = height - int(height/g_waveDamp + 1)

         g_heightMap(g_nh, x, y) = height
      next x
   next y

   rem swap height maps
   temp = g_ch
   g_ch = g_nh
   g_nh = temp
endfunction


rem this creates waved bitmap
function UpdateBitmap()
   local x, y, tx, ty, color
   local srcAddr, dstAddr as dword

   rem skip bitmap edges
   for y=1 to g_bmpHeight-1
      for x=1 to g_bmpWidth-1

         rem calculate pixel displacements based on height difference
         tx = x + (g_heightMap(g_ch, x-1, y) - g_heightMap(g_ch, x, y))/10: rem divide couse height values are too high
         ty = y + (g_heightMap(g_ch, x, y-1) - g_heightMap(g_ch, x, y))/10

         rem if (tx, ty) still inside bitmap bounds
         if tx>=0 and tx<g_bmpWidth and ty>=0 and ty<g_bmpHeight

            rem read color from coords we've calculated
            select g_bytesPerPixel
               case 2: srcAddr = g_srcMemPtr+12+(ty*g_bmpWidth+tx)*2: endcase
               case 4: srcAddr = g_srcMemPtr+12+(ty*g_bmpWidth+tx)*4: endcase
            endselect

            color = *srcAddr
         else
            rem if out of bitmap bounds let the color be black
            color = 0
         endif

         rem store this color at current position
         select g_bytesPerPixel
            case 2: dstAddr = g_dstMemPtr+12+(y*g_bmpWidth+x)*2: endcase
            case 4: dstAddr = g_dstMemPtr+12+(y*g_bmpWidth+x)*4: endcase
         endselect
         *dstAddr = color
      next x
   next y
endfunction

Posted: 27th Sep 2003 1:00
Nout happens for me...
Posted: 27th Sep 2003 1:13
You have posted a DEMO that requires an external file, can you incorporate the external file into the demo or give a link for it to be downloaded.
Posted: 27th Sep 2003 22:09
Yea, sorry for that (you could use any picture)
but ofcourse, here is the link for example picture

http://www.arena.free-host.com/examples/example1.jpg
Posted: 28th Sep 2003 14:25
This is very nice.
I think I'll try to optimize it a little bit.
Posted: 30th Sep 2003 1:43
Just let me know when you finished. Id like to compare this 2 versions
Posted: 30th Sep 2003 13:27
Well, at least I could double the frame rate.
I wished that I could do more, but it's really hard for me to see throw the code.
I think I'll try to understand this code fully .
+ Code Snippet
remstart
   Water Wave Effect
   by Mariusz Skowronski (2003)
remend

disable escapekey

rem global vars
rem bitmap size and color depth
global g_bmpWidth as integer
global g_bmpHeight as integer
global g_bmpBpp as integer
global g_bytesPerPixel as integer

rem memblock pointers (for faster access)
global g_srcMemPtr as dword
global g_dstMemPtr as dword

rem screen dimensions
global g_scrWidth as integer
global g_scrHeight as integer

rem height array swap index (current and new)
global g_ch as integer
global g_nh as integer


rem properties
rem wave amplitude
global g_waveForce as integer
rem drop size
global g_dropRadius as integer
rem damping value (the smaller value the faster waves disappear) 1 - 100
global g_waveDamp as integer


rem init vars
g_scrWidth = 640
g_scrHeight = 480

g_waveForce = 300
g_dropRadius = 8
g_waveDamp = 20 : rem DON'T USE ZERO

rem begin
set display mode g_scrWidth, g_scrHeight, 32
sync on : sync rate 0

rem load bitmap (remember the smaller bitmap the faster it runs)
load bitmap "example1.jpg", 1
g_bmpWidth = bitmap width(1)
g_bmpHeight = bitmap height(1)
g_bmpBpp = bitmap depth(1)
g_bytesPerPixel = g_bmpBpp/8


rem create 2 bitmap memblocks
make memblock from bitmap 2, 1

rem get memblock addresses
g_srcMemPtr = get memblock ptr(2)

rem dont need this bitmap anymore
delete bitmap 1

rem allocate 2 height maps
dim g_heightMap(1, g_bmpWidth-1, g_bmpHeight-1) as integer
rem clear height maps
ClearHeights()

rem set current height map to 0
g_ch = 0: g_nh = 1

set text opaque

do
   rem update heights
   UpdateHeights()
   rem update bitmap
   UpdateBitmap()
   rem uncomment following lie and rem this above to see it in greyscale
   rem DrawHeights()

   text screen width()-text width("FPS: "+str$(screen fps())),screen height()-text size(),"FPS: "+str$(screen fps())
   sync

   if mouseclick()=1
      rem make wave at point mx, my
      MakeWave(mousex(), mousey(), g_dropRadius, g_waveForce)
   endif

   if escapekey() then exit

loop

delete memblock 2
rem that's all
end

rem this clears height maps
function ClearHeights()
   local x, y
   for y=0 to g_bmpHeight-1
      for x=0 to g_bmpWidth-1
         g_heightMap(0, x, y) = 0
         g_heightMap(1, x, y) = 0
      next x
   next y
endfunction


rem this makes a new wave
function MakeWave(x, y, radius, mul)
   local u, v, sqru, sqrv, sqrr

   sqrr = radius*radius
   rem check if not out of bitmap boundary
   if (x>radius) and (x<g_bmpWidth-1-radius) and (y>radius) and (y<g_bmpHeight-1-radius)
      for v=y-radius to y+radius
         sqrv = (v-y)*(v-y)
         for u=x-radius to x+radius
            sqru = (u-x)*(u-x)
            rem for speed reasons check (dx^2 + dy^2) <= r^2
            rem instead of real formula: sqrt(dx^2 + dy^) < r
            if (sqru+sqrv)<=sqrr:
               g_heightMap(g_ch,u,v) = mul*int(radius - sqrt(sqru+sqrv)+1)
            endif
         next u
      next v
   endif

endfunction

rem this is only for debug (shows waves in grayscale)
function DrawHeights()
   local x, y, height, color
   local dstAddr as dword
   rem for each height
   for y=0 to g_bmpHeight-1
      for x=0 to g_bmpWidth-1
         height = g_heightMap(g_ch, x, y)/10
         rem prepare gray color
         color = rgb(height+128, height+128, height+128)
         rem dont need this if useing one color depth
         select g_bytesPerPixel
            case 2: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*2: endcase
            case 4: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*4: endcase
         endselect
         *dstAddr = color
      next x
   next y
endfunction


rem the meat. this updates height map
function UpdateHeights()
   local x, y,  height, temp

   rem we need skip bitmap edges couse we're making kind of area sampling
   for y=2 to g_bmpHeight-3
      for x=2 to g_bmpWidth-3

         rem calculate height difference
         rem read 12 height values surrounding (x,y), divide by 6 so we've got twice as much as average value
         rem and then subtract current height at (x, y)
         height = g_heightMap(g_ch,x-1,y)
         height = height + g_heightMap(g_ch,x-2,y)
         height = height + g_heightMap(g_ch,x+1,y)
         height = height + g_heightMap(g_ch,x+2,y)
         height = height + g_heightMap(g_ch,x,y-1)
         height = height + g_heightMap(g_ch,x,y-2)
         height = height + g_heightMap(g_ch,x,y+1)
         height = height + g_heightMap(g_ch,x,y+2)
         height = height + g_heightMap(g_ch,x-1,y-1)
         height = height + g_heightMap(g_ch,x+1,y-1)
         height = height + g_heightMap(g_ch,x-1,y+1)
         height = height + g_heightMap(g_ch,x+1,y+1)
         height = int(height/6) - g_heightMap(g_nh,x,y)

         rem add some dampig reducing amplitudes
         height = height - int(height/g_waveDamp + 1)

         g_heightMap(g_nh, x, y) = height
      next x
   next y

   rem swap height maps
   temp = g_ch
   g_ch = g_nh
   g_nh = temp
endfunction


rem this creates waved bitmap
function UpdateBitmap()
   local x, y, tx, ty
   local srcAddr, dstAddr, color as dword

   lock backbuffer
   backptr=get backbuffer ptr()
   rem skip bitmap edges
   for y=0 to g_bmpHeight-1
      for x=0 to g_bmpWidth-1

         rem calculate pixel displacements based on height difference
         tx = x + (g_heightMap(g_ch, x-1, y) - g_heightMap(g_ch, x, y))/10: rem divide couse height values are too high
         ty = y + (g_heightMap(g_ch, x, y-1) - g_heightMap(g_ch, x, y))/10

         rem if (tx, ty) still inside bitmap bounds
         if tx>=0 and tx<g_bmpWidth and ty>=0 and ty<g_bmpHeight
            rem read color from coords we've calculated
            select g_bytesPerPixel
               case 2 : copy memory backptr+12+(y*screen width()+x)*2,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*2,2 : endcase
               case 4 : copy memory backptr+12+(y*screen width()+x)*4,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*4,4 : endcase
            endselect
         endif
      next x
   next y
   unlock backbuffer
endfunction
Posted: 30th Sep 2003 14:41
Ok...
I could increase the sync rate once more.
Now it runs with ~28 fps on my pc.

+ Code Snippet
remstart
   Water Wave Effect
   by Mariusz Skowronski (2003)
remend

disable escapekey

rem global vars
rem bitmap size and color depth
global g_bmpWidth as integer
global g_bmpHeight as integer
global g_bmpBpp as integer
global g_bytesPerPixel as integer

rem memblock pointers (for faster access)
global g_srcMemPtr as dword
global g_dstMemPtr as dword

rem screen dimensions
global g_scrWidth as integer
global g_scrHeight as integer

rem height array swap index (current and new)
global g_ch as integer
global g_nh as integer


rem properties
rem wave amplitude
global g_waveForce as integer
rem drop size
global g_dropRadius as integer
rem damping value (the smaller value the faster waves disappear) 1 - 100
global g_waveDamp as integer


rem init vars
g_scrWidth = 640
g_scrHeight = 480

g_waveForce = 300
g_dropRadius = 8
g_waveDamp = 20 : rem DON'T USE ZERO

rem begin
set display mode g_scrWidth, g_scrHeight, 32
sync on : sync rate 0

rem load bitmap (remember the smaller bitmap the faster it runs)
load bitmap "example1.jpg", 1
g_bmpWidth = bitmap width(1)
g_bmpHeight = bitmap height(1)
g_bmpBpp = bitmap depth(1)
g_bytesPerPixel = g_bmpBpp/8


rem create bitmap memblock
make memblock from bitmap 2, 1


rem get memblock addresses
g_srcMemPtr = get memblock ptr(2)

rem dont need this bitmap anymore
delete bitmap 1

rem allocate 2 height maps
dim g_heightMap(1, g_bmpWidth-1, g_bmpHeight-1) as integer
rem clear height maps
ClearHeights()

rem set current height map to 0
g_ch = 0: g_nh = 1

make image from memblock 1, 2
paste image 1,0,0
sync
delete image 1

set text opaque

do
   UpdateHeights()

   if mouseclick() then MakeWave(mousex(), mousey(), g_dropRadius, g_waveForce)
   if escapekey() then exit

   text screen width()-text width("FPS: "+str$(screen fps())),screen height()-text size(),"FPS: "+str$(screen fps())
   sync
loop

delete memblock 2
rem that's all
end

rem this clears height maps
function ClearHeights()
   local x, y
   for y=0 to g_bmpHeight-1
      for x=0 to g_bmpWidth-1
         g_heightMap(0, x, y) = 0
         g_heightMap(1, x, y) = 0
      next x
   next y
endfunction


rem this makes a new wave
function MakeWave(x, y, radius, mul)
   local u, v, sqru, sqrv, sqrr

   sqrr = radius*radius
   rem check if not out of bitmap boundary
   if (x>radius) and (x<g_bmpWidth-1-radius) and (y>radius) and (y<g_bmpHeight-1-radius)
      for v=y-radius to y+radius
         sqrv = (v-y)*(v-y)
         for u=x-radius to x+radius
            sqru = (u-x)*(u-x)
            rem for speed reasons check (dx^2 + dy^2) <= r^2
            rem instead of real formula: sqrt(dx^2 + dy^) < r
            if (sqru+sqrv)<=sqrr:
               g_heightMap(g_ch,u,v) = mul*int(radius - sqrt(sqru+sqrv)+1)
            endif
         next u
      next v
   endif

endfunction

rem this is only for debug (shows waves in grayscale)
function DrawHeights()
   local x, y, height, color
   local dstAddr as dword
   rem for each height
   for y=0 to g_bmpHeight-1
      for x=0 to g_bmpWidth-1
         height = g_heightMap(g_ch, x, y)/10
         rem prepare gray color
         color = rgb(height+128, height+128, height+128)
         rem dont need this if useing one color depth
         select g_bytesPerPixel
            case 2: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*2: endcase
            case 4: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*4: endcase
         endselect
         *dstAddr = color
      next x
   next y
endfunction

rem the meat. this updates height map
function UpdateHeights()
   local x, y,  height, temp

   lock backbuffer

   backptr=get backbuffer ptr()

   rem we need skip bitmap edges couse we're making kind of area sampling
   for y=2 to g_bmpHeight-3
      for x=2 to g_bmpWidth-3

         rem calculate height difference
         rem read 12 height values surrounding (x,y), divide by 6 so we've got twice as much as average value
         rem and then subtract current height at (x, y)
         height = g_heightMap(g_ch,x-1,y)
         inc height,g_heightMap(g_ch,x-2,y)+g_heightMap(g_ch,x+1,y)+g_heightMap(g_ch,x+2,y)+g_heightMap(g_ch,x,y-1)+g_heightMap(g_ch,x,y-2)+g_heightMap(g_ch,x,y+1)+g_heightMap(g_ch,x,y+2)+g_heightMap(g_ch,x-1,y-1)+g_heightMap(g_ch,x+1,y-1)+g_heightMap(g_ch,x-1,y+1)+g_heightMap(g_ch,x+1,y+1)
         height = int(height/6) - g_heightMap(g_nh,x,y)
         rem add some dampig reducing amplitudes
         dec height,height/g_waveDamp + 1
         g_heightMap(g_nh, x, y) = height

         tx = x + (g_heightMap(g_ch, x-1, y) - height)/10: rem divide couse height values are too high
         ty = y + (g_heightMap(g_ch, x, y-1) - height)/10
         rem if (tx, ty) still inside bitmap bounds
         if tx>=0 and tx<g_bmpWidth and ty>=0 and ty<g_bmpHeight and (tx<>x or ty<>y)
            rem read color from coords we've calculated
            select g_bytesPerPixel
               case 2 : copy memory backptr+12+(y*screen width()+x)*2,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*2,2 : endcase
               case 4 : copy memory backptr+12+(y*screen width()+x)*4,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*4,4 : endcase
            endselect
         endif
      next x
   next y

   unlock backbuffer

   rem swap height maps
   temp = g_ch
   g_ch = g_nh
   g_nh = temp
endfunction
Posted: 30th Sep 2003 18:11
Wow! Great work!
I had ~26 with last improvement and now I've got ~36

by the way, didnt know that inc, dec are faster than standard +, - operators
Posted: 1st Oct 2003 13:04
I saw that when the waves disapear the image stays a little "pixelized" (It looks nice too, like picture from some voxel engine). To solve this function UpdateHeights() should rather looks like this:
+ Code Snippet
function UpdateHeights()
   local x, y,  height, temp

   lock backbuffer

   backptr=get backbuffer ptr()

   rem we need skip bitmap edges couse we're making kind of area sampling
   for y=2 to g_bmpHeight-3
      for x=2 to g_bmpWidth-3

         rem calculate height difference
         rem read 12 height values surrounding (x,y), divide by 6 so we've got twice as much as average value
         rem and then subtract current height at (x, y)
         height = g_heightMap(g_ch,x-1,y)
         inc height,g_heightMap(g_ch,x-2,y)+g_heightMap(g_ch,x+1,y)+g_heightMap(g_ch,x+2,y)+g_heightMap(g_ch,x,y-1)+g_heightMap(g_ch,x,y-2)+g_heightMap(g_ch,x,y+1)+g_heightMap(g_ch,x,y+2)+g_heightMap(g_ch,x-1,y-1)+g_heightMap(g_ch,x+1,y-1)+g_heightMap(g_ch,x-1,y+1)+g_heightMap(g_ch,x+1,y+1)
         height = int(height/6) - g_heightMap(g_nh,x,y)
         rem add some dampig reducing amplitudes
         dec height,height/g_waveDamp + 1
         g_heightMap(g_nh, x, y) = height

         tx = x + (g_heightMap(g_ch, x-1, y) - height)/10: rem divide couse height values are too high
         ty = y + (g_heightMap(g_ch, x, y-1) - height)/10
         rem if (tx, ty) still inside bitmap bounds

rem HERE

         if tx>=0 and tx<g_bmpWidth and ty>=0 and ty<g_bmpHeight 
            rem read color from coords we've calculated
            select g_bytesPerPixel
               case 2 : copy memory backptr+12+(y*screen width()+x)*2,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*2,2 : endcase
               case 4 : copy memory backptr+12+(y*screen width()+x)*4,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*4,4 : endcase
            endselect
         endif
      next x
   next y

   unlock backbuffer

   rem swap height maps
   temp = g_ch
   g_ch = g_nh
   g_nh = temp
endfunction


I mean there souldnt be checked condition: and (tx<>x or ty<>y)
Posted: 1st Oct 2003 17:05
Oh...you're right, but it is a little faster, when you don't syncronize what you don't have to.
It's better to use this function even if there is an unwanted effect at the start .

+ Code Snippet
function UpdateHeights()
   local x, y,  height, temp

   lock backbuffer

   backptr=get backbuffer ptr()

   rem we need skip bitmap edges couse we're making kind of area sampling
   for y=2 to g_bmpHeight-3
      for x=2 to g_bmpWidth-3

         rem calculate height difference
         rem read 12 height values surrounding (x,y), divide by 6 so we've got twice as much as average value
         rem and then subtract current height at (x, y)
         height = g_heightMap(g_ch,x-1,y)
         inc height,g_heightMap(g_ch,x-2,y)+g_heightMap(g_ch,x+1,y)+g_heightMap(g_ch,x+2,y)+g_heightMap(g_ch,x,y-1)+g_heightMap(g_ch,x,y-2)+g_heightMap(g_ch,x,y+1)+g_heightMap(g_ch,x,y+2)+g_heightMap(g_ch,x-1,y-1)+g_heightMap(g_ch,x+1,y-1)+g_heightMap(g_ch,x-1,y+1)+g_heightMap(g_ch,x+1,y+1)
         height = int(height/6) - g_heightMap(g_nh,x,y)
         rem add some dampig reducing amplitudes
         dec height,height/g_waveDamp + 1
         g_heightMap(g_nh, x, y) = height

         tx = x + (g_heightMap(g_ch, x-1, y) - height)/10: rem divide couse height values are too high
         ty = y + (g_heightMap(g_ch, x, y-1) - height)/10
         rem if (tx, ty) still inside bitmap bounds
         if tx&gt;=0 and tx&lt;g_bmpWidth and ty&gt;=0 and ty&lt;g_bmpHeight and g_heightMap(g_ch, x-1, y)&lt;&gt;g_heightMap(g_ch, x, y-1)
         rem read color from coords we've calculated
            select g_bytesPerPixel
               case 2 : copy memory backptr+12+(y*screen width()+x)*2,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*2,2 : endcase
               case 4 : copy memory backptr+12+(y*screen width()+x)*4,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*4,4 : endcase
            endselect
         endif
      next x
   next y

   unlock backbuffer

   rem swap height maps
   temp = g_ch
   g_ch = g_nh
   g_nh = temp
endfunction
Posted: 1st Oct 2003 17:12
ok...forget about the last post.
There are more unwanted effects than wanted .
Posted: 1st Oct 2003 18:51
OMG! That is an amazingly amazing effect. Looks so realistic. Great job !
Posted: 1st Oct 2003 19:16
It's better to use this function even if there is an unwanted effect at the start


I didnt mean the effect at the start but that when all waves stops, when image became "dissolved" (dontknow is it wright word), but now it dissapeared and it looks very good and ofcourse compared to the first version it run almost like a rocket

Really good job D Man.
Posted: 1st Oct 2003 19:47
Thank' you , but you had the idea and I knew how to optimize it .
Great job from you, too.
Posted: 2nd Oct 2003 10:31
Thanks!
I've got this code i Code Base so I'll update it with this version and I'll give you credit (wright word I hope).
What do you think about?
Posted: 2nd Oct 2003 14:07
I definately agree that you should update the entry in the Code Base but you don't have to give me credits, as this was your idea, but if you wan't I've nothing against it .
Posted: 3rd Oct 2003 13:43
Well I've updated the simulation with 2 more effects.
Now under keys 1, 2, 3 you've got three effects
1) old one (move mouse and press lmb)
2) something I called rain
3) similar to the 2nd but drops are bigger and slower

here's the code
+ Code Snippet
remstart
   Water Wave Effect
   by Mariusz Skowronski (2003)
   optimized by D Man
remend

#constant EFFECT_PATH 1
#constant EFFECT_RAIN1 2
#constant EFFECT_RAIN2 3

disable escapekey

rem global vars
rem bitmap size and color depth
global g_bmpWidth as integer
global g_bmpHeight as integer
global g_bmpBpp as integer
global g_bytesPerPixel as integer

rem memblock pointers (for faster access)
global g_srcMemPtr as dword
global g_dstMemPtr as dword

rem screen dimensions
global g_scrWidth as integer
global g_scrHeight as integer

rem height array swap index (current and new)
global g_ch as integer
global g_nh as integer

global g_effect as integer

rem properties
rem wave amplitude
global g_waveForce as integer
rem drop size
global g_dropRadius as integer
rem damping value (the smaller value the faster waves disappear) 1 - 100
global g_waveDamp as integer


rem init vars
g_scrWidth = 640
g_scrHeight = 480

g_waveForce = 300
g_dropRadius = 8
g_waveDamp = 20 : rem DON'T USE ZERO

g_effect = EFFECT_PATH

rem begin
set display mode g_scrWidth, g_scrHeight, 32
sync on : sync rate 0

rem load bitmap (remember the smaller bitmap the faster it runs)
load bitmap "example1.jpg", 1
g_bmpWidth = bitmap width(1)
g_bmpHeight = bitmap height(1)
g_bmpBpp = bitmap depth(1)
g_bytesPerPixel = g_bmpBpp/8


rem create bitmap memblock
make memblock from bitmap 2, 1


rem get memblock addresses
g_srcMemPtr = get memblock ptr(2)

rem dont need this bitmap anymore
delete bitmap 1

rem allocate 2 height maps
dim g_heightMap(1, g_bmpWidth-1, g_bmpHeight-1) as integer
rem clear height maps
ClearHeights()

rem set current height map to 0
g_ch = 0: g_nh = 1

`make image from memblock 1, 2
`paste image 1,0,0
sync
`delete image 1

set text opaque
randomize 100
lastTime = 0
do
   UpdateHeights()

   select g_effect
      case EFFECT_PATH:
         if mouseclick() then MakeWave(mousex(), mousey(), g_dropRadius, g_waveForce)
      endcase

      case EFFECT_RAIN1:
            MakeWave(rnd(g_bmpWidth), rnd(g_bmpHeight), rnd(2)+1, g_waveForce)
            MakeWave(rnd(g_bmpWidth), rnd(g_bmpHeight), rnd(2)+1, g_waveForce)
      endcase

      case EFFECT_RAIN2:
         if timer()-lastTime &gt; 2000
            lastTime = timer()
            MakeWave(rnd(g_bmpWidth), rnd(g_bmpHeight), rnd(6)+8, g_waveForce)
         endif
      endcase
   endselect

   char$ = inkey$()
   select char$
      case "1"
          g_effect = EFFECT_PATH
          g_waveForce = 300 : g_dropRadius = 8 : g_waveDamp = 20
      endcase
      case "2"
         g_effect = EFFECT_RAIN1
         g_waveForce = 800 : g_waveDamp = 6
      endcase
      case "3"
         g_effect = EFFECT_RAIN2
         lastTime = timer()
         g_waveForce = 200 : g_waveDamp = 30
      endcase
   endselect

   if escapekey() then exit

   text screen width()-text width("FPS: "+str$(screen fps())), 10,"FPS: "+str$(screen fps())
   sync
loop

delete memblock 2
rem that's all
end

rem this clears height maps
function ClearHeights()
   local x, y
   for y=0 to g_bmpHeight-1
      for x=0 to g_bmpWidth-1
         g_heightMap(0, x, y) = 0
         g_heightMap(1, x, y) = 0
      next x
   next y
endfunction


rem this makes a new wave
function MakeWave(x, y, radius, mul)
   local u, v, sqru, sqrv, sqrr

   sqrr = radius*radius
   rem check if not out of bitmap boundary
   if (x&gt;radius) and (x&lt;g_bmpWidth-1-radius) and (y&gt;radius) and (y&lt;g_bmpHeight-1-radius)
      for v=y-radius to y+radius
         sqrv = (v-y)*(v-y)
         for u=x-radius to x+radius
            sqru = (u-x)*(u-x)
            rem for speed reasons check (dx^2 + dy^2) &lt;= r^2
            rem instead of real formula: sqrt(dx^2 + dy^) &lt; r
            if (sqru+sqrv)&lt;=sqrr:
               g_heightMap(g_ch,u,v) = mul*int(radius - sqrt(sqru+sqrv)+1)
            endif
         next u
      next v
   endif

endfunction

rem this is only for debug (shows waves in grayscale)
function DrawHeights()
   local x, y, height, color
   local dstAddr as dword
   rem for each height
   for y=0 to g_bmpHeight-1
      for x=0 to g_bmpWidth-1
         height = g_heightMap(g_ch, x, y)/10
         rem prepare gray color
         color = rgb(height+128, height+128, height+128)
         rem dont need this if useing one color depth
         select g_bytesPerPixel
            case 2: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*2: endcase
            case 4: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*4: endcase
         endselect
         *dstAddr = color
      next x
   next y
endfunction

rem the meat. this updates height map
function UpdateHeights()
   local x, y,  height, temp

   lock backbuffer

   backptr=get backbuffer ptr()

   rem we need skip bitmap edges couse we're making kind of area sampling
   for y=2 to g_bmpHeight-3
      for x=2 to g_bmpWidth-3

         rem calculate height difference
         rem read 12 height values surrounding (x,y), divide by 6 so we've got twice as much as average value
         rem and then subtract current height at (x, y)
         height = g_heightMap(g_ch,x-1,y)
         inc height,g_heightMap(g_ch,x-2,y)+g_heightMap(g_ch,x+1,y)+g_heightMap(g_ch,x+2,y)+g_heightMap(g_ch,x,y-1)+g_heightMap(g_ch,x,y-2)+g_heightMap(g_ch,x,y+1)+g_heightMap(g_ch,x,y+2)+g_heightMap(g_ch,x-1,y-1)+g_heightMap(g_ch,x+1,y-1)+g_heightMap(g_ch,x-1,y+1)+g_heightMap(g_ch,x+1,y+1)
         height = int(height/6) - g_heightMap(g_nh,x,y)
         rem add some dampig reducing amplitudes
         dec height,height/g_waveDamp + 1
         g_heightMap(g_nh, x, y) = height

         tx = x + (g_heightMap(g_ch, x-1, y) - height)/10: rem divide couse height values are too high
         ty = y + (g_heightMap(g_ch, x, y-1) - height)/10
         rem if (tx, ty) still inside bitmap bounds
         `if tx&gt;=0 and tx&lt;g_bmpWidth and ty&gt;=0 and ty&lt;g_bmpHeight and g_heightMap(g_ch, x-1, y)&lt;&gt;g_heightMap(g_ch, x, y-1)
         if tx&gt;=0 and tx&lt;g_bmpWidth and ty&gt;=0 and ty&lt;g_bmpHeight and g_heightMap(g_ch, x, y)&lt;&gt;g_heightMap(g_nh, x, y)
         rem read color from coords we've calculated
            select g_bytesPerPixel
               case 2 : copy memory backptr+12+(y*screen width()+x)*2,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*2,2 : endcase
               case 4 : copy memory backptr+12+(y*screen width()+x)*4,g_srcMemPtr+12+(ty*g_bmpWidth+tx)*4,4 : endcase
            endselect
         endif
      next x
   next y

   unlock backbuffer

   rem swap height maps
   temp = g_ch
   g_ch = g_nh
   g_nh = temp
endfunction



and the bitmap:
http://www.arena.free-host.com/examples/example1.jpg

again: enjoy
Posted: 4th Oct 2003 0:21
Good idea and thanks for the credits .
Posted: 5th Oct 2003 0:25
Great!