star-3d

Surface structuring for efficient 3D geometric queries
git clone git://git.meso-star.fr/star-3d.git
Log | Files | Refs | README | LICENSE

commit 4be9372fc60560c4474e17b91f165d96186a62e3
parent cf4f816ae2023f193c4adec925ff10b419024e23
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 23 Mar 2015 13:39:46 +0100

Change the API of a sampled/ray-traced primitive indentifier

Take into account the instance transformation in the
s3d_shape_get_attrib function

Diffstat:
Msrc/s3d.h | 11+++++------
Msrc/s3d_scene.c | 65++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/s3d_scene_c.h | 6++++++
Msrc/s3d_shape.c | 42+++++++++++++++++++++++++++++++++++-------
Msrc/s3d_shape_c.h | 6++++++
5 files changed, 90 insertions(+), 40 deletions(-)

diff --git a/src/s3d.h b/src/s3d.h @@ -110,8 +110,7 @@ static const struct s3d_vertex_data S3D_VERTEX_DATA_NULL = /* Intersection point */ struct s3d_hit { struct s3d_shape* shape; /* Hit shape */ - struct s3d_scene* scene; /* Hit scene */ - unsigned iprim; /* Index of the intersected primitive */ + unsigned iprim[2]; /* Indentifiers of the intersected primitive */ float normal[3]; /* Unormalized geometry normal */ float uv[2]; /* Barycentric coordinates of the hit onto `iprim' */ float distance; /* Hit distance from the ray origin */ @@ -119,7 +118,7 @@ struct s3d_hit { /* Constant defining a NULL intersection. Should be used to initialize a hit */ static const struct s3d_hit S3D_HIT_NULL = -{NULL, NULL, 0, {0.f,0.f,0.f}, {0.f,0.f}, FLT_MAX}; +{NULL, {(unsigned)-1, (unsigned)-1}, {0.f,0.f,0.f}, {0.f,0.f}, FLT_MAX}; /* Helper macro that defines whether or not the hit is valid, i.e. the ray * intersects a shape or not */ @@ -264,16 +263,16 @@ s3d_shape_sample (struct s3d_shape* shape, /* Uniform random variables in [0, 1) */ const float u, const float v, const float w, - unsigned* iprim, /* Sampled primitive */ + unsigned iprim[2], /* Sampled primitive */ float uv[2]); /* Sampled barycentric coordinate onto `iprim' */ /* Retrieve the attribute of the shape prim `iprim' at the barycentric * coordinates `uv' */ S3D_API res_T -s3d_mesh_get_attrib +s3d_shape_get_attrib (struct s3d_shape* shape, const enum s3d_attrib_usage attr, /* Attribute to retrieve */ - const unsigned iprim, /* Id of the primitive on which `attr' is retrieved */ + const unsigned iprim[2], /* Id of the primitive on which `attr' is retrieved */ const float uv[2], /* Barycentric coordinates of `attr' on `iprim' */ struct s3d_attrib* attrib); /* Resulting attrib */ diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -223,6 +223,36 @@ scene_release(ref_T* ref) } /******************************************************************************* + * Local function + ******************************************************************************/ +struct s3d_shape* +scene_shape_from_rtc_geom(struct s3d_scene* scn, const unsigned igeom) +{ + struct s3d_shape* shape = NULL; + res_T res = RES_OK; + ASSERT(scn); + + mutex_lock(scn->lock); + if(darray_geom2shape_size_get(&scn->geom2shape) <= igeom) + goto error; + shape = darray_geom2shape_data_get(&scn->geom2shape)[igeom]; +error: + mutex_unlock(scn->lock); + return shape; +exit: + goto error; +} + +void +scene_remove_shape(struct s3d_scene* scn, struct s3d_shape* shape) +{ + ASSERT(scn); + mutex_lock(scn->lock); + scene_remove_shape_unsafe(scn, shape); + mutex_unlock(scn->lock); +} + +/******************************************************************************* * Exported s3d_scene functions ******************************************************************************/ res_T @@ -425,7 +455,6 @@ s3d_scene_trace_ray /* Prevent concurrent modifications on the Embree scene */ mutex_rw_rlock(scn->lock_rtc); rtcIntersect(scn->rtc_scn, ray); - mutex_rw_unlock(scn->lock_rtc); if((unsigned)ray.geomID == RTC_INVALID_GEOMETRY_ID) { *hit = S3D_HIT_NULL; @@ -434,47 +463,29 @@ s3d_scene_trace_ray hit->uv[0] = ray.u; hit->uv[1] = ray.v; hit->distance = ray.tfar; - hit->iprim = ray.primID; + hit->iprim[TRIANGLE_ID] = ray.primID; if((unsigned)ray.instID == RTC_INVALID_GEOMETRY_ID) { ASSERT((unsigned)ray.geomID < darray_geom2shape_size_get(&scn->geom2shape)); - hit->shape = darray_geom2shape_data_get - (&scn->geom2shape)[ray.geomID]; + hit->shape = darray_geom2shape_data_get(&scn->geom2shape)[ray.geomID]; ASSERT(hit->shape != NULL && (unsigned)ray.geomID == hit->shape->rtc_geom); ASSERT(hit->shape->type == SHAPE_MESH); - hit->scene = scn; + hit->iprim[GEOMETRY_ID] = RTC_INVALID_GEOMETRY_ID; } else { /* The hit shape is instantiated */ /* Retrieve the hit instance */ ASSERT((unsigned)ray.instID < darray_geom2shape_size_get(&scn->geom2shape)); - hit->shape = darray_geom2shape_data_get - (&scn->geom2shape)[ray.instID]; - ASSERT(hit->shape != NULL && (unsigned)ray.instID == hit->shape->rtc_geom); + hit->shape = darray_geom2shape_data_get(&scn->geom2shape)[ray.instID]; ASSERT(hit->shape->type == SHAPE_INSTANCE); - hit->scene = hit->shape->data.instance.scene; - - /* Retrieve the hit geometry into the instance */ + ASSERT(hit->shape != NULL && (unsigned)ray.instID == hit->shape->rtc_geom); ASSERT((unsigned)ray.geomID - < darray_geom2shape_size_get(&hit->scene->geom2shape)); - hit->shape = darray_geom2shape_data_get - (&hit->scene->geom2shape)[ray.geomID]; - ASSERT(hit->shape != NULL && (unsigned)ray.geomID == hit->shape->rtc_geom); - ASSERT(hit->shape->type == SHAPE_MESH); + < darray_geom2shape_size_get(&hit->shape->data.instance.scene->geom2shape)); + hit->iprim[GEOMETRY_ID] = ray.geomID; } } + mutex_rw_unlock(scn->lock_rtc); return RES_OK; } -/******************************************************************************* - * Local function - ******************************************************************************/ -void -scene_remove_shape(struct s3d_scene* scn, struct s3d_shape* shape) -{ - ASSERT(scn); - mutex_lock(scn->lock); - scene_remove_shape_unsafe(scn, shape); - mutex_unlock(scn->lock); -} diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h @@ -56,6 +56,12 @@ struct s3d_scene { ref_T ref; }; +/* Return NULL if `rtc_geom' is not registered into `scn' */ +extern LOCAL_SYM struct s3d_shape* +scene_shape_from_rtc_geom + (struct s3d_scene* scn, + const unsigned rtc_geom); + extern LOCAL_SYM void scene_remove_shape (struct s3d_scene* scn, diff --git a/src/s3d_shape.c b/src/s3d_shape.c @@ -381,20 +381,20 @@ res_T s3d_shape_get_attrib (const struct s3d_shape* shape, const enum s3d_attrib_usage usage, - const unsigned iprim, + const unsigned iprim[2], const float uv[2], struct s3d_attrib* attrib) { const uint32_t* ids; + unsigned itri; + const struct s3d_shape* mesh = NULL; + const float* transform = NULL; float w; res_T res = RES_OK; if(!shape || !usage == S3D_ATTRIBS_COUNT__ || !uv || !attrib) return RES_BAD_ARG; - /* Unsupported mesh type */ - if(shape->type != SHAPE_MESH) - return RES_BAD_ARG; /* Unormalized barycentric coordinates */ w = 1.f - uv[0] - uv[1]; if(uv[0] < 0.f || uv[1] < 0.f || !eq_eps(w, 1.f, 1.e-6f)) @@ -402,6 +402,25 @@ s3d_shape_get_attrib mutex_rw_rlock(shape->lock); + switch(shape->type) { + case SHAPE_INSTANCE: + mesh = scene_shape_from_rtc_geom + (shape->data.instance.scene, iprim[GEOMETRY_ID]); + if(!mesh) { + res = RES_BAD_ARG; + goto error; + } + ASSERT(mesh->type == SHAPE_MESH); + transform = shape->data.instance.transform; + break; + case SHAPE_MESH: + mesh = shape; + break; + default: /* Unsupported primitive type */ + res = RES_BAD_ARG; + goto error; + } + /* The mesh haven't the required mesh attrib */ if(usage != S3D_GEOMETRY_NORMAL && !darray_float_size_get(shape->data.mesh.attribs + usage)) { @@ -409,15 +428,15 @@ s3d_shape_get_attrib goto error; } /* Out of bound primitive index */ - if(iprim >= darray_u32_size_get(&shape->data.mesh.indices) / 3/*# prim ids*/) { + itri = iprim[TRIANGLE_ID]; + if(itri >= darray_u32_size_get(&shape->data.mesh.indices) / 3/*# prim ids*/) { res = RES_BAD_ARG; goto error; } - ids = darray_u32_cdata_get(&shape->data.mesh.indices) + iprim * 3; + ids = darray_u32_cdata_get(&shape->data.mesh.indices) + itri * 3; attrib->usage = usage; if(usage == S3D_POSITION || usage == S3D_GEOMETRY_NORMAL) { - /* TODO take into account the instance transformation */ const float* v0, *v1, *v2; const float* pos; attrib->type = S3D_FLOAT3; @@ -429,11 +448,20 @@ s3d_shape_get_attrib if(usage == S3D_GEOMETRY_NORMAL) { /* Compute the geometry normal */ float e0[3], e1[3]; f3_cross(attrib->value, f3_sub(e0, v1, v0), f3_sub(e1, v2, v0)); + if(transform) { /* Transform the normal from local to world space */ + float transform_invtrans[9]; + f33_invtrans(transform_invtrans, transform); + f33_mulf3(attrib->value, transform_invtrans, attrib->value); + } } else { /* Interpolate the vertex position */ float tmp[3]; f3_mulf(attrib->value, v0, uv[0]); f3_add(attrib->value, attrib->value, f3_mulf(tmp, v1, uv[1])); f3_add(attrib->value, attrib->value, f3_mulf(tmp, v2, w)); + if(transform) { /* Transform the position from local to world space */ + f33_mulf3(attrib->value, transform, attrib->value); /* Rotation */ + f3_add(attrib->value, attrib->value, transform + 9); /* Translation */ + } } } else { const float* attr; diff --git a/src/s3d_shape_c.h b/src/s3d_shape_c.h @@ -55,6 +55,12 @@ enum shape_type { SHAPE_NONE = SHAPE_TYPES_COUNT__ }; +/* Helper constants use as synthactic sugar to index the primitive identifiers */ +enum { + GEOMETRY_ID, /* Index toward the Embree Geometry ID of the primtive */ + TRIANGLE_ID /* Index toward the Embree triangle ID of the primitive*/ +}; + struct mesh { /* Triangular mesh */ darray_u32 indices; darray_float attribs[S3D_ATTRIBS_COUNT__];