How to get water height?
How to get water height?
Is there any way to detect the height of the water created with 'CreateWater(' to simulate floating objects?
If translation=Error: reply="Sorry, Im Spanish": Endif
Re: How to get water height?
Apparently the water height (base) is Y=0.
I have modified the Water.pb example to include a few floating barrels; took me some time to get them floating with water friction when under water. I added physics bodies to the entities, and move the ground plane from -5 to -50. When you set the plane to 0 there will be water-less surfaces.
To make it more realistic I suggest you should look into the boat physics example somewhere in this forum. This can be taken as a base for further improvements.
You would to have a list/array of points on the entity to query for submersion; there's also Pick() and raycast functions that can detect water collisions with more precision perhaps. This could be used to apply forces and (counter-) impulses to simulate friction/water contact and submersion, buoyancy. Similarly you could simulate wind on a sail or flat surface, with a set of points on the entity surface to apply wind impulses.
I have modified the Water.pb example to include a few floating barrels; took me some time to get them floating with water friction when under water. I added physics bodies to the entities, and move the ground plane from -5 to -50. When you set the plane to 0 there will be water-less surfaces.
To make it more realistic I suggest you should look into the boat physics example somewhere in this forum. This can be taken as a base for further improvements.
You would to have a list/array of points on the entity to query for submersion; there's also Pick() and raycast functions that can detect water collisions with more precision perhaps. This could be used to apply forces and (counter-) impulses to simulate friction/water contact and submersion, buoyancy. Similarly you could simulate wind on a sail or flat surface, with a set of points on the entity surface to apply wind impulses.
Code: Select all
; ------------------------------------------------------------
;
; PureBasic - Water
;
; (c) Fantaisie Software
;
; ------------------------------------------------------------
; with rusty barrels added
;#################################################################################################################
#end_distance=1024*4
Procedure ColorBlend(color1.l, color2.l, blend.f)
Protected r.w,g.w,b.w,a.w
r= Red(color1) + (Red(color2) - Red(color1)) * blend
g=Green(color1) + (Green(color2) - Green(color1)) * blend
b= Blue(color1) + (Blue(color2) - Blue(color1)) * blend
a=Alpha(color1) + (Alpha(color2) - Alpha(color1)) * blend
ProcedureReturn RGBA(r,g,b,a)
EndProcedure
InitEngine3D():InitSprite():InitKeyboard():InitMouse()
ExamineDesktops():dx=DesktopWidth(0)*0.9:dy=DesktopHeight(0)*0.9
OpenWindow(0, 0,0, DesktopUnscaledX(dx),DesktopUnscaledY(dy), " Water - [PageUp][PageDown] Sun height [F12] Wireframe [Esc] quit",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, dx, dy, 0, 0, 0)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models", #PB_3DArchive_FileSystem)
Parse3DScripts()
CreateCamera(0, 0, 0, 100, 100):MoveCamera(0,0,5,0):CameraLookAt(0,2,5,10)
;sky
tx_sky=LoadTexture(#PB_Any,"sky.png")
SkyDome(TextureID(tx_sky),$cc6600,$0088ff,3,400,-0.5,0)
;ocean
tx_water=LoadTexture(#PB_Any,"waternormal.png")
tx_foam=LoadTexture(#PB_Any,"foam.png")
CreateWater(TextureID(tx_water),TextureID(tx_foam), $cc888800,$886666, #end_distance, 1.5,1.2,0.2,0.7)
;ground
tx_ground=LoadTexture(#PB_Any,"Dirt.jpg")
CreateMaterial(2,TextureID(tx_ground))
CreatePlane(2,#end_distance*2,#end_distance*2,16,16,#end_distance/64,#end_distance/64)
CreateEntity(2,MeshID(2),MaterialID(2),0,-50,0)
CreateEntityBody(2, #PB_Entity_StaticBody,100)
; barrel
tx_barrel=LoadTexture(#PB_Any,"RustyBarrel.png")
tx_rusty =LoadTexture(#PB_Any,"RustySteel.jpg")
CreateMaterial(3, TextureID(tx_barrel))
CreateMaterial(4, TextureID(tx_rusty))
LoadMesh(3,"Barrel.mesh")
For i.i = 1 To 100
CreateEntity(i+10, MeshID(3), MaterialID(3), Random(1000)-Random(1000),Random(1000,1),Random(1000)-Random(1000))
CreateEntityBody(i+10, #PB_Entity_CylinderBody, 1, 0.5, 0.5)
RotateEntity(i+10,Random(180)-Random(180),Random(180)-Random(180),Random(180)-Random(180))
Next
EnableWorldPhysics(1)
EnableWorldCollisions(1)
Procedure CameraUserControl(camera,speed.f=0.2,smooth.f=0.1,yfixed.f=1e10)
Static.f MouseX,Mousey,depx,depz,sdepx,sdepz
depx=-speed*(KeyboardPushed(#PB_Key_Left)-KeyboardPushed(#PB_Key_Right))
depz=-speed*(KeyboardPushed(#PB_Key_Down)-KeyboardPushed(#PB_Key_Up)-MouseWheel()*20)
MouseX = -MouseDeltaX() * 0.05
MouseY = -MouseDeltaY() * 0.05
RotateCamera(camera, MouseY, MouseX, 0, #PB_Relative)
sdepx+(depx-sdepx)*smooth
sdepz+(depz-sdepz)*smooth
MoveCamera (camera, sdepX, 0, -sdepz)
If yfixed<>1e10:MoveCamera(camera,CameraX(camera),yfixed,CameraZ(camera),#PB_Absolute):EndIf
EndProcedure
WorldGravity(0)
Define.f r=1,rr
Repeat
While WindowEvent():Wend
ExamineKeyboard()
ExamineMouse()
If KeyboardReleased(#PB_Key_F12):fdf=1-fdf:If fdf:CameraRenderMode(0,#PB_Camera_Wireframe):Else:CameraRenderMode(0,#PB_Camera_Textured):EndIf:EndIf
CameraUserControl(0,0.2,0.1)
; sun height
r+(KeyboardPushed(#PB_Key_PageUp)-KeyboardPushed(#PB_Key_PageDown))*0.004:If r<0:r=0:ElseIf r>1:r=1:EndIf:rr=Pow(r,0.25)
CreateLight(0,ColorBlend($0088ff,$ffffff,rr),20000, r*40000,20000)
AmbientColor($010101*Int(r*48+64))
Fog(ColorBlend($004488,$ffccaa,r),1,0,#end_distance)
For i=1 To 100
If EntityY(i+10)<0
EntityRenderMode(i+10,#PB_Entity_DisplaySkeleton)
EntityVelocity(i+10,0.99 * GetEntityAttribute(i+10, #PB_Entity_LinearVelocityX),0.99 * GetEntityAttribute(i+10, #PB_Entity_LinearVelocityY),0.99 * GetEntityAttribute(i+10, #PB_Entity_LinearVelocityZ))
ApplyEntityForce(i+10,0,5.4,0)
SetEntityMaterial(i+10,MaterialID(4))
Else
ApplyEntityForce(i+10,0,-9.8,0)
EntityRenderMode(i+10,#PB_Entity_CastShadow)
SetEntityMaterial(i+10,MaterialID(3))
EndIf
Next
RenderWorld()
FlipBuffers()
Until KeyboardReleased(#PB_Key_Escape) Or MouseButton(3)
Re: How to get water height?
Very, very good your example berrnubi!
Thanks for share and thanks for help me with this.
When you say 'list of points', if im in the right, you refer to getMeshData()? Sorry for my ignorance, Idk other way to get the points. But what is the mesh when use CreateWater(), return value is none.
Thanks for share and thanks for help me with this.
When you say 'list of points', if im in the right, you refer to getMeshData()? Sorry for my ignorance, Idk other way to get the points. But what is the mesh when use CreateWater(), return value is none.
If translation=Error: reply="Sorry, Im Spanish": Endif
Re: How to get water height?
The vertex shader positions the vertices using a wavelength parameter and a time parameter. The time is automatically updated. I think you must have a text of the shader, and change it to manually update the time parameter to be able to compute the closest 4 vertices (outside the shader) to your 3d entity to get a water height at a given point.
Re: How to get water height?
@miso
I wish I knew how to do it but I believe I can follow you. This is very interesting! I believe it could work.
Height.f=GetWaveHeight(x,z) ; <- that would be nice
I've updated the example to use vertices, and the barrels behave "very well" now including underwater friction. The barrels balance themselves into a horizontal position quickly which looks more realistic. Check the position of each vertex in the world and apply the forces accordingly (gravity, buoyancy and friction).
F1-F3 keys are for resetting barrel positions and angular velocity (F1=random above water, F2=at bottom, F3=at water line). It's 350 barrels now some stick out with color to follow them over two cameras (one is fixed underwater). You can search & change the constant #MAX_BARRELS.
Hypothetical improvements I'd like to test would be to calculate the centroids from the faces of the mesh, and apply the forces there because these would be less calculations and I'd like to see the effect - but I see no CountMeshFaces() command in the help so I'm puzzled on how to find out (Faces=Vertices/3 maybe?).
I think the example could also be improved by checking meshradius and EntitY() vs. 0 Y height, so that we know when it's fully submerged or fully emerged, and then the vertex iterations can be skipped and the forces can be applied in one command (either up or down) and friction is then also predictable.
There are around 132 vertices per barrel; if we use more complex entities such optimizations could be very beneficial, especially if one could reduce the number of vertices checked; imagine a complex submarine with enterior submeshes, you probably want to check only the outer cylinder vertices from the shell and the tower, but not the inside. But I digress as I apparently try to get myself into a preventive burn-out.
I wish I knew how to do it but I believe I can follow you. This is very interesting! I believe it could work.
Height.f=GetWaveHeight(x,z) ; <- that would be nice
I've updated the example to use vertices, and the barrels behave "very well" now including underwater friction. The barrels balance themselves into a horizontal position quickly which looks more realistic. Check the position of each vertex in the world and apply the forces accordingly (gravity, buoyancy and friction).
F1-F3 keys are for resetting barrel positions and angular velocity (F1=random above water, F2=at bottom, F3=at water line). It's 350 barrels now some stick out with color to follow them over two cameras (one is fixed underwater). You can search & change the constant #MAX_BARRELS.
Hypothetical improvements I'd like to test would be to calculate the centroids from the faces of the mesh, and apply the forces there because these would be less calculations and I'd like to see the effect - but I see no CountMeshFaces() command in the help so I'm puzzled on how to find out (Faces=Vertices/3 maybe?).
I think the example could also be improved by checking meshradius and EntitY() vs. 0 Y height, so that we know when it's fully submerged or fully emerged, and then the vertex iterations can be skipped and the forces can be applied in one command (either up or down) and friction is then also predictable.
There are around 132 vertices per barrel; if we use more complex entities such optimizations could be very beneficial, especially if one could reduce the number of vertices checked; imagine a complex submarine with enterior submeshes, you probably want to check only the outer cylinder vertices from the shell and the tower, but not the inside. But I digress as I apparently try to get myself into a preventive burn-out.
Code: Select all
; WaterBarrels.pb
; Barrel boyancy example based on:
; ------------------------------------------------------------
;
; PureBasic - Water
;
; (c) Fantaisie Software
;
; ------------------------------------------------------------
;#################################################################################################################
#end_distance = 1024 * 4
Procedure ColorBlend(color1.l, color2.l, blend.f)
Protected r.w, g.w, b.w, a.w
r = Red(color1) + (Red(color2) - Red(color1)) * blend
g = Green(color1) + (Green(color2) - Green(color1)) * blend
b = Blue(color1) + (Blue(color2) - Blue(color1)) * blend
a = Alpha(color1) + (Alpha(color2) - Alpha(color1)) * blend
ProcedureReturn RGBA(r, g, b, a)
EndProcedure
InitEngine3D():InitSprite():InitKeyboard():InitMouse()
ExamineDesktops():dx = DesktopWidth(0) * 1:dy = DesktopHeight(0) * 1
OpenWindow(0, 0, 0, DesktopUnscaledX(dx), DesktopUnscaledY(dy), " Water - [PageUp][PageDown] Sun height [F12] Wireframe [Esc] quit", #PB_Window_ScreenCentered | #PB_Window_BorderLess)
OpenWindowedScreen(WindowID(0), 0, 0, dx, dy, 0, 0, 0)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts", #PB_3DArchive_FileSystem)
Parse3DScripts()
CreateCamera(0, 0, 0, 100, 100):MoveCamera(0, 0, 150, 350):CameraLookAt(0, 2, 5, 10)
CreateCamera(1, 80, 0, 20, 20):MoveCamera(1, 0, -45, 150):CameraLookAt(1, 2, 0, 10)
;sky
tx_sky = LoadTexture(#PB_Any, "sky.png")
SkyDome(TextureID(tx_sky), $cc6600, $0088ff, 3, 400, -0.5, 0)
;ocean
tx_water = LoadTexture(#PB_Any, "waternormal.png")
tx_foam = LoadTexture(#PB_Any, "foam.png")
CreateWater(TextureID(tx_water), TextureID(tx_foam), $cc888800, $886666, #end_distance, 1.5, 1.2, 0.2, 0.7)
;ground
tx_ground = LoadTexture(#PB_Any, "Dirt.jpg")
CreateMaterial(2, TextureID(tx_ground))
CreatePlane(2, #end_distance * 2, #end_distance * 2, 16, 16, #end_distance / 64, #end_distance / 64)
CreateEntity(2, MeshID(2), MaterialID(2), 0, -50, 0)
CreateEntityBody(2, #PB_Entity_StaticBody, 100)
; barrel
tx_barrel = LoadTexture(#PB_Any, "RustyBarrel.png")
tx_rusty = LoadTexture(#PB_Any, "RustySteel.jpg")
CreateMaterial(3, TextureID(tx_barrel))
CreateMaterial(4, TextureID(tx_rusty))
;alternate material
mat_red = GetScriptMaterial( - 1, "Color/Red")
mat_green = GetScriptMaterial( - 1, "Color/Green")
mat_blue = GetScriptMaterial( - 1, "Color/Blue")
mat_yellow = GetScriptMaterial( - 1, "Color/Yellow")
LoadMesh(3, "Barrel.mesh")
Define BarrelVertices
BarrelVertices = MeshVertexCount(3)
;Debug "Barrel has "+FormatNumber(BarrelVertices,0)+" vertices, "+FormatNumber(BarrelVertices/3)+" faces???"
Dim BarrelVertex.MeshVertex(BarrelVertices + 1)
GetMeshData(3, 0, BarrelVertex(), #PB_Mesh_Vertex, 0, BarrelVertices - 1)
;WorldShadows(#PB_Shadow_Modulative,500) ; DOESNT WORK :(
#MAX_BARRELS = 250
For i.i = 1 To #MAX_BARRELS
CreateEntity(i + 10, MeshID(3), MaterialID(3), Random(200) - Random(200), Random(200, 1), Random(200) - Random(200), 1 << 7)
; ScaleEntity(i+10,0.334,0.334,0.334,#PB_Absolute)
CreateEntityBody(i + 10, #PB_Entity_CylinderBody, 1, 0.5, 0.5)
RotateEntity(i + 10, Random(180) - Random(180), Random(180) - Random(180), Random(180) - Random(180))
SetEntityAttribute(i + 10, #PB_Entity_Restitution, 0.5)
EntityRenderMode(i + 10, #PB_Entity_CastShadow)
Next
SetEntityMaterial(11, MaterialID(mat_red))
SetEntityMaterial(12, MaterialID(mat_blue))
SetEntityMaterial(13, MaterialID(mat_yellow))
SetEntityMaterial(14, MaterialID(mat_green))
EnableWorldPhysics(1)
EnableWorldCollisions(1)
Procedure CameraUserControl(camera, speed.f = 0.2, smooth.f = 0.1, yfixed.f = 1e10)
Static.f MouseX, Mousey, depx, depz, sdepx, sdepz
depx = - speed * (KeyboardPushed(#PB_Key_Left) - KeyboardPushed(#PB_Key_Right))
depz = - speed * (KeyboardPushed(#PB_Key_Down) - KeyboardPushed(#PB_Key_Up) - MouseWheel() * 20)
MouseX = - MouseDeltaX() * 0.05
MouseY = - MouseDeltaY() * 0.05
RotateCamera(camera, MouseY, MouseX, 0, #PB_Relative)
sdepx + (depx - sdepx) * smooth
sdepz + (depz - sdepz) * smooth
MoveCamera (camera, sdepX, 0, - sdepz)
If yfixed <> 1e10:MoveCamera(camera, CameraX(camera), yfixed, CameraZ(camera), #PB_Absolute):EndIf
EndProcedure
Procedure ApplyBarrelWaterForces(Entity, Boyancy.f, Gravity.f)
Shared BarrelVertex()
Shared BarrelVertices
Protected i
Protected id = EntityID(Entity)
Protected wavesmall.f = GetWorldAttribute(#PB_Water_WaveHeight) + GetWorldAttribute(#PB_Water_WaveSmall)
Protected bellow_count
Protected friction_factor.f
Protected final_friction.f
Protected Boyancy2.f = Boyancy / BarrelVertices
Protected Gravity2.f = Gravity / BarrelVertices
Protected gx.f, gy.f, gz.f
Protected e2
; Check for every barrel vertex if it's bellow water surface (wavesmall) or above
While i < BarrelVertices
ConvertLocalToWorldPosition(id, BarrelVertex(i)\x, BarrelVertex(i)\y, BarrelVertex(i)\z)
gx = GetX()
gy = GetY()
gz = GetZ()
; e2 = RayPick(gx,wavesmall+2,gz,gx,gy,gz,1) ; Raypick doesn't work for now
If e2 = #PB_World_WaterPick Or gy <= wavesmall ; Bellow Water
bellow_count + 1
; apply boyancy on local entity vertex
ApplyEntityForce(Entity, 0, Boyancy2, 0, BarrelVertex(i)\x, BarrelVertex(i)\y, BarrelVertex(i)\z, #PB_World, #PB_Local)
Else
; apply gravitation on local entity vertex
ApplyEntityForce(Entity, 0, Gravity2, 0, BarrelVertex(i)\x, BarrelVertex(i)\y, BarrelVertex(i)\z, #PB_World, #PB_Local)
EndIf
i + 1
Wend
; ratio of vertices bellow water (for global water
friction_factor = bellow_count / BarrelVertices
final_friction = 1 - (friction_factor * 0.025) ; tweak here, seems ok
EntityVelocity(Entity, final_friction * GetEntityAttribute(Entity, #PB_Entity_LinearVelocityX), final_friction * GetEntityAttribute(Entity, #PB_Entity_LinearVelocityY), final_friction * GetEntityAttribute(Entity, #PB_Entity_LinearVelocityZ))
ApplyEntityTorque(Entity, - GetEntityAttribute(Entity, #PB_Entity_AngularVelocityX) * final_friction, - GetEntityAttribute(Entity, #PB_Entity_AngularVelocityY) * final_friction, - GetEntityAttribute(Entity, #PB_Entity_AngularVelocityZ) * final_friction)
EndProcedure
WorldGravity(0)
Define.f r = 1, rr
Repeat
While WindowEvent():Wend
ExamineKeyboard()
ExamineMouse()
If KeyboardReleased(#PB_Key_F12):fdf = 1 - fdf:If fdf:CameraRenderMode(0, #PB_Camera_Wireframe):Else:CameraRenderMode(0, #PB_Camera_Textured):EndIf:EndIf
CameraUserControl(0, 0.2, 0.1)
; sun height
r + (KeyboardPushed(#PB_Key_PageUp) - KeyboardPushed(#PB_Key_PageDown)) * 0.004:If r < 0:r = 0:ElseIf r > 1:r = 1:EndIf:rr = Pow(r, 0.25)
CreateLight(0, ColorBlend($0088ff, $ffffff, rr), 20000, r * 40000, 20000)
AmbientColor($010101*Int(r * 48 + 64))
Fog(ColorBlend($004488, $ffccaa, r), 1, 0, #end_distance)
; Reset barrel positions
If KeyboardReleased(#PB_Key_F1)
; immerge all entities
For i = 11 To #MAX_BARRELS + 10
MoveEntity(i, EntityX(i), Random(500, 50), EntityZ(i), #PB_Absolute)
ApplyEntityTorque(i, Random(3600) - Random(3600), Random(3600) - Random(3600), Random(3600) - Random(3600))
Next
ElseIf KeyboardReleased(#PB_Key_F2)
; submerge all entities
For i = 11 To #MAX_BARRELS + 10
MoveEntity(i, EntityX(i), -45 , EntityZ(i), #PB_Absolute)
ApplyEntityTorque(i, Random(3600) - Random(3600), Random(3600) - Random(3600), Random(3600) - Random(3600))
Next
ElseIf KeyboardReleased(#PB_Key_F3)
For i = 11 To #MAX_BARRELS + 10
MoveEntity(i, EntityX(i), 0, EntityZ(i), #PB_Absolute)
ApplyEntityTorque(i, Random(3600) - Random(3600), Random(3600) - Random(3600), Random(3600) - Random(3600))
Next
EndIf
; Apply forces
For i = 1 To #MAX_BARRELS
ApplyBarrelWaterForces(i + 10, 7.4, -9.8)
Next
RenderWorld()
FlipBuffers()
Until KeyboardReleased(#PB_Key_Escape) Or MouseButton(3) Or event = #PB_Event_CloseWindow
Re: How to get water height?
Thanks benubi and miso.
Where is WaterHeight(#Camera, x, y)?
Will be nice to have any thing like getWaterHeight(x,z) in PB6.2x
I think this was more easy.
Where is WaterHeight(#Camera, x, y)?
Will be nice to have any thing like getWaterHeight(x,z) in PB6.2x
I think this was more easy.

If translation=Error: reply="Sorry, Im Spanish": Endif