ScatterTerrain ( terrain,template,count[,seed][,min_scale#][,max_scale#][,max_slope#][,align_to_ground] )
Parameters
|
terrain - terrain entity to scatter over template - entity to copy; anything CopyEntity accepts count - how many copies to place; this is accepted placements, not attempts seed (optional) - seed for the layout; 0 uses a fixed built-in seed (default) min_scale (optional) - smallest uniform scale multiplier, must be above 0; 1 (default) max_scale (optional) - largest uniform scale multiplier, must not be below min_scale; 1 (default) max_slope (optional) - steepest ground that accepts a copy, in degrees from 0 to 90; 45 (default) align_to_ground (optional) - True tilts each copy to the ground normal, False stands them upright; False (default) |
Description
|
Returns a pivot holding copies of an entity scattered deterministically over a terrain. This is the forest command: point it at a tree, a boulder, a grass tuft or a ruined pillar and it makes count copies with CopyEntity, parents them all to a fresh pivot and returns that pivot. The copies are ordinary entities, so you can walk them with CountChildren and GetChild to tweak individuals, and one FreeEntity on the pivot clears the whole scatter. It is deterministic. The same terrain, arguments and seed always produce the same layout, so a world grown from a level seed comes back identical every time you load it. It uses its own generator rather than the global Blitz random stream, so scattering never disturbs the rest of your game's randomness and SeedRnd never rearranges your forest. Positions are chosen at random across the terrain's cell area. Height and a smoothly interpolated surface normal come from the height field itself rather than the level of detail currently being drawn, so trees sit properly on the ground at any camera distance. Candidates that land on a hole, or on ground steeper than max_slope, are rejected and another position is tried. Each copy gets a random yaw and a uniform scale picked between min_scale and max_scale; with align_to_ground on, its up axis is tilted to the ground normal first, which is what you want for rocks and bushes and exactly what you do not want for trees. The terrain's full world transform is respected, including parenting and non-uniform scale. Because the copies are normal entities they carry whatever the template carried - including its LOD table from AddEntityLOD and its EntityCullRange - and compatible copies are hardware-instanced automatically, so a few hundred identical trees can cost a handful of draw calls. Gotcha: the template is not hidden or freed for you, so it stands wherever you left it until you hide it. Scattering is a snapshot - later terrain edits do not move the copies, so free the pivot and scatter again if the ground changes. The search is bounded at roughly 32 attempts per requested copy, so an impossible slope limit returns fewer copies instead of hanging; it reports requested, placed and rejected counts to the debug log, which you will not see without a debugger, so compare CountChildren with count when the number matters. Bad arguments raise runtime errors: a negative count, a min_scale of 0 or less, a max_scale below min_scale, or a max_slope outside 0 to 90. See also: CopyEntity, CountChildren, TerrainIsHole, AddEntityLOD, EntityCullRange. |
Example
; ScatterTerrain 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 ; A little pine tree used as the scatter template tree=CreatePivot() trunk=CreateCylinder(8,True,tree) ScaleEntity trunk,0.12,0.5,0.12 PositionEntity trunk,0,0.5,0 EntityColor trunk,110,75,40 crown=CreateCone(8,True,tree) ScaleEntity crown,0.7,1.4,0.7 PositionEntity crown,0,1.7,0 EntityColor crown,40,110,45 ; Scatter 250 copies, rejecting slopes above 35 degrees seed=1234 group=ScatterTerrain(terrain,tree,250,seed,0.7,1.3,35,True) ; Hide the template so only the scattered copies show HideEntity tree sun_angle#=-30 While Not KeyDown(1) ; Space re-scatters the forest with a new seed If KeyHit(57) FreeEntity group seed=seed+1 group=ScatterTerrain(terrain,tree,250,seed,0.7,1.3,35,True) EndIf ; The sun slowly circles so the hills' shading shifts sun_angle=sun_angle+0.2 RotateEntity light,50,sun_angle,0 ; 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: re-scatter Esc: exit" Text 0,20,"ScatterTerrain(terrain,tree,250,"+seed+",0.7,1.3,35,True)" Text 0,40,"Trees placed: "+CountChildren(group)+" (same seed = same forest)" Flip Wend End
Index