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:
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);