Compare commits

..

2 Commits

Author SHA1 Message Date
8d8c87c5b0 collada_scene: skinned animation 2026-02-25 03:14:30 +00:00
5f867891fa scene: add noodle 2026-02-25 01:35:03 +00:00
14 changed files with 4148 additions and 26 deletions

View File

@ -68,6 +68,15 @@ mat4 = {
t[13], t[14], t[15], t[16])
end,
store_table = function(M)
return {
M.m[0], M.m[1], M.m[2], M.m[3],
M.m[4], M.m[5], M.m[6], M.m[7],
M.m[8], M.m[9], M.m[10], M.m[11],
M.m[12], M.m[13], M.m[14], M.m[15],
}
end,
set = function(m00, m01, m02, m03,
m10, m11, m12, m13,
m20, m21, m22, m23,
@ -363,6 +372,9 @@ mat4 = {
end,
rotation_axis = function(axis, angle)
assert(not vec3.equal(axis, vec3._zero))
assert(not vec3.isinfinite(axis))
local normal = vec3.normalize(axis)
return mat4.rotation_normal(normal, angle)
end,

View File

@ -7,7 +7,8 @@ local scalar = _math.scalar
local collada_types = require 'collada_types'
local pixel_data = love.filesystem.newFileData("pixel.glsl")
local vertex_data = love.filesystem.newFileData("vertex.glsl")
--local vertex_data = love.filesystem.newFileData("vertex.glsl")
local vertex_data = love.filesystem.newFileData("skinned_vertex.glsl")
local shader = love.graphics.newShader(pixel_data, vertex_data)
local images_textures = {}
@ -23,21 +24,30 @@ collada_scene = {
-- index buffer
----------------------------------------------------------------------
local index_data = love.filesystem.newFileData("scene/test/test.idx")
local index_data = love.filesystem.newFileData("scene/noodle/noodle.idx")
index_buffer = love.graphics.newBuffer("uint32", index_data, { index = true, usage = "static" })
----------------------------------------------------------------------
-- vertex shader storage buffer
----------------------------------------------------------------------
local format = {
local vtx_format = {
{ name = 'Position', format = 'floatvec4' },
{ name = 'Normal', format = 'floatvec4' },
{ name = 'Texture', format = 'floatvec4' },
}
local vertex_data = love.filesystem.newFileData("scene/test/test.vtx")
local shaderstorage_buffer = love.graphics.newBuffer(format, vertex_data, { shaderstorage = true, usage = "static" })
shader:send("VertexLayout", shaderstorage_buffer)
local vtx_data = love.filesystem.newFileData("scene/noodle/noodle.vtx")
local vtx_shaderstorage_buffer = love.graphics.newBuffer(vtx_format, vtx_data, { shaderstorage = true, usage = "static" })
local vjw_format = {
{ name = 'Joint', format = 'int32vec4' },
{ name = 'Weight', format = 'floatvec4' },
}
local vjw_data = love.filesystem.newFileData("scene/noodle/noodle.vjw")
local vjw_shaderstorage_buffer = love.graphics.newBuffer(vjw_format, vjw_data, { shaderstorage = true, usage = "static" })
shader:send("VertexPNTLayout", vtx_shaderstorage_buffer)
shader:send("VertexJWLayout", vjw_shaderstorage_buffer)
end,
load_images = function(base_path, images)
@ -98,22 +108,77 @@ collada_scene = {
end,
draw_geometry = function(geometry, instance_materials)
local base_index_buffer_offset = geometry.mesh.index_buffer_offset / 4
local mesh = geometry.mesh
local base_index_buffer_offset = mesh.index_buffer_offset / 4
for _, instance_material in ipairs(instance_materials) do
collada_scene.set_instance_material(instance_material)
local triangles = geometry.mesh.triangles[instance_material.element_index + 1]
local triangles = mesh.triangles[instance_material.element_index + 1]
local index_offset = base_index_buffer_offset + triangles.index_offset
local index_count = triangles.count * 3
local vertex_offset = geometry.mesh.vertex_buffer_offset / (4 * 4 * 3)
shader:send("VertexOffset", vertex_offset)
local vertex_offset = mesh.vertex_buffer_offset / (4 * 4 * 3)
shader:send("VertexPNTOffset", vertex_offset)
love.graphics.drawFromShader(index_buffer, index_count, 1, 1 + index_offset)
end
end,
draw_node = function(node, node_instance, transform)
draw_instance_geometries = function(instance_geometries)
for _, instance_geometry in ipairs(instance_geometries) do
collada_scene.draw_geometry(instance_geometry.geometry, instance_geometry.instance_materials)
end
end,
draw_skin = function(skin, instance_materials)
local mesh = skin.geometry.mesh
local base_index_buffer_offset = mesh.index_buffer_offset / 4
for _, instance_material in ipairs(instance_materials) do
collada_scene.set_instance_material(instance_material)
local triangles = mesh.triangles[instance_material.element_index + 1]
local index_offset = base_index_buffer_offset + triangles.index_offset
local index_count = triangles.count * 3
local mesh_vertex_offset = mesh.vertex_buffer_offset / (4 * 4 * 3)
shader:send("VertexPNTOffset", mesh_vertex_offset)
local skin_vertex_offset = skin.vertex_buffer_offset / (4 * 4 * 2)
shader:send("VertexJWOffset", skin_vertex_offset)
love.graphics.drawFromShader(index_buffer, index_count, 1, 1 + index_offset)
end
end,
draw_instance_controllers = function(node_state, instance_controllers)
for _, instance_controller in ipairs(instance_controllers) do
local skin = instance_controller.controller.skin
local joints = {}
for joint_index = 1, instance_controller.joint_count do
local ibm = mat4.load_table(skin.inverse_bind_matrices[joint_index])
local node_index = instance_controller.joint_node_indices[joint_index]
local node_instance = node_state.node_instances[node_index]
joints[joint_index] = ibm * node_instance.world
end
--shader:send("Joints", "column",
--joints[1].data,
--joints[2].data,
--joints[3].data)
shader:send("Joints", "column",
mat4.store_table(joints[1]),
mat4.store_table(joints[2]),
mat4.store_table(joints[3]))
collada_scene.draw_skin(instance_controller.controller.skin,
instance_controller.instance_materials)
end
end,
draw_node = function(node_state, node, node_instance, transform)
if node.type ~= collada_types.node_type.NODE then
return
end
@ -127,20 +192,19 @@ collada_scene = {
shader:send("world_transform", "column", world.data)
shader:send("transform", "column", transform.data)
for _, instance_geometry in ipairs(node.instance_geometries) do
collada_scene.draw_geometry(instance_geometry.geometry, instance_geometry.instance_materials)
end
collada_scene.draw_instance_geometries(node.instance_geometries)
collada_scene.draw_instance_controllers(node_state, node.instance_controllers)
end,
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})
shader:send("light_position", {-26.649, -56.804, 58.237, 1.0})
local node_index = 0
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)
collada_scene.draw_node(node_state, node, node_instance, transform)
node_index = node_index + 1
end
end,

View File

@ -143,9 +143,9 @@ 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
target_attributes = collada_types.translate_scale_target_attributes
elseif transform.type == collada_types.transform_type.ROTATE then
target_attributes = rotate_target_attributes
target_attributes = collada_types.rotate_target_attributes
else
assert(false)
end
@ -157,7 +157,8 @@ local animate_channel_segment = function(channel, transform, frame_ix, t)
for parameter_ix = 0, target_attributes_count-1 do
local interpolation = channel.source_sampler.interpolation.interpolation_array[frame_ix]
local value
if interpolation == collada_types.interpolation.BEZIER then
--if interpolation == collada_types.interpolation.BEZIER then
if false then
value = bezier_sampler(channel.source_sampler, frame_ix, parameter_ix, t)
else
local iv = linear_interpolate_iv(channel.source_sampler.input, frame_ix, t)
@ -185,7 +186,6 @@ local update = function(_t, node_state)
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)

View File

@ -30,6 +30,10 @@ local transform_matrix = function (loaded_transform)
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)

View File

@ -7,20 +7,22 @@ local mat4 = _math.mat4
local vec3 = _math.vec3
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 scene_test = require 'scene.test.test'
local scene_noodle = require 'scene.noodle.noodle'
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_images("scene/noodle", scene_noodle.descriptor.images)
node_state = collada_scene_node_state(scene_test.descriptor.nodes)
node_state = collada_scene_node_state(scene_noodle.descriptor.nodes)
end
local rotation = 0.0
@ -33,13 +35,13 @@ function love.draw()
width, height = love.graphics.getDimensions()
local aspect_ratio = width / height
local projection = mat4.perspective_fov_rh(scalar.convert_to_radians(45 / 2),
local projection = mat4.perspective_fov_rh(scalar.convert_to_radians(45),
aspect_ratio,
0.1,
1000.0)
local view = mat4.look_at_rh(vec3(-88.57101, -71.71298, 104.5738),
vec3(-19.90239, -27.72767, 54.6898),
local view = mat4.look_at_rh(vec3(-54.43401, -35.53392, 57.3912),
vec3(0.0, 0.0, 13.41141),
vec3(0, 0, 1))
local world1 = mat4.rotation_x(rotation)

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

1674
scene/noodle/noodle.DAE Normal file

File diff suppressed because it is too large Load Diff

BIN
scene/noodle/noodle.idx Normal file

Binary file not shown.

2307
scene/noodle/noodle.lua Normal file

File diff suppressed because it is too large Load Diff

0
scene/noodle/noodle.mk Normal file
View File

4
scene/noodle/noodle.rc Normal file
View File

@ -0,0 +1,4 @@
RES_SCENES_NOODLE_VTX RCDATA "noodle.vtx"
RES_SCENES_NOODLE_VJW RCDATA "noodle.vjw"
RES_SCENES_NOODLE_IDX RCDATA "noodle.idx"

BIN
scene/noodle/noodle.vjw Normal file

Binary file not shown.

BIN
scene/noodle/noodle.vtx Normal file

Binary file not shown.

55
skinned_vertex.glsl Normal file
View File

@ -0,0 +1,55 @@
#pragma language glsl4
struct vertex_pnt_t {
vec4 Position;
vec4 Normal;
vec4 Texture;
};
struct vertex_jw_t {
ivec4 Joint;
vec4 Weight;
};
layout (std430) readonly buffer VertexPNTLayout
{
vertex_pnt_t VertexPNTBuffer[];
};
layout (std430) readonly buffer VertexJWLayout
{
vertex_jw_t VertexJWBuffer[];
};
uniform int VertexPNTOffset;
uniform int VertexJWOffset;
uniform mat4 Joints[3];
uniform mat4 world_transform;
uniform mat4 transform;
varying vec4 PixelNormal;
varying vec4 PixelTexture;
varying vec4 PixelWorldPosition;
void vertexmain()
{
vertex_pnt_t VertexPNT = VertexPNTBuffer[VertexPNTOffset + gl_VertexID];
vertex_jw_t VertexJW = VertexJWBuffer[VertexJWOffset + gl_VertexID];
mat4 mSkin
= VertexJW.Weight.x * Joints[VertexJW.Joint.x]
+ VertexJW.Weight.y * Joints[VertexJW.Joint.y]
+ VertexJW.Weight.z * Joints[VertexJW.Joint.z]
+ VertexJW.Weight.w * Joints[VertexJW.Joint.w]
;
PixelNormal = world_transform * vec4(VertexPNT.Normal.xyz, 0);
PixelTexture = VertexPNT.Texture;
vec4 Position = mSkin * vec4(VertexPNT.Position.xyz, 1);
//vec4 Position = Joints * vec4(VertexPNT.Position.xyz, 1);
PixelWorldPosition = world_transform * Position;
love_Position = transform * Position;
}