solstice-solver

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

commit d7d535b97f8450c74490d0da9a6ecdcff92302d6
parent e1ca1392af7e762c53ec836d2a34d8f0ac9236de
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 10 Oct 2016 11:09:34 +0200

Merge remote-tracking branch 'origin/multi_shapes'

Diffstat:
Msrc/ssol.h | 35++++++++++++++++++++++++++++-------
Msrc/ssol_atmosphere.c | 7+++----
Msrc/ssol_object.c | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/ssol_object_c.h | 28+++++++++++++++++++++++++---
Msrc/ssol_ranst_sun_dir.c | 12++++++------
Msrc/ssol_ranst_sun_dir.h | 34+++++++++++++++++-----------------
Msrc/ssol_ranst_sun_wl.c | 43++++++++++++++++++++++---------------------
Msrc/ssol_ranst_sun_wl.h | 20++++++++++----------
Msrc/ssol_scene.c | 98+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/ssol_scene_c.h | 11+++++++----
Msrc/ssol_shape.c | 98+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/ssol_solver.c | 80++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/ssol_solver_c.h | 1+
Msrc/ssol_spectrum.c | 147++++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/ssol_spectrum_c.h | 14++++++++------
Msrc/test_ssol_atmosphere.c | 10+++++-----
Msrc/test_ssol_instance.c | 3++-
Msrc/test_ssol_object.c | 33+++++++++++++++++++++++++++------
Msrc/test_ssol_scene.c | 7++++---
Msrc/test_ssol_shape.c | 6++++++
Msrc/test_ssol_solver1.c | 16+++++++++-------
Msrc/test_ssol_solver2.c | 11+++++++----
Msrc/test_ssol_solver2b.c | 11+++++++----
Msrc/test_ssol_solver3.c | 8+++++---
Msrc/test_ssol_solver3N.c | 8+++++---
Msrc/test_ssol_solver4.c | 8+++++---
Msrc/test_ssol_solver5.c | 8+++++---
27 files changed, 569 insertions(+), 326 deletions(-)

