Using 3D Perlin Noise with Roblox Terrain?

Hello, I’m looking to create procedural generation using 3D Perlin noise and the Terrain class, however, I’m not exactly sure where to start.

I’ve read a few tutorials on the devforum, however, they usually pertain to using Parts (which is not what I’m doing), and I’m utilizing the Terrain:WriteVoxels() method (I’ve never used it before), so parameters like occupancy are confusing for me to calculate and understand.

I’ve also followed the tutorial on the Parallel Lua page, but that doesn’t go into too much detail.


This is what my code for (calcuating) chunks currently looks like (it’s really messy):

@native local function CreateChunk(fromId: number?, coordX: number?, coordY: number?): (WorldChunk, number)
	local chunk: WorldChunk? = if fromId then 
		getChunk(fromId) 
		elseif not coordX or not coordY then 
		error("Coordinates X and Y (Z) must be provided.") 
		else nil::WorldChunk?
	
	if chunk then
		return chunk, chunk.id
	end
	
	local chunk = {
		materials = {},
		occupancy = {},

		x = -1,
		y = -1
	} :: WorldChunk
	
	local id = SharedTable.size(gen._chunks) + 1
	
	local width, height = getChunkSize()
	local floor = gen.height // 2
	chunk.id = id
	
	for x = 0, width - 1 do
		local t_mat = {} -- These are the required materials in a 4x64x4 array
		local t_occ = {} -- These are the required occupancies in a 4x64x4 array
		for y = 0, height - 1 do
			local c_occupancy = {}
			local c_materials = {}
			for z = 0, width - 1 do
				local pX = noise(0.25 * y + coordY::number, z)
				local pY = noise(0.25 * x + coordX::number, z)
				local pZ = noise(0.25 * x + coordX::number, 0.25 * y + coordY::number)
				local density = pX + pY + pZ
				local occupancy = if density < 0 then 1 else density -- idk
				local material = getMaterial(y, density) -- wip
				table.insert(c_occupancy, occupancy)
				table.insert(c_materials, material)
			end
			table.insert(t_occ, c_occupancy)
			table.insert(t_mat, c_materials)
		end
		table.insert(chunk.occupancy, t_occ)
		table.insert(chunk.materials, t_mat)
	end
	
	if id <= MAX_ID then
		storeChunk(chunk)
	end
	
	return chunk, id
end

If anyone have any ideas or suggestions, that’d be greatly appreciated. I may also be going about this the wrong way.

1 Like