commit 3e5fb1411c8d1b794b05e6685ff81d113a24d0ac
parent 7ec7b1b1676adaac344beaf22282a1ac930dee35
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 22 Jun 2021 09:48:46 +0200
Update the API of the hit filter function
Add the submitted range as input argument. During ray-tracing, it
is simply the ray range. For closest-point queries, the range
goes from 0 to the query radius.
Diffstat:
10 files changed, 79 insertions(+), 21 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2015-2019 |Meso|Star> (contact@meso-star.com)
+# Copyright (C) 2015-2020 |Meso|Star> (contact@meso-star.com)
#
# This software is a computer program whose purpose is to generate files used
# to build the Star-3D library.
diff --git a/src/s3d.h b/src/s3d.h
@@ -214,6 +214,7 @@ typedef int
(const struct s3d_hit* hit,
const float org[3],
const float dir[3], /* Direction from `org' to `hit' */
+ const float range[2], /* Submitted range */
void* query_data, /* User data submitted on query invocation */
void* filter_data); /* Data defined on the setup of the filter function */
diff --git a/src/s3d_scene_view_closest_point.c b/src/s3d_scene_view_closest_point.c
@@ -47,6 +47,7 @@
struct point_query_context {
struct RTCPointQueryContext rtc;
struct s3d_scene_view* scnview;
+ float radius; /* Submitted radius */
void* data; /* Per point query defined data */
};
@@ -167,6 +168,7 @@ closest_point_mesh
(struct RTCPointQueryFunctionArguments* args,
struct geometry* geom,
struct geometry* inst, /* Can be NULL */
+ const float radius,
void* query_data)
{
struct s3d_hit hit = S3D_HIT_NULL;
@@ -181,9 +183,9 @@ closest_point_mesh
double vec[3];
double uv[2];
float dst;
- float pos[3], dir[3];
+ float pos[3], dir[3], range[2];
int flip_surface = 0;
- ASSERT(args && geom && geom->type == GEOM_MESH);
+ ASSERT(args && geom && geom->type == GEOM_MESH && radius >= 0);
ASSERT(args->primID < mesh_get_ntris(geom->data.mesh));
/* Fetch triangle indices */
@@ -267,14 +269,18 @@ closest_point_mesh
+ geom->scene_prim_id_offset
+ (inst ? inst->scene_prim_id_offset : 0);
+ range[0] = 0;
+ range[1] = radius;
+
/* `dir' is the direction along which the closest point was found. We thus
* submit it to the filter function as the direction corresponding to the
* computed hit */
f3_set_d3(dir, vec);
f3_set_d3(pos, query_pos_ws);
+
filter = &geom->data.mesh->filter;
if(filter->func
- && filter->func(&hit, pos, dir, query_data, filter->data)) {
+ && filter->func(&hit, pos, dir, range, query_data, filter->data)) {
return 0; /* This point is filtered. Discard it! */
}
@@ -293,6 +299,7 @@ closest_point_sphere
(struct RTCPointQueryFunctionArguments* args,
struct geometry* geom,
struct geometry* inst,
+ const float radius, /* User defined radius */
void* query_data)
{
struct s3d_hit hit = S3D_HIT_NULL;
@@ -301,12 +308,13 @@ closest_point_sphere
float query_pos[3];
float sphere_pos[3];
float Ng[3];
- float dir[3];
+ float dir[3], range[2];
float uv[2];
float dst;
float len;
int flip_surface = 0;
ASSERT(args && geom && geom->type == GEOM_SPHERE && args->primID == 0);
+ ASSERT(radius >= 0);
/* Local copy of the query position */
query_pos[0] = args->query->x;
@@ -377,12 +385,15 @@ closest_point_sphere
+ geom->scene_prim_id_offset
+ (inst ? inst->scene_prim_id_offset : 0);
+ range[0] = 0;
+ range[1] = radius;
+
/* Use the reversed geometric normal as the hit direction since it is along
* this vector that the closest point was effectively computed */
f3_minus(dir, Ng);
filter = &geom->data.sphere->filter;
if(filter->func
- && filter->func(&hit, query_pos, dir, query_data, filter->data)) {
+ && filter->func(&hit, query_pos, dir, range, query_data, filter->data)) {
return 0;
}
@@ -419,10 +430,12 @@ closest_point(struct RTCPointQueryFunctionArguments* args)
switch(geom->type) {
case GEOM_MESH:
- query_radius_is_upd = closest_point_mesh(args, geom, inst, ctx->data);
+ query_radius_is_upd = closest_point_mesh
+ (args, geom, inst, ctx->radius, ctx->data);
break;
case GEOM_SPHERE:
- query_radius_is_upd = closest_point_sphere(args, geom, inst, ctx->data);
+ query_radius_is_upd = closest_point_sphere
+ (args, geom, inst, ctx->radius, ctx->data);
break;
default: FATAL("Unreachable code\n"); break;
}
@@ -464,6 +477,7 @@ s3d_scene_view_closest_point
/* Initialise the point query context */
rtcInitPointQueryContext(&query_ctx.rtc);
query_ctx.scnview = scnview;
+ query_ctx.radius = radius;
query_ctx.data = query_data;
/* Here we go! */
diff --git a/src/s3d_scene_view_trace_ray.c b/src/s3d_scene_view_trace_ray.c
@@ -48,6 +48,7 @@ struct intersect_context {
void* data; /* Per ray user defined data */
float ws_org[3]; /* World space ray origin */
float ws_dir[3]; /* World space ray direction */
+ float ws_range[3]; /* World space ray range */
};
/*******************************************************************************
@@ -216,6 +217,8 @@ s3d_scene_view_trace_ray
intersect_ctx.ws_dir[0] = dir[0];
intersect_ctx.ws_dir[1] = dir[1];
intersect_ctx.ws_dir[2] = dir[2];
+ intersect_ctx.ws_range[0] = range[0];
+ intersect_ctx.ws_range[1] = range[1];
intersect_ctx.scnview = scnview;
intersect_ctx.data = ray_data;
@@ -276,6 +279,7 @@ rtc_hit_filter_wrapper(const struct RTCFilterFunctionNArguments* args)
struct intersect_context* ctx;
struct geometry* geom;
struct hit_filter* filter;
+ int is_hit_filtered = 0;
ASSERT(args && args->N == 1 && args->context && args->valid[0] != 0);
rtc_rayN_get_ray(args->ray, args->N, 0, &ray_hit.ray);
@@ -296,7 +300,9 @@ rtc_hit_filter_wrapper(const struct RTCFilterFunctionNArguments* args)
ASSERT(filter->func);
hit_setup(ctx->scnview, &ray_hit, &hit);
- if(filter->func(&hit, ctx->ws_org, ctx->ws_dir, ctx->data, filter->data)) {
+ is_hit_filtered = filter->func
+ (&hit, ctx->ws_org, ctx->ws_dir, ctx->ws_range, ctx->data, filter->data);
+ if(is_hit_filtered) {
args->valid[0] = 0;
}
}
diff --git a/src/test_s3d_closest_point.c b/src/test_s3d_closest_point.c
@@ -473,6 +473,7 @@ test_cbox_sphere(struct s3d_device* dev)
******************************************************************************/
struct sphere_filter_data {
float query_pos[3];
+ float query_radius;
};
static int
@@ -480,6 +481,7 @@ sphere_filter
(const struct s3d_hit* hit,
const float org[3],
const float dir[3],
+ const float range[2],
void* query_data,
void* filter_data)
{
@@ -488,7 +490,7 @@ sphere_filter
float pos[3];
float vec[3];
- CHK(hit && org && dir && !S3D_HIT_NONE(hit));
+ CHK(hit && org && dir && range && !S3D_HIT_NONE(hit));
CHK((intptr_t)filter_data == (intptr_t)0xDECAFBAD);
CHK(f3_normalize(vec, dir) != 0);
@@ -498,6 +500,8 @@ sphere_filter
CHK(f3_eq_eps(attr.value, pos, POSITION_EPSILON));
CHK(f3_eq_eps(data->query_pos, org, POSITION_EPSILON));
+ CHK(range[0] == 0);
+ CHK(range[1] == data->query_radius);
return 1;
}
@@ -588,6 +592,7 @@ test_sphere(struct s3d_device* dev)
f3_splat(query_pos, 10);
f3_set(filter_data.query_pos, query_pos);
+ filter_data.query_radius = (float)INF;
CHK(s3d_scene_view_closest_point
(scnview, query_pos, (float)INF, &filter_data, &hit) == RES_OK);
CHK(!S3D_HIT_NONE(&hit));
@@ -615,6 +620,7 @@ enum cbox_geom {
struct cbox_filter_data {
float query_pos[3];
+ float query_radius;
unsigned geom_to_filter[3];
};
@@ -623,6 +629,7 @@ cbox_filter
(const struct s3d_hit* hit,
const float org[3],
const float dir[3],
+ const float range[2],
void* query_data,
void* filter_data)
{
@@ -631,7 +638,7 @@ cbox_filter
float pos[3];
float vec[3];
- CHK(hit && org && dir && !S3D_HIT_NONE(hit));
+ CHK(hit && org && dir && range && !S3D_HIT_NONE(hit));
CHK((intptr_t)filter_data == (intptr_t)0xDECAFBAD);
CHK(f3_normalize(vec, dir) != 0);
@@ -643,6 +650,8 @@ cbox_filter
if(!query_data) return 0;
CHK(f3_eq_eps(data->query_pos, org, POSITION_EPSILON));
+ CHK(range[0] == 0);
+ CHK(range[1] == data->query_radius);
return data->geom_to_filter[0] == hit->prim.geom_id
|| data->geom_to_filter[1] == hit->prim.geom_id
@@ -762,6 +771,7 @@ test_cbox(struct s3d_device* dev)
pos[1] = (ucast.ui = 0x43e635b8, ucast.f);
pos[2] = (ucast.ui = 0x4319ab78, ucast.f);
f3_set(filter_data.query_pos, pos);
+ filter_data.query_radius = (float)INF;
CHK(s3d_scene_view_closest_point
(scnview, pos, (float)INF, &filter_data, &hit) == RES_OK);
check_closest_point_cbox(pos, geom_id, &hit);
@@ -795,6 +805,7 @@ test_cbox(struct s3d_device* dev)
pos[2] = mid[2] + (rand_canonic() * 2 - 1) * (upp[2] - low[2]);
f3_set(filter_data.query_pos, pos);
+ filter_data.query_radius = (float)INF;
CHK(s3d_scene_view_closest_point
(scnview, pos, (float)INF, &filter_data, &hit) == RES_OK);
diff --git a/src/test_s3d_scene_view.c b/src/test_s3d_scene_view.c
@@ -48,10 +48,11 @@ filter
(const struct s3d_hit* hit,
const float org[3],
const float dir[3],
+ const float range[2],
void* ray_data,
void* filter_data)
{
- (void)org, (void)dir, (void)ray_data, (void)filter_data;
+ (void)org, (void)dir, (void)range, (void)ray_data, (void)filter_data;
CHK(S3D_HIT_NONE(hit) == 0);
return hit->prim.prim_id % 2 == 0;
}
diff --git a/src/test_s3d_shape.c b/src/test_s3d_shape.c
@@ -42,10 +42,11 @@ filter_none
(const struct s3d_hit* hit,
const float org[3],
const float dir[3],
+ const float range[2],
void* ray_data,
void* filter_data)
{
- (void)hit, (void)org, (void)dir, (void)ray_data, (void)filter_data;
+ (void)hit, (void)org, (void)dir, (void)range, (void)ray_data, (void)filter_data;
return 0;
}
diff --git a/src/test_s3d_sphere_instance.c b/src/test_s3d_sphere_instance.c
@@ -45,12 +45,15 @@ filter_front_face
(const struct s3d_hit* hit,
const float pos[3],
const float dir[3],
+ const float range[2],
void* ray_data,
void* filter_data)
{
CHK(hit != NULL);
CHK(pos != NULL);
CHK(dir != NULL);
+ CHK(range != NULL);
+ CHK(range[0] < range[1]);
CHK(filter_data == NULL);
CHK(ray_data == NULL);
CHK(S3D_HIT_NONE(hit) == 0);
diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c
@@ -35,28 +35,41 @@
#include "test_s3d_cbox.h"
#include "test_s3d_utils.h"
-#include <rsys/image.h>
+#include <rsys/float2.h>
#include <rsys/float3.h>
+#include <rsys/image.h>
#include <string.h>
#define IMG_WIDTH 640
#define IMG_HEIGHT 480
+struct ray_data {
+ float ray_org[3];
+ float ray_dir[3];
+ float ray_range[2];
+};
+
static int
filter_func
(const struct s3d_hit* hit,
const float pos[3],
const float dir[3],
+ const float range[2],
void* ray_data,
void* filter_data)
{
+ struct ray_data* data = ray_data;
CHK(hit != NULL);
CHK(pos != NULL);
CHK(dir != NULL);
- CHK((uintptr_t)ray_data == 0xDEADBEEF);
+ CHK(range != NULL);
+ CHK(ray_data != NULL);
CHK((uintptr_t)filter_data == 0xDECAFBAD);
CHK(S3D_HIT_NONE(hit) == 0);
+ CHK(f3_eq(pos, data->ray_org));
+ CHK(f3_eq(dir, data->ray_dir));
+ CHK(f2_eq(range, data->ray_range));
return hit->prim.prim_id % 2 == 0;
}
@@ -309,12 +322,17 @@ main(int argc, char** argv)
pixel[1] = (float)iy/(float)IMG_HEIGHT;
FOR_EACH(ix, 0, IMG_WIDTH) {
+ struct ray_data ray_data;
const size_t ipix = (iy*IMG_WIDTH + ix) * 3/*RGB*/;
pixel[0] = (float)ix/(float)IMG_WIDTH;
camera_ray(&cam, pixel, org, dir);
+
+ f3_set(ray_data.ray_org, org);
+ f3_set(ray_data.ray_dir, dir);
+ f2_set(ray_data.ray_range, range);
CHK(s3d_scene_view_trace_ray
- (scnview, org, dir, range, (void*)(uintptr_t)0xDEADBEEF, &hit) == RES_OK);
+ (scnview, org, dir, range, &ray_data, &hit) == RES_OK);
if(S3D_HIT_NONE(&hit)) {
((uint8_t*)img.pixels)[ipix+0] = 0;
diff --git a/src/test_s3d_trace_ray_instance.c b/src/test_s3d_trace_ray_instance.c
@@ -56,11 +56,13 @@ struct ray {
};
static int
-filter(const struct s3d_hit* hit,
- const float ray_org[3],
- const float ray_dir[3],
- void* ray_data,
- void* filter_data)
+filter
+ (const struct s3d_hit* hit,
+ const float ray_org[3],
+ const float ray_dir[3],
+ const float ray_range[2],
+ void* ray_data,
+ void* filter_data)
{
struct ray* ray = ray_data;
@@ -68,6 +70,7 @@ filter(const struct s3d_hit* hit,
CHK(ray_org != NULL);
CHK(ray_dir != NULL);
CHK(ray_data != NULL);
+ CHK(ray_range != NULL);
CHK(filter_data == NULL);
CHK(f3_eq(ray_org, ray->org) == 1);
CHK(f3_eq(ray_dir, ray->dir) == 1);