Build out level animation export logic

This commit is contained in:
James Lambert 2022-12-30 20:28:27 -07:00
parent ff3545d409
commit 226057dd61
15 changed files with 422 additions and 58 deletions

View file

@ -210,9 +210,9 @@ build/src/player/player.o: build/assets/models/player/chell.h build/assets/mater
build/assets/models/player/chell.h: assets/materials/chell.skm.yaml build/assets/models/player/chell.h: assets/materials/chell.skm.yaml
build/anims.ld: $(ANIM_LIST) tools/generate_animation_ld.js build/anims.ld: $(ANIM_LIST) $(ANIM_TEST_CHAMBERS) tools/generate_animation_ld.js
@mkdir -p $(@D) @mkdir -p $(@D)
node tools/generate_animation_ld.js $@ $(ANIM_LIST) node tools/generate_animation_ld.js $@ $(ANIM_LIST) $(ANIM_TEST_CHAMBERS)
#################### ####################
## Test Chambers ## Test Chambers
@ -223,6 +223,8 @@ TEST_CHAMBERS = assets/test_chambers/test_chamber_00/test_chamber_00.blend \
assets/test_chambers/test_chamber_02/test_chamber_02.blend \ assets/test_chambers/test_chamber_02/test_chamber_02.blend \
assets/test_chambers/test_chamber_03/test_chamber_03.blend assets/test_chambers/test_chamber_03/test_chamber_03.blend
ANIM_TEST_CHAMBERS = build/assets/test_chambers/test_chamber_03/test_chamber_03_anim.o
TEST_CHAMBER_HEADERS = $(TEST_CHAMBERS:%.blend=build/%.h) TEST_CHAMBER_HEADERS = $(TEST_CHAMBERS:%.blend=build/%.h)
TEST_CHAMBER_OBJECTS = $(TEST_CHAMBERS:%.blend=build/%_geo.o) TEST_CHAMBER_OBJECTS = $(TEST_CHAMBERS:%.blend=build/%_geo.o)
@ -232,7 +234,7 @@ build/%.fbx: %.blend
@mkdir -p $(@D) @mkdir -p $(@D)
$(BLENDER_3_0) $< --background --python tools/export_fbx.py -- $@ $(BLENDER_3_0) $< --background --python tools/export_fbx.py -- $@
build/assets/test_chambers/%.h build/assets/test_chambers/%_geo.c: build/assets/test_chambers/%.fbx build/assets/materials/static.h $(SKELATOOL64) $(TEXTURE_IMAGES) $(LUA_FILES) build/assets/test_chambers/%.h build/assets/test_chambers/%_geo.c build/assets/test_chambers/%_anim.c: build/assets/test_chambers/%.fbx build/assets/materials/static.h $(SKELATOOL64) $(TEXTURE_IMAGES) $(LUA_FILES)
$(SKELATOOL64) --script tools/export_level.lua --fixed-point-scale 256 --model-scale 0.01 --name $(<:build/assets/test_chambers/%.fbx=%) -m assets/materials/static.skm.yaml -o $(<:%.fbx=%.h) $< $(SKELATOOL64) --script tools/export_level.lua --fixed-point-scale 256 --model-scale 0.01 --name $(<:build/assets/test_chambers/%.fbx=%) -m assets/materials/static.skm.yaml -o $(<:%.fbx=%.h) $<
build/assets/test_chambers/%.o: build/assets/test_chambers/%.c build/assets/materials/static.h build/assets/test_chambers/%.o: build/assets/test_chambers/%.c build/assets/materials/static.h

View file

