Try my new website:
www.urcho.com
- the new SIMPLE social network
Sign up
|
357
members |
125
snippets
Search for:
ALL
POPULAR
File Controls
Multiplayer Code
2D Effects
3D Effects
Oldskool demos
Basic Functions
Maths/Physics
Sound
Tutorials
Misc
Username:
Password:
Sign up
Dynamic Water by Danny
[
back
]
Author:
Archive
| Viewed:
917
times | Language:
BlitzBasic 3D
| Category:
3D Effects
; fxWater Module by Danny van der Ark - dendanny@xs4all.nl ; ; (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
= 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 ;-------------------------------------------------------------------------------------------------- ;[end of stuff]
Author Comments:
These functions can easily be used to have your characters footsteps cause ripples in the water. This Demo shows a boucning ball between two liquid surfaces. Not fully finished yet, but should get you going. Hit the left-mouse button to create random splashes... Heavily inspired on previous samples by Reda Borchardt and Rob Cummings. Have fun,- Danny
Login or
create an account
to comment on this snippet