57 lines
2.0 KiB
Lua
57 lines
2.0 KiB
Lua
local mlvec = modlib.vector
|
|
|
|
local media_paths = epidermis.media_paths
|
|
|
|
local bad_character_b3d_path = modlib.mod.get_resource"character_without_normals.b3d"
|
|
local bad_character_b3d_hash = minetest.sha1(modlib.file.read(bad_character_b3d_path))
|
|
local fixed_character_b3d_path = modlib.mod.get_resource"character_with_normals.b3d"
|
|
|
|
return setmetatable({}, {__index = function(self, filename)
|
|
local _, ext = modlib.file.get_extension(filename)
|
|
if not ext or ext:lower() ~= "b3d" then
|
|
-- Only B3D support currently
|
|
return
|
|
end
|
|
local path = assert(media_paths[filename], filename)
|
|
-- HACK replace a "bad" character.b3d with a fixed version that includes normals
|
|
-- Susceptible to SHA1 collisions, but so is MT's media loading process
|
|
-- See https://github.com/minetest/minetest_game/pull/2902
|
|
if filename == "character.b3d" and minetest.sha1(modlib.file.read(path)) == bad_character_b3d_hash then
|
|
path = fixed_character_b3d_path
|
|
end
|
|
local model = io.open(path, "r")
|
|
local character = assert(modlib.b3d.read(model))
|
|
assert(not model:read(1))
|
|
model:close()
|
|
local mesh = assert(character.node.mesh)
|
|
local vertices = assert(mesh.vertices)
|
|
for _, vertex in ipairs(vertices) do
|
|
-- Minetest hardcodes a blocksize of 10 model units
|
|
vertex.pos = mlvec.divide_scalar(vertex.pos, 10)
|
|
end
|
|
-- Triangle sets by texture index
|
|
local tris_by_tex = {}
|
|
local func = modlib.func
|
|
for _, set in pairs(assert(mesh.triangle_sets)) do
|
|
local tris = set.vertex_ids
|
|
for _, tri in pairs(tris) do
|
|
modlib.table.map(tri, func.curry(func.index, vertices))
|
|
tri.poses = {tri[1].pos, tri[2].pos, tri[3].pos}
|
|
end
|
|
local brush_id = tris.brush_id or mesh.brush_id
|
|
local tex_id
|
|
if brush_id then
|
|
tex_id = assert(character.brushes[brush_id].texture_id[1])
|
|
else
|
|
-- No brush, default to first texture
|
|
tex_id = 1
|
|
end
|
|
tris_by_tex[tex_id] = tris_by_tex[tex_id] and modlib.table.append(tris_by_tex[tex_id], tris) or tris
|
|
end
|
|
self[filename] = {
|
|
vertices = vertices,
|
|
triangle_sets = tris_by_tex,
|
|
frames = (character.node.animation or {}).frames or 1
|
|
}
|
|
return self[filename]
|
|
end}) |