@ -82,7 +82,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2022-12-29 21:32:18 </i> <i style="float:right;">Last updated 2022-12-30 12:30:52 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -33,6 +33,7 @@
<h2>Contents</h2> <h2>Contents</h2>
<ul> <ul>
<li><a href="#Functions">Functions</a></li> <li><a href="#Functions">Functions</a></li>
<li><a href="#Tables">Tables</a></li>
<li><a href="#Class_Armature">Class Armature </a></li> <li><a href="#Class_Armature">Class Armature </a></li>
</ul> </ul>
@ -64,14 +65,33 @@
<td class="summary"></td> <td class="summary"></td>
</tr> </tr>
<tr> <tr>
<td class="name" nowrap><a href="#export_animations">export_animations (name_hint, armature, animations, file_suffix, animation_file_suffix)</a></td> <td class="name" nowrap><a href="#export_animation">export_animation (animation, armature, name_hint, file_suffix, animation_file_suffix)</a></td>
<td class="summary"></td>
</tr>
<tr>
<td class="name" nowrap><a href="#filter_animations_for_armature">filter_animations_for_armature (armature, animations)</a></td>
<td class="summary"></td>
</tr>
<tr>
<td class="name" nowrap><a href="#export_armature">export_armature (armature, gfx_reference_or_nil, name_hint, file_suffix)</a></td>
<td class="summary"></td>
</tr>
</table>
<h2><a href="#Tables">Tables</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Clip">Clip</a></td>
<td class="summary"></td> <td class="summary"></td>
</tr> </tr>
</table> </table>
<h2><a href="#Class_Armature">Class Armature </a></h2> <h2><a href="#Class_Armature">Class Armature </a></h2>
<table class="function_list"> <table class="function_list">
<tr> <tr>
<td class="name" nowrap><a href="#Armature:has_node">Armature:has_node ()</a></td> <td class="name" nowrap><a href="#Armature:has_node">Armature:has_node (Node)</a></td>
<td class="summary"></td>
</tr>
<tr>
<td class="name" nowrap><a href="#Armature:get_parent_bone">Armature:get_parent_bone (Node)</a></td>
<td class="summary"></td> <td class="summary"></td>
</tr> </tr>
</table> </table>
@ -111,8 +131,8 @@
</dd> </dd>
<dt> <dt>
<a name = "export_animations"></a> <a name = "export_animation"></a>
<strong>export_animations (name_hint, armature, animations, file_suffix, animation_file_suffix)</strong> <strong>export_animation (animation, armature, name_hint, file_suffix, animation_file_suffix)</strong>
</dt> </dt>
<dd> <dd>
@ -120,16 +140,16 @@
<h3>Parameters:</h3> <h3>Parameters:</h3>
<ul> <ul>
<li><span class="parameter">name_hint</span> <li><span class="parameter">animation</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span> <span class="types"><span class="type">sk_scene.Animation</span></span>
</li> </li>
<li><span class="parameter">armature</span> <li><span class="parameter">armature</span>
<span class="types"><a class="type" href="../modules/sk_animation.html#Armature">Armature</a></span> <span class="types"><a class="type" href="../modules/sk_animation.html#Armature">Armature</a></span>
</li> </li>
<li><span class="parameter">animations</span> <li><span class="parameter">name_hint</span>
<span class="types"><span class="type">{sk_scene.Animation,...}</span></span> <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</li> </li>
<li><span class="parameter">file_suffix</span> <li><span class="parameter">file_suffix</span>
@ -142,6 +162,119 @@
</li> </li>
</ul> </ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/sk_animation.html#Clip">Clip</a></span>
the exported clip object use sk_definition_writer.reference_to(clip) to reference in other data
</ol>
</dd>
<dt>
<a name = "filter_animations_for_armature"></a>
<strong>filter_animations_for_armature (armature, animations)</strong>
</dt>
<dd>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">armature</span>
<span class="types"><a class="type" href="../modules/sk_animation.html#Armature">Armature</a></span>
</li>
<li><span class="parameter">animations</span>
<span class="types"><span class="type">{sk_scene.Animation,...}</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">{sk_scene.Animation,...}</span></span>
</ol>
</dd>
<dt>
<a name = "export_armature"></a>
<strong>export_armature (armature, gfx_reference_or_nil, name_hint, file_suffix)</strong>
</dt>
<dd>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">armature</span>
<span class="types"><a class="type" href="../modules/sk_animation.html#Armature">Armature</a></span>
</li>
<li><span class="parameter">gfx_reference_or_nil</span>
<span class="types"><span class="type">sk_definition_writer.RefType</span> or <span class="type">nil</span></span>
</li>
<li><span class="parameter">name_hint</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</li>
<li><span class="parameter">file_suffix</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
</ol>
</dd>
</dl>
<h2 class="section-header "><a name="Tables"></a>Tables</h2>
<dl class="function">
<dt>
<a name = "Clip"></a>
<strong>Clip</strong>
</dt>
<dd>
<h3>Fields:</h3>
<ul>
<li><span class="parameter">nFrames</span>
<span class="types"><span class="type">number</span></span>
</li>
<li><span class="parameter">nBones</span>
<span class="types"><span class="type">number</span></span>
</li>
<li><span class="parameter">frames</span>
<span class="types"><span class="type">sk_definition_writer.RefType</span></span>
</li>
<li><span class="parameter">fps</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
@ -153,13 +286,56 @@
<dl class="function"> <dl class="function">
<dt> <dt>
<a name = "Armature:has_node"></a> <a name = "Armature:has_node"></a>
<strong>Armature:has_node ()</strong> <strong>Armature:has_node (Node)</strong>
</dt> </dt>
<dd> <dd>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">Node</span>
<span class="types"><span class="type">sk_scene.Node</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Armature:get_parent_bone"></a>
<strong>Armature:get_parent_bone (Node)</strong>
</dt>
<dd>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">Node</span>
<span class="types"><span class="type">sk_scene.Node</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<li>
<span class="types"><span class="type">sk_scene.Node</span> or <span class="type">nil</span></span>
</li>
<li>
<span class="types"><span class="type">number</span></span>
bone_index|nil</li>
</ol>
@ -172,7 +348,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2022-12-29 21:32:18 </i> <i style="float:right;">Last updated 2022-12-30 12:30:52 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -542,7 +542,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2022-12-29 21:32:18 </i> <i style="float:right;">Last updated 2022-12-30 12:30:52 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -136,7 +136,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2022-12-29 21:32:18 </i> <i style="float:right;">Last updated 2022-12-30 12:30:52 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -901,7 +901,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2022-12-29 21:32:18 </i> <i style="float:right;">Last updated 2022-12-30 12:30:52 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -303,7 +303,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2022-12-29 21:32:18 </i> <i style="float:right;">Last updated 2022-12-30 12:30:52 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -429,7 +429,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2022-12-29 21:32:18 </i> <i style="float:right;">Last updated 2022-12-30 12:30:52 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -187,7 +187,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2022-12-29 21:32:18 </i> <i style="float:right;">Last updated 2022-12-30 12:30:52 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -80,15 +80,15 @@ local function build_armature(animation_nodes)
return (node_order[a] or 0) < (node_order[b] or 0) return (node_order[a] or 0) < (node_order[b] or 0)
end) end)
local nodes_as_set = {} local node_to_index = {}
for _, node in pairs(nodes) do for index, node in pairs(nodes) do
nodes_as_set[node] = true node_to_index[node] = index
end end
return setmetatable({ return setmetatable({
nodes = nodes, nodes = nodes,
nodes_as_set = nodes_as_set, node_to_index = node_to_index,
}, Armature) }, Armature)
end end
@ -106,12 +106,17 @@ local function add_to_node_pose(node_pose, node)
end end
end end
local function build_node_pose(node, node_pose) local function build_node_pose(armature, node, node_pose)
local result = nil local result = nil
while node do while node do
result = result and (node_pose[node] * result) or node_pose[node] result = result and (node_pose[node] * result) or node_pose[node]
node = node.parent node = node.parent
-- only build the transform relative to the ancestor in the chain
if node and armature:has_node(node) then
return result
end
end end
return result return result
@ -135,7 +140,7 @@ end
local function build_armature_pose(armature, node_pose, result) local function build_armature_pose(armature, node_pose, result)
for _, node in pairs(armature.nodes) do for _, node in pairs(armature.nodes) do
local pose = build_node_pose(node, node_pose) local pose = build_node_pose(armature, node, node_pose)
local pos, rot = pose:decompose() local pos, rot = pose:decompose()
@ -170,26 +175,30 @@ local function build_animation(armature, animation)
return frames, n_frames return frames, n_frames
end end
--- @function export_animations --- @table Clip
--- @tparam string name_hint --- @tfield number nFrames
--- @tfield number nBones
--- @tfield sk_definition_writer.RefType frames
--- @tfield number fps
--- @function build_animation_clip
--- @tparam sk_scene.Animation animation
--- @tparam Armature armature --- @tparam Armature armature
--- @tparam {sk_scene.Animation,...} animations
--- @tparam string file_suffix
--- @tparam string animation_file_suffix --- @tparam string animation_file_suffix
local function export_animations(name_hint, armature, animations, file_suffix, animation_file_suffix) --- @treturn Clip the exported clip object use sk_definition_writer.reference_to(clip) to reference in other data
for _, animation in pairs(animations) do local function build_animation_clip(animation, armature, animation_file_suffix)
local animation_frames, n_frames = build_animation(armature, animation) local animation_frames, n_frames = build_animation(armature, animation)
sk_definition_writer.add_definition(name_hint .. animation.name .. '_frames', 'struct SKAnimationBoneFrame[]', animation_file_suffix, animation_frames)
sk_definition_writer.add_definition(animation.name .. '_frames', 'struct SKAnimationBoneFrame[]', animation_file_suffix, animation_frames)
local clip = { local clip = {
nFrames = n_frames, nFrames = n_frames,
nBones = #armature.nodes, nBones = #armature.nodes,
frames = sk_definition_writer.reference_to(animation_frames, 1), frames = sk_definition_writer.reference_to(animation_frames, 1),
fps = sk_input.settings.ticks_per_second fps = sk_input.settings.ticks_per_second
} }
sk_definition_writer.add_definition(name_hint .. animation.name .. '_clip', 'struct SKAnimationClip', file_suffix, clip) return clip
end
end end
local function build_armature_for_animations(animations) local function build_armature_for_animations(animations)
@ -210,18 +219,108 @@ local function build_armature_for_animations(animations)
return build_armature(all_nodes) return build_armature(all_nodes)
end end
--- @function filter_animations_for_armature
--- @tparam Armature armature
--- @tparam {sk_scene.Animation,...} animations
--- @treturn {sk_scene.Animation,...}
local function filter_animations_for_armature(armature, animations)
local result = {}
for _, animation in pairs(animations) do
for _, channel in pairs(animation.channels) do
if armature:has_node(sk_scene.node_with_name(channel.node_name)) then
table.insert(result, animation)
break
end
end
end
return result
end
--- @function build_armature_data
--- @tparam Armature armature
--- @tparam sk_definition_writer.RefType|nil gfx_reference_or_nil
--- @tparam string name_hint
--- @tparam string file_suffix
--- @treturn table
local function build_armature_data(armature, gfx_reference_or_nil, name_hint, file_suffix)
local node_pose = {}
local transforms = {}
local parent_mapping = {}
for _, node in pairs(armature.nodes) do
add_to_node_pose(node_pose, node)
-- calculate base pose
local relative_transform = build_node_pose(armature, node, node_pose)
local pos, rot, scale = relative_transform:decompose()
table.insert(transforms, {pos, rot, scale})
-- calculate parent mapping
local _, parent_index = armature:get_parent_bone(node)
if parent_index then
table.insert(parent_mapping, parent_index - 1)
else
table.insert(parent_mapping, sk_definition_writer.raw('NO_BONE_PARENT'))
end
end
sk_definition_writer.add_definition(name_hint .. '_base_transform', 'struct Transform[]', file_suffix, transforms)
sk_definition_writer.add_definition(name_hint .. '_parent_mapping', 'unsigned short[]', file_suffix, parent_mapping)
return {
displayList = gfx_reference_or_nil or sk_definition_writer.null_value,
boneTransforms = sk_definition_writer.reference_to(transforms, 1),
numberOfBones = #armature.nodes,
numberOfAttachments = 0,
boneParentIndex = sk_definition_writer.reference_to(parent_mapping, 1),
}
end
--- @type Armature --- @type Armature
--- @tfield {sk_scene.Node,...} nodes --- @tfield {sk_scene.Node,...} nodes
Armature.__index = Armature; Armature.__index = Armature;
--- @function has_node --- @function has_node
--- @tparam sk_scene.Node Node
--- @treturn boolean
Armature.has_node = function(armature, node) Armature.has_node = function(armature, node)
return armature.nodes_as_set[node] or false return armature.node_to_index[node] or false
end
--- @function get_parent_bone
--- @tparam sk_scene.Node Node
--- @treturn sk_scene.Node|nil
--- @treturn number bone_index|nil
Armature.get_parent_bone = function(armature, node)
local curr = node
while curr do
-- check if current parent is in the armature
local parent_index = armature.node_to_index[node.parent]
if parent_index then
-- return the parent bone if in armature
return armature.nodes[parent_index], parent_index
end
curr = curr.parent
end
-- no parent bone in armature so return nil
return nil, nil
end end
return { return {
build_armature = build_armature, build_armature = build_armature,
export_animations = export_animations,
build_armature_for_animations = build_armature_for_animations, build_armature_for_animations = build_armature_for_animations,
build_armature_data = build_armature_data,
filter_animations_for_armature = filter_animations_for_armature,
build_animation_clip = build_animation_clip,
Armature = Armature, Armature = Armature,
} }

