如何在Lua中压缩一个三维数组?

所以,我有一个在Lua中基本上是三维数组的体素系统。它看起来像这样:

  local VoxelTable = {
    [1] = { --X
      [5] = { --Y
        [2] = { --Z
          ["Type"] = "Solid",
          ["Rotation"] = "InverseX",
          ["Material"] = "Grass",
          ["Size"]     = Vector3.new(1,1,1)
          --一个旋转“InverseX”的1x1x1实心草块
        }
      }
    }
}

这些体素是生成的,因为这样我无法手动压缩它们。但是,如果不进行压缩,渲染将大大拖慢游戏。

我的想法是,如果有三个高度相同、旋转值相同的草块,我将它们合并成一个体素,尺寸为Vector3.new(1,3,1),并将其放置在三个草块的中间位置上。

所以

[1] = { --X
  [5] = { --Y
    [2] = { --Z
      ["Type"] = "Solid",
      ["Rotation"] = "InverseX",
      ["Material"] = "Grass",
      ["Size"]     = Vector3.new(1,1,1)
    }
  },
  [6] = { --Y
    [2] = { --Z
      ["Type"] = "Solid",
      ["Rotation"] = "InverseX",
      ["Material"] = "Grass",
      ["Size"]     = Vector3.new(1,1,1)
    }
  },
  [7] = { --Y
    [2] = { --Z
      ["Type"] = "Solid",
      ["Rotation"] = "InverseX",
      ["Material"] = "Grass",
      ["Size"]     = Vector3.new(1,1,1)
    }
  }
}

变成

[1] = { --X
  [6] = { --Y
    [2] = { --Z
      ["Type"] = "Solid",
      ["Rotation"] = "InverseX",
      ["Material"] = "Grass",
      ["Size"]     = Vector3.new(1,3,1)
    }
  }
}
点赞
用户4403144
用户4403144

以下是一个比较简单的例子。我创建了一个 10 x 10 x 10 的立方体,给每个体素一个 vec3 大小属性(就像你的代码一样)和一个随机字母属性(a、b 或 c)。然后我迭代每个体素,向上和向下查找。如果我所在的体素与上下的体素具有相同的字母属性,则将上方和下方的体素设置为 nil,并增加中间体素的大小属性。我确定这一切都可以进行优化,而且我相信更复杂的逻辑可以查找除了这个硬编码的三个相同体素堆栈之外的其他体素关系。但这是一个开始:

local world = {}
local letters = {"a", "b", "c"}

function setup()
    -- 创建简化的测试数据
    for x = 1, 10 do
        world[x] = {}

        for y = 1, 10 do
            world[x][y] = {}

            for z = 1, 10 do
                world[x][y][z] = {}

                local randomIndex = math.random(1, 3)
                world[x][y][z].letter = letters[randomIndex]
                world[x][y][z].size = vec3(1, 1, 1)
            end
        end
    end

    -- 合并三个相同的体素堆栈
    for x = 1, 10 do
        for y = 2, 9 do -- 确保有上面一层(y == 1)或下面一层(y == 10)
            for z = 1, 10 do
                combineStacks(x, y, z)
            end
        end
    end
end
function combineStacks(x, y, z)
    local low = world[x][y - 1][z]
    local mid = world[x][y][z]
    local high = world[x][y + 1][z]

    if low ~= nil and mid ~= nil and high ~= nil then
        if low.letter == mid.letter and mid.letter == high.letter then
            world[x][y - 1][z] = nil -- low
            world[x][y + 1][z] = nil -- high

            mid.size = vec3(1, 3, 1)
            print("发现三个相同的体素堆栈!")
        end
    end
end

以上代码已在 Codea 中编写、测试和可视化,下面是进行了二维可视化的结果,每个方块显示一个体素立方体的切片。如果你看到一个黄色点(代表三个相同的体素堆栈!),看左右两侧的方块切片,你会发现这个位置的体素被设置为 nil:

enter image description here

2019-04-06 01:26:35