mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 22:35:43 +08:00
458 lines
21 KiB
Lua
458 lines
21 KiB
Lua
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
|
|
|
-- Based on voxel terrain generator by Stickmasterluke
|
|
|
|
local kSelectedBiomes = {
|
|
['Mountains'] = true,
|
|
['Canyons'] = true,
|
|
['Dunes'] = true,
|
|
['Arctic'] = true,
|
|
['Lavaflow'] = true,
|
|
['Hills'] = true,
|
|
['Plains'] = true,
|
|
['Marsh'] = true,
|
|
['Water'] = true,
|
|
}
|
|
|
|
---------Directly used in Generation---------
|
|
local masterSeed = 618033988
|
|
local mapWidth = 32
|
|
local mapHeight = 32
|
|
local biomeSize = 16
|
|
local generateCaves = true
|
|
local waterLevel = .48
|
|
local surfaceThickness = .018
|
|
local biomes = {}
|
|
---------------------------------------------
|
|
|
|
local rock = "Rock"
|
|
local snow = "Snow"
|
|
local ice = "Glacier"
|
|
local grass = "Grass"
|
|
local ground = "Ground"
|
|
local mud = "Mud"
|
|
local slate = "Slate"
|
|
local concrete = "Concrete"
|
|
local lava = "CrackedLava"
|
|
local basalt = "Basalt"
|
|
local air = "Air"
|
|
local sand = "Sand"
|
|
local sandstone = "Sandstone"
|
|
local water = "Water"
|
|
|
|
math.randomseed(6180339)
|
|
local theseed={}
|
|
for i=1,999 do
|
|
table.insert(theseed,math.random())
|
|
end
|
|
|
|
local function getPerlin(x,y,z,seed,scale,raw)
|
|
local seed = seed or 0
|
|
local scale = scale or 1
|
|
if not raw then
|
|
return math.noise(x/scale+(seed*17)+masterSeed,y/scale-masterSeed,z/scale-seed*seed)*.5 + .5 -- accounts for bleeding from interpolated line
|
|
else
|
|
return math.noise(x/scale+(seed*17)+masterSeed,y/scale-masterSeed,z/scale-seed*seed)
|
|
end
|
|
end
|
|
|
|
local function getNoise(x,y,z,seed1)
|
|
local x = x or 0
|
|
local y = y or 0
|
|
local z = z or 0
|
|
local seed1 = seed1 or 7
|
|
local wtf=x+y+z+seed1+masterSeed + (masterSeed-x)*(seed1+z) + (seed1-y)*(masterSeed+z) -- + x*(y+z) + z*(masterSeed+seed1) + seed1*(x+y) --x+y+z+seed1+masterSeed + x*y*masterSeed-y*z+(z+masterSeed)*x --((x+y)*(y-seed1)*seed1)-(x+z)*seed2+x*11+z*23-y*17
|
|
return theseed[(math.floor(wtf%(#theseed)))+1]
|
|
end
|
|
|
|
local function thresholdFilter(value, bottom, size)
|
|
if value <= bottom then
|
|
return 0
|
|
elseif value >= bottom+size then
|
|
return 1
|
|
else
|
|
return (value-bottom)/size
|
|
end
|
|
end
|
|
|
|
local function ridgedFilter(value) --absolute and flip for ridges. and normalize
|
|
return value<.5 and value*2 or 2-value*2
|
|
end
|
|
|
|
local function ridgedFlippedFilter(value) --unflipped
|
|
return value < .5 and 1-value*2 or value*2-1
|
|
end
|
|
|
|
local function advancedRidgedFilter(value, cutoff)
|
|
local cutoff = cutoff or .5
|
|
value = value - cutoff
|
|
return 1 - (value < 0 and -value or value) * 1/(1-cutoff)
|
|
end
|
|
|
|
local function fractalize(operation,x,y,z, operationCount, scale, offset, gain)
|
|
local operationCount = operationCount or 3
|
|
local scale = scale or .5
|
|
local offset = 0
|
|
local gain = gain or 1
|
|
local totalValue = 0
|
|
local totalScale = 0
|
|
for i=1, operationCount do
|
|
local thisScale = scale^(i-1)
|
|
totalScale = totalScale + thisScale
|
|
totalValue = totalValue + (offset + gain * operation(x,y,z,i))*thisScale
|
|
end
|
|
return totalValue/totalScale
|
|
end
|
|
|
|
local function mountainsOperation(x,y,z,i)
|
|
return ridgedFilter(getPerlin(x,y,z,100+i,(1/i)*160))
|
|
end
|
|
|
|
local canyonBandingMaterial = {rock,mud,sand,sand,sandstone,sandstone,sandstone,sandstone,sandstone,sandstone,}
|
|
|
|
local function findBiomeInfo(choiceBiome,x,y,z,verticalGradientTurbulence)
|
|
local choiceBiomeValue = .5
|
|
local choiceBiomeSurface = grass
|
|
local choiceBiomeFill = rock
|
|
if choiceBiome == 'City' then
|
|
choiceBiomeValue = .55
|
|
choiceBiomeSurface = concrete
|
|
choiceBiomeFill = slate
|
|
elseif choiceBiome == 'Water' then
|
|
choiceBiomeValue = .36+getPerlin(x,y,z,2,50)*.08
|
|
choiceBiomeSurface =
|
|
(1-verticalGradientTurbulence < .44 and slate)
|
|
or sand
|
|
elseif choiceBiome == 'Marsh' then
|
|
local preLedge = getPerlin(x+getPerlin(x,0,z,5,7,true)*10+getPerlin(x,0,z,6,30,true)*50,0,z+getPerlin(x,0,z,9,7,true)*10+getPerlin(x,0,z,10,30,true)*50,2,70) --could use some turbulence
|
|
local grassyLedge = thresholdFilter(preLedge,.65,0)
|
|
local largeGradient = getPerlin(x,y,z,4,100)
|
|
local smallGradient = getPerlin(x,y,z,3,20)
|
|
local smallGradientThreshold = thresholdFilter(smallGradient,.5,0)
|
|
choiceBiomeValue = waterLevel-.04
|
|
+preLedge*grassyLedge*.025
|
|
+largeGradient*.035
|
|
+smallGradient*.025
|
|
choiceBiomeSurface =
|
|
(grassyLedge >= 1 and grass)
|
|
or (1-verticalGradientTurbulence < waterLevel-.01 and mud)
|
|
or (1-verticalGradientTurbulence < waterLevel+.01 and ground)
|
|
or grass
|
|
choiceBiomeFill = slate
|
|
elseif choiceBiome == 'Plains' then
|
|
local rivulet = ridgedFlippedFilter(getPerlin(x+getPerlin(x,y,z,17,40)*25,0,z+getPerlin(x,y,z,19,40)*25,2,200))
|
|
local rivuletThreshold = thresholdFilter(rivulet,.01,0)
|
|
|
|
local rockMap = thresholdFilter(ridgedFlippedFilter(getPerlin(x,0,z,101,7)),.3,.7) --rocks
|
|
* thresholdFilter(getPerlin(x,0,z,102,50),.6,.05) --zoning
|
|
|
|
choiceBiomeValue = .5 --.51
|
|
+getPerlin(x,y,z,2,100)*.02 --.05
|
|
+rivulet*.05 --.02
|
|
+rockMap*.05 --.03
|
|
+rivuletThreshold*.005
|
|
|
|
local verticalGradient = 1-((y-1)/(mapHeight-1))
|
|
local surfaceGradient = verticalGradient*.5 + choiceBiomeValue*.5
|
|
local thinSurface = surfaceGradient > .5-surfaceThickness*.4 and surfaceGradient < .5+surfaceThickness*.4
|
|
choiceBiomeSurface =
|
|
(rockMap>0 and rock)
|
|
or (not thinSurface and mud)
|
|
or (thinSurface and rivuletThreshold <=0 and water)
|
|
or (1-verticalGradientTurbulence < waterLevel-.01 and sand)
|
|
or grass
|
|
choiceBiomeFill =
|
|
(rockMap>0 and rock)
|
|
or sandstone
|
|
elseif choiceBiome == 'Canyons' then
|
|
local canyonNoise = ridgedFlippedFilter(getPerlin(x,0,z,2,200))
|
|
local canyonNoiseTurbed = ridgedFlippedFilter(getPerlin(x+getPerlin(x,0,z,5,20,true)*20,0,z+getPerlin(x,0,z,9,20,true)*20,2,200))
|
|
local sandbank = thresholdFilter(canyonNoiseTurbed,0,.05)
|
|
local canyonTop = thresholdFilter(canyonNoiseTurbed,.125,0)
|
|
local mesaSlope = thresholdFilter(canyonNoise,.33,.12)
|
|
local mesaTop = thresholdFilter(canyonNoiseTurbed,.49,0)
|
|
choiceBiomeValue = .42
|
|
+getPerlin(x,y,z,2,70)*.05
|
|
+canyonNoise*.05
|
|
+sandbank*.04 --canyon bottom slope
|
|
+thresholdFilter(canyonNoiseTurbed,.05,0)*.08 --canyon cliff
|
|
+thresholdFilter(canyonNoiseTurbed,.05,.075)*.04 --canyon cliff top slope
|
|
+canyonTop*.01 --canyon cliff top ledge
|
|
|
|
+thresholdFilter(canyonNoiseTurbed,.0575,.2725)*.01 --plane slope
|
|
|
|
+mesaSlope*.06 --mesa slope
|
|
+thresholdFilter(canyonNoiseTurbed,.45,0)*.14 --mesa cliff
|
|
+thresholdFilter(canyonNoiseTurbed,.45,.04)*.025 --mesa cap
|
|
+mesaTop*.02 --mesa top ledge
|
|
choiceBiomeSurface =
|
|
(1-verticalGradientTurbulence < waterLevel+.015 and sand) --this for biome blending in to lakes
|
|
or (sandbank>0 and sandbank<1 and sand) --this for canyonbase sandbanks
|
|
--or (canyonTop>0 and canyonTop<=1 and mesaSlope<=0 and grass) --this for grassy canyon tops
|
|
--or (mesaTop>0 and mesaTop<=1 and grass) --this for grassy mesa tops
|
|
or sandstone
|
|
choiceBiomeFill = canyonBandingMaterial[math.ceil((1-getNoise(1,y,2))*10)]
|
|
elseif choiceBiome == 'Hills' then
|
|
local rivulet = ridgedFlippedFilter(getPerlin(x+getPerlin(x,y,z,17,20)*20,0,z+getPerlin(x,y,z,19,20)*20,2,200))^(1/2)
|
|
local largeHills = getPerlin(x,y,z,3,60)
|
|
choiceBiomeValue = .48
|
|
+largeHills*.05
|
|
+(.05
|
|
+largeHills*.1
|
|
+getPerlin(x,y,z,4,25)*.125)
|
|
*rivulet
|
|
local surfaceMaterialGradient = (1-verticalGradientTurbulence)*.9 + rivulet*.1
|
|
choiceBiomeSurface =
|
|
(surfaceMaterialGradient < waterLevel-.015 and mud)
|
|
or (surfaceMaterialGradient < waterLevel and ground)
|
|
or grass
|
|
choiceBiomeFill = slate
|
|
elseif choiceBiome == 'Dunes' then
|
|
local duneTurbulence = getPerlin(x,0,z,227,20)*24
|
|
local layer1 = ridgedFilter(getPerlin(x,0,z,201,40))
|
|
local layer2 = ridgedFilter(getPerlin(x/10+duneTurbulence,0,z+duneTurbulence,200,48))
|
|
choiceBiomeValue = .4+.1*(layer1 + layer2)
|
|
choiceBiomeSurface = sand
|
|
choiceBiomeFill = sandstone
|
|
elseif choiceBiome == 'Mountains' then
|
|
local rivulet = ridgedFlippedFilter(getPerlin(x+getPerlin(x,y,z,17,20)*20,0,z+getPerlin(x,y,z,19,20)*20,2,200))
|
|
choiceBiomeValue = -.4 --.3
|
|
+fractalize(mountainsOperation,x,y/20,z, 8, .65)*1.2
|
|
+rivulet*.2
|
|
choiceBiomeSurface =
|
|
(verticalGradientTurbulence < .275 and snow)
|
|
or (verticalGradientTurbulence < .35 and rock)
|
|
or (verticalGradientTurbulence < .4 and ground)
|
|
or (1-verticalGradientTurbulence < waterLevel and rock)
|
|
or (1-verticalGradientTurbulence < waterLevel+.01 and mud)
|
|
or (1-verticalGradientTurbulence < waterLevel+.015 and ground)
|
|
or grass
|
|
elseif choiceBiome == 'Lavaflow' then
|
|
local crackX = x+getPerlin(x,y*.25,z,21,8,true)*5
|
|
local crackY = y+getPerlin(x,y*.25,z,22,8,true)*5
|
|
local crackZ = z+getPerlin(x,y*.25,z,23,8,true)*5
|
|
local crack1 = ridgedFilter(getPerlin(crackX+getPerlin(x,y,z,22,30,true)*30,crackY,crackZ+getPerlin(x,y,z,24,30,true)*30,2,120))
|
|
local crack2 = ridgedFilter(getPerlin(crackX,crackY,crackZ,3,40))*(crack1*.25+.75)
|
|
local crack3 = ridgedFilter(getPerlin(crackX,crackY,crackZ,4,20))*(crack2*.25+.75)
|
|
|
|
local generalHills = thresholdFilter(getPerlin(x,y,z,9,40),.25,.5)*getPerlin(x,y,z,10,60)
|
|
|
|
local cracks = math.max(0,1-thresholdFilter(crack1,.975,0)-thresholdFilter(crack2,.925,0)-thresholdFilter(crack3,.9,0))
|
|
|
|
local spires = thresholdFilter(getPerlin(crackX/40,crackY/300,crackZ/30,123,1),.6,.4)
|
|
|
|
choiceBiomeValue = waterLevel+.02
|
|
+cracks*(.5+generalHills*.5)*.02
|
|
+generalHills*.05
|
|
+spires*.3
|
|
+((1-verticalGradientTurbulence > waterLevel+.01 or spires>0) and .04 or 0) --This lets it lip over water
|
|
|
|
choiceBiomeFill = (spires>0 and rock) or (cracks<1 and lava) or basalt
|
|
choiceBiomeSurface = (choiceBiomeFill == lava and 1-verticalGradientTurbulence < waterLevel and basalt) or choiceBiomeFill
|
|
elseif choiceBiome == 'Arctic' then
|
|
local preBoundary = getPerlin(x+getPerlin(x,0,z,5,8,true)*5,y/8,z+getPerlin(x,0,z,9,8,true)*5,2,20)
|
|
--local cliffs = thresholdFilter(preBoundary,.5,0)
|
|
local boundary = ridgedFilter(preBoundary)
|
|
local roughChunks = getPerlin(x,y/4,z,436,2)
|
|
local boundaryMask = thresholdFilter(boundary,.8,.1) --,.7,.25)
|
|
local boundaryTypeMask = getPerlin(x,0,z,6,74)-.5
|
|
local boundaryComp = 0
|
|
if boundaryTypeMask < 0 then --divergent
|
|
boundaryComp = (boundary > (1+boundaryTypeMask*.5) and -.17 or 0)
|
|
--* boundaryTypeMask*-2
|
|
else --convergent
|
|
boundaryComp = boundaryMask*.1*roughChunks
|
|
* boundaryTypeMask
|
|
end
|
|
choiceBiomeValue = .55
|
|
+boundary*.05*boundaryTypeMask --.1 --soft slope up or down to boundary
|
|
+boundaryComp --convergent/divergent effects
|
|
+getPerlin(x,0,z,123,25)*.025 --*cliffs --gentle rolling slopes
|
|
|
|
choiceBiomeSurface = (1-verticalGradientTurbulence < waterLevel-.1 and ice) or (boundaryMask>.6 and boundaryTypeMask>.1 and roughChunks>.5 and ice) or snow
|
|
choiceBiomeFill = ice
|
|
end
|
|
return choiceBiomeValue, choiceBiomeSurface, choiceBiomeFill
|
|
end
|
|
|
|
function findBiomeTransitionValue(biome,weight,value,averageValue)
|
|
if biome == 'Arctic' then
|
|
return (weight>.2 and 1 or 0)*value
|
|
elseif biome == 'Canyons' then
|
|
return (weight>.7 and 1 or 0)*value
|
|
elseif biome == 'Mountains' then
|
|
local weight = weight^3 --This improves the ease of mountains transitioning to other biomes
|
|
return averageValue*(1-weight)+value*weight
|
|
else
|
|
return averageValue*(1-weight)+value*weight
|
|
end
|
|
end
|
|
|
|
function generate()
|
|
local mapWidth = mapWidth
|
|
local biomeSize = biomeSize
|
|
local biomeBlendPercent = .25 --(biomeSize==50 or biomeSize == 100) and .5 or .25
|
|
local biomeBlendPercentInverse = 1-biomeBlendPercent
|
|
local biomeBlendDistortion = biomeBlendPercent
|
|
local smoothScale = .5/mapHeight
|
|
|
|
biomes = {}
|
|
for i,v in pairs(kSelectedBiomes) do
|
|
if v then
|
|
table.insert(biomes,i)
|
|
end
|
|
end
|
|
if #biomes<=0 then
|
|
table.insert(biomes,'Hills')
|
|
end
|
|
table.sort(biomes)
|
|
--local oMap = {}
|
|
--local mMap = {}
|
|
for x = 1, mapWidth do
|
|
local oMapX = {}
|
|
--oMap[x] = oMapX
|
|
local mMapX = {}
|
|
--mMap[x] = mMapX
|
|
for z = 1, mapWidth do
|
|
local biomeNoCave = false
|
|
local cellToBiomeX = x/biomeSize + getPerlin(x,0,z,233,biomeSize*.3)*.25 + getPerlin(x,0,z,235,biomeSize*.05)*.075
|
|
local cellToBiomeZ = z/biomeSize + getPerlin(x,0,z,234,biomeSize*.3)*.25 + getPerlin(x,0,z,236,biomeSize*.05)*.075
|
|
local closestDistance = 1000000
|
|
local biomePoints = {}
|
|
for vx=-1,1 do
|
|
for vz=-1,1 do
|
|
local gridPointX = math.floor(cellToBiomeX+vx+.5)
|
|
local gridPointZ = math.floor(cellToBiomeZ+vz+.5)
|
|
--local pointX, pointZ = getBiomePoint(gridPointX,gridPointZ)
|
|
local pointX = gridPointX+(getNoise(gridPointX,gridPointZ,53)-.5)*.75 --de-uniforming grid for vornonoi
|
|
local pointZ = gridPointZ+(getNoise(gridPointX,gridPointZ,73)-.5)*.75
|
|
|
|
local dist = math.sqrt((pointX-cellToBiomeX)^2 + (pointZ-cellToBiomeZ)^2)
|
|
if dist < closestDistance then
|
|
closestDistance = dist
|
|
end
|
|
table.insert(biomePoints,{
|
|
x = pointX,
|
|
z = pointZ,
|
|
dist = dist,
|
|
biomeNoise = getNoise(gridPointX,gridPointZ),
|
|
weight = 0
|
|
})
|
|
end
|
|
end
|
|
local weightTotal = 0
|
|
local weightPoints = {}
|
|
for _,point in pairs(biomePoints) do
|
|
local weight = point.dist == closestDistance and 1 or ((closestDistance / point.dist)-biomeBlendPercentInverse)/biomeBlendPercent
|
|
if weight > 0 then
|
|
local weight = weight^2.1 --this smooths the biome transition from linear to cubic InOut
|
|
weightTotal = weightTotal + weight
|
|
local biome = biomes[math.ceil(#biomes*(1-point.biomeNoise))] --inverting the noise so that it is limited as (0,1]. One less addition operation when finding a random list index
|
|
weightPoints[biome] = {
|
|
weight = weightPoints[biome] and weightPoints[biome].weight + weight or weight
|
|
}
|
|
end
|
|
end
|
|
for biome,info in pairs(weightPoints) do
|
|
info.weight = info.weight / weightTotal
|
|
if biome == 'Arctic' then --biomes that don't have caves that breach the surface
|
|
biomeNoCave = true
|
|
end
|
|
end
|
|
|
|
|
|
for y = 1, mapHeight do
|
|
local oMapY = oMapX[y] or {}
|
|
oMapX[y] = oMapY
|
|
local mMapY = mMapX[y] or {}
|
|
mMapX[y] = mMapY
|
|
|
|
--[[local oMapY = {}
|
|
oMapX[y] = oMapY
|
|
local mMapY = {}
|
|
mMapX[z] = mMapY]]
|
|
|
|
|
|
local verticalGradient = 1-((y-1)/(mapHeight-1))
|
|
local caves = 0
|
|
local verticalGradientTurbulence = verticalGradient*.9 + .1*getPerlin(x,y,z,107,15)
|
|
local choiceValue = 0
|
|
local choiceSurface = lava
|
|
local choiceFill = rock
|
|
|
|
if verticalGradient > .65 or verticalGradient < .1 then
|
|
--under surface of every biome; don't get biome data; waste of time.
|
|
choiceValue = .5
|
|
elseif #biomes == 1 then
|
|
choiceValue, choiceSurface, choiceFill = findBiomeInfo(biomes[1],x,y,z,verticalGradientTurbulence)
|
|
else
|
|
local averageValue = 0
|
|
--local findChoiceMaterial = -getNoise(x,y,z,19)
|
|
for biome,info in pairs(weightPoints) do
|
|
local biomeValue, biomeSurface, biomeFill = findBiomeInfo(biome,x,y,z,verticalGradientTurbulence)
|
|
info.biomeValue = biomeValue
|
|
info.biomeSurface = biomeSurface
|
|
info.biomeFill = biomeFill
|
|
local value = biomeValue * info.weight
|
|
averageValue = averageValue + value
|
|
--[[if findChoiceMaterial < 0 and findChoiceMaterial + weight >= 0 then
|
|
choiceMaterial = biomeMaterial
|
|
end
|
|
findChoiceMaterial = findChoiceMaterial + weight]]
|
|
end
|
|
for biome,info in pairs(weightPoints) do
|
|
local value = findBiomeTransitionValue(biome,info.weight,info.biomeValue,averageValue)
|
|
if value > choiceValue then
|
|
choiceValue = value
|
|
choiceSurface = info.biomeSurface
|
|
choiceFill = info.biomeFill
|
|
end
|
|
end
|
|
end
|
|
|
|
local preCaveComp = verticalGradient*.5 + choiceValue*.5
|
|
|
|
local surface = preCaveComp > .5-surfaceThickness and preCaveComp < .5+surfaceThickness
|
|
|
|
if generateCaves --user wants caves
|
|
and (not biomeNoCave or verticalGradient > .65) --biome allows caves or deep enough
|
|
and not (surface and (1-verticalGradient) < waterLevel+.005) --caves only breach surface above waterlevel
|
|
and not (surface and (1-verticalGradient) > waterLevel+.58) then --caves don't go too high so that they don't cut up mountain tops
|
|
local ridged2 = ridgedFilter(getPerlin(x,y,z,4,30))
|
|
local caves2 = thresholdFilter(ridged2,.84,.01)
|
|
local ridged3 = ridgedFilter(getPerlin(x,y,z,5,30))
|
|
local caves3 = thresholdFilter(ridged3,.84,.01)
|
|
local ridged4 = ridgedFilter(getPerlin(x,y,z,6,30))
|
|
local caves4 = thresholdFilter(ridged4,.84,.01)
|
|
local caveOpenings = (surface and 1 or 0) * thresholdFilter(getPerlin(x,0,z,143,62),.35,0) --.45
|
|
caves = caves2 * caves3 * caves4 - caveOpenings
|
|
caves = caves < 0 and 0 or caves > 1 and 1 or caves
|
|
end
|
|
|
|
local comp = preCaveComp - caves
|
|
|
|
local smoothedResult = thresholdFilter(comp,.5,smoothScale)
|
|
|
|
---below water level -above surface -no terrain
|
|
if 1-verticalGradient < waterLevel and preCaveComp <= .5 and smoothedResult <= 0 then
|
|
smoothedResult = 1
|
|
choiceSurface = water
|
|
choiceFill = water
|
|
surface = true
|
|
end
|
|
|
|
oMapY[z] = (y == 1 and 1) or smoothedResult
|
|
mMapY[z] = (y == 1 and lava) or (smoothedResult <= 0 and air) or (surface and choiceSurface) or choiceFill
|
|
end
|
|
end
|
|
|
|
-- local regionStart = Vector3.new(mapWidth*-2+(x-1)*4,mapHeight*-2,mapWidth*-2)
|
|
-- local regionEnd = Vector3.new(mapWidth*-2+x*4,mapHeight*2,mapWidth*2)
|
|
-- local mapRegion = Region3.new(regionStart, regionEnd)
|
|
-- terrain:WriteVoxels(mapRegion, 4, {mMapX}, {oMapX})
|
|
end
|
|
end
|
|
|
|
bench.runCode(generate, "voxelgen")
|