collada: animated book

This commit is contained in:
Zack Buhman 2026-03-17 17:46:29 -05:00
parent f4e95aee09
commit 2b379aa27c
12 changed files with 4677 additions and 29 deletions

View File

@ -43,7 +43,8 @@ OBJS = \
src/collada/animate.o \
data/scenes/ship20/ship20.o \
data/scenes/noodle/noodle.o \
data/scenes/shadow_test/shadow_test.o
data/scenes/shadow_test/shadow_test.o \
data/scenes/book/book.o
all: test.so

View File

@ -21,3 +21,15 @@ PYTHONPATH=~/d3d10 python -m collada.main \
PYTHONPATH=~/d3d10 python -m collada.main \
include/data/scenes/shadow_test.h
# book
PYTHONPATH=~/d3d10 python -m collada.main \
~/Downloads/book.DAE \
data/scenes/book/book.cpp \
data/scenes/book/book.vtx \
data/scenes/book/book.vjw \
data/scenes/book/book.idx
PYTHONPATH=~/d3d10 python -m collada.main \
include/data/scenes/book.h

4616
data/scenes/book/book.cpp Normal file

File diff suppressed because it is too large Load Diff

BIN
data/scenes/book/book.idx Normal file

Binary file not shown.

BIN
data/scenes/book/book.vjw Normal file

Binary file not shown.

BIN
data/scenes/book/book.vtx Normal file

Binary file not shown.

View File

