commit aa858e2ecf18ab9677ca7fd3f8f65357d3dcfbd4
parent 61ef1b92dea5c2dfcb3c3eda30d45b9d45034bfd
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 28 Jul 2016 15:23:29 +0200
Rename the whole session API in scene_view
Diffstat:
15 files changed, 2790 insertions(+), 2789 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -68,7 +68,7 @@ set(S3D_FILES_SRC
s3d_mesh.c
s3d_primitive.c
s3d_scene.c
- s3d_session.c
+ s3d_scene_view.c
s3d_shape.c)
set(S3D_FILES_INC_API s3d.h)
set(S3D_FILES_INC
@@ -79,7 +79,8 @@ set(S3D_FILES_INC
s3d_geometry.h
s3d_instance.h
s3d_mesh.h
- s3d_session_c.h
+ s3d_scene_c.h
+ s3d_scene_view_c.h
s3d_shape_c.h)
set(S3D_FILES_DOC COPYING.fr COPYING.en README.md)
@@ -141,7 +142,7 @@ if(NOT NO_TEST)
new_test(test_s3d_primitive)
new_test(test_s3d_sampler)
new_test(test_s3d_scene)
- new_test(test_s3d_session)
+ new_test(test_s3d_scene_view)
new_test(test_s3d_shape)
build_test(test_s3d_trace_ray)
diff --git a/src/s3d.h b/src/s3d.h
@@ -159,7 +159,7 @@ struct s3d_hit {
static const struct s3d_hit S3D_HIT_NULL = S3D_HIT_NULL__;
-enum s3d_session_flag {
+enum s3d_scene_view_flag {
S3D_TRACE = BIT(0),
S3D_SAMPLE = BIT(1),
S3D_GET_PRIMITIVE = BIT(2)
@@ -184,8 +184,8 @@ typedef int
/* Forward declaration of s3d opaque data types */
struct s3d_device; /* Entry point of the library */
struct s3d_scene; /* Collection of shapes */
+struct s3d_scene_view; /* Scene state */
struct s3d_shape; /* Surfacic geometry */
-struct s3d_session; /* Scene state */
/* Forward declaration of external data types */
struct logger;
@@ -270,30 +270,30 @@ s3d_scene_get_device
struct s3d_device** dev);
/*******************************************************************************
- * Session API - View of the current scene geometry
+ * Scene view API - State of the scene geometry
******************************************************************************/
S3D_API res_T
-s3d_session_create
+s3d_scene_view_create
(struct s3d_scene* scn,
- const int session_mask, /* Combination of s3d_session_flag */
- struct s3d_session** session);
+ const int mask, /* Combination of s3d_scene_view_flag */
+ struct s3d_scene_view** scnview);
S3D_API res_T
-s3d_session_ref_get
- (struct s3d_session* session);
+s3d_scene_view_ref_get
+ (struct s3d_scene_view* scnview);
S3D_API res_T
-s3d_session_ref_put
- (struct s3d_session* session);
+s3d_scene_view_ref_put
+ (struct s3d_scene_view* scnview);
S3D_API res_T
-s3d_session_get_mask
- (struct s3d_session* session,
+s3d_scene_view_get_mask
+ (struct s3d_scene_view* scnview,
int* mask);
S3D_API res_T
-s3d_session_trace_ray
- (struct s3d_session* session,
+s3d_scene_view_trace_ray
+ (struct s3d_scene_view* scnview,
const float origin[3], /* Ray origin */
const float direction[3], /* Ray direction. Must be normalized */
const float range[2], /* In [0, INF)^2 */
@@ -304,11 +304,11 @@ s3d_session_trace_ray
* along them. The rays are defined by `origin' + t*`direction' = 0 with t in
* [`range[0]', `range[1]'). Note that if a range is degenerated (i.e.
* `range[0]' >= `range[1]') then its associated ray is not traced and `hit' is
- * set to S3D_HIT_NULL. Can be called only if the session was created with the
+ * set to S3D_HIT_NULL. Can be called only if the scnview was created with the
* S3D_TRACE flag. */
S3D_API res_T
-s3d_session_trace_rays
- (struct s3d_session* session,
+s3d_scene_view_trace_rays
+ (struct s3d_scene_view* scnview,
const size_t nrays, /* # rays */
const int mask, /* Combination of s3d_ray_flag */
const float* origins, /* List of 3D ray origins */
@@ -319,46 +319,46 @@ s3d_session_trace_rays
struct s3d_hit* hits);
/* Uniformly sample the scene and returned the sampled primitive and its sample
- * uv position. Can be called only if the session was created with the
+ * uv position. Can be called only if the scnview was created with the
* S3D_SAMPLE flag */
S3D_API res_T
-s3d_session_sample
- (struct s3d_session* session,
+s3d_scene_view_sample
+ (struct s3d_scene_view* scnview,
const float u, const float v, const float w, /* Random numbers in [0, 1) */
struct s3d_primitive* primitive, /* Sampled primitive */
float st[2]); /* Sampled parametric coordinates on the primitive */
-/* Retrieve a primitive from the scene. Can be called only if the session was
+/* Retrieve a primitive from the scene. Can be called only if the scnview was
* created with the S3D_GET_PRIMITIVE flag */
S3D_API res_T
-s3d_session_get_primitive
- (struct s3d_session* session,
+s3d_scene_view_get_primitive
+ (struct s3d_scene_view* scnview,
const unsigned iprim, /* in [0, #prims) */
struct s3d_primitive* prim);
/* Return the overall number of scene primitives */
S3D_API res_T
-s3d_session_primitives_count
- (struct s3d_session* session,
+s3d_scene_view_primitives_count
+ (struct s3d_scene_view* scnview,
size_t* primitives_count);
/* Compute the overall scene surface area */
S3D_API res_T
-s3d_session_compute_area
- (struct s3d_session* session,
+s3d_scene_view_compute_area
+ (struct s3d_scene_view* scnview,
float* area);
/* This function assumes that the scene defines a closed volume and that the
* normals point into the volume. */
S3D_API res_T
-s3d_session_compute_volume
- (struct s3d_session* session,
+s3d_scene_view_compute_volume
+ (struct s3d_scene_view* scnview,
float* volume);
/* Retrieve the Axis Aligned Bounding Box of the scene */
S3D_API res_T
-s3d_session_get_aabb
- (struct s3d_session* session,
+s3d_scene_view_get_aabb
+ (struct s3d_scene_view* scnview,
float lower[3], /* AABB lower bound */
float upper[3]); /* AABB upper bound */
diff --git a/src/s3d_instance.h b/src/s3d_instance.h
@@ -40,7 +40,7 @@
struct instance {
float transform[12]; /* local to world 3x4 column major matrix */
struct s3d_scene* scene; /* Instantiated scene */
- struct s3d_session* session; /* Current session of the instance */
+ struct s3d_scene_view* scnview; /* Current view of the instantiated scene */
ref_T ref;
};
diff --git a/src/s3d_scene.c b/src/s3d_scene.c
@@ -33,7 +33,7 @@
#include "s3d.h"
#include "s3d_device_c.h"
#include "s3d_scene_c.h"
-#include "s3d_session_c.h"
+#include "s3d_scene_view_c.h"
#include "s3d_shape_c.h"
#include <rsys/list.h>
@@ -53,8 +53,8 @@ scene_release(ref_T* ref)
ASSERT(ref);
scn = CONTAINER_OF(ref, struct s3d_scene, ref);
dev = scn->dev;
- LIST_FOR_EACH_SAFE(node, tmp, &scn->sessions) {
- session_destroy(CONTAINER_OF(node, struct s3d_session, node));
+ LIST_FOR_EACH_SAFE(node, tmp, &scn->scnviews) {
+ scene_view_destroy(CONTAINER_OF(node, struct s3d_scene_view, node));
}
S3D(scene_clear(scn));
htable_shape_release(&scn->shapes);
@@ -83,7 +83,7 @@ s3d_scene_create(struct s3d_device* dev, struct s3d_scene** out_scn)
}
htable_shape_init(dev->allocator, &scn->shapes);
SIG_INIT(&scn->sig_shape_detach);
- list_init(&scn->sessions);
+ list_init(&scn->scnviews);
ref_init(&scn->ref);
S3D(device_ref_get(dev));
scn->dev = dev;
diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h
@@ -52,7 +52,7 @@ CLBK(scene_shape_cb_T, ARG2
struct s3d_scene {
struct htable_shape shapes; /* List of attached shapes */
size_t instances_count; /* # instances in the scene */
- struct list_node sessions; /* Pool of available s3d_sessions */
+ struct list_node scnviews; /* Pool of available s3d_scene_view */
signal_T sig_shape_detach;
diff --git a/src/s3d_scene_view.c b/src/s3d_scene_view.c
@@ -0,0 +1,1418 @@
+/* Copyright (C) |Meso|Star> 2015-2016 (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.h"
+#include "s3d_device_c.h"
+#include "s3d_scene_c.h"
+#include "s3d_scene_view_c.h"
+#include "s3d_shape_c.h"
+
+#include <rsys/float3.h>
+#include <rsys/float33.h>
+#include <rsys/mem_allocator.h>
+
+#include <algorithm>
+
+struct ray_extended : public RTCRay {
+ struct s3d_scene_view* scnview;
+ void* data; /* User defined data */
+};
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static FINLINE bool
+operator < (const struct fltui& it, const float val)
+{
+ /* This operator is used by the std::lower_bound algorithm that returns an
+ * iterator to the first element that is not less than val while one expect
+ * an iterator on the first element that is not less *or equal* than val.
+ * That's why we use <= rather than < */
+ return it.flt <= val;
+}
+
+static FINLINE bool
+operator < (const struct nprims_cdf& it, const size_t iprim)
+{
+ /* This operator is used by the std::lower_bound algorithm that returns an
+ * iterator to the first element that is not less than iprim while one expect
+ * an iterator on the first element that is not less *or equal* than iprim.
+ * That's why we use <= rather than < */
+ return it.nprims <= iprim;
+}
+
+static INLINE void
+scene_view_destroy_geometry(struct s3d_scene_view* scnview, struct geometry* geom)
+{
+ ASSERT(geom);
+ if(geom->irtc != RTC_INVALID_GEOMETRY_ID) {
+ rtcDeleteGeometry(scnview->rtc_scn, geom->irtc);
+ geom->irtc = RTC_INVALID_GEOMETRY_ID;
+ scnview->rtc_delete_geometry = 1; /* Notify the scene upd */
+ }
+ geometry_ref_put(geom);
+}
+
+static void
+on_shape_detach
+ (const struct s3d_scene* scn,
+ const struct s3d_shape* shape,
+ void* data)
+{
+ struct geometry** pgeom;
+ struct geometry* geom;
+ struct s3d_scene_view* scnview = (struct s3d_scene_view*)data;
+ unsigned shape_id;
+ ASSERT(scn && shape && data);
+ (void)scn;
+
+ S3D(shape_get_id(shape, &shape_id));
+ pgeom = htable_geom_find(&scnview->cached_geoms, &shape_id);
+
+ /* The scnview did not register a geometry for this shape. Ignore the signal */
+ if(!pgeom) return;
+
+ geom = *pgeom;
+ if(scnview->mask == 0) {
+ /* The scnview is NOT in use. Directly rm the cached geometry */
+ size_t n; (void)n;
+ scene_view_destroy_geometry(scnview, geom);
+ n = htable_geom_erase(&scnview->cached_geoms, &shape_id);
+ ASSERT(n == 1);
+ } else {
+ /* The scnview is in use. Delay the deletion of the cached geometry */
+ res_T res = darray_uint_push_back(&scnview->detached_shapes, &shape_id);
+ if(res != RES_OK) FATAL("Insufficient memory.\n");
+ }
+}
+
+static INLINE void
+hit_setup(struct s3d_scene_view* scnview, const RTCRay* ray, struct s3d_hit* hit)
+{
+ float w;
+ char flip_surface = 0;
+
+ ASSERT(scnview && hit && ray);
+
+ if((unsigned)ray->geomID == RTC_INVALID_GEOMETRY_ID) { /* No hit */
+ *hit = S3D_HIT_NULL;
+ return;
+ }
+
+ f3_set(hit->normal, ray->Ng);
+ hit->distance = ray->tfar;
+
+ hit->uv[0] = ray->u;
+ hit->uv[1] = ray->v;
+ 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 ray parameters the barycentric coordinates of
+ * the hit with respect to the second and third triangle vertices,
+ * respectively. The following code computes the barycentric coordinates of
+ * the hit for the first and second triangle vertices */
+ hit->uv[1] = hit->uv[0];
+ hit->uv[0] = w;
+
+ if((unsigned)ray->instID == RTC_INVALID_GEOMETRY_ID) {
+ struct geometry* geom_mesh;
+ ASSERT((unsigned)ray->geomID < darray_geom_size_get(&scnview->embree2geoms));
+ geom_mesh = scene_view_geometry_from_embree_id(scnview, ray->geomID);
+ hit->prim.mesh__ = geom_mesh;
+ hit->prim.inst__ = NULL;
+ hit->prim.prim_id = ray->primID;
+ hit->prim.geom_id = geom_mesh->name;
+ hit->prim.inst_id = S3D_INVALID_ID;
+ hit->prim.scene_prim_id = /* Compute the "scene space" primitive id */
+ hit->prim.prim_id /* Mesh space */
+ + geom_mesh->scene_prim_id_offset; /* Scene space */
+
+ } else { /* The hit shape is instantiated */
+ /* Retrieve the hit instance */
+ struct geometry* geom_inst;
+ struct geometry* geom_mesh;
+ ASSERT((unsigned)ray->instID < darray_geom_size_get(&scnview->embree2geoms));
+ geom_inst = scene_view_geometry_from_embree_id(scnview, ray->instID);
+ geom_mesh = scene_view_geometry_from_embree_id
+ (geom_inst->data.instance->scnview, ray->geomID);
+ hit->prim.mesh__ = geom_mesh;
+ hit->prim.inst__ = geom_inst;
+ hit->prim.prim_id = ray->primID;
+ hit->prim.geom_id = geom_mesh->name;
+ hit->prim.inst_id = geom_inst->name;
+ hit->prim.scene_prim_id = /* Compute the "scene space" */
+ hit->prim.prim_id /* Mesh space */
+ + geom_mesh->scene_prim_id_offset /* Inst space */
+ + geom_inst->scene_prim_id_offset; /* Scene space */
+
+ flip_surface = geom_inst->flip_surface;
+ ASSERT(hit->prim.inst__);
+ ASSERT(((struct geometry*)hit->prim.inst__)->type == GEOM_INSTANCE);
+ }
+ ASSERT(hit->prim.mesh__);
+ ASSERT(((struct geometry*)hit->prim.mesh__)->type == GEOM_MESH);
+
+ /* Flip geometric normal with respect to the flip surface flag */
+ flip_surface ^= ((struct geometry*)hit->prim.mesh__)->flip_surface;
+ if(flip_surface) f3_minus(hit->normal, hit->normal);
+}
+
+/* Wrapper between an Embree and a Star-3D filter function */
+static void
+filter_wrapper(void* user_ptr, RTCRay& ray)
+{
+ struct s3d_hit hit;
+ struct hit_filter* filter = (struct hit_filter*)user_ptr;
+ struct ray_extended* ray_ex = static_cast<struct ray_extended*>(&ray);
+
+ hit_setup(ray_ex->scnview, &ray, &hit);
+ if(filter->func(&hit, ray_ex->org, ray_ex->dir, ray_ex->data, filter->data)) {
+ /* Discard the intersection */
+ ray.geomID = RTC_INVALID_GEOMETRY_ID;
+ }
+}
+
+static res_T
+embree_geometry_register
+ (struct s3d_scene_view* scnview,
+ struct geometry* geom)
+{
+ ASSERT(scnview && geom && (geom->type==GEOM_MESH || geom->type==GEOM_INSTANCE));
+
+ /* Create the Embree geometry if it is not valid */
+ if(geom->irtc == RTC_INVALID_GEOMETRY_ID) {
+ switch(geom->type) {
+ case GEOM_MESH:
+ geom->irtc = rtcNewTriangleMesh(scnview->rtc_scn, RTC_GEOMETRY_DYNAMIC,
+ mesh_get_ntris(geom->data.mesh), mesh_get_nverts(geom->data.mesh));
+ break;
+ case GEOM_INSTANCE:
+ geom->irtc = rtcNewInstance
+ (scnview->rtc_scn, geom->data.instance->scnview->rtc_scn);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ if(geom->irtc == RTC_INVALID_GEOMETRY_ID)
+ return RES_UNKNOWN_ERR;
+ }
+
+ /* Register the embree geometry in the embree2geoms associative array */
+ if(geom->irtc >= darray_geom_size_get(&scnview->embree2geoms)) {
+ const res_T res = darray_geom_resize(&scnview->embree2geoms, geom->irtc+1);
+ if(res != RES_OK) {
+ rtcDeleteGeometry(scnview->rtc_scn, geom->irtc);
+ geom->irtc = RTC_INVALID_GEOMETRY_ID;
+ return res;
+ }
+ }
+ darray_geom_data_get(&scnview->embree2geoms)[geom->irtc] = geom;
+ return RES_OK;
+}
+
+static INLINE void
+embree_geometry_setup_positions
+ (struct s3d_scene_view* scnview, struct geometry* geom)
+{
+ ASSERT(scnview && geom && geom->type == GEOM_MESH);
+ ASSERT(geom->irtc != RTC_INVALID_GEOMETRY_ID);
+ rtcSetBuffer(scnview->rtc_scn, geom->irtc, RTC_VERTEX_BUFFER,
+ mesh_get_pos(geom->data.mesh), 0, sizeof(float[3]));
+ rtcUpdateBuffer(scnview->rtc_scn, geom->irtc, RTC_VERTEX_BUFFER);
+}
+
+static INLINE void
+embree_geometry_setup_indices
+ (struct s3d_scene_view* scnview, struct geometry* geom)
+{
+ ASSERT(scnview && geom && geom->type == GEOM_MESH);
+ ASSERT(geom->irtc != RTC_INVALID_GEOMETRY_ID);
+ rtcSetBuffer(scnview->rtc_scn, geom->irtc, RTC_INDEX_BUFFER,
+ mesh_get_ids(geom->data.mesh), 0, sizeof(uint32_t[3]));
+ rtcUpdateBuffer(scnview->rtc_scn, geom->irtc, RTC_INDEX_BUFFER);
+}
+
+static INLINE void
+embree_geometry_setup_enable_state
+ (struct s3d_scene_view* scnview, struct geometry* geom)
+{
+ ASSERT(scnview && geom);
+ if(geom->is_enabled) {
+ rtcEnable(scnview->rtc_scn, geom->irtc);
+ } else {
+ rtcDisable(scnview->rtc_scn, geom->irtc);
+ }
+}
+
+static INLINE void
+embree_geometry_setup_filter_function
+ (struct s3d_scene_view* scnview, struct geometry* geom)
+{
+ ASSERT(scnview && geom && geom->irtc != RTC_INVALID_GEOMETRY_ID);
+ ASSERT(geom->type == GEOM_MESH);
+
+ if(!geom->data.mesh->filter.func) {
+ rtcSetIntersectionFilterFunction(scnview->rtc_scn, geom->irtc, NULL);
+ } else {
+ rtcSetIntersectionFilterFunction(scnview->rtc_scn, geom->irtc, filter_wrapper);
+ rtcSetUserData(scnview->rtc_scn, geom->irtc, &geom->data.mesh->filter);
+ }
+}
+
+static INLINE void
+embree_geometry_setup_transform
+ (struct s3d_scene_view* scnview, struct geometry* geom)
+{
+ ASSERT(scnview && geom && geom->irtc != RTC_INVALID_GEOMETRY_ID);
+ ASSERT(geom->type == GEOM_INSTANCE);
+ rtcSetTransform
+ (scnview->rtc_scn,
+ geom->irtc,
+ RTC_MATRIX_COLUMN_MAJOR,
+ geom->data.instance->transform);
+}
+
+
+static INLINE res_T
+scene_view_setup_embree(struct s3d_scene_view* scnview)
+{
+ struct htable_geom_iterator it, end;
+ int rtc_outdated = scnview->rtc_delete_geometry;
+ res_T res = RES_OK;
+ ASSERT(scnview);
+
+ htable_geom_begin(&scnview->cached_geoms, &it);
+ htable_geom_end(&scnview->cached_geoms, &end);
+
+ while(!htable_geom_iterator_eq(&it, &end)) {
+ struct geometry** pgeom = htable_geom_iterator_data_get(&it);
+ struct geometry* geom = *pgeom;
+
+ htable_geom_iterator_next(&it);
+
+ /* Define whether or not the embree scene is outdated */
+ if(geom->embree_outdated_mask) rtc_outdated = 1;
+
+ /* Register the embree geometry */
+ res = embree_geometry_register(scnview, geom);
+ if(res != RES_OK) goto error;
+
+ /* Flush the embree geometry states */
+ if((geom->embree_outdated_mask & EMBREE_VERTICES) != 0)
+ embree_geometry_setup_positions(scnview, geom);
+ if((geom->embree_outdated_mask & EMBREE_INDICES) != 0)
+ embree_geometry_setup_indices(scnview, geom);
+ if((geom->embree_outdated_mask & EMBREE_ENABLE) != 0)
+ embree_geometry_setup_enable_state(scnview, geom);
+ if((geom->embree_outdated_mask & EMBREE_FILTER_FUNCTION) != 0)
+ embree_geometry_setup_filter_function(scnview, geom);
+ if((geom->embree_outdated_mask & EMBREE_TRANSFORM) != 0)
+ embree_geometry_setup_transform(scnview, geom);
+
+ geom->embree_outdated_mask = 0;
+ }
+
+ /* Commit the embree changes */
+ if(rtc_outdated) {
+ rtcCommit(scnview->rtc_scn);
+ scnview->rtc_delete_geometry = 0;
+ }
+
+exit:
+ return res;
+error:
+ darray_geom_clear(&scnview->embree2geoms);
+ goto exit;
+}
+
+static res_T
+scene_view_register_mesh
+ (struct s3d_scene_view* scnview,
+ struct s3d_shape* shape)
+{
+ struct geometry** pgeom = NULL;
+ struct geometry* geom = NULL;
+ size_t iattr;
+ unsigned shape_id;
+
+ res_T res = RES_OK;
+ ASSERT(scnview && shape && shape->type == GEOM_MESH);
+
+ /* Retrieve the cached geometry */
+ S3D(shape_get_id(shape, &shape_id));
+ pgeom = htable_geom_find(&scnview->cached_geoms, &shape_id);
+ if(pgeom) {
+ geom = *pgeom;
+ } else {
+ res = geometry_create(scnview->scn->dev, &geom);
+ if(res != RES_OK) goto error;
+ res = mesh_create(scnview->scn->dev, &geom->data.mesh);
+ if(res != RES_OK) goto error;
+ geom->type = GEOM_MESH;
+ res = htable_geom_set(&scnview->cached_geoms, &shape_id, &geom);
+ if(res != RES_OK) goto error;
+ geom->name = shape->id.index;
+ }
+
+ /* Discard the geometry that is not geometrically valid */
+ if(!shape->data.mesh->indices || !shape->data.mesh->attribs[S3D_POSITION]) {
+ if(geom->irtc != RTC_INVALID_GEOMETRY_ID) {
+ rtcDeleteGeometry(scnview->rtc_scn, geom->irtc);
+ geom->irtc = RTC_INVALID_GEOMETRY_ID;
+ }
+ mesh_clear(geom->data.mesh);
+ goto exit;
+ }
+
+ /* Get a reference onto the shape mesh indices */
+ if(geom->data.mesh->indices != shape->data.mesh->indices) {
+ geom->embree_outdated_mask |= EMBREE_INDICES;
+ if(geom->data.mesh->indices) { /* Release the previous index buffer */
+ index_buffer_ref_put(geom->data.mesh->indices);
+ geom->data.mesh->indices = NULL;
+ }
+ ASSERT(shape->data.mesh->indices);
+ index_buffer_ref_get(shape->data.mesh->indices);
+ geom->data.mesh->indices = shape->data.mesh->indices;
+ }
+
+ /* Get a reference onto the shape mesh attribs */
+ FOR_EACH(iattr, 0, S3D_ATTRIBS_COUNT__) {
+ geom->embree_outdated_mask |= EMBREE_VERTICES;
+ if(geom->data.mesh->attribs[iattr] == shape->data.mesh->attribs[iattr])
+ continue;
+
+ if(geom->data.mesh->attribs[iattr]) { /* Release the previous buffer */
+ vertex_buffer_ref_put(geom->data.mesh->attribs[iattr]);
+ geom->data.mesh->attribs[iattr] = NULL;
+ }
+ if(!shape->data.mesh->attribs[iattr])
+ continue;
+
+ vertex_buffer_ref_get(shape->data.mesh->attribs[iattr]);
+ geom->data.mesh->attribs[iattr] = shape->data.mesh->attribs[iattr];
+ geom->data.mesh->attribs_type[iattr] = shape->data.mesh->attribs_type[iattr];
+ }
+
+ /* Update the enable flag */
+ if(geom->is_enabled != shape->is_enabled) {
+ geom->is_enabled = shape->is_enabled;
+ geom->embree_outdated_mask |= EMBREE_ENABLE;
+ }
+
+ /* Update the filter function */
+ if(geom->data.mesh->filter.func != shape->data.mesh->filter.func
+ || geom->data.mesh->filter.data != shape->data.mesh->filter.data) {
+ geom->data.mesh->filter = shape->data.mesh->filter;
+ geom->embree_outdated_mask |= EMBREE_FILTER_FUNCTION;
+ }
+
+ if(geom->irtc != RTC_INVALID_GEOMETRY_ID) {
+ struct index_buffer* shape_ids = shape->data.mesh->indices;
+ struct index_buffer* geom_ids = geom->data.mesh->indices;
+ struct vertex_buffer* shape_verts = shape->data.mesh->attribs[S3D_POSITION];
+ struct vertex_buffer* geom_verts = geom->data.mesh->attribs[S3D_POSITION];
+ const size_t shape_nids = darray_u32_size_get(&shape_ids->data);
+ const size_t geom_nids = darray_u32_size_get(&geom_ids->data);
+ const size_t shape_nverts = darray_float_size_get(&shape_verts->data);
+ const size_t geom_nverts = darray_float_size_get(&geom_verts->data);
+
+ /* The shape mesh was resize => the Embree geometry is no more valid */
+ if(shape_nids != geom_nids || shape_nverts != geom_nverts) {
+ rtcDeleteGeometry(scnview->rtc_scn, geom->irtc);
+ geom->irtc = RTC_INVALID_GEOMETRY_ID;
+ }
+ }
+
+ geom->flip_surface = shape->flip_surface;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+scene_view_register_instance
+ (struct s3d_scene_view* scnview,
+ struct s3d_shape* shape,
+ const int mask)
+{
+ struct geometry** pgeom = NULL;
+ struct geometry* geom = NULL;
+ struct s3d_scene_view* instance_scnview = NULL;
+ unsigned shape_id;
+ res_T res = RES_OK;
+ ASSERT(scnview && shape && shape->type == GEOM_INSTANCE);
+
+ /* The instance cannot contain instances, i.e. one instancing level is
+ * supported */
+ if(shape->data.instance->scene->instances_count != 0) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Recursively create a scnview on the scene to instantiate */
+ res = s3d_scene_view_create
+ (shape->data.instance->scene, mask, &instance_scnview);
+ if(res != RES_OK) goto error;
+
+ S3D(shape_get_id(shape, &shape_id));
+ pgeom = htable_geom_find(&scnview->cached_geoms, &shape_id);
+ /* Create the scene instance of the geometry if necessary */
+ if(pgeom) {
+ geom = *pgeom;
+ } else {
+ res = geometry_create(scnview->scn->dev, &geom);
+ if(res != RES_OK) goto error;
+ geom->type = GEOM_INSTANCE;
+ res = instance_create(shape->data.instance->scene, &geom->data.instance);
+ if(res != RES_OK) goto error;
+ res = htable_geom_set(&scnview->cached_geoms, &shape_id, &geom);
+ if(res != RES_OK) goto error;
+ geom->name = shape->id.index;
+ }
+ ASSERT(geom->data.instance->scene == shape->data.instance->scene);
+ geom->data.instance->scnview = instance_scnview;
+
+ /* Update the Embree instance transformation if necessary */
+ if(!f33_eq(shape->data.instance->transform, geom->data.instance->transform)
+ || !f3_eq(shape->data.instance->transform+9, geom->data.instance->transform+9)) {
+ geom->embree_outdated_mask |= EMBREE_TRANSFORM;
+ f33_set(geom->data.instance->transform, shape->data.instance->transform);
+ f3_set(geom->data.instance->transform+9, shape->data.instance->transform+9);
+ }
+
+ /* Update the enable flag */
+ if(geom->is_enabled != shape->is_enabled) {
+ geom->is_enabled = shape->is_enabled;
+ geom->embree_outdated_mask |= EMBREE_TRANSFORM;
+ }
+
+ geom->flip_surface = shape->flip_surface;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+scene_view_compute_cdf(struct s3d_scene_view* scnview)
+{
+ struct htable_geom_iterator it, end;
+ size_t len;
+ float area = 0.f;
+ res_T res = RES_OK;
+ ASSERT(scnview);
+ ASSERT(darray_fltui_size_get(&scnview->cdf) == 0);
+
+ htable_geom_begin(&scnview->cached_geoms, &it);
+ htable_geom_end(&scnview->cached_geoms, &end);
+
+ while(!htable_geom_iterator_eq(&it, &end)) {
+ const unsigned* shape_id = htable_geom_iterator_key_get(&it);
+ struct geometry** pgeom = htable_geom_iterator_data_get(&it);
+ struct geometry* geom = *pgeom;
+ struct fltui fltui;
+
+ htable_geom_iterator_next(&it);
+
+ if(!geom->is_enabled) continue;
+
+ switch(geom->type) {
+ case GEOM_MESH:
+ res = mesh_compute_cdf(geom->data.mesh);
+ if(res != RES_OK) goto error;
+ len = darray_float_size_get(&geom->data.mesh->cdf);
+ if(len) {
+ area += darray_float_cdata_get(&geom->data.mesh->cdf)[len - 1];
+ }
+ break;
+ case GEOM_INSTANCE:
+ /* The instance CDF was computed during its scnview synchronisation */
+ len = darray_fltui_size_get(&geom->data.instance->scnview->cdf);
+ if(len) {
+ area += darray_fltui_cdata_get
+ (&geom->data.instance->scnview->cdf)[len - 1].flt;
+ }
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ fltui.ui = *shape_id;
+ fltui.flt = area;
+ if(len) {
+ res = darray_fltui_push_back(&scnview->cdf, &fltui);
+ if(res != RES_OK) goto error;
+ }
+ }
+exit:
+ return res;
+error:
+ darray_fltui_clear(&scnview->cdf);
+ goto exit;
+}
+
+static res_T
+scene_view_compute_nprims_cdf
+ (struct s3d_scene_view* scnview,
+ const char store_cdf)
+{
+ struct htable_geom_iterator it, end;
+ size_t len;
+ unsigned nprims;
+ res_T res = RES_OK;
+ ASSERT(scnview);
+ ASSERT(darray_nprims_cdf_size_get(&scnview->nprims_cdf) == 0);
+
+ htable_geom_begin(&scnview->cached_geoms, &it);
+ htable_geom_end(&scnview->cached_geoms, &end);
+
+ nprims = 0;
+ while(!htable_geom_iterator_eq(&it, &end)) {
+ const unsigned* shape_id = htable_geom_iterator_key_get(&it);
+ struct geometry** pgeom = htable_geom_iterator_data_get(&it);
+ struct geometry* geom = *pgeom;
+ struct nprims_cdf cdf;
+
+ htable_geom_iterator_next(&it);
+
+ if(!geom->is_enabled) continue;
+
+ geom->scene_prim_id_offset = nprims;
+ switch(geom->type) {
+ case GEOM_MESH:
+ len = mesh_get_ntris(geom->data.mesh);
+ nprims += (unsigned)len;
+ break;
+ case GEOM_INSTANCE:
+ /* The instance CDF was computed during its scnview synchronisation */
+ len = darray_nprims_cdf_size_get
+ (&geom->data.instance->scnview->nprims_cdf);
+ if(len) {
+ nprims += darray_nprims_cdf_cdata_get
+ (&geom->data.instance->scnview->nprims_cdf)[len - 1].nprims;
+ }
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+
+ cdf.nprims = nprims;
+ cdf.ishape = *shape_id;
+ if(store_cdf && len) {
+ res = darray_nprims_cdf_push_back(&scnview->nprims_cdf, &cdf);
+ if(res != RES_OK) goto error;
+ }
+ }
+exit:
+ return res;
+error:
+ darray_nprims_cdf_clear(&scnview->nprims_cdf);
+ goto exit;
+}
+
+static void
+scene_view_compute_scene_aabb(struct s3d_scene_view* scnview)
+{
+ struct htable_geom_iterator it, end;
+ float lower[3], upper[3];
+
+ ASSERT(scnview->lower[0] == FLT_MAX && scnview->upper[0] == -FLT_MAX);
+ ASSERT(scnview->lower[1] == FLT_MAX && scnview->upper[1] == -FLT_MAX);
+ ASSERT(scnview->lower[2] == FLT_MAX && scnview->upper[2] == -FLT_MAX);
+
+ htable_geom_begin(&scnview->cached_geoms, &it);
+ htable_geom_end(&scnview->cached_geoms, &end);
+
+ while(!htable_geom_iterator_eq(&it, &end)) {
+ struct instance* inst;
+ struct geometry** pgeom = htable_geom_iterator_data_get(&it);
+ struct geometry* geom = *pgeom;
+
+ htable_geom_iterator_next(&it);
+
+ if(!geom->is_enabled) continue;
+
+ switch(geom->type) {
+ case GEOM_MESH: mesh_compute_aabb(geom->data.mesh, lower, upper); break;
+ case GEOM_INSTANCE:
+ /* Note that the instance AABB was computed during its scnview
+ * synchronisation. */
+ inst = geom->data.instance;
+ /* Transform local scene AABB in world space */
+ f33_mulf3(lower, inst->transform, inst->scnview->lower);
+ f33_mulf3(upper, inst->transform, inst->scnview->upper);
+ f3_add(lower, inst->transform + 9, lower);
+ f3_add(upper, inst->transform + 9, upper);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ f3_min(scnview->lower, scnview->lower, lower);
+ f3_max(scnview->upper, scnview->upper, upper);
+ }
+}
+
+float
+scene_view_compute_volume
+ (struct s3d_scene_view* scnview,
+ const char flip_surface)
+{
+ struct htable_geom_iterator it, end;
+ float volume;
+
+ ASSERT(scnview);
+ htable_geom_begin(&scnview->cached_geoms, &it);
+ htable_geom_end(&scnview->cached_geoms, &end);
+
+ volume = 0.f;
+ while(!htable_geom_iterator_eq(&it, &end)) {
+ struct geometry** pgeom = htable_geom_iterator_data_get(&it);
+ struct geometry* geom = *pgeom;
+ const char flip = geom->flip_surface ^ flip_surface;
+
+ htable_geom_iterator_next(&it);
+
+ if(!geom->is_enabled) continue;
+
+ switch(geom->type) {
+ case GEOM_MESH:
+ volume += mesh_compute_volume(geom->data.mesh, flip);
+ break;
+ case GEOM_INSTANCE:
+ volume += scene_view_compute_volume(geom->data.instance->scnview, flip);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ }
+
+ if(volume < 0.f) {
+ log_warning(scnview->scn->dev,
+"%s:\n"
+"\tthe volume is negative. The scene shapes might not represent closed 2D\n"
+"\tmanifold volumes, or their surface normal might not point inward the volume.\n",
+ FUNC_NAME);
+ }
+
+ return volume;
+}
+
+
+static res_T
+scene_view_sync
+ (struct s3d_scene_view* scnview,
+ const int mask)
+{
+ struct htable_shape_iterator it, end;
+ res_T res = RES_OK;
+
+ ASSERT(scnview);
+ ASSERT((mask & (S3D_TRACE|S3D_SAMPLE|S3D_GET_PRIMITIVE)) != 0);
+
+ /* Commit the scene shape to the scnview */
+ htable_shape_begin(&scnview->scn->shapes, &it);
+ htable_shape_end(&scnview->scn->shapes, &end);
+ while(!htable_shape_iterator_eq(&it, &end)) {
+ struct s3d_shape** pshape = htable_shape_iterator_data_get(&it);
+ struct s3d_shape* shape = *pshape;
+
+ switch(shape->type) {
+ case GEOM_INSTANCE:
+ res = scene_view_register_instance(scnview, shape, mask);
+ break;
+ case GEOM_MESH:
+ res = scene_view_register_mesh(scnview, shape);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ if(res != RES_OK) goto error;
+ htable_shape_iterator_next(&it);
+ }
+
+ scene_view_compute_scene_aabb(scnview);
+
+ /* Setup the scene for the S3D_TRACE scnview */
+ if((mask & S3D_TRACE) != 0) {
+ res = scene_view_setup_embree(scnview);
+ if(res != RES_OK) goto error;
+ }
+ /* Setup the scene for the S3D_SAMPLE scnview */
+ if((mask & S3D_SAMPLE) != 0) {
+ res = scene_view_compute_cdf(scnview);
+ if(res != RES_OK) goto error;
+ }
+ /* Setup the scene for the scene_primitive_id/S3D_GET_PRIMITIVE scnview */
+ res = scene_view_compute_nprims_cdf(scnview, (mask & S3D_GET_PRIMITIVE)!=0);
+ if(res != RES_OK) goto error;
+
+ scnview->mask = mask;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+scene_view_create(struct s3d_scene* scn, struct s3d_scene_view** out_scnview)
+{
+ struct s3d_scene_view* scnview = NULL;
+ res_T res = RES_OK;
+ ASSERT(scn && out_scnview);
+
+ if(!is_list_empty(&scn->scnviews)) {
+ /* Retrieve an already allocated scnview */
+ scnview = CONTAINER_OF(list_head(&scn->scnviews), struct s3d_scene_view, node);
+ list_del(&scnview->node);
+ ref_get(&scnview->ref);
+ } else {
+ const RTCSceneFlags rtc_scene_mask =
+ RTC_SCENE_DYNAMIC
+ | RTC_SCENE_INCOHERENT
+ | RTC_SCENE_ROBUST;
+ const RTCAlgorithmFlags rtc_algorithm_mask =
+ RTC_INTERSECT1
+ | RTC_INTERSECT4;
+
+ scnview = (struct s3d_scene_view*)MEM_CALLOC
+ (scn->dev->allocator, 1, sizeof(struct s3d_scene_view));
+ if(!scnview) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ list_init(&scnview->node);
+ htable_geom_init(scn->dev->allocator, &scnview->cached_geoms);
+ darray_geom_init(scn->dev->allocator, &scnview->embree2geoms);
+ darray_fltui_init(scn->dev->allocator, &scnview->cdf);
+ darray_nprims_cdf_init(scn->dev->allocator, &scnview->nprims_cdf);
+ darray_uint_init(scn->dev->allocator, &scnview->detached_shapes);
+ f3_splat(scnview->lower, FLT_MAX);
+ f3_splat(scnview->upper,-FLT_MAX);
+ ref_init(&scnview->ref);
+
+ scnview->rtc_scn = rtcDeviceNewScene
+ (scn->dev->rtc, rtc_scene_mask, rtc_algorithm_mask);
+ if(!scnview->rtc_scn) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ CLBK_INIT(&scnview->on_shape_detach_cb);
+ CLBK_SETUP(&scnview->on_shape_detach_cb, on_shape_detach, scnview);
+ SIG_CONNECT_CLBK(&scn->sig_shape_detach, &scnview->on_shape_detach_cb);
+ }
+ S3D(scene_ref_get(scn));
+ scnview->scn = scn;
+exit:
+ *out_scnview = scnview;
+ return res;
+error:
+ if(scnview) {
+ S3D(scene_view_ref_put(scnview));
+ scnview = NULL;
+ }
+ goto exit;
+}
+
+static void
+scene_view_release(ref_T* ref)
+{
+ struct htable_geom_iterator it, end;
+ struct s3d_scene_view* scnview = CONTAINER_OF(ref, struct s3d_scene_view, ref);
+ size_t i, n;
+ ASSERT(ref);
+
+ /* Release the scnview of the instances */
+ htable_geom_begin(&scnview->cached_geoms, &it);
+ htable_geom_end(&scnview->cached_geoms, &end);
+ while(!htable_geom_iterator_eq(&it, &end)) {
+ struct geometry** pgeom = htable_geom_iterator_data_get(&it);
+ struct geometry* geom = *pgeom;
+ htable_geom_iterator_next(&it);
+
+ if(geom->type == GEOM_INSTANCE) {
+ if(geom->data.instance->scnview) {
+ S3D(scene_view_ref_put(geom->data.instance->scnview));
+ geom->data.instance->scnview = NULL;
+ }
+ }
+ }
+
+ /* Remove the geometry of the shapes detached while the scnview was active */
+ n = darray_uint_size_get(&scnview->detached_shapes);
+ FOR_EACH(i, 0, n) {
+ const unsigned shape_id = darray_uint_cdata_get(&scnview->detached_shapes)[i];
+ struct geometry** pgeom = htable_geom_find(&scnview->cached_geoms, &shape_id);
+ struct geometry* geom = *pgeom;
+ size_t n; (void)n;
+ scene_view_destroy_geometry(scnview, geom);
+ n = htable_geom_erase(&scnview->cached_geoms, &shape_id);
+ ASSERT(n == 1);
+ }
+ darray_uint_clear(&scnview->detached_shapes);
+
+ /* Clear the scnview data structures excepted the cache of geometries that
+ * will be used to speed up the future scnview creation */
+ darray_geom_clear(&scnview->embree2geoms);
+ darray_fltui_clear(&scnview->cdf);
+ darray_nprims_cdf_clear(&scnview->nprims_cdf);
+ f3_splat(scnview->lower, FLT_MAX);
+ f3_splat(scnview->upper,-FLT_MAX);
+ scnview->mask = 0;
+
+ /* Do not physically release the memory space of the scnview. Add it to the
+ * available scnviews pool of the scene */
+ list_add(&scnview->scn->scnviews, &scnview->node);
+ S3D(scene_ref_put(scnview->scn));
+}
+
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
+res_T
+s3d_scene_view_create
+ (struct s3d_scene* scn,
+ const int mask,
+ struct s3d_scene_view** out_scnview)
+{
+ struct s3d_scene_view* scnview = NULL;
+ res_T res = RES_OK;
+
+ if(!scn || !out_scnview) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!(mask & S3D_TRACE)
+ && !(mask & S3D_SAMPLE)
+ && !(mask & S3D_GET_PRIMITIVE)) {
+ log_error(scn->dev, "%s: no valid scene view mask is defined.\n", FUNC_NAME);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = scene_view_create(scn, &scnview);
+ if(res != RES_OK) goto error;
+
+ res = scene_view_sync(scnview, mask);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(out_scnview) *out_scnview = scnview;
+ return res;
+error:
+ if(scnview) {
+ S3D(scene_view_ref_put(scnview));
+ scnview = NULL;
+ }
+ goto exit;
+}
+
+res_T
+s3d_scene_view_ref_get(struct s3d_scene_view* scnview)
+{
+ if(!scnview) return RES_BAD_ARG;
+ ref_get(&scnview->ref);
+ return RES_OK;
+}
+
+res_T
+s3d_scene_view_ref_put(struct s3d_scene_view* scnview)
+{
+ if(!scnview) return RES_BAD_ARG;
+ ref_put(&scnview->ref, scene_view_release);
+ return RES_OK;
+}
+
+res_T
+s3d_scene_view_get_mask(struct s3d_scene_view* scnview, int* mask)
+{
+ if(!scnview || !mask) return RES_BAD_ARG;
+ *mask = scnview->mask;
+ return RES_OK;
+}
+
+res_T
+s3d_scene_view_trace_ray
+ (struct s3d_scene_view* scnview,
+ const float org[3],
+ const float dir[3],
+ const float range[2],
+ void* ray_data,
+ struct s3d_hit* hit)
+{
+ struct ray_extended ray_ex;
+ if(!scnview || !org || !dir || !range || !hit)
+ return RES_BAD_ARG;
+ if(!f3_is_normalized(dir)) {
+ log_error(scnview->scn->dev,
+ "%s: unnormalized ray direction {%g, %g, %g}.\n",
+ FUNC_NAME, SPLIT3(dir));
+ return RES_BAD_ARG;
+ }
+ if((scnview->mask & S3D_TRACE) == 0) {
+ log_error(scnview->scn->dev,
+ "%s: no active S3D_TRACE scnview on the submitted scnview.\n", FUNC_NAME);
+ return RES_BAD_OP;
+ }
+ if(range[0] > range[1]) { /* Degenerated range <=> disabled ray */
+ *hit = S3D_HIT_NULL;
+ return RES_OK;
+ }
+
+ f3_set(ray_ex.org, org);
+ f3_set(ray_ex.dir, dir);
+ ray_ex.tnear = range[0];
+ ray_ex.tfar = range[1];
+ ray_ex.geomID = RTC_INVALID_GEOMETRY_ID;
+ ray_ex.primID = RTC_INVALID_GEOMETRY_ID;
+ ray_ex.instID = RTC_INVALID_GEOMETRY_ID;
+ ray_ex.mask = 0xFFFFFFFF;
+ ray_ex.time = 0.f;
+ ray_ex.scnview = scnview;
+ ray_ex.data = ray_data;
+
+ rtcIntersect(scnview->rtc_scn, ray_ex);
+
+ hit_setup(scnview, &ray_ex, hit);
+
+ return RES_OK;
+}
+
+res_T
+s3d_scene_view_trace_rays
+ (struct s3d_scene_view* scnview,
+ const size_t nrays,
+ const int mask,
+ const float* origins,
+ const float* directions,
+ const float* ranges,
+ void* rays_data,
+ const size_t sizeof_ray_data,
+ struct s3d_hit* hits)
+{
+ size_t iray;
+ size_t iorg, idir, irange, idata;
+ size_t org_step, dir_step, range_step, data_step;
+ res_T res = RES_OK;
+
+ if(!scnview) return RES_BAD_ARG;
+ if(!nrays) return RES_OK;
+
+ org_step = mask & S3D_RAYS_SINGLE_ORIGIN ? 0 : 3;
+ dir_step = mask & S3D_RAYS_SINGLE_DIRECTION ? 0 : 3;
+ range_step = mask & S3D_RAYS_SINGLE_RANGE ? 0 : 2;
+ data_step = (mask & S3D_RAYS_SINGLE_DATA) || !rays_data ? 0 : sizeof_ray_data;
+ iorg = idir = irange = idata = 0;
+
+ FOR_EACH(iray, 0, nrays) {
+ res = s3d_scene_view_trace_ray(scnview, origins+iorg, directions+idir,
+ ranges+irange, (char*)rays_data+idata, hits+iray);
+ if(UNLIKELY(res != RES_OK)) break;
+ iorg += org_step;
+ idir += dir_step;
+ irange += range_step;
+ idata += data_step;
+ }
+ return res;
+}
+
+res_T
+s3d_scene_view_sample
+ (struct s3d_scene_view* scnview,
+ const float u,
+ const float v,
+ const float w,
+ struct s3d_primitive* primitive, /* sampled primitive */
+ float st[2])
+{
+ struct geometry** pgeom;
+ struct geometry* geom;
+ const struct fltui* fltui_begin, *fltui_end, *fltui_found;
+ const float* flt_begin, *flt_end, *flt_found;
+ unsigned ishape;
+ float f;
+ res_T res = RES_OK;
+
+ if(!scnview || !primitive || !st) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ /* Expecting canonic numbers */
+ if(u < 0.f || u >= 1.f || v < 0.f || v >= 1.f || w < 0.f || w >= 1.f) {
+ log_error(scnview->scn->dev,
+ "%s: the submitted numbers are not canonical, i.e. they are not in [0, 1[.\n",
+ FUNC_NAME);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if((scnview->mask & S3D_SAMPLE) == 0) {
+ log_error(scnview->scn->dev,
+ "%s: no active S3D_SAMPLE scnview on the submitted scene.\n",
+ FUNC_NAME);
+ res = RES_BAD_OP;
+ goto error;
+ }
+
+ /* Find the sampled geometry */
+ if(darray_fltui_size_get(&scnview->cdf) == 0) {
+ /* No geometry to sample */
+ *primitive = S3D_PRIMITIVE_NULL;
+ goto exit;
+ } else if(darray_fltui_size_get(&scnview->cdf) == 1) {
+ ishape = darray_fltui_cdata_get(&scnview->cdf)[0].ui;
+ /* Map u to the CDF bounds */
+ f = u * darray_fltui_cdata_get(&scnview->cdf)[0].flt;
+ } else {
+ fltui_begin = darray_fltui_cdata_get(&scnview->cdf);
+ fltui_end = fltui_begin + darray_fltui_size_get(&scnview->cdf);
+ f = u * fltui_end[-1].flt; /* Map u to the CDF bounds */
+ fltui_found = std::lower_bound(fltui_begin, fltui_end, f);
+ ASSERT(fltui_found != fltui_end);
+ ishape = fltui_found->ui;
+
+ /* Transform u to the geometry CDF bounds */
+ if(fltui_found != fltui_begin)
+ f -= fltui_found[-1].flt;
+ }
+ pgeom = htable_geom_find(&scnview->cached_geoms, &ishape);
+ ASSERT(pgeom);
+ geom = *pgeom;
+
+ if(geom->type == GEOM_MESH) {
+ primitive->inst__ = NULL;
+ primitive->inst_id = S3D_INVALID_ID;
+ primitive->scene_prim_id = 0;
+ } else {
+ /* Find the sampled instantiated geometry */
+ ASSERT(geom->type == GEOM_INSTANCE);
+ primitive->inst__ = geom;
+ primitive->inst_id = geom->name;
+ primitive->scene_prim_id = geom->scene_prim_id_offset;
+ if(darray_fltui_size_get(&geom->data.instance->scnview->cdf) == 1) {
+ ishape = darray_fltui_cdata_get(&geom->data.instance->scnview->cdf)[0].ui;
+ } else {
+ fltui_begin = darray_fltui_cdata_get(&geom->data.instance->scnview->cdf);
+ fltui_end = fltui_begin + darray_fltui_size_get(&geom->data.instance->scnview->cdf);
+ fltui_found = std::lower_bound(fltui_begin, fltui_end, f);
+ ASSERT(fltui_found != fltui_end);
+ ishape = fltui_found->ui;
+
+ /* Transform u to the geometry CDF bounds */
+ if(fltui_found != fltui_begin)
+ f -= fltui_found[-1].flt;
+ }
+ pgeom = htable_geom_find(&geom->data.instance->scnview->cached_geoms, &ishape);
+ ASSERT(pgeom);
+ geom = *pgeom;
+ }
+ ASSERT(geom->type == GEOM_MESH);
+
+ /* Find the sampled triangle */
+ primitive->mesh__ = geom;
+ primitive->geom_id = geom->name;
+ primitive->scene_prim_id += geom->scene_prim_id_offset;
+ flt_begin = darray_float_cdata_get(&geom->data.mesh->cdf);
+ flt_end = flt_begin + darray_float_size_get(&geom->data.mesh->cdf);
+ flt_found = std::lower_bound(flt_begin, flt_end, f);
+ ASSERT(flt_found != flt_end);
+
+ primitive->prim_id = (unsigned)(flt_found - flt_begin);
+ primitive->scene_prim_id += primitive->prim_id;
+ S3D(primitive_sample(primitive, v, w, st));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+s3d_scene_view_get_primitive
+ (struct s3d_scene_view* scnview,
+ const unsigned iprim,
+ struct s3d_primitive* prim)
+{
+ struct geometry** pgeom;
+ struct geometry* geom;
+ const struct nprims_cdf* begin, *end, *found;
+ size_t nprims;
+ unsigned ishape;
+ size_t i;
+ res_T res = RES_OK;
+
+ if(!scnview || !prim) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if((scnview->mask & S3D_GET_PRIMITIVE) == 0) {
+ log_error(scnview->scn->dev,
+ "%s: no active S3D_GET_PRIMITIVE scnview on the submitted scene.\n",
+ FUNC_NAME);
+ res = RES_BAD_OP;
+ goto error;
+ }
+ S3D(scene_view_primitives_count(scnview, &nprims));
+ if(iprim >= nprims) {
+ log_error(scnview->scn->dev,
+ "%s: the primitive index %u exceeds the number of scene primitives %u.\n",
+ FUNC_NAME, iprim, (unsigned)nprims);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ i = iprim;
+ if(darray_nprims_cdf_size_get(&scnview->nprims_cdf) == 1) {
+ ishape = darray_nprims_cdf_cdata_get(&scnview->nprims_cdf)[0].ishape;
+ } else {
+ begin = darray_nprims_cdf_cdata_get(&scnview->nprims_cdf);
+ end = begin + darray_nprims_cdf_size_get(&scnview->nprims_cdf);
+ found = std::lower_bound(begin, end, i);
+ ASSERT(found != end);
+ ishape = found->ishape;
+ if(found != begin) {
+ ASSERT(i >= found[-1].nprims);
+ i -= found[-1].nprims;
+ }
+ }
+ pgeom = htable_geom_find(&scnview->cached_geoms, &ishape);
+ ASSERT(pgeom);
+ geom = *pgeom;
+
+ if(geom->type == GEOM_MESH) {
+ prim->inst__ = NULL;
+ prim->inst_id = S3D_INVALID_ID;
+ prim->scene_prim_id = 0;
+ } else {
+ ASSERT(geom->type == GEOM_INSTANCE);
+ prim->inst__ = geom;
+ prim->inst_id = geom->name;
+ prim->scene_prim_id = geom->scene_prim_id_offset;
+ if(darray_nprims_cdf_size_get(&geom->data.instance->scnview->nprims_cdf)==1) {
+ ishape = darray_nprims_cdf_cdata_get
+ (&geom->data.instance->scnview->nprims_cdf)[0].ishape;
+ } else {
+ begin = darray_nprims_cdf_cdata_get
+ (&geom->data.instance->scnview->nprims_cdf);
+ end = begin + darray_nprims_cdf_size_get
+ (&geom->data.instance->scnview->nprims_cdf);
+ found = std::lower_bound(begin, end, i);
+ ASSERT(found != end);
+ ishape = found->ishape;
+ if(found != begin) {
+ ASSERT(i >= found[-1].nprims);
+ i -= found[-1].nprims;
+ }
+ }
+ pgeom = htable_geom_find(&geom->data.instance->scnview->cached_geoms, &ishape);
+ ASSERT(pgeom);
+ geom = *pgeom;
+ }
+ ASSERT(geom->type == GEOM_MESH);
+ ASSERT(i < mesh_get_ntris(geom->data.mesh));
+ prim->mesh__ = geom;
+ prim->geom_id = geom->name;
+ prim->prim_id = (unsigned)i;
+ prim->scene_prim_id += geom->scene_prim_id_offset;
+ prim->scene_prim_id += prim->prim_id;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+s3d_scene_view_primitives_count(struct s3d_scene_view* scnview, size_t* prims_count)
+{
+ res_T res = RES_OK;
+
+ if(!scnview || !prims_count) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if((scnview->mask & S3D_GET_PRIMITIVE) != 0) {
+ const size_t len = darray_nprims_cdf_size_get(&scnview->nprims_cdf);
+ if(!len) {
+ *prims_count = 0;
+ } else {
+ *prims_count = darray_nprims_cdf_cdata_get
+ (&scnview->nprims_cdf)[len - 1].nprims;
+ }
+ } else {
+ struct htable_geom_iterator it, end;
+ size_t inst_count;
+
+ htable_geom_begin(&scnview->cached_geoms, &it);
+ htable_geom_end(&scnview->cached_geoms, &end);
+ *prims_count = 0;
+ while(!htable_geom_iterator_eq(&it, &end)) {
+ struct geometry** pgeom = htable_geom_iterator_data_get(&it);
+ struct geometry* geom = *pgeom;
+ htable_geom_iterator_next(&it);
+
+ if(!geom->is_enabled) continue;
+
+ switch(geom->type) {
+ case GEOM_MESH:
+ *prims_count += mesh_get_ntris(geom->data.mesh);
+ break;
+ case GEOM_INSTANCE:
+ S3D(scene_view_primitives_count(geom->data.instance->scnview, &inst_count));
+ *prims_count += inst_count;
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ }
+ }
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+s3d_scene_view_compute_area(struct s3d_scene_view* scnview, float* out_area)
+{
+ float area;
+ res_T res = RES_OK;
+
+ if(!scnview || !out_area) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if((scnview->mask & S3D_SAMPLE) != 0) {
+ /* Retrieve the overall scene area from the scene cumulative distribution
+ * function. Note that the CDF stores the cumulative triangle area
+ * multiplied by 2; the real scene area is thus the CDF upper bound / 2 */
+ size_t len = darray_fltui_size_get(&scnview->cdf);
+ if(!len) {
+ area = 0.f;
+ } else {
+ area = darray_fltui_cdata_get(&scnview->cdf)[len - 1].flt * 0.5f;
+ }
+ } else {
+ struct htable_geom_iterator it, end;
+ float inst_area;
+
+ htable_geom_begin(&scnview->cached_geoms, &it);
+ htable_geom_end(&scnview->cached_geoms, &end);
+
+ area = 0.f;
+ while(!htable_geom_iterator_eq(&it, &end)) {
+ struct geometry** pgeom = htable_geom_iterator_data_get(&it);
+ struct geometry* geom = *pgeom;
+
+ htable_geom_iterator_next(&it);
+
+ if(!geom->is_enabled) continue;
+
+ switch(geom->type) {
+ case GEOM_MESH:
+ area += mesh_compute_area(geom->data.mesh);
+ break;
+ case GEOM_INSTANCE:
+ /* TODO take into account the instance scale factor */
+ S3D(scene_view_compute_area(geom->data.instance->scnview, &inst_area));
+ area += inst_area;
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ }
+ }
+
+exit:
+ if(out_area) *out_area = area;
+ return res;
+error:
+ area = -1.f;
+ goto exit;
+}
+
+res_T
+s3d_scene_view_compute_volume(struct s3d_scene_view* scnview, float* out_volume)
+{
+ if(!scnview || !out_volume) return RES_BAD_ARG;
+ *out_volume = scene_view_compute_volume(scnview, 0/*No initial flip_surface*/);
+ return RES_OK;
+}
+
+res_T
+s3d_scene_view_get_aabb(struct s3d_scene_view* scnview, float lower[3], float upper[3])
+{
+ if(!scnview || !lower || !upper) return RES_BAD_ARG;
+ f3_set(lower, scnview->lower);
+ f3_set(upper, scnview->upper);
+ return RES_OK;
+}
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+void
+scene_view_destroy(struct s3d_scene_view* scnview)
+{
+ htable_geom_iterator it, end;
+ ASSERT(scnview && !is_list_empty(&scnview->node)/*Not in use*/);
+ ASSERT(scnview->mask == 0);
+
+ /* Delete the cached geometries */
+ htable_geom_begin(&scnview->cached_geoms, &it);
+ htable_geom_end(&scnview->cached_geoms, &end);
+ while(!htable_geom_iterator_eq(&it, &end)) {
+ struct geometry** pgeom = htable_geom_iterator_data_get(&it);
+ struct geometry* geom = *pgeom;
+ scene_view_destroy_geometry(scnview, geom);
+ htable_geom_iterator_next(&it);
+ }
+
+ /* Delete the back-end scene */
+ if(scnview->rtc_scn) rtcDeleteScene(scnview->rtc_scn);
+
+ /* Release internal data structure */
+ htable_geom_release(&scnview->cached_geoms);
+ darray_geom_release(&scnview->embree2geoms);
+ darray_fltui_release(&scnview->cdf);
+ darray_nprims_cdf_release(&scnview->nprims_cdf);
+ darray_uint_release(&scnview->detached_shapes);
+
+ /* Remove the scnview from its pool */
+ list_del(&scnview->node);
+ CLBK_DISCONNECT(&scnview->on_shape_detach_cb);
+
+ /* Free the scnview memory space */
+ MEM_RM(scnview->scn->dev->allocator, scnview);
+}
+
diff --git a/src/s3d_scene_view_c.h b/src/s3d_scene_view_c.h
@@ -0,0 +1,124 @@
+/* Copyright (C) |Meso|Star> 2015-2016 (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. */
+
+#ifndef S3D_SCENE_VIEW_C_H
+#define S3D_SCENE_VIEW_C_H
+
+#include "s3d_backend.h"
+#include "s3d_scene_c.h"
+
+#include <rsys/dynamic_array.h>
+#include <rsys/dynamic_array_uint.h>
+#include <rsys/hash_table.h>
+#include <rsys/list.h>
+#include <rsys/ref_count.h>
+
+/* Forward declarations */
+struct s3d_scene_view;
+
+/*
+ * The geometry pointers must be initialized to NULL in order to define
+ * which pointers are valid or not
+ */
+static FINLINE void
+geom_ptr_init__(struct mem_allocator* alloc, struct geometry** geom)
+{
+ (void)alloc; *geom = NULL;
+}
+
+/* Generate the darray_geom dynamic array */
+#define DARRAY_NAME geom
+#define DARRAY_DATA struct geometry*
+#define DARRAY_FUNCTOR_INIT geom_ptr_init__
+#include <rsys/dynamic_array.h>
+
+/* Generate the htable_geom hash table */
+#define HTABLE_NAME geom
+#define HTABLE_DATA struct geometry*
+#define HTABLE_KEY unsigned /* Id of the shape */
+#include <rsys/hash_table.h>
+
+/* Generate the darray_fltui dynamic array */
+struct fltui { float flt; unsigned ui; };
+#define DARRAY_NAME fltui
+#define DARRAY_DATA struct fltui
+#include <rsys/dynamic_array.h>
+
+/* Generate the darray_geom_nprims array */
+struct nprims_cdf { unsigned nprims, ishape; };
+#define DARRAY_NAME nprims_cdf
+#define DARRAY_DATA struct nprims_cdf
+#include <rsys/dynamic_array.h>
+
+struct s3d_scene_view {
+ struct list_node node; /* Attachment point to the scene scene_views pool */
+
+ struct htable_geom cached_geoms; /* Cached shape geometries */
+ struct darray_geom embree2geoms; /* Embree index to geometry */
+ struct darray_fltui cdf; /* Unormalized CDF */
+ struct darray_nprims_cdf nprims_cdf;
+
+ /* Id of Shapes detached while the scnview is active */
+ struct darray_uint detached_shapes;
+
+ float lower[3], upper[3]; /* AABB of the scene */
+
+ /* Callback attached to the sig_shape_detach signal of scn */
+ scene_shape_cb_T on_shape_detach_cb;
+
+ int mask; /* Combinatin of enum s3d_scene_view_flag */
+ int rtc_delete_geometry; /* Define if Embree geometries were deleted */
+ RTCScene rtc_scn; /* Embree scene */
+
+ ref_T ref;
+ struct s3d_scene* scn;
+};
+
+extern LOCAL_SYM void
+scene_view_destroy
+ (struct s3d_scene_view* scnview);
+
+static FINLINE struct geometry*
+scene_view_geometry_from_embree_id
+ (struct s3d_scene_view* scnview,
+ const unsigned irtc)
+{
+ struct geometry* geom;
+ ASSERT(scnview && irtc != RTC_INVALID_GEOMETRY_ID);
+ ASSERT(irtc < darray_geom_size_get(&scnview->embree2geoms));
+ geom = darray_geom_data_get(&scnview->embree2geoms)[irtc];
+ ASSERT(geom);
+ return geom;
+}
+
+#endif /* S3D_SCENE_VIEW_C_H */
+
diff --git a/src/s3d_session.c b/src/s3d_session.c
@@ -1,1418 +0,0 @@
-/* Copyright (C) |Meso|Star> 2015-2016 (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.h"
-#include "s3d_device_c.h"
-#include "s3d_scene_c.h"
-#include "s3d_session_c.h"
-#include "s3d_shape_c.h"
-
-#include <rsys/float3.h>
-#include <rsys/float33.h>
-#include <rsys/mem_allocator.h>
-
-#include <algorithm>
-
-struct ray_extended : public RTCRay {
- struct s3d_session* session;
- void* data; /* User defined data */
-};
-
-/*******************************************************************************
- * Helper functions
- ******************************************************************************/
-static FINLINE bool
-operator < (const struct fltui& it, const float val)
-{
- /* This operator is used by the std::lower_bound algorithm that returns an
- * iterator to the first element that is not less than val while one expect
- * an iterator on the first element that is not less *or equal* than val.
- * That's why we use <= rather than < */
- return it.flt <= val;
-}
-
-static FINLINE bool
-operator < (const struct nprims_cdf& it, const size_t iprim)
-{
- /* This operator is used by the std::lower_bound algorithm that returns an
- * iterator to the first element that is not less than iprim while one expect
- * an iterator on the first element that is not less *or equal* than iprim.
- * That's why we use <= rather than < */
- return it.nprims <= iprim;
-}
-
-static INLINE void
-session_destroy_geometry(struct s3d_session* session, struct geometry* geom)
-{
- ASSERT(geom);
- if(geom->irtc != RTC_INVALID_GEOMETRY_ID) {
- rtcDeleteGeometry(session->rtc_scn, geom->irtc);
- geom->irtc = RTC_INVALID_GEOMETRY_ID;
- session->rtc_delete_geometry = 1; /* Notify the scene upd */
- }
- geometry_ref_put(geom);
-}
-
-static void
-on_shape_detach
- (const struct s3d_scene* scn,
- const struct s3d_shape* shape,
- void* data)
-{
- struct geometry** pgeom;
- struct geometry* geom;
- struct s3d_session* session = (struct s3d_session*)data;
- unsigned shape_id;
- ASSERT(scn && shape && data);
- (void)scn;
-
- S3D(shape_get_id(shape, &shape_id));
- pgeom = htable_geom_find(&session->cached_geoms, &shape_id);
-
- /* The session did not register a geometry for this shape. Ignore the signal */
- if(!pgeom) return;
-
- geom = *pgeom;
- if(session->mask == 0) {
- /* The session is NOT in use. Directly rm the cached geometry */
- size_t n; (void)n;
- session_destroy_geometry(session, geom);
- n = htable_geom_erase(&session->cached_geoms, &shape_id);
- ASSERT(n == 1);
- } else {
- /* The session is in use. Delay the deletion of the cached geometry */
- res_T res = darray_uint_push_back(&session->detached_shapes, &shape_id);
- if(res != RES_OK) FATAL("Insufficient memory.\n");
- }
-}
-
-static INLINE void
-hit_setup(struct s3d_session* session, const RTCRay* ray, struct s3d_hit* hit)
-{
- float w;
- char flip_surface = 0;
-
- ASSERT(session && hit && ray);
-
- if((unsigned)ray->geomID == RTC_INVALID_GEOMETRY_ID) { /* No hit */
- *hit = S3D_HIT_NULL;
- return;
- }
-
- f3_set(hit->normal, ray->Ng);
- hit->distance = ray->tfar;
-
- hit->uv[0] = ray->u;
- hit->uv[1] = ray->v;
- 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 ray parameters the barycentric coordinates of
- * the hit with respect to the second and third triangle vertices,
- * respectively. The following code computes the barycentric coordinates of
- * the hit for the first and second triangle vertices */
- hit->uv[1] = hit->uv[0];
- hit->uv[0] = w;
-
- if((unsigned)ray->instID == RTC_INVALID_GEOMETRY_ID) {
- struct geometry* geom_mesh;
- ASSERT((unsigned)ray->geomID < darray_geom_size_get(&session->embree2geoms));
- geom_mesh = session_geometry_from_embree_id(session, ray->geomID);
- hit->prim.mesh__ = geom_mesh;
- hit->prim.inst__ = NULL;
- hit->prim.prim_id = ray->primID;
- hit->prim.geom_id = geom_mesh->name;
- hit->prim.inst_id = S3D_INVALID_ID;
- hit->prim.scene_prim_id = /* Compute the "scene space" primitive id */
- hit->prim.prim_id /* Mesh space */
- + geom_mesh->scene_prim_id_offset; /* Scene space */
-
- } else { /* The hit shape is instantiated */
- /* Retrieve the hit instance */
- struct geometry* geom_inst;
- struct geometry* geom_mesh;
- ASSERT((unsigned)ray->instID < darray_geom_size_get(&session->embree2geoms));
- geom_inst = session_geometry_from_embree_id(session, ray->instID);
- geom_mesh = session_geometry_from_embree_id
- (geom_inst->data.instance->session, ray->geomID);
- hit->prim.mesh__ = geom_mesh;
- hit->prim.inst__ = geom_inst;
- hit->prim.prim_id = ray->primID;
- hit->prim.geom_id = geom_mesh->name;
- hit->prim.inst_id = geom_inst->name;
- hit->prim.scene_prim_id = /* Compute the "scene space" */
- hit->prim.prim_id /* Mesh space */
- + geom_mesh->scene_prim_id_offset /* Inst space */
- + geom_inst->scene_prim_id_offset; /* Scene space */
-
- flip_surface = geom_inst->flip_surface;
- ASSERT(hit->prim.inst__);
- ASSERT(((struct geometry*)hit->prim.inst__)->type == GEOM_INSTANCE);
- }
- ASSERT(hit->prim.mesh__);
- ASSERT(((struct geometry*)hit->prim.mesh__)->type == GEOM_MESH);
-
- /* Flip geometric normal with respect to the flip surface flag */
- flip_surface ^= ((struct geometry*)hit->prim.mesh__)->flip_surface;
- if(flip_surface) f3_minus(hit->normal, hit->normal);
-}
-
-/* Wrapper between an Embree and a Star-3D filter function */
-static void
-filter_wrapper(void* user_ptr, RTCRay& ray)
-{
- struct s3d_hit hit;
- struct hit_filter* filter = (struct hit_filter*)user_ptr;
- struct ray_extended* ray_ex = static_cast<struct ray_extended*>(&ray);
-
- hit_setup(ray_ex->session, &ray, &hit);
- if(filter->func(&hit, ray_ex->org, ray_ex->dir, ray_ex->data, filter->data)) {
- /* Discard the intersection */
- ray.geomID = RTC_INVALID_GEOMETRY_ID;
- }
-}
-
-static res_T
-embree_geometry_register
- (struct s3d_session* session,
- struct geometry* geom)
-{
- ASSERT(session && geom && (geom->type==GEOM_MESH || geom->type==GEOM_INSTANCE));
-
- /* Create the Embree geometry if it is not valid */
- if(geom->irtc == RTC_INVALID_GEOMETRY_ID) {
- switch(geom->type) {
- case GEOM_MESH:
- geom->irtc = rtcNewTriangleMesh(session->rtc_scn, RTC_GEOMETRY_DYNAMIC,
- mesh_get_ntris(geom->data.mesh), mesh_get_nverts(geom->data.mesh));
- break;
- case GEOM_INSTANCE:
- geom->irtc = rtcNewInstance
- (session->rtc_scn, geom->data.instance->session->rtc_scn);
- break;
- default: FATAL("Unreachable code\n"); break;
- }
- if(geom->irtc == RTC_INVALID_GEOMETRY_ID)
- return RES_UNKNOWN_ERR;
- }
-
- /* Register the embree geometry in the embree2geoms associative array */
- if(geom->irtc >= darray_geom_size_get(&session->embree2geoms)) {
- const res_T res = darray_geom_resize(&session->embree2geoms, geom->irtc+1);
- if(res != RES_OK) {
- rtcDeleteGeometry(session->rtc_scn, geom->irtc);
- geom->irtc = RTC_INVALID_GEOMETRY_ID;
- return res;
- }
- }
- darray_geom_data_get(&session->embree2geoms)[geom->irtc] = geom;
- return RES_OK;
-}
-
-static INLINE void
-embree_geometry_setup_positions
- (struct s3d_session* session, struct geometry* geom)
-{
- ASSERT(session && geom && geom->type == GEOM_MESH);
- ASSERT(geom->irtc != RTC_INVALID_GEOMETRY_ID);
- rtcSetBuffer(session->rtc_scn, geom->irtc, RTC_VERTEX_BUFFER,
- mesh_get_pos(geom->data.mesh), 0, sizeof(float[3]));
- rtcUpdateBuffer(session->rtc_scn, geom->irtc, RTC_VERTEX_BUFFER);
-}
-
-static INLINE void
-embree_geometry_setup_indices
- (struct s3d_session* session, struct geometry* geom)
-{
- ASSERT(session && geom && geom->type == GEOM_MESH);
- ASSERT(geom->irtc != RTC_INVALID_GEOMETRY_ID);
- rtcSetBuffer(session->rtc_scn, geom->irtc, RTC_INDEX_BUFFER,
- mesh_get_ids(geom->data.mesh), 0, sizeof(uint32_t[3]));
- rtcUpdateBuffer(session->rtc_scn, geom->irtc, RTC_INDEX_BUFFER);
-}
-
-static INLINE void
-embree_geometry_setup_enable_state
- (struct s3d_session* session, struct geometry* geom)
-{
- ASSERT(session && geom);
- if(geom->is_enabled) {
- rtcEnable(session->rtc_scn, geom->irtc);
- } else {
- rtcDisable(session->rtc_scn, geom->irtc);
- }
-}
-
-static INLINE void
-embree_geometry_setup_filter_function
- (struct s3d_session* session, struct geometry* geom)
-{
- ASSERT(session && geom && geom->irtc != RTC_INVALID_GEOMETRY_ID);
- ASSERT(geom->type == GEOM_MESH);
-
- if(!geom->data.mesh->filter.func) {
- rtcSetIntersectionFilterFunction(session->rtc_scn, geom->irtc, NULL);
- } else {
- rtcSetIntersectionFilterFunction(session->rtc_scn, geom->irtc, filter_wrapper);
- rtcSetUserData(session->rtc_scn, geom->irtc, &geom->data.mesh->filter);
- }
-}
-
-static INLINE void
-embree_geometry_setup_transform
- (struct s3d_session* session, struct geometry* geom)
-{
- ASSERT(session && geom && geom->irtc != RTC_INVALID_GEOMETRY_ID);
- ASSERT(geom->type == GEOM_INSTANCE);
- rtcSetTransform
- (session->rtc_scn,
- geom->irtc,
- RTC_MATRIX_COLUMN_MAJOR,
- geom->data.instance->transform);
-}
-
-
-static INLINE res_T
-session_setup_embree(struct s3d_session* session)
-{
- struct htable_geom_iterator it, end;
- int rtc_outdated = session->rtc_delete_geometry;
- res_T res = RES_OK;
- ASSERT(session);
-
- htable_geom_begin(&session->cached_geoms, &it);
- htable_geom_end(&session->cached_geoms, &end);
-
- while(!htable_geom_iterator_eq(&it, &end)) {
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
-
- htable_geom_iterator_next(&it);
-
- /* Define whether or not the embree scene is outdated */
- if(geom->embree_outdated_mask) rtc_outdated = 1;
-
- /* Register the embree geometry */
- res = embree_geometry_register(session, geom);
- if(res != RES_OK) goto error;
-
- /* Flush the embree geometry states */
- if((geom->embree_outdated_mask & EMBREE_VERTICES) != 0)
- embree_geometry_setup_positions(session, geom);
- if((geom->embree_outdated_mask & EMBREE_INDICES) != 0)
- embree_geometry_setup_indices(session, geom);
- if((geom->embree_outdated_mask & EMBREE_ENABLE) != 0)
- embree_geometry_setup_enable_state(session, geom);
- if((geom->embree_outdated_mask & EMBREE_FILTER_FUNCTION) != 0)
- embree_geometry_setup_filter_function(session, geom);
- if((geom->embree_outdated_mask & EMBREE_TRANSFORM) != 0)
- embree_geometry_setup_transform(session, geom);
-
- geom->embree_outdated_mask = 0;
- }
-
- /* Commit the embree changes */
- if(rtc_outdated) {
- rtcCommit(session->rtc_scn);
- session->rtc_delete_geometry = 0;
- }
-
-exit:
- return res;
-error:
- darray_geom_clear(&session->embree2geoms);
- goto exit;
-}
-
-static res_T
-session_register_mesh
- (struct s3d_session* session,
- struct s3d_shape* shape)
-{
- struct geometry** pgeom = NULL;
- struct geometry* geom = NULL;
- size_t iattr;
- unsigned shape_id;
-
- res_T res = RES_OK;
- ASSERT(session && shape && shape->type == GEOM_MESH);
-
- /* Retrieve the cached geometry */
- S3D(shape_get_id(shape, &shape_id));
- pgeom = htable_geom_find(&session->cached_geoms, &shape_id);
- if(pgeom) {
- geom = *pgeom;
- } else {
- res = geometry_create(session->scn->dev, &geom);
- if(res != RES_OK) goto error;
- res = mesh_create(session->scn->dev, &geom->data.mesh);
- if(res != RES_OK) goto error;
- geom->type = GEOM_MESH;
- res = htable_geom_set(&session->cached_geoms, &shape_id, &geom);
- if(res != RES_OK) goto error;
- geom->name = shape->id.index;
- }
-
- /* Discard the geometry that is not geometrically valid */
- if(!shape->data.mesh->indices || !shape->data.mesh->attribs[S3D_POSITION]) {
- if(geom->irtc != RTC_INVALID_GEOMETRY_ID) {
- rtcDeleteGeometry(session->rtc_scn, geom->irtc);
- geom->irtc = RTC_INVALID_GEOMETRY_ID;
- }
- mesh_clear(geom->data.mesh);
- goto exit;
- }
-
- /* Get a reference onto the shape mesh indices */
- if(geom->data.mesh->indices != shape->data.mesh->indices) {
- geom->embree_outdated_mask |= EMBREE_INDICES;
- if(geom->data.mesh->indices) { /* Release the previous index buffer */
- index_buffer_ref_put(geom->data.mesh->indices);
- geom->data.mesh->indices = NULL;
- }
- ASSERT(shape->data.mesh->indices);
- index_buffer_ref_get(shape->data.mesh->indices);
- geom->data.mesh->indices = shape->data.mesh->indices;
- }
-
- /* Get a reference onto the shape mesh attribs */
- FOR_EACH(iattr, 0, S3D_ATTRIBS_COUNT__) {
- geom->embree_outdated_mask |= EMBREE_VERTICES;
- if(geom->data.mesh->attribs[iattr] == shape->data.mesh->attribs[iattr])
- continue;
-
- if(geom->data.mesh->attribs[iattr]) { /* Release the previous buffer */
- vertex_buffer_ref_put(geom->data.mesh->attribs[iattr]);
- geom->data.mesh->attribs[iattr] = NULL;
- }
- if(!shape->data.mesh->attribs[iattr])
- continue;
-
- vertex_buffer_ref_get(shape->data.mesh->attribs[iattr]);
- geom->data.mesh->attribs[iattr] = shape->data.mesh->attribs[iattr];
- geom->data.mesh->attribs_type[iattr] = shape->data.mesh->attribs_type[iattr];
- }
-
- /* Update the enable flag */
- if(geom->is_enabled != shape->is_enabled) {
- geom->is_enabled = shape->is_enabled;
- geom->embree_outdated_mask |= EMBREE_ENABLE;
- }
-
- /* Update the filter function */
- if(geom->data.mesh->filter.func != shape->data.mesh->filter.func
- || geom->data.mesh->filter.data != shape->data.mesh->filter.data) {
- geom->data.mesh->filter = shape->data.mesh->filter;
- geom->embree_outdated_mask |= EMBREE_FILTER_FUNCTION;
- }
-
- if(geom->irtc != RTC_INVALID_GEOMETRY_ID) {
- struct index_buffer* shape_ids = shape->data.mesh->indices;
- struct index_buffer* geom_ids = geom->data.mesh->indices;
- struct vertex_buffer* shape_verts = shape->data.mesh->attribs[S3D_POSITION];
- struct vertex_buffer* geom_verts = geom->data.mesh->attribs[S3D_POSITION];
- const size_t shape_nids = darray_u32_size_get(&shape_ids->data);
- const size_t geom_nids = darray_u32_size_get(&geom_ids->data);
- const size_t shape_nverts = darray_float_size_get(&shape_verts->data);
- const size_t geom_nverts = darray_float_size_get(&geom_verts->data);
-
- /* The shape mesh was resize => the Embree geometry is no more valid */
- if(shape_nids != geom_nids || shape_nverts != geom_nverts) {
- rtcDeleteGeometry(session->rtc_scn, geom->irtc);
- geom->irtc = RTC_INVALID_GEOMETRY_ID;
- }
- }
-
- geom->flip_surface = shape->flip_surface;
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-session_register_instance
- (struct s3d_session* session,
- struct s3d_shape* shape,
- const int session_mask)
-{
- struct geometry** pgeom = NULL;
- struct geometry* geom = NULL;
- struct s3d_session* instance_session = NULL;
- unsigned shape_id;
- res_T res = RES_OK;
- ASSERT(session && shape && shape->type == GEOM_INSTANCE);
-
- /* The instance cannot contain instances, i.e. one instancing level is
- * supported */
- if(shape->data.instance->scene->instances_count != 0) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Recursively create a session on the scene to instantiate */
- res = s3d_session_create
- (shape->data.instance->scene, session_mask, &instance_session);
- if(res != RES_OK) goto error;
-
- S3D(shape_get_id(shape, &shape_id));
- pgeom = htable_geom_find(&session->cached_geoms, &shape_id);
- /* Create the scene instance of the geometry if necessary */
- if(pgeom) {
- geom = *pgeom;
- } else {
- res = geometry_create(session->scn->dev, &geom);
- if(res != RES_OK) goto error;
- geom->type = GEOM_INSTANCE;
- res = instance_create(shape->data.instance->scene, &geom->data.instance);
- if(res != RES_OK) goto error;
- res = htable_geom_set(&session->cached_geoms, &shape_id, &geom);
- if(res != RES_OK) goto error;
- geom->name = shape->id.index;
- }
- ASSERT(geom->data.instance->scene == shape->data.instance->scene);
- geom->data.instance->session = instance_session;
-
- /* Update the Embree instance transformation if necessary */
- if(!f33_eq(shape->data.instance->transform, geom->data.instance->transform)
- || !f3_eq(shape->data.instance->transform+9, geom->data.instance->transform+9)) {
- geom->embree_outdated_mask |= EMBREE_TRANSFORM;
- f33_set(geom->data.instance->transform, shape->data.instance->transform);
- f3_set(geom->data.instance->transform+9, shape->data.instance->transform+9);
- }
-
- /* Update the enable flag */
- if(geom->is_enabled != shape->is_enabled) {
- geom->is_enabled = shape->is_enabled;
- geom->embree_outdated_mask |= EMBREE_TRANSFORM;
- }
-
- geom->flip_surface = shape->flip_surface;
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-session_compute_cdf(struct s3d_session* session)
-{
- struct htable_geom_iterator it, end;
- size_t len;
- float area = 0.f;
- res_T res = RES_OK;
- ASSERT(session);
- ASSERT(darray_fltui_size_get(&session->cdf) == 0);
-
- htable_geom_begin(&session->cached_geoms, &it);
- htable_geom_end(&session->cached_geoms, &end);
-
- while(!htable_geom_iterator_eq(&it, &end)) {
- const unsigned* shape_id = htable_geom_iterator_key_get(&it);
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
- struct fltui fltui;
-
- htable_geom_iterator_next(&it);
-
- if(!geom->is_enabled) continue;
-
- switch(geom->type) {
- case GEOM_MESH:
- res = mesh_compute_cdf(geom->data.mesh);
- if(res != RES_OK) goto error;
- len = darray_float_size_get(&geom->data.mesh->cdf);
- if(len) {
- area += darray_float_cdata_get(&geom->data.mesh->cdf)[len - 1];
- }
- break;
- case GEOM_INSTANCE:
- /* The instance CDF was computed during its session synchronisation */
- len = darray_fltui_size_get(&geom->data.instance->session->cdf);
- if(len) {
- area += darray_fltui_cdata_get
- (&geom->data.instance->session->cdf)[len - 1].flt;
- }
- break;
- default: FATAL("Unreachable code\n"); break;
- }
- fltui.ui = *shape_id;
- fltui.flt = area;
- if(len) {
- res = darray_fltui_push_back(&session->cdf, &fltui);
- if(res != RES_OK) goto error;
- }
- }
-exit:
- return res;
-error:
- darray_fltui_clear(&session->cdf);
- goto exit;
-}
-
-static res_T
-session_compute_nprims_cdf
- (struct s3d_session* session,
- const char store_cdf)
-{
- struct htable_geom_iterator it, end;
- size_t len;
- unsigned nprims;
- res_T res = RES_OK;
- ASSERT(session);
- ASSERT(darray_nprims_cdf_size_get(&session->nprims_cdf) == 0);
-
- htable_geom_begin(&session->cached_geoms, &it);
- htable_geom_end(&session->cached_geoms, &end);
-
- nprims = 0;
- while(!htable_geom_iterator_eq(&it, &end)) {
- const unsigned* shape_id = htable_geom_iterator_key_get(&it);
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
- struct nprims_cdf cdf;
-
- htable_geom_iterator_next(&it);
-
- if(!geom->is_enabled) continue;
-
- geom->scene_prim_id_offset = nprims;
- switch(geom->type) {
- case GEOM_MESH:
- len = mesh_get_ntris(geom->data.mesh);
- nprims += (unsigned)len;
- break;
- case GEOM_INSTANCE:
- /* The instance CDF was computed during its session synchronisation */
- len = darray_nprims_cdf_size_get
- (&geom->data.instance->session->nprims_cdf);
- if(len) {
- nprims += darray_nprims_cdf_cdata_get
- (&geom->data.instance->session->nprims_cdf)[len - 1].nprims;
- }
- break;
- default: FATAL("Unreachable code\n"); break;
- }
-
- cdf.nprims = nprims;
- cdf.ishape = *shape_id;
- if(store_cdf && len) {
- res = darray_nprims_cdf_push_back(&session->nprims_cdf, &cdf);
- if(res != RES_OK) goto error;
- }
- }
-exit:
- return res;
-error:
- darray_nprims_cdf_clear(&session->nprims_cdf);
- goto exit;
-}
-
-static void
-session_compute_scene_aabb(struct s3d_session* session)
-{
- struct htable_geom_iterator it, end;
- float lower[3], upper[3];
-
- ASSERT(session->lower[0] == FLT_MAX && session->upper[0] == -FLT_MAX);
- ASSERT(session->lower[1] == FLT_MAX && session->upper[1] == -FLT_MAX);
- ASSERT(session->lower[2] == FLT_MAX && session->upper[2] == -FLT_MAX);
-
- htable_geom_begin(&session->cached_geoms, &it);
- htable_geom_end(&session->cached_geoms, &end);
-
- while(!htable_geom_iterator_eq(&it, &end)) {
- struct instance* inst;
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
-
- htable_geom_iterator_next(&it);
-
- if(!geom->is_enabled) continue;
-
- switch(geom->type) {
- case GEOM_MESH: mesh_compute_aabb(geom->data.mesh, lower, upper); break;
- case GEOM_INSTANCE:
- /* Note that the instance AABB was computed during its session
- * synchronisation. */
- inst = geom->data.instance;
- /* Transform local scene AABB in world space */
- f33_mulf3(lower, inst->transform, inst->session->lower);
- f33_mulf3(upper, inst->transform, inst->session->upper);
- f3_add(lower, inst->transform + 9, lower);
- f3_add(upper, inst->transform + 9, upper);
- break;
- default: FATAL("Unreachable code\n"); break;
- }
- f3_min(session->lower, session->lower, lower);
- f3_max(session->upper, session->upper, upper);
- }
-}
-
-float
-session_compute_volume
- (struct s3d_session* session,
- const char flip_surface)
-{
- struct htable_geom_iterator it, end;
- float volume;
-
- ASSERT(session);
- htable_geom_begin(&session->cached_geoms, &it);
- htable_geom_end(&session->cached_geoms, &end);
-
- volume = 0.f;
- while(!htable_geom_iterator_eq(&it, &end)) {
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
- const char flip = geom->flip_surface ^ flip_surface;
-
- htable_geom_iterator_next(&it);
-
- if(!geom->is_enabled) continue;
-
- switch(geom->type) {
- case GEOM_MESH:
- volume += mesh_compute_volume(geom->data.mesh, flip);
- break;
- case GEOM_INSTANCE:
- volume += session_compute_volume(geom->data.instance->session, flip);
- break;
- default: FATAL("Unreachable code\n"); break;
- }
- }
-
- if(volume < 0.f) {
- log_warning(session->scn->dev,
-"%s:\n"
-"\tthe volume is negative. The scene shapes might not represent closed 2D\n"
-"\tmanifold volumes, or their surface normal might not point inward the volume.\n",
- FUNC_NAME);
- }
-
- return volume;
-}
-
-
-static res_T
-session_sync
- (struct s3d_session* session,
- const int mask)
-{
- struct htable_shape_iterator it, end;
- res_T res = RES_OK;
-
- ASSERT(session);
- ASSERT((mask & (S3D_TRACE|S3D_SAMPLE|S3D_GET_PRIMITIVE)) != 0);
-
- /* Commit the scene shape to the session */
- htable_shape_begin(&session->scn->shapes, &it);
- htable_shape_end(&session->scn->shapes, &end);
- while(!htable_shape_iterator_eq(&it, &end)) {
- struct s3d_shape** pshape = htable_shape_iterator_data_get(&it);
- struct s3d_shape* shape = *pshape;
-
- switch(shape->type) {
- case GEOM_INSTANCE:
- res = session_register_instance(session, shape, mask);
- break;
- case GEOM_MESH:
- res = session_register_mesh(session, shape);
- break;
- default: FATAL("Unreachable code\n"); break;
- }
- if(res != RES_OK) goto error;
- htable_shape_iterator_next(&it);
- }
-
- session_compute_scene_aabb(session);
-
- /* Setup the scene for the S3D_TRACE session */
- if((mask & S3D_TRACE) != 0) {
- res = session_setup_embree(session);
- if(res != RES_OK) goto error;
- }
- /* Setup the scene for the S3D_SAMPLE session */
- if((mask & S3D_SAMPLE) != 0) {
- res = session_compute_cdf(session);
- if(res != RES_OK) goto error;
- }
- /* Setup the scene for the scene_primitive_id/S3D_GET_PRIMITIVE session */
- res = session_compute_nprims_cdf(session, (mask & S3D_GET_PRIMITIVE)!=0);
- if(res != RES_OK) goto error;
-
- session->mask = mask;
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-session_create(struct s3d_scene* scn, struct s3d_session** out_session)
-{
- struct s3d_session* session = NULL;
- res_T res = RES_OK;
- ASSERT(scn && out_session);
-
- if(!is_list_empty(&scn->sessions)) {
- /* Retrieve an already allocated session */
- session = CONTAINER_OF(list_head(&scn->sessions), struct s3d_session, node);
- list_del(&session->node);
- ref_get(&session->ref);
- } else {
- const RTCSceneFlags rtc_scene_mask =
- RTC_SCENE_DYNAMIC
- | RTC_SCENE_INCOHERENT
- | RTC_SCENE_ROBUST;
- const RTCAlgorithmFlags rtc_algorithm_mask =
- RTC_INTERSECT1
- | RTC_INTERSECT4;
-
- session = (struct s3d_session*)MEM_CALLOC
- (scn->dev->allocator, 1, sizeof(struct s3d_session));
- if(!session) {
- res = RES_MEM_ERR;
- goto error;
- }
- list_init(&session->node);
- htable_geom_init(scn->dev->allocator, &session->cached_geoms);
- darray_geom_init(scn->dev->allocator, &session->embree2geoms);
- darray_fltui_init(scn->dev->allocator, &session->cdf);
- darray_nprims_cdf_init(scn->dev->allocator, &session->nprims_cdf);
- darray_uint_init(scn->dev->allocator, &session->detached_shapes);
- f3_splat(session->lower, FLT_MAX);
- f3_splat(session->upper,-FLT_MAX);
- ref_init(&session->ref);
-
- session->rtc_scn = rtcDeviceNewScene
- (scn->dev->rtc, rtc_scene_mask, rtc_algorithm_mask);
- if(!session->rtc_scn) {
- res = RES_MEM_ERR;
- goto error;
- }
-
- CLBK_INIT(&session->on_shape_detach_cb);
- CLBK_SETUP(&session->on_shape_detach_cb, on_shape_detach, session);
- SIG_CONNECT_CLBK(&scn->sig_shape_detach, &session->on_shape_detach_cb);
- }
- S3D(scene_ref_get(scn));
- session->scn = scn;
-exit:
- *out_session = session;
- return res;
-error:
- if(session) {
- S3D(session_ref_put(session));
- session = NULL;
- }
- goto exit;
-}
-
-static void
-session_release(ref_T* ref)
-{
- struct htable_geom_iterator it, end;
- struct s3d_session* session = CONTAINER_OF(ref, struct s3d_session, ref);
- size_t i, n;
- ASSERT(ref);
-
- /* Release the session of the instances */
- htable_geom_begin(&session->cached_geoms, &it);
- htable_geom_end(&session->cached_geoms, &end);
- while(!htable_geom_iterator_eq(&it, &end)) {
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
- htable_geom_iterator_next(&it);
-
- if(geom->type == GEOM_INSTANCE) {
- if(geom->data.instance->session) {
- S3D(session_ref_put(geom->data.instance->session));
- geom->data.instance->session = NULL;
- }
- }
- }
-
- /* Remove the geometry of the shapes detached while the session was active */
- n = darray_uint_size_get(&session->detached_shapes);
- FOR_EACH(i, 0, n) {
- const unsigned shape_id = darray_uint_cdata_get(&session->detached_shapes)[i];
- struct geometry** pgeom = htable_geom_find(&session->cached_geoms, &shape_id);
- struct geometry* geom = *pgeom;
- size_t n; (void)n;
- session_destroy_geometry(session, geom);
- n = htable_geom_erase(&session->cached_geoms, &shape_id);
- ASSERT(n == 1);
- }
- darray_uint_clear(&session->detached_shapes);
-
- /* Clear the session data structures excepted the cache of geometries that
- * will be used to speed up the future session creation */
- darray_geom_clear(&session->embree2geoms);
- darray_fltui_clear(&session->cdf);
- darray_nprims_cdf_clear(&session->nprims_cdf);
- f3_splat(session->lower, FLT_MAX);
- f3_splat(session->upper,-FLT_MAX);
- session->mask = 0;
-
- /* Do not physically release the memory space of the session. Add it to the
- * available sessions pool of the scene */
- list_add(&session->scn->sessions, &session->node);
- S3D(scene_ref_put(session->scn));
-}
-
-/*******************************************************************************
- * Exported functions
- ******************************************************************************/
-res_T
-s3d_session_create
- (struct s3d_scene* scn,
- const int session_mask,
- struct s3d_session** out_session)
-{
- struct s3d_session* session = NULL;
- res_T res = RES_OK;
-
- if(!scn || !out_session) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(!(session_mask & S3D_TRACE)
- && !(session_mask & S3D_SAMPLE)
- && !(session_mask & S3D_GET_PRIMITIVE)) {
- log_error(scn->dev, "%s: no valid session is defined.\n", FUNC_NAME);
- res = RES_BAD_ARG;
- goto error;
- }
-
- res = session_create(scn, &session);
- if(res != RES_OK) goto error;
-
- res = session_sync(session, session_mask);
- if(res != RES_OK) goto error;
-
-exit:
- if(out_session) *out_session = session;
- return res;
-error:
- if(session) {
- S3D(session_ref_put(session));
- session = NULL;
- }
- goto exit;
-}
-
-res_T
-s3d_session_ref_get(struct s3d_session* session)
-{
- if(!session) return RES_BAD_ARG;
- ref_get(&session->ref);
- return RES_OK;
-}
-
-res_T
-s3d_session_ref_put(struct s3d_session* session)
-{
- if(!session) return RES_BAD_ARG;
- ref_put(&session->ref, session_release);
- return RES_OK;
-}
-
-res_T
-s3d_session_get_mask(struct s3d_session* session, int* mask)
-{
- if(!session || !mask) return RES_BAD_ARG;
- *mask = session->mask;
- return RES_OK;
-}
-
-res_T
-s3d_session_trace_ray
- (struct s3d_session* session,
- const float org[3],
- const float dir[3],
- const float range[2],
- void* ray_data,
- struct s3d_hit* hit)
-{
- struct ray_extended ray_ex;
- if(!session || !org || !dir || !range || !hit)
- return RES_BAD_ARG;
- if(!f3_is_normalized(dir)) {
- log_error(session->scn->dev,
- "%s: unnormalized ray direction {%g, %g, %g}.\n",
- FUNC_NAME, SPLIT3(dir));
- return RES_BAD_ARG;
- }
- if((session->mask & S3D_TRACE) == 0) {
- log_error(session->scn->dev,
- "%s: no active S3D_TRACE session on the submitted session.\n", FUNC_NAME);
- return RES_BAD_OP;
- }
- if(range[0] > range[1]) { /* Degenerated range <=> disabled ray */
- *hit = S3D_HIT_NULL;
- return RES_OK;
- }
-
- f3_set(ray_ex.org, org);
- f3_set(ray_ex.dir, dir);
- ray_ex.tnear = range[0];
- ray_ex.tfar = range[1];
- ray_ex.geomID = RTC_INVALID_GEOMETRY_ID;
- ray_ex.primID = RTC_INVALID_GEOMETRY_ID;
- ray_ex.instID = RTC_INVALID_GEOMETRY_ID;
- ray_ex.mask = 0xFFFFFFFF;
- ray_ex.time = 0.f;
- ray_ex.session = session;
- ray_ex.data = ray_data;
-
- rtcIntersect(session->rtc_scn, ray_ex);
-
- hit_setup(session, &ray_ex, hit);
-
- return RES_OK;
-}
-
-res_T
-s3d_session_trace_rays
- (struct s3d_session* session,
- const size_t nrays,
- const int mask,
- const float* origins,
- const float* directions,
- const float* ranges,
- void* rays_data,
- const size_t sizeof_ray_data,
- struct s3d_hit* hits)
-{
- size_t iray;
- size_t iorg, idir, irange, idata;
- size_t org_step, dir_step, range_step, data_step;
- res_T res = RES_OK;
-
- if(!session) return RES_BAD_ARG;
- if(!nrays) return RES_OK;
-
- org_step = mask & S3D_RAYS_SINGLE_ORIGIN ? 0 : 3;
- dir_step = mask & S3D_RAYS_SINGLE_DIRECTION ? 0 : 3;
- range_step = mask & S3D_RAYS_SINGLE_RANGE ? 0 : 2;
- data_step = (mask & S3D_RAYS_SINGLE_DATA) || !rays_data ? 0 : sizeof_ray_data;
- iorg = idir = irange = idata = 0;
-
- FOR_EACH(iray, 0, nrays) {
- res = s3d_session_trace_ray(session, origins+iorg, directions+idir,
- ranges+irange, (char*)rays_data+idata, hits+iray);
- if(UNLIKELY(res != RES_OK)) break;
- iorg += org_step;
- idir += dir_step;
- irange += range_step;
- idata += data_step;
- }
- return res;
-}
-
-res_T
-s3d_session_sample
- (struct s3d_session* session,
- const float u,
- const float v,
- const float w,
- struct s3d_primitive* primitive, /* sampled primitive */
- float st[2])
-{
- struct geometry** pgeom;
- struct geometry* geom;
- const struct fltui* fltui_begin, *fltui_end, *fltui_found;
- const float* flt_begin, *flt_end, *flt_found;
- unsigned ishape;
- float f;
- res_T res = RES_OK;
-
- if(!session || !primitive || !st) {
- res = RES_BAD_ARG;
- goto error;
- }
- /* Expecting canonic numbers */
- if(u < 0.f || u >= 1.f || v < 0.f || v >= 1.f || w < 0.f || w >= 1.f) {
- log_error(session->scn->dev,
- "%s: the submitted numbers are not canonical, i.e. they are not in [0, 1[.\n",
- FUNC_NAME);
- res = RES_BAD_ARG;
- goto error;
- }
- if((session->mask & S3D_SAMPLE) == 0) {
- log_error(session->scn->dev,
- "%s: no active S3D_SAMPLE session on the submitted scene.\n",
- FUNC_NAME);
- res = RES_BAD_OP;
- goto error;
- }
-
- /* Find the sampled geometry */
- if(darray_fltui_size_get(&session->cdf) == 0) {
- /* No geometry to sample */
- *primitive = S3D_PRIMITIVE_NULL;
- goto exit;
- } else if(darray_fltui_size_get(&session->cdf) == 1) {
- ishape = darray_fltui_cdata_get(&session->cdf)[0].ui;
- /* Map u to the CDF bounds */
- f = u * darray_fltui_cdata_get(&session->cdf)[0].flt;
- } else {
- fltui_begin = darray_fltui_cdata_get(&session->cdf);
- fltui_end = fltui_begin + darray_fltui_size_get(&session->cdf);
- f = u * fltui_end[-1].flt; /* Map u to the CDF bounds */
- fltui_found = std::lower_bound(fltui_begin, fltui_end, f);
- ASSERT(fltui_found != fltui_end);
- ishape = fltui_found->ui;
-
- /* Transform u to the geometry CDF bounds */
- if(fltui_found != fltui_begin)
- f -= fltui_found[-1].flt;
- }
- pgeom = htable_geom_find(&session->cached_geoms, &ishape);
- ASSERT(pgeom);
- geom = *pgeom;
-
- if(geom->type == GEOM_MESH) {
- primitive->inst__ = NULL;
- primitive->inst_id = S3D_INVALID_ID;
- primitive->scene_prim_id = 0;
- } else {
- /* Find the sampled instantiated geometry */
- ASSERT(geom->type == GEOM_INSTANCE);
- primitive->inst__ = geom;
- primitive->inst_id = geom->name;
- primitive->scene_prim_id = geom->scene_prim_id_offset;
- if(darray_fltui_size_get(&geom->data.instance->session->cdf) == 1) {
- ishape = darray_fltui_cdata_get(&geom->data.instance->session->cdf)[0].ui;
- } else {
- fltui_begin = darray_fltui_cdata_get(&geom->data.instance->session->cdf);
- fltui_end = fltui_begin + darray_fltui_size_get(&geom->data.instance->session->cdf);
- fltui_found = std::lower_bound(fltui_begin, fltui_end, f);
- ASSERT(fltui_found != fltui_end);
- ishape = fltui_found->ui;
-
- /* Transform u to the geometry CDF bounds */
- if(fltui_found != fltui_begin)
- f -= fltui_found[-1].flt;
- }
- pgeom = htable_geom_find(&geom->data.instance->session->cached_geoms, &ishape);
- ASSERT(pgeom);
- geom = *pgeom;
- }
- ASSERT(geom->type == GEOM_MESH);
-
- /* Find the sampled triangle */
- primitive->mesh__ = geom;
- primitive->geom_id = geom->name;
- primitive->scene_prim_id += geom->scene_prim_id_offset;
- flt_begin = darray_float_cdata_get(&geom->data.mesh->cdf);
- flt_end = flt_begin + darray_float_size_get(&geom->data.mesh->cdf);
- flt_found = std::lower_bound(flt_begin, flt_end, f);
- ASSERT(flt_found != flt_end);
-
- primitive->prim_id = (unsigned)(flt_found - flt_begin);
- primitive->scene_prim_id += primitive->prim_id;
- S3D(primitive_sample(primitive, v, w, st));
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-s3d_session_get_primitive
- (struct s3d_session* session,
- const unsigned iprim,
- struct s3d_primitive* prim)
-{
- struct geometry** pgeom;
- struct geometry* geom;
- const struct nprims_cdf* begin, *end, *found;
- size_t nprims;
- unsigned ishape;
- size_t i;
- res_T res = RES_OK;
-
- if(!session || !prim) {
- res = RES_BAD_ARG;
- goto error;
- }
- if((session->mask & S3D_GET_PRIMITIVE) == 0) {
- log_error(session->scn->dev,
- "%s: no active S3D_GET_PRIMITIVE session on the submitted scene.\n",
- FUNC_NAME);
- res = RES_BAD_OP;
- goto error;
- }
- S3D(session_primitives_count(session, &nprims));
- if(iprim >= nprims) {
- log_error(session->scn->dev,
- "%s: the primitive index %u exceeds the number of scene primitives %u.\n",
- FUNC_NAME, iprim, (unsigned)nprims);
- res = RES_BAD_ARG;
- goto error;
- }
-
- i = iprim;
- if(darray_nprims_cdf_size_get(&session->nprims_cdf) == 1) {
- ishape = darray_nprims_cdf_cdata_get(&session->nprims_cdf)[0].ishape;
- } else {
- begin = darray_nprims_cdf_cdata_get(&session->nprims_cdf);
- end = begin + darray_nprims_cdf_size_get(&session->nprims_cdf);
- found = std::lower_bound(begin, end, i);
- ASSERT(found != end);
- ishape = found->ishape;
- if(found != begin) {
- ASSERT(i >= found[-1].nprims);
- i -= found[-1].nprims;
- }
- }
- pgeom = htable_geom_find(&session->cached_geoms, &ishape);
- ASSERT(pgeom);
- geom = *pgeom;
-
- if(geom->type == GEOM_MESH) {
- prim->inst__ = NULL;
- prim->inst_id = S3D_INVALID_ID;
- prim->scene_prim_id = 0;
- } else {
- ASSERT(geom->type == GEOM_INSTANCE);
- prim->inst__ = geom;
- prim->inst_id = geom->name;
- prim->scene_prim_id = geom->scene_prim_id_offset;
- if(darray_nprims_cdf_size_get(&geom->data.instance->session->nprims_cdf)==1) {
- ishape = darray_nprims_cdf_cdata_get
- (&geom->data.instance->session->nprims_cdf)[0].ishape;
- } else {
- begin = darray_nprims_cdf_cdata_get
- (&geom->data.instance->session->nprims_cdf);
- end = begin + darray_nprims_cdf_size_get
- (&geom->data.instance->session->nprims_cdf);
- found = std::lower_bound(begin, end, i);
- ASSERT(found != end);
- ishape = found->ishape;
- if(found != begin) {
- ASSERT(i >= found[-1].nprims);
- i -= found[-1].nprims;
- }
- }
- pgeom = htable_geom_find(&geom->data.instance->session->cached_geoms, &ishape);
- ASSERT(pgeom);
- geom = *pgeom;
- }
- ASSERT(geom->type == GEOM_MESH);
- ASSERT(i < mesh_get_ntris(geom->data.mesh));
- prim->mesh__ = geom;
- prim->geom_id = geom->name;
- prim->prim_id = (unsigned)i;
- prim->scene_prim_id += geom->scene_prim_id_offset;
- prim->scene_prim_id += prim->prim_id;
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-s3d_session_primitives_count(struct s3d_session* session, size_t* prims_count)
-{
- res_T res = RES_OK;
-
- if(!session || !prims_count) {
- res = RES_BAD_ARG;
- goto error;
- }
- if((session->mask & S3D_GET_PRIMITIVE) != 0) {
- const size_t len = darray_nprims_cdf_size_get(&session->nprims_cdf);
- if(!len) {
- *prims_count = 0;
- } else {
- *prims_count = darray_nprims_cdf_cdata_get
- (&session->nprims_cdf)[len - 1].nprims;
- }
- } else {
- struct htable_geom_iterator it, end;
- size_t inst_count;
-
- htable_geom_begin(&session->cached_geoms, &it);
- htable_geom_end(&session->cached_geoms, &end);
- *prims_count = 0;
- while(!htable_geom_iterator_eq(&it, &end)) {
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
- htable_geom_iterator_next(&it);
-
- if(!geom->is_enabled) continue;
-
- switch(geom->type) {
- case GEOM_MESH:
- *prims_count += mesh_get_ntris(geom->data.mesh);
- break;
- case GEOM_INSTANCE:
- S3D(session_primitives_count(geom->data.instance->session, &inst_count));
- *prims_count += inst_count;
- break;
- default: FATAL("Unreachable code\n"); break;
- }
- }
- }
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-s3d_session_compute_area(struct s3d_session* session, float* out_area)
-{
- float area;
- res_T res = RES_OK;
-
- if(!session || !out_area) {
- res = RES_BAD_ARG;
- goto error;
- }
- if((session->mask & S3D_SAMPLE) != 0) {
- /* Retrieve the overall scene area from the scene cumulative distribution
- * function. Note that the CDF stores the cumulative triangle area
- * multiplied by 2; the real scene area is thus the CDF upper bound / 2 */
- size_t len = darray_fltui_size_get(&session->cdf);
- if(!len) {
- area = 0.f;
- } else {
- area = darray_fltui_cdata_get(&session->cdf)[len - 1].flt * 0.5f;
- }
- } else {
- struct htable_geom_iterator it, end;
- float inst_area;
-
- htable_geom_begin(&session->cached_geoms, &it);
- htable_geom_end(&session->cached_geoms, &end);
-
- area = 0.f;
- while(!htable_geom_iterator_eq(&it, &end)) {
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
-
- htable_geom_iterator_next(&it);
-
- if(!geom->is_enabled) continue;
-
- switch(geom->type) {
- case GEOM_MESH:
- area += mesh_compute_area(geom->data.mesh);
- break;
- case GEOM_INSTANCE:
- /* TODO take into account the instance scale factor */
- S3D(session_compute_area(geom->data.instance->session, &inst_area));
- area += inst_area;
- break;
- default: FATAL("Unreachable code\n"); break;
- }
- }
- }
-
-exit:
- if(out_area) *out_area = area;
- return res;
-error:
- area = -1.f;
- goto exit;
-}
-
-res_T
-s3d_session_compute_volume(struct s3d_session* session, float* out_volume)
-{
- if(!session || !out_volume) return RES_BAD_ARG;
- *out_volume = session_compute_volume(session, 0/*No initial flip_surface*/);
- return RES_OK;
-}
-
-res_T
-s3d_session_get_aabb(struct s3d_session* session, float lower[3], float upper[3])
-{
- if(!session || !lower || !upper) return RES_BAD_ARG;
- f3_set(lower, session->lower);
- f3_set(upper, session->upper);
- return RES_OK;
-}
-
-/*******************************************************************************
- * Local functions
- ******************************************************************************/
-void
-session_destroy(struct s3d_session* session)
-{
- htable_geom_iterator it, end;
- ASSERT(session && !is_list_empty(&session->node)/*Not in use*/);
- ASSERT(session->mask == 0);
-
- /* Delete the cached geometries */
- htable_geom_begin(&session->cached_geoms, &it);
- htable_geom_end(&session->cached_geoms, &end);
- while(!htable_geom_iterator_eq(&it, &end)) {
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
- session_destroy_geometry(session, geom);
- htable_geom_iterator_next(&it);
- }
-
- /* Delete the back-end scene */
- if(session->rtc_scn) rtcDeleteScene(session->rtc_scn);
-
- /* Release internal data structure */
- htable_geom_release(&session->cached_geoms);
- darray_geom_release(&session->embree2geoms);
- darray_fltui_release(&session->cdf);
- darray_nprims_cdf_release(&session->nprims_cdf);
- darray_uint_release(&session->detached_shapes);
-
- /* Remove the session from its pool */
- list_del(&session->node);
- CLBK_DISCONNECT(&session->on_shape_detach_cb);
-
- /* Free the session memory space */
- MEM_RM(session->scn->dev->allocator, session);
-}
-
diff --git a/src/s3d_session_c.h b/src/s3d_session_c.h
@@ -1,124 +0,0 @@
-/* Copyright (C) |Meso|Star> 2015-2016 (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. */
-
-#ifndef S3D_SESSION_C_H
-#define S3D_SESSION_C_H
-
-#include "s3d_backend.h"
-#include "s3d_scene_c.h"
-
-#include <rsys/dynamic_array.h>
-#include <rsys/dynamic_array_uint.h>
-#include <rsys/hash_table.h>
-#include <rsys/list.h>
-#include <rsys/ref_count.h>
-
-/* Forward declarations */
-struct s3d_session;
-
-/*
- * The geometry pointers must be initialized to NULL in order to define
- * which pointers are valid or not
- */
-static FINLINE void
-geom_ptr_init__(struct mem_allocator* alloc, struct geometry** geom)
-{
- (void)alloc; *geom = NULL;
-}
-
-/* Generate the darray_geom dynamic array */
-#define DARRAY_NAME geom
-#define DARRAY_DATA struct geometry*
-#define DARRAY_FUNCTOR_INIT geom_ptr_init__
-#include <rsys/dynamic_array.h>
-
-/* Generate the htable_geom hash table */
-#define HTABLE_NAME geom
-#define HTABLE_DATA struct geometry*
-#define HTABLE_KEY unsigned /* Id of the shape */
-#include <rsys/hash_table.h>
-
-/* Generate the darray_fltui dynamic array */
-struct fltui { float flt; unsigned ui; };
-#define DARRAY_NAME fltui
-#define DARRAY_DATA struct fltui
-#include <rsys/dynamic_array.h>
-
-/* Generate the darray_geom_nprims array */
-struct nprims_cdf { unsigned nprims, ishape; };
-#define DARRAY_NAME nprims_cdf
-#define DARRAY_DATA struct nprims_cdf
-#include <rsys/dynamic_array.h>
-
-struct s3d_session {
- struct list_node node; /* Attachment point to the scene sessions pool */
-
- struct htable_geom cached_geoms; /* Cached shape geometries */
- struct darray_geom embree2geoms; /* Embree index to geometry */
- struct darray_fltui cdf; /* Unormalized CDF */
- struct darray_nprims_cdf nprims_cdf;
-
- /* Id of Shapes detached while the session is active */
- struct darray_uint detached_shapes;
-
- float lower[3], upper[3]; /* AABB of the scene */
-
- /* Callback attached to the sig_shape_detach signal of scn */
- scene_shape_cb_T on_shape_detach_cb;
-
- int mask; /* Combinatin of enum s3d_session_flag */
- int rtc_delete_geometry; /* Define if Embree geometries were deleted */
- RTCScene rtc_scn; /* Embree scene */
-
- ref_T ref;
- struct s3d_scene* scn;
-};
-
-extern LOCAL_SYM void
-session_destroy
- (struct s3d_session* session);
-
-static FINLINE struct geometry*
-session_geometry_from_embree_id
- (struct s3d_session* session,
- const unsigned irtc)
-{
- struct geometry* geom;
- ASSERT(session && irtc != RTC_INVALID_GEOMETRY_ID);
- ASSERT(irtc < darray_geom_size_get(&session->embree2geoms));
- geom = darray_geom_data_get(&session->embree2geoms)[irtc];
- ASSERT(geom);
- return geom;
-}
-
-#endif /* S3D_SESSION_C_H */
-
diff --git a/src/test_s3d_primitive.c b/src/test_s3d_primitive.c
@@ -86,7 +86,7 @@ main(int argc, char** argv)
struct mem_allocator allocator;
struct s3d_device* dev;
struct s3d_scene* scn;
- struct s3d_session* session;
+ struct s3d_scene_view* scnview;
struct s3d_shape* walls;
struct s3d_shape* plane;
struct s3d_attrib attr;
@@ -128,9 +128,9 @@ main(int argc, char** argv)
CHECK(s3d_mesh_setup_indexed_vertices
(plane, plane_ntris, plane_get_ids, plane_nverts, &attribs, 1, NULL), RES_OK);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_sample(session, 0, 0, 0, &prim, uv), RES_OK);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0, 0, 0, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_primitive_get_attrib(NULL, S3D_ATTRIBS_COUNT__, NULL, NULL), RES_BAD_ARG);
CHECK(s3d_primitive_get_attrib(&prim, S3D_ATTRIBS_COUNT__, NULL, NULL), RES_BAD_ARG);
@@ -183,12 +183,12 @@ main(int argc, char** argv)
CHECK(s3d_scene_clear(scn), RES_OK);
CHECK(s3d_scene_attach_shape(scn, plane), RES_OK);
- CHECK(s3d_session_create(scn, S3D_GET_PRIMITIVE, &session), RES_OK);
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_GET_PRIMITIVE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
CHECK(nprims, 2);
- CHECK(s3d_session_get_primitive(session, 0, &prim), RES_OK);
+ CHECK(s3d_scene_view_get_primitive(scnview, 0, &prim), RES_OK);
CHECK(S3D_PRIMITIVE_EQ(&prim, &S3D_PRIMITIVE_NULL), 0);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_primitive_compute_area(NULL, NULL), RES_BAD_ARG);
CHECK(s3d_primitive_compute_area(&prim, NULL), RES_BAD_ARG);
diff --git a/src/test_s3d_sampler.c b/src/test_s3d_sampler.c
@@ -53,7 +53,7 @@ main(int argc, char** argv)
struct s3d_device* dev;
struct s3d_scene* scn;
struct s3d_scene* scn2;
- struct s3d_session* session;
+ struct s3d_scene_view* scnview;
struct s3d_shape* cbox;
struct s3d_shape* walls;
struct s3d_shape* short_block;
@@ -88,24 +88,24 @@ main(int argc, char** argv)
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_session_create(scn, S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_sample(NULL, 0, 0, 0, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 0, 0, 0, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_sample(NULL, 0, 0, 0, &prim, NULL), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 0, 0, 0, &prim, NULL), RES_BAD_ARG);
- CHECK(s3d_session_sample(NULL, 0, 0, 0, NULL, uv), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 0, 0, 0, NULL, uv), RES_BAD_ARG);
- CHECK(s3d_session_sample(NULL, 0, 0, 0, &prim, uv), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 0, 0, 0, &prim, uv), RES_OK);
- CHECK(s3d_session_sample(session, -1, 0, 0, &prim, uv), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 0, -1, 0, &prim, uv), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 0, 0, -1, &prim, uv), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 1, 0, 0, &prim, uv), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 0, 1, 0, &prim, uv), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 0, 0, 1, &prim, uv), RES_BAD_ARG);
- CHECK(s3d_session_sample(session, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_sample(NULL, 0, 0, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 0, 0, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(NULL, 0, 0, 0, &prim, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 0, 0, 0, &prim, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(NULL, 0, 0, 0, NULL, uv), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 0, 0, 0, NULL, uv), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(NULL, 0, 0, 0, &prim, uv), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 0, 0, 0, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, -1, 0, 0, &prim, uv), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 0, -1, 0, &prim, uv), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 0, 0, -1, &prim, uv), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 1, 0, 0, &prim, uv), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 0, 1, 0, &prim, uv), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 0, 0, 1, &prim, uv), RES_BAD_ARG);
+ CHECK(s3d_scene_view_sample(scnview, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
CHECK(S3D_PRIMITIVE_EQ(&prim, &S3D_PRIMITIVE_NULL), 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
attribs.usage = S3D_POSITION;
attribs.type = S3D_FLOAT3;
@@ -120,11 +120,11 @@ main(int argc, char** argv)
CHECK(s3d_scene_attach_shape(scn, walls), RES_OK);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
- CHECK(s3d_session_sample(session, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
CHECK(s3d_primitive_get_attrib(&prim, S3D_POSITION, uv, &attr0), RES_OK);
- CHECK(s3d_session_sample(session, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
CHECK(s3d_primitive_get_attrib(&prim, S3D_POSITION, uv, &attr1), RES_OK);
prim1 = prim;
@@ -143,17 +143,17 @@ main(int argc, char** argv)
CHECK(attr1.type, S3D_FLOAT3);
CHECK(f3_eq_eps(attr0.value, attr1.value, 1.e-6f), 1);
- CHECK(s3d_session_sample(session, 0.3f, 0.1f, 0.2f, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.3f, 0.1f, 0.2f, &prim, uv), RES_OK);
CHECK(s3d_primitive_get_attrib(&prim, S3D_POSITION, uv, &attr1), RES_OK);
NCHECK(f3_eq_eps(attr0.value, attr1.value, 1.e-6f), 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_shape_enable(walls, 0), RES_OK);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_sample(session, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
CHECK(S3D_PRIMITIVE_EQ(&prim, &S3D_PRIMITIVE_NULL), 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_shape_enable(walls, 1), RES_OK);
ntris = sizeof(cbox_block_ids)/sizeof(unsigned[3]);
@@ -166,35 +166,35 @@ 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_session_create(scn, S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_sample(session, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
CHECK(s3d_primitive_get_attrib(&prim, S3D_POSITION, uv, &attr0), RES_OK);
desc.vertices = cbox_tall_block;
CHECK(s3d_mesh_setup_indexed_vertices
(tall_block, ntris, cbox_get_ids, nverts, &attribs, 1, &desc), RES_OK);
- CHECK(s3d_session_sample(session, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
CHECK(s3d_primitive_get_attrib(&prim, S3D_POSITION, uv, &attr1), RES_OK);
CHECK(f3_eq_eps(attr0.value, attr1.value, 1.e-6f), 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_sample(session, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
CHECK(s3d_primitive_get_attrib(&prim, S3D_POSITION, uv, &attr1), RES_OK);
NCHECK(f3_eq_eps(attr0.value, attr1.value, 1.e-6f), 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_shape_enable(cbox, 0), RES_OK);
- CHECK(s3d_session_create(scn2, S3D_SAMPLE|S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_sample(session, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_create(scn2, S3D_SAMPLE|S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK);
CHECK(S3D_PRIMITIVE_EQ(&prim, &S3D_PRIMITIVE_NULL), 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_shape_enable(cbox, 1), RES_OK);
- CHECK(s3d_session_create(scn2, S3D_SAMPLE|S3D_TRACE, &session), RES_OK);
+ CHECK(s3d_scene_view_create(scn2, S3D_SAMPLE|S3D_TRACE, &scnview), RES_OK);
FOR_EACH(i, 0, NSAMPS) {
const float u = rand_canonic();
const float v = rand_canonic();
const float w = rand_canonic();
- CHECK(s3d_session_sample(session, u, v, w, &prim, uv), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 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);
@@ -206,7 +206,7 @@ main(int argc, char** argv)
CHECK(prim.scene_prim_id < 30, 1);
printf("%f %f %f\n", SPLIT3(attr0.value));
}
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_device_ref_put(dev), RES_OK);
CHECK(s3d_scene_ref_put(scn), RES_OK);
diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c
@@ -92,9 +92,9 @@ main(int argc, char** argv)
struct s3d_scene* scn;
struct s3d_scene* scn2;
struct s3d_scene* scn3;
- struct s3d_session* session;
- struct s3d_session* session2;
- struct s3d_session* session3;
+ struct s3d_scene_view* scnview;
+ struct s3d_scene_view* scnview2;
+ struct s3d_scene_view* scnview3;
struct s3d_vertex_data attribs;
struct s3d_shape* shapes[4];
const size_t nshapes = sizeof(shapes)/sizeof(struct s3d_shape*);
@@ -155,66 +155,66 @@ main(int argc, char** argv)
CHECK(s3d_scene_attach_shape(scn, shapes[0]), RES_OK);
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_get_mask(session, &mask), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_get_mask(scnview, &mask), RES_OK);
CHECK(mask, S3D_TRACE);
CHECK(s3d_scene_detach_shape(scn, shapes[0]), RES_OK);
CHECK(s3d_scene_clear(scn), RES_OK);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
CHECK(s3d_scene_attach_shape(scn, shapes[0]), RES_OK);
CHECK(s3d_scene_detach_shape(scn, shapes[0]), RES_OK);
CHECK(s3d_scene_attach_shape(scn, shapes[0]), RES_OK);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_scene_attach_shape(scn2, shapes[1]), RES_OK);
CHECK(s3d_scene_attach_shape(scn2, shapes[2]), RES_OK);
CHECK(s3d_scene_attach_shape(scn3, shapes[1]), RES_OK);
- CHECK(s3d_session_create(scn2, S3D_SAMPLE|S3D_TRACE, &session2), RES_OK);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_create(scn3, S3D_SAMPLE, &session3), RES_OK);
- CHECK(s3d_session_ref_put(session3), RES_OK);
+ CHECK(s3d_scene_view_create(scn2, S3D_SAMPLE|S3D_TRACE, &scnview2), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn3, S3D_SAMPLE, &scnview3), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview3), RES_OK);
- CHECK(s3d_session_compute_area(NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_compute_area(session2, NULL), RES_BAD_ARG);
- CHECK(s3d_session_compute_area(NULL, &area), RES_BAD_ARG);
- CHECK(s3d_session_compute_area(session2, &area), RES_OK);
+ CHECK(s3d_scene_view_compute_area(NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_compute_area(scnview2, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_compute_area(NULL, &area), RES_BAD_ARG);
+ CHECK(s3d_scene_view_compute_area(scnview2, &area), RES_OK);
CHECK(area, 0.f);
- CHECK(s3d_session_compute_volume(NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_compute_volume(session2, NULL), RES_BAD_ARG);
- CHECK(s3d_session_compute_volume(NULL, &volume), RES_BAD_ARG);
- CHECK(s3d_session_compute_volume(session2, &volume), RES_OK);
+ CHECK(s3d_scene_view_compute_volume(NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_compute_volume(scnview2, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_compute_volume(NULL, &volume), RES_BAD_ARG);
+ CHECK(s3d_scene_view_compute_volume(scnview2, &volume), RES_OK);
CHECK(volume, 0.f);
- CHECK(s3d_session_primitives_count(NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_primitives_count(session2, NULL), RES_BAD_ARG);
- CHECK(s3d_session_primitives_count(NULL, &nprims), RES_BAD_ARG);
- CHECK(s3d_session_primitives_count(session2, &nprims), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_primitives_count(scnview2, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_primitives_count(NULL, &nprims), RES_BAD_ARG);
+ CHECK(s3d_scene_view_primitives_count(scnview2, &nprims), RES_OK);
CHECK(nprims, 0);
- CHECK(s3d_session_get_aabb(NULL, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_aabb(session2, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_aabb(NULL, lower, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_aabb(session2, lower, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_aabb(NULL, NULL, upper), RES_BAD_ARG);
- CHECK(s3d_session_get_aabb(session2, NULL, upper), RES_BAD_ARG);
- CHECK(s3d_session_get_aabb(NULL, lower, upper), RES_BAD_ARG);
- CHECK(s3d_session_get_aabb(session2, lower, upper), RES_OK);
+ CHECK(s3d_scene_view_get_aabb(NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_aabb(scnview2, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_aabb(NULL, lower, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_aabb(scnview2, lower, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_aabb(NULL, NULL, upper), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_aabb(scnview2, NULL, upper), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_aabb(NULL, lower, upper), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_aabb(scnview2, lower, upper), RES_OK);
CHECK(lower[0] > upper[0], 1);
CHECK(lower[1] > upper[1], 1);
CHECK(lower[2] > upper[2], 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_ref_put(session2), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview2), RES_OK);
CHECK(s3d_scene_instantiate(scn2, shapes + 3), RES_OK);
CHECK(s3d_scene_attach_shape(scn3, shapes[3]), RES_OK);
- CHECK(s3d_session_create(scn3, S3D_SAMPLE|S3D_TRACE, &session3), RES_BAD_ARG);
+ CHECK(s3d_scene_view_create(scn3, S3D_SAMPLE|S3D_TRACE, &scnview3), RES_BAD_ARG);
CHECK(s3d_scene_detach_shape(scn, shapes[0]), RES_OK);
@@ -242,12 +242,12 @@ main(int argc, char** argv)
cbox_get_ids, cbox_walls_nverts, &attribs, 1, data), RES_OK);
CHECK(s3d_scene_attach_shape(scn, shapes[0]), RES_OK);
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_compute_area(session, &area), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_compute_area(scnview, &area), RES_OK);
CHECK(eq_epsf(area, 1532296.f, 1.e-6f), 1);
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
CHECK(nprims, 10);
- CHECK(s3d_session_get_aabb(session, lower, upper), RES_OK);
+ CHECK(s3d_scene_view_get_aabb(scnview, lower, upper), RES_OK);
CHECK(eq_epsf(lower[0], 0.f, 1.e-6f), 1);
CHECK(eq_epsf(lower[1], 0.f, 1.e-6f), 1);
CHECK(eq_epsf(lower[2], 0.f, 1.e-6f), 1);
@@ -258,12 +258,12 @@ main(int argc, char** argv)
CHECK(s3d_scene_instantiate(scn, shapes + 1), RES_OK);
CHECK(s3d_scene_attach_shape(scn2, shapes[1]), RES_OK);
- CHECK(s3d_session_create(scn2, S3D_GET_PRIMITIVE, &session2), RES_OK);
- CHECK(s3d_session_compute_area(session2, &area), RES_OK);
+ CHECK(s3d_scene_view_create(scn2, S3D_GET_PRIMITIVE, &scnview2), RES_OK);
+ CHECK(s3d_scene_view_compute_area(scnview2, &area), RES_OK);
CHECK(eq_epsf(area, 1532296.f, 1.e-6f), 1);
- CHECK(s3d_session_primitives_count(session2, &nprims), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(scnview2, &nprims), RES_OK);
CHECK(nprims, 10);
- CHECK(s3d_session_get_aabb(session2, lower, upper), RES_OK);
+ CHECK(s3d_scene_view_get_aabb(scnview2, lower, upper), RES_OK);
CHECK(eq_epsf(lower[0], 0.f, 1.e-6f), 1);
CHECK(eq_epsf(lower[1], 0.f, 1.e-6f), 1);
CHECK(eq_epsf(lower[2], 0.f, 1.e-6f), 1);
@@ -271,27 +271,27 @@ main(int argc, char** argv)
CHECK(eq_epsf(upper[1], 559.f, 1.e-6f), 1);
CHECK(eq_epsf(upper[2], 548.f, 1.e-6f), 1);
- CHECK(s3d_session_compute_area(session, &area), RES_OK);
+ CHECK(s3d_scene_view_compute_area(scnview, &area), RES_OK);
CHECK(eq_epsf(area, 1532296.f, 1.e-6f), 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
- CHECK(s3d_session_get_primitive(NULL, 11, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_primitive(session2, 11, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_primitive(NULL, 0, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_primitive(session2, 0, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_primitive(NULL, 11, prims + 0), RES_BAD_ARG);
- CHECK(s3d_session_get_primitive(session2, 11, prims + 0), RES_BAD_ARG);
- CHECK(s3d_session_get_primitive(NULL, 0, prims + 0), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_primitive(NULL, 11, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_primitive(scnview2, 11, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_primitive(NULL, 0, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_primitive(scnview2, 0, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_primitive(NULL, 11, prims + 0), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_primitive(scnview2, 11, prims + 0), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_primitive(NULL, 0, prims + 0), RES_BAD_ARG);
FOR_EACH(i, 0, nprims) {
size_t j;
- CHECK(s3d_session_get_primitive(session2, (unsigned)i, prims + i), RES_OK);
+ CHECK(s3d_scene_view_get_primitive(scnview2, (unsigned)i, prims + i), RES_OK);
CHECK(S3D_PRIMITIVE_EQ(prims + i, &S3D_PRIMITIVE_NULL), 0);
CHECK(prims[i].scene_prim_id, i);
FOR_EACH(j, 0, i)
CHECK(S3D_PRIMITIVE_EQ(prims + i, prims + j), 0);
}
- CHECK(s3d_session_ref_put(session2), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview2), RES_OK);
attribs.type = S3D_FLOAT3;
attribs.usage = S3D_POSITION;
@@ -299,18 +299,18 @@ main(int argc, char** argv)
CHECK(s3d_mesh_setup_indexed_vertices
(shapes[0], cube_ntris, cube_get_ids, cube_nverts, &attribs, 1, NULL), RES_OK);
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_compute_area(session, &area), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_compute_area(scnview, &area), RES_OK);
CHECK(eq_epsf(area, 6.f, 1.e-6f), 1);
- CHECK(s3d_session_compute_volume(session, &volume), RES_OK);
+ CHECK(s3d_scene_view_compute_volume(scnview, &volume), RES_OK);
CHECK(eq_epsf(volume, 1.f, 1.e-6f), 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_shape_flip_surface(shapes[0]), RES_OK);
- CHECK(s3d_session_create(scn, S3D_GET_PRIMITIVE, &session), RES_OK);
- CHECK(s3d_session_compute_volume(session, &volume), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_GET_PRIMITIVE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_compute_volume(scnview, &volume), RES_OK);
CHECK(eq_epsf(volume, -1.f, 1.e-6f), 1);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_scene_get_device(NULL, NULL), RES_BAD_ARG);
CHECK(s3d_scene_get_device(scn, NULL), RES_BAD_ARG);
diff --git a/src/test_s3d_scene_view.c b/src/test_s3d_scene_view.c
@@ -0,0 +1,1048 @@
+/* Copyright (C) |Meso|Star> 2015-2016 (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.h"
+#include "test_s3d_utils.h"
+
+#include <rsys/float3.h>
+#include <rsys/float2.h>
+
+#include <string.h>
+
+struct mesh_context {
+ const float* verts;
+ const unsigned* ids;
+};
+
+static int
+filter
+ (const struct s3d_hit* hit,
+ const float org[3],
+ const float dir[3],
+ void* ray_data,
+ void* filter_data)
+{
+ (void)org, (void)dir, (void)ray_data, (void)filter_data;
+ CHECK(S3D_HIT_NONE(hit), 0);
+ return hit->prim.prim_id % 2 == 0;
+}
+
+/*******************************************************************************
+ * Cube data
+ ******************************************************************************/
+static const float cube_verts[] = {
+ 0.f, 0.f, 0.f,
+ 1.f, 0.f, 0.f,
+ 0.f, 1.f, 0.f,
+ 1.f, 1.f, 0.f,
+ 0.f, 0.f, 1.f,
+ 1.f, 0.f, 1.f,
+ 0.f, 1.f, 1.f,
+ 1.f, 1.f, 1.f
+};
+static const unsigned cube_nverts = sizeof(cube_verts) / sizeof(float[3]);
+
+/* Front faces are CW. The normals point into the cube */
+static const unsigned cube_ids[] = {
+ 0, 2, 1, 1, 2, 3, /* Front */
+ 0, 4, 2, 2, 4, 6, /* Left */
+ 4, 5, 6, 6, 5, 7, /* Back */
+ 3, 7, 1, 1, 7, 5, /* Right */
+ 2, 6, 3, 3, 6, 7, /* Top */
+ 0, 1, 4, 4, 1, 5 /* Bottom */
+};
+static const unsigned cube_ntris = sizeof(cube_ids) / sizeof(unsigned[3]);
+
+/*******************************************************************************
+ * Plane data
+ ******************************************************************************/
+static const float plane_verts[] = {
+ 0.f, 0.f, 0.5f,
+ 1.f, 0.f, 0.5f,
+ 1.f, 1.f, 0.5f,
+ 0.f, 1.f, 0.5f
+};
+static const unsigned plane_nverts = sizeof(plane_verts) / sizeof(float[3]);
+
+static const unsigned plane_ids[] = { 0, 1, 2, 2, 3, 0 };
+static const unsigned plane_ntris = sizeof(plane_ids) / sizeof(unsigned[3]);
+
+/*******************************************************************************
+ * helper function
+ ******************************************************************************/
+static float
+rand_canonic(void)
+{
+ int r;
+ while((r = rand()) == RAND_MAX);
+ return (float)r / (float)RAND_MAX;
+}
+
+static void
+get_ids(const unsigned itri, unsigned ids[3], void* data)
+{
+ const unsigned id = itri * 3;
+ const struct mesh_context* ctx = data;
+ NCHECK(ctx, NULL);
+ NCHECK(ids, NULL);
+ ids[0] = ctx->ids[id + 0];
+ ids[1] = ctx->ids[id + 1];
+ ids[2] = ctx->ids[id + 2];
+}
+
+static void
+get_pos(const unsigned ivert, float pos[3], void* data)
+{
+ const unsigned i = ivert*3;
+ const struct mesh_context* ctx = data;
+ NCHECK(ctx, NULL);
+ NCHECK(pos, NULL);
+ pos[0] = ctx->verts[i + 0];
+ pos[1] = ctx->verts[i + 1];
+ pos[2] = ctx->verts[i + 2];
+}
+
+static void
+test_miscellaneous
+ (struct s3d_device* dev,
+ struct s3d_shape* cube,
+ struct s3d_shape* plane)
+{
+ struct s3d_scene* scn;
+ struct s3d_scene_view* scnview;
+ int mask;
+
+ CHECK(s3d_scene_create(dev, &scn), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, plane), RES_OK);
+
+ CHECK(s3d_scene_view_create(NULL, 0, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_create(scn, 0, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_create(NULL, S3D_SAMPLE, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_create(NULL, 0, &scnview), RES_BAD_ARG);
+ CHECK(s3d_scene_view_create(scn, 0, &scnview), RES_BAD_ARG);
+ CHECK(s3d_scene_view_create(NULL, S3D_SAMPLE, &scnview), RES_BAD_ARG);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+
+ CHECK(s3d_scene_view_get_mask(NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_mask(scnview, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_mask(NULL, &mask), RES_BAD_ARG);
+ CHECK(s3d_scene_view_get_mask(scnview, &mask), RES_OK);
+ CHECK(mask, S3D_SAMPLE);
+
+ CHECK(s3d_scene_view_ref_get(NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_ref_get(scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE|S3D_GET_PRIMITIVE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_get_mask(scnview, &mask), RES_OK);
+ CHECK(mask & S3D_TRACE, S3D_TRACE);
+ CHECK(mask & S3D_GET_PRIMITIVE, S3D_GET_PRIMITIVE);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE|S3D_GET_PRIMITIVE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_get_mask(scnview, &mask), RES_OK);
+ CHECK(mask & S3D_SAMPLE, S3D_SAMPLE);
+ CHECK(mask & S3D_GET_PRIMITIVE, S3D_GET_PRIMITIVE);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+
+ CHECK(s3d_scene_ref_put(scn), RES_OK);
+}
+
+static void
+test_trace_ray
+ (struct s3d_device* dev,
+ struct s3d_shape* cube,
+ struct s3d_shape* plane)
+{
+ struct s3d_scene* scn;
+ struct s3d_scene* scn2;
+ struct s3d_scene* scn3;
+ struct s3d_scene_view* scnview;
+ struct s3d_scene_view* scnview2;
+ struct s3d_scene_view* scnview3;
+ struct s3d_shape* inst0;
+ struct s3d_shape* inst1;
+ struct s3d_hit hit, hit2;
+ float org[3], dir[3], range[2];
+ unsigned icube;
+ unsigned iplane;
+ unsigned iinst0;
+ unsigned iinst1;
+
+ CHECK(s3d_shape_get_id(cube, &icube), RES_OK);
+ CHECK(s3d_shape_get_id(plane, &iplane), RES_OK);
+
+ CHECK(s3d_scene_create(dev, &scn), RES_OK);
+ CHECK(s3d_scene_create(dev, &scn2), RES_OK);
+ CHECK(s3d_scene_create(dev, &scn3), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, plane), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn2, cube), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn2, plane), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE|S3D_GET_PRIMITIVE, &scnview), RES_OK);
+
+ f3(org, 0.5f, 0.25f, 0.25f);
+ f3(dir, 0.f, 0.f, 1.f);
+ f2(range, 0.f, FLT_MAX);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_BAD_OP);
+
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview2), RES_OK);
+ CHECK(s3d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 0);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 0);
+
+ f3(dir, 0.f, 0.f, -1.f);
+ CHECK(s3d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 0);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, icube);
+ CHECK(hit.prim.prim_id, 0);
+ f3(dir, 0.f, 0.f, 1.f);
+
+ CHECK(s3d_shape_enable(plane, 0), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+
+ CHECK(s3d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 0);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 0);
+
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 0);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, icube);
+ CHECK(hit.prim.prim_id, 4);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview2), RES_OK);
+ CHECK(s3d_shape_enable(plane, 1), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn2, S3D_TRACE, &scnview2), RES_OK);
+
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(s3d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit2), RES_OK);
+ CHECK(f3_eq(hit.normal, hit2.normal), 1);
+ CHECK(f2_eq(hit.uv, hit2.uv), 1);
+ CHECK(hit.distance, hit2.distance);
+ CHECK(S3D_PRIMITIVE_EQ(&hit.prim, &hit2.prim), 1);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 0);
+
+ CHECK(s3d_scene_detach_shape(scn2, plane), RES_OK);
+ CHECK(s3d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit2), RES_OK);
+ CHECK(f3_eq(hit.normal, hit2.normal), 1);
+ CHECK(f2_eq(hit.uv, hit2.uv), 1);
+ CHECK(hit.distance, hit2.distance);
+ CHECK(S3D_PRIMITIVE_EQ(&hit.prim, &hit2.prim), 1);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview2), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn2, S3D_TRACE, &scnview2), RES_OK);
+
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(f3_eq(hit.normal, hit2.normal), 1);
+ CHECK(f2_eq(hit.uv, hit2.uv), 1);
+ CHECK(hit.distance, hit2.distance);
+ CHECK(S3D_PRIMITIVE_EQ(&hit.prim, &hit2.prim), 1);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 0);
+
+ CHECK(s3d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit2), RES_OK);
+ CHECK(hit2.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit2.prim.geom_id, icube);
+ CHECK(hit2.prim.prim_id, 4);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview2), RES_OK);
+
+ CHECK(s3d_scene_instantiate(scn2, &inst0), RES_OK);
+ CHECK(s3d_scene_instantiate(scn2, &inst1), RES_OK);
+ CHECK(s3d_shape_get_id(inst0, &iinst0), RES_OK);
+ CHECK(s3d_shape_get_id(inst1, &iinst1), RES_OK);
+ CHECK(s3d_instance_translate
+ (inst0, S3D_WORLD_TRANSFORM, f3(org,-2.f, 0.f, 0.f)), RES_OK);
+ CHECK(s3d_instance_translate
+ (inst1, S3D_WORLD_TRANSFORM, f3(org, 2.f, 0.f, 0.f)), RES_OK);
+
+ CHECK(s3d_scene_attach_shape(scn3, inst0), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn3, inst1), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, inst0), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, inst1), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn3, S3D_TRACE, &scnview3), RES_OK);
+
+ f3(org, 0.5f, 0.25f, 0.25f);
+ f3(dir, 0.f, 0.f, 1.f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 0);
+
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+
+ f3(org, -1.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, iinst0);
+ CHECK(hit.prim.geom_id, icube);
+ CHECK(hit.prim.prim_id, 4);
+
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit2), RES_OK);
+ CHECK(hit2.prim.inst_id, iinst0);
+ CHECK(hit2.prim.geom_id, icube);
+ CHECK(hit2.prim.prim_id, 4);
+
+ CHECK(f3_eq(hit.normal, hit2.normal), 1);
+ CHECK(f2_eq(hit.uv, hit2.uv), 1);
+ CHECK(hit.distance, hit2.distance);
+
+ CHECK(s3d_scene_clear(scn2), RES_OK);
+
+ f3(org, 2.5f, 0.25f, 0.25f);
+
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, iinst1);
+ CHECK(hit.prim.geom_id, icube);
+ CHECK(hit.prim.prim_id, 4);
+
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit2), RES_OK);
+ CHECK(hit2.prim.inst_id, iinst1);
+ CHECK(hit2.prim.geom_id, icube);
+ CHECK(hit2.prim.prim_id, 4);
+
+ CHECK(f3_eq(hit.normal, hit2.normal), 1);
+ CHECK(f2_eq(hit.uv, hit2.uv), 1);
+ CHECK(hit.distance, hit2.distance);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+
+ f3(org, -1.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, iinst0);
+ CHECK(hit.prim.geom_id, icube);
+ CHECK(hit.prim.prim_id, 4);
+
+ f3(org, 2.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, iinst1);
+ CHECK(hit.prim.geom_id, icube);
+ CHECK(hit.prim.prim_id, 4);
+
+ f3(org, 0.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 0);
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+
+ CHECK(s3d_scene_attach_shape(scn2, plane), RES_OK);
+ CHECK(s3d_mesh_set_hit_filter_function(plane, filter, NULL), RES_OK);
+
+ f3(org, 0.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 0);
+
+ CHECK(s3d_scene_view_ref_put(scnview3), RES_OK);
+ CHECK(s3d_scene_view_create(scn3, S3D_TRACE, &scnview3), RES_OK);
+
+ f3(org, -1.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+
+ f3(org, -1.5f, 0.75f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, iinst0);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 1);
+
+ f3(org, 2.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+
+ f3(org, 2.5f, 0.75f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, iinst1);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 1);
+
+ f3(org, 0.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 0);
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+
+ f3(org, 0.5f, 0.75f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 1);
+ CHECK(s3d_scene_view_trace_ray(scnview3, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ f3(org, 0.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, icube);
+ CHECK(hit.prim.prim_id, 4);
+ f3(org, 0.5f, 0.75f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, S3D_INVALID_ID);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 1);
+
+ f3(org, -1.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+ f3(org, -1.5f, 0.75f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, iinst0);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 1);
+
+ f3(org, 2.5f, 0.25f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S3D_HIT_NONE(&hit), 1);
+ f3(org, 2.5f, 0.75f, 0.25f);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(hit.prim.inst_id, iinst1);
+ CHECK(hit.prim.geom_id, iplane);
+ CHECK(hit.prim.prim_id, 1);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview3), RES_OK);
+
+ CHECK(s3d_shape_ref_put(inst0), RES_OK);
+ CHECK(s3d_shape_ref_put(inst1), RES_OK);
+ CHECK(s3d_scene_ref_put(scn), RES_OK);
+ CHECK(s3d_scene_ref_put(scn2), RES_OK);
+ CHECK(s3d_scene_ref_put(scn3), RES_OK);
+}
+
+static void
+test_sample
+ (struct s3d_device* dev,
+ struct s3d_shape* cube,
+ struct s3d_shape* plane)
+{
+ #define NSAMPS 512
+ struct s3d_scene* scn;
+ struct s3d_scene* scn2;
+ struct s3d_scene* scn3;
+ struct s3d_scene_view* scnview;
+ struct s3d_scene_view* scnview3;
+ struct s3d_shape* inst0;
+ struct s3d_shape* inst1;
+ struct s3d_primitive prims[NSAMPS];
+ float u, v, w, st[2];
+ float pos[3];
+ unsigned icube;
+ unsigned iplane;
+ unsigned iinst0;
+ unsigned iinst1;
+ int nsamps_cube;
+ int nsamps_plane;
+ int nsamps_inst0;
+ int nsamps_inst1;
+ int i;
+
+ CHECK(s3d_scene_create(dev, &scn), RES_OK);
+ CHECK(s3d_scene_create(dev, &scn2), RES_OK);
+ CHECK(s3d_scene_create(dev, &scn3), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, plane), RES_OK);
+ CHECK(s3d_shape_get_id(cube, &icube), RES_OK);
+ CHECK(s3d_shape_get_id(plane, &iplane), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.f, 0.f, 0.f, &prims[0], st), RES_BAD_OP);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_sample(scnview, 0.f, 0.f, 0.f, &prims[0], st), RES_OK);
+ CHECK(prims[0].inst_id, S3D_INVALID_ID);
+ CHECK(prims[0].geom_id == icube || prims[0].geom_id == iplane, 1);
+
+ nsamps_cube = 0;
+ nsamps_plane = 0;
+ srand(0);
+ FOR_EACH(i, 0, NSAMPS) {
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview, u, v, w, &prims[i], st), RES_OK);
+ CHECK(prims[i].inst_id, S3D_INVALID_ID);
+ if(prims[i].geom_id == icube) {
+ ++nsamps_cube;
+ } else {
+ CHECK(prims[i].geom_id, iplane);
+ ++nsamps_plane;
+ }
+ }
+ NCHECK(nsamps_cube, 0);
+ NCHECK(nsamps_plane, 0);
+
+ CHECK(s3d_shape_enable(cube, 0), RES_OK);
+ srand(0);
+ FOR_EACH(i, 0, NSAMPS) {
+ struct s3d_primitive prim;
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview, u, v, w, &prim, st), RES_OK);
+ CHECK(S3D_PRIMITIVE_EQ(&prim, &prims[i]), 1);
+ }
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+
+ srand(0);
+ FOR_EACH(i, 0, NSAMPS) {
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview, u, v, w, &prims[i], st), RES_OK);
+ CHECK(prims[i].inst_id, S3D_INVALID_ID);
+ CHECK(prims[i].geom_id, iplane);
+ }
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+
+ CHECK(s3d_shape_enable(cube, 1), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn2, cube), RES_OK);
+ CHECK(s3d_scene_instantiate(scn2, &inst0), RES_OK);
+ CHECK(s3d_scene_instantiate(scn2, &inst1), RES_OK);
+ CHECK(s3d_shape_get_id(inst0, &iinst0), RES_OK);
+ CHECK(s3d_shape_get_id(inst1, &iinst1), RES_OK);
+ CHECK(s3d_instance_translate
+ (inst0, S3D_WORLD_TRANSFORM, f3(pos,-2.f, 0.f, 0.f)), RES_OK);
+ CHECK(s3d_instance_translate
+ (inst1, S3D_WORLD_TRANSFORM, f3(pos, 2.f, 0.f, 0.f)), RES_OK);
+
+ CHECK(s3d_scene_attach_shape(scn, inst0), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, inst1), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn3, inst0), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn3, inst1), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn3, S3D_SAMPLE, &scnview3), RES_OK);
+
+ CHECK(s3d_scene_detach_shape(scn2, cube), RES_OK);
+
+ nsamps_cube = 0;
+ nsamps_inst0 = 0;
+ nsamps_inst1 = 0;
+ nsamps_plane = 0;
+ srand(0);
+ FOR_EACH(i, 0, NSAMPS) {
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview, u, v, w, &prims[i], st), RES_OK);
+ if(prims[i].inst_id != S3D_INVALID_ID) {
+ CHECK(prims[i].geom_id, icube);
+ if(prims[i].inst_id == iinst0) {
+ ++nsamps_inst0;
+ } else {
+ CHECK(prims[i].inst_id, iinst1);
+ ++nsamps_inst1;
+ }
+ } else {
+ if(prims[i].geom_id == icube) {
+ ++nsamps_cube;
+ } else {
+ CHECK(prims[i].geom_id, iplane);
+ ++nsamps_plane;
+ }
+ }
+
+ }
+ NCHECK(nsamps_cube, 0);
+ NCHECK(nsamps_inst0, 0);
+ NCHECK(nsamps_inst1, 0);
+ NCHECK(nsamps_plane, 0);
+
+ nsamps_inst0 = 0;
+ nsamps_inst1 = 0;
+ srand(0);
+ FOR_EACH(i, 0, NSAMPS) {
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview3, u, v, w, &prims[i], st), RES_OK);
+ CHECK(prims[i].geom_id, icube);
+ if(prims[i].inst_id == iinst0) {
+ ++nsamps_inst0;
+ } else {
+ CHECK(prims[i].inst_id, iinst1);
+ ++nsamps_inst1;
+ }
+ }
+ NCHECK(nsamps_inst0, 0);
+ NCHECK(nsamps_inst1, 0);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+
+ nsamps_cube = 0;
+ nsamps_plane = 0;
+ srand(0);
+ FOR_EACH(i, 0, NSAMPS) {
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview, u, v, w, &prims[i], st), RES_OK);
+ CHECK(prims[i].inst_id, S3D_INVALID_ID);
+ if(prims[i].geom_id == icube) {
+ ++nsamps_cube;
+ } else {
+ CHECK(prims[i].geom_id, iplane);
+ ++nsamps_plane;
+ }
+ }
+ NCHECK(nsamps_cube, 0);
+ NCHECK(nsamps_plane, 0);
+
+ nsamps_inst0 = 0;
+ nsamps_inst1 = 0;
+ srand(0);
+ FOR_EACH(i, 0, NSAMPS) {
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview3, u, v, w, &prims[i], st), RES_OK);
+ CHECK(prims[i].geom_id, icube);
+ if(prims[i].inst_id == iinst0) {
+ ++nsamps_inst0;
+ } else {
+ CHECK(prims[i].inst_id, iinst1);
+ ++nsamps_inst1;
+ }
+ }
+ NCHECK(nsamps_inst0, 0);
+ NCHECK(nsamps_inst1, 0);
+
+ CHECK(s3d_scene_attach_shape(scn2, plane), RES_OK);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+
+ FOR_EACH(i, 0, NSAMPS) {
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview, u, v, w, &prims[i], st), RES_OK);
+ if(prims[i].inst_id != S3D_INVALID_ID) {
+ CHECK(prims[i].geom_id, iplane);
+ if(prims[i].inst_id == iinst0) {
+ ++nsamps_inst0;
+ } else {
+ CHECK(prims[i].inst_id, iinst1);
+ ++nsamps_inst1;
+ }
+ } else {
+ if(prims[i].geom_id == icube) {
+ ++nsamps_cube;
+ } else {
+ CHECK(prims[i].geom_id, iplane);
+ ++nsamps_plane;
+ }
+ }
+
+ }
+ NCHECK(nsamps_cube, 0);
+ NCHECK(nsamps_inst0, 0);
+ NCHECK(nsamps_inst1, 0);
+ NCHECK(nsamps_plane, 0);
+
+ nsamps_inst0 = 0;
+ nsamps_inst1 = 0;
+ srand(0);
+ FOR_EACH(i, 0, NSAMPS) {
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview3, u, v, w, &prims[i], st), RES_OK);
+ CHECK(prims[i].geom_id, icube);
+ if(prims[i].inst_id == iinst0) {
+ ++nsamps_inst0;
+ } else {
+ CHECK(prims[i].inst_id, iinst1);
+ ++nsamps_inst1;
+ }
+ }
+ NCHECK(nsamps_inst0, 0);
+ NCHECK(nsamps_inst1, 0);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview3), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn3, S3D_SAMPLE, &scnview3), RES_OK);
+ nsamps_inst0 = 0;
+ nsamps_inst1 = 0;
+ srand(0);
+ FOR_EACH(i, 0, NSAMPS) {
+ u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
+ CHECK(s3d_scene_view_sample(scnview3, u, v, w, &prims[i], st), RES_OK);
+ CHECK(prims[i].geom_id, iplane);
+ if(prims[i].inst_id == iinst0) {
+ ++nsamps_inst0;
+ } else {
+ CHECK(prims[i].inst_id, iinst1);
+ ++nsamps_inst1;
+ }
+ }
+ NCHECK(nsamps_inst0, 0);
+ NCHECK(nsamps_inst1, 0);
+
+ CHECK(s3d_scene_view_ref_put(scnview3), RES_OK);
+
+ CHECK(s3d_scene_ref_put(scn), RES_OK);
+ CHECK(s3d_scene_ref_put(scn2), RES_OK);
+ CHECK(s3d_scene_ref_put(scn3), RES_OK);
+ CHECK(s3d_shape_ref_put(inst0), RES_OK);
+ CHECK(s3d_shape_ref_put(inst1), RES_OK);
+}
+
+static void
+test_get_primitive
+ (struct s3d_device* dev,
+ struct s3d_shape* cube,
+ struct s3d_shape* plane)
+{
+ struct s3d_scene* scn;
+ struct s3d_scene* scn2;
+ struct s3d_scene* scn3;
+ struct s3d_scene_view* scnview;
+ struct s3d_scene_view* scnview3;
+ struct s3d_shape* inst0;
+ struct s3d_shape* inst1;
+ struct s3d_primitive prim;
+ size_t nprims;
+ unsigned i;
+ unsigned icube;
+ unsigned iplane;
+ unsigned iinst0;
+ unsigned iinst1;
+ float pos[3];
+ int cube_prims[12];
+ int plane_prims[2];
+ int inst0_prims[12];
+ int inst1_prims[12];
+
+ CHECK(s3d_scene_create(dev, &scn), RES_OK);
+ CHECK(s3d_scene_create(dev, &scn2), RES_OK);
+ CHECK(s3d_scene_create(dev, &scn3), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, plane), RES_OK);
+ CHECK(s3d_shape_get_id(cube, &icube), RES_OK);
+ CHECK(s3d_shape_get_id(plane, &iplane), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_get_primitive(scnview, 0, &prim), RES_BAD_OP);
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
+ CHECK(nprims, 14);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_GET_PRIMITIVE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
+ CHECK(nprims, 14);
+
+ memset(cube_prims, 0, sizeof(cube_prims));
+ memset(plane_prims, 0, sizeof(plane_prims));
+ FOR_EACH(i, 0, nprims) {
+ CHECK(s3d_scene_view_get_primitive(scnview, i, &prim), RES_OK);
+ CHECK(prim.inst_id, S3D_INVALID_ID);
+ CHECK(prim.scene_prim_id, i);
+ if(prim.geom_id == icube) {
+ cube_prims[prim.prim_id] = 1;
+ } else {
+ CHECK(prim.geom_id, iplane);
+ plane_prims[prim.prim_id] = 1;
+ }
+ }
+ FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
+ FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
+
+ CHECK(s3d_scene_detach_shape(scn, cube), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
+ CHECK(nprims, 14);
+ memset(cube_prims, 0, sizeof(cube_prims));
+ memset(plane_prims, 0, sizeof(plane_prims));
+ FOR_EACH(i, 0, nprims) {
+ CHECK(s3d_scene_view_get_primitive(scnview, i, &prim), RES_OK);
+ CHECK(prim.inst_id, S3D_INVALID_ID);
+ CHECK(prim.scene_prim_id, i);
+ if(prim.geom_id == icube) {
+ cube_prims[prim.prim_id] = 1;
+ } else {
+ CHECK(prim.geom_id, iplane);
+ plane_prims[prim.prim_id] = 1;
+ }
+ }
+ FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
+ FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_GET_PRIMITIVE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
+ CHECK(nprims, 2);
+ memset(plane_prims, 0, sizeof(plane_prims));
+ FOR_EACH(i, 0, nprims) {
+ CHECK(s3d_scene_view_get_primitive(scnview, i, &prim), RES_OK);
+ CHECK(prim.inst_id, S3D_INVALID_ID);
+ CHECK(prim.scene_prim_id, i);
+ CHECK(prim.geom_id, iplane);
+ plane_prims[prim.prim_id] = 1;
+ }
+ FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+
+ CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
+
+ CHECK(s3d_scene_attach_shape(scn2, plane), RES_OK);
+ CHECK(s3d_scene_instantiate(scn2, &inst0), RES_OK);
+ CHECK(s3d_scene_instantiate(scn2, &inst1), RES_OK);
+ CHECK(s3d_shape_get_id(inst0, &iinst0), RES_OK);
+ CHECK(s3d_shape_get_id(inst1, &iinst1), RES_OK);
+ CHECK(s3d_instance_translate
+ (inst0, S3D_WORLD_TRANSFORM, f3(pos,-2.f, 0.f, 0.f)), RES_OK);
+ CHECK(s3d_instance_translate
+ (inst1, S3D_WORLD_TRANSFORM, f3(pos, 2.f, 0.f, 0.f)), RES_OK);
+
+ CHECK(s3d_scene_attach_shape(scn, inst0), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn3, inst0), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn3, inst1), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_GET_PRIMITIVE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_create(scn3, S3D_GET_PRIMITIVE, &scnview3), RES_OK);
+
+ CHECK(s3d_scene_clear(scn2), RES_OK);
+
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
+ CHECK(nprims, 16);
+ memset(plane_prims, 0, sizeof(plane_prims));
+ memset(cube_prims, 0, sizeof(cube_prims));
+ memset(inst0_prims, 0, sizeof(inst0_prims));
+ FOR_EACH(i, 0, nprims) {
+ CHECK(s3d_scene_view_get_primitive(scnview, i, &prim), RES_OK);
+ if(prim.inst_id != S3D_INVALID_ID) {
+ CHECK(prim.inst_id, iinst0);
+ CHECK(prim.geom_id, iplane);
+ inst0_prims[prim.prim_id] = 1;
+ } else {
+ if(prim.geom_id == icube) {
+ cube_prims[prim.prim_id] = 1;
+ } else {
+ CHECK(prim.geom_id, iplane);
+ plane_prims[prim.prim_id] = 1;
+ }
+ }
+ }
+ FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
+ FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
+ FOR_EACH(i, 0, 2) CHECK(inst0_prims[i], 1);
+
+ CHECK(s3d_scene_view_primitives_count(scnview3, &nprims), RES_OK);
+ CHECK(nprims, 4);
+ memset(inst0_prims, 0, sizeof(inst0_prims));
+ memset(inst1_prims, 0, sizeof(inst1_prims));
+ FOR_EACH(i, 0, nprims) {
+ CHECK(s3d_scene_view_get_primitive(scnview3, i, &prim), RES_OK);
+ NCHECK(prim.inst_id, S3D_INVALID_ID);
+ CHECK(prim.geom_id, iplane);
+ if(prim.inst_id == iinst0) {
+ inst0_prims[prim.prim_id] = 1;
+ } else {
+ CHECK(prim.inst_id, iinst1);
+ inst1_prims[prim.prim_id] = 1;
+ }
+ }
+ FOR_EACH(i, 0, 2) CHECK(inst1_prims[i], 1);
+ FOR_EACH(i, 0, 2) CHECK(inst1_prims[i], 1);
+
+ CHECK(s3d_scene_view_ref_put(scnview3), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn3, S3D_GET_PRIMITIVE, &scnview3), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(scnview3, &nprims), RES_OK);
+ CHECK(nprims, 0);
+ CHECK(s3d_scene_view_ref_put(scnview3), RES_OK);
+
+ CHECK(s3d_scene_attach_shape(scn2, cube), RES_OK);
+ CHECK(s3d_scene_view_create(scn3, S3D_GET_PRIMITIVE, &scnview3), RES_OK);
+
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
+ CHECK(nprims, 16);
+ memset(plane_prims, 0, sizeof(plane_prims));
+ memset(cube_prims, 0, sizeof(cube_prims));
+ memset(inst0_prims, 0, sizeof(inst0_prims));
+ FOR_EACH(i, 0, nprims) {
+ CHECK(s3d_scene_view_get_primitive(scnview, i, &prim), RES_OK);
+ if(prim.inst_id != S3D_INVALID_ID) {
+ CHECK(prim.inst_id, iinst0);
+ CHECK(prim.geom_id, iplane);
+ inst0_prims[prim.prim_id] = 1;
+ } else {
+ if(prim.geom_id == icube) {
+ cube_prims[prim.prim_id] = 1;
+ } else {
+ CHECK(prim.geom_id, iplane);
+ plane_prims[prim.prim_id] = 1;
+ }
+ }
+ }
+ FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
+ FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
+ FOR_EACH(i, 0, 2) CHECK(inst0_prims[i], 1);
+
+ CHECK(s3d_scene_view_primitives_count(scnview3, &nprims), RES_OK);
+ CHECK(nprims, 24);
+ memset(inst0_prims, 0, sizeof(inst0_prims));
+ memset(inst1_prims, 0, sizeof(inst1_prims));
+ FOR_EACH(i, 0, nprims) {
+ CHECK(s3d_scene_view_get_primitive(scnview3, i, &prim), RES_OK);
+ NCHECK(prim.inst_id, S3D_INVALID_ID);
+ CHECK(prim.geom_id, icube);
+ if(prim.inst_id == iinst0) {
+ inst0_prims[prim.prim_id] = 1;
+ } else {
+ CHECK(prim.inst_id, iinst1);
+ inst1_prims[prim.prim_id] = 1;
+ }
+ }
+ FOR_EACH(i, 0, 12) CHECK(inst1_prims[i], 1);
+ FOR_EACH(i, 0, 12) CHECK(inst1_prims[i], 1);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview3), RES_OK);
+
+ CHECK(s3d_scene_view_create(scn, S3D_GET_PRIMITIVE, &scnview), RES_OK);
+
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
+ CHECK(nprims, 26);
+ memset(plane_prims, 0, sizeof(plane_prims));
+ memset(cube_prims, 0, sizeof(cube_prims));
+ memset(inst0_prims, 0, sizeof(inst0_prims));
+ FOR_EACH(i, 0, nprims) {
+ CHECK(s3d_scene_view_get_primitive(scnview, i, &prim), RES_OK);
+ if(prim.inst_id != S3D_INVALID_ID) {
+ CHECK(prim.inst_id, iinst0);
+ CHECK(prim.geom_id, icube);
+ inst0_prims[prim.prim_id] = 1;
+ } else {
+ if(prim.geom_id == icube) {
+ cube_prims[prim.prim_id] = 1;
+ } else {
+ CHECK(prim.geom_id, iplane);
+ plane_prims[prim.prim_id] = 1;
+ }
+ }
+ }
+ FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
+ FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
+ FOR_EACH(i, 0, 12) CHECK(inst0_prims[i], 1);
+
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
+
+ CHECK(s3d_shape_ref_put(inst0), RES_OK);
+ CHECK(s3d_shape_ref_put(inst1), RES_OK);
+ CHECK(s3d_scene_ref_put(scn), RES_OK);
+ CHECK(s3d_scene_ref_put(scn2), RES_OK);
+ CHECK(s3d_scene_ref_put(scn3), RES_OK);
+}
+
+/*******************************************************************************
+ * Main test function
+ ******************************************************************************/
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct mesh_context ctx;
+ struct s3d_device* dev;
+ struct s3d_shape* cube;
+ struct s3d_shape* plane;
+ struct s3d_vertex_data vdata;
+ (void)argc, (void)argv;
+
+ mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+
+ CHECK(s3d_device_create(NULL, &allocator, 1, &dev), RES_OK);
+
+ vdata.type = S3D_FLOAT3;
+ vdata.usage = S3D_POSITION;
+ vdata.get = get_pos;
+
+ ctx.ids = cube_ids;
+ ctx.verts = cube_verts;
+ CHECK(s3d_shape_create_mesh(dev, &cube), RES_OK);
+ CHECK(s3d_mesh_setup_indexed_vertices
+ (cube, cube_ntris, get_ids, cube_nverts, &vdata, 1, &ctx), RES_OK);
+
+ ctx.ids = plane_ids;
+ ctx.verts = plane_verts;
+ CHECK(s3d_shape_create_mesh(dev, &plane), RES_OK);
+ CHECK(s3d_mesh_setup_indexed_vertices
+ (plane, plane_ntris, get_ids, plane_nverts, &vdata, 1, &ctx), RES_OK);
+
+ test_miscellaneous(dev, cube, plane);
+ test_trace_ray(dev, cube, plane);
+ test_sample(dev, cube, plane);
+ test_get_primitive(dev, cube, plane);
+
+ CHECK(s3d_shape_ref_put(cube), RES_OK);
+ CHECK(s3d_shape_ref_put(plane), RES_OK);
+ CHECK(s3d_device_ref_put(dev), RES_OK);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}
+
diff --git a/src/test_s3d_session.c b/src/test_s3d_session.c
@@ -1,1048 +0,0 @@
-/* Copyright (C) |Meso|Star> 2015-2016 (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.h"
-#include "test_s3d_utils.h"
-
-#include <rsys/float3.h>
-#include <rsys/float2.h>
-
-#include <string.h>
-
-struct mesh_context {
- const float* verts;
- const unsigned* ids;
-};
-
-static int
-filter
- (const struct s3d_hit* hit,
- const float org[3],
- const float dir[3],
- void* ray_data,
- void* filter_data)
-{
- (void)org, (void)dir, (void)ray_data, (void)filter_data;
- CHECK(S3D_HIT_NONE(hit), 0);
- return hit->prim.prim_id % 2 == 0;
-}
-
-/*******************************************************************************
- * Cube data
- ******************************************************************************/
-static const float cube_verts[] = {
- 0.f, 0.f, 0.f,
- 1.f, 0.f, 0.f,
- 0.f, 1.f, 0.f,
- 1.f, 1.f, 0.f,
- 0.f, 0.f, 1.f,
- 1.f, 0.f, 1.f,
- 0.f, 1.f, 1.f,
- 1.f, 1.f, 1.f
-};
-static const unsigned cube_nverts = sizeof(cube_verts) / sizeof(float[3]);
-
-/* Front faces are CW. The normals point into the cube */
-static const unsigned cube_ids[] = {
- 0, 2, 1, 1, 2, 3, /* Front */
- 0, 4, 2, 2, 4, 6, /* Left */
- 4, 5, 6, 6, 5, 7, /* Back */
- 3, 7, 1, 1, 7, 5, /* Right */
- 2, 6, 3, 3, 6, 7, /* Top */
- 0, 1, 4, 4, 1, 5 /* Bottom */
-};
-static const unsigned cube_ntris = sizeof(cube_ids) / sizeof(unsigned[3]);
-
-/*******************************************************************************
- * Plane data
- ******************************************************************************/
-static const float plane_verts[] = {
- 0.f, 0.f, 0.5f,
- 1.f, 0.f, 0.5f,
- 1.f, 1.f, 0.5f,
- 0.f, 1.f, 0.5f
-};
-static const unsigned plane_nverts = sizeof(plane_verts) / sizeof(float[3]);
-
-static const unsigned plane_ids[] = { 0, 1, 2, 2, 3, 0 };
-static const unsigned plane_ntris = sizeof(plane_ids) / sizeof(unsigned[3]);
-
-/*******************************************************************************
- * helper function
- ******************************************************************************/
-static float
-rand_canonic(void)
-{
- int r;
- while((r = rand()) == RAND_MAX);
- return (float)r / (float)RAND_MAX;
-}
-
-static void
-get_ids(const unsigned itri, unsigned ids[3], void* data)
-{
- const unsigned id = itri * 3;
- const struct mesh_context* ctx = data;
- NCHECK(ctx, NULL);
- NCHECK(ids, NULL);
- ids[0] = ctx->ids[id + 0];
- ids[1] = ctx->ids[id + 1];
- ids[2] = ctx->ids[id + 2];
-}
-
-static void
-get_pos(const unsigned ivert, float pos[3], void* data)
-{
- const unsigned i = ivert*3;
- const struct mesh_context* ctx = data;
- NCHECK(ctx, NULL);
- NCHECK(pos, NULL);
- pos[0] = ctx->verts[i + 0];
- pos[1] = ctx->verts[i + 1];
- pos[2] = ctx->verts[i + 2];
-}
-
-static void
-test_miscellaneous
- (struct s3d_device* dev,
- struct s3d_shape* cube,
- struct s3d_shape* plane)
-{
- struct s3d_scene* scn;
- struct s3d_session* session;
- int mask;
-
- CHECK(s3d_scene_create(dev, &scn), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, plane), RES_OK);
-
- CHECK(s3d_session_create(NULL, 0, NULL), RES_BAD_ARG);
- CHECK(s3d_session_create(scn, 0, NULL), RES_BAD_ARG);
- CHECK(s3d_session_create(NULL, S3D_SAMPLE, NULL), RES_BAD_ARG);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, NULL), RES_BAD_ARG);
- CHECK(s3d_session_create(NULL, 0, &session), RES_BAD_ARG);
- CHECK(s3d_session_create(scn, 0, &session), RES_BAD_ARG);
- CHECK(s3d_session_create(NULL, S3D_SAMPLE, &session), RES_BAD_ARG);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
-
- CHECK(s3d_session_get_mask(NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_mask(session, NULL), RES_BAD_ARG);
- CHECK(s3d_session_get_mask(NULL, &mask), RES_BAD_ARG);
- CHECK(s3d_session_get_mask(session, &mask), RES_OK);
- CHECK(mask, S3D_SAMPLE);
-
- CHECK(s3d_session_ref_get(NULL), RES_BAD_ARG);
- CHECK(s3d_session_ref_get(session), RES_OK);
- CHECK(s3d_session_ref_put(NULL), RES_BAD_ARG);
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_ref_put(session), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_TRACE|S3D_GET_PRIMITIVE, &session), RES_OK);
- CHECK(s3d_session_get_mask(session, &mask), RES_OK);
- CHECK(mask & S3D_TRACE, S3D_TRACE);
- CHECK(mask & S3D_GET_PRIMITIVE, S3D_GET_PRIMITIVE);
- CHECK(s3d_session_ref_put(session), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_SAMPLE|S3D_GET_PRIMITIVE, &session), RES_OK);
- CHECK(s3d_session_get_mask(session, &mask), RES_OK);
- CHECK(mask & S3D_SAMPLE, S3D_SAMPLE);
- CHECK(mask & S3D_GET_PRIMITIVE, S3D_GET_PRIMITIVE);
- CHECK(s3d_session_ref_put(session), RES_OK);
-
- CHECK(s3d_scene_ref_put(scn), RES_OK);
-}
-
-static void
-test_trace_ray
- (struct s3d_device* dev,
- struct s3d_shape* cube,
- struct s3d_shape* plane)
-{
- struct s3d_scene* scn;
- struct s3d_scene* scn2;
- struct s3d_scene* scn3;
- struct s3d_session* session;
- struct s3d_session* session2;
- struct s3d_session* session3;
- struct s3d_shape* inst0;
- struct s3d_shape* inst1;
- struct s3d_hit hit, hit2;
- float org[3], dir[3], range[2];
- unsigned icube;
- unsigned iplane;
- unsigned iinst0;
- unsigned iinst1;
-
- CHECK(s3d_shape_get_id(cube, &icube), RES_OK);
- CHECK(s3d_shape_get_id(plane, &iplane), RES_OK);
-
- CHECK(s3d_scene_create(dev, &scn), RES_OK);
- CHECK(s3d_scene_create(dev, &scn2), RES_OK);
- CHECK(s3d_scene_create(dev, &scn3), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, plane), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
- CHECK(s3d_scene_attach_shape(scn2, cube), RES_OK);
- CHECK(s3d_scene_attach_shape(scn2, plane), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_SAMPLE|S3D_GET_PRIMITIVE, &session), RES_OK);
-
- f3(org, 0.5f, 0.25f, 0.25f);
- f3(dir, 0.f, 0.f, 1.f);
- f2(range, 0.f, FLT_MAX);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_BAD_OP);
-
- CHECK(s3d_session_create(scn, S3D_TRACE, &session2), RES_OK);
- CHECK(s3d_session_trace_ray(session2, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 0);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 0);
-
- f3(dir, 0.f, 0.f, -1.f);
- CHECK(s3d_session_trace_ray(session2, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 0);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, icube);
- CHECK(hit.prim.prim_id, 0);
- f3(dir, 0.f, 0.f, 1.f);
-
- CHECK(s3d_shape_enable(plane, 0), RES_OK);
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
-
- CHECK(s3d_session_trace_ray(session2, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 0);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 0);
-
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 0);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, icube);
- CHECK(hit.prim.prim_id, 4);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_ref_put(session2), RES_OK);
- CHECK(s3d_shape_enable(plane, 1), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_create(scn2, S3D_TRACE, &session2), RES_OK);
-
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(s3d_session_trace_ray(session2, org, dir, range, NULL, &hit2), RES_OK);
- CHECK(f3_eq(hit.normal, hit2.normal), 1);
- CHECK(f2_eq(hit.uv, hit2.uv), 1);
- CHECK(hit.distance, hit2.distance);
- CHECK(S3D_PRIMITIVE_EQ(&hit.prim, &hit2.prim), 1);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 0);
-
- CHECK(s3d_scene_detach_shape(scn2, plane), RES_OK);
- CHECK(s3d_session_trace_ray(session2, org, dir, range, NULL, &hit2), RES_OK);
- CHECK(f3_eq(hit.normal, hit2.normal), 1);
- CHECK(f2_eq(hit.uv, hit2.uv), 1);
- CHECK(hit.distance, hit2.distance);
- CHECK(S3D_PRIMITIVE_EQ(&hit.prim, &hit2.prim), 1);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_ref_put(session2), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_create(scn2, S3D_TRACE, &session2), RES_OK);
-
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(f3_eq(hit.normal, hit2.normal), 1);
- CHECK(f2_eq(hit.uv, hit2.uv), 1);
- CHECK(hit.distance, hit2.distance);
- CHECK(S3D_PRIMITIVE_EQ(&hit.prim, &hit2.prim), 1);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 0);
-
- CHECK(s3d_session_trace_ray(session2, org, dir, range, NULL, &hit2), RES_OK);
- CHECK(hit2.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit2.prim.geom_id, icube);
- CHECK(hit2.prim.prim_id, 4);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_ref_put(session2), RES_OK);
-
- CHECK(s3d_scene_instantiate(scn2, &inst0), RES_OK);
- CHECK(s3d_scene_instantiate(scn2, &inst1), RES_OK);
- CHECK(s3d_shape_get_id(inst0, &iinst0), RES_OK);
- CHECK(s3d_shape_get_id(inst1, &iinst1), RES_OK);
- CHECK(s3d_instance_translate
- (inst0, S3D_WORLD_TRANSFORM, f3(org,-2.f, 0.f, 0.f)), RES_OK);
- CHECK(s3d_instance_translate
- (inst1, S3D_WORLD_TRANSFORM, f3(org, 2.f, 0.f, 0.f)), RES_OK);
-
- CHECK(s3d_scene_attach_shape(scn3, inst0), RES_OK);
- CHECK(s3d_scene_attach_shape(scn3, inst1), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, inst0), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, inst1), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_create(scn3, S3D_TRACE, &session3), RES_OK);
-
- f3(org, 0.5f, 0.25f, 0.25f);
- f3(dir, 0.f, 0.f, 1.f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 0);
-
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
-
- f3(org, -1.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, iinst0);
- CHECK(hit.prim.geom_id, icube);
- CHECK(hit.prim.prim_id, 4);
-
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit2), RES_OK);
- CHECK(hit2.prim.inst_id, iinst0);
- CHECK(hit2.prim.geom_id, icube);
- CHECK(hit2.prim.prim_id, 4);
-
- CHECK(f3_eq(hit.normal, hit2.normal), 1);
- CHECK(f2_eq(hit.uv, hit2.uv), 1);
- CHECK(hit.distance, hit2.distance);
-
- CHECK(s3d_scene_clear(scn2), RES_OK);
-
- f3(org, 2.5f, 0.25f, 0.25f);
-
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, iinst1);
- CHECK(hit.prim.geom_id, icube);
- CHECK(hit.prim.prim_id, 4);
-
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit2), RES_OK);
- CHECK(hit2.prim.inst_id, iinst1);
- CHECK(hit2.prim.geom_id, icube);
- CHECK(hit2.prim.prim_id, 4);
-
- CHECK(f3_eq(hit.normal, hit2.normal), 1);
- CHECK(f2_eq(hit.uv, hit2.uv), 1);
- CHECK(hit.distance, hit2.distance);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
-
- f3(org, -1.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, iinst0);
- CHECK(hit.prim.geom_id, icube);
- CHECK(hit.prim.prim_id, 4);
-
- f3(org, 2.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, iinst1);
- CHECK(hit.prim.geom_id, icube);
- CHECK(hit.prim.prim_id, 4);
-
- f3(org, 0.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 0);
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
-
- CHECK(s3d_scene_attach_shape(scn2, plane), RES_OK);
- CHECK(s3d_mesh_set_hit_filter_function(plane, filter, NULL), RES_OK);
-
- f3(org, 0.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 0);
-
- CHECK(s3d_session_ref_put(session3), RES_OK);
- CHECK(s3d_session_create(scn3, S3D_TRACE, &session3), RES_OK);
-
- f3(org, -1.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
-
- f3(org, -1.5f, 0.75f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, iinst0);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 1);
-
- f3(org, 2.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
-
- f3(org, 2.5f, 0.75f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, iinst1);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 1);
-
- f3(org, 0.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 0);
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
-
- f3(org, 0.5f, 0.75f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 1);
- CHECK(s3d_session_trace_ray(session3, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- f3(org, 0.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, icube);
- CHECK(hit.prim.prim_id, 4);
- f3(org, 0.5f, 0.75f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, S3D_INVALID_ID);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 1);
-
- f3(org, -1.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
- f3(org, -1.5f, 0.75f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, iinst0);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 1);
-
- f3(org, 2.5f, 0.25f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(S3D_HIT_NONE(&hit), 1);
- f3(org, 2.5f, 0.75f, 0.25f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(hit.prim.inst_id, iinst1);
- CHECK(hit.prim.geom_id, iplane);
- CHECK(hit.prim.prim_id, 1);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_ref_put(session3), RES_OK);
-
- CHECK(s3d_shape_ref_put(inst0), RES_OK);
- CHECK(s3d_shape_ref_put(inst1), RES_OK);
- CHECK(s3d_scene_ref_put(scn), RES_OK);
- CHECK(s3d_scene_ref_put(scn2), RES_OK);
- CHECK(s3d_scene_ref_put(scn3), RES_OK);
-}
-
-static void
-test_sample
- (struct s3d_device* dev,
- struct s3d_shape* cube,
- struct s3d_shape* plane)
-{
- #define NSAMPS 512
- struct s3d_scene* scn;
- struct s3d_scene* scn2;
- struct s3d_scene* scn3;
- struct s3d_session* session;
- struct s3d_session* session3;
- struct s3d_shape* inst0;
- struct s3d_shape* inst1;
- struct s3d_primitive prims[NSAMPS];
- float u, v, w, st[2];
- float pos[3];
- unsigned icube;
- unsigned iplane;
- unsigned iinst0;
- unsigned iinst1;
- int nsamps_cube;
- int nsamps_plane;
- int nsamps_inst0;
- int nsamps_inst1;
- int i;
-
- CHECK(s3d_scene_create(dev, &scn), RES_OK);
- CHECK(s3d_scene_create(dev, &scn2), RES_OK);
- CHECK(s3d_scene_create(dev, &scn3), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, plane), RES_OK);
- CHECK(s3d_shape_get_id(cube, &icube), RES_OK);
- CHECK(s3d_shape_get_id(plane, &iplane), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_sample(session, 0.f, 0.f, 0.f, &prims[0], st), RES_BAD_OP);
- CHECK(s3d_session_ref_put(session), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_sample(session, 0.f, 0.f, 0.f, &prims[0], st), RES_OK);
- CHECK(prims[0].inst_id, S3D_INVALID_ID);
- CHECK(prims[0].geom_id == icube || prims[0].geom_id == iplane, 1);
-
- nsamps_cube = 0;
- nsamps_plane = 0;
- srand(0);
- FOR_EACH(i, 0, NSAMPS) {
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session, u, v, w, &prims[i], st), RES_OK);
- CHECK(prims[i].inst_id, S3D_INVALID_ID);
- if(prims[i].geom_id == icube) {
- ++nsamps_cube;
- } else {
- CHECK(prims[i].geom_id, iplane);
- ++nsamps_plane;
- }
- }
- NCHECK(nsamps_cube, 0);
- NCHECK(nsamps_plane, 0);
-
- CHECK(s3d_shape_enable(cube, 0), RES_OK);
- srand(0);
- FOR_EACH(i, 0, NSAMPS) {
- struct s3d_primitive prim;
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session, u, v, w, &prim, st), RES_OK);
- CHECK(S3D_PRIMITIVE_EQ(&prim, &prims[i]), 1);
- }
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
-
- srand(0);
- FOR_EACH(i, 0, NSAMPS) {
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session, u, v, w, &prims[i], st), RES_OK);
- CHECK(prims[i].inst_id, S3D_INVALID_ID);
- CHECK(prims[i].geom_id, iplane);
- }
-
- CHECK(s3d_session_ref_put(session), RES_OK);
-
- CHECK(s3d_shape_enable(cube, 1), RES_OK);
- CHECK(s3d_scene_attach_shape(scn2, cube), RES_OK);
- CHECK(s3d_scene_instantiate(scn2, &inst0), RES_OK);
- CHECK(s3d_scene_instantiate(scn2, &inst1), RES_OK);
- CHECK(s3d_shape_get_id(inst0, &iinst0), RES_OK);
- CHECK(s3d_shape_get_id(inst1, &iinst1), RES_OK);
- CHECK(s3d_instance_translate
- (inst0, S3D_WORLD_TRANSFORM, f3(pos,-2.f, 0.f, 0.f)), RES_OK);
- CHECK(s3d_instance_translate
- (inst1, S3D_WORLD_TRANSFORM, f3(pos, 2.f, 0.f, 0.f)), RES_OK);
-
- CHECK(s3d_scene_attach_shape(scn, inst0), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, inst1), RES_OK);
- CHECK(s3d_scene_attach_shape(scn3, inst0), RES_OK);
- CHECK(s3d_scene_attach_shape(scn3, inst1), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_create(scn3, S3D_SAMPLE, &session3), RES_OK);
-
- CHECK(s3d_scene_detach_shape(scn2, cube), RES_OK);
-
- nsamps_cube = 0;
- nsamps_inst0 = 0;
- nsamps_inst1 = 0;
- nsamps_plane = 0;
- srand(0);
- FOR_EACH(i, 0, NSAMPS) {
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session, u, v, w, &prims[i], st), RES_OK);
- if(prims[i].inst_id != S3D_INVALID_ID) {
- CHECK(prims[i].geom_id, icube);
- if(prims[i].inst_id == iinst0) {
- ++nsamps_inst0;
- } else {
- CHECK(prims[i].inst_id, iinst1);
- ++nsamps_inst1;
- }
- } else {
- if(prims[i].geom_id == icube) {
- ++nsamps_cube;
- } else {
- CHECK(prims[i].geom_id, iplane);
- ++nsamps_plane;
- }
- }
-
- }
- NCHECK(nsamps_cube, 0);
- NCHECK(nsamps_inst0, 0);
- NCHECK(nsamps_inst1, 0);
- NCHECK(nsamps_plane, 0);
-
- nsamps_inst0 = 0;
- nsamps_inst1 = 0;
- srand(0);
- FOR_EACH(i, 0, NSAMPS) {
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session3, u, v, w, &prims[i], st), RES_OK);
- CHECK(prims[i].geom_id, icube);
- if(prims[i].inst_id == iinst0) {
- ++nsamps_inst0;
- } else {
- CHECK(prims[i].inst_id, iinst1);
- ++nsamps_inst1;
- }
- }
- NCHECK(nsamps_inst0, 0);
- NCHECK(nsamps_inst1, 0);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
-
- nsamps_cube = 0;
- nsamps_plane = 0;
- srand(0);
- FOR_EACH(i, 0, NSAMPS) {
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session, u, v, w, &prims[i], st), RES_OK);
- CHECK(prims[i].inst_id, S3D_INVALID_ID);
- if(prims[i].geom_id == icube) {
- ++nsamps_cube;
- } else {
- CHECK(prims[i].geom_id, iplane);
- ++nsamps_plane;
- }
- }
- NCHECK(nsamps_cube, 0);
- NCHECK(nsamps_plane, 0);
-
- nsamps_inst0 = 0;
- nsamps_inst1 = 0;
- srand(0);
- FOR_EACH(i, 0, NSAMPS) {
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session3, u, v, w, &prims[i], st), RES_OK);
- CHECK(prims[i].geom_id, icube);
- if(prims[i].inst_id == iinst0) {
- ++nsamps_inst0;
- } else {
- CHECK(prims[i].inst_id, iinst1);
- ++nsamps_inst1;
- }
- }
- NCHECK(nsamps_inst0, 0);
- NCHECK(nsamps_inst1, 0);
-
- CHECK(s3d_scene_attach_shape(scn2, plane), RES_OK);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
-
- FOR_EACH(i, 0, NSAMPS) {
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session, u, v, w, &prims[i], st), RES_OK);
- if(prims[i].inst_id != S3D_INVALID_ID) {
- CHECK(prims[i].geom_id, iplane);
- if(prims[i].inst_id == iinst0) {
- ++nsamps_inst0;
- } else {
- CHECK(prims[i].inst_id, iinst1);
- ++nsamps_inst1;
- }
- } else {
- if(prims[i].geom_id == icube) {
- ++nsamps_cube;
- } else {
- CHECK(prims[i].geom_id, iplane);
- ++nsamps_plane;
- }
- }
-
- }
- NCHECK(nsamps_cube, 0);
- NCHECK(nsamps_inst0, 0);
- NCHECK(nsamps_inst1, 0);
- NCHECK(nsamps_plane, 0);
-
- nsamps_inst0 = 0;
- nsamps_inst1 = 0;
- srand(0);
- FOR_EACH(i, 0, NSAMPS) {
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session3, u, v, w, &prims[i], st), RES_OK);
- CHECK(prims[i].geom_id, icube);
- if(prims[i].inst_id == iinst0) {
- ++nsamps_inst0;
- } else {
- CHECK(prims[i].inst_id, iinst1);
- ++nsamps_inst1;
- }
- }
- NCHECK(nsamps_inst0, 0);
- NCHECK(nsamps_inst1, 0);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_ref_put(session3), RES_OK);
-
- CHECK(s3d_session_create(scn3, S3D_SAMPLE, &session3), RES_OK);
- nsamps_inst0 = 0;
- nsamps_inst1 = 0;
- srand(0);
- FOR_EACH(i, 0, NSAMPS) {
- u = rand_canonic(), v = rand_canonic(), w = rand_canonic();
- CHECK(s3d_session_sample(session3, u, v, w, &prims[i], st), RES_OK);
- CHECK(prims[i].geom_id, iplane);
- if(prims[i].inst_id == iinst0) {
- ++nsamps_inst0;
- } else {
- CHECK(prims[i].inst_id, iinst1);
- ++nsamps_inst1;
- }
- }
- NCHECK(nsamps_inst0, 0);
- NCHECK(nsamps_inst1, 0);
-
- CHECK(s3d_session_ref_put(session3), RES_OK);
-
- CHECK(s3d_scene_ref_put(scn), RES_OK);
- CHECK(s3d_scene_ref_put(scn2), RES_OK);
- CHECK(s3d_scene_ref_put(scn3), RES_OK);
- CHECK(s3d_shape_ref_put(inst0), RES_OK);
- CHECK(s3d_shape_ref_put(inst1), RES_OK);
-}
-
-static void
-test_get_primitive
- (struct s3d_device* dev,
- struct s3d_shape* cube,
- struct s3d_shape* plane)
-{
- struct s3d_scene* scn;
- struct s3d_scene* scn2;
- struct s3d_scene* scn3;
- struct s3d_session* session;
- struct s3d_session* session3;
- struct s3d_shape* inst0;
- struct s3d_shape* inst1;
- struct s3d_primitive prim;
- size_t nprims;
- unsigned i;
- unsigned icube;
- unsigned iplane;
- unsigned iinst0;
- unsigned iinst1;
- float pos[3];
- int cube_prims[12];
- int plane_prims[2];
- int inst0_prims[12];
- int inst1_prims[12];
-
- CHECK(s3d_scene_create(dev, &scn), RES_OK);
- CHECK(s3d_scene_create(dev, &scn2), RES_OK);
- CHECK(s3d_scene_create(dev, &scn3), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
- CHECK(s3d_scene_attach_shape(scn, plane), RES_OK);
- CHECK(s3d_shape_get_id(cube, &icube), RES_OK);
- CHECK(s3d_shape_get_id(plane, &iplane), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_get_primitive(session, 0, &prim), RES_BAD_OP);
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
- CHECK(nprims, 14);
- CHECK(s3d_session_ref_put(session), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_GET_PRIMITIVE, &session), RES_OK);
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
- CHECK(nprims, 14);
-
- memset(cube_prims, 0, sizeof(cube_prims));
- memset(plane_prims, 0, sizeof(plane_prims));
- FOR_EACH(i, 0, nprims) {
- CHECK(s3d_session_get_primitive(session, i, &prim), RES_OK);
- CHECK(prim.inst_id, S3D_INVALID_ID);
- CHECK(prim.scene_prim_id, i);
- if(prim.geom_id == icube) {
- cube_prims[prim.prim_id] = 1;
- } else {
- CHECK(prim.geom_id, iplane);
- plane_prims[prim.prim_id] = 1;
- }
- }
- FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
- FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
-
- CHECK(s3d_scene_detach_shape(scn, cube), RES_OK);
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
- CHECK(nprims, 14);
- memset(cube_prims, 0, sizeof(cube_prims));
- memset(plane_prims, 0, sizeof(plane_prims));
- FOR_EACH(i, 0, nprims) {
- CHECK(s3d_session_get_primitive(session, i, &prim), RES_OK);
- CHECK(prim.inst_id, S3D_INVALID_ID);
- CHECK(prim.scene_prim_id, i);
- if(prim.geom_id == icube) {
- cube_prims[prim.prim_id] = 1;
- } else {
- CHECK(prim.geom_id, iplane);
- plane_prims[prim.prim_id] = 1;
- }
- }
- FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
- FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_create(scn, S3D_GET_PRIMITIVE, &session), RES_OK);
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
- CHECK(nprims, 2);
- memset(plane_prims, 0, sizeof(plane_prims));
- FOR_EACH(i, 0, nprims) {
- CHECK(s3d_session_get_primitive(session, i, &prim), RES_OK);
- CHECK(prim.inst_id, S3D_INVALID_ID);
- CHECK(prim.scene_prim_id, i);
- CHECK(prim.geom_id, iplane);
- plane_prims[prim.prim_id] = 1;
- }
- FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
-
- CHECK(s3d_scene_attach_shape(scn, cube), RES_OK);
-
- CHECK(s3d_scene_attach_shape(scn2, plane), RES_OK);
- CHECK(s3d_scene_instantiate(scn2, &inst0), RES_OK);
- CHECK(s3d_scene_instantiate(scn2, &inst1), RES_OK);
- CHECK(s3d_shape_get_id(inst0, &iinst0), RES_OK);
- CHECK(s3d_shape_get_id(inst1, &iinst1), RES_OK);
- CHECK(s3d_instance_translate
- (inst0, S3D_WORLD_TRANSFORM, f3(pos,-2.f, 0.f, 0.f)), RES_OK);
- CHECK(s3d_instance_translate
- (inst1, S3D_WORLD_TRANSFORM, f3(pos, 2.f, 0.f, 0.f)), RES_OK);
-
- CHECK(s3d_scene_attach_shape(scn, inst0), RES_OK);
- CHECK(s3d_scene_attach_shape(scn3, inst0), RES_OK);
- CHECK(s3d_scene_attach_shape(scn3, inst1), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_GET_PRIMITIVE, &session), RES_OK);
- CHECK(s3d_session_create(scn3, S3D_GET_PRIMITIVE, &session3), RES_OK);
-
- CHECK(s3d_scene_clear(scn2), RES_OK);
-
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
- CHECK(nprims, 16);
- memset(plane_prims, 0, sizeof(plane_prims));
- memset(cube_prims, 0, sizeof(cube_prims));
- memset(inst0_prims, 0, sizeof(inst0_prims));
- FOR_EACH(i, 0, nprims) {
- CHECK(s3d_session_get_primitive(session, i, &prim), RES_OK);
- if(prim.inst_id != S3D_INVALID_ID) {
- CHECK(prim.inst_id, iinst0);
- CHECK(prim.geom_id, iplane);
- inst0_prims[prim.prim_id] = 1;
- } else {
- if(prim.geom_id == icube) {
- cube_prims[prim.prim_id] = 1;
- } else {
- CHECK(prim.geom_id, iplane);
- plane_prims[prim.prim_id] = 1;
- }
- }
- }
- FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
- FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
- FOR_EACH(i, 0, 2) CHECK(inst0_prims[i], 1);
-
- CHECK(s3d_session_primitives_count(session3, &nprims), RES_OK);
- CHECK(nprims, 4);
- memset(inst0_prims, 0, sizeof(inst0_prims));
- memset(inst1_prims, 0, sizeof(inst1_prims));
- FOR_EACH(i, 0, nprims) {
- CHECK(s3d_session_get_primitive(session3, i, &prim), RES_OK);
- NCHECK(prim.inst_id, S3D_INVALID_ID);
- CHECK(prim.geom_id, iplane);
- if(prim.inst_id == iinst0) {
- inst0_prims[prim.prim_id] = 1;
- } else {
- CHECK(prim.inst_id, iinst1);
- inst1_prims[prim.prim_id] = 1;
- }
- }
- FOR_EACH(i, 0, 2) CHECK(inst1_prims[i], 1);
- FOR_EACH(i, 0, 2) CHECK(inst1_prims[i], 1);
-
- CHECK(s3d_session_ref_put(session3), RES_OK);
-
- CHECK(s3d_session_create(scn3, S3D_GET_PRIMITIVE, &session3), RES_OK);
- CHECK(s3d_session_primitives_count(session3, &nprims), RES_OK);
- CHECK(nprims, 0);
- CHECK(s3d_session_ref_put(session3), RES_OK);
-
- CHECK(s3d_scene_attach_shape(scn2, cube), RES_OK);
- CHECK(s3d_session_create(scn3, S3D_GET_PRIMITIVE, &session3), RES_OK);
-
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
- CHECK(nprims, 16);
- memset(plane_prims, 0, sizeof(plane_prims));
- memset(cube_prims, 0, sizeof(cube_prims));
- memset(inst0_prims, 0, sizeof(inst0_prims));
- FOR_EACH(i, 0, nprims) {
- CHECK(s3d_session_get_primitive(session, i, &prim), RES_OK);
- if(prim.inst_id != S3D_INVALID_ID) {
- CHECK(prim.inst_id, iinst0);
- CHECK(prim.geom_id, iplane);
- inst0_prims[prim.prim_id] = 1;
- } else {
- if(prim.geom_id == icube) {
- cube_prims[prim.prim_id] = 1;
- } else {
- CHECK(prim.geom_id, iplane);
- plane_prims[prim.prim_id] = 1;
- }
- }
- }
- FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
- FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
- FOR_EACH(i, 0, 2) CHECK(inst0_prims[i], 1);
-
- CHECK(s3d_session_primitives_count(session3, &nprims), RES_OK);
- CHECK(nprims, 24);
- memset(inst0_prims, 0, sizeof(inst0_prims));
- memset(inst1_prims, 0, sizeof(inst1_prims));
- FOR_EACH(i, 0, nprims) {
- CHECK(s3d_session_get_primitive(session3, i, &prim), RES_OK);
- NCHECK(prim.inst_id, S3D_INVALID_ID);
- CHECK(prim.geom_id, icube);
- if(prim.inst_id == iinst0) {
- inst0_prims[prim.prim_id] = 1;
- } else {
- CHECK(prim.inst_id, iinst1);
- inst1_prims[prim.prim_id] = 1;
- }
- }
- FOR_EACH(i, 0, 12) CHECK(inst1_prims[i], 1);
- FOR_EACH(i, 0, 12) CHECK(inst1_prims[i], 1);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
- CHECK(s3d_session_ref_put(session3), RES_OK);
-
- CHECK(s3d_session_create(scn, S3D_GET_PRIMITIVE, &session), RES_OK);
-
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
- CHECK(nprims, 26);
- memset(plane_prims, 0, sizeof(plane_prims));
- memset(cube_prims, 0, sizeof(cube_prims));
- memset(inst0_prims, 0, sizeof(inst0_prims));
- FOR_EACH(i, 0, nprims) {
- CHECK(s3d_session_get_primitive(session, i, &prim), RES_OK);
- if(prim.inst_id != S3D_INVALID_ID) {
- CHECK(prim.inst_id, iinst0);
- CHECK(prim.geom_id, icube);
- inst0_prims[prim.prim_id] = 1;
- } else {
- if(prim.geom_id == icube) {
- cube_prims[prim.prim_id] = 1;
- } else {
- CHECK(prim.geom_id, iplane);
- plane_prims[prim.prim_id] = 1;
- }
- }
- }
- FOR_EACH(i, 0, 12) CHECK(cube_prims[i], 1);
- FOR_EACH(i, 0, 2) CHECK(plane_prims[i], 1);
- FOR_EACH(i, 0, 12) CHECK(inst0_prims[i], 1);
-
- CHECK(s3d_session_ref_put(session), RES_OK);
-
- CHECK(s3d_shape_ref_put(inst0), RES_OK);
- CHECK(s3d_shape_ref_put(inst1), RES_OK);
- CHECK(s3d_scene_ref_put(scn), RES_OK);
- CHECK(s3d_scene_ref_put(scn2), RES_OK);
- CHECK(s3d_scene_ref_put(scn3), RES_OK);
-}
-
-/*******************************************************************************
- * Main test function
- ******************************************************************************/
-int
-main(int argc, char** argv)
-{
- struct mem_allocator allocator;
- struct mesh_context ctx;
- struct s3d_device* dev;
- struct s3d_shape* cube;
- struct s3d_shape* plane;
- struct s3d_vertex_data vdata;
- (void)argc, (void)argv;
-
- mem_init_proxy_allocator(&allocator, &mem_default_allocator);
-
- CHECK(s3d_device_create(NULL, &allocator, 1, &dev), RES_OK);
-
- vdata.type = S3D_FLOAT3;
- vdata.usage = S3D_POSITION;
- vdata.get = get_pos;
-
- ctx.ids = cube_ids;
- ctx.verts = cube_verts;
- CHECK(s3d_shape_create_mesh(dev, &cube), RES_OK);
- CHECK(s3d_mesh_setup_indexed_vertices
- (cube, cube_ntris, get_ids, cube_nverts, &vdata, 1, &ctx), RES_OK);
-
- ctx.ids = plane_ids;
- ctx.verts = plane_verts;
- CHECK(s3d_shape_create_mesh(dev, &plane), RES_OK);
- CHECK(s3d_mesh_setup_indexed_vertices
- (plane, plane_ntris, get_ids, plane_nverts, &vdata, 1, &ctx), RES_OK);
-
- test_miscellaneous(dev, cube, plane);
- test_trace_ray(dev, cube, plane);
- test_sample(dev, cube, plane);
- test_get_primitive(dev, cube, plane);
-
- CHECK(s3d_shape_ref_put(cube), RES_OK);
- CHECK(s3d_shape_ref_put(plane), RES_OK);
- CHECK(s3d_device_ref_put(dev), RES_OK);
-
- check_memory_allocator(&allocator);
- mem_shutdown_proxy_allocator(&allocator);
- CHECK(mem_allocated_size(), 0);
- return 0;
-}
-
diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c
@@ -108,7 +108,7 @@ main(int argc, char** argv)
struct s3d_hit hit;
struct s3d_scene* scn;
struct s3d_scene* scn2;
- struct s3d_session* session;
+ struct s3d_scene_view* scnview;
struct s3d_shape* inst;
struct s3d_shape* walls;
struct s3d_shape* walls_copy;
@@ -170,43 +170,43 @@ main(int argc, char** argv)
CHECK(s3d_scene_attach_shape(scn, walls), RES_OK);
CHECK(s3d_shape_ref_put(walls), RES_OK);
- CHECK(s3d_session_create(scn, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_trace_ray(NULL, NULL, NULL, NULL, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, NULL, NULL, NULL, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, org, NULL, NULL, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, org, NULL, NULL, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, NULL, dir, NULL, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, NULL, dir, NULL, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, org, dir, NULL, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, org, dir, NULL, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, NULL, NULL, range, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, NULL, NULL, range, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, org, NULL, range, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, org, NULL, range, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, NULL, dir, range, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, NULL, dir, range, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, org, dir, range, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, NULL, NULL, NULL, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, NULL, NULL, NULL, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, org, NULL, NULL, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, org, NULL, NULL, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, NULL, dir, NULL, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, NULL, dir, NULL, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, org, dir, NULL, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, org, dir, NULL, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, NULL, NULL, range, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, NULL, NULL, range, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, org, NULL, range, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, org, NULL, range, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, NULL, dir, range, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, NULL, dir, range, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(NULL, org, dir, range, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_trace_ray(NULL, NULL, NULL, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, NULL, NULL, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, org, NULL, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, NULL, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, NULL, dir, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, NULL, dir, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, org, dir, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, NULL, NULL, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, NULL, NULL, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, org, NULL, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, NULL, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, NULL, dir, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, NULL, dir, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, org, dir, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, NULL, NULL, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, NULL, NULL, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, org, NULL, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, NULL, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, NULL, dir, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, NULL, dir, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, org, dir, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, NULL, NULL, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, NULL, NULL, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, org, NULL, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, NULL, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, NULL, dir, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, NULL, dir, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(NULL, org, dir, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_OK);
f3(dir, 1.f, 1.f, 1.f);
- CHECK(s3d_session_trace_ray(session, org, dir, range, NULL, &hit), RES_BAD_ARG);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
f3(dir, 0.f, 1.f, 0.f);
CHECK(s3d_scene_clear(scn), RES_OK);
@@ -237,10 +237,10 @@ main(int argc, char** argv)
/* Instantiate the scene */
CHECK(s3d_scene_instantiate(scn, &inst), RES_OK);
- CHECK(s3d_session_create(scn, S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
+ CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
CHECK(nprims, 20);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_shape_get_id(inst, &inst_id), RES_OK);
/* Create the CBox walls */
@@ -266,12 +266,12 @@ main(int argc, char** argv)
CHECK(s3d_instance_set_position(inst, org), RES_OK);
CHECK(s3d_shape_enable(inst, 0), RES_OK);
- CHECK(s3d_session_create(scn2, S3D_TRACE|S3D_SAMPLE, &session), RES_OK);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_create(scn2, S3D_TRACE|S3D_SAMPLE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_shape_enable(inst, 1), RES_OK);
- CHECK(s3d_session_create(scn2, S3D_TRACE, &session), RES_OK);
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_create(scn2, S3D_TRACE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
CHECK(s3d_shape_create_mesh(dev, &walls_copy), RES_OK);
CHECK(s3d_mesh_copy(walls, walls_copy), RES_OK);
@@ -287,11 +287,11 @@ 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_session_create(scn2, S3D_TRACE|S3D_GET_PRIMITIVE, &session), RES_OK);
- CHECK(s3d_session_primitives_count(session, &nprims), RES_OK);
+ CHECK(s3d_scene_view_create(scn2, S3D_TRACE|S3D_GET_PRIMITIVE, &scnview), RES_OK);
+ CHECK(s3d_scene_view_primitives_count(scnview, &nprims), RES_OK);
CHECK(nprims, 30);
- CHECK(s3d_session_get_aabb(session, lower, upper), RES_OK);
+ CHECK(s3d_scene_view_get_aabb(scnview, lower, upper), RES_OK);
CHECK(eq_epsf(lower[0], -100.f, 1.e-6f), 1);
CHECK(eq_epsf(lower[1], 0.f, 1.e-6f), 1);
CHECK(eq_epsf(lower[2], -2.f, 1.e-6f), 1);
@@ -301,7 +301,7 @@ main(int argc, char** argv)
FOR_EACH(i, 0, nprims) {
size_t j;
- CHECK(s3d_session_get_primitive(session, (unsigned)i, prims + i), RES_OK);
+ CHECK(s3d_scene_view_get_primitive(scnview, (unsigned)i, prims + i), RES_OK);
CHECK(S3D_PRIMITIVE_EQ(prims + i, &S3D_PRIMITIVE_NULL), 0);
FOR_EACH(j, 0, i) {
CHECK(S3D_PRIMITIVE_EQ(prims + i, prims + j), 0);
@@ -324,8 +324,8 @@ main(int argc, char** argv)
pixel[0] = (float)ix/(float)IMG_WIDTH;
camera_ray(&cam, pixel, org, dir);
- CHECK(s3d_session_trace_ray
- (session, org, dir, range, (void*)(uintptr_t)0xDEADBEEF, &hit), RES_OK);
+ CHECK(s3d_scene_view_trace_ray
+ (scnview, org, dir, range, (void*)(uintptr_t)0xDEADBEEF, &hit), RES_OK);
if(S3D_HIT_NONE(&hit)) {
if(img) {
@@ -390,7 +390,7 @@ main(int argc, char** argv)
}
}
}
- CHECK(s3d_session_ref_put(session), RES_OK);
+ CHECK(s3d_scene_view_ref_put(scnview), RES_OK);
if(img_name) {
CHECK(image_ppm_write(img_name, IMG_WIDTH, IMG_HEIGHT, 3, img), RES_OK);