Blitz3D+ Command Reference

ModifyTerrainHole terrain,terrain_x,terrain_z[,enable]

Parameters

terrain - terrain entity to edit

terrain_x - cell column, 0 to TerrainSize(terrain)-1

terrain_z - cell row, 0 to TerrainSize(terrain)-1

enable (optional) - True opens a hole, False fills the cell back in; True (default)

Description

Opens or closes a hole in one terrain cell.

A hole takes both triangles of that cell out of the world. They stop being drawn, stop casting shadows, stop taking part in Blitz ray and sphere collision and picking, stop receiving ScatterTerrain placements, and are marked as holes in the next Box3D height field you create or refresh. That is how you get a cave mouth, a mineshaft, a bunker entrance or a sinkhole through otherwise solid ground.

Holes are per cell, so a doorway is a small rectangle of calls rather than one. Punching a lot of them is exactly the case BeginTerrainUpdate exists for - open a batch, carve the opening, close it, and only the affected chunks rebuild.

It does not build anything for you: no cave walls, no tunnel, no lip around the edge, no interior. You place an ordinary mesh through the opening. That boundary is deliberate - it keeps the feature small and lets you model what is under the ground however you like.

Gotcha: the coordinates address cells, so their range is 0 to TerrainSize-1 - one less than the sample range TerrainHeight accepts. Out of range raises "Terrain hole coordinates are outside the terrain cell area". A chunk that contains any hole is forced to full detail and never uses a coarser level, so scattering isolated holes across a large map costs more triangles than grouping them. TerrainY still reports the height the ground would have had, so use TerrainIsHole when your code has to tell open space from solid footing. And Box3D only notices holes when its shape is created or refreshed.

See also: TerrainIsHole, BeginTerrainUpdate, EndTerrainUpdate, ModifyTerrain, RefreshPhysicsTerrain.

Example

; ModifyTerrainHole Example
; -------------------------

Graphics3D 640,480,0,2
SetBuffer BackBuffer()

camera=CreateCamera()
PositionEntity camera,0,6,-40
CameraClsColor camera,110,150,200

light=CreateLight(1)
RotateEntity light,50,-30,0

; Rolling hills built from a sine-wave height field
terrain=CreateTerrain(128)
For z=0 To 127
    For x=0 To 127
        ModifyTerrain terrain,x,z,0.2+Sin(x*10)*Cos(z*10)*0.12
    Next
Next
ScaleEntity terrain,0.5,20,0.5
PositionEntity terrain,-32,-5,-32
TerrainShading terrain,True
TerrainDetail terrain,8000,True

; Plain grass texture drawn in code
grass=CreateTexture(8,8,1+8)
SetBuffer TextureBuffer(grass) : ClsColor 75,135,60 : Cls : SetBuffer BackBuffer()
EntityTexture terrain,grass

; Start with one hole already punched near the middle
For z=61 To 67
    For x=61 To 67
        ModifyTerrainHole terrain,x,z,True
    Next
Next

; A marker that circles the terrain showing where holes will go
marker=CreateSphere(8)
ScaleEntity marker,0.8,0.8,0.8
EntityColor marker,255,70,50

orbit#=0

While Not KeyDown(1)

    ; The marker circles the middle of the terrain
    orbit=orbit+0.4
    cx=64+Cos(orbit)*32
    cz=64+Sin(orbit)*32
    wx#=-32+cx*0.5
    wz#=-32+cz*0.5
    PositionEntity marker,wx,TerrainY(terrain,wx,0,wz)+1,wz

    ; Space punches (or fills) a 7x7 block of cells under the marker
    If KeyHit(57)
        punch=1-TerrainIsHole(terrain,cx,cz)
        For z=cz-3 To cz+3
            For x=cx-3 To cx+3
                ModifyTerrainHole terrain,x,z,punch
            Next
        Next
    EndIf

    ; Arrow keys move the camera
    If KeyDown(200) Then MoveEntity camera,0,0,0.1
    If KeyDown(208) Then MoveEntity camera,0,0,-0.1
    If KeyDown(203) Then TurnEntity camera,0,1,0
    If KeyDown(205) Then TurnEntity camera,0,-1,0

    RenderWorld

    Text 0,0,"Arrow keys: move camera   Space: punch/fill hole at marker   Esc: exit"
    Text 0,20,"Marker cell "+cx+","+cz+"   hole here: "+TerrainIsHole(terrain,cx,cz)

    Flip

Wend

End

Index