voxelarea.lua 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. VoxelArea = {
  2. MinEdge = {x=1, y=1, z=1},
  3. MaxEdge = {x=0, y=0, z=0},
  4. ystride = 0,
  5. zstride = 0,
  6. }
  7. function VoxelArea:new(o)
  8. o = o or {}
  9. setmetatable(o, self)
  10. self.__index = self
  11. local e = o:getExtent()
  12. o.ystride = e.x
  13. o.zstride = e.x * e.y
  14. return o
  15. end
  16. function VoxelArea:getExtent()
  17. local MaxEdge, MinEdge = self.MaxEdge, self.MinEdge
  18. return {
  19. x = MaxEdge.x - MinEdge.x + 1,
  20. y = MaxEdge.y - MinEdge.y + 1,
  21. z = MaxEdge.z - MinEdge.z + 1,
  22. }
  23. end
  24. function VoxelArea:getVolume()
  25. local e = self:getExtent()
  26. return e.x * e.y * e.z
  27. end
  28. function VoxelArea:index(x, y, z)
  29. local MinEdge = self.MinEdge
  30. local i = (z - MinEdge.z) * self.zstride +
  31. (y - MinEdge.y) * self.ystride +
  32. (x - MinEdge.x) + 1
  33. return math.floor(i)
  34. end
  35. function VoxelArea:indexp(p)
  36. local MinEdge = self.MinEdge
  37. local i = (p.z - MinEdge.z) * self.zstride +
  38. (p.y - MinEdge.y) * self.ystride +
  39. (p.x - MinEdge.x) + 1
  40. return math.floor(i)
  41. end
  42. function VoxelArea:position(i)
  43. local p = {}
  44. local MinEdge = self.MinEdge
  45. i = i - 1
  46. p.z = math.floor(i / self.zstride) + MinEdge.z
  47. i = i % self.zstride
  48. p.y = math.floor(i / self.ystride) + MinEdge.y
  49. i = i % self.ystride
  50. p.x = math.floor(i) + MinEdge.x
  51. return p
  52. end
  53. function VoxelArea:contains(x, y, z)
  54. local MaxEdge, MinEdge = self.MaxEdge, self.MinEdge
  55. return (x >= MinEdge.x) and (x <= MaxEdge.x) and
  56. (y >= MinEdge.y) and (y <= MaxEdge.y) and
  57. (z >= MinEdge.z) and (z <= MaxEdge.z)
  58. end
  59. function VoxelArea:containsp(p)
  60. local MaxEdge, MinEdge = self.MaxEdge, self.MinEdge
  61. return (p.x >= MinEdge.x) and (p.x <= MaxEdge.x) and
  62. (p.y >= MinEdge.y) and (p.y <= MaxEdge.y) and
  63. (p.z >= MinEdge.z) and (p.z <= MaxEdge.z)
  64. end
  65. function VoxelArea:containsi(i)
  66. return (i >= 1) and (i <= self:getVolume())
  67. end
  68. function VoxelArea:iter(minx, miny, minz, maxx, maxy, maxz)
  69. local i = self:index(minx, miny, minz) - 1
  70. local xrange = maxx - minx + 1
  71. local nextaction = i + 1 + xrange
  72. local y = 0
  73. local yrange = maxy - miny + 1
  74. local yreqstride = self.ystride - xrange
  75. local z = 0
  76. local zrange = maxz - minz + 1
  77. local multistride = self.zstride - ((yrange - 1) * self.ystride + xrange)
  78. return function()
  79. -- continue i until it needs to jump
  80. i = i + 1
  81. if i ~= nextaction then
  82. return i
  83. end
  84. -- continue y until maxy is exceeded
  85. y = y + 1
  86. if y ~= yrange then
  87. -- set i to index(minx, miny + y, minz + z) - 1
  88. i = i + yreqstride
  89. nextaction = i + xrange
  90. return i
  91. end
  92. -- continue z until maxz is exceeded
  93. z = z + 1
  94. if z == zrange then
  95. -- cuboid finished, return nil
  96. return
  97. end
  98. -- set i to index(minx, miny, minz + z) - 1
  99. i = i + multistride
  100. y = 0
  101. nextaction = i + xrange
  102. return i
  103. end
  104. end
  105. function VoxelArea:iterp(minp, maxp)
  106. return self:iter(minp.x, minp.y, minp.z, maxp.x, maxp.y, maxp.z)
  107. end