Load B3D models lazily from foreign media paths
parent
803d31fa66
commit
b7bdb090f5
|
@ -4,7 +4,7 @@ Animates the character. Resembles [`playeranim`](https://github.com/minetest-mod
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
Depends on [`modlib`](https://github.com/appgurueu/modlib). Code written by Lars Mueller aka LMD or appguru(eu) and licensed under the MIT license. Media (player model) was created by [MTG contributors](https://github.com/minetest/minetest_game/blob/master/mods/player_api/README.txt) (MirceaKitsune, stujones11 and An0n3m0us) and is licensed under the CC BY-SA 3.0 license, as must be its derivatives (`skinsdb` and `3d_armor` variants).
|
Depends on [`modlib`](https://github.com/appgurueu/modlib). Code written by Lars Mueller aka LMD or appguru(eu) and licensed under the MIT license.
|
||||||
|
|
||||||
## Screenshot
|
## Screenshot
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ Depends on [`modlib`](https://github.com/appgurueu/modlib). Code written by Lars
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Animates head, right arm & body
|
* Animates head, right arm & body
|
||||||
|
* Also provides support for arbitrary player models, as long as `Head`, `Arm_Right` & `Body` bones exist
|
||||||
* Advantages over `playeranim`:
|
* Advantages over `playeranim`:
|
||||||
* Extracts exact animations and bone positions from glTF models
|
* Extracts exact animations and bone positions from glTF models
|
||||||
* Also animates attached players (with restrictions on angles)
|
* Also animates attached players (with restrictions on angles)
|
||||||
|
|
29
main.lua
29
main.lua
|
@ -1,11 +1,19 @@
|
||||||
local models = {}
|
-- TODO deduplicate code: move to modlib (see ghosts mod)
|
||||||
for _, model in ipairs(minetest.get_dir_list(modlib.mod.get_resource"models", false)) do
|
local media_paths = modlib.minetest.media.paths
|
||||||
if modlib.text.ends_with(model, ".b3d") then
|
local models = setmetatable({}, {__index = function(self, filename)
|
||||||
local stream = io.open(modlib.mod.get_resource(minetest.get_current_modname(), "models", model), "r")
|
local _, ext = modlib.file.get_extension(filename)
|
||||||
models[model] = modlib.b3d.read(stream)
|
if not ext or ext:lower() ~= "b3d" then
|
||||||
assert(stream:read() == nil)
|
-- Only B3D support currently
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
local path = assert(media_paths[filename], filename)
|
||||||
|
local stream = io.open(path, "r")
|
||||||
|
local model = assert(modlib.b3d.read(stream))
|
||||||
|
assert(not stream:read(1))
|
||||||
|
stream:close()
|
||||||
|
self[filename] = model
|
||||||
|
return model
|
||||||
|
end})
|
||||||
|
|
||||||
function get_animation_value(animation, keyframe_index, is_rotation)
|
function get_animation_value(animation, keyframe_index, is_rotation)
|
||||||
local values = animation.values
|
local values = animation.values
|
||||||
|
@ -83,7 +91,6 @@ local function handle_player_animations(dtime, player)
|
||||||
local conf = conf.models[mesh] or conf.default
|
local conf = conf.models[mesh] or conf.default
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local range, frame_speed, frame_blend, frame_loop = player:get_animation()
|
local range, frame_speed, frame_blend, frame_loop = player:get_animation()
|
||||||
disable_animation(player)
|
|
||||||
local player_animation = players[name]
|
local player_animation = players[name]
|
||||||
local anim = {range, frame_speed, frame_blend, frame_loop}
|
local anim = {range, frame_speed, frame_blend, frame_loop}
|
||||||
local animation_time = player_animation.animation_time
|
local animation_time = player_animation.animation_time
|
||||||
|
@ -122,6 +129,10 @@ local function handle_player_animations(dtime, player)
|
||||||
bone_positions[bone] = {position = position, rotation = rotation, euler_rotation = euler_rotation}
|
bone_positions[bone] = {position = position, rotation = rotation, euler_rotation = euler_rotation}
|
||||||
end
|
end
|
||||||
local Body, Head, Arm_Right = bone_positions.Body.euler_rotation, bone_positions.Head.euler_rotation, bone_positions.Arm_Right.euler_rotation
|
local Body, Head, Arm_Right = bone_positions.Body.euler_rotation, bone_positions.Head.euler_rotation, bone_positions.Arm_Right.euler_rotation
|
||||||
|
if not (Body and Head and Arm_Right) then
|
||||||
|
-- Model is missing some bones, don't animate serverside
|
||||||
|
return
|
||||||
|
end
|
||||||
local look_vertical = -math.deg(player:get_look_vertical())
|
local look_vertical = -math.deg(player:get_look_vertical())
|
||||||
Head.x = look_vertical
|
Head.x = look_vertical
|
||||||
local interacting = is_interacting(player)
|
local interacting = is_interacting(player)
|
||||||
|
@ -181,6 +192,8 @@ local function handle_player_animations(dtime, player)
|
||||||
end
|
end
|
||||||
Arm_Right.y = clamp(Arm_Right.y, conf.arm_right.yaw)
|
Arm_Right.y = clamp(Arm_Right.y, conf.arm_right.yaw)
|
||||||
|
|
||||||
|
-- Replace animation with serverside bone animation
|
||||||
|
disable_animation(player)
|
||||||
for bone, values in pairs(bone_positions) do
|
for bone, values in pairs(bone_positions) do
|
||||||
player:set_bone_position(bone, values.position, values.euler_rotation)
|
player:set_bone_position(bone, values.position, values.euler_rotation)
|
||||||
end
|
end
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue