Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

What do I need to know to properly understand this? ( Terrain Generation )

Asked by
bloxxyz 274 Moderation Voter
10 years ago

I know a good amount of Lua, however some of the syntax and maths I do not seem to understand in this wiki article. I've tested the script and it works as described, however I want to make custom terrain myself and I do not understand it. I've tried messing around with it a bit but this confuses me. Any recommendations on wiki articles I can view to help me use this to the extent of helping me learn?

This is what I have trouble understanding, by the way: http://wiki.roblox.com/index.php?title=Terrain_Generation

Hope this isn't too much to ask, I'm not asking you to narrow down the whole article, just some pages or advice that can help me learn this better. Cheers! :)

0
If you want to avoid all that math which still wont get you exactly what you want, I suggest 3d modeling it, then importing it with a OBJ importing script. It's a easy way of avoiding that whole mess. Orlando777 315 — 10y

1 answer

Log in to vote
0
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
10 years ago

The concept of "terrain" in programming usually means generating some sort of "height map".

That is a map that takes a position along the horizontal plane (x, z) and turns it into a height.


There are some useful observations about the sorts of height maps you want when generating realistic terrain:

  • They are more or less smooth, meaning they aren't jagged
  • They are almost always continuous, meaning even when there are peaks / ridges, there isn't a vertical cliff
  • They are more or less irregular -- there isn't some visible repeating pattern

So the goal can usually be stated as, *make a function h(x, z) that gives me a height for a part positioned at Vector3.new(x, __, z).

Since we want it to be wavy, we could take advantage of sine and cosine;

Simple Smooth Functions

function h1(x, z)
    x = x / 20 -- Sine and Cosine want relatively close
    -- numbers; x and z in studs will make it way too noisy
    z = z / 20
    return (math.sin(x) + math.sin(z)) * 20 -- -40 to 40 studs
end

You'll get a wavy pattern if you use something like that.

Here's a different one:

function h2(x, z)
    x, z = x / 20, z / 20
    return math.sin(x) * math.cos(z) * 20 -- -40 to 40 studs
end

Interestingly, you can also add these two functions to get something that has a bit of both features:

function h3(x, z)
    return (h1(x, z) + h2(x, z) ) /2
end

Fractal Noise

With this in mind, there is the concept of fractal noise which is similar to Perlin noise.

We use a simple noise function over and over but at different scales, e.g.,

function h(x, z)
    local weight = 0
    local sum = 0
    for i = 1, 10 do
        local w = math.exp(-i / 5)
        local f = h3(x * i, z * i);
        sum = sum + f * w
        weight = weight + w
    end
    return sum / weight
end

Node Based Smooth Noise

Another basic approach would be to place "nodes" which control the terrain -- "higher" nodes make mountains, lower ones valleys.

When you put enough mixed together, then you get a messy but smoothish result -- which is ideal for nice terrain.

Here is an inefficient, but simple algorithm. It consists of generating random points; the height function is then a weighted average of all of the values of the random points, where the weight of each decreases when you get further from it.


local points = {}; while #points < 100 do table.insert(points, {x = math.random() * 100, y = math.random() * 100; v = math.random()}) end -- Only will works nicely for points in the box [0, 100] x [0, 100] function h(x, z) local query = Vector3.new(x, 0, z); local totalWeight = 0; local total = 0; for _, point in pairs(points) do local position = Vector3.new(point.x, 0, point.y); local distance = position - query.magnitude; local weight = math.exp(-distance^2 / 1000.0); totalWeight = totalWeight + weight total = total + weight * point.v end return total / totalWeight end
Ad

Answer this question