From ae351e152702da4c7c4f4b2ef546bb9da61e64a7 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Tue, 24 Feb 2026 22:42:50 +0000 Subject: [PATCH] collada_scene: node animation --- _math.lua | 34 ++- collada_scene.lua | 110 +------- collada_scene/animate.lua | 123 +++++++++ collada_scene/node_state.lua | 116 +++++++++ collada_types.lua | 15 ++ main.lua | 13 +- scene/test/test.DAE | 314 ++++++++++++++++++++++- scene/test/test.lua | 484 ++++++++++++++++++++++++++++++++++- 8 files changed, 1093 insertions(+), 116 deletions(-) create mode 100644 collada_scene/animate.lua create mode 100644 collada_scene/node_state.lua diff --git a/_math.lua b/_math.lua index 44b646a..214b659 100644 --- a/_math.lua +++ b/_math.lua @@ -32,7 +32,7 @@ mat4 = { -- newByteData is zero-initialized local data = love.data.newByteData(16 * 4) local m = ffi.cast('float*', data:getFFIPointer()) - value = { + local value = { data = data, m = m, } @@ -557,7 +557,7 @@ vec3 = { -- newByteData is zero-initialized local data = love.data.newByteData(3 * 4) local f = ffi.cast('float*', data:getFFIPointer()) - value = { + local value = { data = data, f = f, } @@ -576,6 +576,18 @@ vec3 = { return vec3(t[1], t[2], t[3]) end, + set_x = function(v, value) + return vec3(value, v.f[1], v.f[2]) + end, + + set_y = function(v, value) + return vec3(v.f[0], value, v.f[2]) + end, + + set_z = function(v, value) + return vec3(v.f[0], v.f[1], value) + end, + replicate = function(value) return vec3(value, value, value) end, @@ -716,7 +728,7 @@ vec4 = { -- newByteData is zero-initialized local data = love.data.newByteData(4 * 4) local f = ffi.cast('float*', data:getFFIPointer()) - value = { + local value = { data = data, f = f, } @@ -737,6 +749,22 @@ vec4 = { return vec4(t[1], t[2], t[3], t[4]) end, + set_x = function(v, value) + return vec4(value, v.f[1], v.f[2], v.f[3]) + end, + + set_y = function(v, value) + return vec4(v.f[0], value, v.f[2], v.f[3]) + end, + + set_z = function(v, value) + return vec4(v.f[0], v.f[1], value, v.f[3]) + end, + + set_w = function(v, value) + return vec4(v.f[0], v.f[1], v.f[2], value) + end, + print = function(v) print(tostring(v.f[0]) .. " " .. tostring(v.f[1]) .. " " .. tostring(v.f[2]) .. " " .. tostring(v.f[3])) end, diff --git a/collada_scene.lua b/collada_scene.lua index ff27813..e6ccca9 100644 --- a/collada_scene.lua +++ b/collada_scene.lua @@ -53,104 +53,6 @@ collada_scene = { end end, - load_transform = function(transform) - if transform.type == collada_types.transform_type.LOOKAT then - assert(false) - elseif transform.type == collada_types.transform_type.MATRIX then - return mat4.load_table(transform.matrix) - elseif transform.type == collada_types.transform_type.ROTATE then - return vec4.load_table(transform.rotate) - elseif transform.type == collada_types.transform_type.SCALE then - return vec3.load_table(transform.scale) - elseif transform.type == collada_types.transform_type.TRANSLATE then - return vec3.load_table(transform.translate) - else - assert(false) - end - end, - - transform_matrix = function (loaded_transform) - local type = loaded_transform.type - local value = loaded_transform.value - if type == collada_types.transform_type.LOOKAT then - assert(false) - elseif type == collada_types.transform_type.MATRIX then - return value - elseif type == collada_types.transform_type.ROTATE then - return mat4.rotation_axis(value, scalar.convert_to_radians(value.f[3])) - elseif type == collada_types.transform_type.SCALE then - return mat4.scaling_from_vector(value) - elseif type == collada_types.transform_type.TRANSLATE then - return mat4.translation_from_vector(value) - else - assert(false) - end - end, - - -- - -- node instance - -- - -- { - -- transforms = .., - -- transforms_count = .., - -- world = .., - -- } - - node_instance_initialize_transforms = function(node) - local transforms = {} - - local transform_index = 0 - for _, transform in ipairs(node.transforms) do - local value = collada_scene.load_transform(transform) - local loaded_transform = { - type = transform.type, - value = value, - } - transforms[transform_index] = loaded_transform - transform_index = transform_index + 1 - end - - return transforms, transform_index - end, - - node_instance_world = function(node, transforms, transforms_count) - local world - if node.parent_index >= 0 then - world = node_instances[node.parent_index].world - assert(world ~= nil) - else - world = mat4.identity() - end - - local transform_index = 0 - while transform_index < transforms_count do - local m = collada_scene.transform_matrix(transforms[transform_index]) - world = m * world - transform_index = transform_index + 1 - end - return world - end, - - node_instance_initialize = function(node) - local transforms, transforms_count = collada_scene.node_instance_initialize_transforms(node) - local world = collada_scene.node_instance_world(node, transforms, transforms_count) - local node_instance = { - transforms = transforms, - transforms_count = transforms_count, - world = world, - } - return node_instance - end, - - load_node_instances = function(nodes) - local node_index = 0 - for _, node in ipairs(nodes) do - local node_instance = collada_scene.node_instance_initialize(node) - node_instances[node_index] = node_instance - node_index = node_index + 1 - end - end, - set_color_or_texture = function(color_or_texture, color_uniform, sampler_uniform) if color_or_texture.type == collada_types.color_or_texture_type.COLOR then shader:send(color_uniform, color_or_texture.color) @@ -211,7 +113,7 @@ collada_scene = { end end, - draw_node = function(node_index, node, transform) + draw_node = function(node, node_instance, transform) if node.type ~= collada_types.node_type.NODE then return end @@ -220,7 +122,7 @@ collada_scene = { return end - local world = node_instances[node_index].world + local world = node_instance.world transform = world * transform shader:send("world_transform", "column", world.data) shader:send("transform", "column", transform.data) @@ -230,14 +132,15 @@ collada_scene = { end end, - draw_nodes = function(nodes, transform) + draw_nodes = function(node_state, transform) love.graphics.setShader(shader) shader:send("view_position", {-88.57101, -71.71298, 104.5738, 1.0}) shader:send("light_position", {0.0, -56.804, 58.237, 1.0}) local node_index = 0 - for _, node in ipairs(nodes) do - collada_scene.draw_node(node_index, node, transform) + for _, node in ipairs(node_state.nodes) do + local node_instance = node_state.node_instances[node_index] + collada_scene.draw_node(node, node_instance, transform) node_index = node_index + 1 end end, @@ -248,4 +151,5 @@ return { load_buffers = collada_scene.load_buffers, load_node_instances = collada_scene.load_node_instances, load_images = collada_scene.load_images, + update = collada_scene.update, } diff --git a/collada_scene/animate.lua b/collada_scene/animate.lua new file mode 100644 index 0000000..06d1834 --- /dev/null +++ b/collada_scene/animate.lua @@ -0,0 +1,123 @@ +local _math = require '_math' +local mat4 = _math.mat4 +local vec3 = _math.vec3 +local vec4 = _math.vec4 +local scalar = _math.scalar + +local collada_types = require 'collada_types' + +local fract = function(f) + return f - math.floor(f) +end + +local loop = function(f, n) + return fract(f / n) * n +end + +local find_frame_ix = function(source, t) + for i = 1, source.count - 1 do + if source.float_array[i] <= t and source.float_array[i+1] > t then + return i - 1 -- 0-based index + end + end + return -1 +end + +local linear_interpolate_iv = function(source, frame_ix, t) + local prev = source.float_array[(frame_ix + 0) * source.stride + 1] + local next = source.float_array[(frame_ix + 1) * source.stride + 1] + return (t - prev) / (next - prev) +end + +local linear_interpolate_value = function(source, frame_ix, parameter_ix, iv) + local prev = source.float_array[(frame_ix + 0) * source.stride + parameter_ix + 1] + local next = source.float_array[(frame_ix + 1) * source.stride + parameter_ix + 1] + return prev + iv * (next - prev) +end + +local apply_transform_target = function(transform, channel_target_attribute, value) + if transform.type == collada_types.transform_type.TRANSLATE or transform.type == collada_types.transform_type.SCALE then + if channel_target_attribute == collada_types.target_attribute.X then + transform.value = vec3.set_x(transform.value, value) + elseif channel_target_attribute == collada_types.target_attribute.Y then + transform.value = vec3.set_y(transform.value, value) + elseif channel_target_attribute == collada_types.target_attribute.Z then + transform.value = vec3.set_z(transform.value, value) + else + assert(false) + end + elseif transform.type == collada_types.transform_type.ROTATE then + if channel_target_attribute == collada_types.target_attribute.X then + transform.value = vec4.set_x(transform.value, value) + elseif channel_target_attribute == collada_types.target_attribute.Y then + transform.value = vec4.set_y(transform.value, value) + elseif channel_target_attribute == collada_types.target_attribute.Z then + transform.value = vec4.set_z(transform.value, value) + elseif channel_target_attribute == collada_types.target_attribute.ANGLE then + transform.value = vec4.set_w(transform.value, value) + else + assert(false) + end + else + assert(false) + end +end + +local animate_channel_segment = function(channel, transform, frame_ix, t) + local target_attributes = {channel.target_attribute} + if channel.target_attribute == collada_types.target_attribute.ALL then + if transform.type == collada_types.transform_type.TRANSLATE or transform.type == collada_types.transform_type.SCALE then + target_attributes = translate_scale_target_attributes + elseif transform.type == collada_types.transform_type.ROTATE then + target_attributes = rotate_target_attributes + else + assert(false) + end + end + + target_attributes_count = #target_attributes + + -- parameter_ix: 0-based index + for parameter_ix = 0, target_attributes_count-1 do + local interpolation = channel.source_sampler.interpolation.interpolation_array[frame_ix] + local value + if false then + else + local iv = linear_interpolate_iv(channel.source_sampler.input, frame_ix, t) + value = linear_interpolate_value(channel.source_sampler.output, frame_ix, parameter_ix, iv) + end + + apply_transform_target(transform, target_attributes[parameter_ix + 1], value) + end +end + +local animate_node = function(node, node_instance, t) + for _, channel in ipairs(node.channels) do + local transform = node_instance.transforms[channel.target_transform_index] + assert(transform ~= nil) + -- frame_ix: 0-based index + local frame_ix = find_frame_ix(channel.source_sampler.input, t) + assert(frame_ix >= 0) + animate_channel_segment(channel, transform, frame_ix, t) + end +end + +local update = function(_t, node_state) + local t = loop(_t / 2.0, 3.333333) + + local node_index = 0 + for _, node in ipairs(node_state.nodes) do + node_instance = node_state.node_instances[node_index] + + animate_node(node, node_instance, t) + + local world = node_state:node_instance_world(node, node_instance.transforms) + node_instance.world = world + + node_index = node_index + 1 + end +end + +return { + update = update, +} diff --git a/collada_scene/node_state.lua b/collada_scene/node_state.lua new file mode 100644 index 0000000..a951386 --- /dev/null +++ b/collada_scene/node_state.lua @@ -0,0 +1,116 @@ +local _math = require '_math' +local mat4 = _math.mat4 +local vec3 = _math.vec3 +local vec4 = _math.vec4 +local scalar = _math.scalar + +local collada_types = require 'collada_types' + +local load_transform = function(transform) + if transform.type == collada_types.transform_type.LOOKAT then + assert(false) + elseif transform.type == collada_types.transform_type.MATRIX then + return mat4.load_table(transform.matrix) + elseif transform.type == collada_types.transform_type.ROTATE then + return vec4.load_table(transform.rotate) + elseif transform.type == collada_types.transform_type.SCALE then + return vec3.load_table(transform.scale) + elseif transform.type == collada_types.transform_type.TRANSLATE then + return vec3.load_table(transform.translate) + else + assert(false) + end +end + +local transform_matrix = function (loaded_transform) + local type = loaded_transform.type + local value = loaded_transform.value + if type == collada_types.transform_type.LOOKAT then + assert(false) + elseif type == collada_types.transform_type.MATRIX then + return value + elseif type == collada_types.transform_type.ROTATE then + return mat4.rotation_axis(value, scalar.convert_to_radians(value.f[3])) + elseif type == collada_types.transform_type.SCALE then + return mat4.scaling_from_vector(value) + elseif type == collada_types.transform_type.TRANSLATE then + return mat4.translation_from_vector(value) + else + assert(false) + end +end + +local instance_transforms_from_node = function(node) + local transforms = {} + + local transform_index = 0 + for _, transform in ipairs(node.transforms) do + local value = load_transform(transform) + local loaded_transform = { + type = transform.type, + value = value, + } + transforms[transform_index] = loaded_transform + transform_index = transform_index + 1 + end + + return transforms +end + +local collada_scene_node_state + +collada_scene_node_state = { + __index = { + node_instance_world = function(this, node, transforms) + local world + if node.parent_index >= 0 then + world = this.node_instances[node.parent_index].world + assert(world ~= nil) + else + world = mat4.identity() + end + + local transforms_count = #node.transforms + local transform_index = 0 + while transform_index < transforms_count do + local m = transform_matrix(transforms[transform_index]) + world = m * world + transform_index = transform_index + 1 + end + return world + end, + + node_instance_new = function(this, node) + local transforms = instance_transforms_from_node(node) + local world = this:node_instance_world(node, transforms) + local node_instance = { + transforms = transforms, + transforms_count = transforms_count, + world = world, + } + return node_instance + end, + + node_instances_new = function(this, nodes) + local node_index = 0 + for _, node in ipairs(nodes) do + local node_instance = this:node_instance_new(node) + this.node_instances[node_index] = node_instance + node_index = node_index + 1 + end + end, + }, + + __call = function(_t, nodes) + local value = { + nodes = nodes, + node_instances = {}, + } + setmetatable(value, collada_scene_node_state) + value:node_instances_new(nodes) + return value + end, +} +setmetatable(collada_scene_node_state, collada_scene_node_state) + +return collada_scene_node_state diff --git a/collada_types.lua b/collada_types.lua index f559aae..2ac649a 100644 --- a/collada_types.lua +++ b/collada_types.lua @@ -67,6 +67,19 @@ local target_attribute = { ALL = {} } +local rotate_target_attributes = { + target_attribute.X, + target_attribute.Y, + target_attribute.Z, + target_attribute.ANGLE, +} + +local translate_scale_target_attributes = { + target_attribute.X, + target_attribute.Y, + target_attribute.Z, +} + return { input_format = input_format, light_type = light_type, @@ -76,4 +89,6 @@ return { node_type = node_type, interpolation = interpolation, target_attribute = target_attribute, + rotate_target_attributes = rotate_target_attributes, + translate_scale_target_attributes = translate_scale_target_attributes, } diff --git a/main.lua b/main.lua index 0ab7777..356e7e8 100644 --- a/main.lua +++ b/main.lua @@ -9,16 +9,22 @@ local vec4 = _math.vec4 local scalar = _math.scalar local scene_test = require 'scene.test.test' local collada_scene = require 'collada_scene' +local collada_scene_animate = require 'collada_scene.animate' +local collada_scene_node_state = require 'collada_scene.node_state' + +local node_state function love.load(args) love.window.setMode(1024, 1024, {depth=true}) collada_scene.load_buffers() collada_scene.load_images("scene/test", scene_test.descriptor.images) - collada_scene.load_node_instances(scene_test.descriptor.nodes) + + node_state = collada_scene_node_state(scene_test.descriptor.nodes) end local rotation = 0.0 +local t = 0.0 function love.draw() local radius = 100 @@ -42,6 +48,9 @@ function love.draw() local transform = view * projection + collada_scene_animate.update(t, node_state) + t = t + 0.016 + love.graphics.setDepthMode("less", true) - collada_scene.draw_nodes(scene_test.descriptor.nodes, transform) + collada_scene.draw_nodes(node_state, transform) end diff --git a/scene/test/test.DAE b/scene/test/test.DAE index f826530..535c61a 100644 --- a/scene/test/test.DAE +++ b/scene/test/test.DAE @@ -6,8 +6,8 @@ OpenCOLLADA for 3ds Max; Version: 1.6; Revision: 68 file:///C:/Users/bilbo/Documents/wood/scenes/test/test.max - 2026-02-23T22:42:05 - 2026-02-23T22:42:05 + 2026-02-24T13:10:30 + 2026-02-24T13:10:30 Z_UP @@ -422,7 +422,7 @@ - -21.94384 -1.68812e-14 45.45129 + -21.94384 -1.68812e-14 45.45129 -1 -2.22051e-16 -2.22051e-16 -90 0.5458366 0.5458366 0.5458366 @@ -443,7 +443,9 @@ 3.281013 -28.30101 45.45129 - 0.9075136 -0.007434183 0.4199569 -178.1592 + 0 0 1 -2.386906 + 0 1 0 -49.62295 + 1 0 0 -176.868 0.9893375 0 0.1456411 -1.382112 0.5458366 0.5458367 0.5458366 0.9893375 0 0.1456411 1.382112 @@ -522,6 +524,310 @@ + + + + 0 1 2 3 3.333333 + + + + + + + + -21.94384 17.57915 40.64392 -0.591423 -21.94384 + + + + + + + + -0.3329306 -21.94384 0.667 7.158293 1.667 40.64392 2.667 15.03987 3.222333 -21.94384 + + + + + + + + + 0.333 -21.94384 1.333 28.00002 2.333 40.64392 3.111 -5.801854 3.666264 -21.94384 + + + + + + + + + BEZIER BEZIER BEZIER BEZIER BEZIER + + + + + + + + 0 1 2 3 3.333333 + + + + + + + + -1.68812e-14 24.27013 -12.4935 9.835234 -1.68812e-14 + + + + + + + + -0.3329306 -1.68812e-14 0.667 24.27013 1.667 -12.4935 2.667 9.835234 3.222333 -1.68812e-14 + + + + + + + + + 0.333 -1.68812e-14 1.333 24.27013 2.333 -12.4935 3.111 9.835234 3.666264 -1.68812e-14 + + + + + + + + + BEZIER BEZIER BEZIER BEZIER BEZIER + + + + + + + + 0 1 2 3 3.333333 + + + + + + + + 45.45129 45.45129 45.45129 45.45129 45.45129 + + + + + + + + -0.3329306 45.45129 0.667 45.45129 1.667 45.45129 2.667 45.45129 3.222333 45.45129 + + + + + + + + + 0.333 45.45129 1.333 45.45129 2.333 45.45129 3.111 45.45129 3.666264 45.45129 + + + + + + + + + BEZIER BEZIER BEZIER BEZIER BEZIER + + + + + + + + 0 0.5 1 1.5 2 2.5 3.333333 + + + + + + + + -2.386905 -47.8331 -59.67817 -40.14935 -120.2731 -163.7238 -2.386905 + + + + + + + + -0.3329306 -2.386905 0.3335 -38.2941 0.8335 -59.67817 1.3335 -40.14935 1.8335 -99.69791 2.3335 -163.7238 3.055833 -2.386905 + + + + + + + + + 0.1665 -2.386905 0.6665 -57.37209 1.1665 -59.67817 1.6665 -40.14935 2.1665 -140.8482 2.7775 -163.7238 3.666264 -2.386905 + + + + + + + + + BEZIER BEZIER BEZIER BEZIER BEZIER BEZIER BEZIER + + + + + + + + 0 0.5 1 1.5 2 2.5 3.333333 + + + + + + + + -49.62293 -15.37984 34.11597 -56.85069 -56.85069 -170.1778 -49.62293 + + + + + + + + -0.3329306 -49.62293 0.3335 -29.32237 0.8335 34.11597 1.3335 -56.85069 1.8335 -56.85069 2.3335 -170.1778 3.055833 -49.62293 + + + + + + + + + 0.1665 -49.62293 0.6665 -1.437308 1.1665 34.11597 1.6665 -56.85069 2.1665 -56.85069 2.7775 -170.1778 3.666264 -49.62293 + + + + + + + + + BEZIER BEZIER BEZIER BEZIER BEZIER BEZIER BEZIER + + + + + + + + 0 0.5 1 1.5 2 2.5 3.333333 + + + + + + + + 183.132 256.4932 196.3711 133.4248 133.4248 152.3479 183.132 + + + + + + + + -0.3329306 183.132 0.3335 256.4932 0.8335 216.862 1.3335 133.4248 1.8335 133.4248 2.3335 146.1407 3.055833 183.132 + + + + + + + + + 0.1665 183.132 0.6665 256.4932 1.1665 175.8802 1.6665 133.4248 2.1665 133.4248 2.7775 162.6932 3.666264 183.132 + + + + + + + + + BEZIER BEZIER BEZIER BEZIER BEZIER BEZIER BEZIER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scene/test/test.lua b/scene/test/test.lua index 5641db2..227186d 100644 --- a/scene/test/test.lua +++ b/scene/test/test.lua @@ -15,6 +15,468 @@ local light_omni001_light = { type = collada_types.light_type.POINT, color = {1.0, 1.0, 1.0}, } +local array_node_torus_knot23_translation_x_input_array = { + 0.0, + 1.0, + 2.0, + 3.0, + 3.333333, +} +local array_node_torus_knot23_translation_x_output_array = { + -21.94384, + 17.57915, + 40.64392, + -0.591423, + -21.94384, +} +local array_node_torus_knot23_translation_x_intangent_array = { + {-0.3329306, -21.94384}, + {0.667, 7.158293}, + {1.667, 40.64392}, + {2.667, 15.03987}, + {3.222333, -21.94384}, +} +local array_node_torus_knot23_translation_x_outtangent_array = { + {0.333, -21.94384}, + {1.333, 28.00002}, + {2.333, 40.64392}, + {3.111, -5.801854}, + {3.666264, -21.94384}, +} +local array_node_torus_knot23_translation_x_interpolation_array = { + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, +} +local sampler_node_torus_knot23_translation_x_sampler = { + -- node_torus_knot23_translation_x_input + input = { + float_array = array_node_torus_knot23_translation_x_input_array, + count = 5, + stride = 1, + }, + -- node_torus_knot23_translation_x_output + output = { + float_array = array_node_torus_knot23_translation_x_output_array, + count = 5, + stride = 1, + }, + -- node_torus_knot23_translation_x_intangent + in_tangent = { + float_array = array_node_torus_knot23_translation_x_intangent_array, + count = 5, + stride = 2, + }, + -- node_torus_knot23_translation_x_outtangent + out_tangent = { + float_array = array_node_torus_knot23_translation_x_outtangent_array, + count = 5, + stride = 2, + }, + -- node_torus_knot23_translation_x_interpolation + interpolation = { + interpolation_array = array_node_torus_knot23_translation_x_interpolation_array, + count = 5, + stride = 1, + }, +} +local array_node_torus_knot23_translation_y_input_array = { + 0.0, + 1.0, + 2.0, + 3.0, + 3.333333, +} +local array_node_torus_knot23_translation_y_output_array = { + -1.68812e-14, + 24.27013, + -12.4935, + 9.835234, + -1.68812e-14, +} +local array_node_torus_knot23_translation_y_intangent_array = { + {-0.3329306, -1.68812e-14}, + {0.667, 24.27013}, + {1.667, -12.4935}, + {2.667, 9.835234}, + {3.222333, -1.68812e-14}, +} +local array_node_torus_knot23_translation_y_outtangent_array = { + {0.333, -1.68812e-14}, + {1.333, 24.27013}, + {2.333, -12.4935}, + {3.111, 9.835234}, + {3.666264, -1.68812e-14}, +} +local array_node_torus_knot23_translation_y_interpolation_array = { + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, +} +local sampler_node_torus_knot23_translation_y_sampler = { + -- node_torus_knot23_translation_y_input + input = { + float_array = array_node_torus_knot23_translation_y_input_array, + count = 5, + stride = 1, + }, + -- node_torus_knot23_translation_y_output + output = { + float_array = array_node_torus_knot23_translation_y_output_array, + count = 5, + stride = 1, + }, + -- node_torus_knot23_translation_y_intangent + in_tangent = { + float_array = array_node_torus_knot23_translation_y_intangent_array, + count = 5, + stride = 2, + }, + -- node_torus_knot23_translation_y_outtangent + out_tangent = { + float_array = array_node_torus_knot23_translation_y_outtangent_array, + count = 5, + stride = 2, + }, + -- node_torus_knot23_translation_y_interpolation + interpolation = { + interpolation_array = array_node_torus_knot23_translation_y_interpolation_array, + count = 5, + stride = 1, + }, +} +local array_node_torus_knot23_translation_z_input_array = { + 0.0, + 1.0, + 2.0, + 3.0, + 3.333333, +} +local array_node_torus_knot23_translation_z_output_array = { + 45.45129, + 45.45129, + 45.45129, + 45.45129, + 45.45129, +} +local array_node_torus_knot23_translation_z_intangent_array = { + {-0.3329306, 45.45129}, + {0.667, 45.45129}, + {1.667, 45.45129}, + {2.667, 45.45129}, + {3.222333, 45.45129}, +} +local array_node_torus_knot23_translation_z_outtangent_array = { + {0.333, 45.45129}, + {1.333, 45.45129}, + {2.333, 45.45129}, + {3.111, 45.45129}, + {3.666264, 45.45129}, +} +local array_node_torus_knot23_translation_z_interpolation_array = { + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, +} +local sampler_node_torus_knot23_translation_z_sampler = { + -- node_torus_knot23_translation_z_input + input = { + float_array = array_node_torus_knot23_translation_z_input_array, + count = 5, + stride = 1, + }, + -- node_torus_knot23_translation_z_output + output = { + float_array = array_node_torus_knot23_translation_z_output_array, + count = 5, + stride = 1, + }, + -- node_torus_knot23_translation_z_intangent + in_tangent = { + float_array = array_node_torus_knot23_translation_z_intangent_array, + count = 5, + stride = 2, + }, + -- node_torus_knot23_translation_z_outtangent + out_tangent = { + float_array = array_node_torus_knot23_translation_z_outtangent_array, + count = 5, + stride = 2, + }, + -- node_torus_knot23_translation_z_interpolation + interpolation = { + interpolation_array = array_node_torus_knot23_translation_z_interpolation_array, + count = 5, + stride = 1, + }, +} +local array_node_torusknot25_rotationz_angle_input_array = { + 0.0, + 0.5, + 1.0, + 1.5, + 2.0, + 2.5, + 3.333333, +} +local array_node_torusknot25_rotationz_angle_output_array = { + -2.386905, + -47.8331, + -59.67817, + -40.14935, + -120.2731, + -163.7238, + -2.386905, +} +local array_node_torusknot25_rotationz_angle_intangent_array = { + {-0.3329306, -2.386905}, + {0.3335, -38.2941}, + {0.8335, -59.67817}, + {1.3335, -40.14935}, + {1.8335, -99.69791}, + {2.3335, -163.7238}, + {3.055833, -2.386905}, +} +local array_node_torusknot25_rotationz_angle_outtangent_array = { + {0.1665, -2.386905}, + {0.6665, -57.37209}, + {1.1665, -59.67817}, + {1.6665, -40.14935}, + {2.1665, -140.8482}, + {2.7775, -163.7238}, + {3.666264, -2.386905}, +} +local array_node_torusknot25_rotationz_angle_interpolation_array = { + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, +} +local sampler_node_torusknot25_rotationz_angle_sampler = { + -- node_torusknot25_rotationz_angle_input + input = { + float_array = array_node_torusknot25_rotationz_angle_input_array, + count = 7, + stride = 1, + }, + -- node_torusknot25_rotationz_angle_output + output = { + float_array = array_node_torusknot25_rotationz_angle_output_array, + count = 7, + stride = 1, + }, + -- node_torusknot25_rotationz_angle_intangent + in_tangent = { + float_array = array_node_torusknot25_rotationz_angle_intangent_array, + count = 7, + stride = 2, + }, + -- node_torusknot25_rotationz_angle_outtangent + out_tangent = { + float_array = array_node_torusknot25_rotationz_angle_outtangent_array, + count = 7, + stride = 2, + }, + -- node_torusknot25_rotationz_angle_interpolation + interpolation = { + interpolation_array = array_node_torusknot25_rotationz_angle_interpolation_array, + count = 7, + stride = 1, + }, +} +local array_node_torusknot25_rotationy_angle_input_array = { + 0.0, + 0.5, + 1.0, + 1.5, + 2.0, + 2.5, + 3.333333, +} +local array_node_torusknot25_rotationy_angle_output_array = { + -49.62293, + -15.37984, + 34.11597, + -56.85069, + -56.85069, + -170.1778, + -49.62293, +} +local array_node_torusknot25_rotationy_angle_intangent_array = { + {-0.3329306, -49.62293}, + {0.3335, -29.32237}, + {0.8335, 34.11597}, + {1.3335, -56.85069}, + {1.8335, -56.85069}, + {2.3335, -170.1778}, + {3.055833, -49.62293}, +} +local array_node_torusknot25_rotationy_angle_outtangent_array = { + {0.1665, -49.62293}, + {0.6665, -1.437308}, + {1.1665, 34.11597}, + {1.6665, -56.85069}, + {2.1665, -56.85069}, + {2.7775, -170.1778}, + {3.666264, -49.62293}, +} +local array_node_torusknot25_rotationy_angle_interpolation_array = { + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, +} +local sampler_node_torusknot25_rotationy_angle_sampler = { + -- node_torusknot25_rotationy_angle_input + input = { + float_array = array_node_torusknot25_rotationy_angle_input_array, + count = 7, + stride = 1, + }, + -- node_torusknot25_rotationy_angle_output + output = { + float_array = array_node_torusknot25_rotationy_angle_output_array, + count = 7, + stride = 1, + }, + -- node_torusknot25_rotationy_angle_intangent + in_tangent = { + float_array = array_node_torusknot25_rotationy_angle_intangent_array, + count = 7, + stride = 2, + }, + -- node_torusknot25_rotationy_angle_outtangent + out_tangent = { + float_array = array_node_torusknot25_rotationy_angle_outtangent_array, + count = 7, + stride = 2, + }, + -- node_torusknot25_rotationy_angle_interpolation + interpolation = { + interpolation_array = array_node_torusknot25_rotationy_angle_interpolation_array, + count = 7, + stride = 1, + }, +} +local array_node_torusknot25_rotationx_angle_input_array = { + 0.0, + 0.5, + 1.0, + 1.5, + 2.0, + 2.5, + 3.333333, +} +local array_node_torusknot25_rotationx_angle_output_array = { + 183.132, + 256.4932, + 196.3711, + 133.4248, + 133.4248, + 152.3479, + 183.132, +} +local array_node_torusknot25_rotationx_angle_intangent_array = { + {-0.3329306, 183.132}, + {0.3335, 256.4932}, + {0.8335, 216.862}, + {1.3335, 133.4248}, + {1.8335, 133.4248}, + {2.3335, 146.1407}, + {3.055833, 183.132}, +} +local array_node_torusknot25_rotationx_angle_outtangent_array = { + {0.1665, 183.132}, + {0.6665, 256.4932}, + {1.1665, 175.8802}, + {1.6665, 133.4248}, + {2.1665, 133.4248}, + {2.7775, 162.6932}, + {3.666264, 183.132}, +} +local array_node_torusknot25_rotationx_angle_interpolation_array = { + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, + collada_types.interpolation.BEZIER, +} +local sampler_node_torusknot25_rotationx_angle_sampler = { + -- node_torusknot25_rotationx_angle_input + input = { + float_array = array_node_torusknot25_rotationx_angle_input_array, + count = 7, + stride = 1, + }, + -- node_torusknot25_rotationx_angle_output + output = { + float_array = array_node_torusknot25_rotationx_angle_output_array, + count = 7, + stride = 1, + }, + -- node_torusknot25_rotationx_angle_intangent + in_tangent = { + float_array = array_node_torusknot25_rotationx_angle_intangent_array, + count = 7, + stride = 2, + }, + -- node_torusknot25_rotationx_angle_outtangent + out_tangent = { + float_array = array_node_torusknot25_rotationx_angle_outtangent_array, + count = 7, + stride = 2, + }, + -- node_torusknot25_rotationx_angle_interpolation + interpolation = { + interpolation_array = array_node_torusknot25_rotationx_angle_interpolation_array, + count = 7, + stride = 1, + }, +} +local node_channel_node_torus_knot23_translation_x = { + source_sampler = sampler_node_torus_knot23_translation_x_sampler, + target_transform_index = 0, + target_attribute = collada_types.target_attribute.X, +} +local node_channel_node_torus_knot23_translation_y = { + source_sampler = sampler_node_torus_knot23_translation_y_sampler, + target_transform_index = 0, + target_attribute = collada_types.target_attribute.Y, +} +local node_channel_node_torus_knot23_translation_z = { + source_sampler = sampler_node_torus_knot23_translation_z_sampler, + target_transform_index = 0, + target_attribute = collada_types.target_attribute.Z, +} +local node_channel_node_torusknot25_rotationz_angle = { + source_sampler = sampler_node_torusknot25_rotationz_angle_sampler, + target_transform_index = 1, + target_attribute = collada_types.target_attribute.ANGLE, +} +local node_channel_node_torusknot25_rotationy_angle = { + source_sampler = sampler_node_torusknot25_rotationy_angle_sampler, + target_transform_index = 2, + target_attribute = collada_types.target_attribute.ANGLE, +} +local node_channel_node_torusknot25_rotationx_angle = { + source_sampler = sampler_node_torusknot25_rotationx_angle_sampler, + target_transform_index = 3, + target_attribute = collada_types.target_attribute.ANGLE, +} -- logOnly_png local image_logonly_png = { uri = "./images/0_logOnly.png", @@ -363,6 +825,9 @@ local instance_controllers_node_torus_knot23 = { local instance_lights_node_torus_knot23 = { } local node_channels_node_torus_knot23 = { + node_channel_node_torus_knot23_translation_y, + node_channel_node_torus_knot23_translation_x, + node_channel_node_torus_knot23_translation_z, } local node_node_torus_knot23 = { parent_index = -1, @@ -382,7 +847,7 @@ local node_node_torus_knot23 = { instance_lights_count = 0, channels = node_channels_node_torus_knot23, - channels_count = 0, + channels_count = 3, } local transforms_node_torusknot25 = { { @@ -391,7 +856,15 @@ local transforms_node_torusknot25 = { }, { type = collada_types.transform_type.ROTATE, - rotate = {0.9075136, -0.007434183, 0.4199569, -178.1592}, + rotate = {0.0, 0.0, 1.0, -2.386906}, + }, + { + type = collada_types.transform_type.ROTATE, + rotate = {0.0, 1.0, 0.0, -49.62295}, + }, + { + type = collada_types.transform_type.ROTATE, + rotate = {1.0, 0.0, 0.0, -176.868}, }, { type = collada_types.transform_type.ROTATE, @@ -430,6 +903,9 @@ local instance_controllers_node_torusknot25 = { local instance_lights_node_torusknot25 = { } local node_channels_node_torusknot25 = { + node_channel_node_torusknot25_rotationz_angle, + node_channel_node_torusknot25_rotationx_angle, + node_channel_node_torusknot25_rotationy_angle, } local node_node_torusknot25 = { parent_index = -1, @@ -437,7 +913,7 @@ local node_node_torusknot25 = { type = collada_types.node_type.NODE, transforms = transforms_node_torusknot25, - transforms_count = 5, + transforms_count = 7, instance_geometries = instance_geometries_node_torusknot25, instance_geometries_count = 1, @@ -449,7 +925,7 @@ local node_node_torusknot25 = { instance_lights_count = 0, channels = node_channels_node_torusknot25, - channels_count = 0, + channels_count = 3, } local transforms_node_camerahelper = { {