Skip to content

Instantly share code, notes, and snippets.

@ALLAH-2
Last active June 18, 2023 03:32
Show Gist options
  • Save ALLAH-2/27b071e7f552c96580a2cd55fa5046e1 to your computer and use it in GitHub Desktop.
Save ALLAH-2/27b071e7f552c96580a2cd55fa5046e1 to your computer and use it in GitHub Desktop.
--[[
This mesher only handles 16x16x16 chunks!
Uses a more optimal approach towards creating
chunks. Checks plane intersections of the chunk
for greedy meshing.
This type of plane-intersection greedy meshing is
useful for fixing certain problems w/ voxel based
greedy meshing, where transparent objects may be
see through.
@author Magical_Noob
@submodule Mesh
]]
local Mesh = {};
Mesh.__index = Mesh;
local function pack(vec)
-- cast a vector3in16 to an int
return vec.X*256 + vec.Y*16 + vec.Z;
end
function Mesh.plane(
chunk,
normal,
d,u,v
)
-- this case checks the voxel grid
-- with a plane. the plane's normal
-- will be used to check if a block
-- is obscured.
local out = {};
local n = 0;
for i = 0, 15 do
for j = 0, 15 do
-- sweep through the cross section,
-- adding chunk indicies to everything
n += 1;
local position = d + u*i + v*j;
local id = chunk[pack(position)];
if(not id)then
-- this is an air block
-- ie. should not greedy mesh!
continue;
elseif(chunk[pack(position + normal)])then
-- there is a block above
-- the given normal
continue;
end
out[n] = id;
end
end
return out;
end
function Mesh.meshPlane(
mesh,
d,u,v
)
-- greedy meshes a subsection
-- of the intersection plane
local quads = {};
local n = 0;
for i = 0, 15 do -- u
for j = 0, 15 do -- v
-- now check every other index
-- memoized time is really slow though!
n += 1;
local id = mesh[n];
if(not id)then
continue;
end
local sizeX = 1;
local sizeY = 1;
local done;
-- expand on the j or v direction
while(mesh[n + sizeX]==id and j+sizeX<16)do
sizeX += 1;
end
-- expand on the i or u direction
sizeX -= 1;
while(not done and i+sizeY<16)do
local offset = sizeY*16;
for sx = 0, sizeX do
if(mesh[n + sx + offset]~=id)then
done = true;
break;
end
end
if(not done)then
sizeY += 1;
end
end
-- clear out the size X & Y components
sizeY -= 1;
for sy = 0, sizeY do
for sx = 0, sizeX do
mesh[n + sx + sy*16] = nil;
end
end
-- append to triangle list
local start = d+(u*i)+(v*j);
table.insert(quads, {
-- a, b
start;
start
+((sizeX+1)*v)
+((sizeY+1)*u);
});
end
end
return quads;
end
function Mesh.draw(chunk)
local quads = {};
for _, face in {
-- iterate through the mesh's faces
{Vector3.new(0,0,1), Vector3.new(1,0,0), Vector3.new(0,1,0)},
{Vector3.new(0,1,0), Vector3.new(0,0,1), Vector3.new(1,0,0)},
{Vector3.new(1,0,0), Vector3.new(0,1,0), Vector3.new(0,0,1)},
-- negative faces
{Vector3.new(0,0,-1), Vector3.new(1,0,0), Vector3.new(0,1,0)},
{Vector3.new(0,-1,0), Vector3.new(0,0,1), Vector3.new(1,0,0)},
{Vector3.new(-1,0,0), Vector3.new(0,1,0), Vector3.new(0,0,1)}
} do
local normal, u, v = unpack(face);
local abs = normal:Max(-normal); -- depths within range of chunk boundaries
local dataOff = normal:Max(Vector3.zero); -- positive offset from greedy mesh
for i = 0, 15 do
local d = abs*i;
local data = Mesh.meshPlane(
Mesh.plane(chunk, normal, d, u, v), -- create mesh information
d + dataOff, u, v -- upload depth and uv information
);
if(#data == 0)then
-- well its empty!
continue;
else
-- upload quad data
table.move(
data,
1,
#data,
#quads+1,
quads
);
end
end
end
-- returns a list of face pairs
-- { start, finish }
return quads;
end
Mesh.pack = pack;
return Mesh;
@ALLAH-2
Copy link
Author

ALLAH-2 commented Jun 18, 2023

k here nerds

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment