Jump to content
  • entries
    39
  • comments
    81
  • views
    13,032

Creating hills + terrain + paint from script


Marcousik

1,929 views

 Share

Example:

991436339_Capturedcran(7).thumb.png.9e3d7227258a237a63214a17b6173bdc.png

 

I could strangely find nothing about terrain generation from script except for LE5... 

So here is an example that will run with LE4.6 on how you can generate 2 little  hills on a terrain and paint it from script. Can be usefull for games with random generated landscape.

The script I modified is from here: https://www.leadwerks.com/community/topic/15715-minimap-generator/?do=findComment&comment=104697

So first install the minimap shader to run this:

 

 

Quote

window = Window:Create("example",0,0,1600,900,Window.Titlebar+Window.Center)
context = Context:Create(window)
world = World:Create()
skybox = Texture:Load("Materials/Sky/skybox_texture.tex")
world:SetSkybox(skybox)
light = DirectionalLight:Create()
light:SetRotation(45,45,0)
window:HideMouse()

player = Prefab:Load("Prefabs/player/fpsplayer.pfb")
player:SetPosition(0,20,0)
camera = tolua.cast(player.script.camera, "Camera")
camera:SetMultisampleMode(8)

mm_size = 256.0 -- size of map 64
mm_zoom = 0.1
mm_toggle = 0
mm_shader = Shader:Load("Shaders/Drawing/drawing_minimap.shader")
mm_mask = Texture:Load("Materials/developer/trigger.tex")
mm_shader:SetVec2("terrain_size", Vec2(mm_size,mm_size)) --send terrain size to shader uniform
cur_buffer = Buffer:GetCurrent()
mm_buffer = Buffer:Create(1024,1024,1,0) -- can be any size but higher = better resolution

terraintex0 = Texture:Load("Materials/Grass/grass01.tex")
terraintex1 = Texture:Load("Materials/Rock//rockwall01.tex")
terraintex1_nrm = Texture:Load("Materials/Rock/rockwall01_dot3.tex")
terraintex1_disp = Texture:Load("Materials/Rock/rockwall01_disp.tex")

terrain = Terrain:Create(256)
terrain:SetScale(1,20,1)

local varx
local vary
local Posx={}
local Posy={}
 Posx[1]=150    -- hill 1 pos
 Posy[1]=100    

 Posx[2]=-15    -- hill 2 distance from hill 1
 Posy[2]=-5


local des
local des1
local hauteur=5        -- hill height 1
local hauteur2=10    -- hill height 2
local longueur=3
local largeur=1

    for varx=-50,50 do
        for vary=-50,50 do

                des=Math:Random(150,200)    -- intensity noise (0-200)
                des1=math.random()*0.75    -- height noise (0-2)

---------------------------------        <--used to build a hill---------->
            local HauteurTerrainButte1 = ((varx*varx*longueur)+(vary*vary*largeur))/-200

------------ = if over water level:
            if hauteur + HauteurTerrainButte1 > 0 then
------------------------------------------------------           <---- used to build noise-------------------->   
                terrain:SetElevation(Posx[1]+varx, Posy[1]+vary, ((math.sin(varx+des))*math.sin(vary+des)*des1)+ hauteur + HauteurTerrainButte1 , true)
            end
            
--        estimation of terrain elevation at second hill position:
            HauteurTerrainButte1 = (((varx+Posx[2])*(varx+Posx[2])*longueur)+((vary+Posx[2])*(vary+Posx[2])*largeur))/-200
            local HauteurTerrainButte2 = ((varx*varx*longueur)+(vary*vary*largeur*4))/-20

------  if over the elevation:
            if hauteur +hauteur2+ HauteurTerrainButte2 > hauteur + HauteurTerrainButte1 then 
                terrain:SetElevation(Posx[1]+varx+Posx[2], Posy[1]+vary+Posx[2], ((math.sin(varx+des))*math.sin(vary+des)*des1)+ hauteur+hauteur2 + HauteurTerrainButte2, true)
            end

        end
    end

terrain:UpdateNormals()

