commit a5b18367bb7164b3eae5be70ae6bf992e61aeadc
parent ef902cf2722f131033e139ca187f97e463b65a4b
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 8 Oct 2020 16:14:38 +0200
Speed up closest point on instantiated meshes
Closest point computation on instantiated meshes is performed in
instance space rather than in world space. Only the query position is
thus transformed.
Diffstat:
1 file changed, 22 insertions(+), 31 deletions(-)
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,39 +192,38 @@ 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;
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 */
+ query_pos_ls[0] = f3_dot(query_pos_ws, world2inst+0) + world2inst[12];
+ query_pos_ls[1] = f3_dot(query_pos_ws, world2inst+4) + world2inst[13];
+ query_pos_ls[2] = f3_dot(query_pos_ws, world2inst+8) + 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);
/* Compute the distance */
- f3_sub(vec, closest_point, query_pos);
+ f3_sub(vec, closest_point, query_pos_ls);
dst = f3_len(vec);
- /* Adjust the distance in world space */
+ /* Transform the distance in world space */
if(args->context->instStackSize != 0) {
- ASSERT(args->context->instStackSize == 1);
ASSERT(args->similarityScale > 0);
dst /= args->similarityScale;
}
@@ -261,7 +261,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! */
}
@@ -305,7 +305,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));
@@ -326,13 +325,6 @@ closest_point_sphere
/* Evaluate the distance from the query pos to the sphere surface */
dst = fabsf(len - geom->data.sphere->radius);
- if(args->context->instStackSize != 0) { /* It is an instance */
- /* Adjust the distance in world space */
- ASSERT(args->context->instStackSize == 1);
- ASSERT(args->similarityScale > 0);
- dst /= args->similarityScale;
- }
-
/* The closest point onto the sphere is outside the query radius */
if(dst >= args->query->radius)
return 0;
@@ -406,7 +398,6 @@ closest_point(struct RTCPointQueryFunctionArguments* args)
(ctx->scnview, args->geomID);
} else {
ASSERT(args->context->instStackSize == 1);
- ASSERT(args->similarityScale > 0);
inst = scene_view_geometry_from_embree_id
(ctx->scnview, args->context->instID[0]);
geom = scene_view_geometry_from_embree_id