TGC Codebase Backup



Water Wave Effect by skovron

25th Sep 2003 18:25
Summary

Use your mouse and LMB to generate water waves...



Description

This code loads some image, than for each pixel position it calculates displacement. Displacement points to pixel which replaces current pixel. It could produce very chaotic bitmaps but displacement is calculatet with use of heightmaps. Each coord of heightmap holds wave amplitude at that position so calculationg difference between neighbor amplitudes (along each axis) we simply calculate displacement for pixel position

It's hard for me to explain it in more detail becouse my english is very bad.
Well, sorry for that.

Now prepare some image, but remember it should be very small, the bigger the bitmap is the more loops have to execute
I use 320x240, with 640x480 my computer has a little troubles

Move mouse and use left button, than try to change some properties inside the code

Well enjoy!

New version 2.0 has some optimalizations made by D Man



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    remstart
   Water Wave Effect
   by Mariusz Skowronski (2003)
   optimalized by D Man
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