Jump to content
  • entries
  • comments
  • views

Bulldozer Tool - Road building




I really wanted to use the spline tool to make roads because it is a powerful tool but it has a big inconvenient: It builds the spline as you want but then moves the terrain to pass it to the spline - this sounds first ok but using this especially on big maps, you end up with a terrain that shows artificial big too sharpened contours and hollowed areas where the road is going through.

To avoid this problem, you have to place a lot of spline pivots and nodes very carefully on the map, following the actual terrain movement. This takes hours and the result is disapointing if you forget one hill, it will shows this ugly sharpened cutted unnatural shapes.

That 's why I want to build a tool that operates on the terrain but with the feature to pass the roads to the terrain and not the opposite.

It should operates like a bulldozer does: Moving on the hills (and not cutting them!) the bulldozer builds a large passage practicable with a car.

Here in this little demo, you simply need to throw 2 pivots on the map - no matter the height where they are placed - and the script calculates the rest:

Script function for a straight road looks like that


function Script:TraceRouteDroite(entite1, entite2)

local pos= entite1:GetPosition(true)
local pos2= entite2:GetPosition(true)

    local oppose= pos2.z - pos.z
    local adjacente= pos2.x - pos.x + 0.0001        -- évite les divisions par 0
    local angle=math.atan(oppose/adjacente)                -- angle de route dans plan (x,z)    -- ANGLE EN RAD !!!!!
    if adjacente<0 then angle=angle+math.rad(180) end

local DonneesTerrain={}
local angle_N=angle+math.rad(90)
local i,j

    local longueur= math.sqrt(math.pow(adjacente, 2) + math.pow(oppose, 2))        -- Pythagore!!
System:Print("ANGLE DROITE="..math.deg(angle))

--==================================== Données ZWISCHEN Pfosten==============

    local longueur_Pfost= (3/4)*longueur
    local Pos_Pfostx = pos.x+(math.cos(angle)*longueur_Pfost) + (-self.Rayon*math.cos(angle_N))
    local Pos_Pfostz = pos.z+(math.sin(angle)*longueur_Pfost) + (-self.Rayon*math.sin(angle_N))
    local Pos_Pfosty = self.terr:GetElevation(Pos_Pfostx, Pos_Pfostz)

    self.Pfost1:SetPosition(Pos_Pfostx, Pos_Pfosty, Pos_Pfostz, true)     -- this adds the center of the next curve

-- debug==============
        local bille1=Model:Sphere()
-- =============== ===================SAVE THE SPLINE==============

    for j=0,longueur_Pfost,1 do    

--=================================== TREAT self.terrAIN:            -- TRACE LIGNE de route droite selon angle avec largeur !

    for j=0,longueur_Pfost,1 do                                

        for i= 0, 5, 0.5 do        -- largeur  de la route     Tracée latérale

            self.terr:SetElevation(512+pos.x + (math.cos(angle)*j) + (i*math.cos(angle_N)), 512+pos.z+(math.sin(angle)*j) +(i*math.sin(angle_N)), DonneesTerrain[j],true)

        -- smoothing:
            local zw_donnees=(DonneesTerrain[j]+DonneesTerrain[j+1])/2
            self.terr:SetElevation(512+pos.x + (math.cos(angle)*(j+0.333)) + (i*math.cos(angle_N)), 512+pos.z+(math.sin(angle)*(j+0.333)) +(i*math.sin(angle_N)), zw_donnees,true)
            self.terr:SetElevation(512+pos.x + (math.cos(angle)*(j+0.666)) + (i*math.cos(angle_N)), 512+pos.z+(math.sin(angle)*(j+0.666)) +(i*math.sin(angle_N)), zw_donnees,true)


--============================== DEBUG BILLES

local hauteur2=0
    for j=0,longueur_Pfost,1 do    
        for i= 0, 5, 1 do        -- largeur=4  de la route     Tracée latérale

            local bil=bille1:Instance()
        --    if i>0 then bil:SetColor(0,0,1) end
--            hauteur2=self.terr:GetElevation(pos.x+(math.cos(angle)*j) + i, pos.z+(math.sin(angle)*j)-i)    -- Rajout de "-i" pour le tracage
            bil:SetPosition(pos.x +(math.cos(angle)*j) + (i*math.cos(angle_N)), DonneesTerrain[j]+0.3, pos.z+(math.sin(angle)*j) + (i*math.sin(angle_N)),true)

--        System:Print("angle="..math.deg(angle).." /norm: "..math.deg(angle_N))




2) Building curves:

Code for curve looks like this:



Showcase: Just tell the editor where the roads has to pass through to get this: (placing a few pivots)


3) roads junctions are done ?

Always keeping the simpliest way:

  • With 3 pivots in the map, the script automaticly  generates the first road segment with 1 curve.
  • With 3 others pivots in the map, it builds the second road segment with 1 curve too.
  • Then only add the second road segment as junction entity in the first road segment script property and the segments will be correctly calculated and attached together:


4)  Texturing the roads:

The textures will be drawn between the little sphere, creating surfaces and vertex in an appropriate way.

The surfaces have to be joined ttogether from one road part to the next. Then only need to be shape.

Well the first road is done, throwing 2 * 3 pivots on the map, where you want the road to go through, then attach the 2 road segments together with drag and drop property entity.

More is not necessery to do...and the script calculates the rest, here a little showcase of the road:

  • Like 2


Recommended Comments

There are no comments to display.

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...