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 3aecf0499972bd03c9f3ba2becde012eb669049e
parent f3314a3c58b2c85403b549e2dfc10631cb68d9af
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 25 Mar 2015 14:36:35 +0100

Implement the s3d_primitive_get_attrib function

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/s3d.h | 17++++++++---------
Msrc/s3d_mesh.c | 7+++++++
Msrc/s3d_mesh.h | 5+++++
Asrc/s3d_primitive.c | 139+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/s3d_scene.c | 12++++++------
Msrc/s3d_scene_c.h | 11+++++++++++
Msrc/s3d_shape.c | 109-------------------------------------------------------------------------------
8 files changed, 177 insertions(+), 124 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -63,6 +63,7 @@ set(S3D_FILES_SRC s3d_device.c s3d_instance.c s3d_mesh.c + s3d_primitive.c s3d_scene.c s3d_shape.c) set(S3D_FILES_INC diff --git a/src/s3d.h b/src/s3d.h @@ -84,10 +84,10 @@ enum s3d_transform_space { }; struct s3d_primitive { - /* Internal data */ - void* ptr; - unsigned iprim; - unsigned igeom; + /* Internal data. Should not be accessed */ + void* ptr__; + unsigned iprim__; + unsigned igeom__; }; struct s3d_attrib { @@ -118,7 +118,7 @@ static const struct s3d_vertex_data S3D_VERTEX_DATA_NULL = struct s3d_hit { struct s3d_primitive prim; /* Intersected primitive */ float normal[3]; /* Unormalized geometry normal */ - float uv[2]; /* Barycentric coordinates of the hit onto `iprim' */ + float uv[2]; /* Barycentric coordinates of the hit onto `prim' */ float distance; /* Hit distance from the ray origin */ }; @@ -133,7 +133,6 @@ static const struct s3d_hit S3D_HIT_NULL = /* Forward declaration of s3d opaque data types */ struct s3d_device; /* Entry point of the library */ struct s3d_scene; /* Collection of shapes */ -struct s3d_rt_session; /* Ray tracing session */ struct s3d_shape; /* Untyped geometry */ /* Forward declaration of external data types */ @@ -147,9 +146,6 @@ struct mem_allocator; * functions take or release a reference on the data, i.e. they increment or * decrement the reference counter, respectively. When this counter reach 0 the * object is silently destroyed and should not be used anymore. - * - * The s3d API is thread safe, i.e. the functions can be invoked concurrently - * by all threads that have a reference onto the function parameters */ BEGIN_DECLS @@ -273,6 +269,9 @@ s3d_shape_sample struct s3d_primitive* primitive, /* Sampled primitive */ float uv[2]); /* Sampled barycentric coordinate onto `primitive' */ +/******************************************************************************* + * Primitive API - Define a geometric primitive of a shape + ******************************************************************************/ /* Retrieve the attribute of the shape prim `iprim' at the barycentric * coordinates `uv' */ S3D_API res_T diff --git a/src/s3d_mesh.c b/src/s3d_mesh.c @@ -274,6 +274,13 @@ mesh_get_pos(struct mesh* mesh) return darray_float_data_get(&mesh->attribs[S3D_POSITION]->data); } +float* +mesh_get_attr(struct mesh* mesh, const enum s3d_attrib_usage usage) +{ + ASSERT(mesh && usage < S3D_ATTRIBS_COUNT__ && mesh->attribs[usage]); + return darray_float_data_get(&mesh->attribs[usage]->data); +} + res_T mesh_setup_indexed_vertices (struct mesh* mesh, diff --git a/src/s3d_mesh.h b/src/s3d_mesh.h @@ -94,6 +94,11 @@ extern LOCAL_SYM float* mesh_get_pos (struct mesh* mesh); +extern LOCAL_SYM float* +mesh_get_attr + (struct mesh* mesh, + const enum s3d_attrib_usage usage); + extern LOCAL_SYM res_T mesh_setup_indexed_vertices (struct mesh* mesh, diff --git a/src/s3d_primitive.c b/src/s3d_primitive.c @@ -0,0 +1,139 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is a computer program whose purpose is to describe a + * virtual 3D environment that can be ray-traced and sampled both robustly + * and efficiently. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#include "s3d_c.h" +#include "s3d_instance.h" +#include "s3d_mesh.h" +#include "s3d_scene_c.h" + +#include <rsys/float33.h> + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +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) +{ + const uint32_t* ids; + struct mesh* mesh = NULL; + const float* transform = NULL; + float w; + res_T res = RES_OK; + + if(!prim || !usage == S3D_ATTRIBS_COUNT__ || !uv || !attrib) + 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)) + 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__; + mesh = scene_get_mesh(inst->scene, prim->igeom__); + if(!mesh) { + res = RES_BAD_ARG; + goto error; + } + } + + /* The mesh haven't the required mesh attrib */ + if(usage != S3D_GEOMETRY_NORMAL && !mesh->attribs[usage]) { + res = RES_BAD_ARG; + goto error; + } + + /* Out of bound primitive index */ + if(prim->iprim__ >= mesh_get_ntris(mesh)) { + res = RES_BAD_ARG; + goto error; + } + ids = mesh_get_ids(mesh) + prim->iprim__ * 3/*#ids per triangle*/; + attrib->usage = usage; + + if(usage == S3D_POSITION || usage == S3D_GEOMETRY_NORMAL) { + const float* v0, *v1, *v2; + const float* pos; + attrib->type = S3D_FLOAT3; + /* Fetch data */ + pos = mesh_get_pos(mesh); + v0 = pos + ids[0] * 3; + v1 = pos + ids[1] * 3; + 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)); + 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; + const float* v0, *v1, *v2; + unsigned i, dim; + attrib->type = mesh->attribs_type[usage]; + /* Fetch attrib data */ + dim = s3d_type_get_dimension(attrib->type); + attr = mesh_get_attr(mesh, usage); + v0 = attr + ids[0] * dim; + v1 = attr + ids[1] * dim; + v2 = attr + ids[2] * dim; + /* Interpolate the vertex attribs */ + ASSERT(dim <= 4); + FOR_EACH(i, 0, dim) { + attrib->value[i] = v0[i]*uv[0] + v1[i]*uv[1] + v2[i]*w; + } + } +exit: + return res; +error: + goto exit; +} + diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -558,15 +558,15 @@ s3d_scene_trace_ray if((unsigned)ray.instID == RTC_INVALID_GEOMETRY_ID) { ASSERT((unsigned)ray.geomID < darray_geom2mesh_size_get(&scn->geom2mesh)); - hit->prim.ptr = darray_geom2mesh_data_get(&scn->geom2mesh)[ray.geomID]; - hit->prim.iprim = ray.primID; - hit->prim.igeom = RTC_INVALID_GEOMETRY_ID; + hit->prim.ptr__ = darray_geom2mesh_data_get(&scn->geom2mesh)[ray.geomID]; + hit->prim.iprim__ = ray.primID; + hit->prim.igeom__ = RTC_INVALID_GEOMETRY_ID; } 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.igeom = ray.geomID; - hit->prim.iprim = ray.primID; + hit->prim.ptr__ = darray_geom2inst_data_get(&scn->geom2inst); + hit->prim.igeom__ = ray.geomID; + hit->prim.iprim__ = ray.primID; } } return RES_OK; diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h @@ -71,5 +71,16 @@ struct s3d_scene { ref_T ref; }; +static FINLINE struct mesh* +scene_get_mesh(struct s3d_scene* scn, const unsigned igeom) +{ + struct mesh* mesh; + ASSERT(scn && igeom != RTC_INVALID_GEOMETRY_ID); + ASSERT(igeom < darray_geom2mesh_size_get(&scn->geom2mesh)); + mesh = darray_geom2mesh_data_get(&scn->geom2mesh)[igeom]; + ASSERT(mesh); + return mesh; +} + #endif /* S3D_SCENE_C_H */ diff --git a/src/s3d_shape.c b/src/s3d_shape.c @@ -168,115 +168,6 @@ s3d_shape_sample return RES_OK; } -#if 0 -res_T -s3d_shape_get_attrib - (const struct s3d_shape* shape, - const enum s3d_attrib_usage usage, - 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; - - /* 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)) - return RES_BAD_ARG; - - 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)) { - res = RES_BAD_ARG; - goto error; - } - /* Out of bound primitive index */ - 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) + itri * 3; - attrib->usage = usage; - - if(usage == S3D_POSITION || usage == S3D_GEOMETRY_NORMAL) { - const float* v0, *v1, *v2; - const float* pos; - attrib->type = S3D_FLOAT3; - /* Fetch data */ - pos = darray_float_cdata_get(shape->data.mesh.attribs + S3D_POSITION); - v0 = pos + ids[0] * 3; - v1 = pos + ids[1] * 3; - 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)); - 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; - const float* v0, *v1, *v2; - unsigned i, dim; - attrib->type = shape->data.mesh.attribs_type[usage]; - /* Fetch attrib data */ - dim = get_s3d_type_dimension(attrib->type); - attr = darray_float_cdata_get(shape->data.mesh.attribs + usage); - v0 = attr + ids[0] * dim; - v1 = attr + ids[1] * dim; - v2 = attr + ids[2] * dim; - /* Interpolate the vertex attribs */ - ASSERT(dim <= 4); - FOR_EACH(i, 0, dim) { - attrib->value[i] = v0[i]*uv[0] + v1[i]*uv[1] + v2[i]*w; - } - } -exit: - return res; -error: - goto exit; -} -#endif - res_T s3d_instance_set_position (struct s3d_shape* shape, const float position[3])