Skip to content

Instantly share code, notes, and snippets.

@Domiii
Last active November 19, 2021 00:10
Show Gist options
  • Save Domiii/5b5ca24513314ef1c7f798c2d2d16493 to your computer and use it in GitHub Desktop.
Save Domiii/5b5ca24513314ef1c7f798c2d2d16493 to your computer and use it in GitHub Desktop.
Import real world terrain into Roblox
--[[
Steps:
1. Download heightmap Bitmap
e.g. from terrain.party: http://terrain.party/api/export?name=guarda&box=10.186055,46.850130,10.080975,46.778264)
e.g. from earthe
Data Sets: NASA LPDAAC Collections -> NASA SRTM (SRTM 3) Collections
2. Use this site to convert BMP to Lua: https://codepen.io/Domiii/pen/oMJvoJ?editors=0010
3. Copy the final Lua code to workspace.TerrainPixels (ModuleScript)
4. Run this script!
]]
local MaxHeight = 1800
local VoxelSize = 1
local MaxPixelValue = 255
local Resolution = 1 -- only use every 4th pixel
-- xLen = 100
-- zLen = 100
local VoxelVectorSize = Vector3.new(VoxelSize, VoxelSize, VoxelSize)
local origin = Vector3.new(0, 0, 0)
function GenerateMountain(origin, xLen, zLen, height)
for i = 1, xLen do
for j = 1, zLen do
local y = math.random() * height
--print(y)
for k = 1, y do
--local size = Vector3.new(Amount*Amount-(i*10),Y*(i*2),Amount*Amount-(i*10))
--local pos = pos + Vector3.new(i * VoxelSize, k*VoxelSize, j*VoxelSize)
local pos = origin + Vector3.new(i*VoxelSize, k*VoxelSize, j*VoxelSize)
game.Workspace.Terrain:FillBlock(CFrame.new(pos), VoxelVectorSize, Enum.Material.Rock)
end
end
end
end
local cancelName = 'TerrainCancel'
local guiName = 'TerrainGenStatusGui'
local cancelledRef
local gui
local statusLabel
function Cleanup()
if game.StarterGui:FindFirstChild(guiName) then
game.StarterGui:FindFirstChild(guiName):Destroy()
end
if workspace:FindFirstChild(cancelName) then
workspace:FindFirstChild(cancelName):Destroy()
end
end
function GetProgressPercent(current, max)
return current / max * 100
end
function UpdateStatus(current, max)
local progressPct = GetProgressPercent(current, max)
statusLabel.Text = tostring(math.floor(progressPct + 0.5)) .. '%'
end
function ShowTerrainGui()
gui = Instance.new('ScreenGui')
gui.Name = guiName
statusLabel = Instance.new('TextLabel')
statusLabel.Parent = gui
statusLabel.Size = UDim2.new(1, 0, 0, 30)
gui.Parent = game.StarterGui
cancelledRef = workspace:FindFirstChild(cancelName)
if not cancelledRef then
cancelledRef = Instance.new('BoolValue')
cancelledRef.Name = cancelName
cancelledRef.Parent = workspace
end
cancelledRef.Value = false
-- select the Cancel object
local select = { cancelledRef }
game.Selection:Set(select)
end
function CheckCancel()
if cancelledRef and cancelledRef.Value then
print('Terrain Generation Cancelled')
Cleanup()
return true
end
return false
end
function GetMaterial(yNormalized)
local material
if yNormalized < 0.4 then
material = Enum.Material.Grass
elseif yNormalized < 0.8 then
material = Enum.Material.Rock
else
material = Enum.Material.Snow
end
return material
end
function GenTerrainFromHeightmap(origin)
local pixels = require(workspace.TerrainPixels:Clone())
local xLen = #pixels
local zLen = #pixels[1]
Cleanup()
ShowTerrainGui()
workspace.Terrain:Clear()
for i = 1, xLen, Resolution do
local row = pixels[i]
for j = 1, zLen, Resolution do
local px = row[j]
local yNormalized = px / MaxPixelValue
local material = GetMaterial(yNormalized)
y = yNormalized * MaxHeight
--for k = 1, y do
local pos = origin + Vector3.new(i*VoxelSize, 0, j*VoxelSize)
local size = Vector3.new(VoxelSize, y * VoxelSize, VoxelSize)
game.Workspace.Terrain:FillBlock(CFrame.new(pos), size, material)
--end
end
if CheckCancel() then return end
UpdateStatus(i, xLen)
wait()
end
print('Terrain Generation Finished!')
Cleanup()
end
--GenTerrainFromHeightmap(origin, pixels)
--GenerateMountain(origin, xLen, zLen, height)
function GenTerrainBetweenParts(basePart)
Cleanup()
ShowTerrainGui()
workspace.Terrain:Clear()
local material = Enum.Material.Grass
local size = basePart.Size
local pos1 = basePart.Position - size / 2
local pos2 = pos1 + size
local y = basePart.Position.Y + size.Y
--local y = (pos1.Y + pos2.Y) / 2
local up = Vector3.new(0, 1, 0)
for z = pos1.Z, pos2.Z do
for x = pos1.X, pos2.X do
local origin = Vector3.new(x, y, z)
local ray = Ray.new(origin, origin + up * 100000)
local terrainCellsAreCubes = false
local ignoreWater = true
local part, pos, normal, material2 = workspace:FindPartOnRay (
ray,
basePart,
terrainCellsAreCubes,
ignoreWater
)
--print(x,y,z, part, pos, normal, material2)
-- local p = Instance.new('Part')
-- p.Shape = Enum.PartType.Ball
-- p.Position = origin
-- p.Parent = workspace.Tmp
--if part then
local blockSize = Vector3.new(1, (pos - origin).Y, 1)
-- NOTE: basePos is the center of the block!
local basePos = origin + blockSize/2
game.Workspace.Terrain:FillBlock(CFrame.new(basePos), blockSize, material)
--end
end
if CheckCancel() then return end
UpdateStatus(z-pos1.Z, pos2.Z-pos1.Z)
wait()
end
print('Terrain Generation Finished!')
Cleanup()
end
GenTerrainBetweenParts(workspace.Baseplate)
@hampee
Copy link

hampee commented Nov 21, 2018

It says
The current identity (2) cannot Set (lacking permission 1)
What is wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment