121 lines
3.7 KiB
Lua
121 lines
3.7 KiB
Lua
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
|
|
if value.f[0] == 0 and value.f[1] == 0 and value.f[2] == 0 then
|
|
-- WUT?
|
|
return mat4.identity()
|
|
end
|
|
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
|