-- paint the ground: // only run well with 4 layers 0,1,2,3.
terrain:SetLayerTexture(0, terraintex0, 0)
terrain:SetLayerTexture(1, terraintex1, 0)        -- diffuse
terrain:SetLayerTexture(1, terraintex1_nrm, 1) -- normal
terrain:SetLayerTexture(1, terraintex1_disp, 2) -- disp
terrain:SetLayerSlopeConstraints(1, 25, 90, 5)
terrain:SetLayerAlpha(1,1)


while not window:KeyHit(Key.Escape) do
    if window:Closed() then return false end

    Time:Update()
    world:Update()
    world:Render()

--local CamPos=camera:GetPosition(true)
--System:Print("Code="..terrain:GetLayerAtPoint(01,01))

    if mm_toggle==0 then
        mm_toggle = 1
        camera_prev_mat = camera:GetMatrix()
        --calculate proper height based on camera's FOV
        mm_pos = math.tan((90-camera:GetFOV()/2)*math.pi/180) * (mm_size/2)
        camera:SetPosition(0,mm_pos,0)
        camera:SetRotation(90,0,0)
        mm_buffer:Enable()
        world:Render()
        minimap = mm_buffer:GetColorTexture(0)
        camera:SetMatrix(camera_prev_mat)
        cur_buffer:Enable()
    end

    if window:KeyHit(Key.Right) then mm_zoom = mm_zoom + 0.1 end
    if window:KeyHit(Key.Left) then mm_zoom = mm_zoom - 0.1 end
    mm_zoom = math.max(mm_zoom, 0.1)
    mm_zoom = math.min(mm_zoom, 1.0)
    
    context:SetBlendMode(1)
    context:SetColor(1,1,1,0.55)
    cur_shader = context:GetShader()
    context:SetShader(mm_shader)
    pos = player:GetPosition(true)
    mm_shader:SetVec2("player_pos", Vec2(pos.x,pos.z)) --send player's position to shader uniform
    mm_shader:SetVec2("zoom", Vec2(mm_zoom)) --send current zoom to shader uniform
    minimap:Bind(1)
    context:DrawImage(mm_mask,600,10,180,180)
    context:SetShader(cur_shader)
    context:SetColor(1,0,0,1)
    context:DrawRect(686,96,8,8,0,0)
    context:SetColor(1,1,1,1)
    context:DrawText(string.format("FPS: %.2f", Time:UPS()),2,2)
    context:DrawText("Player Position: "..player:GetPosition():ToString(),2,22)
    context:DrawText("Press LEFT/RIGHT Arrow Keys To Change Zoom",2,42)
    context:DrawText("Zoom: "..mm_zoom,2,62)
    context:SetBlendMode(0)
    context:Sync(true)
end

You can only handle 4 layers from the script: 0,1,2,3. More will have no effect.

 

1468156290_Capturedcran(10).thumb.png.80ee58547cfd60717a11718ea560c014.png

 

> Add this to create vegetation:

Quote

-- veget:
            terrain:AddVegetationLayer()
--System:Print("CountLayers="..terrain:CountVegetationLayers())

            HerbeRouge=terrain:GetVegetationLayer(0)
             HerbeRougeModel=Model:Load("Models/Nature/Plants/bush01.mdl")
            
            HerbeRouge:SetModel(HerbeRougeModel)
            HerbeRouge:SetSeed(100)
            HerbeRouge:SetViewDistance(200)

            HerbeRouge:SetSlopeConstraints(0, 20)    
            HerbeRouge:SetHeightConstraints(0, 300)    
            HerbeRouge:SetDensity(5)
            HerbeRouge:SetBillboardMode(false)
            HerbeRouge:SetShadowMode(1)

HerbeRougeModel:Release()

    for varx=-50,50 do
        for vary=-50,50 do

            HerbeRouge:SetVisibility(varx, vary, false)
        end
    end

 

  • Like 4
 Share

1 Comment


Recommended Comments

You can add multiple gradient noise generators to make different type of height maps. You can also subtract height gradually more  at the edges and make an island generator. 
In the library I used I used only one perlin noise, with different octaves and frequency of details in it. if you have less frequency hills will get larger on xz and if you have higher octaves you can get more hills and holes.

//EDIT
You can also generate Biomes / textures with https://en.wikipedia.org/wiki/Voronoi_diagram Voronoi.
basically use one texture ant interpolate between them.

  • Like 1
Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...