Hello! I’ve recently been working on a game that has destruction physics heavily inspired by Jujutsu Shenanigans (not a 1:1 system, but something more that fits my game), however whilst making the meshing algorithm I ran into a few issues that I cannot seem to wrap my head around.
Using code from this post as a base.
I attempted to make it work with my own system by extending it to the Z axis too, however I ran into an issue, instead of it returning a table with all the greedy mesh position data, it simply returns all of the grid positions.
Expected Behavior:
Takes this part (pictured below), splits it into a predefined grids of smaller cubes, gets the cubes touching the hitbox part (not visible here), removes them from the original grid table and then greedy meshes the remaining cubes, and prints out the table of greedy mesh data.
Voxels that should be subtracted from the original grid:
Voxels that should be greedy meshed and placed into the world
Actual Behavior:
Instead of only giving me that parts should be greedy meshed, it spits out all of the grid positions with the same corner1 and corner2 coordinates.
I’ve attempted to look through the forums for more information, however I cannot seem to find anything remotely close to my issue, or much on greedy meshing for that matter…
Here is the entire greedy meshing function,
The grid variable is just a dictionary that gets made in another function that splits the part
into smaller cuboids.
Example of some grid data:
A grid has x,y,z positions starting from one corner of a part to the other, with part size and world positions saved too.
local x = 1
local y = 1
local z = 1
local coordinates = x.."-"..y.."-"..z
Grid = {
coordinates = { Size = vector3.one, Position = CFrame.new(0,0,0)},
}
The greedy meshing code:
function GreedyMesh(Grid)
local MaxX = 0
local MaxY = 0
local MaxZ = 0
for GridCoordinate, Data in pairs(Grid) do
local Coordinates = string.split(GridCoordinate,"-")
if tonumber(Coordinates[1]) > MaxX then
MaxX = tonumber(Coordinates[1])
local Size = Data.Size
end
if tonumber(Coordinates[2]) > MaxY then
MaxY = tonumber(Coordinates[2])
local Size = Data.Size
end
if tonumber(Coordinates[3]) > MaxZ then
MaxZ = tonumber(Coordinates[3])
local Size = Data.Size
end
end
local IsVisited = {}
local GreedyMeshes = {}
local function IsEmpty(Grid,GridCoords)
return Grid[GridCoords] == nil
end
for X = 1, MaxX, 1 do
for Y = 1, MaxY, 1 do
for Z = 1, MaxZ, 1 do
local StartX = X
local StartY = Y
local StartZ = Z
local EndX = X
local EndY = Y
local EndZ = Z
local Coordinates = X.."-"..Y.."-"..Z
IsVisited[Coordinates] = true
while EndX < MaxX do
local NewEndX = EndX + 1
local Coordinates = NewEndX.."-"..Y.."-"..Z
local IsUseable = not IsVisited[Coordinates] and not IsEmpty(Grid,Coordinates)
if not IsUseable then
break
end
IsVisited[Coordinates] = true
EndX = NewEndX
end
while EndY < MaxY do
local NewEndY = EndY + 1
local IsRowUseable = true
for dx=StartX, EndX do
local Coordinates = dx.."-"..NewEndY.."-"..Z
local IsUseable = not IsVisited[Coordinates] and not IsEmpty(Grid,Coordinates)
if not IsUseable then
IsRowUseable = false
break
end
end
if not IsRowUseable then
break
end
for dx=StartX, EndX do
local Coordinates = dx.."-"..NewEndY.."-"..Z
IsVisited[Coordinates] = true
end
EndY = NewEndY
end
while EndZ < MaxZ do
local NewEndZ = EndZ + 1
local IsRowUseable = true
for dx=StartX, EndX do
local Coordinates = dx.."-"..EndY.."-"..NewEndZ
local IsUseable = not IsVisited[Coordinates] and not IsEmpty(Grid,Coordinates)
if not IsUseable then
IsRowUseable = false
break
end
end
if not IsRowUseable then
break
end
for dx=StartX, EndX do
local Coordinates = dx.."-"..EndY.."-"..NewEndZ
IsVisited[Coordinates] = true
end
EndZ = NewEndZ
end
table.insert(GreedyMeshes, {
Corner1 = StartX.."-"..StartY.."-"..StartZ,
Corner2 = EndX.."-"..EndY.."-"..EndZ
})
end
end
end
print(GreedyMeshes)
print(#GreedyMeshes)
end
If you have any questions as to how any of the code / systems work, feel free to ask.