Simple Cone Based Terrain Generation

[quote] Try drawing circles of random depth, width, and position. The closer a tile is to the center of the circle, the higher/lower that terrain is made. It doesn’t produce the most beautiful terrain, but it is coded in just a few minutes. It will look something like this:

Terrain Generator - Roblox [/quote]
Original thread

I’m in need of a terrain generation algorithm. After playing with a few real methods like using Perlin noise, I wanted to try to make something myself that used a simpler more layman approach. My approach is inspired by this post from HatHelper. The way I went about it may or may not be exactly what he had in mind. I didn’t really expect too much quality out of this approach, but given the right parameters, I’ve been pleasantly surprised. The results are more than acceptable for my needs.

When working on this, I found it more useful to think of random cones rather than the circles that HatHelper described. The method generates a number of cones, based on a parameter coneDensity, in random positions of random base diameters and heights, based on parameters coneMaxRadius, coneMinRadius, coneMaxHeight, and coneMinHeight. If all these cones are spread in the workspace, the elevation of each point is defined as the sum of the heights of the points on the cones at that point.

Here’s the code:

function coneMap(x,y,coneDensity,coneMinRadius,coneMaxRadius,coneMinHeight,coneMaxHeight)
	local numCones=x*y*coneDensity
	
	local cones={}
	local coneModels={}
	
	for i=1,numCones do
		cones[i]={}
		cones[i]['PosX']=math.random()*x
		cones[i]['PosY']=math.random()*y
		cones[i]['Radius']=math.random()*(coneMaxRadius-coneMinRadius)+coneMinRadius
		cones[i]['Height']=math.random()*(coneMaxHeight-coneMinHeight)+coneMinHeight
	end
	
	local result={}
	for px=1,x do
		result[px]={}
		for py=1,y do
			
			result[px][py]=0
			
			for _, cone in pairs(cones) do
				local dist=math.sqrt((px-cone['PosX'])^2+(py-cone['PosY'])^2)
				if dist<cone['Radius'] then
					
					result[px][py]=result[px][py]+(cone['Radius']-dist)/cone['Radius']*cone['Height']
					
				end
			end
		end
	end
	
	return result, coneModels
end


size=3

pb=Instance.new("Part")
pb.BrickColor=BrickColor.new("Bright green")
pb.Anchored=true
pb.Size=Vector3.new(1,1,1)*size
pb.TopSurface="Smooth"

terrainMap,coneModels=coneMap(100,100,0.01,10,26,-0.5,3)
		
for x=1,#terrainMap do
	for z=1,#terrainMap[x] do
		p=pb:clone()
		p.Position=Vector3.new(x,10+terrainMap[x][z],z)*size
		p.Parent=workspace
	end
end

And here’s how it goes down. If we set the ConeDensity really low, such that only a few cones are generated, we see that exactly. My function parameters are coneMap(xSize, ySize, coneDensity, coneMinRadius, coneMaxRadius, coneMinHeight, coneMaxHeight)

And if we bring ConeDensity up a bit, we see how cones that get generated on top of each other will cause terrain to stack up at those points.

A bit more playing with the parameters and we start to get something a bit more presentable.

I found that in addition to positive cones, you can also generate negative cones, by setting minConeSize to a value less than zero. This will create subtractive cones, so they’ll create craters.

I’m pretty satisfied with these results, and I’ll probably use this method if I can come up with a better alternative to a box terrain representation of the heightmap.

Here’s a place to play with it. I also added an exploration mode here, where you can walk and terrain is continuously generated in your path. Like Minecraft.

1 Like

While I personally love hand-building instead of generating, I do like this a lot, and I definitely enjoy how it’s coupled to a loading and unloading world. You could possibly edit the brick length and width to create different “Biome” landscapes, which would be neat (for example larger square shapes for a flatter, larger map, or strips of rectangles to recreate a desert and sand dunes). I like it :slight_smile:

EDIT: for a desert themed map you’d probably have to do an elliptic shape instead of cones