Need help with creating random terrain of high quality

Hello everyone! I started working on a little project a few days ago, in Blender 2.5’s game engine. I’m trying to create a large open world that the player can walk on, with large quality terrain. Tricky part is, I want my terrain to be auto-generated whenever I run the engine. In a way that’s both of high quality, does not reduce FPS by too much, and takes a reasonable amount of time to generate (not block the engine for several seconds).

What happened so far: As discussed in another topic, someone first offered a script that could randomize the vertices of a plane. It wasn’t usable for my purpose however, because it was too slow to generate, too spikey, and collisions didn’t work properly either. I then found a system made by someone else which is just perfect for what I need. But, it uses a script that only works in Blender 2.4, and not in 2.5 any more. Lastly, I managed to get a texture applied dynamically to a patch mesh yesterday. I did that by using an auto-generated cloud texture in Blender, and applying it as a Displacement modifier to the subdivided flat plane. The terrain is of beautiful quality and player collisions work well too… even if FPS is a bit low for my wishes. What I got so far this way can be seen over here (two displacement modifiers using different generated textures). Still, those textures are not re-created and randomized each run… which is what I was hoping could be done, to get a fully new terrain each run.

Here is the 2.4 script I mentioned above, that won’t work in 2.5 any more (not mine): http://pastebin.com/zitKiHaH I would appreciate it if someone could perhaps adapt it to 2.5. Or, if someone could offer any script that creates a random cloud texture, and can apply it to the texture the Displacement modifier of the terrain plane uses. Thanks :slight_smile:

I would suggest writing your own as it gives you the most control, or looking at the API and modifying the script yourself. I wrote a quick script for you to randomize the vertex z locations on a plane, as well as randomize the color a little bit just for fun.

Just add a plane, add a material, go to modifiers and add the subdivision surface modifier to make sure there are plenty of vertices, then scale up the plane size for visibility. Link this script up to a keyboard sensor or something on the plane to check it out.

import bge
import random

PeakMin = 0
PeakMax = 0.075
NullMin = 0
NullMax = 0.1
#MaxNumPeaks = 30
#MaxNumNulls = 30
VertexPercentPeaks = 0.15
VertexPercentNulls = 0.15

co = bge.logic.getCurrentController()
obj = co.owner
mesh = obj.meshes[0]
mat = mesh.materials[0]
verts = mesh.getVertexArrayLength(0)

numpeaks = random.randint(0,int(VertexPercentPeaks*verts))
#numpeaks = random.randint(0,MaxNumPeaks)
peaklocs = []
numnulls = random.randint(0,int(VertexPercentNulls*verts))
#numnulls = random.randint(0,MaxNumNulls)
nulllocs = []

for ind in range(numpeaks):
    peaklocs.append(random.randint(0,verts))
for ind in range(numnulls):
    nulllocs.append(random.randint(0,verts))

for ind in range(verts):
    vertex = mesh.getVertex(0,ind)
    vertex.color = [0,(.5+.2*random.random()),0,1] #Green

for peak in peaklocs:
    vertex = mesh.getVertex(0,peak)
    vertex.z = PeakMax*random.random()
    
for null in nulllocs:
    vertex = mesh.getVertex(0,null)
    vertex.z = -NullMax*random.random()

You can do more of these same loops with things like “BigPeaks” or “BigNulls”, or run this script multiple times with lesser values using += on the vertex instead of =. There are many ways to tweak this until you are satisfied with the results. I’m not sure how the vertex indexing is done, but if you know then I would suggest raising vertices surrounding a peak by a random percentage of the peak value. Or select a polygon based on a vertex and use that to select other surrounding vertices.

Anyway, going from here to a terrain randomizer that you’re satisfied with shouldn’t be too difficult for you to do conceptually, using a combination of different scales of randomization, tweaking values, etc. should eventually get you where you’d like to be. The key from here to make the terrain not so jagged is finding how to select the vertices around a peak/null and setting those to quasi random values that will round out your terrain.

Thank you, OhSkyCake! I did all that and applied the script, though for some reason it doesn’t seem to work yet. I put the script in a text file, added a material to the plane, subdivided it, added a subsurf modifier, then added logics to the plane to run the script on key press. Is there anything else I need to do?

RandomMeshTest.blend (406 KB)

There shouldn’t be, that’s strange. Attached is a .blend file with my script that works fine for me, try this out and see if it works for you.

That does seem to work. However, it stops working once I apply the SubSurface modifier. And since I need my terrain to be smooth, I need to apply that too :frowning: Any idea how that can be fixed?

By SubSurface modifier, are you talking about the Subdivision Surface modifier? That’s just what I used to add more vertices, and I am able to apply it more without any issues. How would applying that smooth things out? Maybe I am misunderstanding you…

The subsurf modifier usually smooths all surfaces and makes them of higher quality. So I was hoping I could use it dynamically here, to get rid of the spikey effect on the run. I tried tweaking the script still, but it’s not smooth enough. Mostly because I think it randomizes all vertices, and creates spikes instead of smooth hills. Not sure if that can be helped.

Hmm. Well, it sounds like you’ll need to grab a vertex and drag it up randomly, but also drag up the surrounding vertices a percentage of that same amount, like a brush in Sculpt mode.

Try deforming the mesh using randomly generated perlin noise.

Ex.

Sure, but how? Does anyone have a 2.5 script that can do that?