Minetest-WorldEditAdditions/worldeditadditions_core/utils/mesh.lua

94 lines
3.0 KiB
Lua

local wea_c = worldeditadditions_core
-- ███████ █████ ██████ ███████
-- ██ ██ ██ ██ ██
-- █████ ███████ ██ █████
-- ██ ██ ██ ██ ██
-- ██ ██ ██ ██████ ███████
--- A single face of a Mesh.
-- @class worldeditadditions_core.Face
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.
-- @class worldeditadditions_core.Mesh
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_c.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
return Mesh, Face