star-gs

Literate program for a geometric sensitivity calculation
git clone git://git.meso-star.fr/star-gs.git
Log | Files | Refs | README | LICENSE

commit 9b0fd6fd923b31d78a6d31dc65d1776db546de7e
parent f1b509ca2c98a7fdb8122a7f648d659fd60b6816
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 26 Apr 2021 22:06:11 +0200

Upd the profile of the sgs_geometry_trace_ray function

Diffstat:
Msrc/sgs_geometry.c | 64++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/sgs_geometry.h | 41+++++++++++++++++++++++++++++++++++++++--
2 files changed, 77 insertions(+), 28 deletions(-)

diff --git a/src/sgs_geometry.c b/src/sgs_geometry.c @@ -30,9 +30,9 @@ struct hit_filter_context { float range[2]; - struct s3d_hit hit_from; + struct sgs_s3d_position pos_from; }; -#define HIT_FILTER_CONTEXT_NULL__ {{0,FLT_MAX}, S3D_HIT_NULL__} +#define HIT_FILTER_CONTEXT_NULL__ {{0,FLT_MAX}, SGS_S3D_POSITION_NULL__} static const struct hit_filter_context HIT_FILTER_CONTEXT_NULL = HIT_FILTER_CONTEXT_NULL__; @@ -47,20 +47,20 @@ static const struct mesh MESH_NULL = {NULL, NULL, 0, 0}; /******************************************************************************* * Helper functions ******************************************************************************/ -/* Check that `hit' roughly lies on an edge. For triangular primitives, a - * simple but approximative way is to test that its position have at least one - * barycentric coordinate roughly equal to 0 or 1. */ +/* Check that the barycentric coordinates defines a position near of an edge. + * To do so test that at least one barycentric coordinate is roughly equal to 0 + * or 1. */ static FINLINE int -hit_on_edge(const struct s3d_hit* hit) +is_on_edge(const float uv[2]) { const float on_edge_eps = 1.e-4f; float w; - ASSERT(hit && !S3D_HIT_NONE(hit)); - w = 1.f - hit->uv[0] - hit->uv[1]; - return eq_epsf(hit->uv[0], 0.f, on_edge_eps) - || eq_epsf(hit->uv[0], 1.f, on_edge_eps) - || eq_epsf(hit->uv[1], 0.f, on_edge_eps) - || eq_epsf(hit->uv[1], 1.f, on_edge_eps) + ASSERT(uv); + w = 1.f - uv[0] - uv[1]; + return eq_epsf(uv[0], 0.f, on_edge_eps) + || eq_epsf(uv[0], 1.f, on_edge_eps) + || eq_epsf(uv[1], 0.f, on_edge_eps) + || eq_epsf(uv[1], 1.f, on_edge_eps) || eq_epsf(w, 0.f, on_edge_eps) || eq_epsf(w, 1.f, on_edge_eps); } @@ -73,23 +73,22 @@ self_hit const float ray_org[3], const float ray_dir[3], const float ray_range[2], - const struct s3d_hit* hit_from) + const struct sgs_s3d_position* pos_from) { - ASSERT(hit && hit_from); + ASSERT(hit && pos_from); (void)ray_org, (void)ray_dir, (void)ray_range; - /* The hit primitive is the one from which the the ray starts. Discard these - * hits */ - if(S3D_PRIMITIVE_EQ(&hit->prim, &hit_from->prim)) + /* The hit primitive is the one from which the the ray starts. Discard it */ + if(S3D_PRIMITIVE_EQ(&hit->prim, &pos_from->prim)) return 1; /* If the targeted point is near of the origin, check that it lies on an * edge/vertex shared by the 2 primitives. In such situation, we assume that * it is a self intersection and discard this hit */ - if(!S3D_HIT_NONE(hit_from) + if(!S3D_PRIMITIVE_EQ(&pos_from->prim, &S3D_PRIMITIVE_NULL) && eq_epsf(hit->distance, 0, 1.e-1f) - && hit_on_edge(hit_from) - && hit_on_edge(hit)) { + && is_on_edge(pos_from->st) + && is_on_edge(hit->uv)) { return 1; } @@ -117,7 +116,7 @@ hit_filter if(hit->distance <= ctx->range[0] || hit->distance >= ctx->range[1]) return 1; - if(self_hit(hit, ray_org, ray_dir, ctx->range, &ctx->hit_from)) + if(self_hit(hit, ray_org, ray_dir, ctx->range, &ctx->pos_from)) return 1; /* Discard this hit */ return 0; /* No filtering */ @@ -231,14 +230,15 @@ sgs_geometry_trace_ray const double ray_org[3], const double ray_dir[3], const double ray_range[2], - const struct s3d_hit* hit_from, - struct s3d_hit* hit) + const struct sgs_s3d_position* pos_from, + struct sgs_hit* out_hit) { struct hit_filter_context filter_ctx = HIT_FILTER_CONTEXT_NULL; + struct s3d_hit hit = S3D_HIT_NULL; float org[3]; float dir[3]; float range[2]; - ASSERT(geom && ray_org && ray_dir && ray_range && hit); + ASSERT(geom && ray_org && ray_dir && ray_range && out_hit); /* Convert ray data to single precision */ f3_set_d3(org, ray_org); @@ -252,10 +252,22 @@ sgs_geometry_trace_ray /* Setup the hit filter data */ filter_ctx.range[0] = range[0]; filter_ctx.range[1] = range[1]; - filter_ctx.hit_from = hit_from ? *hit_from : S3D_HIT_NULL; + filter_ctx.pos_from = pos_from ? *pos_from : SGS_S3D_POSITION_NULL; /* Trace the ray */ - S3D(scene_view_trace_ray(geom->view_rt, org, dir, range, &filter_ctx, hit)); + S3D(scene_view_trace_ray(geom->view_rt, org, dir, range, &filter_ctx, &hit)); + + /* Setup the output hit */ + *out_hit = SGS_HIT_NULL; + if(!S3D_HIT_NONE(&hit)) { + d3_set_f3(out_hit->normal, hit.normal); + d3_normalize(out_hit->normal, out_hit->normal); + out_hit->distance = hit.distance; + out_hit->surface_type = darray_int_cdata_get(&geom->tris_type)[hit.prim.prim_id]; + out_hit->s3d_pos.prim = hit.prim; + out_hit->s3d_pos.st[0] = hit.uv[0]; + out_hit->s3d_pos.st[1] = hit.uv[1]; + } } res_T diff --git a/src/sgs_geometry.h b/src/sgs_geometry.h @@ -20,6 +20,7 @@ #ifndef SGS_GEOMETRY_H #define SGS_GEOMETRY_H +#include <star/s3d.h> #include <rsys/rsys.h> enum sgs_geometry_type { @@ -114,6 +115,42 @@ struct sgs_geometry_step_args { static const struct sgs_geometry_step_args SGS_GEOMETRY_STEP_ARGS_DEFAULT = SGS_GEOMETRY_STEP_ARGS_DEFAULT__; +/* Position defined relatively to a Star-3D primitive */ +struct sgs_s3d_position { + struct s3d_primitive prim; + float st[2]; /* Parametric coordinates onto the primitive */ +}; +#define SGS_S3D_POSITION_NULL__ {S3D_PRIMITIVE_NULL__, {0,0}} +static const struct sgs_s3d_position SGS_S3D_POSITION_NULL = + SGS_S3D_POSITION_NULL__; + +/* Position onto a geometry surface */ +struct sgs_fragment { + double normal[3]; /* Normalized */ + double position[3]; + enum sgs_surface_type surface_type; + + /* Position defined wrt the corresponding Star-3D primitive */ + struct sgs_s3d_position s3d_pos; +}; +#define SGS_FRAGMENT_NULL__ {{0,0,0},{0,0,0},0,SGS_S3D_POSITION_NULL__} +static const struct sgs_fragment SGS_FRAGMENT_NULL = SGS_FRAGMENT_NULL__; + +/* Intersection along a ray */ +struct sgs_hit { + double normal[3]; /* Normalized */ + double distance; /* Distance up to the intersection */ + enum sgs_surface_type surface_type; + + /* Position defined wrt the corresponding Star-3D primitive */ + struct sgs_s3d_position s3d_pos; +}; +#define SGS_HIT_NULL__ {{0,0,0},DBL_MAX,0,SGS_S3D_POSITION_NULL__} +static const struct sgs_hit SGS_HIT_NULL = SGS_HIT_NULL__; + +/* Helper macro */ +#define SGS_HIT_NONE(Hit) ((Hit)->distance >= FLT_MAX) + /* Forward declaration */ struct s3d_hit; struct sgs; @@ -154,8 +191,8 @@ sgs_geometry_trace_ray const double ray_org[3], const double ray_dir[3], const double ray_range[2], - const struct s3d_hit* hit_from, /* May be NULL */ - struct s3d_hit* hit); + const struct sgs_s3d_position* pos_from, /* To avoid self hit. May be NULL */ + struct sgs_hit* hit); extern LOCAL_SYM res_T sgs_geometry_dump_vtk