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 7b7d005583773071edb3a1b58d8fb572a0e77db0
parent 3aecf0499972bd03c9f3ba2becde012eb669049e
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 25 Mar 2015 18:19:34 +0100

Test the s3d_primitive_get_attrib function

Ensure that the hit uv parameter map to the first and second triangle
vertices, respectively. Fix the geometry normal computation to
ensure that for a given triangle, its direction is the same as its hit
geometry normal.

Diffstat:
Mcmake/CMakeLists.txt | 4++++
Msrc/s3d.h | 2+-
Msrc/s3d_primitive.c | 6+++---
Msrc/s3d_scene.c | 26++++++++++++++++++++++----
Msrc/test_s3d_trace_ray.c | 37++++++++++++++++++++++++++++++-------
5 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -49,6 +49,10 @@ find_package(RSys 0.1.1 REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) +if(CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") +endif() + include_directories(${Embree_INCLUDE_DIR} ${RSys_INCLUDE_DIR}) ################################################################################ diff --git a/src/s3d.h b/src/s3d.h @@ -276,7 +276,7 @@ s3d_shape_sample * coordinates `uv' */ S3D_API res_T s3d_primitive_get_attrib - (struct s3d_primitive* prim, + (const struct s3d_primitive* prim, const enum s3d_attrib_usage attr, /* Attribute to retrieve */ const float uv[2], /* Barycentric coordinates of `attr' on `iprim' */ struct s3d_attrib* attrib); /* Resulting attrib */ diff --git a/src/s3d_primitive.c b/src/s3d_primitive.c @@ -44,7 +44,6 @@ res_T s3d_primitive_get_attrib (const struct s3d_primitive* prim, const enum s3d_attrib_usage usage, - const unsigned iprim[2], const float uv[2], struct s3d_attrib* attrib) { @@ -59,13 +58,14 @@ s3d_primitive_get_attrib /* 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)) + if(uv[0] < 0.f || uv[1] < 0.f || w < 0.f || w > 1.f) return RES_BAD_ARG; if(prim->igeom__ == RTC_INVALID_GEOMETRY_ID) { mesh = (struct mesh*)prim->ptr__; } else { const struct instance* inst = (const struct instance*)prim->ptr__; + transform = inst->transform; mesh = scene_get_mesh(inst->scene, prim->igeom__); if(!mesh) { res = RES_BAD_ARG; @@ -98,7 +98,7 @@ s3d_primitive_get_attrib v2 = pos + ids[2] * 3; 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)); + f3_cross(attrib->value, f3_sub(e0, v2, v0), f3_sub(e1, v1, v0)); if(transform) { /* Transform the normal from local to world space */ float transform_invtrans[9]; f33_invtrans(transform_invtrans, transform); diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -244,7 +244,10 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) res = htable_inst_set(&scn->instances, &shape, &inst); if(res != RES_OK) goto error; - S3D(scene_ref_get(shape->data.instance.scene)); /* Not necessary but ... */ + /* It is not necessary to get a reference onto the instantiated scene since + * the scene get a reference onto its shape. Anyway it is actually more + * consistent */ + S3D(scene_ref_get(shape->data.instance.scene)); inst->scene = shape->data.instance.scene; } ASSERT(inst->scene == shape->data.instance.scene); @@ -378,7 +381,7 @@ s3d_scene_create(struct s3d_device* dev, struct s3d_scene** out_scn) S3D(device_ref_get(dev)); scn->dev = dev; scn->rtc_scn = rtcNewScene - (RTC_SCENE_DYNAMIC | RTC_SCENE_INCOHERENT, + (RTC_SCENE_DYNAMIC | RTC_SCENE_INCOHERENT | RTC_SCENE_ROBUST, RTC_INTERSECT1 | RTC_INTERSECT4); if(!scn->rtc_scn) { res = RES_MEM_ERR; @@ -551,10 +554,25 @@ s3d_scene_trace_ray if((unsigned)ray.geomID == RTC_INVALID_GEOMETRY_ID) { /* No hit */ *hit = S3D_HIT_NULL; } else { + float w; f3_set(hit->normal, ray.Ng); + hit->distance = ray.tfar; + hit->uv[0] = ray.u; hit->uv[1] = ray.v; - hit->distance = ray.tfar; + w = 1.f - hit->uv[0] - hit->uv[1]; + ASSERT(w <= 1.f); /* This may not occurs */ + if(w < 0.f) { /* Handle precision error */ + if(hit->uv[0] > hit->uv[1]) hit->uv[0] += w; + else hit->uv[1] += w; + w = 0.f; + } + /* Embree stores on the u and v parameters the barycentric coordinate of + * the hit intersection with respect to the second and third triangle + * vertices, respectively. The following code maps the u and v coordinate + * to the first and second triangle vertices */ + hit->uv[1] = hit->uv[0]; + hit->uv[0] = w; if((unsigned)ray.instID == RTC_INVALID_GEOMETRY_ID) { ASSERT((unsigned)ray.geomID < darray_geom2mesh_size_get(&scn->geom2mesh)); @@ -564,7 +582,7 @@ s3d_scene_trace_ray } else { /* The hit shape is instantiated */ /* Retrieve the hit instance */ ASSERT((unsigned)ray.instID < darray_geom2inst_size_get(&scn->geom2inst)); - hit->prim.ptr__ = darray_geom2inst_data_get(&scn->geom2inst); + hit->prim.ptr__ = darray_geom2inst_data_get(&scn->geom2inst)[ray.instID]; hit->prim.igeom__ = ray.geomID; hit->prim.iprim__ = ray.primID; } diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c @@ -159,25 +159,25 @@ main(int argc, char** argv) CHECK(s3d_scene_create(dev, &scn2), RES_OK); - f3(org, -555.f, 0.f, -551.f); + f3(org, -560.f, 0.f, -556.f); CHECK(s3d_shape_ref_put(shape), RES_OK); CHECK(s3d_scene_instantiate(scn, &shape), RES_OK); CHECK(s3d_scene_attach_shape(scn2, shape), RES_OK); CHECK(s3d_instance_set_position(shape, org), RES_OK); - f3(org, 3.f, 0.f, -551.f); + f3(org, 7.f, 0.f, -556.f); CHECK(s3d_shape_ref_put(shape), RES_OK); CHECK(s3d_scene_instantiate(scn, &shape), RES_OK); CHECK(s3d_scene_attach_shape(scn2, shape), RES_OK); CHECK(s3d_instance_set_position(shape, org), RES_OK); - f3(org, -555.f, 0.f, 3.f); + f3(org, -560.f, 0.f, 7.f); CHECK(s3d_shape_ref_put(shape), RES_OK); CHECK(s3d_scene_instantiate(scn, &shape), RES_OK); CHECK(s3d_scene_attach_shape(scn2, shape), RES_OK); CHECK(s3d_instance_set_position(shape, org), RES_OK); - f3(org, 3.f, 0.f, 3.f); + f3(org, 7.f, 0.f, 7.f); CHECK(s3d_shape_ref_put(shape), RES_OK); CHECK(s3d_scene_instantiate(scn, &shape), RES_OK); CHECK(s3d_scene_attach_shape(scn2, shape), RES_OK); @@ -196,16 +196,38 @@ main(int argc, char** argv) pixel[0] = (float)ix/(float)IMG_WIDTH; camera_ray(&cam, pixel, org, dir); CHECK(s3d_scene_trace_ray(scn2, org, dir, range, &hit), RES_OK); - if(!img) - continue; if(S3D_HIT_NONE(&hit)) { - img[ipix+0] = img[ipix+1] = img[ipix+2] = 0; + if(img) { + img[ipix+0] = img[ipix+1] = img[ipix+2] = 0; + } } else { float wi[3], N[3], cos_theta, len; unsigned char color; + struct s3d_attrib attr; + float pos[3]; + + CHECK(s3d_primitive_get_attrib + (&hit.prim, S3D_POSITION, hit.uv, &attr), RES_OK); + CHECK(attr.type, S3D_FLOAT3); + CHECK(attr.usage, S3D_POSITION); + f3_add(pos, f3_mulf(pos, dir, hit.distance), org); + CHECK(f3_eq_eps + (pos, attr.value, 1.e-2f/*Sic O_o!! Really bad precision!*/), 1); + len = f3_normalize(N, hit.normal); NCHECK(len, 0); + + CHECK(s3d_primitive_get_attrib + (&hit.prim, S3D_GEOMETRY_NORMAL, hit.uv, &attr), RES_OK); + CHECK(attr.type, S3D_FLOAT3); + CHECK(attr.usage, S3D_GEOMETRY_NORMAL); + f3_normalize(attr.value, attr.value); + CHECK(f3_eq_eps(attr.value, N, 1.e-6f), 1); + + if(!img) + continue; + cos_theta = f3_dot(f3_minus(wi, dir), N); color = (unsigned char)(cos_theta * 255.f); img[ipix+0] = color; @@ -232,3 +254,4 @@ main(int argc, char** argv) return 0; } +