571 lines
20 KiB
C
571 lines
20 KiB
C
#undef UFBXT_TEST_GROUP
|
|
#define UFBXT_TEST_GROUP "animation"
|
|
|
|
#if UFBXT_IMPL
|
|
typedef struct {
|
|
int frame;
|
|
double value;
|
|
} ufbxt_key_ref;
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_interpolation_modes)
|
|
#if UFBXT_IMPL
|
|
{
|
|
// Curve evaluated values at 24fps
|
|
static const ufbx_real values[] = {
|
|
-8.653366, // Start from zero time
|
|
-8.653366,-8.602998,-8.464664,-8.257528,-8.00075,-7.713489,-7.414906,-7.124163,-6.86042,
|
|
-6.642837,-6.490576,-6.388305,-6.306414,-6.242637,-6.19471,-6.160368,-6.137348,-6.123385,
|
|
-6.116215,-6.113573,-6.113196,-5.969524,-5.825851,-5.682179,-5.538507,-5.394835,-5.251163,
|
|
-5.107491,-4.963819,-4.820146,-4.676474,-4.532802,-4.38913,-4.245458,-4.101785,-3.958113,-4.1529,
|
|
-4.347686,-4.542472,-4.737258,-4.932045,-5.126832,-5.321618,-5.516404,-5.71119,-5.905977,-5.767788,
|
|
-5.315578,-4.954943,-4.83559,-4.856855,-4.960766,-5.118543,-4.976541,-4.885909,-4.865979,-4.93845,
|
|
-5.099224,-5.270246,-5.359269,-5.349404,-5.261964,-5.118543,-5.264501,-5.33535,-5.285445,-5.058857,
|
|
-4.69383,-4.357775,-4.124978,-3.981697,-3.904232,-3.875225,-3.875225,-3.875225,-3.875225,-3.875225,
|
|
-3.875225,-3.875225,-2.942738,-2.942738,-2.942738,-2.942738,-2.942738,-2.942738,-2.942738,-2.942738,
|
|
-2.942738,-1.243537,-1.243537,-1.243537,-1.243537,-1.243537,-1.243537,-1.243537,5.603338,5.603338,
|
|
5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,
|
|
5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338,5.603338
|
|
};
|
|
|
|
ufbxt_assert(scene->anim_layers.count == 1);
|
|
ufbx_anim_layer *layer = scene->anim_layers.data[0];
|
|
for (size_t i = 0; i < layer->anim_values.count; i++) {
|
|
ufbx_anim_value *value = layer->anim_values.data[i];
|
|
if (strcmp(value->name.data, "Lcl Translation")) continue;
|
|
ufbx_anim_curve *curve = value->curves[0];
|
|
|
|
size_t num_keys = 12;
|
|
ufbxt_assert(curve->keyframes.count == num_keys);
|
|
ufbx_keyframe *keys = curve->keyframes.data;
|
|
|
|
static const ufbxt_key_ref key_ref[] = {
|
|
{ 1, -8.653366 },
|
|
{ 11, -6.490576 },
|
|
{ 21, -6.113196 },
|
|
{ 36, -3.958113 },
|
|
{ 46, -5.905977 },
|
|
{ 53, -5.118543 },
|
|
{ 63, -5.118543 },
|
|
{ 73, -3.875225 },
|
|
{ 80, -2.942738 },
|
|
{ 89, -1.927362 },
|
|
{ 96, -1.243537 },
|
|
{ 120, 5.603338 },
|
|
};
|
|
ufbxt_assert(ufbxt_arraycount(key_ref) == num_keys);
|
|
|
|
for (size_t i = 0; i < num_keys; i++) {
|
|
ufbxt_assert_close_real(err, keys[i].time, (double)key_ref[i].frame / 24.0);
|
|
ufbxt_assert_close_real(err, keys[i].value, key_ref[i].value);
|
|
if (i > 0) ufbxt_assert(keys[i].left.dx > 0.0f);
|
|
if (i + 1 < num_keys) ufbxt_assert(keys[i].right.dx > 0.0f);
|
|
}
|
|
|
|
ufbxt_assert(keys[0].interpolation == UFBX_INTERPOLATION_CUBIC);
|
|
ufbxt_assert(keys[0].right.dy == 0.0f);
|
|
ufbxt_assert(keys[1].interpolation == UFBX_INTERPOLATION_CUBIC);
|
|
ufbxt_assert_close_real(err, keys[1].left.dy/keys[1].left.dx, keys[1].right.dy/keys[1].left.dx);
|
|
ufbxt_assert(keys[2].interpolation == UFBX_INTERPOLATION_LINEAR);
|
|
ufbxt_assert_close_real(err, keys[3].left.dy/keys[3].left.dx, keys[2].right.dy/keys[2].right.dx);
|
|
ufbxt_assert(keys[3].interpolation == UFBX_INTERPOLATION_LINEAR);
|
|
ufbxt_assert_close_real(err, keys[4].left.dy/keys[4].left.dx, keys[3].right.dy/keys[3].right.dx);
|
|
ufbxt_assert(keys[4].interpolation == UFBX_INTERPOLATION_CUBIC);
|
|
ufbxt_assert(keys[4].right.dy == 0.0f);
|
|
ufbxt_assert(keys[5].interpolation == UFBX_INTERPOLATION_CUBIC);
|
|
ufbxt_assert(keys[5].left.dy < 0.0f);
|
|
ufbxt_assert(keys[5].right.dy > 0.0f);
|
|
ufbxt_assert(keys[6].interpolation == UFBX_INTERPOLATION_CUBIC);
|
|
ufbxt_assert(keys[6].left.dy > 0.0f);
|
|
ufbxt_assert(keys[6].right.dy < 0.0f);
|
|
ufbxt_assert(keys[7].interpolation == UFBX_INTERPOLATION_CONSTANT_PREV);
|
|
ufbxt_assert(keys[8].interpolation == UFBX_INTERPOLATION_CONSTANT_PREV);
|
|
ufbxt_assert(keys[9].interpolation == UFBX_INTERPOLATION_CONSTANT_NEXT);
|
|
ufbxt_assert(keys[10].interpolation == UFBX_INTERPOLATION_CONSTANT_NEXT);
|
|
|
|
for (size_t i = 0; i < ufbxt_arraycount(values); i++) {
|
|
// Round up to the next frame to make stepped tangents consistent
|
|
double time = (double)i * (1.0/24.0) + 0.000001;
|
|
ufbx_real value = ufbx_evaluate_curve(curve, time, 0.0);
|
|
ufbxt_assert_close_real(err, value, values[i]);
|
|
}
|
|
|
|
size_t num_samples = 64 * 1024;
|
|
for (size_t i = 0; i < num_samples; i++) {
|
|
double time = (double)i * (5.0 / (double)num_samples);
|
|
ufbx_real value = ufbx_evaluate_curve(curve, time, 0.0);
|
|
ufbxt_assert(value >= -16.0f && value <= 16.0f);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_auto_clamp)
|
|
#if UFBXT_IMPL
|
|
{
|
|
// Curve evaluated values at 24fps
|
|
static const ufbx_real values[] = {
|
|
0.000, 0.000, 0.273, 0.515, 0.718, 0.868, 0.945, 0.920, 0.779, 0.611,
|
|
0.591, 0.747, 1.206, 2.059, 3.191, 4.489, 5.837, 7.121, 8.228, 9.042,
|
|
9.449, 9.694, 10.128, 10.610, 10.873, 10.927, 10.854, 10.704, 10.502,
|
|
10.264, 10.000,
|
|
};
|
|
|
|
ufbxt_assert(scene->anim_layers.count == 1);
|
|
ufbx_anim_layer *layer = scene->anim_layers.data[0];
|
|
for (size_t i = 0; i < layer->anim_values.count; i++) {
|
|
ufbx_anim_value *value = layer->anim_values.data[i];
|
|
if (strcmp(value->name.data, "Lcl Translation")) continue;
|
|
ufbx_anim_curve *curve = value->curves[0];
|
|
ufbxt_assert(curve->keyframes.count == 4);
|
|
|
|
for (size_t i = 0; i < ufbxt_arraycount(values); i++) {
|
|
double time = (double)i * (1.0/24.0);
|
|
ufbx_real value = ufbx_evaluate_curve(curve, time, 0.0);
|
|
ufbxt_assert_close_real(err, value, values[i]);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_resampled)
|
|
#if UFBXT_IMPL
|
|
{
|
|
static const ufbx_real values6[] = {
|
|
0,0,0,0,0,0,0,0,0,
|
|
-0.004, -0.022, -0.056, -0.104, -0.166, -0.241, -0.328, -0.427, -0.536, -0.654, -0.783,
|
|
-0.919, -1.063, -1.214, -1.371, -1.533, -1.700, -1.871, -2.044, -2.220, -2.398, -2.577,
|
|
-2.755, -2.933, -3.109, -3.283, -3.454, -3.621, -3.784, -3.941, -4.093, -4.237, -4.374,
|
|
-4.503, -4.623, -4.733, -4.832, -4.920, -4.996, -5.059, -5.108, -5.143, -5.168, -5.186,
|
|
-5.200, -5.209, -5.215, -5.218, -5.220, -5.220, -5.216, -5.192, -5.151, -5.091, -5.013,
|
|
-4.919, -4.810, -4.686,
|
|
};
|
|
|
|
static const ufbx_real values7[] = {
|
|
0,0,0,0,0,0,0,0,
|
|
0.000, -0.004, -0.025, -0.061, -0.112, -0.176, -0.252, -0.337, -0.431, -0.533, -0.648,
|
|
-0.776, -0.915, -1.064, -1.219, -1.378, -1.539, -1.700, -1.865, -2.037, -2.216, -2.397, -2.580,
|
|
-2.761, -2.939, -3.111, -3.278, -3.447, -3.615, -3.782, -3.943, -4.098, -4.244, -4.379,
|
|
-4.500, -4.614, -4.722, -4.821, -4.911, -4.990, -5.056, -5.107, -5.143, -5.168, -5.186, -5.200,
|
|
-5.209, -5.215, -5.218, -5.220, -5.220, -5.215, -5.190, -5.145, -5.082, -5.002, -4.908,
|
|
-4.800, -4.680, -4.550, -4.403, -4.239,
|
|
};
|
|
|
|
const ufbx_real *values = scene->metadata.version >= 7000 ? values7 : values6;
|
|
size_t num_values = scene->metadata.version >= 7000 ? ufbxt_arraycount(values7) : ufbxt_arraycount(values6);
|
|
|
|
ufbxt_assert(scene->anim_layers.count == 1);
|
|
ufbx_anim_layer *layer = scene->anim_layers.data[0];
|
|
for (size_t i = 0; i < layer->anim_values.count; i++) {
|
|
ufbx_anim_value *value = layer->anim_values.data[i];
|
|
if (strcmp(value->name.data, "Lcl Translation")) continue;
|
|
ufbx_anim_curve *curve = value->curves[0];
|
|
|
|
for (size_t i = 0; i < num_values; i++) {
|
|
double time = (double)i * (1.0/200.0);
|
|
ufbx_real value = ufbx_evaluate_curve(curve, time, 0.0);
|
|
ufbxt_assert_close_real(err, value, values[i]);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if UFBXT_IMPL
|
|
|
|
typedef struct {
|
|
int frame;
|
|
ufbx_real intensity;
|
|
ufbx_vec3 color;
|
|
} ufbxt_anim_light_ref;
|
|
|
|
typedef struct {
|
|
int frame;
|
|
ufbx_vec3 translation;
|
|
ufbx_vec3 rotation_euler;
|
|
ufbx_vec3 scale;
|
|
} ufbxt_anim_transform_ref;
|
|
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_anim_light)
|
|
#if UFBXT_IMPL
|
|
{
|
|
static const ufbxt_anim_light_ref refs[] = {
|
|
{ 0, 3.072, { 0.148, 0.095, 0.440 } },
|
|
{ 12, 1.638, { 0.102, 0.136, 0.335 } },
|
|
{ 24, 1.948, { 0.020, 0.208, 0.149 } },
|
|
{ 32, 3.676, { 0.010, 0.220, 0.113 } },
|
|
{ 40, 4.801, { 0.118, 0.195, 0.115 } },
|
|
{ 48, 3.690, { 0.288, 0.155, 0.117 } },
|
|
{ 56, 1.565, { 0.421, 0.124, 0.119 } },
|
|
{ 60, 1.145, { 0.442, 0.119, 0.119 } },
|
|
};
|
|
|
|
for (size_t i = 0; i < ufbxt_arraycount(refs); i++) {
|
|
const ufbxt_anim_light_ref *ref = &refs[i];
|
|
|
|
double time = ref->frame * (1.0/24.0);
|
|
ufbx_scene *state = ufbx_evaluate_scene(scene, &scene->anim, time, NULL, NULL);
|
|
ufbxt_assert(state);
|
|
|
|
ufbxt_check_scene(state);
|
|
|
|
ufbx_node *light_node = ufbx_find_node(state, "pointLight1");
|
|
ufbxt_assert(light_node);
|
|
ufbx_light *light = light_node->light;
|
|
ufbxt_assert(light);
|
|
|
|
ufbxt_assert_close_real(err, light->intensity, ref->intensity);
|
|
ufbxt_assert_close_vec3(err, light->color, ref->color);
|
|
|
|
ufbx_free_scene(state);
|
|
}
|
|
|
|
{
|
|
ufbx_node *node = ufbx_find_node(scene, "pointLight1");
|
|
ufbxt_assert(node && node->light);
|
|
uint32_t element_id = node->light->element.element_id;
|
|
|
|
ufbx_prop_override overrides[] = {
|
|
{ element_id, "Intensity", { (ufbx_real)10.0 } },
|
|
{ element_id, "Color", { (ufbx_real)0.3, (ufbx_real)0.6, (ufbx_real)0.9 } },
|
|
{ element_id, "|NewProp", { 10, 20, 30 }, "Test" },
|
|
{ element_id, "IntProp", { 0, 0, 0 }, "", 15 },
|
|
};
|
|
|
|
ufbx_anim anim = scene->anim;
|
|
anim.prop_overrides = ufbx_prepare_prop_overrides(overrides, ufbxt_arraycount(overrides));
|
|
|
|
ufbx_scene *state = ufbx_evaluate_scene(scene, &anim, 1.0f, NULL, NULL);
|
|
ufbxt_assert(state);
|
|
|
|
ufbxt_check_scene(state);
|
|
|
|
ufbx_node *light_node = ufbx_find_node(state, "pointLight1");
|
|
ufbxt_assert(light_node);
|
|
ufbx_light *light = light_node->light;
|
|
ufbxt_assert(light);
|
|
|
|
ufbx_vec3 ref_color = { (ufbx_real)0.3, (ufbx_real)0.6, (ufbx_real)0.9 };
|
|
ufbxt_assert_close_real(err, light->intensity, 0.1f);
|
|
ufbxt_assert_close_vec3(err, light->color, ref_color);
|
|
|
|
{
|
|
ufbx_vec3 ref_new = { 10, 20, 30 };
|
|
ufbx_prop *new_prop = ufbx_find_prop(&light->props, "|NewProp");
|
|
ufbxt_assert(new_prop);
|
|
ufbxt_assert((new_prop->flags & UFBX_PROP_FLAG_OVERRIDDEN) != 0);
|
|
ufbxt_assert(!strcmp(new_prop->value_str.data, "Test"));
|
|
ufbxt_assert(new_prop->value_int == 10);
|
|
ufbxt_assert_close_vec3(err, new_prop->value_vec3, ref_new);
|
|
|
|
ufbx_prop *int_prop = ufbx_find_prop(&light->props, "IntProp");
|
|
ufbxt_assert(int_prop);
|
|
ufbxt_assert((int_prop->flags & UFBX_PROP_FLAG_OVERRIDDEN) != 0);
|
|
ufbxt_assert_close_real(err, int_prop->value_real, 15.0f);
|
|
ufbxt_assert(int_prop->value_int == 15);
|
|
}
|
|
|
|
{
|
|
ufbx_element *original_light = &node->light->element;
|
|
|
|
ufbx_prop color = ufbx_evaluate_prop(&anim, original_light, "Color", 1.0);
|
|
ufbxt_assert((color.flags & UFBX_PROP_FLAG_OVERRIDDEN) != 0);
|
|
ufbxt_assert_close_vec3(err, color.value_vec3, ref_color);
|
|
|
|
ufbx_prop intensity = ufbx_evaluate_prop(&anim, original_light, "Intensity", 1.0);
|
|
ufbxt_assert((intensity.flags & UFBX_PROP_FLAG_OVERRIDDEN) != 0);
|
|
ufbxt_assert_close_real(err, intensity.value_real, 10.0f);
|
|
|
|
ufbx_vec3 ref_new = { 10, 20, 30 };
|
|
ufbx_prop new_prop = ufbx_evaluate_prop(&anim, original_light, "|NewProp", 1.0);
|
|
ufbxt_assert((new_prop.flags & UFBX_PROP_FLAG_OVERRIDDEN) != 0);
|
|
ufbxt_assert(!strcmp(new_prop.value_str.data, "Test"));
|
|
ufbxt_assert(new_prop.value_int == 10);
|
|
ufbxt_assert_close_vec3(err, new_prop.value_vec3, ref_new);
|
|
|
|
ufbx_prop int_prop = ufbx_evaluate_prop(&anim, original_light, "IntProp", 1.0);
|
|
ufbxt_assert((int_prop.flags & UFBX_PROP_FLAG_OVERRIDDEN) != 0);
|
|
ufbxt_assert_close_real(err, int_prop.value_real, 15.0f);
|
|
ufbxt_assert(int_prop.value_int == 15);
|
|
}
|
|
|
|
ufbx_free_scene(state);
|
|
}
|
|
|
|
{
|
|
ufbx_anim_layer *layer = scene->anim_layers.data[0];
|
|
ufbx_node *node = ufbx_find_node(scene, "pointLight1");
|
|
ufbxt_assert(node && node->light);
|
|
ufbx_light *light = node->light;
|
|
|
|
{
|
|
ufbx_anim_prop_list props = ufbx_find_anim_props(layer, &node->element);
|
|
ufbxt_assert(props.count == 3);
|
|
ufbxt_assert(!strcmp(props.data[0].prop_name.data, "Lcl Rotation"));
|
|
ufbxt_assert(!strcmp(props.data[1].prop_name.data, "Lcl Scaling"));
|
|
ufbxt_assert(!strcmp(props.data[2].prop_name.data, "Lcl Translation"));
|
|
|
|
ufbx_anim_prop *prop;
|
|
prop = ufbx_find_anim_prop(layer, &node->element, "Lcl Rotation");
|
|
ufbxt_assert(prop && !strcmp(prop->prop_name.data, "Lcl Rotation"));
|
|
prop = ufbx_find_anim_prop(layer, &node->element, "Lcl Scaling");
|
|
ufbxt_assert(prop && !strcmp(prop->prop_name.data, "Lcl Scaling"));
|
|
prop = ufbx_find_anim_prop(layer, &node->element, "Lcl Translation");
|
|
ufbxt_assert(prop && !strcmp(prop->prop_name.data, "Lcl Translation"));
|
|
}
|
|
|
|
{
|
|
ufbx_anim_prop_list props = ufbx_find_anim_props(layer, &light->element);
|
|
ufbxt_assert(props.count == 2);
|
|
ufbxt_assert(!strcmp(props.data[0].prop_name.data, "Color"));
|
|
ufbxt_assert(!strcmp(props.data[1].prop_name.data, "Intensity"));
|
|
|
|
ufbx_anim_prop *prop;
|
|
prop = ufbx_find_anim_prop(layer, &light->element, "Color");
|
|
ufbxt_assert(prop && !strcmp(prop->prop_name.data, "Color"));
|
|
prop = ufbx_find_anim_prop(layer, &light->element, "Intensity");
|
|
ufbxt_assert(prop && !strcmp(prop->prop_name.data, "Intensity"));
|
|
|
|
prop = ufbx_find_anim_prop(layer, &light->element, "Nonexistent");
|
|
ufbxt_assert(prop == NULL);
|
|
}
|
|
|
|
{
|
|
ufbx_anim_prop_list props = ufbx_find_anim_props(layer, &layer->element);
|
|
ufbxt_assert(props.count == 0);
|
|
|
|
ufbx_anim_prop *prop = ufbx_find_anim_prop(layer, &layer->element, "Weight");
|
|
ufbxt_assert(prop == NULL);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_transform_animation)
|
|
#if UFBXT_IMPL
|
|
{
|
|
static const ufbxt_anim_transform_ref refs[] = {
|
|
{ 1, { 0.000f, 0.000f, 0.000f }, { 0.000f, 0.000f, 0.000f }, { 1.000f, 1.000f, 1.000f } },
|
|
{ 5, { 0.226f, 0.452f, 0.677f }, { 2.258f, 4.515f, 6.773f }, { 1.023f, 1.045f, 1.068f } },
|
|
{ 14, { 1.000f, 2.000f, 3.000f }, { 10.000f, 20.000f, 30.000f }, { 1.100f, 1.200f, 1.300f } },
|
|
{ 20, { -0.296f, -0.592f, -0.888f }, { -2.960f, -5.920f, -8.880f }, { 0.970f, 0.941f, 0.911f } },
|
|
{ 24, { -1.000f, -2.000f, -3.000f }, { -10.000f, -20.000f, -30.000f }, { 0.900f, 0.800f, 0.700f } },
|
|
};
|
|
|
|
ufbx_node *node = ufbx_find_node(scene, "pCube1");
|
|
|
|
for (size_t i = 0; i < ufbxt_arraycount(refs); i++) {
|
|
const ufbxt_anim_transform_ref *ref = &refs[i];
|
|
double time = ref->frame * (1.0/24.0);
|
|
|
|
ufbx_scene *state = ufbx_evaluate_scene(scene, &scene->anim, time, NULL, NULL);
|
|
ufbxt_assert(state);
|
|
ufbxt_check_scene(state);
|
|
|
|
ufbx_transform t1 = state->nodes.data[node->element.typed_id]->local_transform;
|
|
ufbx_transform t2 = ufbx_evaluate_transform(&scene->anim, node, time);
|
|
|
|
ufbx_vec3 t1_euler = ufbx_quat_to_euler(t1.rotation, UFBX_ROTATION_ORDER_XYZ);
|
|
ufbx_vec3 t2_euler = ufbx_quat_to_euler(t2.rotation, UFBX_ROTATION_ORDER_XYZ);
|
|
|
|
ufbxt_assert_close_vec3(err, ref->translation, t1.translation);
|
|
ufbxt_assert_close_vec3(err, ref->translation, t2.translation);
|
|
ufbxt_assert_close_vec3(err, ref->rotation_euler, t1_euler);
|
|
ufbxt_assert_close_vec3(err, ref->rotation_euler, t2_euler);
|
|
ufbxt_assert_close_vec3(err, ref->scale, t1.scale);
|
|
ufbxt_assert_close_vec3(err, ref->scale, t2.scale);
|
|
|
|
ufbx_free_scene(state);
|
|
}
|
|
|
|
{
|
|
uint32_t element_id = node->element.element_id;
|
|
ufbxt_anim_transform_ref ref = refs[2];
|
|
ref.translation.x -= 0.1f;
|
|
ref.translation.y -= 0.2f;
|
|
ref.translation.z -= 0.3f;
|
|
ref.scale.x = 2.0f;
|
|
ref.scale.y = 3.0f;
|
|
ref.scale.z = 4.0f;
|
|
|
|
ufbx_prop_override overrides[] = {
|
|
{ element_id, "Color", { (ufbx_real)0.3, (ufbx_real)0.6, (ufbx_real)0.9 } },
|
|
{ element_id, "|NewProp", { 10, 20, 30 }, "Test", },
|
|
{ element_id, "Lcl Scaling", { 2.0f, 3.0f, 4.0f } },
|
|
{ element_id, "RotationOffset", { -0.1f, -0.2f, -0.3f } },
|
|
};
|
|
|
|
double time = 14.0/24.0;
|
|
ufbx_anim anim = scene->anim;
|
|
anim.prop_overrides = ufbx_prepare_prop_overrides(overrides, ufbxt_arraycount(overrides));
|
|
ufbx_scene *state = ufbx_evaluate_scene(scene, &anim, time, NULL, NULL);
|
|
ufbxt_assert(state);
|
|
ufbxt_check_scene(state);
|
|
|
|
ufbx_transform t1 = state->nodes.data[node->element.typed_id]->local_transform;
|
|
ufbx_transform t2 = ufbx_evaluate_transform(&anim, node, time);
|
|
|
|
ufbx_vec3 t1_euler = ufbx_quat_to_euler(t1.rotation, UFBX_ROTATION_ORDER_XYZ);
|
|
ufbx_vec3 t2_euler = ufbx_quat_to_euler(t2.rotation, UFBX_ROTATION_ORDER_XYZ);
|
|
|
|
ufbxt_assert_close_vec3(err, ref.translation, t1.translation);
|
|
ufbxt_assert_close_vec3(err, ref.translation, t2.translation);
|
|
ufbxt_assert_close_vec3(err, ref.rotation_euler, t1_euler);
|
|
ufbxt_assert_close_vec3(err, ref.rotation_euler, t2_euler);
|
|
ufbxt_assert_close_vec3(err, ref.scale, t1.scale);
|
|
ufbxt_assert_close_vec3(err, ref.scale, t2.scale);
|
|
|
|
ufbx_free_scene(state);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
UFBXT_FILE_TEST(maya_anim_layers)
|
|
#if UFBXT_IMPL
|
|
{
|
|
ufbx_anim_layer *x = (ufbx_anim_layer*)ufbx_find_element(scene, UFBX_ELEMENT_ANIM_LAYER, "X");
|
|
ufbx_anim_layer *y = (ufbx_anim_layer*)ufbx_find_element(scene, UFBX_ELEMENT_ANIM_LAYER, "Y");
|
|
ufbxt_assert(x && y);
|
|
ufbxt_assert(y->compose_rotation == false);
|
|
ufbxt_assert(y->compose_scale == false);
|
|
}
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_anim_layers_acc)
|
|
#if UFBXT_IMPL
|
|
{
|
|
ufbx_anim_layer *x = (ufbx_anim_layer*)ufbx_find_element(scene, UFBX_ELEMENT_ANIM_LAYER, "X");
|
|
ufbx_anim_layer *y = (ufbx_anim_layer*)ufbx_find_element(scene, UFBX_ELEMENT_ANIM_LAYER, "Y");
|
|
ufbxt_assert(x && y);
|
|
ufbxt_assert(y->compose_rotation == true);
|
|
ufbxt_assert(y->compose_scale == true);
|
|
}
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_anim_layers_over)
|
|
#if UFBXT_IMPL
|
|
{
|
|
ufbx_anim_layer *x = (ufbx_anim_layer*)ufbx_find_element(scene, UFBX_ELEMENT_ANIM_LAYER, "X");
|
|
ufbx_anim_layer *y = (ufbx_anim_layer*)ufbx_find_element(scene, UFBX_ELEMENT_ANIM_LAYER, "Y");
|
|
ufbxt_assert(x && y);
|
|
ufbxt_assert(y->compose_rotation == false);
|
|
ufbxt_assert(y->compose_scale == false);
|
|
}
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_anim_layers_over_acc)
|
|
#if UFBXT_IMPL
|
|
{
|
|
ufbx_anim_layer *x = (ufbx_anim_layer*)ufbx_find_element(scene, UFBX_ELEMENT_ANIM_LAYER, "X");
|
|
ufbx_anim_layer *y = (ufbx_anim_layer*)ufbx_find_element(scene, UFBX_ELEMENT_ANIM_LAYER, "Y");
|
|
ufbxt_assert(x && y);
|
|
ufbxt_assert(y->compose_rotation == true);
|
|
ufbxt_assert(y->compose_scale == true);
|
|
}
|
|
#endif
|
|
|
|
#if UFBXT_IMPL
|
|
typedef struct {
|
|
double time;
|
|
bool visible;
|
|
} ufbxt_visibility_ref;
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_cube_blinky)
|
|
#if UFBXT_IMPL
|
|
{
|
|
ufbxt_visibility_ref refs[] = {
|
|
{ 1.0, false },
|
|
{ 9.5, false },
|
|
{ 10.5, true },
|
|
{ 11.5, false },
|
|
{ 15.0, false },
|
|
{ 19.5, false },
|
|
{ 20.5, false },
|
|
{ 25.0, false },
|
|
{ 29.5, false },
|
|
{ 30.5, true },
|
|
{ 40.0, true },
|
|
{ 50.0, true },
|
|
};
|
|
|
|
for (size_t i = 0; i < ufbxt_arraycount(refs); i++) {
|
|
double time = refs[i].time / 24.0;
|
|
ufbx_scene *state = ufbx_evaluate_scene(scene, &scene->anim, time, NULL, NULL);
|
|
ufbxt_assert(state);
|
|
|
|
ufbxt_check_scene(state);
|
|
|
|
ufbx_node *node = ufbx_find_node(state, "pCube1");
|
|
ufbxt_assert(node);
|
|
ufbxt_assert(node->visible == refs[i].visible);
|
|
|
|
ufbx_free_scene(state);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if UFBXT_IMPL
|
|
typedef struct {
|
|
double time;
|
|
ufbx_real value;
|
|
} ufbxt_anim_ref;
|
|
#endif
|
|
|
|
UFBXT_FILE_TEST(maya_anim_interpolation)
|
|
#if UFBXT_IMPL
|
|
{
|
|
ufbxt_anim_ref anim_ref[] = {
|
|
// Cubic
|
|
{ 0.0 / 30.0, 0.0 },
|
|
{ 1.0 / 30.0, -0.855245 },
|
|
{ 2.0 / 30.0, -1.13344 },
|
|
{ 3.0 / 30.0, -1.17802 },
|
|
{ 4.0 / 30.0, -1.10882 },
|
|
{ 5.0 / 30.0, -0.991537 },
|
|
{ 6.0 / 30.0, -0.875223 },
|
|
{ 7.0 / 30.0, -0.808958 },
|
|
{ 8.0 / 30.0, -0.858419 },
|
|
{ 9.0 / 30.0, -1.14293 },
|
|
// Linear
|
|
{ 10.0 / 30.0, -2.0 },
|
|
// Constant previous
|
|
{ 20.0 / 30.0, -4.0 },
|
|
{ 25.0 / 30.0 - 0.001, -4.0 },
|
|
// Constant next
|
|
{ 25.0 / 30.0, -6.0 },
|
|
{ 25.0 / 30.0 + 0.001, -8.0 },
|
|
// Constant previous
|
|
{ 30.0 / 30.0, -8.0 },
|
|
{ 35.0 / 30.0 - 0.001, -8.0 },
|
|
// Linear
|
|
{ 35.0 / 30.0, -10.0 },
|
|
// Constant next
|
|
{ 40.0 / 30.0, -12.0 },
|
|
{ 40.0 / 30.0 + 0.001, -14.0 },
|
|
// Constant previous
|
|
{ 45.0 / 30.0, -14.0 },
|
|
{ 50.0 / 30.0 - 0.001, -14.0 },
|
|
// Constant next
|
|
{ 50.0 / 30.0, -16.0 },
|
|
{ 50.0 / 30.0 + 0.001, -14.0 },
|
|
// inal
|
|
{ 55.0 / 30.0, -14.0, },
|
|
};
|
|
|
|
ufbx_node *node = ufbx_find_node(scene, "pCube1");
|
|
ufbxt_assert(node);
|
|
|
|
for (size_t i = 0; i < ufbxt_arraycount(anim_ref); i++) {
|
|
ufbxt_anim_ref ref = anim_ref[i];
|
|
ufbxt_hintf("%zu: %f (frame %.2f)", i, ref.time, ref.time * 30.0f);
|
|
|
|
ufbx_prop p = ufbx_evaluate_prop(&scene->anim, &node->element, "Lcl Translation", ref.time);
|
|
ufbxt_assert_close_real(err, p.value_vec3.x, ref.value);
|
|
}
|
|
}
|
|
#endif
|
|
|