1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| Heuristic = { DepthBased = 1, CapacityBased = 2, Hybrid = 3 }
Point = {} function Point:new(x, y, z) local p = {x = x or 0, y = y or 0, z = z or 0} setmetatable(p, self) self.__index = self return p end
BoundingBox = {} function BoundingBox:new(min, max) local b = {min = min or Point:new(), max = max or Point:new()} setmetatable(b, self) self.__index = self return b end
function BoundingBox:contains(p) return p.x >= self.min.x and p.x <= self.max.x and p.y >= self.min.y and p.y <= self.max.y and p.z >= self.min.z and p.z <= self.max.z end
OctreeNode = {} function OctreeNode:new(bounds, depth, maxDepth, capacity, heuristic) local node = { bounds = bounds, points = {}, children = nil, depth = depth, maxDepth = maxDepth, capacity = capacity, heuristic = heuristic } setmetatable(node, self) self.__index = self return node end
function OctreeNode:subdivide() self.children = {} for i = 1, 8 do table.insert(self.children, OctreeNode:new(BoundingBox:new(), self.depth + 1, self.maxDepth, self.capacity, self.heuristic)) end end
function OctreeNode:insert(point) if not self.bounds:contains(point) then return end
if self.children == nil then local shouldInsert = false if self.heuristic == Heuristic.CapacityBased and #self.points < self.capacity then shouldInsert = true elseif self.heuristic == Heuristic.DepthBased and self.depth >= self.maxDepth then shouldInsert = true elseif self.heuristic == Heuristic.Hybrid and (self.depth >= self.maxDepth or #self.points < self.capacity) then shouldInsert = true end
if shouldInsert then table.insert(self.points, point) else self:subdivide() for _, child in ipairs(self.children) do child:insert(point) end end else for _, child in ipairs(self.children) do child:insert(point) end end end
|