mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-12-23 12:05:01 +00:00
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.
This commit is contained in:
parent
dbdf509d79
commit
f32d8588e0
5 changed files with 120 additions and 0 deletions
|
@ -9,6 +9,7 @@ worldeditadditions = {}
|
||||||
worldeditadditions.modpath = minetest.get_modpath("worldeditadditions")
|
worldeditadditions.modpath = minetest.get_modpath("worldeditadditions")
|
||||||
dofile(worldeditadditions.modpath.."/utils/vector.lua")
|
dofile(worldeditadditions.modpath.."/utils/vector.lua")
|
||||||
dofile(worldeditadditions.modpath.."/utils/vector3.lua")
|
dofile(worldeditadditions.modpath.."/utils/vector3.lua")
|
||||||
|
dofile(worldeditadditions.modpath.."/utils/mesh.lua")
|
||||||
|
|
||||||
dofile(worldeditadditions.modpath.."/utils/strings/init.lua")
|
dofile(worldeditadditions.modpath.."/utils/strings/init.lua")
|
||||||
dofile(worldeditadditions.modpath.."/utils/format/init.lua")
|
dofile(worldeditadditions.modpath.."/utils/format/init.lua")
|
||||||
|
|
99
worldeditadditions/utils/mesh.lua
Normal file
99
worldeditadditions/utils/mesh.lua
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
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
|
|
@ -20,3 +20,4 @@ dofile(worldeditadditions.modpath.."/utils/tables/table_map.lua")
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/table_tostring.lua")
|
dofile(worldeditadditions.modpath.."/utils/tables/table_tostring.lua")
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/table_unique.lua")
|
dofile(worldeditadditions.modpath.."/utils/tables/table_unique.lua")
|
||||||
dofile(worldeditadditions.modpath.."/utils/tables/table_unpack.lua")
|
dofile(worldeditadditions.modpath.."/utils/tables/table_unpack.lua")
|
||||||
|
dofile(worldeditadditions.modpath.."/utils/tables/table_contains.lua")
|
||||||
|
|
18
worldeditadditions/utils/tables/table_contains.lua
Normal file
18
worldeditadditions/utils/tables/table_contains.lua
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
--- Looks to see whether a given table contains a given value.
|
||||||
|
-- @param tbl table The table to look in.
|
||||||
|
-- @param target any The target to look for.
|
||||||
|
-- @returns bool Whether the table contains the given target or not.
|
||||||
|
local function table_contains(tbl, target)
|
||||||
|
for key, value in ipairs(tbl) do
|
||||||
|
if value == target then return true end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if worldeditadditions then
|
||||||
|
worldeditadditions.table_contains = table_contains
|
||||||
|
else
|
||||||
|
return table_contains
|
||||||
|
end
|
|
@ -1,3 +1,4 @@
|
||||||
|
--- A 3-dimensional vector.
|
||||||
local Vector3 = {}
|
local Vector3 = {}
|
||||||
Vector3.__index = Vector3
|
Vector3.__index = Vector3
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue