LEEF update
This commit is contained in:
parent
8453de9caf
commit
edf8aeb9ed
10
README.md
10
README.md
@ -1,10 +1,10 @@
|
||||
# MTUL-b3d
|
||||
# LEEF-b3d
|
||||
a b3d library that use's [Appgurue's work](https://github.com/appgurueu/modlib), a b3d reader, and expands it's usefulness into node reading, global transformation solving,
|
||||
and more- mostly in one package. Online documentation can be found [here](https://minetest-unification-library.github.io/MTUL-b3d/).
|
||||
and more- mostly in one package. Online documentation can be found [here](https://minetest-unification-library.github.io/LEEF-b3d/).
|
||||
|
||||
dependencies
|
||||
* MTUL-core: provides binary reading (potential rename)
|
||||
* MTUL-cpml: OPTIONAL allows use of b3d_nodes library (for node solving)
|
||||
* LEEF-core: provides binary reading (potential rename)
|
||||
* LEEF-math: OPTIONAL allows use of b3d_nodes library (for node solving)
|
||||
|
||||
features:
|
||||
* read a b3d file
|
||||
@ -15,7 +15,7 @@ features:
|
||||
* solve the global transformation of a node (mat4)
|
||||
|
||||
todo:
|
||||
* allow use of `get_node_by_name()` without CPML. (move to b3d_reader or set alias?)
|
||||
* allow use of `get_node_by_name()` without MATH. (move to b3d_reader or set alias?)
|
||||
* document b3d table contents (I already wrote most of the documentation in modlib's wiki...)
|
||||
* finish b3d writer (NOTE: must offset "frame" by +1 as the reader is modified to match irrlicht)
|
||||
|
||||
|
21
init.lua
21
init.lua
@ -9,27 +9,26 @@
|
||||
has it's own respective directory for licensing purposes.
|
||||
]]
|
||||
|
||||
mtul.b3d_reader = {}
|
||||
mtul.b3d_writer = {}
|
||||
mtul.loaded_modules.b3d = true
|
||||
leef = leef or {}
|
||||
leef.b3d_reader = {}
|
||||
leef.b3d_writer = {}
|
||||
leef.loaded_modules.b3d = true
|
||||
|
||||
local modpath = minetest.get_modpath("mtul_b3d")
|
||||
local modpath = minetest.get_modpath("leef_b3d")
|
||||
--placed in a seperate directory for the license
|
||||
dofile(modpath.."/modlib/read_b3d.lua")
|
||||
dofile(modpath.."/modlib/write_b3d.lua")
|
||||
--dofile(modpath.."/modlib/to_gltf.lua")
|
||||
|
||||
--prevent accidental access of unavailable features:
|
||||
if mtul.loaded_modules.cpml then
|
||||
mtul.b3d_nodes = dofile(modpath.."/nodes.lua")
|
||||
mtul.loaded_modules.b3d_nodes = true
|
||||
mtul.b3d_nodes.loaded = true
|
||||
if leef.math then
|
||||
leef.b3d_nodes = dofile(modpath.."/nodes.lua")
|
||||
else
|
||||
mtul.b3d_nodes = {}
|
||||
setmetatable(mtul.b3d_nodes, {
|
||||
leef.b3d_nodes = {}
|
||||
setmetatable(leef.b3d_nodes, {
|
||||
__index = function(_, k)
|
||||
if k ~= "loaded" then
|
||||
error("MTUL-CPML not present, b3d_nodes module inaccessible.")
|
||||
error("LEEF-Math not present, b3d_nodes not loaded.")
|
||||
else
|
||||
return false
|
||||
end
|
||||
|
@ -1,5 +1,5 @@
|
||||
project="MTUL b3d"
|
||||
title="MTUL b3d reader/writer documentation"
|
||||
project="LEEF b3d"
|
||||
title="LEEF b3d reader/writer documentation"
|
||||
description="A library containing hopefully all you need to read, solve and navigate a b3d. Aswell as (eventually) write one."
|
||||
format="markdown"
|
||||
backtick_references=false
|
||||
|
10
mod.conf
10
mod.conf
@ -1,6 +1,6 @@
|
||||
name = mtul_b3d
|
||||
title = MTUL b3d standalone
|
||||
description = a b3d reader for minetest, cloned from modlib. Requires MTUL-core, also requires MTUL-CPML for nodes module.
|
||||
depends = mtul_filesystem
|
||||
optional_depends = mtul_cpml
|
||||
name = leef_b3d
|
||||
title = LEEF b3d
|
||||
description = a b3d reader for minetest, cloned from modlib. Requires LEEF-core, requires LEEF-Math for nodes module.
|
||||
depends = leef_filesystem
|
||||
optional_depends = leef_math
|
||||
author = FatalError42O, Appgurue
|
@ -2,7 +2,7 @@
|
||||
-- note: capitlization of name indicates a "chunk" defined by the blitz3d format (see b3d_specification.txt)
|
||||
--@module b3d_reader
|
||||
|
||||
local read_int, read_single = mtul.binary.read_int, mtul.binary.read_single
|
||||
local read_int, read_single = leef.binary.read_int, leef.binary.read_single
|
||||
local function tbl_append(table, other_table)
|
||||
local length = #table
|
||||
for index, value in ipairs(other_table) do
|
||||
@ -20,14 +20,14 @@ end
|
||||
--reads a model directly (based on name). Note that "node_only" abstracts chunks not necessary to finding the position/transform of a bone/node.
|
||||
|
||||
--- read b3d models by their name. This simplifies read_from_stream.
|
||||
-- @function mtul.b3d_reader.read_model
|
||||
-- @function leef.b3d_reader.read_model
|
||||
-- @param modelname string, the name of model you are trying to read.
|
||||
-- @param node_only bool, specifies wether to ignore textures, meshes, or anything else. Use this if you're only trying to solve bone transforms.
|
||||
-- @return b3d table (documentation needed!)
|
||||
function mtul.b3d_reader.read_model(modelname, node_only)
|
||||
function leef.b3d_reader.read_model(modelname, node_only)
|
||||
assert(modelname, "no modelname provided")
|
||||
-- @todo remove core dependancy on
|
||||
local path = assert(mtul.paths.media_paths[modelname], "no model found by the name "..modelname.."'")
|
||||
local path = assert(leef.paths.media_paths[modelname], "no model found by the name "..modelname.."'")
|
||||
local out
|
||||
local ignored
|
||||
if node_only then
|
||||
@ -35,8 +35,8 @@ function mtul.b3d_reader.read_model(modelname, node_only)
|
||||
end
|
||||
local stream = io.open(path, "rb")
|
||||
if not stream then return end --if the file wasn't found we probably shouldnt just assert.
|
||||
out = mtul.b3d_reader.read_from_stream(stream, ignored)
|
||||
assert(stream:read(1)==nil, "MTUL b3d_reader: unknown error, EOF not reached")
|
||||
out = leef.b3d_reader.read_from_stream(stream, ignored)
|
||||
assert(stream:read(1)==nil, "LEEF b3d_reader: unknown error, EOF not reached")
|
||||
stream:close()
|
||||
return out
|
||||
end
|
||||
@ -66,14 +66,14 @@ end
|
||||
-- @field 6 "BONE" node vertex weights
|
||||
-- @field 7 "ANIM" animation information
|
||||
-- @field 8 "KEYS" keyframes
|
||||
-- @table ignore_chunks
|
||||
-- @table chunks
|
||||
|
||||
--- read directly from file
|
||||
-- @function mtul.b3d_reader.read_from_stream
|
||||
-- @function leef.b3d_reader.read_from_stream
|
||||
-- @param stream the file object (from the io library) to read from. Make sure you open it as "rb" (read binary.)
|
||||
-- @param ignore_chunks a list of @{ignore_chunks} to be ignored
|
||||
-- @return @{BB3D}
|
||||
function mtul.b3d_reader.read_from_stream(stream, ignore_chunks)
|
||||
-- @param ignore_chunks a list of @{chunks} to be ignored (documentation needed)
|
||||
-- @return @{BB3D} (documentation needed!)
|
||||
function leef.b3d_reader.read_from_stream(stream, ignore_chunks)
|
||||
local left = 8
|
||||
|
||||
local ignored = {}
|
||||
@ -164,12 +164,6 @@ function mtul.b3d_reader.read_from_stream(stream, ignore_chunks)
|
||||
local chunk
|
||||
local chunks = {
|
||||
TEXS = function()
|
||||
--- textures
|
||||
--@field file
|
||||
--@field flags
|
||||
--@field pos table {float, float}
|
||||
--@field pos table {float, float}
|
||||
--@table TEXS
|
||||
local textures = {}
|
||||
while content() do
|
||||
local tex = {}
|
||||
@ -184,14 +178,6 @@ function mtul.b3d_reader.read_from_stream(stream, ignore_chunks)
|
||||
return textures
|
||||
end,
|
||||
BRUS = function()
|
||||
--- brushes (materials)
|
||||
-- @field name
|
||||
-- @field color
|
||||
-- @field shininess
|
||||
-- @field blend
|
||||
-- @field fx
|
||||
-- @field texture_id
|
||||
-- @table BRUS
|
||||
local brushes = {}
|
||||
local n_texs = int()
|
||||
assert(n_texs <= 8)
|
||||
@ -344,13 +330,11 @@ function mtul.b3d_reader.read_from_stream(stream, ignore_chunks)
|
||||
return ret
|
||||
end,
|
||||
NODE = function()
|
||||
--- a node chunk possibly containing the following chunks.
|
||||
--- node
|
||||
-- a node chunk possibly containing the following chunks.
|
||||
-- there are three possible "types" of nodes. All bones will contain the following chunks:
|
||||
-- `position`, `rotation`, `scale`.
|
||||
-- Bones will have a bone field which will contain IDs from it's parent node's mesh chunk.
|
||||
-- Meshes will have a mesh field containing information about their mesh.
|
||||
-- Pivots will have neither of those and simply serve as parents to child nodes. <3
|
||||
--
|
||||
-- position, rotation, scale. Bones will have a
|
||||
-- bone field which will contain IDs from it's parent node's mesh chunk.
|
||||
-- @field name
|
||||
-- @field type string which is either "pivot", "bone" or "mesh"
|
||||
-- @field children a list of child nodes, Transoformations (position, rotation, scale) will be applied to the children.
|
||||
@ -415,11 +399,12 @@ function mtul.b3d_reader.read_from_stream(stream, ignore_chunks)
|
||||
end)
|
||||
return node
|
||||
end,
|
||||
--- note: in `b3d_writer` the node_paths field is ignored
|
||||
-- @field node_paths all nodes in the model indexed by a table @{node_paths}
|
||||
--- b3d table
|
||||
-- note: in the b3d writer the node_paths field is ignored
|
||||
-- @field node_paths all of the nodes in the model @{b3d_nodes}
|
||||
-- @field node a table containing the root @{NODE} of the model.
|
||||
-- @field textures a list of @{TEXS} chunks
|
||||
-- @field brushes a list of @{BRUS} chunks
|
||||
-- @field textures @{TEXS} texture information
|
||||
-- @field brushes @{BRUS} material information
|
||||
-- @field version `{major=float, minor=float}` this functionally means nothing, but it's version information.
|
||||
-- @table BB3D
|
||||
BB3D = function()
|
||||
@ -473,7 +458,7 @@ function mtul.b3d_reader.read_from_stream(stream, ignore_chunks)
|
||||
--also, Fatal here: for the sake of my reputation (which is nonexistent), typically I wouldn't nest these functions
|
||||
--because I am not a physcopath and or a german named Lars, but for the sake of consistency it has to happen.
|
||||
--(Not that its *always* a bad idea, but unless you're baking in parameters it's sort of useless and potentially wasteful)
|
||||
local copy_path = function(tbl)
|
||||
local copy_path = leef.table and leef.table.shallow_copy or function(tbl)
|
||||
local new_table = {}
|
||||
for i, v in pairs(tbl) do
|
||||
new_table[i] = v
|
||||
@ -497,10 +482,10 @@ function mtul.b3d_reader.read_from_stream(stream, ignore_chunks)
|
||||
make_paths(self.node, {}, self.node_paths)
|
||||
|
||||
--b3d metatable unimplemented
|
||||
return setmetatable(self, mtul._b3d_metatable or {})
|
||||
return setmetatable(self, leef._b3d_metatable or {})
|
||||
end
|
||||
|
||||
--- node paths
|
||||
-- a list of nodes indexed by a list which containing every related parent node aswell as itself.
|
||||
-- a list of nodes indexed by a hieracrchy of nodes i.e. "path.to.node"
|
||||
-- @field (...) node
|
||||
-- @table node_paths
|
@ -9,7 +9,7 @@
|
||||
--! Highly experimental; expect bugs!
|
||||
|
||||
-- glTF constants
|
||||
local write_int, write_uint, write_single = mtul.binary.write_int, mtul.binary.write_uint, mtul.binary.write_single
|
||||
local write_int, write_uint, write_single = leef.binary.write_int, leef.binary.write_uint, leef.binary.write_single
|
||||
local array_buffer = 34962 -- "Buffer containing vertex attributes, such as vertices, texcoords or colors."
|
||||
local element_array_buffer = 34963 -- "Buffer used for element indices."
|
||||
local component_type = {
|
||||
@ -76,7 +76,7 @@ local function write_quaternion(write_byte, quat)
|
||||
return write_floats(write_byte, quaternion_to_gltf(quat), 4)
|
||||
end
|
||||
|
||||
function mtul.b3d.to_gltf(self)
|
||||
function leef.b3d.to_gltf(self)
|
||||
-- Accessor helper: Stores arrays of raw data in a buffer, produces views & accessors.
|
||||
-- Everything is dumped in the same large buffer.
|
||||
local buffer_rope = {} -- buffer content (table of strings)
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
--Writer
|
||||
local write_int, write_single = mtul.binary.write_int, mtul.binary.write_single
|
||||
local write_int, write_single = leef.binary.write_int, leef.binary.write_single
|
||||
local string_char = string.char
|
||||
|
||||
local function write_rope(self)
|
||||
@ -37,7 +37,7 @@ local function write_rope(self)
|
||||
end
|
||||
|
||||
local function float(val)
|
||||
write_single(byte, mtul.binary.fround(val))
|
||||
write_single(byte, leef.binary.fround(val))
|
||||
end
|
||||
|
||||
local function float_array(arr, len)
|
||||
@ -151,8 +151,7 @@ local function write_rope(self)
|
||||
chunk("KEYS", function()
|
||||
int(flags)
|
||||
for _, frame in ipairs(keys) do
|
||||
--reader offsets by 1, so writer should to.
|
||||
int(frame.frame+1)
|
||||
int(frame.frame)
|
||||
if frame.position then vector3(frame.position) end
|
||||
if frame.scale then vector3(frame.scale) end
|
||||
if frame.rotation then quaternion(frame.rotation) end
|
||||
@ -219,18 +218,18 @@ local function write_rope(self)
|
||||
end
|
||||
|
||||
--- output a string of binary in the blitz 3d format
|
||||
-- @function mtul.b3d_writer.write_string
|
||||
-- @param self @{b3d_reader.BB3D|BB3D chunk}
|
||||
-- @function leef.b3d_writer.write_string
|
||||
-- @param self @{BB3D}
|
||||
-- @return string containing the binary file
|
||||
function mtul.b3d_writer.write_string(self)
|
||||
function leef.b3d_writer.write_string(self)
|
||||
return table.concat(write_rope(self))
|
||||
end
|
||||
|
||||
--- output in the blitz3d format file reference
|
||||
-- @function mtul.b3d_writer.write_model_to_file
|
||||
-- @param self @{b3d_reader.BB3D|BB3D chunk}
|
||||
-- @function leef.b3d_writer.write_model_to_file
|
||||
-- @param self @{BB3D}
|
||||
-- @param stream io file object to write to
|
||||
function mtul.b3d_writer.write_model_to_file(self, stream)
|
||||
function leef.b3d_writer.write_model_to_file(self, stream)
|
||||
for _, str in ipairs(write_rope(self)) do
|
||||
stream:write(str)
|
||||
end
|
||||
|
28
nodes.lua
28
nodes.lua
@ -1,18 +1,18 @@
|
||||
--- allows you to get information about nodes (bones or meshes) within a b3d table (generated with `b3d_reader`)
|
||||
--- located in `mtul.b3d_nodes`.
|
||||
--- WARNING! mtul-cpml must be present for this module to run!
|
||||
--- located in `leef.b3d_nodes`.
|
||||
--- WARNING! leef_math must be present for this module to run!
|
||||
--@module b3d_nodes
|
||||
--@warning for this module mtul_cpml is required, trying to use these functions without mtul_cpml ran will error.
|
||||
--@warning for this module leef_math is required, trying to use these functions without leef_math ran will error.
|
||||
|
||||
--gets node by name
|
||||
--this breaks if you have multiple nodes with the same name.
|
||||
--if there are meshes that go by the same name, you can set "bone" param to true.
|
||||
local b3d_nodes = {}
|
||||
local mat4 = mtul.math.mat4
|
||||
local quat = mtul.math.quat
|
||||
local mat4 = leef.math.mat4
|
||||
local quat = leef.math.quat
|
||||
|
||||
--- get a node by it's name
|
||||
-- @function mtul.b3d_nodes.get_node_by_name
|
||||
-- @function leef.b3d_nodes.get_node_by_name
|
||||
-- @param self the b3d table (from b3d_reader)
|
||||
-- @param node_name the name of the node to fine
|
||||
-- @param is_bone (optional) bool to indicate wether the node is a bone or not (incase there's a mesh named the same thing). False will only return meshes and pivots, true will only return bones. Nil will return any.
|
||||
@ -28,7 +28,7 @@ function b3d_nodes.get_node_by_name(self, node_name, is_bone)
|
||||
end
|
||||
end
|
||||
--don't know why I'd ever just not return nil?
|
||||
--error("MTUL-b3d, b3d_nodes: no node found by the name '"..tostring(node_name).."'")
|
||||
--error("LEEF-b3d, b3d_nodes: no node found by the name '"..tostring(node_name).."'")
|
||||
end
|
||||
|
||||
--non-methods:
|
||||
@ -44,12 +44,12 @@ local interpolate = function(a, b, ratio)
|
||||
end
|
||||
|
||||
--- get the local "TRS" (translation, rotation, scale) of a bone in animation. This is used for global transformation calculations.
|
||||
--- quaternion is returned as a string indexed table because it needs to be a cpml object to be interpolated, also has to be usable anyway.
|
||||
-- @function mtul.b3d_nodes.get_animated_local_trs
|
||||
--- quaternion is returned as a string indexed table because it needs to be a math object to be interpolated, also has to be usable anyway.
|
||||
-- @function leef.b3d_nodes.get_animated_local_trs
|
||||
-- @param node table, the node from within a b3d table to read (as outputed by b3d_reader).
|
||||
-- @param target_frame float, the frame to find the TRS in, can be inbetween frames/keyframes (of course).
|
||||
-- @return `position` ordered table: {x, y, z}
|
||||
-- @return `rotation` quat from `mtul_cpml`: (example) {w=0,x=0,y=0,z=1}
|
||||
-- @return `rotation` quat from `leef_math`: (example) {w=0,x=0,y=0,z=1}
|
||||
-- @return `scale` ordered table: {x, y, z}
|
||||
--outputs need cleaning up.
|
||||
function b3d_nodes.get_animated_local_trs(node, target_frame)
|
||||
@ -90,11 +90,11 @@ end
|
||||
--param 3 (outputs) is either "rotation" or "transform"- determines what's calculated. You can use this if you dont want uncessary calculations. If nil outputs both
|
||||
|
||||
--- get a node's global mat4 transform and rotation.
|
||||
-- @function mtul.b3d_nodes.get_node_global_transform
|
||||
-- @function leef.b3d_nodes.get_node_global_transform
|
||||
-- @param node table, the node from within a b3d table to read (as outputed by `b3d_reader`).
|
||||
-- @param frame float, the frame to find the transform and rotation in.
|
||||
-- @param outputs (optional) string, either "rotation" or "transform". Set to nil to return both.
|
||||
-- @return `global_transform`, a matrix 4x4, note that CPML's tranforms are column major (i.e. 1st column is 1, 2, 3, 4). (see `mtul_cpml` docs)
|
||||
-- @return `global_transform`, a matrix 4x4, note that MATH's tranforms are column major (i.e. 1st column is 1, 2, 3, 4). (see `leef_math` docs)
|
||||
-- @return `rotation quat`, the quaternion rotation in global space. (cannot be assumed to be normalized, this uses raw interpolated data from the b3d reader)
|
||||
function b3d_nodes.get_node_global_transform(node, frame, outputs)
|
||||
local global_transform
|
||||
@ -137,7 +137,7 @@ end
|
||||
--Returns X, Y, Z. is_bone is optional, if "node" is the name of a node (and not the node table), parameter 1 (self) and parameter 3 (is_bone) is used to find it.
|
||||
|
||||
--- find the position of a node in global model space.
|
||||
--@function mtul.b3d_nodes.get_node_global_position
|
||||
--@function leef.b3d_nodes.get_node_global_position
|
||||
--@param self b3d table, (optional if node is a node table and not name)
|
||||
--@param node string or table, either the node from b3d table or a the name of the node to find.
|
||||
--@param is_bone (optional) if node is string, this is used to find it (see `get_node_by_name`)
|
||||
@ -156,7 +156,7 @@ function b3d_nodes.get_node_global_position(self, node, is_bone, frame)
|
||||
return transform[13], transform[14], transform[15]
|
||||
end
|
||||
--- find the global rotation of a node in model space.
|
||||
--@function mtul.b3d_nodes.get_node_rotation
|
||||
--@function leef.b3d_nodes.get_node_rotation
|
||||
--@param self b3d table, (optional if node is a node table and not name)
|
||||
--@param node string or table, either the node from b3d table or a the name of the node to find.
|
||||
--@param is_bone (optional) if node is string, this is used to find it (see `get_node_by_name`)
|
||||
|
Loading…
x
Reference in New Issue
Block a user