diff --git a/src/ssol.h b/src/ssol.h @@ -147,10 +147,16 @@ struct ssol_quadric { struct ssol_quadric_parabol parabol; struct ssol_quadric_parabolic_cylinder parabolic_cylinder; } data; + + /* 3x4 column major transformation of the quadric in object space */ + double transform[12]; }; -#define SSOL_QUADRIC_DEFAULT__ \ - {SSOL_QUADRIC_PLANE, {SSOL_QUADRIC_PLANE_DEFAULT__}} +#define SSOL_QUADRIC_DEFAULT__ { \ + SSOL_QUADRIC_PLANE, \ + {SSOL_QUADRIC_PLANE_DEFAULT__}, \ + {1,0,0, 0,1,0, 0,0,1, 0,0,0} \ +} static const struct ssol_quadric SSOL_QUADRIC_DEFAULT = SSOL_QUADRIC_DEFAULT__; /* Define the contour of a 2D polygon as well as the clipping operation to @@ -370,6 +376,12 @@ SSOL_API res_T ssol_shape_ref_put (struct ssol_shape* shape); +/* Retrieve the id of the shape */ +SSOL_API res_T +ssol_shape_get_id + (struct ssol_shape* shape, + uint32_t* id); + /* Define a punched surface in local space, i.e. no translation & no orientation */ SSOL_API res_T ssol_punched_surface_setup @@ -422,9 +434,6 @@ ssol_mirror_set_shader SSOL_API res_T ssol_object_create (struct ssol_device* dev, - struct ssol_shape* shape, - struct ssol_material* mtl_front, /* Material to apply to front faces */ - struct ssol_material* mtl_back, /* Material to apply to back faces */ struct ssol_object** obj); SSOL_API res_T @@ -435,6 +444,18 @@ SSOL_API res_T ssol_object_ref_put (struct ssol_object* obj); +SSOL_API res_T +ssol_object_add_shaded_shape + (struct ssol_object* object, + struct ssol_shape* shape, + struct ssol_material* mtl_front, /* Front face material of the shape */ + struct ssol_material* mtl_back); /* Back face material of the shape */ + +/* Remove all the shaded shapes */ +SSOL_API res_T +ssol_object_clear + (struct ssol_object* object); + /******************************************************************************* * Object Instance API - Clone of an object with a set of per instance data as * world transformation, material parameters, etc. Note that the object @@ -566,7 +587,7 @@ ssol_sun_set_buie_param /******************************************************************************* * Atmosphere API - Describe an atmosphere model. ******************************************************************************/ -/* The atmosphere describes absorbtion along the light paths */ +/* The atmosphere describes absorption along the light paths */ SSOL_API res_T ssol_atmosphere_create_uniform (struct ssol_device* dev, @@ -582,7 +603,7 @@ ssol_atmosphere_ref_put /* List of per wavelength power of the sun */ SSOL_API res_T -ssol_atmosphere_set_uniform_absorbtion +ssol_atmosphere_set_uniform_absorption (struct ssol_atmosphere* atmosphere, struct ssol_spectrum* spectrum); diff --git a/src/ssol_atmosphere.c b/src/ssol_atmosphere.c @@ -62,7 +62,7 @@ compute_atmosphere_attenuation switch (atmosphere->type) { case ATMOS_UNIFORM: spectrum = atmosphere->data.uniform.spectrum; - CHECK(spectrum_interpolate(spectrum, wavelength, &ka), RES_OK); + ka = spectrum_interpolate(spectrum, wavelength); break; default: FATAL("Unreachable code\n"); break; } @@ -124,7 +124,7 @@ ssol_atmosphere_ref_put } res_T -ssol_atmosphere_set_uniform_absorbtion +ssol_atmosphere_set_uniform_absorption (struct ssol_atmosphere* atmosphere, struct ssol_spectrum* spectrum) { @@ -139,4 +139,4 @@ ssol_atmosphere_set_uniform_absorbtion SSOL(spectrum_ref_get(spectrum)); uni->spectrum = spectrum; return RES_OK; -} -\ No newline at end of file +} diff --git a/src/ssol_object.c b/src/ssol_object.c @@ -33,9 +33,10 @@ object_release(ref_T* ref) ASSERT(ref); dev = object->dev; ASSERT(dev && dev->allocator); - SSOL(shape_ref_put(object->shape)); - SSOL(material_ref_put(object->mtl_front)); - SSOL(material_ref_put(object->mtl_back)); + SSOL(object_clear(object)); + darray_shaded_shape_release(&object->shaded_shapes); + htable_shaded_shape_release(&object->shaded_shapes_rt); + htable_shaded_shape_release(&object->shaded_shapes_samp); 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); @@ -48,15 +49,12 @@ object_release(ref_T* ref) res_T ssol_object_create (struct ssol_device* dev, - struct ssol_shape* shape, - struct ssol_material* mtl_front, - struct ssol_material* mtl_back, struct ssol_object** out_object) { struct ssol_object* object = NULL; res_T res = RES_OK; - if(!dev || !shape || !mtl_front || !mtl_back || !out_object) { + if(!dev || !out_object) { res = RES_BAD_ARG; goto error; } @@ -66,28 +64,19 @@ ssol_object_create res = RES_MEM_ERR; goto error; } - /* Check if material/shape association is legit: TODO */ - SSOL(shape_ref_get(shape)); - SSOL(material_ref_get(mtl_front)); - SSOL(material_ref_get(mtl_back)); SSOL(device_ref_get(dev)); object->dev = dev; - object->shape = shape; - object->mtl_front = mtl_front; - object->mtl_back = mtl_back; ref_init(&object->ref); + darray_shaded_shape_init(dev->allocator, &object->shaded_shapes); + htable_shaded_shape_init(dev->allocator, &object->shaded_shapes_rt); + htable_shaded_shape_init(dev->allocator, &object->shaded_shapes_samp); /* 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->scn_samp, object->shape->shape_samp); - if(res != RES_OK) goto error; exit: if(out_object) *out_object = object; @@ -99,7 +88,6 @@ error: } goto exit; } - res_T ssol_object_ref_get(struct ssol_object* object) { @@ -116,3 +104,113 @@ ssol_object_ref_put(struct ssol_object* object) return RES_OK; } +res_T +ssol_object_add_shaded_shape + (struct ssol_object* object, + struct ssol_shape* shape, + struct ssol_material* front, + struct ssol_material* back) +{ + enum { + ATTACH_S3D_RT, ATTACH_S3D_SAMP, REGISTER_RT, REGISTER_SAMP, REGISTER_SHAPE + }; + struct shaded_shape* shaded_shape; + unsigned id_rt, id_samp; + size_t i; + int mask = 0; + res_T res = RES_OK; + + if(!object || !shape || !front || !back) { + res = RES_BAD_ARG; + goto error; + } + + S3D(shape_get_id(shape->shape_rt, &id_rt)); + S3D(shape_get_id(shape->shape_samp, &id_samp)); + if(htable_shaded_shape_find(&object->shaded_shapes_rt, &id_rt)) { + log_warning + (object->dev, "%s: the object already own the shape.\n", FUNC_NAME); + goto exit; + } + + /* Add the shape RT to the RT scene of the object */ + res = s3d_scene_attach_shape(object->scn_rt, shape->shape_rt); + if(res != RES_OK) goto error; + mask |= BIT(ATTACH_S3D_RT); + + /* Add the shape samp to the sampling scene of the object */ + res = s3d_scene_attach_shape(object->scn_samp, shape->shape_samp); + if(res != RES_OK) goto error; + mask |= BIT(ATTACH_S3D_SAMP); + + /* Ask for a shaded shape identifier */ + i = darray_shaded_shape_size_get(&object->shaded_shapes); + res = darray_shaded_shape_resize(&object->shaded_shapes, i+1); + if(res != RES_OK) goto error; + mask |= BIT(REGISTER_SHAPE); + + /* Register the RT shape identifer */ + res = htable_shaded_shape_set(&object->shaded_shapes_rt, &id_rt, &i); + if(res != RES_OK) goto error; + mask |= BIT(REGISTER_RT); + + /* Register the samp shape identifier */ + res = htable_shaded_shape_set(&object->shaded_shapes_samp, &id_samp, &i); + if(res != RES_OK) goto error; + mask |= BIT(REGISTER_SAMP); + + /* Setup the object shaded shape */ + SSOL(shape_ref_get(shape)); + SSOL(material_ref_get(front)); + SSOL(material_ref_get(back)); + shaded_shape = darray_shaded_shape_data_get(&object->shaded_shapes)+i; + shaded_shape->shape = shape; + shaded_shape->mtl_front = front; + shaded_shape->mtl_back = back; + +exit: + return res; +error: + if(mask & BIT(ATTACH_S3D_RT)) { + S3D(scene_detach_shape(object->scn_rt, shape->shape_rt)); + } + if(mask & BIT(ATTACH_S3D_SAMP)) { + S3D(scene_detach_shape(object->scn_samp, shape->shape_samp)); + } + if(mask & BIT(REGISTER_SHAPE)) { + darray_shaded_shape_pop_back(&object->shaded_shapes); + } + if(mask & BIT(REGISTER_RT)) { + i = htable_shaded_shape_erase(&object->shaded_shapes_rt, &id_rt); + ASSERT(i == 1); + } + if(mask & BIT(REGISTER_SAMP)) { + i = htable_shaded_shape_erase(&object->shaded_shapes_samp, &id_samp); + ASSERT(i == 1); + } + goto exit; +} + +res_T +ssol_object_clear(struct ssol_object* obj) +{ + size_t i, n; + if(!obj) return RES_BAD_ARG; + + n = darray_shaded_shape_size_get(&obj->shaded_shapes); + FOR_EACH(i, 0, n) { + struct shaded_shape* s = darray_shaded_shape_data_get(&obj->shaded_shapes); + SSOL(shape_ref_put(s->shape)); + SSOL(material_ref_put(s->mtl_front)); + SSOL(material_ref_put(s->mtl_back)); + } + darray_shaded_shape_clear(&obj->shaded_shapes); + htable_shaded_shape_clear(&obj->shaded_shapes_rt); + htable_shaded_shape_clear(&obj->shaded_shapes_samp); + + S3D(scene_clear(obj->scn_rt)); + S3D(scene_clear(obj->scn_samp)); + + return RES_OK; +} + diff --git a/src/ssol_object_c.h b/src/ssol_object_c.h @@ -16,12 +16,34 @@ #ifndef SSOL_OBJECT_C_H #define SSOL_OBJECT_C_H +#include <rsys/dynamic_array.h> +#include <rsys/hash_table.h> #include <rsys/ref_count.h> -struct ssol_object { +struct shaded_shape { struct ssol_shape* shape; - struct ssol_material* mtl_front; /* Front faces material */ - struct ssol_material* mtl_back; /* Back faces material */ + struct ssol_material* mtl_back; /* Material of the front faces */ + struct ssol_material* mtl_front; /* Material of the back faces */ +}; + +/* Define the darray_shaded_shape data structure */ +#define DARRAY_NAME shaded_shape +#define DARRAY_DATA struct shaded_shape +#include <rsys/dynamic_array.h> + +/* Define the htable_shaded_shape data structure */ +#define HTABLE_NAME shaded_shape +#define HTABLE_KEY unsigned /* S3D object instance identifier */ +#define HTABLE_DATA size_t +#include <rsys/hash_table.h> + +struct ssol_object { + /* List of shaded shapes added to the object */ + struct darray_shaded_shape shaded_shapes; + + /* Map the RT/Samp S3D id to an entry into the shaded_shapes array */ + struct htable_shaded_shape shaded_shapes_rt; + struct htable_shaded_shape shaded_shapes_samp; struct s3d_scene* scn_rt; /* RT scene to instantiate */ struct s3d_scene* scn_samp; /* Sampling scene to instantiate */ diff --git a/src/ssol_ranst_sun_dir.c b/src/ssol_ranst_sun_dir.c @@ -257,9 +257,9 @@ ran_pillbox_get ******************************************************************************/ static double* ran_dirac_get -(const struct ranst_sun_dir* ran, - struct ssp_rng* rng, - double dir[3]) + (const struct ranst_sun_dir* ran, + struct ssp_rng* rng, + double dir[3]) { (void) rng; ASSERT(d3_is_normalized(ran->state.dirac.dir)); @@ -356,9 +356,9 @@ ranst_sun_dir_dirac_setup const double dir[3]) { if (!ran || !dir) return RES_BAD_ARG; - if (0 == d3_normalize(ran->state.dirac.dir, dir)) - /* zero vector */ - return RES_BAD_ARG; + if (0 == d3_normalize(ran->state.dirac.dir, dir)) { + return RES_BAD_ARG; /* zero vector */ + } ran->get = ran_dirac_get; return RES_OK; } diff --git a/src/ssol_ranst_sun_dir.h b/src/ssol_ranst_sun_dir.h @@ -16,19 +16,33 @@ #ifndef SSOL_RANST_SUN_DIR_H #define SSOL_RANST_SUN_DIR_H -/* Random variate state of a sun direction */ -struct ranst_sun_dir; - /* External types */ struct ssp_rng; struct mem_allocator; +/* Random variate state of a sun direction */ +struct ranst_sun_dir; + extern LOCAL_SYM res_T ranst_sun_dir_create (struct mem_allocator* allocator, struct ranst_sun_dir** ran); extern LOCAL_SYM res_T +ranst_sun_dir_ref_get + (struct ranst_sun_dir* ran); + +extern LOCAL_SYM res_T +ranst_sun_dir_ref_put + (struct ranst_sun_dir* ran); + +extern LOCAL_SYM double* +ranst_sun_dir_get + (const struct ranst_sun_dir* ran, + struct ssp_rng* rng, + double dir[3]); + +extern LOCAL_SYM res_T ranst_sun_dir_buie_setup (struct ranst_sun_dir* ran, const double param, @@ -45,19 +59,5 @@ ranst_sun_dir_dirac_setup (struct ranst_sun_dir* ran, const double dir[3]); -extern LOCAL_SYM res_T -ranst_sun_dir_ref_get - (struct ranst_sun_dir* ran); - -extern LOCAL_SYM res_T -ranst_sun_dir_ref_put - (struct ranst_sun_dir* ran); - -extern LOCAL_SYM double* -ranst_sun_dir_get - (const struct ranst_sun_dir* ran, - struct ssp_rng* rng, - double dir[3]); - #endif /* SSOL_RANST_SUN_DIR_H */ diff --git a/src/ssol_ranst_sun_wl.c b/src/ssol_ranst_sun_wl.c @@ -24,7 +24,7 @@ #include <rsys/rsys.h> #include <rsys/ref_count.h> - /******************************************************************************* +/******************************************************************************* * Distributions types for wavelengths ******************************************************************************/ struct ran_piecewise_wl_state { @@ -42,7 +42,7 @@ enum wl_ran_type { }; /* One single type for all distributions. Only the state type depends on the -* distribution type */ + * distribution type */ struct ranst_sun_wl { double(*get) (const struct ranst_sun_wl* ran, struct ssp_rng* rng); @@ -66,13 +66,13 @@ distrib_sun_wl_release(ref_T* ref) ASSERT(ref); ran = CONTAINER_OF(ref, struct ranst_sun_wl, ref); switch (ran->type) { - case WL_DIRAC: - break; - case WL_PIECEWISE: - SSP(ranst_piecewise_linear_ref_put(ran->state.piecewise.spectrum)); - ran->state.piecewise.spectrum = NULL; - break; - default: FATAL("Unreachable code\n"); break; + case WL_DIRAC: + break; + case WL_PIECEWISE: + SSP(ranst_piecewise_linear_ref_put(ran->state.piecewise.spectrum)); + ran->state.piecewise.spectrum = NULL; + break; + default: FATAL("Unreachable code\n"); break; } MEM_RM(ran->allocator, ran); } @@ -85,7 +85,8 @@ ran_piecewise_get (const struct ranst_sun_wl* ran, struct ssp_rng* rng) { - ASSERT(ran && rng && ran->type == WL_PIECEWISE && ran->state.piecewise.spectrum); + ASSERT(ran && rng && ran->type == WL_PIECEWISE); + ASSERT(ran->state.piecewise.spectrum); return ssp_ranst_piecewise_linear_get(ran->state.piecewise.spectrum, rng); } @@ -94,8 +95,8 @@ ran_piecewise_get ******************************************************************************/ static double ran_dirac_get -(const struct ranst_sun_wl* ran, - struct ssp_rng* rng) + (const struct ranst_sun_wl* ran, + struct ssp_rng* rng) { (void) rng; ASSERT(ran && rng && ran->type == WL_DIRAC); @@ -164,24 +165,24 @@ ranst_sun_wl_setup if (sz > 1) { ran->type = WL_PIECEWISE; ran->get = &ran_piecewise_get; - res = ssp_ranst_piecewise_linear_create( - ran->allocator, &ran->state.piecewise.spectrum); + res = ssp_ranst_piecewise_linear_create + (ran->allocator, &ran->state.piecewise.spectrum); if (res != RES_OK) goto error; res = ssp_ranst_piecewise_linear_setup - (ran->state.piecewise.spectrum, wavelengths, intensities, sz); + (ran->state.piecewise.spectrum, wavelengths, intensities, sz); if (res != RES_OK) goto error; - } - else { + } else { ran->type = WL_DIRAC; ran->get = &ran_dirac_get; ran->state.dirac.wavelength = wavelengths[0]; } -end: +exit: return res; error: - if (ran->state.piecewise.spectrum) + if(ran->state.piecewise.spectrum) { SSP(ranst_piecewise_linear_ref_put(ran->state.piecewise.spectrum)); - ran->state.piecewise.spectrum = NULL; - goto end; + ran->state.piecewise.spectrum = NULL; + } + goto exit; } diff --git a/src/ssol_ranst_sun_wl.h b/src/ssol_ranst_sun_wl.h @@ -16,26 +16,19 @@ #ifndef SSOL_RANST_SUN_WL_H #define SSOL_RANST_SUN_WL_H -/* Random variate state of a sun direction */ -struct ranst_sun_wl; - /* External types */ struct ssp_rng; struct mem_allocator; +/* Random variate state of a sun direction */ +struct ranst_sun_wl; + extern LOCAL_SYM res_T ranst_sun_wl_create (struct mem_allocator* allocator, struct ranst_sun_wl** ran); extern LOCAL_SYM res_T -ranst_sun_wl_setup - (struct ranst_sun_wl* ran, - const double* wavelengths, - const double* intensities, - const size_t sz); - -extern LOCAL_SYM res_T ranst_sun_wl_ref_get (struct ranst_sun_wl* ran); @@ -48,5 +41,12 @@ ranst_sun_wl_get (const struct ranst_sun_wl* ran, struct ssp_rng* rng); +extern LOCAL_SYM res_T +ranst_sun_wl_setup + (struct ranst_sun_wl* ran, + const double* wavelengths, + const double* intensities, + const size_t sz); + #endif /* SSOL_RANST_SUN_WL_H */ diff --git a/src/ssol_scene.c b/src/ssol_scene.c @@ -121,7 +121,7 @@ ssol_scene_attach_instance res_T res; if(!scene || !instance) return RES_BAD_ARG; - + /* 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; @@ -291,9 +291,8 @@ scene_setup_s3d_sampling_scene unsigned id; htable_instance_iterator_next(&it); - if (!str_is_empty(&inst->receiver_back) - || !str_is_empty(&inst->receiver_front)) - { + if(!str_is_empty(&inst->receiver_back) + || !str_is_empty(&inst->receiver_front)) { hr = 1; } @@ -340,10 +339,12 @@ hit_filter_function void* filter_data) { struct ssol_instance* inst; + const struct shaded_shape* shaded_shape; const struct ssol_shape* shape; const struct str* receiver_name; struct realisation* rs = realisation; struct segment* seg; + size_t id; (void) filter_data, (void) org, (void) dir; ASSERT(rs); @@ -357,44 +358,57 @@ hit_filter_function ASSERT(seg->self_front != NON_BOOL); inst = *htable_instance_find(&rs->data.scene->instances_rt, &hit->prim.inst_id); - shape = inst->object->shape; + id = *htable_shaded_shape_find + (&inst->object->shaded_shapes_rt, &hit->prim.geom_id); + shaded_shape = darray_shaded_shape_cdata_get(&inst->object->shaded_shapes)+id; + shape = shaded_shape->shape; seg->on_punched = (shape->type == SHAPE_PUNCHED); switch (shape->type) { - case SHAPE_PUNCHED: { - /* hits on quadrics must be recomputed more accurately */ - double org_local[3], hit_pos_local[3], dir_local[3]; - const double* transform = inst->transform; - double tr[9]; - int valid; - d33_inverse(tr, transform); - - /* get org in local coordinate */ - d3_set(org_local, seg->org); - d3_sub(org_local, org_local, transform + 9); - d33_muld3(org_local, tr, org_local); - - /* get dir in local */ - d33_muld3(dir_local, tr, seg->dir); - /* recompute hit */ - valid = punched_shape_intersect_local(shape, org_local, dir_local, - hit->distance, hit_pos_local, seg->hit_normal, &seg->hit_distance); - if (!valid) return 1; - /* transform point to world */ - d33_muld3(seg->hit_pos, transform, hit_pos_local); - d3_add(seg->hit_pos, transform + 9, seg->hit_pos); - /* transform normal to world */ - d33_invtrans(tr, transform); - d33_muld3(seg->hit_normal, tr, seg->hit_normal); - break; - } - case SHAPE_MESH: { - d3_set_f3(seg->hit_normal, hit->normal); - /* use raytraced distance to fill hit_pos */ - d3_add(seg->hit_pos, seg->org, d3_muld(seg->hit_pos, seg->dir, hit->distance)); - seg->hit_distance = hit->distance; - break; - } - default: FATAL("Unreachable code.\n"); break; + case SHAPE_MESH: { + d3_set_f3(seg->hit_normal, hit->normal); + /* use raytraced distance to fill hit_pos */ + d3_add(seg->hit_pos, seg->org, d3_muld(seg->hit_pos, seg->dir, hit->distance)); + seg->hit_distance = hit->distance; + break; + } + case SHAPE_PUNCHED: { + /* hits on quadrics must be recomputed more accurately */ + double org_local[3], hit_pos_local[3], dir_local[3]; + double R[9]; /* Rotation matrix */ + double T[3]; /* Translation vector */ + double R_invtrans[9]; /* Inverse transpose rotation matrix */ + double T_inv[3]; /* Inverse of the translation vector */ + int valid; + + if(d33_is_identity(shape->quadric.transform)) { + d33_set(R, inst->transform); + d3_set (T, inst->transform+9); + } else { + d33_muld33(R, shape->quadric.transform, inst->transform); + d33_muld3 (T, shape->quadric.transform, inst->transform+9); + } + d33_invtrans(R_invtrans, R); + d3_minus(T_inv, T); + + /* get org in local coordinate */ + d3_set(org_local, seg->org); + d3_add(org_local, org_local, T_inv); + d3_muld33(org_local, org_local, R_invtrans); + + /* get dir in local */ + d3_muld33(dir_local, seg->dir, R_invtrans); + /* recompute hit */ + valid = punched_shape_intersect_local(shape, org_local, dir_local, + hit->distance, hit_pos_local, seg->hit_normal, &seg->hit_distance); + if (!valid) return 1; + /* transform point to world */ + d33_muld3(seg->hit_pos, R, hit_pos_local); + d3_add(seg->hit_pos, seg->hit_pos, T); + /* transform normal to world */ + d33_muld3(seg->hit_normal, R_invtrans, seg->hit_normal); + break; + } + default: FATAL("Unreachable code.\n"); break; } d3_normalize(seg->hit_normal, seg->hit_normal); @@ -405,11 +419,11 @@ hit_filter_function } if(seg->hit_front) { - seg->hit_material = inst->object->mtl_front; + seg->hit_material = shaded_shape->mtl_front; receiver_name = &inst->receiver_front; } else { d3_muld(seg->hit_normal, seg->hit_normal, -1); - seg->hit_material = inst->object->mtl_back; + seg->hit_material = shaded_shape->mtl_back; receiver_name = &inst->receiver_back; } diff --git a/src/ssol_scene_c.h b/src/ssol_scene_c.h @@ -36,12 +36,15 @@ struct ssol_scene; struct ssol_sun; struct ssol_scene { + /* Map the instantiated RT/Samp S3D shape id to its SSOL intrance */ struct htable_instance instances_rt; struct htable_instance instances_samp; - struct s3d_scene* scn_rt; - struct s3d_scene* scn_samp; - struct ssol_sun* sun; - struct ssol_atmosphere* atmosphere; + + struct s3d_scene* scn_rt; /* S3D scene to ray trace */ + struct s3d_scene* scn_samp; /* S3D scene to sample */ + + struct ssol_sun* sun; /* Sun of the scene */ + struct ssol_atmosphere* atmosphere; /* Atmosphere of the scene */ struct ssol_device* dev; ref_T ref; diff --git a/src/ssol_shape.c b/src/ssol_shape.c @@ -18,10 +18,12 @@ #include "ssol_device_c.h" #include "ssol_shape_c.h" -#include <rsys/double3.h> #include <rsys/double2.h> +#include <rsys/double3.h> +#include <rsys/double33.h> #include <rsys/dynamic_array_double.h> #include <rsys/dynamic_array_size_t.h> +#include <rsys/float3.h> #include <rsys/mem_allocator.h> #include <rsys/ref_count.h> #include <rsys/rsys.h> @@ -40,6 +42,7 @@ struct quadric_mesh_context { const double* coords; const size_t* ids; double focal; /* Use by parabol and parabolic cylinder quadrics */ + const double* transform; /* 3x4 column major matrix */ }; /******************************************************************************* @@ -171,10 +174,17 @@ quadric_mesh_plane_get_pos(const unsigned ivert, float pos[3], void* ctx) { const size_t i = ivert*2/*#coords per vertex*/; const struct quadric_mesh_context* msh = ctx; + double p[3]; /* Temporary quadric space position */ ASSERT(pos && ctx); - pos[0] = (float)msh->coords[i+0]; - pos[1] = (float)msh->coords[i+1]; - pos[2] = 0.f; + p[0] = (float)msh->coords[i+0]; + p[1] = (float)msh->coords[i+1]; + p[2] = 0.f; + + /* Transform the position in object space */ + d33_muld3(p, msh->transform, p); + d3_add(p, p, msh->transform+9); + + f3_set_d3(pos, p); } static void @@ -182,13 +192,17 @@ quadric_mesh_parabol_get_pos(const unsigned ivert, float pos[3], void* ctx) { const size_t i = ivert*2/*#coords per vertex*/; const struct quadric_mesh_context* msh = ctx; - double x, y; + double p[3]; /* Temporary quadric space position */ ASSERT(pos && ctx); - x = msh->coords[i+0]; - y = msh->coords[i+1]; - pos[0] = (float)x; - pos[1] = (float)y; - pos[2] = (float)((x*x + y*y) / (4.0*msh->focal)); + p[0] = msh->coords[i+0]; + p[1] = msh->coords[i+1]; + p[2] = (p[0]*p[0] + p[1]*p[1]) / (4.0*msh->focal); + + /* Transform the position in object space */ + d33_muld3(p, msh->transform, p); + d3_add(p, p, msh->transform+9); + + f3_set_d3(pos, p); } static void @@ -197,13 +211,17 @@ quadric_mesh_parabolic_cylinder_get_pos { const size_t i = ivert*2/*#coords per vertex*/; const struct quadric_mesh_context* msh = ctx; - double x, y; + double p[3]; /* Temporary quadric space position */ ASSERT(pos && ctx); - x = msh->coords[i+0]; - y = msh->coords[i+1]; - pos[0] = (float)x; - pos[1] = (float)y; - pos[2] = (float)((y*y) / (4.0*msh->focal)); + p[0] = msh->coords[i+0]; + p[1] = msh->coords[i+1]; + p[2] = ((p[1]*p[1]) / (4.0*msh->focal)); + + /* Transform the position in object space */ + d33_muld3(p, msh->transform, p); + d3_add(p, p, msh->transform+9); + + f3_set_d3(pos, p); } static FINLINE int @@ -425,6 +443,7 @@ quadric_setup_s3d_shape_rt 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); + ctx.transform = quadric->transform; vdata.usage = S3D_POSITION; vdata.type = S3D_FLOAT3; @@ -538,9 +557,9 @@ inject_same_sign(const double x, const double src) return ucast.d; } -/* solve a 2nd degree equation - hint is used to select among the 2 solutions (if applies) - the selected solution is then the closest to hint positive value */ +/* Solve a 2nd degree equation + * hint is used to select among the 2 solutions (if applies) + * the selected solution is then the closest to hint positive value */ static int quadric_solve_second (const double a, @@ -550,38 +569,38 @@ quadric_solve_second double* dist) { ASSERT(dist); - if (a != 0) { - /* standard case: 2nd degree */ + if(a != 0) { + /* Standard case: 2nd degree */ const double delta = b * b - 4 * a * c; - if (delta > 0) { + if(delta > 0) { const double sqrt_delta = sqrt(delta); - /* precise formula */ + /* Precise formula */ const double t1 = (-b - inject_same_sign(sqrt_delta, b)) / (2 * b); const double t2 = c / (a * t1); - if (t1 < 0 && t2 < 0) return 0; /* no positive solution */ - if (t1 < 0) { + if(t1 < 0 && t2 < 0) return 0; /* no positive solution */ + if(t1 < 0) { *dist = t2; /* t2 is the only positive solution */ return 1; } - if (t2 < 0) { + if(t2 < 0) { *dist = t1; /* t1 is the only positive solution */ return 1; } - /* both t1 and t2 are positive: choose the closest value to hint */ + /* Both t1 and t2 are positive: choose the closest value to hint */ *dist = fabs(t1 - hint) < fabs(t2 - hint) ? t1 : t2; return 1; - } else if (delta == 0) { + } else if(delta == 0) { const double t = -b / (2 * a); - if (t < 0) return 0; /* no positive solution */ + if(t < 0) return 0; /* no positive solution */ *dist = t; return 1; } else { return 0; } - } else if (b != 0) { + } else if(b != 0) { /* degenerated case: 1st degree only */ const double t = -c / b; - if (t < 0) return 0; /* no positive solution */ + if(t < 0) return 0; /* no positive solution */ *dist = t; return 1; } @@ -632,7 +651,7 @@ quadric_plane_intersect_local const double b = dir[2]; const double c = org[2]; int sol = quadric_solve_second(a, b, c, 0, dist); - if (!sol) return 0; + if(!sol) return 0; d3_add(pt, org, d3_muld(pt, dir, *dist)); quadric_plane_gradient_local(grad); return 1; @@ -654,7 +673,7 @@ quadric_parabol_intersect_local 2 * org[0] * dir[0] + 2 * org[1] * dir[1] - 4 * quad->focal * dir[2]; const double c = org[0] * org[0] + org[1] * org[1] - 4 * quad->focal * org[2]; const int sol = quadric_solve_second(a, b, c, hint, dist); - if (!sol) return 0; + if(!sol) return 0; d3_add(pt, org, d3_muld(pt, dir, *dist)); quadric_parabol_gradient_local(quad, pt, grad); return 1; @@ -675,7 +694,7 @@ quadric_parabolic_cylinder_intersect_local const double b = 2 * org[1] * dir[1] - 4 * quad->focal * dir[2]; const double c = org[1] * org[1] - 4 * quad->focal * org[2]; const int sol = quadric_solve_second(a, b, c, hint, dist); - if (!sol) return 0; + if(!sol) return 0; d3_add(pt, org, d3_muld(pt, dir, *dist)); quadric_parabolic_cylinder_gradient_local(quad, pt, grad); return 1; @@ -821,6 +840,17 @@ ssol_shape_ref_put(struct ssol_shape* shape) } res_T +ssol_shape_get_id(struct ssol_shape* shape, uint32_t* id) +{ + unsigned ui; + STATIC_ASSERT(sizeof(unsigned) <= sizeof(uint32_t), Unexpected_sizeof_unsigned); + if(!shape || !id) return RES_BAD_ARG; + S3D(shape_get_id(shape->shape_rt, &ui)); + *id = (uint32_t)ui; + return RES_OK; +} + +res_T ssol_punched_surface_setup (struct ssol_shape* shape, const struct ssol_punched_surface* psurf) diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -67,39 +67,33 @@ cmp_candidates(const void* _c1, const void* _c2) } static FINLINE res_T -check_scene(const struct ssol_scene* scene) { - ASSERT(scene); +check_scene(const struct ssol_scene* scene, const char* caller) +{ + ASSERT(scene && caller); + if (!scene->sun) { - log_error(scene->dev, "%s: no sun attached.\n", FUNC_NAME); + log_error(scene->dev, "%s: no sun attached.\n", caller); return RES_BAD_ARG; } if (!scene->sun->spectrum) { - log_error(scene->dev, "%s: sun's spectrum undefined.\n", FUNC_NAME); + log_error(scene->dev, "%s: sun's spectrum undefined.\n", caller); return RES_BAD_ARG; } if (scene->sun->dni <= 0) { - log_error(scene->dev, "%s: sun's DNI undefined.\n", FUNC_NAME); + log_error(scene->dev, "%s: sun's DNI undefined.\n", caller); return RES_BAD_ARG; } if (scene->atmosphere) { - switch (scene->atmosphere->type) { - case ATMOS_UNIFORM: { - char ok; - CHECK(spectrum_includes( - scene->atmosphere->data.uniform.spectrum, - scene->sun->spectrum, - &ok), - RES_OK); - if (!ok) { - log_error(scene->dev, "%s: sun/atmosphere spectra mismatch.\n", FUNC_NAME); - return RES_BAD_ARG; - } - break; - } - default: FATAL("Unreachable code\n"); break; + int i; + ASSERT(scene->atmosphere->type == ATMOS_UNIFORM); + i = spectrum_includes + (scene->atmosphere->data.uniform.spectrum, scene->sun->spectrum); + if (!i) { + log_error(scene->dev, "%s: sun/atmosphere spectra mismatch.\n", caller); + return RES_BAD_ARG; } } return RES_OK; @@ -471,6 +465,7 @@ sample_starting_point(struct realisation* rs) struct solver_data* data; struct s3d_primitive sampl_prim; struct starting_point* start; + size_t id; ASSERT(rs); data = &rs->data; @@ -489,7 +484,11 @@ sample_starting_point(struct realisation* rs) start->instance = *htable_instance_find (&data->scene->instances_samp, &sampl_prim.inst_id); start->sampl_primitive = sampl_prim; - shape = start->instance->object->shape; + id = *htable_shaded_shape_find + (&start->instance->object->shaded_shapes_samp, &sampl_prim.geom_id); + start->shaded_shape = darray_shaded_shape_cdata_get + (&start->instance->object->shaded_shapes)+id; + shape = start->shaded_shape->shape; start->on_punched = (shape->type == SHAPE_PUNCHED); /* set sampling normal */ S3D(primitive_get_attrib(&sampl_prim, S3D_GEOMETRY_NORMAL, start->uv, &attrib)); @@ -503,21 +502,36 @@ sample_starting_point(struct realisation* rs) break; } case SHAPE_PUNCHED: { - const double* transform = start->instance->transform; - double tr[9], pos_local[3]; + struct ssol_instance* inst = start->instance; + double pos_local[3]; + double R[9]; /* Rotation matrix */ + double T[3]; /* Translation vector */ + double R_invtrans[9]; /* Inverse transpose rotation matrix */ + double T_inv[3]; /* Inverse of the translation vector */ + + if(d33_is_identity(shape->quadric.transform)) { + d33_set(R, inst->transform); + d3_set (T, inst->transform+9); + } else { + d33_muld33(R, shape->quadric.transform, inst->transform); + d33_muld3 (T, shape->quadric.transform, inst->transform+9); + } + d33_invtrans(R_invtrans, R); + d3_minus(T_inv, T); + /* project the sampled point on the quadric */ - d33_inverse(tr, transform); - d3_sub(pos_local, start->pos, transform + 9); - d33_muld3(pos_local, tr, pos_local); + d3_set(pos_local, start->pos); + d3_add(pos_local, pos_local, T_inv); + d3_muld33(pos_local, pos_local, R_invtrans); + punched_shape_set_z_local(shape, pos_local); /* transform point to world */ - d33_muld3(start->pos, transform, pos_local); - d3_add(start->pos, transform + 9, start->pos); + d33_muld3(start->pos, R, pos_local); + d3_add(start->pos, start->pos, T); /* compute exact normal on the instance */ punched_shape_set_normal_local(shape, pos_local, start->rt_normal); /* transform normal to world */ - d33_invtrans(tr, transform); - d33_muld3(start->rt_normal, tr, start->rt_normal); + d33_muld3(start->rt_normal, R_invtrans, start->rt_normal); break; } default: FATAL("Unreachable code.\n"); break; @@ -568,9 +582,9 @@ receive_sunlight(struct realisation* rs) start->geom_cos = d3_dot(start->rt_normal, start->sundir); start->front_exposed = start->geom_cos < 0; if (start->front_exposed) { - start->material = start->instance->object->mtl_front; + start->material = start->shaded_shape->mtl_front; } else { - start->material = start->instance->object->mtl_back; + start->material = start->shaded_shape->mtl_back; } /* normals must face the sun and cos must be positive */ if (start->geom_cos > 0) { @@ -774,7 +788,7 @@ ssol_solve if (!scene || !rng || !output || !estimator || !realisations_count) return RES_BAD_ARG; - res = check_scene(scene); + res = check_scene(scene, FUNC_NAME); if (res != RES_OK) return res; /* init realisation */ diff --git a/src/ssol_solver_c.h b/src/ssol_solver_c.h @@ -60,6 +60,7 @@ struct segment { struct starting_point { struct ssol_instance* instance; + const struct shaded_shape* shaded_shape; const struct ssol_material* material; struct s3d_primitive sampl_primitive; double sundir[3]; diff --git a/src/ssol_spectrum.c b/src/ssol_spectrum.c @@ -40,105 +40,96 @@ spectrum_release(ref_T* ref) SSOL(device_ref_put(dev)); } -static char +static int spectrum_includes_point (const struct ssol_spectrum* spectrum, - const double wavelenght) + const double wavelength) { const double* data; size_t sz; - ASSERT(spectrum && spectrum->wavelengths.data && spectrum->intensities.data); - sz = spectrum->wavelengths.size; - ASSERT(sz && sz == spectrum->intensities.size); - data = spectrum->wavelengths.data; - return data[0] <= wavelenght && wavelenght <= data[sz - 1]; + ASSERT(spectrum); + sz = darray_double_size_get(&spectrum->wavelengths); + ASSERT(sz && sz == darray_double_size_get(&spectrum->intensities)); + data = darray_double_cdata_get(&spectrum->wavelengths); + return data[0] <= wavelength && wavelength <= data[sz - 1]; } static int -eq_d(const void* key, const void* base) +eq_dbl(const void* key, const void* base) { - double k = *(double*) key; - double b = *(double*) base; - if (k > b) return +1; - if (k < b) return -1; + const double k = *(const double*) key; + const double b = *(const double*) base; + if(k > b) return +1; + if(k < b) return -1; return 0; } /******************************************************************************* -* Local ssol_spectrum functions -******************************************************************************/ -res_T + * Local ssol_spectrum functions + ******************************************************************************/ +int spectrum_includes (const struct ssol_spectrum* reference, - const struct ssol_spectrum* tested, - char* include) + const struct ssol_spectrum* tested) { const double* test_data; size_t test_sz; - if(!reference || !tested || !include) { - return RES_BAD_ARG; - } - - test_sz = tested->wavelengths.size; - test_data = tested->wavelengths.data; - *include = spectrum_includes_point(reference, test_data[0]) - && spectrum_includes_point(reference, test_data[test_sz - 1]); + ASSERT(reference && tested); - return RES_OK; + test_sz = darray_double_size_get(&tested->wavelengths); + test_data = darray_double_cdata_get(&tested->wavelengths); + return spectrum_includes_point(reference, test_data[0]) + && spectrum_includes_point(reference, test_data[test_sz - 1]); } -res_T +double spectrum_interpolate (const struct ssol_spectrum* spectrum, - const double wavelenght, - double* intensity) + const double wavelength) { - double* next; - double* wavelengths; - double* ints; + const double* wls; + const double* ints; + const double* next; double slope; - size_t idx_next, sz; - if (!spectrum - || !intensity - || !spectrum_includes_point(spectrum, wavelenght)) - { - return RES_BAD_ARG; - } - - sz = spectrum->wavelengths.size; - wavelengths = spectrum->wavelengths.data; - ints = spectrum->intensities.data; - next = search_lower_bound(&wavelenght, wavelengths, sz, sizeof(double), &eq_d); - ASSERT(next); /* cause spectrum_includes_point */ - idx_next = (size_t)(next - wavelengths); - ASSERT(idx_next); /* cause spectrum_includes_point */ - ASSERT(ints[idx_next] >= ints[idx_next - 1]); - ASSERT(wavelengths[idx_next] >= wavelengths[idx_next - 1]); - - slope = (ints[idx_next] - ints[idx_next - 1]) - / (wavelengths[idx_next] - wavelengths[idx_next - 1]); - *intensity = ints[idx_next - 1] - + (wavelenght - wavelengths[idx_next - 1]) * slope; - ASSERT(*intensity >= 0); - return RES_OK; + double intensity; + size_t id_next, sz; + ASSERT(spectrum && spectrum_includes_point(spectrum, wavelength)); + + sz = darray_double_size_get(&spectrum->wavelengths); + wls = darray_double_cdata_get(&spectrum->wavelengths); + ints = darray_double_cdata_get(&spectrum->intensities); + next = search_lower_bound(&wavelength, wls, sz, sizeof(double), &eq_dbl); + ASSERT(next); /* because spectrum_includes_point */ + + id_next = (size_t)(next - wls); + ASSERT(id_next); /* because spectrum_includes_point */ + ASSERT(ints[id_next] >= ints[id_next - 1]); + ASSERT(wls[id_next] >= wls[id_next - 1]); + + slope = (ints[id_next] - ints[id_next-1]) / (wls[id_next] - wls[id_next-1]); + intensity = ints[id_next-1] + (wavelength - wls[id_next - 1]) * slope; + ASSERT(intensity >= 0); + return intensity; } /******************************************************************************* -* Exported ssol_spectrum functions -******************************************************************************/ + * Exported ssol_spectrum functions + ******************************************************************************/ res_T ssol_spectrum_create (struct ssol_device* dev, struct ssol_spectrum** out_spectrum) { struct ssol_spectrum* spectrum = NULL; res_T res = RES_OK; - if (!dev || !out_spectrum) { - return RES_BAD_ARG; + + if(!dev || !out_spectrum) { + res = RES_BAD_ARG; + goto error; } spectrum = (struct ssol_spectrum*)MEM_CALLOC (dev->allocator, 1, sizeof(struct ssol_spectrum)); - if (!spectrum) { + if(!spectrum) { res = RES_MEM_ERR; goto error; } @@ -150,10 +141,10 @@ ssol_spectrum_create darray_double_init(dev->allocator, &spectrum->intensities); exit: - if (out_spectrum) *out_spectrum = spectrum; + if(out_spectrum) *out_spectrum = spectrum; return res; error: - if (spectrum) { + if(spectrum) { SSOL(spectrum_ref_put(spectrum)); spectrum = NULL; } @@ -163,8 +154,7 @@ error: res_T ssol_spectrum_ref_get(struct ssol_spectrum* spectrum) { - if (!spectrum) - return RES_BAD_ARG; + if(!spectrum) return RES_BAD_ARG; ref_get(&spectrum->ref); return RES_OK; } @@ -172,8 +162,7 @@ ssol_spectrum_ref_get(struct ssol_spectrum* spectrum) res_T ssol_spectrum_ref_put(struct ssol_spectrum* spectrum) { - if (!spectrum) - return RES_BAD_ARG; + if(!spectrum) return RES_BAD_ARG; ref_put(&spectrum->ref, spectrum_release); return RES_OK; } @@ -187,25 +176,29 @@ ssol_spectrum_setup { res_T res = RES_OK; size_t i; - if(!spectrum - || nwavelength <= 0 - || !wavelengths - || !data) - return RES_BAD_ARG; + if(!spectrum || !nwavelength || !wavelengths || !data) { + res = RES_BAD_ARG; + goto error; + } res = darray_double_resize(&spectrum->wavelengths, nwavelength); - if (res != RES_OK) return res; + if(res != RES_OK) goto error; res = darray_double_resize(&spectrum->intensities, nwavelength); - if (res != RES_OK) { - darray_double_clear(&spectrum->wavelengths); - return res; - } + if(res != RES_OK) goto error; FOR_EACH(i, 0, nwavelength) { spectrum->wavelengths.data[i] = wavelengths[i]; spectrum->intensities.data[i] = data[i]; } +exit: return res; +error: + if(spectrum) { + darray_double_clear(&spectrum->wavelengths); + darray_double_clear(&spectrum->intensities); + } + goto exit; } + diff --git a/src/ssol_spectrum_c.h b/src/ssol_spectrum_c.h @@ -22,20 +22,22 @@ struct ssol_spectrum { struct darray_double wavelengths; struct darray_double intensities; + struct ssol_device* dev; ref_T ref; }; -extern LOCAL_SYM res_T +/* Check that the `tested' spectrum is included into `reference' */ +extern LOCAL_SYM int spectrum_includes (const struct ssol_spectrum* reference, - const struct ssol_spectrum* tested, - char* include); + const struct ssol_spectrum* tested); -extern LOCAL_SYM res_T +/* Retrieve the linearly interpolated spectrum intensity for the commited + * wavelength */ +extern LOCAL_SYM double spectrum_interpolate (const struct ssol_spectrum* spectrum, - const double wavelenght, - double* intensity); + const double wavelength); #endif /* SSOL_SPECTRUM_C_H */ diff --git a/src/test_ssol_atmosphere.c b/src/test_ssol_atmosphere.c @@ -52,11 +52,11 @@ main(int argc, char** argv) CHECK(ssol_atmosphere_ref_put(NULL), RES_BAD_ARG); CHECK(ssol_atmosphere_ref_put(atm), RES_OK); - CHECK(ssol_atmosphere_set_uniform_absorbtion(NULL, spectrum), RES_BAD_ARG); - CHECK(ssol_atmosphere_set_uniform_absorbtion(atm, NULL), RES_BAD_ARG); - CHECK(ssol_atmosphere_set_uniform_absorbtion(atm, spectrum), RES_OK); - CHECK(ssol_atmosphere_set_uniform_absorbtion(atm, spectrum2), RES_OK); - CHECK(ssol_atmosphere_set_uniform_absorbtion(atm, spectrum2), RES_OK); + CHECK(ssol_atmosphere_set_uniform_absorption(NULL, spectrum), RES_BAD_ARG); + CHECK(ssol_atmosphere_set_uniform_absorption(atm, NULL), RES_BAD_ARG); + CHECK(ssol_atmosphere_set_uniform_absorption(atm, spectrum), RES_OK); + CHECK(ssol_atmosphere_set_uniform_absorption(atm, spectrum2), RES_OK); + CHECK(ssol_atmosphere_set_uniform_absorption(atm, spectrum2), RES_OK); CHECK(ssol_atmosphere_ref_put(atm), RES_OK); diff --git a/src/test_ssol_instance.c b/src/test_ssol_instance.c @@ -44,7 +44,8 @@ main(int argc, char** argv) CHECK(ssol_material_create_virtual(dev, &material), RES_OK); CHECK(ssol_shape_create_punched_surface(dev, &shape), RES_OK); - CHECK(ssol_object_create(dev, shape, material, material, &object), RES_OK); + CHECK(ssol_object_create(dev, &object), RES_OK); + CHECK(ssol_object_add_shaded_shape(object, shape, material, material), RES_OK); CHECK(ssol_object_instantiate(object, &instance), RES_OK); diff --git a/src/test_ssol_object.c b/src/test_ssol_object.c @@ -43,11 +43,27 @@ main(int argc, char** argv) CHECK(ssol_material_create_virtual(dev, &mtl2), RES_OK); CHECK(ssol_shape_create_punched_surface(dev, &shape), RES_OK); - CHECK(ssol_object_create(NULL, shape, mtl, NULL, &object), RES_BAD_ARG); - CHECK(ssol_object_create(dev, NULL, mtl, NULL, &object), RES_BAD_ARG); - CHECK(ssol_object_create(dev, shape, NULL, mtl, &object), RES_BAD_ARG); - CHECK(ssol_object_create(dev, shape, mtl, mtl, NULL), RES_BAD_ARG); - CHECK(ssol_object_create(dev, shape, mtl, mtl, &object), RES_OK); + CHECK(ssol_object_create(NULL, NULL), RES_BAD_ARG); + CHECK(ssol_object_create(dev, NULL), RES_BAD_ARG); + CHECK(ssol_object_create(NULL, &object), RES_BAD_ARG); + CHECK(ssol_object_create(dev, &object), RES_OK); + + CHECK(ssol_object_add_shaded_shape(NULL, NULL, NULL, NULL), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(object, NULL, NULL, NULL), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(NULL, shape, NULL, NULL), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(object, shape, NULL, NULL), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(NULL, NULL, mtl, NULL), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(object, NULL, mtl, NULL), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(NULL, shape, mtl, NULL), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(object, shape, mtl, NULL), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(NULL, NULL, NULL, mtl), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(object, NULL, NULL, mtl), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(NULL, shape, NULL, mtl), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(object, shape, NULL, mtl), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(NULL, NULL, mtl, mtl), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(object, NULL, mtl, mtl), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(NULL, shape, mtl, mtl), RES_BAD_ARG); + CHECK(ssol_object_add_shaded_shape(object, shape, mtl, mtl), RES_OK); CHECK(ssol_object_ref_get(NULL), RES_BAD_ARG); CHECK(ssol_object_ref_get(object), RES_OK); @@ -55,7 +71,12 @@ main(int argc, char** argv) CHECK(ssol_object_ref_put(object), RES_OK); CHECK(ssol_object_ref_put(object), RES_OK); - CHECK(ssol_object_create(dev, shape, mtl, mtl2, &object), RES_OK); + CHECK(ssol_object_create(dev, &object), RES_OK); + CHECK(ssol_object_add_shaded_shape(object, shape, mtl, mtl2), RES_OK); + CHECK(ssol_object_add_shaded_shape(object, shape, mtl2, mtl), RES_OK); + + CHECK(ssol_object_clear(NULL), RES_BAD_ARG); + CHECK(ssol_object_clear(object), RES_OK); CHECK(ssol_object_ref_put(object), RES_OK); CHECK(ssol_shape_ref_put(shape), RES_OK); diff --git a/src/test_ssol_scene.c b/src/test_ssol_scene.c @@ -53,7 +53,8 @@ main(int argc, char** argv) CHECK(ssol_material_create_virtual(dev, &material), RES_OK); CHECK(ssol_shape_create_punched_surface(dev, &shape), RES_OK); - CHECK(ssol_object_create(dev, shape, material, material, &object), RES_OK); + CHECK(ssol_object_create(dev, &object), RES_OK); + CHECK(ssol_object_add_shaded_shape(object, shape, material, material), RES_OK); CHECK(ssol_object_instantiate(object, &instance), RES_OK); CHECK(ssol_instance_set_transform(instance, transform), RES_OK); CHECK(ssol_sun_create_directional(dev, &sun), RES_OK); @@ -111,9 +112,9 @@ main(int argc, char** argv) CHECK(ssol_spectrum_create(dev, &spectrum), RES_OK); CHECK(ssol_spectrum_setup(spectrum, wavelengths, data, 3), RES_OK); CHECK(ssol_atmosphere_create_uniform(dev, &atm), RES_OK); - CHECK(ssol_atmosphere_set_uniform_absorbtion(atm, spectrum), RES_OK); + CHECK(ssol_atmosphere_set_uniform_absorption(atm, spectrum), RES_OK); CHECK(ssol_atmosphere_create_uniform(dev, &atm2), RES_OK); - CHECK(ssol_atmosphere_set_uniform_absorbtion(atm2, spectrum), RES_OK); + CHECK(ssol_atmosphere_set_uniform_absorption(atm2, spectrum), RES_OK); CHECK(ssol_scene_attach_atmosphere(NULL, atm), RES_BAD_ARG); CHECK(ssol_scene_attach_atmosphere(scene, NULL), RES_BAD_ARG); diff --git a/src/test_ssol_shape.c b/src/test_ssol_shape.c @@ -37,6 +37,7 @@ main(int argc, char** argv) struct ssol_punched_surface punched_surface; struct ssol_carving carving; struct ssol_quadric quadric; + uint32_t id; double polygon[] = { -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 0.f, -2.f }; @@ -58,6 +59,11 @@ main(int argc, char** argv) CHECK(ssol_shape_create_mesh(NULL, &shape), RES_BAD_ARG); CHECK(ssol_shape_create_mesh(dev, &shape), RES_OK); + CHECK(ssol_shape_get_id(NULL, NULL), RES_BAD_ARG); + CHECK(ssol_shape_get_id(shape, NULL), RES_BAD_ARG); + CHECK(ssol_shape_get_id(NULL, &id), RES_BAD_ARG); + CHECK(ssol_shape_get_id(shape, &id), RES_OK); + CHECK(ssol_shape_ref_get(NULL), RES_BAD_ARG); CHECK(ssol_shape_ref_get(shape), RES_OK); diff --git a/src/test_ssol_solver1.c b/src/test_ssol_solver1.c @@ -126,7 +126,8 @@ main(int argc, char** argv) CHECK(ssol_mirror_set_shader(m_mtl, &shader), RES_OK); CHECK(ssol_material_create_virtual(dev, &v_mtl), RES_OK); - CHECK(ssol_object_create(dev, square, m_mtl, m_mtl, &m_object), RES_OK); + CHECK(ssol_object_create(dev, &m_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(m_object, square, m_mtl, m_mtl), RES_OK); CHECK(ssol_object_instantiate(m_object, &heliostat), RES_OK); CHECK(ssol_instance_set_receiver(heliostat, "miroir", NULL), RES_OK); CHECK(ssol_instance_set_target_mask(heliostat, 0x1, 0), RES_OK); @@ -138,7 +139,8 @@ main(int argc, char** argv) CHECK(ssol_instance_set_target_mask(secondary, 0x2, 0), RES_OK); CHECK(ssol_scene_attach_instance(scene, secondary), RES_OK); - CHECK(ssol_object_create(dev, square, v_mtl, v_mtl, &t_object), RES_OK); + CHECK(ssol_object_create(dev, &t_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(t_object, square, v_mtl, v_mtl), RES_OK); CHECK(ssol_object_instantiate(t_object, &target), RES_OK); CHECK(ssol_instance_set_transform(target, transform2), RES_OK); CHECK(ssol_instance_set_receiver(target, "cible", NULL), RES_OK); @@ -185,7 +187,7 @@ main(int argc, char** argv) CHECK(ssol_spectrum_create(dev, &abs), RES_OK); CHECK(ssol_spectrum_setup(abs, mismatch, ka, 2), RES_OK); CHECK(ssol_atmosphere_create_uniform(dev, &atm), RES_OK); - CHECK(ssol_atmosphere_set_uniform_absorbtion(atm, abs), RES_OK); + CHECK(ssol_atmosphere_set_uniform_absorption(atm, abs), RES_OK); CHECK(ssol_scene_attach_atmosphere(scene, atm), RES_OK); CHECK(ssol_solve(scene, rng, 10, stdout, estimator), RES_BAD_ARG); /* spectra mismatch */ CHECK(ssol_scene_detach_atmosphere(scene, atm), RES_OK); @@ -237,11 +239,11 @@ main(int argc, char** argv) logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE); CHECK(eq_eps(status.E, 0, 1e-4), 1); - /* check atmosphere model; with no absorbtion result is unchanged */ + /* check atmosphere model; with no absorption result is unchanged */ CHECK(ssol_spectrum_create(dev, &abs), RES_OK); CHECK(ssol_spectrum_setup(abs, wavelengths, ka, 3), RES_OK); CHECK(ssol_atmosphere_create_uniform(dev, &atm), RES_OK); - CHECK(ssol_atmosphere_set_uniform_absorbtion(atm, abs), RES_OK); + CHECK(ssol_atmosphere_set_uniform_absorption(atm, abs), RES_OK); CHECK(ssol_scene_attach_atmosphere(scene, atm), RES_OK); NCHECK(tmp = tmpfile(), 0); @@ -262,12 +264,12 @@ main(int argc, char** argv) logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE); CHECK(eq_eps(status.E, 0, 1e-4), 1); - /* check atmosphere model; with absorbtion power decreases */ + /* check atmosphere model; with absorption power decreases */ ka[0] = ka[1] = ka[2] = 0.1; CHECK(ssol_spectrum_create(dev, &abs), RES_OK); CHECK(ssol_spectrum_setup(abs, wavelengths, ka, 3), RES_OK); CHECK(ssol_atmosphere_create_uniform(dev, &atm), RES_OK); - CHECK(ssol_atmosphere_set_uniform_absorbtion(atm, abs), RES_OK); + CHECK(ssol_atmosphere_set_uniform_absorption(atm, abs), RES_OK); CHECK(ssol_scene_attach_atmosphere(scene, atm), RES_OK); NCHECK(tmp = tmpfile(), 0); diff --git a/src/test_ssol_solver2.c b/src/test_ssol_solver2.c @@ -56,7 +56,7 @@ main(int argc, char** argv) struct ssol_vertex_data attribs[1]; struct ssol_shape* quad_square; struct ssol_carving carving; - struct ssol_quadric quadric; + struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT; struct ssol_punched_surface punched; struct ssol_material* m_mtl; struct ssol_material* v_mtl; @@ -150,7 +150,8 @@ main(int argc, char** argv) CHECK(ssol_mirror_set_shader(m_mtl, &shader), RES_OK); CHECK(ssol_material_create_virtual(dev, &v_mtl), RES_OK); - CHECK(ssol_object_create(dev, rect, m_mtl, m_mtl, &m_object), RES_OK); + CHECK(ssol_object_create(dev, &m_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(m_object, rect, m_mtl, m_mtl), RES_OK); CHECK(ssol_object_instantiate(m_object, &heliostat1), RES_OK); CHECK(ssol_object_instantiate(m_object, &heliostat2), RES_OK); CHECK(ssol_instance_set_receiver(heliostat1, "miroir", NULL), RES_OK); @@ -162,14 +163,16 @@ main(int argc, char** argv) CHECK(ssol_scene_attach_instance(scene, heliostat1), RES_OK); CHECK(ssol_scene_attach_instance(scene, heliostat2), RES_OK); - CHECK(ssol_object_create(dev, quad_square, m_mtl, m_mtl, &s_object), RES_OK); + CHECK(ssol_object_create(dev, &s_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(s_object, quad_square, m_mtl, m_mtl), RES_OK); CHECK(ssol_object_instantiate(s_object, &secondary), RES_OK); CHECK(ssol_instance_set_receiver(secondary, "secondaire", NULL), RES_OK); CHECK(ssol_instance_set_transform(secondary, transform1), RES_OK); CHECK(ssol_instance_dont_sample(secondary, 1), RES_OK); CHECK(ssol_scene_attach_instance(scene, secondary), RES_OK); - CHECK(ssol_object_create(dev, square, v_mtl, v_mtl, &t_object), RES_OK); + CHECK(ssol_object_create(dev, &t_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(t_object, square, v_mtl, v_mtl), RES_OK); CHECK(ssol_object_instantiate(t_object, &target), RES_OK); CHECK(ssol_instance_set_transform(target, transform2), RES_OK); CHECK(ssol_instance_set_receiver(target, "cible", NULL), RES_OK); diff --git a/src/test_ssol_solver2b.c b/src/test_ssol_solver2b.c @@ -56,7 +56,7 @@ main(int argc, char** argv) struct ssol_shape* quad_square; struct ssol_shape* quad_rect; struct ssol_carving carving; - struct ssol_quadric quadric; + struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT; struct ssol_punched_surface punched; struct ssol_material* m_mtl; struct ssol_material* v_mtl; @@ -155,7 +155,8 @@ main(int argc, char** argv) CHECK(ssol_mirror_set_shader(m_mtl, &shader), RES_OK); CHECK(ssol_material_create_virtual(dev, &v_mtl), RES_OK); - CHECK(ssol_object_create(dev, quad_rect, m_mtl, m_mtl, &m_object), RES_OK); + CHECK(ssol_object_create(dev, &m_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(m_object, quad_rect, m_mtl, m_mtl), RES_OK); CHECK(ssol_object_instantiate(m_object, &heliostat1), RES_OK); CHECK(ssol_object_instantiate(m_object, &heliostat2), RES_OK); CHECK(ssol_instance_set_receiver(heliostat1, "miroir", NULL), RES_OK); @@ -167,14 +168,16 @@ main(int argc, char** argv) CHECK(ssol_scene_attach_instance(scene, heliostat1), RES_OK); CHECK(ssol_scene_attach_instance(scene, heliostat2), RES_OK); - CHECK(ssol_object_create(dev, quad_square, m_mtl, m_mtl, &s_object), RES_OK); + CHECK(ssol_object_create(dev, &s_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(s_object, quad_square, m_mtl, m_mtl), RES_OK); CHECK(ssol_object_instantiate(s_object, &secondary), RES_OK); CHECK(ssol_instance_set_receiver(secondary, "secondaire", NULL), RES_OK); CHECK(ssol_instance_set_transform(secondary, transform1), RES_OK); CHECK(ssol_instance_dont_sample(secondary, 1), RES_OK); CHECK(ssol_scene_attach_instance(scene, secondary), RES_OK); - CHECK(ssol_object_create(dev, rect, v_mtl, v_mtl, &t_object), RES_OK); + CHECK(ssol_object_create(dev, &t_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(t_object, rect, v_mtl, v_mtl), RES_OK); CHECK(ssol_object_instantiate(t_object, &target), RES_OK); CHECK(ssol_instance_set_transform(target, transform2), RES_OK); CHECK(ssol_instance_set_receiver(target, "cible", NULL), RES_OK); diff --git a/src/test_ssol_solver3.c b/src/test_ssol_solver3.c @@ -50,7 +50,7 @@ main(int argc, char** argv) struct ssol_vertex_data attribs[1]; struct ssol_shape* quad_square; struct ssol_carving carving; - struct ssol_quadric quadric; + struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT; struct ssol_punched_surface punched; struct ssol_material* m_mtl; struct ssol_material* v_mtl; @@ -124,12 +124,14 @@ main(int argc, char** argv) CHECK(ssol_mirror_set_shader(m_mtl, &shader), RES_OK); CHECK(ssol_material_create_virtual(dev, &v_mtl), RES_OK); - CHECK(ssol_object_create(dev, quad_square, m_mtl, m_mtl, &m_object), RES_OK); + CHECK(ssol_object_create(dev, &m_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(m_object, quad_square, m_mtl, m_mtl), RES_OK); CHECK(ssol_object_instantiate(m_object, &heliostat), RES_OK); CHECK(ssol_instance_set_receiver(heliostat, "heliostat", NULL), RES_OK); CHECK(ssol_scene_attach_instance(scene, heliostat), RES_OK); - CHECK(ssol_object_create(dev, square, v_mtl, v_mtl, &t_object), RES_OK); + CHECK(ssol_object_create(dev, &t_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(t_object, square, v_mtl, v_mtl), RES_OK); CHECK(ssol_object_instantiate(t_object, &target), RES_OK); CHECK(ssol_instance_set_transform(target, transform), RES_OK); CHECK(ssol_instance_set_receiver(target, "cible", NULL), RES_OK); diff --git a/src/test_ssol_solver3N.c b/src/test_ssol_solver3N.c @@ -94,7 +94,7 @@ main(int argc, char** argv) struct ssol_vertex_data attribs[1]; struct ssol_shape* quad_square; struct ssol_carving carving; - struct ssol_quadric quadric; + struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT; struct ssol_punched_surface punched; struct ssol_material* m_mtl; struct ssol_material* v_mtl; @@ -168,7 +168,8 @@ main(int argc, char** argv) CHECK(ssol_mirror_set_shader(m_mtl, &shader), RES_OK); CHECK(ssol_material_create_virtual(dev, &v_mtl), RES_OK); - CHECK(ssol_object_create(dev, quad_square, m_mtl, v_mtl, &m_object), RES_OK); + CHECK(ssol_object_create(dev, &m_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(m_object, quad_square, m_mtl, v_mtl), RES_OK); common.scene = scene; d3_set(common.sun_dir, sun_dir); @@ -194,7 +195,8 @@ main(int argc, char** argv) d33_rotation_pitch(transform, PI); /* flip faces: invert normal */ d3_set(transform + 9, target_pos); - CHECK(ssol_object_create(dev, square, v_mtl, v_mtl, &t_object), RES_OK); + CHECK(ssol_object_create(dev, &t_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(t_object, square, v_mtl, v_mtl), RES_OK); CHECK(ssol_object_instantiate(t_object, &target), RES_OK); CHECK(ssol_instance_set_transform(target, transform), RES_OK); CHECK(ssol_instance_set_receiver(target, "cible", NULL), RES_OK); diff --git a/src/test_ssol_solver4.c b/src/test_ssol_solver4.c @@ -50,7 +50,7 @@ main(int argc, char** argv) struct ssol_vertex_data attribs[1]; struct ssol_shape* quad_square; struct ssol_carving carving; - struct ssol_quadric quadric; + struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT; struct ssol_punched_surface punched; struct ssol_material* m_mtl; struct ssol_material* v_mtl; @@ -126,11 +126,13 @@ main(int argc, char** argv) CHECK(ssol_mirror_set_shader(m_mtl, &shader), RES_OK); CHECK(ssol_material_create_virtual(dev, &v_mtl), RES_OK); - CHECK(ssol_object_create(dev, quad_square, m_mtl, m_mtl, &m_object), RES_OK); + CHECK(ssol_object_create(dev, &m_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(m_object, quad_square, m_mtl, m_mtl), RES_OK); CHECK(ssol_object_instantiate(m_object, &heliostat), RES_OK); CHECK(ssol_scene_attach_instance(scene, heliostat), RES_OK); - CHECK(ssol_object_create(dev, square, v_mtl, v_mtl, &t_object), RES_OK); + CHECK(ssol_object_create(dev, &t_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(t_object, square, v_mtl, v_mtl), RES_OK); CHECK(ssol_object_instantiate(t_object, &target1), RES_OK); CHECK(ssol_instance_set_transform(target1, transform), RES_OK); CHECK(ssol_instance_set_receiver(target1, "cible1", NULL), RES_OK); diff --git a/src/test_ssol_solver5.c b/src/test_ssol_solver5.c @@ -50,7 +50,7 @@ main(int argc, char** argv) struct ssol_vertex_data attribs[1]; struct ssol_shape* quad_square; struct ssol_carving carving; - struct ssol_quadric quadric; + struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT; struct ssol_punched_surface punched; struct ssol_material* m_mtl; struct ssol_material* v_mtl; @@ -125,11 +125,13 @@ main(int argc, char** argv) CHECK(ssol_mirror_set_shader(m_mtl, &shader), RES_OK); CHECK(ssol_material_create_virtual(dev, &v_mtl), RES_OK); - CHECK(ssol_object_create(dev, quad_square, m_mtl, m_mtl, &m_object), RES_OK); + CHECK(ssol_object_create(dev, &m_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(m_object, quad_square, m_mtl, m_mtl), RES_OK); CHECK(ssol_object_instantiate(m_object, &heliostat), RES_OK); CHECK(ssol_scene_attach_instance(scene, heliostat), RES_OK); - CHECK(ssol_object_create(dev, rect, v_mtl, v_mtl, &t_object), RES_OK); + CHECK(ssol_object_create(dev, &t_object), RES_OK); + CHECK(ssol_object_add_shaded_shape(t_object, rect, v_mtl, v_mtl), RES_OK); CHECK(ssol_object_instantiate(t_object, &target), RES_OK); CHECK(ssol_instance_set_transform(target, transform), RES_OK); CHECK(ssol_instance_set_receiver(target, "cible", NULL), RES_OK);