collada_scene: linear interpolation
This commit is contained in:
parent
e4bb6c2616
commit
b0906ecdc6
@ -525,6 +525,9 @@ def render_array(state, collada, accessor, array):
|
|||||||
it = iter(array.floats)
|
it = iter(array.floats)
|
||||||
for i in range(accessor.count):
|
for i in range(accessor.count):
|
||||||
vector = ", ".join(f"{float(f)}f" for f in islice(it, accessor.stride))
|
vector = ", ".join(f"{float(f)}f" for f in islice(it, accessor.stride))
|
||||||
|
if accessor.stride == 1:
|
||||||
|
yield f"{vector},"
|
||||||
|
else:
|
||||||
yield f"{{ {vector} }},"
|
yield f"{{ {vector} }},"
|
||||||
yield "};"
|
yield "};"
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -24,6 +24,7 @@ namespace collada_scene {
|
|||||||
|
|
||||||
struct node_instance {
|
struct node_instance {
|
||||||
transform * transforms = NULL;
|
transform * transforms = NULL;
|
||||||
|
XMMATRIX world;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scene_state {
|
struct scene_state {
|
||||||
@ -41,7 +42,7 @@ namespace collada_scene {
|
|||||||
collada::descriptor const * m_descriptor;
|
collada::descriptor const * m_descriptor;
|
||||||
|
|
||||||
HRESULT load_scene(collada::descriptor const * const descriptor);
|
HRESULT load_scene(collada::descriptor const * const descriptor);
|
||||||
void render();
|
void render(float t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HRESULT load_layouts();
|
HRESULT load_layouts();
|
||||||
@ -51,6 +52,7 @@ namespace collada_scene {
|
|||||||
|
|
||||||
void render_geometries(collada::instance_geometry const * const instance_geometries,
|
void render_geometries(collada::instance_geometry const * const instance_geometries,
|
||||||
int const instance_geometries_count);
|
int const instance_geometries_count);
|
||||||
|
void node_world_transform(collada::node const& node, node_instance& node_instance);
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT LoadEffect();
|
HRESULT LoadEffect();
|
||||||
|
|||||||
@ -5,17 +5,17 @@ namespace curve_interpolation {
|
|||||||
using namespace collada;
|
using namespace collada;
|
||||||
|
|
||||||
float const array_node_cube_translation_x_input_array[] = {
|
float const array_node_cube_translation_x_input_array[] = {
|
||||||
{ 0.0f },
|
0.0f,
|
||||||
{ 1.666667f },
|
1.666667f,
|
||||||
{ 3.333333f },
|
3.333333f,
|
||||||
{ 5.0f },
|
5.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
float const array_node_cube_translation_x_output_array[] = {
|
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[] = {
|
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[] = {
|
float const array_node_cube_translation_y_input_array[] = {
|
||||||
{ -0.8333334f },
|
-0.8333334f,
|
||||||
{ 0.8333334f },
|
0.8333334f,
|
||||||
{ 2.5f },
|
2.5f,
|
||||||
{ 4.166667f },
|
4.166667f,
|
||||||
};
|
};
|
||||||
|
|
||||||
float const array_node_cube_translation_y_output_array[] = {
|
float const array_node_cube_translation_y_output_array[] = {
|
||||||
{ -10.05776f },
|
-10.05776f,
|
||||||
{ 10.05852f },
|
10.05852f,
|
||||||
{ -9.941484f },
|
-9.941484f,
|
||||||
{ 10.05852f },
|
10.05852f,
|
||||||
};
|
};
|
||||||
|
|
||||||
float2 const array_node_cube_translation_y_intangent_array[] = {
|
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[] = {};
|
channel const * const node_channels_node_environmentambientlight[] = {};
|
||||||
|
|
||||||
node const node_node_environmentambientlight = {
|
node const node_node_environmentambientlight = {
|
||||||
|
.parent_index = -1,
|
||||||
|
|
||||||
.type = node_type::NODE,
|
.type = node_type::NODE,
|
||||||
|
|
||||||
.transforms = transforms_node_environmentambientlight,
|
.transforms = transforms_node_environmentambientlight,
|
||||||
@ -574,11 +576,13 @@ instance_geometry const instance_geometries_node_cube[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
channel const * const node_channels_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_y,
|
||||||
|
&node_channel_node_cube_translation_x,
|
||||||
};
|
};
|
||||||
|
|
||||||
node const node_node_cube = {
|
node const node_node_cube = {
|
||||||
|
.parent_index = -1,
|
||||||
|
|
||||||
.type = node_type::NODE,
|
.type = node_type::NODE,
|
||||||
|
|
||||||
.transforms = transforms_node_cube,
|
.transforms = transforms_node_cube,
|
||||||
@ -613,6 +617,8 @@ channel const * const node_channels_node_cylinder001[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
node const node_node_cylinder001 = {
|
node const node_node_cylinder001 = {
|
||||||
|
.parent_index = -1,
|
||||||
|
|
||||||
.type = node_type::NODE,
|
.type = node_type::NODE,
|
||||||
|
|
||||||
.transforms = transforms_node_cylinder001,
|
.transforms = transforms_node_cylinder001,
|
||||||
@ -655,6 +661,8 @@ channel const * const node_channels_node_plane001[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
node const node_node_plane001 = {
|
node const node_node_plane001 = {
|
||||||
|
.parent_index = -1,
|
||||||
|
|
||||||
.type = node_type::NODE,
|
.type = node_type::NODE,
|
||||||
|
|
||||||
.transforms = transforms_node_plane001,
|
.transforms = transforms_node_plane001,
|
||||||
|
|||||||
@ -287,26 +287,26 @@ namespace collada_scene {
|
|||||||
{
|
{
|
||||||
switch (effect.type) {
|
switch (effect.type) {
|
||||||
case effect_type::BLINN:
|
case effect_type::BLINN:
|
||||||
g_pEmissionVariable->SetFloatVector((float *)&effect.blinn.emission.color.x);
|
g_pEmissionVariable->SetFloatVector((float *)&effect.blinn.emission.color);
|
||||||
g_pAmbientVariable->SetFloatVector((float *)&effect.blinn.ambient.color.x);
|
g_pAmbientVariable->SetFloatVector((float *)&effect.blinn.ambient.color);
|
||||||
g_pDiffuseVariable->SetFloatVector((float *)&effect.blinn.diffuse.color.x);
|
g_pDiffuseVariable->SetFloatVector((float *)&effect.blinn.diffuse.color);
|
||||||
g_pSpecularVariable->SetFloatVector((float *)&effect.blinn.specular.color.x);
|
g_pSpecularVariable->SetFloatVector((float *)&effect.blinn.specular.color);
|
||||||
g_pShininessVariable->SetFloat(effect.blinn.shininess);
|
g_pShininessVariable->SetFloat(effect.blinn.shininess);
|
||||||
break;
|
break;
|
||||||
case effect_type::LAMBERT:
|
case effect_type::LAMBERT:
|
||||||
g_pEmissionVariable->SetFloatVector((float *)&effect.lambert.emission.color.x);
|
g_pEmissionVariable->SetFloatVector((float *)&effect.lambert.emission.color);
|
||||||
g_pAmbientVariable->SetFloatVector((float *)&effect.lambert.ambient.color.x);
|
g_pAmbientVariable->SetFloatVector((float *)&effect.lambert.ambient.color);
|
||||||
g_pDiffuseVariable->SetFloatVector((float *)&effect.lambert.diffuse.color.x);
|
g_pDiffuseVariable->SetFloatVector((float *)&effect.lambert.diffuse.color);
|
||||||
break;
|
break;
|
||||||
case effect_type::PHONG:
|
case effect_type::PHONG:
|
||||||
g_pEmissionVariable->SetFloatVector((float *)&effect.phong.emission.color.x);
|
g_pEmissionVariable->SetFloatVector((float *)&effect.phong.emission.color);
|
||||||
g_pAmbientVariable->SetFloatVector((float *)&effect.phong.ambient.color.x);
|
g_pAmbientVariable->SetFloatVector((float *)&effect.phong.ambient.color);
|
||||||
g_pDiffuseVariable->SetFloatVector((float *)&effect.phong.diffuse.color.x);
|
g_pDiffuseVariable->SetFloatVector((float *)&effect.phong.diffuse.color);
|
||||||
g_pSpecularVariable->SetFloatVector((float *)&effect.phong.specular.color.x);
|
g_pSpecularVariable->SetFloatVector((float *)&effect.phong.specular.color);
|
||||||
g_pShininessVariable->SetFloat(effect.phong.shininess);
|
g_pShininessVariable->SetFloat(effect.phong.shininess);
|
||||||
break;
|
break;
|
||||||
case effect_type::CONSTANT:
|
case effect_type::CONSTANT:
|
||||||
g_pEmissionVariable->SetFloatVector((float *)&effect.constant.color.x);
|
g_pEmissionVariable->SetFloatVector((float *)&effect.constant.color);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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_pViewVariable->SetMatrix((float *)&g_View);
|
||||||
g_pProjectionVariable->SetMatrix((float *)&g_Projection);
|
g_pProjectionVariable->SetMatrix((float *)&g_Projection);
|
||||||
|
|
||||||
g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
|
||||||
|
t = loop(t / 2.0f, 3.333333f);
|
||||||
|
|
||||||
for (int i = 0; i < m_descriptor->nodes_count; i++) {
|
for (int i = 0; i < m_descriptor->nodes_count; i++) {
|
||||||
node const& node = *m_descriptor->nodes[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)
|
if (node.type != node_type::NODE)
|
||||||
continue;
|
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);
|
render_geometries(node.instance_geometries, node.instance_geometries_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1843,7 +1843,7 @@ void Render(float t, float dt)
|
|||||||
|
|
||||||
//collada::Render(t);
|
//collada::Render(t);
|
||||||
|
|
||||||
g_SceneState.render();
|
g_SceneState.render(t);
|
||||||
|
|
||||||
RenderFont(dt);
|
RenderFont(dt);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user