我需要最好的方法来存储像素的三维表。我需要做的是有多个x,y表(基本上是三维),它是用透明度栅格多个二维像素图。你看我可以像这样容易地创建两个维度:
pixels = {{},{}}
pixels[1][5] = "green" --just an example
print(pixels[1][5])
但是,我不能像Java那样做到这一点......
pixels = {{}, {}, {}}
pixels[1][4][3] = "red" -- [x][y][z]
print(pixels[1][4][3])
这是我想要的功能,但我这样做是非常令人厌恶的......
pixels = {}
pixels["x23,y02,z05"] = "green"
print(pixels["x23,y02,z05"]")
我只是使用string.sub和string.concat来读取和设置表格...我真的希望示例2的功能可以工作,但是我知道它可能需要以不同的方式实现。
答案 0 :(得分:3)
基本上有两种方法可以解决这个问题
自动表使用元表透明地生成子表,基本上在创建它之后你应该可以忘记它们。
function newAutotable(dim)
local MT = {};
for i=1, dim do
MT[i] = {__index = function(t, k)
if i < dim then
t[k] = setmetatable({}, MT[i+1])
return t[k];
end
end}
end
return setmetatable({}, MT[1]);
end
-- Usage
local at = newAutotable(3);
print(at[0]) -- returns table
print(at[0][1]) -- returns table
print(at[0][1][2]) -- returns nil
at[0][1][2] = 2;
print(at[0][1][2]) -- returns value
print(at[0][1][3][3]) -- error, because only 3 dimensions set
对他们来说不太好的是他们生成很多表 - 显然。这是一些内存开销,每个深度级别都会增加执行时间。
他们的好处在于它们的大小可以完全动态。你甚至可以让它们无限深入。虽然在你的用例中这很可能没有必要,甚至可能是一个坏主意。
这个结构非常适合非整数索引,但是你可以使深度甚至依赖于“模板结构”,因此实现了一个透明的动态配置表,但我得到了侧面跟踪......
另一种变体是扁平阵列。 user3125367已经写过关于它们的内容,但是我想对此进行扩展,因为这可以做得更方便并解释一些事情。
无论如何,在CG中经常展平你的多维数组是一个好主意,因为那时你可以很容易地做很多矩阵运算。就所需的处理时间而言,计算修改的索引也相对便宜。但应该注意的是,虽然有点明显,但这种方法只适用于数字键和矩阵的预定义大小。
function newMdArray(X, Y, Z)
local MT = { __call = function(t, x, y, z, v)
if x>X or y>Y or z>Z or x<1 or y<1 or z<1 then return; end
local k = x + X*(y-1) + X*Y*(z-1);
if v ~= nil then t[k] = v; end
return t[k];
end };
return setmetatable({}, MT);
end
-- Usage
local mdt = newMdArray(100, 100, 100);
local v = mdt(1, 2, 3);
mdt(1, 2, 3, v*.1);
此代码取自我的另一个答案:dynamic tables or arrays
它可能会稍微优化一下(例如在闭包中计算X*Y
)但我想在这里粘贴原始代码。无论如何,通过使用常规数组索引,您可以轻松地处理扁平化结构:
for i=1, #mdt
mdt[i] = (mdt[i] or 0)*.5
end
直接访问3d索引:
mdt(12, 13, 14, 0)
您还可以通过向metatable添加__index
字段或者保存矩阵尺寸等来轻松修改函数以返回缺失键的默认值。
答案 1 :(得分:2)
在您的第一个代码中:
pixels = {{},{}}
相当于:
pixels = {}
pixels[1] = {}
pixels[2] = {}
此处pixels[1]
已经是一个表格,这就是为什么您可以为pixels[1][5]
分配值。
但在你的第二个代码中:
pixels = {{}, {}, {}}
这里,pixels
仍然是一个二维数组(有3个元素)。它相当于:
pixels = {}
pixels[1] = {}
pixels[2] = {}
pixels[3] = {}
pixels[1]
是一个表格,但pixels[1][4]
不是。你需要做的是给pixels[1][4]
一个像这样的表构造函数:
pixels = {{}, {}, {}}
pixels[1][4] = {} --initialize it to an empty table
pixels[1][4][3] = "red"
print(pixels[1][4][3])
答案 2 :(得分:2)
除了阵列中阵列中的经典&#39;数组&#39;方案,你可以使用Lua表内部的好处。怎么样? Lua表只是从键到值的映射,当您将它用作数组时,您可以跳过一些键,这几乎不需要任何费用。
t = { }
t[1] = "Hello"
t[500000] = "World" -- does NOT allocate additional 499999 elements
因此,如果您的数据稀少(超过50%的3d积分没有价值),您可以从中受益:
local n_x, n_y, n_z = 1920, 1080, 1000
local n_xy = n_x * n_y
function setValue(t, x, y, z, value)
assert(x > 0 and x < n_x)
assert(y > 0 and y < n_y)
assert(z > 0 and z < n_z)
t[((z-1) * n_xy) + ((y-1) * n_z) + x] = value
end
function getValue(t, x, y, z)
assert(x > 0 and x < n_x)
assert(y > 0 and y < n_y)
assert(z > 0 and z < n_z)
return t[((z-1) * n_xy) + ((y-1) * n_z) + x]
end
t = { }
setValue(t, 1, 1, 1, "red")
setValue(t, 1, 1, 2, "green")