#undef UFBXT_TEST_GROUP #define UFBXT_TEST_GROUP "cache" #if UFBXT_IMPL static void ufbxt_test_sine_cache(ufbxt_diff_error *err, const char *path, double begin, double end, double err_threshold) { char buf[512]; snprintf(buf, sizeof(buf), "%s%s", data_root, path); ufbx_geometry_cache *cache = ufbx_load_geometry_cache(buf, NULL, NULL); ufbxt_assert(cache); ufbxt_assert(cache->channels.count == 2); bool found_cube1 = false; for (size_t i = 0; i < cache->channels.count; i++) { ufbx_cache_channel *channel = &cache->channels.data[i]; ufbxt_assert(channel->interpretation == UFBX_CACHE_INTERPRETATION_VERTEX_POSITION); if (!strcmp(channel->name.data, "pCubeShape1")) { found_cube1 = true; ufbx_vec3 pos[64]; for (double time = begin; time <= end + 0.0001; time += 0.1/24.0) { size_t num_verts = ufbx_sample_geometry_cache_vec3(channel, time, pos, ufbxt_arraycount(pos), NULL); ufbxt_assert(num_verts == 36); size_t dry_verts = ufbx_sample_geometry_cache_vec3(channel, time, pos, SIZE_MAX, NULL); ufbxt_assert(num_verts == dry_verts); double t = (time - 1.0/24.0) / (29.0/24.0) * 4.0; double pi2 = 3.141592653589793*2.0; double err_scale = 0.001 / err_threshold; for (size_t i = 0; i < num_verts; i++) { ufbx_vec3 v = pos[i]; double sx = sin((v.y + t * 0.5f)*pi2) * 0.25; double vx = v.x; vx += vx > 0.0 ? -0.5 : 0.5; ufbxt_assert_close_real(err, vx*err_scale, sx*err_scale); } } } } ufbxt_assert(found_cube1); ufbx_free_geometry_cache(cache); } #endif UFBXT_FILE_TEST(maya_cache_sine) #if UFBXT_IMPL { ufbx_node *node = ufbx_find_node(scene, "pCube1"); ufbxt_assert(node && node->mesh); ufbx_mesh *mesh = node->mesh; ufbxt_assert(mesh->cache_deformers.count == 2); for (size_t i = 0; i < 2; i++) { ufbx_cache_deformer *deformer = mesh->cache_deformers.data[i]; ufbxt_assert(deformer->file); ufbxt_assert(deformer->file->format == UFBX_CACHE_FILE_FORMAT_MC); } ufbxt_check_frame(scene, err, false, "maya_cache_sine_12", NULL, 12.0/24.0); ufbxt_check_frame(scene, err, false, "maya_cache_sine_18", NULL, 18.0/24.0); } #endif UFBXT_TEST(maya_cache_sine_caches) #if UFBXT_IMPL { ufbxt_diff_error err = { 0 }; ufbxt_test_sine_cache(&err, "caches/sine_mcmf_undersample/cache.xml", 1.0/24.0, 29.0/24.0, 0.04); ufbxt_test_sine_cache(&err, "caches/sine_mcsd_oversample/cache.xml", 1.0/24.0, 29.0/24.0, 0.003); ufbxt_test_sine_cache(&err, "caches/sine_mxmd_oversample/cache.xml", 11.0/24.0, 19.0/24.0, 0.003); ufbxt_test_sine_cache(&err, "caches/sine_mxsf_regular/cache.xml", 1.0/24.0, 29.0/24.0, 0.008); ufbxt_logf(".. Absolute diff: avg %.3g, max %.3g (%zu tests)", err.sum / (ufbx_real)err.num, err.max, err.num); } #endif UFBXT_FILE_TEST(max_cache_box) #if UFBXT_IMPL { ufbx_node *node = ufbx_find_node(scene, "Box001"); ufbxt_assert(node && node->mesh); ufbx_mesh *mesh = node->mesh; ufbxt_assert(mesh->cache_deformers.count == 1); ufbx_cache_deformer *deformer = mesh->cache_deformers.data[0]; ufbxt_assert(deformer->file); ufbxt_assert(deformer->file->format == UFBX_CACHE_FILE_FORMAT_PC2); ufbxt_assert(deformer->external_cache); ufbxt_assert(deformer->external_channel); ufbxt_assert(deformer->external_channel->frames.count == 11); for (size_t i = 0; i < deformer->external_channel->frames.count; i++) { ufbx_cache_frame *frame = &deformer->external_channel->frames.data[i]; ufbxt_assert(frame->file_format == UFBX_CACHE_FILE_FORMAT_PC2); } ufbxt_check_frame(scene, err, false, "max_cache_box_44", NULL, 44.0/30.0); ufbxt_check_frame(scene, err, false, "max_cache_box_48", NULL, 48.0/30.0); } #endif UFBXT_TEST(cache_xml_parse) #if UFBXT_IMPL { char buf[512]; snprintf(buf, sizeof(buf), "%s%s", data_root, "caches/sine_xml_parse/cache.xml"); ufbx_geometry_cache *cache = ufbx_load_geometry_cache(buf, NULL, NULL); ufbxt_assert(cache); ufbxt_assert(cache->extra_info.count == 2); ufbxt_check_string(cache->extra_info.data[0]); ufbxt_check_string(cache->extra_info.data[1]); const char *ex0 = "cdata! \"'&<><--<a-->!CDATA[]>\x61\xce\xb2\xe3\x82\xab\xf0\x9f\x98\x82]]"; ufbxt_assert(!strcmp(cache->extra_info.data[0].data, ex0)); const char *ex1 = "\"'&<>\x61\x61\x61\xce\xb2\xce\xb2\xce\xb2\xe3\x82\xab\xe3\x82\xab\xe3\x82\xab\xf0\x9f\x98\x82\xf0\x9f\x98\x82\xf0\x9f\x98\x82"; ufbxt_assert(!strcmp(cache->extra_info.data[1].data, ex1)); ufbxt_assert(cache->channels.count == 2); ufbxt_check_string(cache->channels.data[0].name); ufbxt_check_string(cache->channels.data[1].name); ufbxt_check_string(cache->channels.data[0].interpretation_name); ufbxt_check_string(cache->channels.data[1].interpretation_name); ufbxt_assert(cache->channels.data[0].interpretation == UFBX_CACHE_INTERPRETATION_UNKNOWN); ufbxt_assert(cache->channels.data[1].interpretation == UFBX_CACHE_INTERPRETATION_UNKNOWN); ufbxt_assert(!strcmp(cache->channels.data[0].interpretation_name.data, "")); ufbxt_assert(!strcmp(cache->channels.data[1].interpretation_name.data, "]]>")); ufbx_free_geometry_cache(cache); } #endif UFBXT_TEST(cache_xml_depth) #if UFBXT_IMPL { char buf[512]; snprintf(buf, sizeof(buf), "%s%s", data_root, "cache_xml_depth.xml"); ufbx_error error; ufbx_geometry_cache *cache = ufbx_load_geometry_cache(buf, NULL, &error); ufbxt_assert(!cache); ufbxt_assert(error.type == UFBX_ERROR_UNKNOWN); } #endif UFBXT_FILE_TEST_OPTS(marvelous_quad, ufbxt_scale_to_cm_opts) #if UFBXT_IMPL { { ufbx_node *node = ufbx_find_node(scene, "marvelous_quad"); ufbxt_assert(node && node->mesh); ufbx_mesh *mesh = node->mesh; ufbxt_assert(mesh->materials.count == 1); ufbx_material *material = mesh->materials.data[0].material; // What? Marvelous writes relative filenames as absolute. // TODO: Quirk mode to fix this? const char *prefix = "D:\\Dev\\clean\\ufbx\\data\\"; ufbxt_check_material_texture_ex(scene, material->fbx.ambient_color.texture, prefix, "marvelous_quad_diffuse_100-1.png", true); ufbxt_check_material_texture_ex(scene, material->fbx.diffuse_color.texture, prefix, "marvelous_quad_diffuse_100-1.png", true); ufbxt_check_material_texture_ex(scene, material->fbx.normal_map.texture, prefix, "marvelous_quad_normal_100-1.png", true); ufbxt_check_material_texture_ex(scene, material->pbr.base_color.texture, prefix, "marvelous_quad_diffuse_100-1.png", true); ufbxt_check_material_texture_ex(scene, material->pbr.normal_map.texture, prefix, "marvelous_quad_normal_100-1.png", true); } ufbxt_check_frame(scene, err, false, "marvelous_quad_12", NULL, 12.0/24.0); ufbxt_check_frame(scene, err, false, "marvelous_quad_22", NULL, 22.0/24.0); } #endif