commit dff27e2ea9869abde08d775cd52772c9c319e2d6
parent 27cb32ed16e7e7e223cb6bb51411eb3461d86313
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 19 Nov 2020 11:51:14 +0100
Merge branch 'release_0.7.3'
Diffstat:
6 files changed, 172 insertions(+), 37 deletions(-)
diff --git a/README.md b/README.md
@@ -120,9 +120,16 @@ with `<STAR3D_INSTALL_DIR>` the install directory of Star-3D and
## Release notes
+### Version 0.7.3
+
+- Fix the `s3d_scene_view_closest_point` function on the scenes containing
+ instantiated meshes: the rotation of the instances was wrongly taken into
+ account.
+- Speed up the `s3d_scene_view_closest_point` query on instantiated meshes.
+
### Version 0.7.2
-- Fix a precision issue in the `s3d_scene_view_closes_point` function: the
+- Fix a precision issue in the `s3d_scene_view_closest_point` function: the
returned hit could have invalid barycentric coordinates.
### Version 0.7.1
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 2)
+set(VERSION_PATCH 3)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(S3D_FILES_SRC
diff --git a/src/s3d.h b/src/s3d.h
@@ -207,7 +207,7 @@ static const struct s3d_accel_struct_conf S3D_ACCEL_STRUCT_CONF_DEFAULT =
/* Filter function data type. One can define such function to discard
* intersections along a ray or the result of a closest point query with
* respect to user defined criteria, e.g.: masked/transparent primitive, etc.
- * Return 0 or the intersection is not discarded and a value not equal to zero
+ * Return 0 if or the intersection is not discarded and a value not equal to zero
* otherwise. */
typedef int
(*s3d_hit_filter_function_T)
@@ -470,16 +470,16 @@ s3d_shape_flip_surface
/*******************************************************************************
* Primitive API - Define a geometric primitive of a shape
******************************************************************************/
-/* Retrieve the attribute of the shape primitive `iprim' at the barycentric
+/* Retrieve the attribute of the shape primitive `prim' at the barycentric
* coordinates `uv' */
S3D_API res_T
s3d_primitive_get_attrib
(const struct s3d_primitive* prim,
const enum s3d_attrib_usage attr, /* Attribute to retrieve */
- const float st[2], /* Parametric coordinates of `attr' on `iprim' */
+ const float st[2], /* Parametric coordinates of `attr' on `prim' */
struct s3d_attrib* attrib); /* Resulting attrib */
-/* Retrieve if the primitive `iprim' has the attribute `attr' */
+/* Retrieve if the primitive `prim' has the attribute `attr' */
S3D_API res_T
s3d_primitive_has_attrib
(const struct s3d_primitive* prim,
diff --git a/src/s3d_backend.h b/src/s3d_backend.h
@@ -33,6 +33,18 @@
#ifndef S3D_BACKEND_H
#define S3D_BACKEND_H
+#include <rsys/rsys.h> /* COMPILER_CL */
+
+#ifdef COMPILER_CL
+ /* Structure was padded due to alignment specifier */
+ #pragma warning(push)
+ #pragma warning(disable: 4324)
+#endif
+
#include <embree3/rtcore.h>
+#ifdef COMPILER_CL
+ #pragma warning(pop)
+#endif
+
#endif /* S3D_BACKEND_H */
diff --git a/src/s3d_scene_view_closest_point.c b/src/s3d_scene_view_closest_point.c
@@ -171,7 +171,8 @@ closest_point_mesh
struct hit_filter* filter = NULL;
const uint32_t* ids = NULL;
float closest_point[3];
- float query_pos[3];
+ float query_pos_ws[3]; /* World space query position */
+ float query_pos_ls[3]; /* Local space query position */
float v0[3], v1[3], v2[3];
float E0[3], E1[3], Ng[3];
float vec[3];
@@ -191,34 +192,46 @@ closest_point_mesh
f3_set(v2, mesh_get_pos(geom->data.mesh) + ids[2]*3/*#coords per vertex*/);
/* Local copy of the query position */
- query_pos[0] = args->query->x;
- query_pos[1] = args->query->y;
- query_pos[2] = args->query->z;
-
- if(args->context->instStackSize) { /* The mesh is instantiated */
- const float* transform;
- transform = inst->data.instance->transform;
+ query_pos_ws[0] = args->query->x;
+ query_pos_ws[1] = args->query->y;
+ query_pos_ws[2] = args->query->z;
+
+ if(!args->context->instStackSize) { /* The mesh is instantiated */
+ query_pos_ls[0] = query_pos_ws[0];
+ query_pos_ls[1] = query_pos_ws[1];
+ query_pos_ls[2] = query_pos_ws[2];
+ } else {
+ const float* world2inst;
+ float a[3], b[3], c[3];
ASSERT(args->context->instStackSize == 1);
- ASSERT(args->similarityScale == 1);
ASSERT(inst && inst->type == GEOM_INSTANCE);
- ASSERT(f3_eq_eps(transform+0, args->context->inst2world[0]+0, 1.e-6f));
- ASSERT(f3_eq_eps(transform+3, args->context->inst2world[0]+4, 1.e-6f));
- ASSERT(f3_eq_eps(transform+6, args->context->inst2world[0]+8, 1.e-6f));
- ASSERT(f3_eq_eps(transform+9, args->context->inst2world[0]+12,1.e-6f));
- /* Transform the triangle vertices in world space */
- f3_add(v0, f33_mulf3(v0, transform, v0), transform+9);
- f3_add(v1, f33_mulf3(v1, transform, v1), transform+9);
- f3_add(v2, f33_mulf3(v2, transform, v2), transform+9);
+ world2inst = args->context->world2inst[0];
+
+ /* Transform the query position in instance space */
+ f3_mulf(a, world2inst+0, query_pos_ws[0]);
+ f3_mulf(b, world2inst+4, query_pos_ws[1]);
+ f3_mulf(c, world2inst+8, query_pos_ws[2]);
+ query_pos_ls[0] = a[0] + b[0] + c[0] + world2inst[12];
+ query_pos_ls[1] = a[1] + b[1] + c[1] + world2inst[13];
+ query_pos_ls[2] = a[2] + b[2] + c[2] + world2inst[14];
flip_surface = inst->flip_surface;
}
/* Compute the closest point onto the triangle from the submitted point */
- closest_point_triangle(query_pos, v0, v1, v2, closest_point, uv);
+ closest_point_triangle(query_pos_ls, v0, v1, v2, closest_point, uv);
- f3_sub(vec, closest_point, query_pos);
+ /* Compute the distance */
+ f3_sub(vec, closest_point, query_pos_ls);
dst = f3_len(vec);
+
+ /* Transform the distance in world space */
+ if(args->context->instStackSize != 0) {
+ ASSERT(args->similarityScale > 0);
+ dst /= args->similarityScale;
+ }
+
if(dst >= args->query->radius) return 0;
/* Compute the triangle normal in world space */
@@ -252,7 +265,7 @@ closest_point_mesh
* computed hit */
filter = &geom->data.mesh->filter;
if(filter->func
- && filter->func(&hit, query_pos, vec, query_data, filter->data)) {
+ && filter->func(&hit, query_pos_ws, vec, query_data, filter->data)) {
return 0; /* This point is filtered. Discard it! */
}
@@ -296,7 +309,6 @@ closest_point_sphere
const float* transform;
transform = inst->data.instance->transform;
ASSERT(args->context->instStackSize == 1);
- ASSERT(args->similarityScale == 1);
ASSERT(inst && inst->type == GEOM_INSTANCE);
ASSERT(f3_eq_eps(transform+0, args->context->inst2world[0]+0, 1.e-6f));
ASSERT(f3_eq_eps(transform+3, args->context->inst2world[0]+4, 1.e-6f));
@@ -390,7 +402,6 @@ closest_point(struct RTCPointQueryFunctionArguments* args)
(ctx->scnview, args->geomID);
} else {
ASSERT(args->context->instStackSize == 1);
- ASSERT(args->similarityScale == 1);
inst = scene_view_geometry_from_embree_id
(ctx->scnview, args->context->instID[0]);
geom = scene_view_geometry_from_embree_id
diff --git a/src/test_s3d_closest_point.c b/src/test_s3d_closest_point.c
@@ -35,6 +35,7 @@
#include "test_s3d_utils.h"
#include <rsys/float3.h>
+#include <rsys/float33.h>
#include <limits.h>
#define ON_EDGE_EPSILON 1.e-4f
@@ -80,11 +81,12 @@ closest_point_triangle
float ab[3], ac[3], bc[3];
float ap[3], bp[3], cp[3];
float d1, d2, d3, d4, d5, d6, d;
+ float lab, lac, lbc;
CHK(p && a && b && c && pt);
- f3_normalize(ab, f3_sub(ab, b, a));
- f3_normalize(ac, f3_sub(ac, c, a));
- f3_normalize(bc, f3_sub(bc, c, b));
+ lab = f3_normalize(ab, f3_sub(ab, b, a));
+ lac = f3_normalize(ac, f3_sub(ac, c, a));
+ lbc = f3_normalize(bc, f3_sub(bc, c, b));
/* Compute the triangle normal */
f3_cross(N, ac, ab);
@@ -108,22 +110,22 @@ closest_point_triangle
if(d5 <= 0 && d6 <= 0) return f3_set(pt, c);
/* Check if the nearest point is on the 1st triangle edge */
- f3_normalize(Nbc, f3_cross(Nab, ab, N));
+ f3_normalize(Nab, f3_cross(Nab, ab, N));
if(f3_dot(Nab, ap) <= 0) {
- return f3_add(pt, a, f3_mulf(pt, ab, d1));
+ return f3_add(pt, a, f3_mulf(pt, ab, MMIN(d1, lab)));
}
/* Check if the nearest point is on the 2nd triangle edge */
f3_normalize(Nbc, f3_cross(Nbc, bc, N));
if(f3_dot(Nbc, bp) <= 0) {
- return f3_add(pt, b, f3_mulf(pt, bc, d3));
+ return f3_add(pt, b, f3_mulf(pt, bc, MMIN(d3, lbc)));
}
/* Check if the nearest point is on the 3rd triangle edge */
f3_normalize(Nca, f3_cross(Nca, ac, N));
f3_minus(Nca, Nca);
if(f3_dot(Nca, cp) <= 0) {
- return f3_add(pt, c, f3_mulf(pt, ac,-d5));
+ return f3_add(pt, c, f3_mulf(pt, ac,-MMIN(d5, lac)));
}
/* The nearest point is in the triangle */
@@ -746,10 +748,28 @@ test_cbox(struct s3d_device* dev)
mid[1] = (low[1] + upp[1]) * 0.5f;
mid[2] = (low[2] + upp[2]) * 0.5f;
+ /* Filter nothing */
+ filter_data.geom_to_filter[0] = S3D_INVALID_ID;
+ filter_data.geom_to_filter[1] = S3D_INVALID_ID;
+ filter_data.geom_to_filter[2] = S3D_INVALID_ID;
+
+ /* Check a specific position that exhibits a precision issues of the
+ * closest_point_triangle test routine */
+ {
+ union { float f; uint32_t ui; } ucast;
+ pos[0] = (ucast.ui = 0xc386cc9a, ucast.f);
+ pos[1] = (ucast.ui = 0x43e635b8, ucast.f);
+ pos[2] = (ucast.ui = 0x4319ab78, ucast.f);
+ f3_set(filter_data.query_pos, pos);
+ CHK(s3d_scene_view_closest_point
+ (scnview, pos, (float)INF, &filter_data, &hit) == RES_OK);
+ check_closest_point_cbox(pos, geom_id, &hit);
+ }
+
/* Check closest point query on Cornell box */
FOR_EACH(i, 0, 10000) {
/* Randomly generate a point in a bounding box that is 2 times the size of
- * the triangle AABB */
+ * the cornell box AABB */
pos[0] = mid[0] + (rand_canonic() * 2 - 1) * (upp[0] - low[0]);
pos[1] = mid[1] + (rand_canonic() * 2 - 1) * (upp[1] - low[1]);
pos[2] = mid[2] + (rand_canonic() * 2 - 1) * (upp[2] - low[2]);
@@ -768,7 +788,7 @@ test_cbox(struct s3d_device* dev)
/* Check closest point query filtering */
FOR_EACH(i, 0, 10000) {
/* Randomly generate a point in a bounding box that is 2 times the size of
- * the triangle AABB */
+ * the cornell box AABB */
pos[0] = mid[0] + (rand_canonic() * 2 - 1) * (upp[0] - low[0]);
pos[1] = mid[1] + (rand_canonic() * 2 - 1) * (upp[1] - low[1]);
pos[2] = mid[2] + (rand_canonic() * 2 - 1) * (upp[2] - low[2]);
@@ -932,6 +952,90 @@ test_single_triangle(struct s3d_device* dev)
CHK(s3d_scene_ref_put(scn) == RES_OK);
}
+static void
+test_single_triangle_instantiated(struct s3d_device* dev)
+{
+ union { float f; uint32_t u32; } ucast;
+ struct s3d_scene* scn = NULL;
+ struct s3d_shape* shape = NULL;
+ struct s3d_scene_view* view0 = NULL;
+ struct s3d_scene_view* view1 = NULL;
+ struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL;
+ struct s3d_hit hit0 = S3D_HIT_NULL;
+ struct s3d_hit hit1 = S3D_HIT_NULL;
+ float transform[12];
+ float vertices[9];
+ float transformed_vertices[9];
+ float query_pos[3];
+
+ vdata.usage = S3D_POSITION;
+ vdata.type = S3D_FLOAT3;
+ vdata.get = triangle_get_pos;
+
+ /* Setup the query position. The following data are retrieved from a user
+ * case and are thus setuped as it, in its raw binary format */
+ query_pos[0] = (ucast.u32 = 0xc1dc7a9e, ucast.f);
+ query_pos[1] = (ucast.u32 = 0xc382179f, ucast.f);
+ query_pos[2] = (ucast.u32 = 0xc32181b0, ucast.f);
+
+ f3(vertices+0, -28.5f, -298.5f, 69.964429f);
+ f3(vertices+3, -27.0f, -298.5f, 69.899651f);
+ f3(vertices+6, -27.0f, -297.0f, 69.204593f);
+
+ /* Setup the triangle transformation */
+ f33_rotation(transform, (float)MDEG2RAD(45.0), 0, 0);
+ f3_splat(transform+9, 0);
+
+ /* Transform the triangle directly */
+ f33_mulf3(transformed_vertices+0, transform, vertices+0);
+ f33_mulf3(transformed_vertices+3, transform, vertices+3);
+ f33_mulf3(transformed_vertices+6, transform, vertices+6);
+ f3_add(transformed_vertices+0, transformed_vertices+0, transform+9);
+ f3_add(transformed_vertices+1, transformed_vertices+1, transform+9);
+ f3_add(transformed_vertices+2, transformed_vertices+2, transform+9);
+
+ /* Setup the scene with the pre-transformed triangle */
+ CHK(s3d_scene_create(dev, &scn) == RES_OK);
+ CHK(s3d_shape_create_mesh(dev, &shape) == RES_OK);
+ CHK(s3d_scene_attach_shape(scn, shape) == RES_OK);
+ CHK(s3d_mesh_setup_indexed_vertices
+ (shape, 1, triangle_get_ids, 3, &vdata, 1, transformed_vertices) == RES_OK);
+ CHK(s3d_scene_view_create(scn, S3D_TRACE, &view0) == RES_OK);
+ CHK(s3d_scene_ref_put(scn) == RES_OK);
+ CHK(s3d_shape_ref_put(shape) == RES_OK);
+
+ /* Setup the same scene with the transformation performed by Star-3D through
+ * instantiation */
+ CHK(s3d_scene_create(dev, &scn) == RES_OK);
+ CHK(s3d_shape_create_mesh(dev, &shape) == RES_OK);
+ CHK(s3d_scene_attach_shape(scn, shape) == RES_OK);
+ CHK(s3d_mesh_setup_indexed_vertices
+ (shape, 1, triangle_get_ids, 3, &vdata, 1, vertices) == RES_OK);
+ CHK(s3d_shape_ref_put(shape) == RES_OK);
+ CHK(s3d_scene_instantiate(scn, &shape) == RES_OK);
+ CHK(s3d_instance_set_transform(shape, transform) == RES_OK);
+ CHK(s3d_scene_ref_put(scn) == RES_OK);
+ CHK(s3d_scene_create(dev, &scn) == RES_OK);
+ CHK(s3d_scene_attach_shape(scn, shape) == RES_OK);
+ CHK(s3d_scene_view_create(scn, S3D_TRACE, &view1) == RES_OK);
+ CHK(s3d_scene_ref_put(scn) == RES_OK);
+ CHK(s3d_shape_ref_put(shape) == RES_OK);
+
+ /* Find the closest point */
+ CHK(s3d_scene_view_closest_point
+ (view0, query_pos, (float)INF, NULL, &hit0) == RES_OK);
+ CHK(s3d_scene_view_closest_point
+ (view1, query_pos, (float)INF, NULL, &hit1) == RES_OK);
+
+ /* Check that the found hits are the same */
+ CHK(!S3D_HIT_NONE(&hit0));
+ CHK(!S3D_HIT_NONE(&hit1));
+ CHK(eq_epsf(hit0.distance, hit1.distance, 1.e-6f));
+
+ CHK(s3d_scene_view_ref_put(view0) == RES_OK);
+ CHK(s3d_scene_view_ref_put(view1) == RES_OK);
+}
+
/*******************************************************************************
* Miscellaneous test
******************************************************************************/
@@ -976,6 +1080,7 @@ main(int argc, char** argv)
test_api(dev);
test_single_triangle(dev);
+ test_single_triangle_instantiated(dev);
test_cbox(dev);
test_sphere(dev);
test_cbox_sphere(dev);