solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

commit e533c1aa7cbfe3e83462f023bc04569de7b00605
parent d74054cf855ab88d073e21386b0126c2d9f64d9c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue,  6 Sep 2016 11:58:22 +0200

Add a Star-3D sampling shape to the ssol_shape.

Use the Star-3D sampling shape to create a Star-3D sampling scene in the
ssol_object. Instantiate it as a sampling instance in the
ssol_object_instance. On solve invocation, conditionally attach the
Star-3D sampling instance to the Star-3D sampling scene of the
ssol_scene whether its associated material is a mirror or not. Fill an
associative container that maps the Star-3D instance identifier to its
associated ssol_object_instance and use it to retrieve the sampled
solstice instance at the beginning of each realisation.

Clean up the code by removing useless getters.

Diffstat:
Msrc/ssol_material_c.h | 7-------
Msrc/ssol_object.c | 36+++++++++++++++++++++---------------
Msrc/ssol_object_c.h | 11++---------
Msrc/ssol_object_instance.c | 37++++++++++++++++++++++++++++---------
Msrc/ssol_object_instance_c.h | 25++-----------------------
Msrc/ssol_scene.c | 174+++++++++++++++++++++++++++++++++++++------------------------------------------
Msrc/ssol_scene_c.h | 54++++++++++++++++++------------------------------------
Msrc/ssol_shape.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/ssol_shape_c.h | 10++--------
Msrc/ssol_solver.c | 162+++++++++++++++++++++++++++-----------------------------------------------------
Msrc/ssol_solver_c.h | 12++++++------
11 files changed, 270 insertions(+), 321 deletions(-)

diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h @@ -53,13 +53,6 @@ struct ssol_material { ref_T ref; }; -static INLINE enum material_type -material_get_type(const struct ssol_material* mtl) -{ - ASSERT(mtl); - return mtl->type; -} - extern LOCAL_SYM void surface_fragment_setup (struct surface_fragment* fragment, diff --git a/src/ssol_object.c b/src/ssol_object.c @@ -25,6 +25,16 @@ /******************************************************************************* * Helper functions ******************************************************************************/ +static INLINE res_T +object_ok(const struct ssol_object* object) +{ + if(!object + || !object->shape + || !object->material) + return RES_BAD_ARG; + return RES_OK; +} + static void object_release(ref_T* ref) { @@ -35,21 +45,12 @@ object_release(ref_T* ref) ASSERT(dev && dev->allocator); SSOL(shape_ref_put(object->shape)); SSOL(material_ref_put(object->material)); - if(object->s3d_scn) S3D(scene_ref_put(object->s3d_scn)); + if(object->scn_rt) S3D(scene_ref_put(object->scn_rt)); + if(object->scn_samp) S3D(scene_ref_put(object->scn_samp)); MEM_RM(dev->allocator, object); SSOL(device_ref_put(dev)); } -static INLINE res_T -object_ok(const struct ssol_object* object) -{ - if(!object - || !object->shape - || !object->material) - return RES_BAD_ARG; - return RES_OK; -} - /******************************************************************************* * Exported ssol_object functions ******************************************************************************/ @@ -81,11 +82,16 @@ ssol_object_create object->material = material; ref_init(&object->ref); - /* Create the Star-3D scene to instantiate through the object instance */ - res = s3d_scene_create(dev->s3d, &object->s3d_scn); + /* Create the Star-3D RT scene to instantiate through the instance */ + res = s3d_scene_create(dev->s3d, &object->scn_rt); + if(res != RES_OK) goto error; + res = s3d_scene_attach_shape(object->scn_rt, object->shape->shape_rt); + if(res != RES_OK) goto error; + + /* Create the Star-3D sampling scene to instantiated through the instance */ + res = s3d_scene_create(dev->s3d, &object->scn_samp); if(res != RES_OK) goto error; - res = s3d_scene_attach_shape - (object->s3d_scn, shape_get_s3d_shape(object->shape)); + res = s3d_scene_attach_shape(object->scn_samp, object->shape->shape_samp); if(res != RES_OK) goto error; exit: diff --git a/src/ssol_object_c.h b/src/ssol_object_c.h @@ -22,18 +22,11 @@ struct ssol_object { struct ssol_shape* shape; struct ssol_material* material; - struct s3d_scene* s3d_scn; /* Scene to instantiate */ + struct s3d_scene* scn_rt; /* RT scene to instantiate */ + struct s3d_scene* scn_samp; /* Sampling scene to instantiate */ struct ssol_device* dev; ref_T ref; }; -static FINLINE struct ssol_material* -object_get_material(const struct ssol_object* object) -{ - ASSERT(object); - return object->material; -} - - #endif /* SSOL_OBJECT_C_H */ diff --git a/src/ssol_object_instance.c b/src/ssol_object_instance.c @@ -40,7 +40,8 @@ object_instance_release(ref_T* ref) ASSERT(dev && dev->allocator); SSOL(object_ref_put(instance->object)); - if(instance->s3d_shape) S3D(shape_ref_put(instance->s3d_shape)); + if(instance->shape_rt) S3D(shape_ref_put(instance->shape_rt)); + if(instance->shape_samp) S3D(shape_ref_put(instance->shape_samp)); str_release(&instance->receiver_name); MEM_RM(dev->allocator, instance); SSOL(device_ref_put(dev)); @@ -80,8 +81,12 @@ ssol_object_instantiate SSOL(device_ref_get(dev)); ref_init(&instance->ref); - /* Create the Star-3D instance */ - res = s3d_scene_instantiate(object->s3d_scn, &instance->s3d_shape); + /* Create the Star-3D instance to ray-trace */ + res = s3d_scene_instantiate(object->scn_rt, &instance->shape_rt); + if(res != RES_OK) goto error; + + /* Create the Star-3D instance to sample */ + res = s3d_scene_instantiate(object->scn_samp, &instance->shape_samp); if(res != RES_OK) goto error; exit: @@ -98,7 +103,7 @@ error: res_T ssol_object_instance_ref_get(struct ssol_object_instance* instance) { - if (!instance) + if(!instance) return RES_BAD_ARG; ref_get(&instance->ref); return RES_OK; @@ -120,13 +125,27 @@ ssol_object_instance_set_transform { float t[12]; int i; - if (!instance || !transform) - return RES_BAD_ARG; + res_T res = RES_OK; - for (i = 0; i < 12; i++) t[i] = (float) transform[i]; - s3d_instance_set_transform(instance->s3d_shape, t); + if(!instance || !transform) { + res = RES_BAD_ARG; + goto error; + } - return RES_OK; + FOR_EACH(i, 0, 12) t[i] = (float)transform[i]; + + res = s3d_instance_set_transform(instance->shape_rt, t); + if(res != RES_OK) goto error; + + if(instance->shape_rt != instance->shape_samp) { + res = s3d_instance_set_transform(instance->shape_samp, t); + if(res != RES_OK) goto error; + } + +exit: + return res; +error: + goto exit; } res_T diff --git a/src/ssol_object_instance_c.h b/src/ssol_object_instance_c.h @@ -23,7 +23,8 @@ struct ssol_object_instance { struct ssol_object* object; /* Instantiated object */ - struct s3d_shape* s3d_shape; /* Instantiated Star-3D shape */ + struct s3d_shape* shape_rt; /* Instantiated Star-3D shape to ray-trace */ + struct s3d_shape* shape_samp; /* Instantiated Star-3D shape to sample */ struct str receiver_name; /* Empty if not a receiver */ uint32_t target_mask; @@ -31,21 +32,6 @@ struct ssol_object_instance ref_T ref; }; -/* Return the Star-3D shape of the object instance */ -static INLINE struct s3d_shape* -object_instance_get_s3d_shape(const struct ssol_object_instance* instance) -{ - ASSERT(instance); - return instance->s3d_shape; -} - -static INLINE struct ssol_object* -object_instance_get_object(const struct ssol_object_instance* instance) -{ - ASSERT(instance); - return instance->object; -} - static INLINE const char* object_instance_get_receiver_name(const struct ssol_object_instance* instance) { @@ -54,11 +40,4 @@ object_instance_get_receiver_name(const struct ssol_object_instance* instance) ? NULL : str_cget(&instance->receiver_name); } -static INLINE uint32_t -object_instance_get_target_mask(const struct ssol_object_instance* instance) -{ - ASSERT(instance); - return instance->target_mask; -} - #endif /* SSOL_OBJECT_INSTANCE_C_H */ diff --git a/src/ssol_scene.c b/src/ssol_scene.c @@ -40,10 +40,11 @@ scene_release(ref_T* ref) dev = scene->dev; ASSERT(dev && dev->allocator); SSOL(scene_clear(scene)); - if (scene->s3d_raytracing_scn) S3D(scene_ref_put(scene->s3d_raytracing_scn)); - if (scene->s3d_sampling_scn) S3D(scene_ref_put(scene->s3d_sampling_scn)); + if(scene->scn_rt) S3D(scene_ref_put(scene->scn_rt)); + if(scene->scn_samp) S3D(scene_ref_put(scene->scn_samp)); if(scene->sun) SSOL(sun_ref_put(scene->sun)); - htable_instance_release(&scene->instances); + htable_instance_release(&scene->instances_rt); + htable_instance_release(&scene->instances_samp); MEM_RM(dev->allocator, scene); SSOL(device_ref_put(dev)); } @@ -58,32 +59,32 @@ ssol_scene_create { struct ssol_scene* scene = NULL; res_T res = RES_OK; - if (!dev || !out_scene) { + if(!dev || !out_scene) { return RES_BAD_ARG; } scene = (struct ssol_scene*)MEM_CALLOC (dev->allocator, 1, sizeof(struct ssol_scene)); - if (!scene) { + if(!scene) { res = RES_MEM_ERR; goto error; } - htable_instance_init(dev->allocator, &scene->instances); + htable_instance_init(dev->allocator, &scene->instances_rt); + htable_instance_init(dev->allocator, &scene->instances_samp); SSOL(device_ref_get(dev)); scene->dev = dev; ref_init(&scene->ref); - res = s3d_scene_create(dev->s3d, &scene->s3d_raytracing_scn); - if (res != RES_OK) goto error; - - res = s3d_scene_create(dev->s3d, &scene->s3d_sampling_scn); - if (res != RES_OK) goto error; + res = s3d_scene_create(dev->s3d, &scene->scn_rt); + if(res != RES_OK) goto error; + res = s3d_scene_create(dev->s3d, &scene->scn_samp); + if(res != RES_OK) goto error; exit: - if (out_scene) *out_scene = scene; + if(out_scene) *out_scene = scene; return res; error: - if (scene) { + if(scene) { SSOL(scene_ref_put(scene)); scene = NULL; } @@ -110,23 +111,21 @@ res_T ssol_scene_attach_object_instance (struct ssol_scene* scene, struct ssol_object_instance* instance) { - struct s3d_shape* shape; unsigned id; res_T res; if(!scene || !instance) return RES_BAD_ARG; - shape = object_instance_get_s3d_shape(instance); - /* attach the instantiated s3d shape to s3d scene */ - res = s3d_scene_attach_shape(scene->s3d_raytracing_scn, shape); + /* Attach the instantiated s3d shape to ray-trace to the RT scene */ + res = s3d_scene_attach_shape(scene->scn_rt, instance->shape_rt); if(res != RES_OK) return res; /* Register the instance against the scene */ - S3D(shape_get_id(shape, &id)); - ASSERT(!htable_instance_find(&scene->instances, &id)); - res = htable_instance_set(&scene->instances, &id, &instance); + S3D(shape_get_id(instance->shape_rt, &id)); + ASSERT(!htable_instance_find(&scene->instances_rt, &id)); + res = htable_instance_set(&scene->instances_rt, &id, &instance); if(res != RES_OK) { - S3D(scene_detach_shape(scene->s3d_raytracing_scn, shape)); + S3D(scene_detach_shape(scene->scn_rt, instance->shape_rt)); return res; } SSOL(object_instance_ref_get(instance)); @@ -140,7 +139,6 @@ ssol_scene_detach_object_instance { struct ssol_object_instance** pinst; struct ssol_object_instance* inst; - struct s3d_shape* shape; unsigned id; size_t n; (void)n, (void)inst; @@ -148,19 +146,18 @@ ssol_scene_detach_object_instance if(!scene || !instance) return RES_BAD_ARG; /* Retrieve the object instance identifier */ - shape = object_instance_get_s3d_shape(instance); - S3D(shape_get_id(shape, &id)); + S3D(shape_get_id(instance->shape_rt, &id)); /* Check that the instance is effectively registered into the scene */ - pinst = htable_instance_find(&scene->instances, &id); + pinst = htable_instance_find(&scene->instances_rt, &id); if(!pinst) return RES_BAD_ARG; inst = *pinst; ASSERT(inst == instance); /* Detach the object instance */ - n = htable_instance_erase(&scene->instances, &id); + n = htable_instance_erase(&scene->instances_rt, &id); ASSERT(n == 1); - S3D(scene_detach_shape(scene->s3d_raytracing_scn, shape)); + S3D(scene_detach_shape(scene->scn_rt, instance->shape_rt)); SSOL(object_instance_ref_put(instance)); return RES_OK; @@ -172,28 +169,29 @@ ssol_scene_clear(struct ssol_scene* scene) struct htable_instance_iterator it, it_end; if(!scene) return RES_BAD_ARG; - htable_instance_begin(&scene->instances, &it); - htable_instance_end(&scene->instances, &it_end); + htable_instance_begin(&scene->instances_rt, &it); + htable_instance_end(&scene->instances_rt, &it_end); while(!htable_instance_iterator_eq(&it, &it_end)) { struct ssol_object_instance* inst; inst = *htable_instance_iterator_data_get(&it); - S3D(scene_detach_shape(scene->s3d_raytracing_scn, object_instance_get_s3d_shape(inst))); + S3D(scene_detach_shape(scene->scn_rt, inst->shape_rt)); SSOL(object_instance_ref_put(inst)); htable_instance_iterator_next(&it); } - htable_instance_clear(&scene->instances); - S3D(scene_clear(scene->s3d_raytracing_scn)); - if(scene->sun) - ssol_scene_detach_sun(scene, scene->sun); + htable_instance_clear(&scene->instances_rt); + htable_instance_clear(&scene->instances_samp); + S3D(scene_clear(scene->scn_rt)); + S3D(scene_clear(scene->scn_samp)); + if(scene->sun) ssol_scene_detach_sun(scene, scene->sun); return RES_OK; } res_T ssol_scene_attach_sun(struct ssol_scene* scene, struct ssol_sun* sun) { - if (!scene || ! sun - || sun->scene_attachment /* should detach this sun first from its own scene */ - || scene->sun) /* should detach previous sun first */ + if(!scene || ! sun + || sun->scene_attachment /* Should detach this sun first from its own scene */ + || scene->sun) /* Should detach previous sun first */ return RES_BAD_ARG; SSOL(sun_ref_get(sun)); @@ -205,7 +203,7 @@ ssol_scene_attach_sun(struct ssol_scene* scene, struct ssol_sun* sun) res_T ssol_scene_detach_sun(struct ssol_scene* scene, struct ssol_sun* sun) { - if (!scene || !sun || !scene->sun || sun->scene_attachment != scene) + if(!scene || !sun || !scene->sun || sun->scene_attachment != scene) return RES_BAD_ARG; ASSERT(sun == scene->sun); @@ -218,30 +216,48 @@ ssol_scene_detach_sun(struct ssol_scene* scene, struct ssol_sun* sun) /******************************************************************************* * Local functions ******************************************************************************/ -struct s3d_scene* -scene_get_s3d_raytracing_scn(const struct ssol_scene* scn) +res_T +scene_setup_s3d_sampling_scene(struct ssol_scene* scn) { + struct htable_instance_iterator it, end; + res_T res = RES_OK; ASSERT(scn); - return scn->s3d_raytracing_scn; -} -struct s3d_scene* -scene_get_s3d_sampling_scn(const struct ssol_scene* scn) -{ - ASSERT(scn); - return scn->s3d_sampling_scn; -} + S3D(scene_clear(scn->scn_samp)); + htable_instance_clear(&scn->instances_samp); -struct ssol_object_instance* -scene_get_object_instance_from_s3d_hit - (struct ssol_scene* scn, - const struct s3d_hit* hit) -{ - struct ssol_object_instance** pinst; - ASSERT(scn && hit); - pinst = htable_instance_find(&scn->instances, &hit->prim.inst_id); - ASSERT(pinst); - return *pinst; + htable_instance_begin(&scn->instances_rt, &it); + htable_instance_end(&scn->instances_rt, &end); + + while(!htable_instance_iterator_eq(&it, &end)) { + struct ssol_object_instance* inst = *htable_instance_iterator_data_get(&it); + unsigned id; + htable_instance_iterator_next(&it); + + /* TODO: keep only primary mirrors */ + if(inst->object->material->type != MATERIAL_MIRROR) + continue; + + /* Attach the instantiated s3d sampling shape to the s3d sampling scene */ + res = s3d_scene_attach_shape(scn->scn_samp, inst->shape_samp); + if(res != RES_OK) goto error; + + /* Register the instantiated s3d sampling shape */ + S3D(shape_get_id(inst->shape_samp, &id)); + ASSERT(!htable_instance_find(&scn->instances_samp, &id)); + res = htable_instance_set(&scn->instances_samp, &id, &inst); + if(res != RES_OK) goto error; + + /* Do not get a reference onto the instance since it was already referenced + * by the scene on its attachment */ + } + +exit: + return res; +error: + S3D(scene_clear(scn->scn_samp)); + htable_instance_clear(&scn->instances_samp); + goto exit; } /******************************************************************************* @@ -255,8 +271,7 @@ hit_filter_function void* realisation, void* filter_data) { - struct ssol_object_instance* instance; - struct ssol_material* material; + struct ssol_object_instance* inst; const char* receiver_name; struct realisation* rs = realisation; struct segment* seg; @@ -274,10 +289,10 @@ hit_filter_function if(prev && S3D_PRIMITIVE_EQ(&hit->prim, &prev->hit.prim)) return 1; /* Discard self intersection */ - instance = scene_get_object_instance_from_s3d_hit(rs->data.scene, hit); + inst = *htable_instance_find(&rs->data.scene->instances_rt, &hit->prim.inst_id); /* Check if the hit surface is a receiver that registers hit data */ - receiver_name = object_instance_get_receiver_name(instance); + receiver_name = object_instance_get_receiver_name(inst); if(receiver_name) { float cos_in; /* check normal orientation */ @@ -301,40 +316,15 @@ hit_filter_function } /* register success mask */ - if (front_face) - rs->success_mask |= object_instance_get_target_mask(instance); - - material = object_get_material(object_instance_get_object(instance)); + if(front_face) { + rs->success_mask |= inst->target_mask; + } - if(material_get_type(material) == MATERIAL_VIRTUAL) { + if(inst->object->material->type == MATERIAL_VIRTUAL) { return 1; /* Discard virtual material */ } - rs->data.instance = instance; - + rs->data.instance = inst; return 0; } -struct ssol_sun* -scene_get_sun - (struct ssol_scene* scn) -{ - ASSERT(scn); - return scn->sun; -} - -struct ssol_device* - scene_get_device - (struct ssol_scene* scn) -{ - ASSERT(scn); - return scn->dev; -} - -struct htable_instance* - scene_get_instances - (struct ssol_scene* scn) -{ - ASSERT(scn); - return &scn->instances; -} diff --git a/src/ssol_scene_c.h b/src/ssol_scene_c.h @@ -16,9 +16,11 @@ #ifndef SSOL_SCENE_C_H #define SSOL_SCENE_C_H -#include <rsys/rsys.h> -#include <rsys/ref_count.h> #include <rsys/hash_table.h> +#include <rsys/ref_count.h> +#include <rsys/rsys.h> + +struct ssol_object_instance; /* Define the htable_instance data structure */ #define HTABLE_NAME instance @@ -26,47 +28,27 @@ #define HTABLE_DATA struct ssol_object_instance* #include <rsys/hash_table.h> -struct ssol_scene -{ - struct htable_instance instances; - struct s3d_scene* s3d_raytracing_scn; - struct s3d_scene* s3d_sampling_scn; - struct ssol_sun* sun; - - struct ssol_device* dev; - ref_T ref; -}; - +/* Forward declarations */ struct s3d_hit; struct s3d_scene; -struct ssol_object_instance; +struct ssol_device; struct ssol_scene; struct ssol_sun; -struct ssol_device; - -extern LOCAL_SYM struct s3d_scene* -scene_get_s3d_raytracing_scn - (const struct ssol_scene* scn); - -extern LOCAL_SYM struct s3d_scene* -scene_get_s3d_sampling_scn -(const struct ssol_scene* scn); - -extern LOCAL_SYM struct ssol_object_instance* -scene_get_object_instance_from_s3d_hit - (struct ssol_scene* scn, - const struct s3d_hit* hit); -extern LOCAL_SYM struct ssol_sun* -scene_get_sun - (struct ssol_scene* scn); +struct ssol_scene { + struct htable_instance instances_rt; + struct htable_instance instances_samp; + struct s3d_scene* scn_rt; + struct s3d_scene* scn_samp; + struct ssol_sun* sun; -extern LOCAL_SYM struct ssol_device* -scene_get_device - (struct ssol_scene* scn); + struct ssol_device* dev; + ref_T ref; +}; -extern LOCAL_SYM struct htable_instance* -scene_get_instances +/* Fill the Star-3D sampling scene with the Star-3D shape of the mirrors */ +extern LOCAL_SYM res_T +scene_setup_s3d_sampling_scene (struct ssol_scene* scn); #endif /* SSOL_SCENE_C_H */ diff --git a/src/ssol_shape.c b/src/ssol_shape.c @@ -399,8 +399,11 @@ error: goto exit; } +/* Setup the Star-3D shape of the quadric to ray-trace, i.e. the clipped 2D + * profile of the quadric whose vertices are displaced with respect to the + * quadric equation */ static res_T -quadric_setup_s3d_shape +quadric_setup_s3d_shape_rt (const struct ssol_quadric* quadric, const struct darray_double* coords, const struct darray_size_t* ids, @@ -442,6 +445,36 @@ quadric_setup_s3d_shape (shape, ntris, quadric_mesh_get_ids, nverts, &vdata, 1, &ctx); } +/* Setup the Star-3D shape of the quadric to sample, i.e. the clipped 2D + * profile of the quadric */ +static res_T +quadric_setup_s3d_shape_samp + (const struct darray_double* coords, + const struct darray_size_t* ids, + struct s3d_shape* shape) +{ + struct quadric_mesh_context ctx; + struct s3d_vertex_data vdata; + unsigned nverts; + unsigned ntris; + ASSERT(coords && ids && shape); + ASSERT(darray_double_size_get(coords)%2 == 0); + ASSERT(darray_size_t_size_get(ids)%3 == 0); + ASSERT(darray_double_size_get(coords)/2 <= UINT_MAX); + ASSERT(darray_size_t_size_get(ids)/3 <= UINT_MAX); + + nverts = (unsigned)darray_double_size_get(coords) / 2/*#coords per vertex*/; + ntris = (unsigned)darray_size_t_size_get(ids) / 3/*#ids per triangle*/; + ctx.coords = darray_double_cdata_get(coords); + ctx.ids = darray_size_t_cdata_get(ids); + + vdata.usage = S3D_POSITION; + vdata.type = S3D_FLOAT3; + vdata.get = quadric_mesh_plane_get_pos; + return s3d_mesh_setup_indexed_vertices + (shape, ntris, quadric_mesh_get_ids, nverts, &vdata, 1, &ctx); +} + static res_T shape_create (struct ssol_device* dev, @@ -462,11 +495,15 @@ shape_create goto error; } - /* create a s3d_shape to hold a mesh */ - res = s3d_shape_create_mesh(dev->s3d, &shape->s3d_shape); + /* Create the s3d_shape to ray-trace */ + res = s3d_shape_create_mesh(dev->s3d, &shape->shape_rt); if(res != RES_OK) goto error; res = s3d_mesh_set_hit_filter_function - (shape->s3d_shape, hit_filter_function, NULL); + (shape->shape_rt, hit_filter_function, NULL); + if(res != RES_OK) goto error; + + /* Create the s3d_shape to sample */ + res = s3d_shape_create_mesh(dev->s3d, &shape->shape_samp); if(res != RES_OK) goto error; SSOL(device_ref_get(dev)); @@ -493,7 +530,8 @@ shape_release(ref_T* ref) ASSERT(ref); dev = shape->dev; ASSERT(dev && dev->allocator); - if(shape->s3d_shape) S3D(shape_ref_put(shape->s3d_shape)); + if(shape->shape_rt) S3D(shape_ref_put(shape->shape_rt)); + if(shape->shape_samp) S3D(shape_ref_put(shape->shape_samp)); MEM_RM(dev->allocator, shape); SSOL(device_ref_put(dev)); } @@ -576,8 +614,13 @@ ssol_punched_surface_setup (&coords, &ids, shape->dev->scpr_mesh, psurf->carvings, psurf->nb_carvings); if(res != RES_OK) goto error; - res = quadric_setup_s3d_shape - (psurf->quadric, &coords, &ids, shape->s3d_shape); + /* Setup the Star-3D shape to ray-trace */ + res = quadric_setup_s3d_shape_rt + (psurf->quadric, &coords, &ids, shape->shape_rt); + if(res != RES_OK) goto error; + + /* Setup the Star-3D shape to sample */ + res = quadric_setup_s3d_shape_samp(&coords, &ids, shape->shape_samp); if(res != RES_OK) goto error; exit: @@ -639,7 +682,11 @@ ssol_mesh_setup } } res = s3d_mesh_setup_indexed_vertices - (shape->s3d_shape, ntris, get_indices, nverts, attrs, nattribs, data); + (shape->shape_rt, ntris, get_indices, nverts, attrs, nattribs, data); + if(res != RES_OK) goto error; + + /* The Star-3D shape to sample is the same of the one to ray-traced */ + res = s3d_mesh_copy(shape->shape_rt, shape->shape_samp); if(res != RES_OK) goto error; exit: diff --git a/src/ssol_shape_c.h b/src/ssol_shape_c.h @@ -27,18 +27,12 @@ enum shape_type { struct ssol_shape { enum shape_type type; - struct s3d_shape* s3d_shape; /* 3D shape for the mesh */ + struct s3d_shape* shape_rt; /* Star-3D shape to ray-trace */ + struct s3d_shape* shape_samp; /* Star-3D shape to sample */ struct ssol_quadric quadric; struct ssol_device* dev; ref_T ref; }; -static FINLINE struct s3d_shape* -shape_get_s3d_shape(struct ssol_shape* shape) -{ - ASSERT(shape); - return shape->s3d_shape; -} - #endif /* SSOL_SHAPE_C_H */ diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -54,18 +54,12 @@ get_quadric(const struct ssol_object_instance* instance) return &instance->object->shape->quadric; } -static INLINE struct s3d_scene* -get_3dscene(const struct ssol_object_instance* instance) -{ - ASSERT(instance); - return instance->object->s3d_scn; -} - /******************************************************************************* * Local functions ******************************************************************************/ res_T -set_sun_distributions(struct solver_data* data) { +set_sun_distributions(struct solver_data* data) +{ struct ssol_spectrum* spectrum; struct ssol_device* dev; const struct ssol_sun* sun; @@ -76,9 +70,9 @@ set_sun_distributions(struct solver_data* data) { if (!data) return RES_BAD_ARG; ASSERT(data->scene); - sun = scene_get_sun(data->scene); + sun = data->scene->sun; ASSERT(sun); - dev = scene_get_device(data->scene); + dev = data->scene->dev; ASSERT(dev && dev->allocator); /* first set the spectrum distribution */ res = ssp_ranst_piecewise_linear_create @@ -126,10 +120,11 @@ error: } static void -release_solver_data(struct solver_data* data) { +release_solver_data(struct solver_data* data) +{ ASSERT(data); - if (data->trace_view) s3d_scene_view_ref_put(data->trace_view); - if (data->sample_view) s3d_scene_view_ref_put(data->sample_view); + if (data->view_rt) s3d_scene_view_ref_put(data->view_rt); + if (data->view_samp) s3d_scene_view_ref_put(data->view_samp); if (data->sun_dir_ran) ranst_sun_dir_ref_put(data->sun_dir_ran); if (data->sun_spectrum_ran) ssp_ranst_piecewise_linear_ref_put(data->sun_spectrum_ran); if (data->brdfs) brdf_composite_ref_put(data->brdfs); @@ -137,64 +132,27 @@ release_solver_data(struct solver_data* data) { } res_T -set_views(struct solver_data* data) { +set_views(struct solver_data* data) +{ res_T res = RES_OK; - struct ssol_scene* scene; - struct s3d_scene* raytracing_scene; - struct s3d_scene* sampling_scene; - struct htable_instance_iterator it, it_end; - int mirror_found = 0; + size_t nshapes_samp = 0; if (!data) return RES_BAD_ARG; - scene = data->scene; - ASSERT(scene); - raytracing_scene = scene_get_s3d_raytracing_scn(scene); - ASSERT(raytracing_scene); - sampling_scene = scene_get_s3d_sampling_scn(scene); - ASSERT(sampling_scene); - /* feed sampling s3d_scene */ - S3D(scene_clear(sampling_scene)); - htable_instance_end(&scene->instances, &it_end); - for ( - htable_instance_begin(&scene->instances, &it); - !htable_instance_iterator_eq(&it, &it_end); - htable_instance_iterator_next(&it)) - { - struct ssol_object_instance* inst; - struct ssol_material* mat; - struct ssol_object* object; - inst = *htable_instance_iterator_data_get(&it); - - /* TODO: keep only primary mirrors */ - mat = inst->object->material; - if (material_get_type(mat) != MATERIAL_MIRROR) - continue; - mirror_found = 1; - - object = object_instance_get_object(inst); - switch (object->shape->type) { - case SHAPE_MESH: - /* the same mesh is used for sampling and raytracing */ - res = s3d_scene_attach_shape(sampling_scene, inst->s3d_shape); - break; - case SHAPE_PUNCHED: - /* use the carving's mesh for sampling */ - FATAL("TODO\n"); - break; - default: FATAL("Unreachable code\n"); break; - } - if (res != RES_OK) goto error; - } - if (!mirror_found) { + res = scene_setup_s3d_sampling_scene(data->scene); + if(res != RES_OK) goto error; + + S3D(scene_get_shapes_count(data->scene->scn_samp, &nshapes_samp)); + if(!nshapes_samp) { + log_error(data->scene->dev, "%s: no mirror geometry defined.\n", FUNC_NAME); res = RES_BAD_ARG; - log_error(scene->dev, "%s: no mirror geometry defined.\n", FUNC_NAME); goto error; } - /* create views from scenes */ - res = s3d_scene_view_create(raytracing_scene, S3D_TRACE, &data->trace_view); + + /* Create views from scenes */ + res = s3d_scene_view_create(data->scene->scn_rt, S3D_TRACE, &data->view_rt); if (res != RES_OK) goto error; - res = s3d_scene_view_create(sampling_scene, S3D_SAMPLE, &data->sample_view); + res = s3d_scene_view_create(data->scene->scn_samp, S3D_SAMPLE, &data->view_samp); if (res != RES_OK) goto error; exit: @@ -296,14 +254,10 @@ init_realisation struct realisation* rs) { res_T res = RES_OK; - struct ssol_device* device; if (!scene || !rng || !rs) return RES_BAD_ARG; - device = scene_get_device(scene); - ASSERT(device && device->allocator); - - darray_segment_init(device->allocator, &rs->segments); + darray_segment_init(scene->dev->allocator, &rs->segments); /* set a first size; will grow up with time if needed */ res = darray_segment_resize(&rs->segments, 16); if (res != RES_OK) goto error; @@ -318,7 +272,7 @@ init_realisation /* create sun distributions */ res = set_sun_distributions(&rs->data); if (res != RES_OK) goto error; - res = brdf_composite_create(device, &rs->data.brdfs); + res = brdf_composite_create(scene->dev, &rs->data.brdfs); if (res != RES_OK) goto error; exit: @@ -336,19 +290,13 @@ release_realisation(struct realisation* rs) darray_segment_release(&rs->segments); } -static struct ssol_material* -get_material_from_hit(struct ssol_scene* scene, struct s3d_hit* hit) { - struct ssol_object_instance* instance; - struct ssol_object* object; - struct ssol_material* material; +static INLINE struct ssol_material* +get_material_from_hit(struct ssol_scene* scene, struct s3d_hit* hit) +{ + struct ssol_object_instance* inst; ASSERT(scene && hit); - instance = scene_get_object_instance_from_s3d_hit(scene, hit); - ASSERT(instance); - object = object_instance_get_object(instance); - ASSERT(object); - material = object_get_material(object); - ASSERT(material); - return material; + inst = *htable_instance_find(&scene->instances_rt, &hit->prim.inst_id); + return inst->object->material; } static void @@ -362,36 +310,34 @@ sample_point_on_primary_mirror(struct realisation* rs) struct s3d_primitive tmp_prim; data = &rs->data; - ASSERT(data->rng && data->sample_view && data->scene); + ASSERT(data->rng && data->view_samp && data->scene); /* sample a point on a primary mirror's carving */ r1 = ssp_rng_canonical_float(data->rng); r2 = ssp_rng_canonical_float(data->rng); r3 = ssp_rng_canonical_float(data->rng); - S3D(scene_view_sample(data->sample_view, r1, r2, r3, &tmp_prim, rs->start.uv)); + S3D(scene_view_sample(data->view_samp, r1, r2, r3, &tmp_prim, rs->start.uv)); S3D(primitive_get_attrib(&tmp_prim, S3D_POSITION, rs->start.uv, &attrib)); CHECK(attrib.type, S3D_FLOAT3); /* find the solstice shape and project the sampled point on the mirror */ - rs->start.instance = - *htable_instance_find(&data->scene->instances, &tmp_prim.inst_id); - ASSERT(rs->start.instance); - object = object_instance_get_object(rs->start.instance); - ASSERT(object && object->shape); - rs->start.material = object_get_material(object); + rs->start.instance = *htable_instance_find + (&data->scene->instances_samp, &tmp_prim.inst_id); + object = rs->start.instance->object; + rs->start.material = object->material; ASSERT(rs->start.material); switch (object->shape->type) { - case SHAPE_MESH: - /* no projection needed */ - f3_set(seg->org, attrib.value); - /* to avoid self intersect */ - rs->start.primitive = tmp_prim; - break; - case SHAPE_PUNCHED: - /* project the sampled point on the quadric */ - FATAL("TODO\n"); - /* cannot self intersect as the sampled mesh is not raytraced */ - rs->start.primitive = S3D_PRIMITIVE_NULL; - break; - default: FATAL("Unreachable code\n"); break; + case SHAPE_MESH: + /* no projection needed */ + f3_set(seg->org, attrib.value); + /* to avoid self intersect */ + rs->start.primitive = tmp_prim; + break; + case SHAPE_PUNCHED: + /* project the sampled point on the quadric */ + FATAL("TODO\n"); + /* cannot self intersect as the sampled mesh is not raytraced */ + rs->start.primitive = S3D_PRIMITIVE_NULL; + break; + default: FATAL("Unreachable code\n"); break; } } @@ -436,7 +382,7 @@ receive_sunlight(struct realisation* rs) seg->hit.prim = rs->start.primitive; /* TODO (in s3d): need an occlusion test */ S3D(scene_view_trace_ray - (rs->data.trace_view, seg->org, seg->dir, seg->range, rs, &seg->hit)); + (rs->data.view_rt, seg->org, seg->dir, seg->range, rs, &seg->hit)); receives = S3D_HIT_NONE(&seg->hit); if (!receives) return receives; @@ -457,7 +403,7 @@ receive_sunlight(struct realisation* rs) } /* register success mask (normal orientation has already been checked) */ - rs->success_mask |= object_instance_get_target_mask(rs->start.instance); + rs->success_mask |= rs->start.instance->target_mask; /* restore self intersect information for further visibility test * (previous call to trace_ray overwrote prim) */ @@ -488,7 +434,7 @@ set_output_pos_and_dir(struct realisation* rs) { f3_set(seg->org, prev->hit_pos); material = get_material_from_hit(scene, &prev->hit); } - CHECK(material_get_type(material), MATERIAL_MIRROR); + CHECK(material->type, MATERIAL_MIRROR); res = material_shade(material, &rs->data.fragment, rs->freq, rs->data.brdfs); if (res != RES_OK) { rs->end = TERM_ERR; @@ -498,7 +444,7 @@ set_output_pos_and_dir(struct realisation* rs) { if (fst_segment) { float sundir_f[3]; - const struct ssol_sun* sun = scene_get_sun(rs->data.scene); + const struct ssol_sun* sun = rs->data.scene->sun; ASSERT(-1 <= rs->start.cos_sun && rs->start.cos_sun <= 0); f3_set_d3(sundir_f, rs->start.sundir); seg->weight = sun_get_dni(sun) @@ -518,13 +464,13 @@ propagate(struct realisation* rs) /* check if the ray hits something */ S3D(scene_view_trace_ray - (rs->data.trace_view, seg->org, seg->dir, seg->range, rs, &seg->hit)); + (rs->data.view_rt, seg->org, seg->dir, seg->range, rs, &seg->hit)); if (S3D_HIT_NONE(&seg->hit)) { rs->end = TERM_MISSING; return; } /* should not stop on a virtual surface */ - ASSERT(material_get_type(get_material_from_hit(rs->data.scene, &seg->hit)) + ASSERT(get_material_from_hit(rs->data.scene, &seg->hit)->type != MATERIAL_VIRTUAL); /* offset the impact point and recompute normal if needed */ diff --git a/src/ssol_solver_c.h b/src/ssol_solver_c.h @@ -83,14 +83,14 @@ struct solver_data { struct ssol_scene* scene; struct ssp_rng* rng; FILE* out_stream; - /* the s3d_scene_view used for raytracing */ - struct s3d_scene_view* trace_view; - /* the s3d_scene_view used for sampling */ - struct s3d_scene_view* sample_view; - /* the random distributions for sun sampling */ + /* The s3d_scene_view used for raytracing */ + struct s3d_scene_view* view_rt; + /* The s3d_scene_view used for sampling */ + struct s3d_scene_view* view_samp; + /* The random distributions for sun sampling */ struct ranst_sun_dir* sun_dir_ran; struct ssp_ranst_piecewise_linear* sun_spectrum_ran; - /* tmp data used for propagation */ + /* Tmp data used for propagation */ struct brdf_composite* brdfs; struct ssol_object_instance* instance; struct surface_fragment fragment;