Minetest-WorldEditAdditions/worldeditadditions/utils/mesh.lua
Starbeamrainbowlabs f32d8588e0
Add Mesh & Face classes for #59
Together, these classes provide a way to represent a mesh of faces
generated from the Minetest world. This way, the generation of a mesh
can be abstracted away from any potential output file writers, thereby
allowing for multiple different output file formats to be supported.
2021-06-26 22:03:55 +01:00

99 lines
3.1 KiB
Lua

local wea = worldeditadditions
-- ███████ █████ ██████ ███████
-- ██ ██ ██ ██ ██
-- █████ ███████ ██ █████
-- ██ ██ ██ ██ ██
-- ██ ██ ██ ██████ ███████
--- A single face of a Mesh.
local Face = {}
Face.__index = Face
--- Creates a new face from a list of vertices.
-- The list of vertices should be anti-clockwise.
-- @param vertices Vector3[] A list of Vector3 vertices that define the face.
function Face.new(vertices)
local result = { vertices = vertices }
setmetatable(result, Face)
return result
end
--- Determines whether this face is equal to another face or not.
-- @param a Face The first face to compare.
-- @param b Face The second face to compare.
-- @returns bool Whether the 2 faces are equal or not.
function Face.equal(a, b)
if #a.vertices ~= #b.vertices then return false end
for i,vertex in ipairs(a) do
if vertex ~= b.vertices[i] then return false end
end
return true
end
function Face.__eq(a, b) return Face.equal(a, b) end
-- ███ ███ ███████ ███████ ██ ██
-- ████ ████ ██ ██ ██ ██
-- ██ ████ ██ █████ ███████ ███████
-- ██ ██ ██ ██ ██ ██ ██
-- ██ ██ ███████ ███████ ██ ██
--- A mesh of faces.
local Mesh = {}
Mesh.__index = Mesh
--- Creates a new empty mesh object container.
-- @returns Mesh
function Mesh.new()
local result = { faces = {} }
setmetatable(result, Mesh)
end
--- Adds a face to this mesh.
-- @param self Mesh The mesh instance to operate on.
-- @param face Face The face to add.
-- @returns void
function Mesh.add_face(self, face)
table.insert(self.faces, face)
end
--- Deduplicate the list of faces in this Mesh.
-- Removes all faces that are exactly equal to one another. This reduces the
-- filesize.
-- @returns number The number of faces removed.
function Mesh.dedupe(self)
-- Find the faces to remove
local toremove = {}
for i,face_check in ipairs(self.faces) do
for j,face_next in ipairs(self.faces) do
if i ~= j -- If we're not comparing a face to itself...
and face_check == face_next -- ....and the 2 faces are equal....
and not wea.table_contains(toremove, j) then -- ...and we haven't already marked it for removal...
-- Mark it for removal
table.insert(toremove, j)
end
end
end
-- Sort the list of indexes marked for removal from largest to smallest
-- This way, removing smaller items doesn't alter the index of larger ones
table.sort(toremove, function(a, b) return a > b end)
-- Remove the faces marked for removal
for i, remove_index in ipairs(toremove) do
table.remove(self.faces, remove_index)
end
return #toremove
end
if worldeditadditions then
worldeditadditions.Face = Face
worldeditadditions.Mesh = Mesh
else
return {
Face = Face,
Mesh = Mesh
}
end