hi thanks for the place file was fun playing with this. I took out all the parts and just used the info.
The scan only take about 21 seconds.
-- ### VARIABLES & CONSTANTS
-- cell variables
task.wait(10)
local SS = game:GetService("ServerStorage")
local octreeCell = SS:WaitForChild("OctreeCell")
-- creating octree model
local octree = Instance.new("Folder")
octree.Name = "Octree"
octree.Parent = workspace
-- parameters for scans
local paramsOL = OverlapParams.new()
paramsOL.FilterDescendantsInstances = {octree}
paramsOL.FilterType = Enum.RaycastFilterType.Exclude
paramsOL.MaxParts = 1
local paramsRC = RaycastParams.new()
paramsRC.FilterDescendantsInstances = {octree}
paramsRC.FilterType = Enum.RaycastFilterType.Exclude
-- nodes table
local grid = {}
local nodeCount = 0
local nodes = {}
local octreeTable = {}
-- octree constants and variables
local OCTREE_SIZE = 512
local OCTREE_DEPTH = 9
local MINIMUM_SIZE = OCTREE_SIZE / (2 ^ (OCTREE_DEPTH - 1))
local SUB_REGION_POSITION_OFFSET = {
Vector3.new(0.25, 0.25, -0.25),
Vector3.new(-0.25, 0.25, -0.25),
Vector3.new(0.25, 0.25, 0.25),
Vector3.new(-0.25, 0.25, 0.25),
Vector3.new(0.25, -0.25, -0.25),
Vector3.new(-0.25, -0.25, -0.25),
Vector3.new(0.25, -0.25, 0.25),
Vector3.new(-0.25, -0.25, 0.25)
}
-- populating cell table
local cells = {}
local lastSize = OCTREE_SIZE * 2
for i = 1, OCTREE_DEPTH do
local size = lastSize * 0.5
--local p = octreeCell:Clone()
--p.Size = Vector3.one * size
--p.Position = Vector3.zero
--p.Anchored = true
--p.CanCollide = false
--p.CanQuery = false
--p.CanTouch = false
--p.Transparency = 1
--p.Parent = workspace
cells[size] = Vector3.zero
lastSize = size
end
print(cells)
-- raycast params
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {workspace.Terrain}
raycastParams.FilterType = Enum.RaycastFilterType.Include
-- ### FUNCTIONS
-- creates a debug node
local function debugNode(position)
local p = Instance.new("Part")
p.Transparency = 1
p.Position = position
p.Size = Vector3.one * MINIMUM_SIZE
p.Color = octreeCell.Color
--p.Transparency = octreeCell.Transparency
p.Anchored = true
p.CanCollide = false
p.CanQuery = false
p.CanTouch = false
p.Locked = true
p.Parent = octree
p.Name = octreeCell.Name
end
-- ### MAIN FUNCTIONS
-- function to generate a grid of nodes
local function createGrid(position, size, depth)
depth = depth or 0
if depth < 3 then task.wait() end
local node = cells[size]
if not node then warn("node size does not exist") return end
node = position
if depth < OCTREE_DEPTH - 1 then
local childSize = size * 0.5
for i = 1, 8 do
local multiplier = SUB_REGION_POSITION_OFFSET[i]
createGrid(position + (multiplier * childSize * 2), childSize, depth + 1)
end
else
grid[position.Y] = grid[position.Y] or {}
grid[position.Y][position.X] = grid[position.Y][position.X] or {}
grid[position.Y][position.X][position.Z] = position
end
end
local function terrainScan()
for i, cell in cells do
cell = Vector3.zero
table.remove(cells,i)
end
local max = OCTREE_SIZE * 0.5 - (MINIMUM_SIZE * 0.5) if not grid[max] or not grid[-max] then warn("grid incomplete") return end
for x, zList in pairs(grid[max]) do
--task.wait()
--local castCount = 0
for z, position in zList do
--task.wait()
local lastSpot = Vector3.new(x, max, z)
local noResult = false
--local castCount = 0
repeat
--task.wait()
local result = workspace:Blockcast(CFrame.new(lastSpot), Vector3.one * MINIMUM_SIZE, Vector3.new(x, -max, z) - lastSpot)
if result and result.Position.Y >= -max then
local node = Vector3.new(x, math.floor((result.Position.Y - 1) * 0.5 + 0.5) * 2 + 1, z)
--print(lastSpot, "\n", string.format("%.2f", result.Position.X), string.format("%.2f", result.Position.Y), string.format("%.2f", result.Position.Z), "\n", node)
nodes[node.X] = nodes[node.X] or {}
nodes[node.X][node.Y] = nodes[node.X][node.Y] or {}
nodes[node.X][node.Y][node.Z] = node
lastSpot = node + Vector3.new(0, -MINIMUM_SIZE, 0)
if lastSpot.Y < -max then noResult = true end
else
noResult = true
end
--castCount += 1
until noResult == true
--print(x, z, castCount)
end
--print(x, castCount)
end
end
local function generateMap()
local buff = 0
for x, yList in nodes do
if buff % 10 == 0 then task.wait() end
task.wait()
for y, zList in yList do
for z, position in zList do
table.insert(octreeTable, position)
--debugNode(position)
end
end
buff += 1
end
end
-- ### RUNTIME
print("beginning grid construction")
local t = os.clock()
createGrid(Vector3.zero, OCTREE_SIZE)
local total_1 = os.clock() - t
print("grid construction complete:", string.format("%.2f", total_1))
print("beginning surface scan")
t = os.clock()
terrainScan()
local total_2 = os.clock() - t
print("terrain scan complete:", string.format("%.2f", total_2))
print("generating map")
t = os.clock()
generateMap()
local total_3 = os.clock() - t
print("visualization complete:", string.format("%.2f", total_3))
print(#octreeTable, "nodes found:", string.format("%.2f", total_1 + total_2 + total_3))