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:
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])