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:
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);
}
}
}