View file

@ -300,12 +300,10 @@ local function process_definitions(definitions)
local name_mapping = {} local name_mapping = {}
for k, v in pairs(definitions) do for k, v in pairs(definitions) do
print("populating name mapping for " .. v.name)
populate_name_mapping(v.name, v.data, name_mapping) populate_name_mapping(v.name, v.data, name_mapping)
end end
for k, v in pairs(definitions) do for k, v in pairs(definitions) do
print("replacing references for " .. v.name)
v.data = replace_references(v.data, name_mapping, v.name) v.data = replace_references(v.data, name_mapping, v.name)
end end
end end

View file

@ -7,10 +7,15 @@
#include "../math/boxs16.h" #include "../math/boxs16.h"
#include "../math/box3d.h" #include "../math/box3d.h"
#include "../math/range.h" #include "../math/range.h"
#include "../sk64/skelatool_clip.h"
#include "../sk64/skelatool_armature.h"
#define NO_TRANSFORM_INDEX 0xFF
struct StaticContentElement { struct StaticContentElement {
Gfx* displayList; Gfx* displayList;
u8 materialIndex; u8 materialIndex;
u8 transformIndex;
}; };
struct BoundingSphere { struct BoundingSphere {
@ -167,6 +172,12 @@ struct BoxDropperDefinition {
short signalIndex; short signalIndex;
}; };
struct AnimationInfo {
struct SKArmature armature;
struct SKAnimationClip* clips;
short clipCount;
};
struct LevelDefinition { struct LevelDefinition {
struct CollisionObject* collisionQuads; struct CollisionObject* collisionQuads;
struct StaticContentElement *staticContent; struct StaticContentElement *staticContent;
@ -189,6 +200,7 @@ struct LevelDefinition {
struct PedestalDefinition* pedestals; struct PedestalDefinition* pedestals;
struct SignageDefinition* signage; struct SignageDefinition* signage;
struct BoxDropperDefinition* boxDroppers; struct BoxDropperDefinition* boxDroppers;
struct AnimationInfo* animations;
short collisionQuadCount; short collisionQuadCount;
short staticContentCount; short staticContentCount;
short portalSurfaceCount; short portalSurfaceCount;
@ -204,6 +216,7 @@ struct LevelDefinition {
short pedestalCount; short pedestalCount;
short signageCount; short signageCount;
short boxDropperCount; short boxDropperCount;
short animationInfoCount;
short startLocation; short startLocation;
}; };

View file

@ -47,4 +47,6 @@ sk_definition_writer.add_definition("level", "struct LevelDefinition", "_geo", {
signageCount = #entities.signage, signageCount = #entities.signage,
signalOperators = sk_definition_writer.reference_to(signals.operators, 1), signalOperators = sk_definition_writer.reference_to(signals.operators, 1),
signalOperatorCount = #signals.operators, signalOperatorCount = #signals.operators,
animations = sk_definition_writer.reference_to(animation.animated_nodes, 1),
animationInfoCount = #animation.animated_nodes,
}) })

View file

@ -1,6 +1,80 @@
local sk_scene = require('sk_scene') local sk_scene = require('sk_scene')
local sk_animation = require('sk_animation') local sk_animation = require('sk_animation')
local sk_scene = require('sk_scene')
local sk_definition_writer = require('sk_definition_writer')
local armature = sk_animation.build_armature_for_animations(sk_scene.scene.animations) local armature_bones_by_name = {}
sk_animation.export_animations('animation', armature, sk_scene.scene.animations, '_geo', '_anim') for _, node in pairs(sk_scene.nodes_for_type('@anim')) do
local name = node.arguments[1]
local existing = armature_bones_by_name[name]
if existing then
table.insert(existing, node.node)
else
armature_bones_by_name[name] = {node.node}
end
end
local armatures = {}
local node_to_bone_index = {}
local node_to_armature_index = {}
local bones_as_array = {}
for name, nodes in pairs(armature_bones_by_name) do
table.insert(armatures, {name = name, armature = sk_animation.build_armature(nodes)})
end
table.sort(armatures, function(a, b)
return a.name < b.name
end)
local animated_nodes = {}
for index, armature in pairs(armatures) do
-- build an index used to attached parts of the scene
-- to animation nodes later
for _, node in pairs(armature.armature.nodes) do
table.insert(bones_as_array, node)
local bone_index = #bones_as_array
sk_scene.for_each_node(node, function(child_node)
node_to_bone_index[child_node] = bone_index
node_to_armature_index[child_node] = index
end)
end
local armature_data = sk_animation.build_armature_data(armature.armature, nil, armature.name, '_geo')
local animation_clips = {}
for _, animation in pairs(sk_animation.filter_animations_for_armature(armature.armature, sk_scene.scene.animations)) do
local clip = sk_animation.build_animation_clip(animation, armature.armature, '_anim')
sk_definition_writer.add_macro(armature.name .. '_' .. animation.name, tostring(#animation_clips))
table.insert(animation_clips, clip)
end
sk_definition_writer.add_definition(armature.name .. '_clips', 'struct SKAnimationClip[]', '_geo', animation_clips)
table.insert(animated_nodes, {
armature = armature_data,
clips = sk_definition_writer.reference_to(animation_clips, 1),
clipCount = #animation_clips
})
end
local function get_bone_index_for_node(node)
return node_to_bone_index[node]
end
local function get_bone_for_index(index)
return bones_as_array[index]
end
sk_definition_writer.add_definition('anim', 'struct AnimationInfo[]', '_geo', animated_nodes)
return {
animated_nodes = animated_nodes,
get_bone_index_for_node = get_bone_index_for_node,
get_bone_for_index = get_bone_for_index,
}

View file

@ -4,6 +4,7 @@ local sk_scene = require('sk_scene')
local sk_mesh = require('sk_mesh') local sk_mesh = require('sk_mesh')
local sk_input = require('sk_input') local sk_input = require('sk_input')
local room_export = require('tools.level_scripts.room_export') local room_export = require('tools.level_scripts.room_export')
local animation = require('tools.level_scripts.animation')
sk_definition_writer.add_header('"../build/assets/materials/static.h"') sk_definition_writer.add_header('"../build/assets/materials/static.h"')
sk_definition_writer.add_header('"levels/level_definition.h"') sk_definition_writer.add_header('"levels/level_definition.h"')
@ -33,33 +34,32 @@ local function proccessStaticNodes(nodes)
mesh = chunkV.mesh, mesh = chunkV.mesh,
mesh_bb = mesh_bb, mesh_bb = mesh_bb,
display_list = sk_definition_writer.raw(gfxName), display_list = sk_definition_writer.raw(gfxName),
material_index = sk_definition_writer.raw(chunkV.material.macro_name) material_index = sk_definition_writer.raw(chunkV.material.macro_name),
transform_index = animation.get_bone_index_for_node(v.node),
room_index = room_export.node_nearest_room_index(v.node) or 0
}) })
end end
end end
table.sort(result, function(a, b)
return a.room_index < b.room_index
end)
return result; return result;
end end
local static_nodes = proccessStaticNodes(sk_scene.nodes_for_type('@static')) local static_nodes = proccessStaticNodes(sk_scene.nodes_for_type('@static'))
for _, static_node in pairs(static_nodes) do
static_node.room_index = room_export.node_nearest_room_index(static_node.node) or 0
end
local static_content_elements = {} local static_content_elements = {}
table.sort(static_nodes, function(a, b)
return a.room_index < b.room_index
end)
local room_ranges = {} local room_ranges = {}
local static_bounding_boxes = {} local static_bounding_boxes = {}
for index, static_node in pairs(static_nodes) do for index, static_node in pairs(static_nodes) do
table.insert(static_content_elements, { table.insert(static_content_elements, {
displayList = static_node.display_list, displayList = static_node.display_list,
materialIndex = static_node.material_index materialIndex = static_node.material_index,
transformIndex = static_node.transform_index and (static_node.transform_index - 1) or sk_definition_writer.raw('NO_TRANSFORM_INDEX'),
}) })
table.insert(static_bounding_boxes, { table.insert(static_bounding_boxes, {
static_node.mesh_bb.min.x, static_node.mesh_bb.min.x,