Files
coven/modules/ufbx/test/test_topology.h

303 lines
7.2 KiB
C

#undef UFBXT_TEST_GROUP
#define UFBXT_TEST_GROUP "topology"
#if UFBXT_IMPL
void ufbxt_check_generated_normals(ufbx_mesh *mesh, ufbxt_diff_error *err, size_t expected_normals)
{
ufbx_topo_edge *topo = calloc(mesh->num_indices, sizeof(ufbx_topo_edge));
ufbxt_assert(topo);
ufbx_compute_topology(mesh, topo, mesh->num_indices);
uint32_t *normal_indices = calloc(mesh->num_indices, sizeof(uint32_t));
size_t num_normals = ufbx_generate_normal_mapping(mesh, topo, mesh->num_indices, normal_indices, mesh->num_indices, false);
if (expected_normals > 0) {
ufbxt_assert(num_normals == expected_normals);
}
ufbx_vec3 *normals = calloc(num_normals, sizeof(ufbx_vec3));
ufbx_compute_normals(mesh, &mesh->vertex_position, normal_indices, mesh->num_indices, normals, num_normals);
ufbx_vertex_vec3 new_normals = { 0 };
new_normals.exists = true;
new_normals.values.data = normals;
new_normals.values.count = num_normals;
new_normals.indices.data = normal_indices;
new_normals.indices.count = mesh->num_indices;
for (size_t i = 0; i < mesh->num_indices; i++) {
ufbx_vec3 fn = ufbx_get_vertex_vec3(&mesh->vertex_normal, i);
ufbx_vec3 rn = ufbx_get_vertex_vec3(&new_normals, i);
ufbxt_assert_close_vec3(err, fn, rn);
}
free(normals);
free(normal_indices);
free(topo);
}
#endif
UFBXT_FILE_TEST(maya_edge_smoothing)
#if UFBXT_IMPL
{
ufbx_node *node = ufbx_find_node(scene, "pCube1");
ufbxt_assert(node && node->mesh);
ufbx_mesh *mesh = node->mesh;
ufbxt_check_generated_normals(mesh, err, 16);
}
#endif
UFBXT_FILE_TEST(maya_no_smoothing)
#if UFBXT_IMPL
{
ufbx_node *node = ufbx_find_node(scene, "pCube1");
ufbxt_assert(node && node->mesh);
ufbx_mesh *mesh = node->mesh;
ufbxt_check_generated_normals(mesh, err, 16);
}
#endif
UFBXT_FILE_TEST(maya_planar_ngon)
#if UFBXT_IMPL
{
ufbx_node *node = ufbx_find_node(scene, "pDisc1");
ufbxt_assert(node && node->mesh);
ufbx_mesh *mesh = node->mesh;
ufbxt_check_generated_normals(mesh, err, 0);
}
#endif
UFBXT_FILE_TEST(maya_subsurf_cube)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(maya_subsurf_plane)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(maya_subsurf_cube_crease)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(blender_293_suzanne_subsurf)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST_ALT(subsurf_alloc_fail, maya_subsurf_cube)
#if UFBXT_IMPL
{
ufbx_node *node = ufbx_find_node(scene, "pCube1");
ufbxt_assert(node && node->mesh);
ufbx_mesh *mesh = node->mesh;
for (size_t max_temp = 1; max_temp < 10000; max_temp++) {
ufbx_subdivide_opts opts = { 0 };
opts.temp_allocator.huge_threshold = 1;
opts.temp_allocator.allocation_limit = max_temp;
ufbxt_hintf("Temp limit: %zu", max_temp);
ufbx_error error;
ufbx_mesh *sub_mesh = ufbx_subdivide_mesh(mesh, 2, &opts, &error);
if (sub_mesh) {
ufbxt_logf(".. Tested up to %zu temporary allocations", max_temp);
ufbx_free_mesh(sub_mesh);
break;
}
ufbxt_assert(error.type == UFBX_ERROR_ALLOCATION_LIMIT);
}
for (size_t max_result = 1; max_result < 10000; max_result++) {
ufbx_subdivide_opts opts = { 0 };
opts.result_allocator.huge_threshold = 1;
opts.result_allocator.allocation_limit = max_result;
ufbxt_hintf("Result limit: %zu", max_result);
ufbx_error error;
ufbx_mesh *sub_mesh = ufbx_subdivide_mesh(mesh, 2, &opts, &error);
if (sub_mesh) {
ufbxt_logf(".. Tested up to %zu result allocations", max_result);
ufbx_free_mesh(sub_mesh);
break;
}
ufbxt_assert(error.type == UFBX_ERROR_ALLOCATION_LIMIT);
}
}
#endif
UFBXT_FILE_TEST(blender_293_suzanne_subsurf_uv)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(blender_293x_nonmanifold_subsurf)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(blender_293_ngon_subsurf)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(blender_293x_subsurf_boundary)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(blender_293x_subsurf_max_crease)
#if UFBXT_IMPL
{
ufbx_mesh *mesh = (ufbx_mesh*)ufbx_find_element(scene, UFBX_ELEMENT_MESH, "Plane");
ufbx_mesh *subdivided = ufbx_subdivide_mesh(mesh, 1, NULL, NULL);
for (size_t i = 0; i < mesh->num_edges; i++) {
ufbxt_assert_close_real(err, mesh->edge_crease.data[i], 1.0f);
}
size_t num_edge = 0;
size_t num_center = 0;
for (size_t i = 0; i < subdivided->num_edges; i++) {
ufbx_edge edge = subdivided->edges.data[i];
ufbx_vec3 a = ufbx_get_vertex_vec3(&subdivided->vertex_position, edge.a);
ufbx_vec3 b = ufbx_get_vertex_vec3(&subdivided->vertex_position, edge.b);
ufbx_real a_len = a.x*a.x + a.y*a.y + a.z*a.z;
ufbx_real b_len = b.x*b.x + b.y*b.y + b.z*b.z;
if (a_len < 0.01f || b_len < 0.01f) {
ufbxt_assert_close_real(err, subdivided->edge_crease.data[i], 0.0f);
num_center++;
} else {
ufbxt_assert_close_real(err, subdivided->edge_crease.data[i], 1.0f);
num_edge++;
}
}
ufbxt_assert(num_edge == 8);
ufbxt_assert(num_center == 4);
ufbx_free_mesh(subdivided);
}
#endif
UFBXT_FILE_TEST(maya_subsurf_max_crease)
#if UFBXT_IMPL
{
ufbx_node *node = ufbx_find_node(scene, "pCube1");
ufbxt_assert(node && node->mesh);
ufbx_mesh *subdivided = ufbx_subdivide_mesh(node->mesh, 1, NULL, NULL);
ufbxt_assert(subdivided);
size_t num_top = 0;
size_t num_bottom = 0;
for (size_t i = 0; i < subdivided->num_edges; i++) {
ufbx_edge edge = subdivided->edges.data[i];
ufbx_vec3 a = ufbx_get_vertex_vec3(&subdivided->vertex_position, edge.a);
ufbx_vec3 b = ufbx_get_vertex_vec3(&subdivided->vertex_position, edge.b);
ufbx_real a_len = a.x*a.x + a.z*a.z;
ufbx_real b_len = b.x*b.x + b.z*b.z;
if (a.y < -0.49f && b.y < -0.49f && a_len > 0.01f && b_len > 0.01f) {
ufbxt_assert_close_real(err, subdivided->edge_crease.data[i], 0.8f);
num_bottom++;
} else if (a.y > +0.49f && b.y > +0.49f && a_len > 0.01f && b_len > 0.01f) {
ufbxt_assert_close_real(err, subdivided->edge_crease.data[i], 1.0f);
num_top++;
} else {
ufbxt_assert_close_real(err, subdivided->edge_crease.data[i], 0.0f);
}
a = a;
}
ufbxt_assert(num_top == 8);
ufbxt_assert(num_bottom == 8);
ufbx_free_mesh(subdivided);
}
#endif
UFBXT_FILE_TEST(maya_subsurf_3x_cube)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(maya_subsurf_3x_cube_crease)
#if UFBXT_IMPL
{
}
#endif
#if UFBXT_IMPL
typedef struct {
ufbx_vec3 position;
ufbx_vec3 normal;
} ufbxt_vertex_pn;
#endif
UFBXT_FILE_TEST(blender_293_half_smooth_cube)
#if UFBXT_IMPL
{
ufbx_node *node = ufbx_find_node(scene, "Cube");
ufbxt_assert(node && node->mesh);
ufbx_mesh *mesh = node->mesh;
ufbxt_assert(mesh->num_indices == 6*4);
ufbxt_assert(mesh->num_triangles == 6*2);
ufbxt_vertex_pn vertices[36];
uint32_t indices[36];
size_t num_indices = 0;
uint32_t tri[64];
for (size_t fi = 0; fi < mesh->num_faces; fi++) {
size_t num_tris = ufbx_triangulate_face(tri, 64, mesh, mesh->faces.data[fi]);
for (size_t ti = 0; ti < num_tris * 3; ti++) {
vertices[num_indices].position = ufbx_get_vertex_vec3(&mesh->vertex_position, tri[ti]);
vertices[num_indices].normal = ufbx_get_vertex_vec3(&mesh->vertex_normal, tri[ti]);
num_indices++;
}
}
ufbx_vertex_stream stream = { vertices, sizeof(ufbxt_vertex_pn) };
size_t num_vertices = ufbx_generate_indices(&stream, 1, indices, num_indices, NULL, NULL);
ufbxt_assert(num_vertices == 12);
}
#endif
UFBXT_FILE_TEST(maya_vertex_crease_single)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(maya_vertex_crease)
#if UFBXT_IMPL
{
}
#endif
UFBXT_FILE_TEST(blender_312x_vertex_crease)
#if UFBXT_IMPL
{
}
#endif