I think I understand what you’re saying. I found some old experiments with pathfinding tutorials where two tables exist, toSearch
and searched
. You start off by adding one point to toSearch
and then run a while loop of the function until toSearch
is exhausted. Rather than using strictly recursive function calls, the function simply adds the cell to searched
after searching it and removes it from toSearch
. If it finds the cell is valid, it adds the neighbors to toSearch
.
Unfortunately I tried all of this just now, and it doesn’t seem to have made much of a difference, as now the script times out rather then the stack overflowing.
-- . . .
local toSearch = {}
local searched = {}
local boundsMin, boundsMax = Vector3.one * math.huge, Vector3.one * -math.huge
-- . . .
-- recursive function for flood fill algorithm
local function dfs(pos)
if table.find(searched, pos) then table.remove(toSearch, table.find(toSearch, pos)) return end
local min = pos - (Vector3.one * VOXEL_SIZE * 0.5)
local max = pos + (Vector3.one * VOXEL_SIZE * 0.5)
local materials, occupancies = workspace.Terrain:ReadVoxels(Region3.new(min, max), 4)
local size = materials.Size
local bounded = false
for x = 1, size.X do
for y = 1, size.Y do
for z = 1, size.Z do
local material = materials[x][y][z]
if (material ~= Enum.Material.Air and material ~= Enum.Material.Water) then
bounded = true
end
end
end
end
table.insert(searched, pos)
table.remove(toSearch, table.find(toSearch, pos))
if bounded == true then
--debugNode(pos, VOXEL_SIZE)
if min.X < boundsMin.X then boundsMin = Vector3.new(min.X, boundsMin.Y, boundsMin.Z) end
if min.Y < boundsMin.Y then boundsMin = Vector3.new(boundsMin.X, min.Y, boundsMin.Z) end
if min.Z < boundsMin.Z then boundsMin = Vector3.new(boundsMin.X, boundsMin.Y, min.Z) end
if max.X > boundsMax.X then boundsMax = Vector3.new(max.X, boundsMax.Y, boundsMax.Z) end
if max.Y > boundsMax.Y then boundsMax = Vector3.new(boundsMax.X, max.Y, boundsMax.Z) end
if max.Z > boundsMax.Z then boundsMax = Vector3.new(boundsMax.X, boundsMax.Y, max.Z) end
for i = 1, #TERRAIN_CELL_OFFSETS do table.insert(toSearch, (pos + TERRAIN_CELL_OFFSETS[i] * VOXEL_SIZE)) end
end
end
-- generates an accurate bounding box that includes terrain
local function getTrueBoundingBox()
table.insert(toSearch, Vector3.zero + Vector3.one * VOXEL_SIZE * 0.5)
while #toSearch > 0 do dfs(toSearch[1]) end
-- . . .
end
octree-spacing.rbxl (4.0 MB)