Woah!! that FitMesh function made it run ALOT faster (50fps, 20fps up from my avg), though i still have the problem with the text boundary rectangles (using klepto's begin and end max2d - gfx driver didnt fix TBlitz2d shading).
The 8.1 update didn't change anything, not even the driver version. That was an update for newer models I think. The most recent version for radeon is 6.11, which I have.
heres the funtion for klepto.minib3d (fixes the ceiling being invisible at beginning and the lag)
Method FitMesh(x#,y#,z#,width#,height#,depth#,uniform=False) 'Simon - update bug 1/31/08 Plash was here
' if uniform=true than adjust fitmesh dimensions
If uniform=True
Local wr#=MeshWidth()/width
Local hr#=MeshHeight()/height
Local dr#=MeshDepth()/depth
If wr>=hr And wr>=dr
y=y+((height-(MeshHeight()/wr))/2.0)
z=z+((depth-(MeshDepth()/wr))/2.0)
height=MeshHeight()/wr
depth=MeshDepth()/wr
Else If hr>dr
x=x+((width-(MeshWidth()/hr))/2.0)
z=z+((depth-(MeshDepth()/hr))/2.0)
width=MeshWidth()/hr
depth=MeshDepth()/hr
Else
x=x+((width-(MeshWidth()/dr))/2.0)
y=y+((height-(MeshHeight()/dr))/2.0)
width=MeshWidth()/dr
height=MeshHeight()/dr
EndIf
EndIf
' old to new dimensions ratio, used to update mesh normals
Local wr#=MeshWidth()/width
Local hr#=MeshHeight()/height
Local dr#=MeshDepth()/depth
' find min/max dimensions
Local minx#=9999999999
Local miny#=9999999999
Local minz#=9999999999
Local maxx#=-9999999999
Local maxy#=-9999999999
Local maxz#=-9999999999
For Local s=1 To CountSurfaces()
Local surf:TSurface=GetSurface(s)
For Local v=0 To surf.CountVertices()-1
Local vx#=surf.VertexX#(v)
Local vy#=surf.VertexY#(v)
Local vz#=surf.VertexZ#(v)
If vx#<minx# Then minx#=vx#
If vy#<miny# Then miny#=vy#
If vz#<minz# Then minz#=vz#
If vx#>maxx# Then maxx#=vx#
If vy#>maxy# Then maxy#=vy#
If vz#>maxz# Then maxz#=vz#
Next
Next
For Local s=1 To CountSurfaces()
Local surf:TSurface=GetSurface(s)
For Local v=0 To surf.CountVertices()-1
' update vertex positions
Local vx#=surf.VertexX#(v)
Local vy#=surf.VertexY#(v)
Local vz#=surf.VertexZ#(v)
Local mx#=maxx#-minx#
Local my#=maxy#-miny#
Local mz#=maxz#-minz#
Local ux#,uy#,uz#
If mx#<0.0001 And mx#>-0.0001 Then ux#=0.0 Else ux#=(vx#-minx#)/mx# ' 0-1
If my#<0.0001 And my#>-0.0001 Then uy#=0.0 Else uy#=(vy#-miny#)/my# ' 0-1
If mz#<0.0001 And mz#>-0.0001 Then uz#=0.0 Else uz#=(vz#-minz#)/mz# ' 0-1
vx#=x#+(ux#*width#)
vy#=y#+(uy#*height#)
vz#=z#+(uz#*depth#)
surf.VertexCoords(v,vx#,vy#,vz#)
' update normals
Local nx#=surf.VertexNX#(v)
Local ny#=surf.VertexNY#(v)
Local nz#=surf.VertexNZ#(v)
nx#=nx#*wr#
ny#=ny#*hr#
nz#=nz#*dr#
surf.VertexNormal(v,nx#,ny#,nz#)
Next
' mesh shape has changed - update reset flag bug fix: no vbo in klepto.minib3d Plash was here
'surf.reset_vbo:|1|4
Next
' mesh shape has changed - update reset flag bug fix: changed Plash was here
'reset_bounds=True
'reset_col_tree=True
new_bounds=True
End Method
Current dynamic water code (still needs location correction for pickmode):
Framework brl.max2d
'Import brl.retro
Import brl.timer
Import "bbtype.bmx"
'Import "bbvkey.bmx"
Import klepto.minib3d
'Import sidesign.minib3d
SetGraphicsDriver(GLMax2DDriver(), GRAPHICS_BACKBUFFER | GRAPHICS_DEPTHBUFFER | GRAPHICS_ACCUMBUFFER)
Global fxWaterWave_list:TList=New TList
'Ported to BlitzMax by Plash - 1/30/08
' 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 = 2 '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
Global fxWaterBank#[FXWATER_MAX_BANKS+1, FXWATER_MAX_WIDTH+1, FXWATER_MAX_DEPTH +1]
Type FXWaterWave Extends TBBType
Method New()
Add(fxWaterWave_list)
End Method
Method After:FXWaterWave()
Local t:TLink
t=_link.NextLink()
If t Return FXWaterWave(t.Value())
End Method
Method Before:FXWaterWave()
Local t:TLink
t=_link.PrevLink()
If t Return FXWaterWave(t.Value())
End Method
Field id
Field name$
Field FXWATER_MAX_WIDTH 'max sub-division for water meshes
Field FXWATER_MAX_DEPTH
Field active 'if not ripples then fx is not active
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 800,600,32,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
'camerapick cursor
Local marker:TMesh=CreateSphere()
ScaleEntity marker,0.2,0.2,0.2
EntityColor marker,255,0,0
'load texture
tex = LoadTexture ("water.bmp",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
EntityPickMode water,2
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
'EntityPickMode water,3
'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 bb_list = 0
tim = CreateTimer(50)
Local l:String = "WavyWaterFx by Danny van der Ark"
While Not KeyHit(key_escape)
'update bouncing ball
update_ball( ball )
'update fxWater
fxWater_update()
'render
'UpdateWorld
'RenderWorld
'debug
'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(key_c) 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(key_p) Then
FlushKeys
While Not KeyHit(key_p) Wend
EndIf
'pause ball [B]
If KeyHit(key_b) 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(key_w) Then
OPT_WIREFRAME:~1
Wireframe OPT_WIREFRAME
EndIf
'Dirty refresh [D]
If KeyHit(key_d) Then
OPT_REFRESH = 1 - OPT_REFRESH
EndIf
UpdateWorld
RenderWorld
'Rem
BeginMax2D
SetBlend alphablend
'SetAlpha 0.5
SetColor 100, 100, 100
DrawText "based on samples from Reda Borchardt And Rob Cummings.", 2, 12
SetColor 20, 140, 255
DrawText "[ESC] to quit - [D] for fast but dirty refresh(" + OPT_REFRESH + ") - [W] To toggle WireFrame (" + OPT_WIREFRAME + ")", 2, 454
DrawText "[P] To pause - [B] to pause/reset ball - [C] to toggle ceiling", 2, 466
SetColor 250, 250, 220
DrawText "FPS " + fps, 10, 220
'DrawText "TRIS " + TrisRendered(), 10, 232
SetBlend solidblend
EndMax2D
'EndRem
'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
If MouseDown(1)
' reset entity colors
'EntityColor sphere,255,255,255
'EntityColor mesh,255,255,255
'EntityColor box,255,255,255
Local pick:TEntity=CameraPick(camera,MouseX(),MouseY())
Local pe:TEntity=PickedEntity()
Local ps:TSurface=PickedSurface()
If pick<>Null
'DebugLog "Picked!"
'DebugLog "PickedX(): " + PickedX()
'DebugLog "PickedY(): " + PickedY()
'DebugLog "PickedZ(): " + PickedZ()
'DebugLog "PickedNX(): " + PickedNX()
'DebugLog "PickedNY(): " + PickedNY()
'DebugLog "PickedNZ(): " + PickedNZ()
'DebugLog "PickedTime(): " + PickedTime()
'DebugLog "PickedEntity(): " + (pe).tostring()
'DebugLog "PickedSurface(): " + (ps).tostring()
'DebugLog "PickedTriangle(): " + PickedTriangle()
'EntityColor PickedEntity(), 255, 255, 0
PositionEntity marker,PickedX(), PickedY(), PickedZ()
fxWater_Dimple(w1, PickedX()/2, PickedZ()/2, .5, 4)
'fxWater_Dimple(w1, MouseX(), MouseY(), .5, 4)
DebugLog "x " + Int(PickedX()) + " y " + Int(PickedY()) + " z " + Int(PickedZ())
'Else
' DebugLog "Not Picked"
EndIf
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, 2.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)
'w.surface.vbo_enabled=False
'store handle for quick retrieval during collision
NameEntity w.entity, HandleFromObject(w)
'reserve memory banks to hold vertex energy
w.bank1 = fxWater_Create_Buffer()
w.bank2 = fxWater_Create_Buffer()
'return mesh handle
Return HandleFromObject(w)
End Function
'--------------------------------------------------------------------------------------------------
Function fxWater_update()
For w:FXWaterWave = EachIn fxWaterWave_list
'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 Abs(dyna#) > 0.2 Then
'PatchTransform
k=0
For i = 0 To w.depth
For j = 0 To w.width
h#=fxwaterbank(w.bank2,j,i)
VertexCoords(w.surface,k,VertexX(w.surface,k),h,VertexZ(w.surface,k))
VertexNormal(w.surface,k,-0.8-h*0.25,h*0.1,0.2-h*0.25)
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 = FXWaterWave(HandleToObject(hand))
DebugLog x + "," + z
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 = FXWaterWave(HandleToObject( hand ))
Return w.surface
End Function
'--------------------------------------------------------------------------------------------------
Function fxWater_get_entity( hand )
w:FXWaterWave = FXWaterWave(HandleToObject( 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
'--------------------------------------------------------------------------------------------------
Function BeginMax2D()
Local x,y,w,h
GetViewport(x,y,w,h)
glDisable(GL_LIGHTING)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glDisable(GL_FOG)
glDisable(GL_CULL_FACE)
glMatrixMode GL_TEXTURE
glLoadIdentity
glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho 0,GraphicsWidth(),GraphicsHeight(),0,-1,1
glMatrixMode GL_MODELVIEW
glLoadIdentity
SetViewport x,y,w,h
Local MaxTex:Int
glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))
For Local Layer = 0 Until MaxTex
glActiveTexture(GL_TEXTURE0+Layer)
glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)
glDisable(GL_TEXTURE_2D)
Next
glActiveTexture(GL_TEXTURE0)
'DrawRect - 10 , - 10 , 5 , 5
glViewport(0,0,TGlobal.Width,TGlobal.Height)
glScissor(0,0,TGlobal.Width,TGlobal.Height)
End Function
Function EndMax2D()
glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)
glDisable(GL_TEXTURE_2D)
TGlobal.EnableStates()
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
Using the updated fitmesh function in klepto.minib3d, I get nearly half the fps that I get with USE_VBO=False on sidesign.minib3d (about 25, using sidesign.minib3d 48-51).