Hgs Ca
Hgs Ca

Reputation: 51

How would I compress a 3-dimensional array in Lua?

So, I have what is basically a three-dimensional array in Lua, really a voxel system. It looks like this:

  local VoxelTable = {
    [1] = { --X
      [5] = { --Y
        [2] = { --Z
          ["Type"] = "Solid",
          ["Rotation"] = "InverseX",
          ["Material"] = "Grass",
          ["Size"]     = Vector3.new(1,1,1) 
          --A 1x1x1 Solid grass block with rotation "InverseX"
        }
      }
    }
}

The Voxels are generated, and because of that I can't compress them manually. But without compression rendering lags the game down a lot.

What I want to do is if there are three grass blocks right above/below eachother with the same rotation value, I combine them into one voxel, with a size of Vector3.new(1,3,1), with the position of the middle voxel.

So

[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) 
    }
  }
}

becomes

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

Upvotes: 2

Views: 320

Answers (1)

brianolive
brianolive

Reputation: 1671

Here’s a somewhat simplified example. I’ve created a 10 x 10 x 10 cube of voxels, giving each voxel a vec3 size attribute (as you have it) and a random letter attribute (a, b, or c). I then iterate over the voxels, looking up and down. If the voxel I’m on has the same letter attribute as the voxel above and below, then I set the above and below voxels to nil, and increase the size attribute of the middle voxel. I am sure this could all be optimized, and I’m sure more sophisticated logic could look for other voxel relationships besides this hard-coded stack-of-three identical voxels. But this is a start:

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

function setup()    
    -- Create simplified test data
    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

    -- Combine common stacks of three
    for x = 1, 10 do
        for y = 2, 9 do -- Ensure there is at least a level below (y == 1) or above (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("Stack of three identical voxels found!")
        end
    end
end

The above was written and tested (and visualized, shown below) in Codea. The vec3 construct is native to that environment and not to Lua in general, so keep that in mind.

Here’s a 2D visualization of the results, with each square showing a slice of the voxel cube. If you see a yellow point (representing a stack of three!), look at the square slice to the left and right, and at the same location you will see the voxels there are nil:

enter image description here

Upvotes: 1

Related Questions