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 ed4bbacca6aeb3c63ea9319ec4131057dd6a6fee
parent c5bb097def8871fa821647a8d2e5e8e6005f3d06
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 15 Jul 2015 17:57:45 +0200

Add public geometry identifiers to the primitive structure

The application can use these ids to map from the Star-3D geometry to
its own geometry representation. Note that the geometry and instance
indentifiers cover a compact range of values. A simple sequential array
indexed by these identifiers can thus be used to perform the mapping
from the s3d geometry to the application one.

Diffstat:
Mcmake/CMakeLists.txt | 4++--
Msrc/s3d.h | 24++++++++++++++++++++++--
Msrc/s3d_device.c | 2++
Msrc/s3d_device_c.h | 8++++++++
Msrc/s3d_instance.h | 3+++
Msrc/s3d_mesh.h | 3++-
Msrc/s3d_primitive.c | 6++++--
Msrc/s3d_sampler.c | 12++++++++++--
Msrc/s3d_scene.c | 10++++++++--
Msrc/s3d_shape.c | 11++++++++++-
Msrc/s3d_shape_c.h | 1+
Msrc/test_s3d_sampler.c | 15+++++++++++++++
Msrc/test_s3d_scene.c | 7+++++++
Msrc/test_s3d_shape.c | 7+++++++
Msrc/test_s3d_trace_ray.c | 41++++++++++++++++++++++++++++++++++++-----
15 files changed, 137 insertions(+), 17 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -44,7 +44,7 @@ set(Embree_DIR ${_current_source_dir}/) find_package(Embree REQUIRED) find_package(RCMake 0.2 REQUIRED) -find_package(RSys 0.2 REQUIRED) +find_package(RSys 0.2.1 REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) include(rcmake_runtime) @@ -57,7 +57,7 @@ rcmake_append_runtime_dirs(_runtime_dirs RSys Embree) # Configure and define targets ################################################################################ set(VERSION_MAJOR 0) -set(VERSION_MINOR 1) +set(VERSION_MINOR 2) set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) diff --git a/src/s3d.h b/src/s3d.h @@ -58,6 +58,8 @@ * functor to S3D_KEEP means that this vertex data will not be updated */ #define S3D_KEEP NULL +#define S3D_INVALID_ID ((unsigned)-1) /* Value of an invalid identifer */ + enum s3d_rays_flag { S3D_RAYS_SINGLE_ORIGIN = BIT(0), /* The rays have the same origin */ S3D_RAYS_SINGLE_DIRECTION = BIT(1), /* The rays have the same direction */ @@ -89,11 +91,16 @@ enum s3d_transform_space { S3D_WORLD_TRANSFORM /* The transformation is expressed in world space */ }; +/* Primitive descriptor. The <geom|inst> indentifiers cover a compact ranges of + * value. They can be used in conjunction with a dynamic array to map from s3d + * geometry to application geometry */ struct s3d_primitive { + unsigned prim_id; /* Primitive identifer */ + unsigned geom_id; /* Geometry identifier */ + unsigned inst_id; /* Instance identifier */ /* Internal data. Should not be accessed */ void* mesh__; void* inst__; - unsigned iprim__; }; /* Untyped vertex attribute */ @@ -131,7 +138,12 @@ 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, (unsigned)-1}, {0.f,0.f,0.f}, {0.f,0.f}, FLT_MAX}; +{ + { S3D_INVALID_ID, S3D_INVALID_ID, S3D_INVALID_ID, NULL, NULL }, + { 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 */ @@ -287,6 +299,14 @@ S3D_API res_T s3d_shape_ref_put (struct s3d_shape* shape); +/* Retrieve the id of the shape. This id covers a compact range of value. + * Consequently, it can be used to map from the s3d shapes to the geometry + * representation of the caller with a simple dynamic array */ +S3D_API res_T +s3d_shape_get_id + (struct s3d_shape* shape, + unsigned* id); + /* Enable/disable the shape, i.e. it cannot be hit when its associated scene is * ray-traced or sampled */ S3D_API res_T diff --git a/src/s3d_device.c b/src/s3d_device.c @@ -51,6 +51,7 @@ device_release(ref_T* ref) ASSERT(ref); dev = CONTAINER_OF(ref, struct s3d_device, ref); MEM_RM(dev->allocator, dev); + flist_name_release(&dev->names); rtcExit(); ATOMIC_SET(&g_EmbreeIsInitialized, 0); } @@ -87,6 +88,7 @@ s3d_device_create dev->logger = logger ? logger : LOGGER_DEFAULT; dev->allocator = allocator; dev->verbose = verbose; + flist_name_init(allocator, &dev->names); ref_init(&dev->ref); rtcInit(verbose ? "verbose=1" : NULL); g_EmbreeIsInitialized = 1; diff --git a/src/s3d_device_c.h b/src/s3d_device_c.h @@ -34,11 +34,19 @@ #define S3D_DEVICE_C_H #include <rsys/ref_count.h> +#include <rsys/free_list.h> + +struct name { FITEM; }; +#define FITEM_TYPE name +#include <rsys/free_list.h> struct s3d_device { int verbose; struct logger* logger; struct mem_allocator* allocator; + + struct flist_name names; /* List of shape id */ + ref_T ref; }; diff --git a/src/s3d_instance.h b/src/s3d_instance.h @@ -40,8 +40,11 @@ struct instance { float transform[12]; /* local to world 3x4 column major matrix */ char update_transform; char flip_surface; + struct geometry geom; + unsigned id; /* Unique identifier of an instance */ + struct s3d_scene* scene; ref_T ref; }; diff --git a/src/s3d_mesh.h b/src/s3d_mesh.h @@ -66,9 +66,10 @@ struct mesh { /* Triangular mesh */ int update_mask; /* Combination of buffer_type */ struct geometry geom; - char flip_surface; + unsigned id; /* Unique identifier of a mesh */ + struct s3d_device* dev; ref_T ref; }; diff --git a/src/s3d_primitive.c b/src/s3d_primitive.c @@ -67,6 +67,7 @@ s3d_primitive_get_attrib flip_surface = mesh->flip_surface; } else { const struct instance* inst = (const struct instance*)prim->inst__; + ASSERT(prim->inst_id == inst->id); mesh = (struct mesh*)prim->mesh__; transform = inst->transform; if(!mesh) { @@ -75,6 +76,7 @@ s3d_primitive_get_attrib } flip_surface = inst->flip_surface ^ mesh->flip_surface; } + ASSERT(prim->geom_id == mesh->id); /* The mesh haven't the required mesh attrib */ if(usage != S3D_GEOMETRY_NORMAL && !mesh->attribs[usage]) { @@ -83,11 +85,11 @@ s3d_primitive_get_attrib } /* Out of bound primitive index */ - if(prim->iprim__ >= mesh_get_ntris(mesh)) { + if(prim->prim_id >= mesh_get_ntris(mesh)) { res = RES_BAD_ARG; goto error; } - ids = mesh_get_ids(mesh) + prim->iprim__ * 3/*#ids per triangle*/; + ids = mesh_get_ids(mesh) + prim->prim_id * 3/*#ids per triangle*/; attrib->usage = usage; if(usage == S3D_POSITION || usage == S3D_GEOMETRY_NORMAL) { diff --git a/src/s3d_sampler.c b/src/s3d_sampler.c @@ -55,7 +55,7 @@ struct s3d_sampler { /* Register the shape instance data. If the shape is not a SHAPE_INSTANCE, * the cached_instance is NULL. The cached instance data are synchronised on - * s3d_sampler_begin_invocation by copying the shape instance data to the + * s3d_sampler_begin invocation by copying the shape instance data to the * cache instance. This makes the sampling robust to the updates of shape * instance data until the s3d_sampler_end_sampling invocation */ struct instance* cached_instance; @@ -308,6 +308,9 @@ sampler_cache_instance(struct s3d_sampler* sampler, char* upd_geom) goto error; } + /* Setup the Id of the cached instance */ + sampler->cached_instance->id = sampler->shape->name.index; + f33_set /* Cache the instance rotation */ (sampler->cached_instance->transform, sampler->shape->data.instance->transform); @@ -340,6 +343,7 @@ sampler_cache_instance(struct s3d_sampler* sampler, char* upd_geom) res = darray_mesh_push_back(&sampler->cached_meshes, &mesh); if(res != RES_OK) goto error; } + mesh->id = shape->name.index; /* Setup the Id of the cached mesh */ /* Cache the instance mesh data */ *upd_geom = cache_mesh(mesh, shape->data.mesh) || *upd_geom; ++ishape; @@ -557,7 +561,11 @@ s3d_sampler_get /* Setup the sampled primitive */ primitive->mesh__ = mesh; primitive->inst__ = sampler->cached_instance; - primitive->iprim__ = (unsigned)(cdf_found - cdf_start); + primitive->prim_id = (unsigned)(cdf_found - cdf_start); + primitive->geom_id = mesh->id; + primitive->inst_id = sampler->cached_instance + ? sampler->cached_instance->id + : S3D_INVALID_ID; /* Compute the sampled barycentric coordinate of the sampled primitive */ sqrt_v = sqrt(v); diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -169,6 +169,7 @@ scene_setup_shape_mesh if(res != RES_OK) goto error; res = htable_mesh_set(&scn->cached_meshes, &shape, &mesh); if(res != RES_OK) goto error; + mesh->id = shape->name.index; } /* Discard the shape mesh that is not geometrically valid */ @@ -275,6 +276,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) if(res != RES_OK) goto error; res = htable_inst_set(&scn->cached_instances, &shape, &inst); if(res != RES_OK) goto error; + inst->id = shape->name.index; } /* Update the cached instance states */ ASSERT(inst->scene == shape->data.instance->scene); @@ -654,7 +656,9 @@ s3d_scene_trace_ray ASSERT((unsigned)ray.geomID < darray_mesh_size_get(&scn->meshes)); hit->prim.mesh__ = darray_mesh_data_get(&scn->meshes)[ray.geomID]; hit->prim.inst__ = NULL; - hit->prim.iprim__ = ray.primID; + hit->prim.prim_id = ray.primID; + hit->prim.geom_id = ((struct mesh*)hit->prim.mesh__)->id; + hit->prim.inst_id = S3D_INVALID_ID; } else { /* The hit shape is instantiated */ /* Retrieve the hit instance */ @@ -663,7 +667,9 @@ s3d_scene_trace_ray instance = darray_inst_data_get(&scn->instances)[ray.instID]; hit->prim.mesh__ = scene_get_mesh(instance->scene, ray.geomID); hit->prim.inst__ = instance; - hit->prim.iprim__ = ray.primID; + hit->prim.prim_id = ray.primID; + hit->prim.geom_id = ((struct mesh*)hit->prim.mesh__)->id; + hit->prim.inst_id = instance->id; flip_surface = instance->flip_surface; } ASSERT(hit->prim.mesh__); diff --git a/src/s3d_shape.c b/src/s3d_shape.c @@ -71,6 +71,7 @@ shape_release(ref_T* ref) /* The shape should not be attached */ ASSERT(is_list_empty(&shape->scene_attachment)); + flist_name_del(&dev->names, shape->name); shape_release_data(shape); MEM_RM(dev->allocator, shape); S3D(device_ref_put(dev)); @@ -99,6 +100,7 @@ shape_create(struct s3d_device* dev, struct s3d_shape** out_shape) S3D(device_ref_get(dev)); shape->dev = dev; ref_init(&shape->ref); + shape->name = flist_name_add(&dev->names); exit: if(out_shape) *out_shape = shape; @@ -165,6 +167,14 @@ s3d_shape_ref_put(struct s3d_shape* shape) } res_T +s3d_shape_get_id(struct s3d_shape* shape, unsigned* id) +{ + if(!shape || !id) return RES_BAD_ARG; + *id = shape->name.index; + return RES_OK; +} + +res_T s3d_shape_enable(struct s3d_shape* shape, const char enable) { if(!shape) return RES_BAD_ARG; @@ -273,4 +283,3 @@ s3d_mesh_setup_indexed_vertices return mesh_setup_indexed_vertices (shape->data.mesh, ntris, get_indices, nverts, attribs, data); } - diff --git a/src/s3d_shape_c.h b/src/s3d_shape_c.h @@ -54,6 +54,7 @@ enum shape_type { struct s3d_shape { struct list_node scene_attachment; enum shape_type type; + struct fid name; union { struct instance* instance; diff --git a/src/test_s3d_sampler.c b/src/test_s3d_sampler.c @@ -64,6 +64,10 @@ main(int argc, char** argv) float uv[2]; size_t i; unsigned ntris, nverts; + unsigned cbox_id; + unsigned walls_id; + unsigned short_block_id; + unsigned tall_block_id; (void)argc, (void)argv; mem_init_proxy_allocator(&allocator, &mem_default_allocator); @@ -75,6 +79,11 @@ main(int argc, char** argv) CHECK(s3d_shape_create_mesh(dev, &short_block), RES_OK); CHECK(s3d_shape_create_mesh(dev, &tall_block), RES_OK); + CHECK(s3d_shape_get_id(cbox, &cbox_id), RES_OK); + CHECK(s3d_shape_get_id(walls, &walls_id), RES_OK); + CHECK(s3d_shape_get_id(short_block, &short_block_id), RES_OK); + CHECK(s3d_shape_get_id(tall_block, &tall_block_id), RES_OK); + CHECK(s3d_sampler_create(NULL, NULL), RES_BAD_ARG); CHECK(s3d_sampler_create(walls, NULL), RES_BAD_ARG); CHECK(s3d_sampler_create(NULL, &sampler), RES_BAD_ARG); @@ -185,6 +194,12 @@ main(int argc, char** argv) const float w = rand_canonic(); CHECK(s3d_sampler_get(sampler, u, v, w, &prim, uv), RES_OK); CHECK(s3d_primitive_get_attrib(&prim, S3D_POSITION, uv, &attr0), RES_OK); + + CHECK(prim.inst_id, cbox_id); + CHECK(prim.geom_id == walls_id + || prim.geom_id == tall_block_id + || prim.geom_id == short_block_id, 1); + CHECK(prim.geom_id < 10, 1); /* printf("%f %f %f\n", SPLIT3(attr0.value));*/ } CHECK(s3d_sampler_end_sampling(sampler), RES_OK); diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c @@ -42,6 +42,7 @@ main(int argc, char** argv) struct s3d_shape* shapes[4]; const size_t nshapes = sizeof(shapes)/sizeof(struct s3d_shape*); size_t i; + unsigned id; char b; (void)argc, (void)argv; @@ -78,6 +79,12 @@ main(int argc, char** argv) CHECK(s3d_scene_instantiate(NULL, shapes + 1), RES_BAD_ARG); CHECK(s3d_scene_instantiate(scn, shapes + 1), RES_OK); + CHECK(s3d_shape_get_id(NULL, NULL), RES_BAD_ARG); + CHECK(s3d_shape_get_id(shapes[1], NULL), RES_BAD_ARG); + CHECK(s3d_shape_get_id(NULL, &id), RES_BAD_ARG); + CHECK(s3d_shape_get_id(shapes[1], &id), RES_OK); + NCHECK(id, S3D_INVALID_ID); + CHECK(s3d_scene_clear(NULL), RES_BAD_ARG); CHECK(s3d_scene_clear(scn), RES_OK); CHECK(s3d_scene_clear(scn), RES_OK); diff --git a/src/test_s3d_shape.c b/src/test_s3d_shape.c @@ -46,6 +46,7 @@ main(int argc, char** argv) float pos[3]; const unsigned cbox_ntris = sizeof(cbox_walls_ids) / sizeof(unsigned[3]); const unsigned cbox_nverts = sizeof(cbox_walls) / sizeof(float[3]); + unsigned id; void* data = (void*)&cbox_walls_desc; char c; (void)argc, (void)argv; @@ -60,6 +61,12 @@ main(int argc, char** argv) CHECK(s3d_shape_create_mesh(NULL, &shape), RES_BAD_ARG); CHECK(s3d_shape_create_mesh(dev, &shape), RES_OK); + CHECK(s3d_shape_get_id(NULL, NULL), RES_BAD_ARG); + CHECK(s3d_shape_get_id(shape, NULL), RES_BAD_ARG); + CHECK(s3d_shape_get_id(NULL, &id), RES_BAD_ARG); + CHECK(s3d_shape_get_id(shape, &id), RES_OK); + NCHECK(id, S3D_INVALID_ID); + CHECK(s3d_shape_is_attached(NULL, NULL), RES_BAD_ARG); CHECK(s3d_shape_is_attached(shape, NULL), RES_BAD_ARG); CHECK(s3d_shape_is_attached(NULL, &c), RES_BAD_ARG); diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c @@ -102,6 +102,10 @@ main(int argc, char** argv) float org[3] = { 0.f, 0.f, 0.f }; float dir[3] = { 0.f, 1.f, 0.f }; float range[2] = { 0.f, FLT_MAX }; + unsigned inst_id; + unsigned walls_id; + unsigned tall_block_id; + unsigned short_block_id; mem_init_proxy_allocator(&allocator, &mem_default_allocator); @@ -175,6 +179,7 @@ main(int argc, char** argv) desc.vertices = cbox_short_block; desc.indices = cbox_block_ids; CHECK(s3d_shape_create_mesh(dev, &tall_block), RES_OK); + CHECK(s3d_shape_get_id(tall_block, &tall_block_id), RES_OK); CHECK(s3d_mesh_setup_indexed_vertices (tall_block, ntris, cbox_get_ids, nverts, attribs, &desc), RES_OK); CHECK(s3d_scene_attach_shape(scn, tall_block), RES_OK); @@ -187,6 +192,7 @@ main(int argc, char** argv) /* Create a the CBox short block inst */ desc.vertices = cbox_short_block; CHECK(s3d_shape_create_mesh(dev, &short_block), RES_OK); + CHECK(s3d_shape_get_id(short_block, &short_block_id), RES_OK); CHECK(s3d_mesh_setup_indexed_vertices (short_block, ntris, cbox_get_ids, nverts, attribs, &desc), RES_OK); CHECK(s3d_scene_attach_shape(scn, short_block), RES_OK); @@ -197,14 +203,21 @@ main(int argc, char** argv) nverts = sizeof(cbox_walls)/sizeof(float[3]); ntris = sizeof(cbox_walls_ids)/sizeof(unsigned[3]); CHECK(s3d_shape_create_mesh(dev, &walls), RES_OK); + CHECK(s3d_shape_get_id(walls, &walls_id), RES_OK); CHECK(s3d_mesh_setup_indexed_vertices (walls, ntris, cbox_get_ids, nverts, attribs, &desc), RES_OK); CHECK(s3d_scene_attach_shape(scn, walls), RES_OK); + /* Check that the ids are all different */ + NCHECK(walls_id, short_block_id); + NCHECK(walls_id, tall_block_id); + NCHECK(short_block_id, tall_block_id); + /* Instantiate the whole CBox */ CHECK(s3d_scene_create(dev, &scn2), RES_OK); f3(org, -100.f, 0.f, -2.f); CHECK(s3d_scene_instantiate(scn, &inst), RES_OK); + CHECK(s3d_shape_get_id(inst, &inst_id), RES_OK); CHECK(s3d_scene_attach_shape(scn2, inst), RES_OK); CHECK(s3d_instance_set_position(inst, org), RES_OK); @@ -230,6 +243,7 @@ main(int argc, char** argv) CHECK(s3d_scene_attach_shape(scn, short_block), RES_OK); CHECK(s3d_scene_attach_shape(scn, tall_block), RES_OK); + CHECK(s3d_scene_begin_trace(scn2), RES_OK); camera_init(&cam); @@ -249,10 +263,16 @@ main(int argc, char** argv) img[ipix+0] = img[ipix+1] = img[ipix+2] = 0; } } else { - float N[3], len, w; + float N[3], len, dot, col[3] = { 1.f, 1.f, 1.f }; struct s3d_attrib attr; float pos[3]; + CHECK(hit.prim.inst_id, inst_id); + CHECK(hit.prim.geom_id == walls_id + || hit.prim.geom_id == tall_block_id + || hit.prim.geom_id == short_block_id, 1); + CHECK(hit.prim.geom_id < 10, 1); + CHECK(s3d_primitive_get_attrib (&hit.prim, S3D_POSITION, hit.uv, &attr), RES_OK); CHECK(attr.type, S3D_FLOAT3); @@ -274,10 +294,21 @@ main(int argc, char** argv) if(!img) continue; - w = CLAMP(1.f - hit.uv[0] - hit.uv[1], 0.f, 1.f); - img[ipix+0] = (unsigned char)(hit.uv[0] * 255.f); - img[ipix+1] = (unsigned char)(hit.uv[1] * 255.f); - img[ipix+2] = (unsigned char)(w * 255.f); + if(hit.prim.geom_id == walls_id) { + if(hit.prim.prim_id == 4 || hit.prim.prim_id == 5) { + col[0] = 1.f, col[1] = 0.f, col[2] = 0.f; + } else if(hit.prim.prim_id == 6 || hit.prim.prim_id == 7) { + col[0] = 0.f, col[1] = 1.f, col[2] = 0.f; + } + } + + dot = f3_dot(N, dir); + if(dot < 0.f) + dot = f3_dot(f3_minus(N, N), dir); + + img[ipix+0] = (unsigned char)(dot * col[0] * 255.f); + img[ipix+1] = (unsigned char)(dot * col[1] * 255.f); + img[ipix+2] = (unsigned char)(dot * col[2] * 255.f); } } }