star-3d

Surface structuring for efficient 3D geometric queries
git clone git://git.meso-star.fr/star-3d.git
Log | Files | Refs | README | LICENSE

commit 27cb32ed16e7e7e223cb6bb51411eb3461d86313
parent a27febf6e571876b86d8bfa0c47f1a1e3eca2a15
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon,  6 Jul 2020 11:27:59 +0200

Merge branch 'release_0.7.2'

Diffstat:
MREADME.md | 6++++++
Mcmake/CMakeLists.txt | 2+-
Msrc/s3d_mesh.c | 9+++++----
Msrc/s3d_scene_view_closest_point.c | 6+++++-
Msrc/test_s3d_closest_point.c | 46++++++++++++++++++++++++++++++++++++++--------
5 files changed, 55 insertions(+), 14 deletions(-)

diff --git a/README.md b/README.md @@ -36,6 +36,7 @@ electromagnetism. Please refer to these projects for informations on their purpose. * [High-Tune: RenDeRer](https://gitlab.com/meso-star/htrdr.git) + * [Stardis-Solver](https://gitlab.com/meso-star/stardis-solver.git) * [Solstice-Solver](https://gitlab.com/meso-star/solstice-solver.git) * [Star-4V/S](https://gitlab.com/meso-star/star-4v_s.git) * [Star-GebhartFactor](https://gitlab.com/meso-star/star-gf.git) @@ -119,6 +120,11 @@ with `<STAR3D_INSTALL_DIR>` the install directory of Star-3D and ## Release notes +### Version 0.7.2 + +- Fix a precision issue in the `s3d_scene_view_closes_point` function: the + returned hit could have invalid barycentric coordinates. + ### Version 0.7.1 - Fix an invalid memory read at the setup of the scene view when the diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -58,7 +58,7 @@ endif() ################################################################################ set(VERSION_MAJOR 0) set(VERSION_MINOR 7) -set(VERSION_PATCH 1) +set(VERSION_PATCH 2) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(S3D_FILES_SRC diff --git a/src/s3d_mesh.c b/src/s3d_mesh.c @@ -408,9 +408,10 @@ mesh_compute_volume(struct mesh* mesh, const char flip_surface) ids = mesh_get_ids(mesh); pos = mesh_get_pos(mesh); - /* Build a tetrahedron whose face is the mesh triangle and its appex is the - * origin. Then compute the volume of the tetrahedron and add or sub it from - * the overall volume whether the normal point toward or backward the appex */ + /* Build a tetrahedron whose base is the triangle and whose apex is the + * coordinate system's origin. Then compute the volume of the tetrahedron and + * add or sub it from the overall volume whether the normal point toward or + * backward the apex */ FOR_EACH(itri, 0, ntris) { float E0[3], E1[3], N[3]; float B, h; @@ -427,7 +428,7 @@ mesh_compute_volume(struct mesh* mesh, const char flip_surface) f3_cross(N, E0, E1); } B = f3_normalize(N, N) * 0.5f; /* Base area */ - h = -f3_dot(N, v0); /* Height from the base to the appex */ + h = -f3_dot(N, v0); /* Height from the base to the apex */ volume += (h*B); } return (float)(volume / 3.0); diff --git a/src/s3d_scene_view_closest_point.c b/src/s3d_scene_view_closest_point.c @@ -144,9 +144,13 @@ closest_point_triangle /* Save the uv barycentric coordinates */ uv[0] = 1.f - v - w; uv[1] = v; - ASSERT(eq_epsf(uv[0] + uv[1] + w, 1.f, 1.e-4f)); + if(uv[0] < 0.f) { /* Handle precision issues */ + if(uv[1] > w) uv[1] += uv[0]; + uv[0] = 0; + } + /* Use the barycentric coordinates to compute the world space position of the * closest point onto the triangle */ closest_pt[0] = a[0] + v*ab[0] + w*ac[0]; diff --git a/src/test_s3d_closest_point.c b/src/test_s3d_closest_point.c @@ -806,13 +806,14 @@ triangle_get_ids(const unsigned itri, unsigned ids[3], void* ctx) static void triangle_get_pos(const unsigned ivert, float pos[3], void* ctx) { - (void)ctx; + float* vertices = ctx; + CHK(ctx); CHK(ivert < 3); CHK(pos); switch(ivert) { /* Setup a random triangle */ - case 0: f3(pos, -0.5f, -0.3f, 0.1f); break; - case 1: f3(pos, -0.4f, 0.2f, 0.3f); break; - case 2: f3(pos, 0.7f, 0.01f, -0.5f); break; + case 0: f3_set(pos, vertices+0); break; + case 1: f3_set(pos, vertices+3); break; + case 2: f3_set(pos, vertices+6); break; default: FATAL("Unreachable code\n"); break; } } @@ -820,6 +821,7 @@ triangle_get_pos(const unsigned ivert, float pos[3], void* ctx) static void test_single_triangle(struct s3d_device* dev) { + float vertices[9]; struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL; struct s3d_hit hit = S3D_HIT_NULL; struct s3d_scene* scn = NULL; @@ -830,8 +832,13 @@ test_single_triangle(struct s3d_device* dev) float pos[3] = {0,0,0}; float closest_pos[3] = {0,0,0}; float low[3], upp[3], mid[3]; + union { float f; uint32_t ui32; } ucast; size_t i; + f3(vertices+0, -0.5f, -0.3f, 0.1f); + f3(vertices+3, -0.4f, 0.2f, 0.3f); + f3(vertices+6, 0.7f, 0.01f, -0.5f); + CHK(s3d_scene_create(dev, &scn) == RES_OK); CHK(s3d_shape_create_mesh(dev, &msh) == RES_OK); CHK(s3d_scene_attach_shape(scn, msh) == RES_OK); @@ -840,13 +847,13 @@ test_single_triangle(struct s3d_device* dev) vdata.type = S3D_FLOAT3; vdata.get = triangle_get_pos; CHK(s3d_mesh_setup_indexed_vertices - (msh, 1, triangle_get_ids, 3, &vdata, 1, NULL) == RES_OK); + (msh, 1, triangle_get_ids, 3, &vdata, 1, vertices) == RES_OK); CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK); - triangle_get_pos(0, v0, NULL); - triangle_get_pos(1, v1, NULL); - triangle_get_pos(2, v2, NULL); + triangle_get_pos(0, v0, vertices); + triangle_get_pos(1, v1, vertices); + triangle_get_pos(2, v2, vertices); /* Compute the triangle AABB */ low[0] = MMIN(MMIN(v0[0], v1[0]), v2[0]); @@ -896,6 +903,29 @@ test_single_triangle(struct s3d_device* dev) CHK(!S3D_HIT_NONE(&hit)); CHK(hit.distance == nextafterf(radius, 0.f)); } + CHK(s3d_scene_view_ref_put(view) == RES_OK); + + /* Setup a triangle and a query position that exhibited a precision issue on + * the returned barycentric coordinate and check that this bug is now fixed */ + ucast.ui32 = 0x40400000; vertices[0] = ucast.f; + ucast.ui32 = 0xc1200000; vertices[1] = ucast.f; + ucast.ui32 = 0xbfc00000; vertices[2] = ucast.f; + ucast.ui32 = 0x40400000; vertices[3] = ucast.f; + ucast.ui32 = 0xc1200000; vertices[4] = ucast.f; + ucast.ui32 = 0x3fc00000; vertices[5] = ucast.f; + ucast.ui32 = 0x3f6d5337; vertices[6] = ucast.f; + ucast.ui32 = 0xc0e4b2d5; vertices[7] = ucast.f; + ucast.ui32 = 0xbfc00000; vertices[8] = ucast.f; + f3(pos, 2, -10, 1); + + CHK(s3d_mesh_setup_indexed_vertices + (msh, 1, triangle_get_ids, 3, &vdata, 1, vertices) == RES_OK); + CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK); + CHK(s3d_scene_view_closest_point(view, pos, (float)INF, NULL, &hit) == RES_OK); + CHK(!S3D_HIT_NONE(&hit)); + CHK(0 <= hit.uv[0] && hit.uv[0] <= 1); + CHK(0 <= hit.uv[1] && hit.uv[1] <= 1); + CHK(hit.uv[0] + hit.uv[1] <= 1); CHK(s3d_shape_ref_put(msh) == RES_OK); CHK(s3d_scene_view_ref_put(view) == RES_OK);