are usually penetrate the other meshes and this is also noticed with other engines . sphere radius 0.4 and up does not penetrate your terrain. and to prevent visual illusion happened from the spheres dropped from the edges use big terrain, also we can use a slightly concave terrain but the question is:
there is less spheres escape but then less Mobility .
for your convenience here is your same example but bigger terrain and a scaled cube under it with physics, press '
' to initiate making 500 spheres, (1000 will make the program very slow on my hardware especially the bigger spheres and with material NoCulling.
the spheres here are 0.4 radius. a few spheres are penetrating the scaled cube but not your terrain.
for the users: save this at the same folder of the terrain generator by Samuel here:
Code: Select all
Enumeration
#Window
#Font
#HelpSprite
#Texture
#Material
#Light
#Camera
#Terrain
#HeightMap
EndEnumeration
Declare TG_UpdateSprite()
Declare TG_GenerateTerrain(TilesX, TilesZ, TerrainHeight, TerrainSizeX, TerrainSizeZ, TextureRepeatU, TextureRepeatV, HeightMapHandle)
If InitEngine3D(#PB_Engine3D_DebugLog) = 0
MessageRequester("ERROR", "Failed to initialize the 3D engine.", #PB_MessageRequester_Ok)
End
EndIf
If InitSprite() = 0
MessageRequester("ERROR", "Failed to initialize the sprite environment.", #PB_MessageRequester_Ok)
End
EndIf
If InitKeyboard() = 0
MessageRequester("ERROR", "Failed to initialize the keyboard environment.", #PB_MessageRequester_Ok)
End
EndIf
If InitMouse() = 0
MessageRequester("ERROR", "Failed to initialize the mouse environment.", #PB_MessageRequester_Ok)
End
EndIf
UsePNGImageDecoder()
UseJPEGImageDecoder()
WindowW = 1280
WindowH = 720
Define.f MouseX, MouseY, KeyX, KeyY
Global.i RenderMode, Help
LoadFont(#Font, "Courier New", 11, #PB_Font_Bold)
If OpenWindow(#Window, 0, 0, WindowW, WindowH, "Terrain Generator, ...... press 'B' to drop the spheres", #PB_Window_ScreenCentered)
;AntialiasingMode(#PB_AntialiasingMode_x6)
If OpenWindowedScreen(WindowID(#Window), 0, 0, WindowW, WindowH, 0, 0, 0)
Add3DArchive("Programs\", #PB_3DArchive_FileSystem)
Add3DArchive("Scripts\", #PB_3DArchive_FileSystem)
Add3DArchive("Textures\", #PB_3DArchive_FileSystem)
;Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts", #PB_3DArchive_FileSystem)
Parse3DScripts()
EnableWorldPhysics(#True)
CreateSprite(#HelpSprite, 300, 145)
;# Texture that will cover the terrain.
LoadTexture(#Texture, "grass.jpg")
CreateMaterial(#Material, TextureID(#Texture))
;# Greyscale image that will be used for generating the terrain.
LoadImage(#HeightMap, "Textures\HeightMap00.png")
;## A FEW NOTES ##
;# Stay below 510 tiles total or you will exceed the vertex limit.
;# TerrainHeight can have a positive or negative value.
MeshHandle = TG_GenerateTerrain(255, 255, 5, 200, 200, 100, 100, #HeightMap)
TestHandle = IsMesh(MeshHandle)
If TestHandle <> 0
CreateEntity(#Terrain, MeshID(MeshHandle), MaterialID(#Material))
MaterialCullingMode(#Material, #PB_Material_NoCulling)
;RotateEntity(#Terrain, 0,0,180)
EntityPhysicBody(#Terrain, #PB_Entity_StaticBody)
EndIf
CreateLight (#Light, RGB(0,0,0), 0, 500, 1000)
SetLightColor(#Light, #PB_Light_DiffuseColor, RGB(255,255,255))
AmbientColor(RGB(50,50,50))
CreateCamera (#Camera, 0, 0, 100, 100)
MoveCamera (#Camera, -20, 100, 270, #PB_Absolute)
CameraLookAt (#Camera, 0, 00, 0)
CameraBackColor(#Camera, RGB(80,80,80))
CameraRenderMode(#Camera, #PB_Camera_Wireframe)
RenderMode = 1
SphereMesh = CreateSphere(#PB_Any, 0.4)
;CreateCylinder(5, 250, 50, 8,0,0)
;CreateEntity(5, MeshID(5),MaterialID(#Material) , 0,-50, 0)
;EntityPhysicBody(5, #PB_Entity_StaticBody)
CreateCube(5, 1)
CreateEntity(5, MeshID(5),MaterialID(#Material) , 0,-50, 0)
ScaleEntity(5, 400,30,400)
EntityPhysicBody(5, #PB_Entity_StaticBody)
;For CTR = 1 To 10
; SphereEntity = CreateEntity(#PB_Any, MeshID(SphereMesh), #PB_Material_None, Random(50,0)-25,Random(20,10),Random(50,0)-25)
;EntityPhysicBody(SphereEntity, #PB_Entity_SphereBody, 1.0, 0.3, 0.5)
;Next
;# WARNING!! If you use stencil shadow types (#PB_Shadow_Modulative or #PB_Shadow_Additive)
;and you have over 360 tiles in your terrain the program may crash as you've exceeded the 16 bit index.
;In this case I personally wouldn't use stencil shadows. As they're not meant to be
;used in complex scenes.
;If you really want to use stencil shadows. I highly suggest you keep the terrain simple.
;WorldShadows(#PB_Shadow_Modulative, 100, RGB(150, 150, 150))
Repeat
Event = WindowEvent()
If ExamineMouse()
MouseX = -MouseDeltaX() / 10
MouseY = -MouseDeltaY() / 10
EndIf
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_A)
KeyX = -1.5
ElseIf KeyboardPushed(#PB_Key_D)
KeyX = 1.5
Else
KeyX = 0
EndIf
If KeyboardPushed(#PB_Key_W)
KeyY = -1.5
ElseIf KeyboardPushed(#PB_Key_S)
KeyY = 1.5
Else
KeyY = 0
EndIf
If KeyboardReleased(#PB_Key_R)
If RenderMode = 0
CameraRenderMode(#Camera, #PB_Camera_Wireframe)
RenderMode = 1
Else
CameraRenderMode(#Camera, #PB_Camera_Textured)
RenderMode = 0
EndIf
EndIf
If KeyboardReleased(#PB_Key_H)
If Help = 0
Help = 1
Else
Help = 0
EndIf
EndIf
EndIf
If KeyboardReleased(#PB_Key_B)
For CTR = 1 To 500
SphereEntity = CreateEntity(#PB_Any, MeshID(SphereMesh), #PB_Material_None, Random(50,0)-25,Random(20,10),Random(50,0)-25)
EntityPhysicBody(SphereEntity, #PB_Entity_SphereBody , 1.0, 0.3, 0.5)
;DisableEntityBody(SphereEntity,0)
Next
EndIf
RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
MoveCamera (#Camera, KeyX, 0, KeyY)
RenderWorld()
If Help = 0
TG_UpdateSprite()
DisplaySprite(#HelpSprite, 0, 0)
EndIf
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
EndIf
EndIf
End
Procedure TG_UpdateSprite()
Define.i FPS, Triangles, Batches
FPS = Engine3DStatus(#PB_Engine3D_CurrentFPS)
Triangles = Engine3DStatus(#PB_Engine3D_NbRenderedTriangles)
Batches = Engine3DStatus(#PB_Engine3D_NbRenderedBatches)
StartDrawing(SpriteOutput(#HelpSprite))
DrawingMode(#PB_2DDrawing_Default)
Box(0, 0, SpriteWidth(#HelpSprite), SpriteHeight(#HelpSprite), RGB(20,20,20))
DrawingFont(FontID(#Font))
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(5, 5, "FPS : " + Str(FPS), RGB(255,0,0))
DrawText(5, 25, "Triangles : " + Str(Triangles), RGB(0,255,0))
DrawText(5, 45, "Batches : " + Str(Batches), RGB(0,128,255))
DrawText(5, 65, "Press W,A,S,D to Move Camera.", RGB(255,255,255))
DrawText(5, 85, "Move Mouse to Rotate Camera.", RGB(255,255,255))
If RenderMode = 0
DrawText(5, 105, "Press R : Wireframe Off", RGB(255,128,0))
Else
DrawText(5, 105, "Press R : Wireframe On", RGB(255,128,0))
EndIf
If Help = 0
DrawText(5, 125, "Press H : Help On", RGB(255,255,0))
Else
DrawText(5, 125, "Press H : Help Off", RGB(255,255,0))
EndIf
StopDrawing()
EndProcedure
Procedure TG_GenerateTerrain(TilesX, TilesZ, TerrainHeight, TerrainSizeX, TerrainSizeZ, TextureRepeatU, TextureRepeatV, HeightMapHandle)
;# First check and see if all parameters have valid values.
;# TerrainHeight can have any value positive or negative. So, we will not be testing for it.
If TilesX <= 0
MessageRequester("ERROR", "TilesX must be greater than 0.", #PB_MessageRequester_Ok)
ProcedureReturn #False
EndIf
If TilesZ <= 0
MessageRequester("ERROR", "TilesZ must be greater than 0.", #PB_MessageRequester_Ok)
ProcedureReturn #False
EndIf
If TerrainSizeX <= 0
MessageRequester("ERROR", "TerrainSizeX must be greater than 0.", #PB_MessageRequester_Ok)
ProcedureReturn #False
EndIf
If TerrainSizeZ <= 0
MessageRequester("ERROR", "TerrainSizeZ must be greater than 0.", #PB_MessageRequester_Ok)
ProcedureReturn #False
EndIf
If TextureRepeatU <= 0
MessageRequester("ERROR", "TextureRepeatU must be greater than 0.", #PB_MessageRequester_Ok)
ProcedureReturn #False
EndIf
If TextureRepeatV <= 0
MessageRequester("ERROR", "TextureRepeatV must be greater than 0.", #PB_MessageRequester_Ok)
ProcedureReturn #False
EndIf
If IsImage(HeightMapHandle) = 0
MessageRequester("ERROR", "Failed to find HeightMap.", #PB_MessageRequester_Ok)
ProcedureReturn #False
EndIf
;# Test to make sure terrain will not exceed the 16 bit index limitations (65,536 vertices).
;# There are ways around this limitation, but that's for another day.
Define.i TotalVertices
TotalVertices = (TilesX + 1) * (TilesZ + 1)
If TotalVertices > 65536
MessageRequester("ERROR", "Terrain has too many tiles. Vertex limit has been exceeded.", #PB_MessageRequester_Ok)
ProcedureReturn #False
EndIf
;# Generating Vertex Data
Dim Vertices.d(TotalVertices, 2)
Define.d TileSizeX, TileSizeZ
TileSizeX = TerrainSizeX / TilesX
TileSizeZ = TerrainSizeZ / TilesZ
Define.d TileLocX, TileLocY, TileLocZ
TileLocX = (TerrainSizeX * 0.5) * -1
TileLocZ = (TerrainSizeZ * 0.5) * -1
StartDrawing(ImageOutput(HeightMapHandle))
Define.i ImgWidth, ImgHeight
ImgWidth = ImageWidth (HeightMapHandle) - 1
ImgHeight = ImageHeight(HeightMapHandle) - 1
Define.d ImgXRatio, ImgZRatio
ImgXRatio = ImgWidth / TerrainSizeX
ImgZRatio = ImgHeight / TerrainSizeZ
Define.d HeightRatio
HeightRatio = TerrainHeight / 255
Define.i PixelX, PixelY
Define.i VCTR, CTRX, CTRZ
Define.i Color, ColorValue
For CTRZ = 0 To TilesZ
For CTRX = 0 To TilesX
PixelX = ((TerrainSizeX * 0.5) + TileLocX) * ImgXRatio
PixelY = ((TerrainSizeZ * 0.5) + TileLocZ) * ImgZRatio
Color = Point(PixelX, PixelY)
ColorValue = Red(Color)
TileLocY = ColorValue * HeightRatio
Vertices(VCTR, 0) = TileLocX
Vertices(VCTR, 1) = TileLocY
Vertices(VCTR, 2) = TileLocZ
TileLocX = TileLocX + TileSizeX
VCTR + 1
Next
TileLocX = (TerrainSizeX * 0.5) * -1
TileLocZ = TileLocZ + TileSizeZ
Next
StopDrawing()
;# Generating Face Data
Define.i TotalFaces
TotalFaces = (TilesX * TilesZ) * 2
Dim Faces(TotalFaces, 2)
Define.i FCTR, FaceCTR
For CTRZ = 0 To TilesZ - 1
For CTRX = 0 To TilesX - 1
Faces(FCTR, 0) = FaceCTR
Faces(FCTR, 1) = FaceCTR + 1 + TilesX
Faces(FCTR, 2) = FaceCTR + 1
Faces(FCTR + 1, 0) = FaceCTR + 1
Faces(FCTR + 1, 1) = FaceCTR + 1 + TilesX
Faces(FCTR + 1, 2) = FaceCTR + 2 + TilesX
FCTR + 2
FaceCTR + 1
Next
FaceCTR + 1
Next
;# Now we can create our terrain
Define.i UCounter
Define.d U, V, Uoffset, Voffset
Uoffset = TextureRepeatU * (1 / TilesX)
Voffset = TextureRepeatV * (1 / TilesZ)
Handle = CreateMesh(#PB_Any, #PB_Mesh_TriangleList, #PB_Mesh_Static)
For CTR = 0 To TotalVertices -1
MeshVertexPosition(Vertices(CTR, 0), Vertices(CTR, 1), Vertices(CTR, 2))
MeshVertexNormal(0, 0, 0)
MeshVertexTextureCoordinate(U, V)
U = U + Uoffset
UCounter + 1
If UCounter > TilesX
UCounter = 0
U = 0
V = V + Voffset
EndIf
Next
For CTR = 0 To TotalFaces
MeshFace(Faces(CTR, 0), Faces(CTR, 1), Faces(CTR, 2))
Next
FinishMesh(#True)
;# We normalize the mesh because I haven't spent the time to manually calculate the vertex normals.
;I might add this process later on, but for now I'll keep it this way.
NormalizeMesh(Handle)
FreeArray(Vertices())
FreeArray(Faces())
ProcedureReturn Handle
EndProcedure