collada_scene: linear interpolation
This commit is contained in:
parent
e4bb6c2616
commit
b0906ecdc6
@ -525,7 +525,10 @@ def render_array(state, collada, accessor, array):
|
||||
it = iter(array.floats)
|
||||
for i in range(accessor.count):
|
||||
vector = ", ".join(f"{float(f)}f" for f in islice(it, accessor.stride))
|
||||
yield f"{{ {vector} }},"
|
||||
if accessor.stride == 1:
|
||||
yield f"{vector},"
|
||||
else:
|
||||
yield f"{{ {vector} }},"
|
||||
yield "};"
|
||||
else:
|
||||
assert False, type(array)
|
||||
|
||||
@ -24,6 +24,7 @@ namespace collada_scene {
|
||||
|
||||
struct node_instance {
|
||||
transform * transforms = NULL;
|
||||
XMMATRIX world;
|
||||
};
|
||||
|
||||
struct scene_state {
|
||||
@ -41,7 +42,7 @@ namespace collada_scene {
|
||||
collada::descriptor const * m_descriptor;
|
||||
|
||||
HRESULT load_scene(collada::descriptor const * const descriptor);
|
||||
void render();
|
||||
void render(float t);
|
||||
|
||||
private:
|
||||
HRESULT load_layouts();
|
||||
@ -51,6 +52,7 @@ namespace collada_scene {
|
||||
|
||||
void render_geometries(collada::instance_geometry const * const instance_geometries,
|
||||
int const instance_geometries_count);
|
||||
void node_world_transform(collada::node const& node, node_instance& node_instance);
|
||||
};
|
||||
|
||||
HRESULT LoadEffect();
|
||||
|
||||
@ -5,17 +5,17 @@ namespace curve_interpolation {
|
||||
using namespace collada;
|
||||
|
||||
float const array_node_cube_translation_x_input_array[] = {
|
||||
{ 0.0f },
|
||||
{ 1.666667f },
|
||||
{ 3.333333f },
|
||||
{ 5.0f },
|
||||
0.0f,
|
||||
1.666667f,
|
||||
3.333333f,
|
||||
5.0f,
|
||||
};
|
||||
|
||||
float const array_node_cube_translation_x_output_array[] = {
|
||||
{ 10.0f },
|
||||
{ -10.0f },
|
||||
{ 10.0f },
|
||||
{ -10.0f },
|
||||
10.0f,
|
||||
-10.0f,
|
||||
10.0f,
|
||||
-10.0f,
|
||||
};
|
||||
|
||||
float2 const array_node_cube_translation_x_intangent_array[] = {
|
||||
@ -68,17 +68,17 @@ sampler const sampler_node_cube_translation_x_sampler = {
|
||||
};
|
||||
|
||||
float const array_node_cube_translation_y_input_array[] = {
|
||||
{ -0.8333334f },
|
||||
{ 0.8333334f },
|
||||
{ 2.5f },
|
||||
{ 4.166667f },
|
||||
-0.8333334f,
|
||||
0.8333334f,
|
||||
2.5f,
|
||||
4.166667f,
|
||||
};
|
||||
|
||||
float const array_node_cube_translation_y_output_array[] = {
|
||||
{ -10.05776f },
|
||||
{ 10.05852f },
|
||||
{ -9.941484f },
|
||||
{ 10.05852f },
|
||||
-10.05776f,
|
||||
10.05852f,
|
||||
-9.941484f,
|
||||
10.05852f,
|
||||
};
|
||||
|
||||
float2 const array_node_cube_translation_y_intangent_array[] = {
|
||||
@ -519,6 +519,8 @@ instance_geometry const instance_geometries_node_environmentambientlight[] = {
|
||||
channel const * const node_channels_node_environmentambientlight[] = {};
|
||||
|
||||
node const node_node_environmentambientlight = {
|
||||
.parent_index = -1,
|
||||
|
||||
.type = node_type::NODE,
|
||||
|
||||
.transforms = transforms_node_environmentambientlight,
|
||||
@ -574,11 +576,13 @@ instance_geometry const instance_geometries_node_cube[] = {
|
||||
};
|
||||
|
||||
channel const * const node_channels_node_cube[] = {
|
||||
&node_channel_node_cube_translation_x,
|
||||
&node_channel_node_cube_translation_y,
|
||||
&node_channel_node_cube_translation_x,
|
||||
};
|
||||
|
||||
node const node_node_cube = {
|
||||
.parent_index = -1,
|
||||
|
||||
.type = node_type::NODE,
|
||||
|
||||
.transforms = transforms_node_cube,
|
||||
@ -613,6 +617,8 @@ channel const * const node_channels_node_cylinder001[] = {
|
||||
};
|
||||
|
||||
node const node_node_cylinder001 = {
|
||||
.parent_index = -1,
|
||||
|
||||
.type = node_type::NODE,
|
||||
|
||||
.transforms = transforms_node_cylinder001,
|
||||
@ -655,6 +661,8 @@ channel const * const node_channels_node_plane001[] = {
|
||||
};
|
||||
|
||||
node const node_node_plane001 = {
|
||||
.parent_index = -1,
|
||||
|
||||
.type = node_type::NODE,
|
||||
|
||||
.transforms = transforms_node_plane001,
|
||||
|
||||
@ -287,26 +287,26 @@ namespace collada_scene {
|
||||
{
|
||||
switch (effect.type) {
|
||||
case effect_type::BLINN:
|
||||
g_pEmissionVariable->SetFloatVector((float *)&effect.blinn.emission.color.x);
|
||||
g_pAmbientVariable->SetFloatVector((float *)&effect.blinn.ambient.color.x);
|
||||
g_pDiffuseVariable->SetFloatVector((float *)&effect.blinn.diffuse.color.x);
|
||||
g_pSpecularVariable->SetFloatVector((float *)&effect.blinn.specular.color.x);
|
||||
g_pEmissionVariable->SetFloatVector((float *)&effect.blinn.emission.color);
|
||||
g_pAmbientVariable->SetFloatVector((float *)&effect.blinn.ambient.color);
|
||||
g_pDiffuseVariable->SetFloatVector((float *)&effect.blinn.diffuse.color);
|
||||
g_pSpecularVariable->SetFloatVector((float *)&effect.blinn.specular.color);
|
||||
g_pShininessVariable->SetFloat(effect.blinn.shininess);
|
||||
break;
|
||||
case effect_type::LAMBERT:
|
||||
g_pEmissionVariable->SetFloatVector((float *)&effect.lambert.emission.color.x);
|
||||
g_pAmbientVariable->SetFloatVector((float *)&effect.lambert.ambient.color.x);
|
||||
g_pDiffuseVariable->SetFloatVector((float *)&effect.lambert.diffuse.color.x);
|
||||
g_pEmissionVariable->SetFloatVector((float *)&effect.lambert.emission.color);
|
||||
g_pAmbientVariable->SetFloatVector((float *)&effect.lambert.ambient.color);
|
||||
g_pDiffuseVariable->SetFloatVector((float *)&effect.lambert.diffuse.color);
|
||||
break;
|
||||
case effect_type::PHONG:
|
||||
g_pEmissionVariable->SetFloatVector((float *)&effect.phong.emission.color.x);
|
||||
g_pAmbientVariable->SetFloatVector((float *)&effect.phong.ambient.color.x);
|
||||
g_pDiffuseVariable->SetFloatVector((float *)&effect.phong.diffuse.color.x);
|
||||
g_pSpecularVariable->SetFloatVector((float *)&effect.phong.specular.color.x);
|
||||
g_pEmissionVariable->SetFloatVector((float *)&effect.phong.emission.color);
|
||||
g_pAmbientVariable->SetFloatVector((float *)&effect.phong.ambient.color);
|
||||
g_pDiffuseVariable->SetFloatVector((float *)&effect.phong.diffuse.color);
|
||||
g_pSpecularVariable->SetFloatVector((float *)&effect.phong.specular.color);
|
||||
g_pShininessVariable->SetFloat(effect.phong.shininess);
|
||||
break;
|
||||
case effect_type::CONSTANT:
|
||||
g_pEmissionVariable->SetFloatVector((float *)&effect.constant.color.x);
|
||||
g_pEmissionVariable->SetFloatVector((float *)&effect.constant.color);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -340,26 +340,102 @@ namespace collada_scene {
|
||||
}
|
||||
}
|
||||
|
||||
void scene_state::render()
|
||||
static inline float fract(float f)
|
||||
{
|
||||
return f - floorf(f);
|
||||
}
|
||||
|
||||
static inline float loop(float f, float n)
|
||||
{
|
||||
return fract(f / n) * n;
|
||||
}
|
||||
|
||||
static inline int find_frame_ix(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 -1;
|
||||
}
|
||||
|
||||
static inline float interpolation_value(source const& source, int ix, float t)
|
||||
{
|
||||
float prev = source.float_array[ix];
|
||||
float next = source.float_array[ix+1];
|
||||
return (t - prev) / (next - prev);
|
||||
}
|
||||
|
||||
static inline float linear_interpolate(source const& source, int ix, float iv)
|
||||
{
|
||||
float prev = source.float_array[ix];
|
||||
float next = source.float_array[ix+1];
|
||||
return prev + iv * (next - prev);
|
||||
}
|
||||
|
||||
static void animate_node(node const& node, node_instance& node_instance, float t)
|
||||
{
|
||||
for (int i = 0; i < node.channels_count; i++) {
|
||||
channel const& channel = *node.channels[i];
|
||||
transform& transform = node_instance.transforms[channel.target_transform_index];
|
||||
|
||||
int frame_ix = find_frame_ix(channel.source_sampler->input, t);
|
||||
if (frame_ix < 0)
|
||||
continue; // animation is missing a key frame
|
||||
|
||||
float iv = interpolation_value(channel.source_sampler->input, frame_ix, t);
|
||||
float value = linear_interpolate(channel.source_sampler->output, frame_ix, iv);
|
||||
switch (transform.type) {
|
||||
case transform_type::TRANSLATE:
|
||||
switch (channel.target_attribute) {
|
||||
case target_attribute::X: transform.translate = XMVectorSetX(transform.translate, value); break;
|
||||
case target_attribute::Y: transform.translate = XMVectorSetY(transform.translate, value); break;
|
||||
case target_attribute::Z: transform.translate = XMVectorSetZ(transform.translate, value); break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scene_state::node_world_transform(node const& node, node_instance& node_instance)
|
||||
{
|
||||
// build the node's world transform matrix
|
||||
if (node.parent_index >= 0)
|
||||
node_instance.world = m_nodeInstances[node.parent_index].world;
|
||||
else
|
||||
node_instance.world = XMMatrixIdentity();
|
||||
|
||||
for (int j = 0; j < node.transforms_count; j++) {
|
||||
node_instance.world = TransformMatrix(node_instance.transforms[j]) * node_instance.world;
|
||||
}
|
||||
}
|
||||
|
||||
void scene_state::render(float t)
|
||||
{
|
||||
g_pViewVariable->SetMatrix((float *)&g_View);
|
||||
g_pProjectionVariable->SetMatrix((float *)&g_Projection);
|
||||
|
||||
g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
t = loop(t / 2.0f, 3.333333f);
|
||||
|
||||
for (int i = 0; i < m_descriptor->nodes_count; i++) {
|
||||
node const& node = *m_descriptor->nodes[i];
|
||||
node_instance& node_instance = m_nodeInstances[i];
|
||||
|
||||
animate_node(node, node_instance, t);
|
||||
node_world_transform(node, node_instance);
|
||||
|
||||
g_pWorldVariable->SetMatrix((float *)&node_instance.world);
|
||||
|
||||
// joints aren't rendered
|
||||
if (node.type != node_type::NODE)
|
||||
continue;
|
||||
|
||||
node_instance const& node_instance = m_nodeInstances[i];
|
||||
XMMATRIX World = XMMatrixIdentity();
|
||||
// build the world transform
|
||||
for (int j = 0; j < node.transforms_count; j++) {
|
||||
World = TransformMatrix(node_instance.transforms[j]) * World;
|
||||
}
|
||||
g_pWorldVariable->SetMatrix((float *)&World);
|
||||
|
||||
render_geometries(node.instance_geometries, node.instance_geometries_count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1843,7 +1843,7 @@ void Render(float t, float dt)
|
||||
|
||||
//collada::Render(t);
|
||||
|
||||
g_SceneState.render();
|
||||
g_SceneState.render(t);
|
||||
|
||||
RenderFont(dt);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user