Blitz3D+ Command Reference

EndTerrainUpdate terrain

Parameters

terrain - terrain entity whose open edit batch is committed

Description

Commits a terrain edit batch, rebuilding only the region that changed.

This closes what BeginTerrainUpdate opened. The rectangle covering every sample you edited is committed in one go: the chunks it overlaps are invalidated together with the neighbours that share the changed border, their normals, bounds and level-of-detail error data are recalculated once, and the shadow data for that region is dropped. Every chunk outside the rectangle keeps its cached mesh and costs nothing.

That is the whole point of batching. Digging a 32 by 32 patch out of a 1024 terrain costs you the patch, not the landscape, which is what makes runtime terrain deformation practical in a game - craters under explosions, a trench dug by the player, ground rising as a building is placed.

The rebuild itself happens as part of the terrain's next render, and you can watch it happen: TerrainRebuiltChunks reports how many chunk meshes were rebuilt in the last pass and TerrainUploadBytes how much geometry that produced. A stationary terrain that has not been edited reports 0 for both, so a number that stays high frame after frame means something is dirtying the terrain every frame.

Gotcha: calling this with no batch open raises "Terrain update is not active", so keep the pair balanced - an early Return or Exit that skips the EndTerrainUpdate will bite you on the next frame's BeginTerrainUpdate. Box3D collision is not refreshed automatically; call RefreshPhysicsTerrain once after the batch rather than once per edit, because rebuilding a compressed height field is expensive enough to be visible.

See also: BeginTerrainUpdate, ModifyTerrain, ModifyTerrainHole, TerrainRebuiltChunks, RefreshPhysicsTerrain.

Example

; EndTerrainUpdate 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

phase#=0

While Not KeyDown(1)

    ; Animate a rippling patch inside one update batch each frame -
    ; EndTerrainUpdate commits it, rebuilding only the affected chunks
    phase=phase+5
    BeginTerrainUpdate terrain
    For z=48 To 79
        For x=48 To 79
            ripple#=Sin((x-48)*5.8)*Sin((z-48)*5.8)*Sin((x+z)*12+phase)*0.05
            ModifyTerrain terrain,x,z,0.2+Sin(x*10)*Cos(z*10)*0.12+ripple
        Next
    Next
    EndTerrainUpdate terrain

    ; 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   Esc: exit"
    Text 0,20,"EndTerrainUpdate commits the batch - only touched chunks rebuild"
    Text 0,40,"Chunks rebuilt this frame: "+TerrainRebuiltChunks(terrain)+" of 16"

    Flip

Wend

End

Index