@ -260,6 +260,7 @@ namespace collada::types {
struct skin {
types::geometry const * const geometry; // source
matrix const bind_shape_matrix; // one per skin
matrix const * const inverse_bind_matrices; // one per joint
int const vertex_buffer_offset;

View File

@ -0,0 +1,3 @@
namespace book {
extern collada::types::descriptor const descriptor;
}

View File

@ -7,27 +7,32 @@
namespace collada::animate {
static inline int find_frame_ix(types::source const& source, float t)
struct frame_ix {
int f0;
int f1;
};
static inline frame_ix find_frame_ix(types::source const& source, float t)
{
for (int i = 0; i < source.count - 1; i++) {
if (source.float_array[i] <= t && source.float_array[i+1] > t) {
return i;
return {i, i + 1};
}
}
return -1;
return {source.count - 1, 0};
}
static inline float linear_interpolate_iv(types::source const& source, int frame_ix, float t)
static inline float linear_interpolate_iv(types::source const& source, frame_ix frame_ix, float t)
{
float prev = source.float_array[(frame_ix+0) * source.stride];
float next = source.float_array[(frame_ix+1) * source.stride];
float prev = source.float_array[(frame_ix.f0) * source.stride];
float next = source.float_array[(frame_ix.f1) * source.stride];
return (t - prev) / (next - prev);
}
static inline float linear_interpolate_value(types::source const& source, int frame_ix, int parameter_ix, float iv)
static inline float linear_interpolate_value(types::source const& source, frame_ix frame_ix, int parameter_ix, float iv)
{
float prev = source.float_array[(frame_ix+0) * source.stride + parameter_ix];
float next = source.float_array[(frame_ix+1) * source.stride + parameter_ix];
float prev = source.float_array[(frame_ix.f0) * source.stride + parameter_ix];
float next = source.float_array[(frame_ix.f1) * source.stride + parameter_ix];
return prev + iv * (next - prev);
}
@ -88,7 +93,7 @@ namespace collada::animate {
return (XMFLOAT2 const *)&source.float_array[ix];
}
static float bezier_sampler(types::sampler const * const sampler, int frame_ix, int parameter_ix, float t)
static float bezier_sampler(types::sampler const * const sampler, frame_ix frame_ix, int parameter_ix, float t)
{
/*
P0 is (INPUT[i] , OUTPUT[i])
@ -97,15 +102,15 @@ namespace collada::animate {
P1 is (INPUT[i+1], OUTPUT[i+1])
*/
float frame0_input = sampler->input.float_array[frame_ix+0];
float frame1_input = sampler->input.float_array[frame_ix+1];
float frame0_input = sampler->input.float_array[frame_ix.f0];
float frame1_input = sampler->input.float_array[frame_ix.f1];
float frame0_output = sampler->output.float_array[(frame_ix+0) * sampler->output.stride + parameter_ix];
float frame1_output = sampler->output.float_array[(frame_ix+1) * sampler->output.stride + parameter_ix];
float frame0_output = sampler->output.float_array[(frame_ix.f0) * sampler->output.stride + parameter_ix];
float frame1_output = sampler->output.float_array[(frame_ix.f1) * sampler->output.stride + parameter_ix];
XMVECTOR p0 = XMVectorSet(frame0_input, frame0_output, 0, 0);
XMVECTOR c0 = XMLoadFloat2(tangent_index(sampler->out_tangent, frame_ix + 0, parameter_ix));
XMVECTOR c1 = XMLoadFloat2(tangent_index(sampler->in_tangent, frame_ix + 1, parameter_ix));
XMVECTOR c0 = XMLoadFloat2(tangent_index(sampler->out_tangent, frame_ix.f0, parameter_ix));
XMVECTOR c1 = XMLoadFloat2(tangent_index(sampler->in_tangent, frame_ix.f1, parameter_ix));
XMVECTOR p1 = XMVectorSet(frame1_input, frame1_output, 0, 0);
return bezier_binary_search(p0, c0, c1, p1, t);
@ -153,7 +158,7 @@ namespace collada::animate {
static void animate_channel_segment(types::channel const& channel,
instance_types::transform& transform,
int frame_ix, float t)
frame_ix frame_ix, float t)
{
enum types::target_attribute const * target_attributes = &channel.target_attribute;
int target_attributes_count = 1;
@ -176,7 +181,7 @@ namespace collada::animate {
for (int parameter_ix = 0; parameter_ix < target_attributes_count; parameter_ix++) {
enum types::interpolation interpolation = channel.source_sampler->interpolation.interpolation_array[frame_ix];
enum types::interpolation interpolation = channel.source_sampler->interpolation.interpolation_array[frame_ix.f0];
float value;
if (interpolation == types::interpolation::BEZIER) {
@ -196,8 +201,8 @@ namespace collada::animate {
types::channel const& channel = *node_instance.node->channels[i];
instance_types::transform& transform = node_instance.transforms[channel.target_transform_index];
int frame_ix = find_frame_ix(channel.source_sampler->input, t);
assert(frame_ix >= 0); // animation is missing a key frame
frame_ix frame_ix = find_frame_ix(channel.source_sampler->input, t);
//assert(frame_ix >= 0); // animation is missing a key frame
animate_channel_segment(channel, transform, frame_ix, t);
}

View File

@ -450,6 +450,8 @@ namespace collada::scene {
types::instance_controller const &instance_controller = instance_controllers[i];
types::skin const &skin = instance_controller.controller->skin;
XMMATRIX bsm = XMLoadFloat4x4((XMFLOAT4X4*)&skin.bind_shape_matrix);
XMFLOAT4X4 joints[instance_controller.joint_count];
int joints_size = (sizeof (joints));
for (int joint_index = 0; joint_index < instance_controller.joint_count; joint_index++) {
@ -457,7 +459,7 @@ namespace collada::scene {
int node_index = instance_controller.joint_node_indices[joint_index];
instance_types::node& node_instance = node_state.node_instances[node_index];
XMStoreFloat4x4(&joints[joint_index], ibm * node_instance.world);
XMStoreFloat4x4(&joints[joint_index], bsm * ibm * node_instance.world);
}
glBindBuffer(GL_UNIFORM_BUFFER, joint_uniform_buffer);
glBufferData(GL_UNIFORM_BUFFER, joints_size, (void *)&joints[0], GL_DYNAMIC_DRAW);
@ -520,7 +522,7 @@ namespace collada::scene {
void state::update(float t)
{
t = animate::loop(t / 4.0f, 3.333333f);
t = animate::loop(t / 4.0f, 1.8333333333333333f);
for (int i = 0; i < descriptor->nodes_count; i++) {
animate::animate_node(node_state.node_instances[i], t);

View File

@ -29,6 +29,7 @@
#include "data/scenes/ship20.h"
#include "data/scenes/noodle.h"
#include "data/scenes/shadow_test.h"
#include "data/scenes/book.h"
struct line_location {
struct {
@ -309,11 +310,13 @@ void load(const char * source_path)
//////////////////////////////////////////////////////////////////////
collada::effect::load_effects();
scene_state.load_scene(&noodle::descriptor);
node_eye = scene_state.find_node_by_name("Camera001");
scene_state.load_scene(&book::descriptor);
node_eye = scene_state.find_node_by_name("Camera");
assert(node_eye != nullptr);
node_at = scene_state.find_node_by_name("Camera001.Target");
assert(node_at != nullptr);
//view::state.eye = XMVector3Transform(XMVectorZero(), node_eye->world);
//node_at = scene_state.find_node_by_name("Camera001.Target");
//assert(node_at != nullptr);
}
void update_keyboard(int up, int down, int left, int right,
@ -453,8 +456,13 @@ void update(float time)
current_time = time;
scene_state.update(time);
/*
view::state.eye = XMVector3Transform(XMVectorZero(), node_eye->world);
view::state.at = XMVector3Transform(XMVectorZero(), node_at->world);
if (node_at == nullptr)
view::state.at = XMVectorZero();
else
view::state.at = XMVector3Transform(XMVectorZero(), node_at->world);
*/
view::update_transforms();
}

View File

@ -107,6 +107,6 @@ namespace view {
//state.eye = XMVectorSet(-45.5f, 43.25f, 63.0f, 1);
//state.at = state.eye + state.direction * at_distance;
state.at = XMVectorSet(0, 0, 0, 1);
state.eye = XMVectorSet(0, -10, 0, 1);
state.eye = XMVectorSet(0, -100, 0, 1);
}
}