Methods for mirroring terrain?

I don’t have any other ideas than redoing all my terrain in parts, reflecting it with the stravant reflection plugin and converting every part into terrain. Is there any better method?

Yes there is a way of doing this! It’s quite simple, in the terrain menu, go the the Region tab, click the Select button, and select the terrain you want to mirror/duplicate. Next, you want to select the Copy button, and then the Paste button. Use the move tool to move the terrain where you would like it, and then you can rotate it. Here’s a video showcasing the process.

5 Likes

well, that doesn’t really get the desired mirror that I want with my terrain. the method your using isn’t a mirror at all, it’s just flipping the terrain. but, thank you for the response.

this here would be a mirror.
https://gyazo.com/a220c1856596ae020a645d24607ef58e

this would be flipping the terrain
https://gyazo.com/4fb7aff79045f1fdbe3cf3846154449b

What you can do is just duplicate it section by section. For example, in your first image you can select that giant square grassy terrain on the bottom, duplicate, and move it into position at the other side. Then repeat with each bump / hill / terrain feature to create a “mirror” effect. It’s slow and tedious but probably your only option.

You could try running this script

local function loadRegionFromPart(part, mirrorx, mirrory, mirrorz)
	local region = Region3.new(part.Position - part.Size/2, part.Position + part.Size/2):ExpandToGrid(4)
	local materials, occupancies = game.Workspace.Terrain:ReadVoxels(region, 4)

	local size = materials.Size
	
	local om = {}
	local oo = {}
	
	for x = 1, size.X, 1 do
		local xm = mirrorx and size.X+1-x or x
		table.insert(om, {})
		table.insert(oo, {})
		
		for y = 1, size.Y, 1 do
			local ym = mirrory and size.Y+1-y or y
			table.insert(om[#om], {})
			table.insert(oo[#oo], {})
			
			
			for z = 1, size.Z, 1 do
				local zm = mirrorz and size.Z+1-z or z
				table.insert(om[#om][#om[#om]], occupancies[xm][ym][zm])
				table.insert(oo[#oo][#oo[#oo]], materials[xm][ym][zm])
			end
		end
	end
	
	return {oo, om}
end


local function WriteRegionFromLoadData(part, data)
	local region = Region3.new(part.Position - part.Size/2, part.Position + part.Size/2):ExpandToGrid(4)
	game:GetService("Workspace").Terrain:WriteVoxels(region, 4, data[1], data[2])
end

local function MirrorTerrainToPlace(mirrorFromPart, mirrorToPart, mirrorx, mirrory, mirrorz)
	local d = loadRegionFromPart(mirrorFromPart, mirrorx, mirrory, mirrorz)
	WriteRegionFromLoadData(mirrorToPart, d)
end

MirrorTerrainToPlace(game.Workspace.MirrorFrom, game.Workspace.MirrorTo, true, false, false)

The very last line is the only thing you need to change. You need a part that covers exactly what you want to clone as the first parameter. Duplicate that part (needs to be the exact same size) as the second parameter placing it where it needs to output. Then the next 3 arguments are true or false. True if you want it to mirror on that axis, and false if not. It’s ordered in X,Y,Z. Currently the code mirrors only the X axis since it’s true, nil, nil. Depending on where your parts are positioned the code might error. My parts were aligned in 4x4 grid, but when unaligned in a certain way it errored. I think that’s because it was exactly in the middle, which could probably be solved in the code, but it works to also offset the parts by a small amount. And I have no clue how large the region can be before the code will error. I know if it’s to large it will error saying it’s too large. That could be fixed by modifying this to load it by chunks, but I’m too lazy to do that rn.

7 Likes

thank you so much, tlr22. I’ve found this extremely useful. saved me so much time. : ) huge life savior.

1 Like