commit 4fbdeeef584c135ac392029ece4f3a18bba06364
parent 0ee3b390d45d05c990c2d53406df787cd9a1f933
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 17 Feb 2017 12:15:41 +0100
Make consistent the MC estimations implementation
Rename the 'primary MC' in 'sampled MC'
Diffstat:
6 files changed, 281 insertions(+), 224 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -792,7 +792,7 @@ ssol_estimator_get_mc_global
struct ssol_mc_global* mc_global);
SSOL_API res_T
-ssol_estimator_get_primary_entity_x_receiver_status
+ssol_estimator_get_mc_sampled_x_receiver
(struct ssol_estimator* estimator,
const struct ssol_instance* prim_instance,
const struct ssol_instance* recv_instance,
diff --git a/src/ssol_estimator.c b/src/ssol_estimator.c
@@ -36,7 +36,7 @@ create_mc_receivers
{
struct htable_instance_iterator it, end;
struct mc_receiver mc_rcv_null;
- struct mc_per_primary_data mc_samp_null;
+ struct mc_sampled mc_samp_null;
res_T res = RES_OK;
ASSERT(scene && estimator);
@@ -44,7 +44,7 @@ create_mc_receivers
htable_instance_end(&scene->instances_rt, &end);
mc_receiver_init(estimator->dev->allocator, &mc_rcv_null);
- init_mc_per_prim_data(estimator->dev->allocator, &mc_samp_null);
+ mc_sampled_init(estimator->dev->allocator, &mc_samp_null);
while(!htable_instance_iterator_eq(&it, &end)) {
const struct ssol_instance* inst = *htable_instance_iterator_data_get(&it);
@@ -55,17 +55,17 @@ create_mc_receivers
if(res != RES_OK) goto error;
}
if(inst->sample) {
- res = htable_primary_set(&estimator->global_primaries, &inst, &mc_samp_null);
+ res = htable_sampled_set(&estimator->mc_sampled, &inst, &mc_samp_null);
if(res != RES_OK) goto error;
}
}
exit:
mc_receiver_release(&mc_rcv_null);
- release_mc_per_prim_data(&mc_samp_null);
+ mc_sampled_release(&mc_samp_null);
return res;
error:
htable_receiver_clear(&estimator->mc_receivers);
- htable_primary_clear(&estimator->global_primaries);
+ htable_sampled_clear(&estimator->mc_sampled);
goto exit;
}
@@ -78,7 +78,7 @@ estimator_release(ref_T* ref)
ASSERT(ref);
dev = estimator->dev;
htable_receiver_release(&estimator->mc_receivers);
- htable_primary_release(&estimator->global_primaries);
+ htable_sampled_release(&estimator->mc_sampled);
ASSERT(dev && dev->allocator);
MEM_RM(dev->allocator, estimator);
SSOL(device_ref_put(dev));
@@ -88,10 +88,9 @@ estimator_release(ref_T* ref)
* Exported function
******************************************************************************/
res_T
-ssol_estimator_ref_get
- (struct ssol_estimator* estimator)
+ssol_estimator_ref_get(struct ssol_estimator* estimator)
{
- if (!estimator) return RES_BAD_ARG;
+ if(!estimator) return RES_BAD_ARG;
ref_get(&estimator->ref);
return RES_OK;
}
@@ -125,44 +124,54 @@ ssol_estimator_get_mc_global
}
res_T
-ssol_estimator_get_primary_entity_x_receiver_status
+ssol_estimator_get_mc_sampled_x_receiver
(struct ssol_estimator* estimator,
- const struct ssol_instance* prim_instance,
+ const struct ssol_instance* samp_instance,
const struct ssol_instance* recv_instance,
const enum ssol_side_flag side,
struct ssol_mc_receiver* rcv)
{
- struct mc_per_primary_data* prim_data = NULL;
+ struct mc_sampled* mc_samp = NULL;
+ struct mc_receiver* mc_rcv = NULL;
struct mc_receiver_1side* mc_rcv1 = NULL;
- if(!estimator || !prim_instance || !recv_instance || !rcv
+
+ if(!estimator || !samp_instance || !recv_instance || !rcv
|| (side != SSOL_BACK && side != SSOL_FRONT)
- || !prim_instance->sample
+ || !samp_instance->sample
|| !(recv_instance->receiver_mask & (int)side))
return RES_BAD_ARG;
- /* Check if prim_instance is a primary entity */
- prim_data = estimator_get_primary_entity_data
- (&estimator->global_primaries, prim_instance);
- if(prim_data == NULL) return RES_BAD_ARG;
-
- /* realisation count for this primary */
- mc_rcv1 = estimator_get_prim_recv_data(prim_data, recv_instance, side);
- if(!prim_data->nb_samples || !mc_rcv1) {
- memset(rcv, 0, sizeof(rcv[0]));
- } else {
- #define SETUP_MC_RESULT(Name) { \
- const double N = (double)prim_data->nb_samples; \
- const struct mc_data* data = &mc_rcv1->Name; \
- rcv->Name.E = data->weight / N; \
- rcv->Name.V = data->sqr_weight / N - rcv->Name.E*rcv->Name.E; \
- rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->Name.V / N) : 0; \
- } (void)0
- SETUP_MC_RESULT(integrated_irradiance);
- SETUP_MC_RESULT(absorptivity_loss);
- SETUP_MC_RESULT(reflectivity_loss);
- SETUP_MC_RESULT(cos_loss);
- #undef SETUP_MC_RESULT
+ memset(rcv, 0, sizeof(rcv[0]));
+
+
+ mc_samp = htable_sampled_find(&estimator->mc_sampled, &samp_instance);
+ if(!mc_samp || !mc_samp->nb_samples) {
+ /* The sampled instance has no MC estimation */
+ return RES_BAD_ARG;
+ }
+
+ mc_rcv = htable_receiver_find(&mc_samp->mc_rcvs, &recv_instance);
+ if(!mc_rcv) {
+ /* No radiative path starting from the sampled instance reaches the receiver
+ * instance. */
+ return RES_OK;
}
+
+ mc_rcv1 = side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back;
+ #define SETUP_MC_RESULT(Name) { \
+ const double N = (double)mc_samp->nb_samples; \
+ const struct mc_data* data = &mc_rcv1->Name; \
+ rcv->Name.E = data->weight / N; \
+ rcv->Name.V = data->sqr_weight / N - rcv->Name.E*rcv->Name.E; \
+ rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->Name.V / N) : 0; \
+ } (void)0
+ SETUP_MC_RESULT(integrated_irradiance);
+ SETUP_MC_RESULT(absorptivity_loss);
+ SETUP_MC_RESULT(reflectivity_loss);
+ SETUP_MC_RESULT(cos_loss);
+ #undef SETUP_MC_RESULT
+ rcv->mc__ = mc_rcv1;
+ rcv->N__ = mc_samp->nb_samples;
return RES_OK;
}
@@ -208,7 +217,7 @@ estimator_create
}
htable_receiver_init(dev->allocator, &estimator->mc_receivers);
- htable_primary_init(dev->allocator, &estimator->global_primaries);
+ htable_sampled_init(dev->allocator, &estimator->mc_sampled);
SSOL(device_ref_get(dev));
estimator->dev = dev;
ref_init(&estimator->ref);
diff --git a/src/ssol_estimator_c.h b/src/ssol_estimator_c.h
@@ -133,39 +133,38 @@ mc_receiver_1side_copy_and_release
return RES_OK;
}
-static INLINE struct mc_primitive_1side*
+static INLINE res_T
mc_receiver_1side_get_mc_primitive
- (struct mc_receiver_1side* mc_rcv, const unsigned iprim)
+ (struct mc_receiver_1side* mc_rcv,
+ const unsigned iprim,
+ struct mc_primitive_1side** out_mc_prim1)
{
unsigned* pui = NULL;
- struct mc_primitive_1side* mc_prim = NULL;
+ struct mc_primitive_1side* mc_prim1 = NULL;
+ res_T res = RES_OK;
ASSERT(mc_rcv);
pui = htable_prim2mc_find(&mc_rcv->prim2mc, &iprim);
if(pui) {
- mc_prim = darray_mc_prim_data_get(&mc_rcv->mc_prims) + *pui;
+ mc_prim1 = darray_mc_prim_data_get(&mc_rcv->mc_prims) + *pui;
ASSERT(*pui < darray_mc_prim_size_get(&mc_rcv->mc_prims));
- ASSERT(mc_prim->index == *pui);
+ ASSERT(mc_prim1->index == *pui);
} else {
unsigned ui = (unsigned)darray_mc_prim_size_get(&mc_rcv->mc_prims);
- res_T res;
res = darray_mc_prim_push_back(&mc_rcv->mc_prims, &MC_PRIMITIVE_1SIDE_NULL);
if(res != RES_OK) goto error;
- mc_prim = darray_mc_prim_data_get(&mc_rcv->mc_prims) + ui;
- mc_prim->index = ui;
+ mc_prim1 = darray_mc_prim_data_get(&mc_rcv->mc_prims) + ui;
+ mc_prim1->index = ui;
res = htable_prim2mc_set(&mc_rcv->prim2mc, &iprim, &ui);
if(res != RES_OK) goto error;
}
exit:
- return mc_prim;
+ *out_mc_prim1 = mc_prim1;
+ return res;
error:
- if(pui && mc_prim) {
- darray_mc_prim_pop_back(&mc_rcv->mc_prims);
- }
- mc_prim = NULL;
goto exit;
}
@@ -229,108 +228,93 @@ mc_receiver_copy_and_release
#include <rsys/hash_table.h>
/*******************************************************************************
- * Per primitive MC data
+ * Per sampled instance MC data
******************************************************************************/
-struct mc_per_primary_data {
- /* global data for this entity */
+struct mc_sampled {
+ /* Global data for this entity */
struct mc_data cos_loss;
- struct mc_data shadow_loss;
+ struct mc_data shadowed;
double area;
double sun_cos;
size_t nb_samples;
- size_t nb_failed;
- /* by-receptor data for this entity */
- struct htable_receiver by_receiver;
+
+ /* By-receptor data for this entity */
+ struct htable_receiver mc_rcvs;
};
static INLINE void
-init_mc_per_prim_data
- (struct mem_allocator* alloc,
- struct mc_per_primary_data* data)
+mc_sampled_init
+ (struct mem_allocator* allocator,
+ struct mc_sampled* samp)
{
- ASSERT(alloc && data);
- data->area = 0;
- data->sun_cos = 0;
- data->cos_loss = MC_DATA_NULL;
- data->shadow_loss = MC_DATA_NULL;
- data->nb_samples = 0;
- data->nb_failed = 0;
- htable_receiver_init(alloc, &data->by_receiver);
+ ASSERT(samp);
+ samp->cos_loss = MC_DATA_NULL;
+ samp->shadowed = MC_DATA_NULL;
+ samp->area = 0;
+ samp->sun_cos = 0;
+ samp->nb_samples = 0;
+ htable_receiver_init(allocator, &samp->mc_rcvs);
}
static INLINE void
-release_mc_per_prim_data(struct mc_per_primary_data* data)
+mc_sampled_release(struct mc_sampled* samp)
{
- ASSERT(data);
- htable_receiver_release(&data->by_receiver);
+ ASSERT(samp);
+ htable_receiver_release(&samp->mc_rcvs);
}
-#define PRIM_COPY(Dst, Src) {\
- Dst->area = Src->area;\
- Dst->sun_cos = Src->sun_cos;\
- Dst->nb_failed = Src->nb_failed;\
- Dst->nb_samples = Src->nb_samples;\
- Dst->shadow_loss = Src->shadow_loss;\
- Dst->cos_loss = Src->cos_loss;\
-} (void)0
-
static INLINE res_T
-copy_mc_per_prim_data
- (struct mc_per_primary_data* dst,
- const struct mc_per_primary_data* src)
+mc_sampled_copy(struct mc_sampled* dst, const struct mc_sampled* src)
{
ASSERT(dst && src);
- PRIM_COPY(dst, src);
- return htable_receiver_copy(&dst->by_receiver, &src->by_receiver);
+ dst->cos_loss = src->cos_loss;
+ dst->shadowed = src->shadowed;
+ dst->area = src->area;
+ dst->sun_cos = src->sun_cos;
+ dst->nb_samples = src->nb_samples;
+ return htable_receiver_copy(&dst->mc_rcvs, &src->mc_rcvs);
}
static INLINE res_T
-copy_and_release_mc_per_prim_data
- (struct mc_per_primary_data* dst,
- struct mc_per_primary_data* src)
+mc_sampled_copy_and_release(struct mc_sampled* dst, struct mc_sampled* src)
{
ASSERT(dst && src);
- PRIM_COPY(dst, src);
- return htable_receiver_copy_and_release(&dst->by_receiver, &src->by_receiver);
+ dst->cos_loss = src->cos_loss;
+ dst->shadowed = src->shadowed;
+ dst->area = src->area;
+ dst->sun_cos = src->sun_cos;
+ dst->nb_samples = src->nb_samples;
+ return htable_receiver_copy_and_release(&dst->mc_rcvs, &src->mc_rcvs);
}
static INLINE res_T
-copy_and_clear_mc_per_prim_data
- (struct mc_per_primary_data* dst,
- struct mc_per_primary_data* src)
-{
- ASSERT(dst && src);
- PRIM_COPY(dst, src);
- return htable_receiver_copy_and_clear(&dst->by_receiver, &src->by_receiver);
-}
-
-
-static INLINE struct mc_receiver_1side*
-mc_per_primary_get_mc_receiver
- (struct mc_per_primary_data* primary,
- const struct ssol_instance* instance,
- const enum ssol_side_flag side)
+mc_sampled_get_mc_receiver_1side
+ (struct mc_sampled* mc_samp,
+ const struct ssol_instance* inst,
+ const enum ssol_side_flag side,
+ struct mc_receiver_1side** out_mc_rcv1)
{
struct mc_receiver* mc_rcv = NULL;
struct mc_receiver_1side* mc_rcv1 = NULL;
struct mc_receiver mc_rcv_null;
res_T res = RES_OK;
- ASSERT(primary && instance);
- ASSERT(instance->receiver_mask & (int)side);
-
- mc_receiver_init(instance->dev->allocator, &mc_rcv_null);
+ ASSERT(mc_samp && inst);
+ ASSERT(inst->receiver_mask & (int)side);
- mc_rcv = htable_receiver_find(&primary->by_receiver, &instance);
+ mc_receiver_init(inst->dev->allocator, &mc_rcv_null);
+
+ mc_rcv = htable_receiver_find(&mc_samp->mc_rcvs, &inst);
if(!mc_rcv) {
- res = htable_receiver_set(&primary->by_receiver, &instance, &mc_rcv_null);
+ res = htable_receiver_set(&mc_samp->mc_rcvs, &inst, &mc_rcv_null);
if(res != RES_OK) goto error;
- mc_rcv = htable_receiver_find(&primary->by_receiver, &instance);
+ mc_rcv = htable_receiver_find(&mc_samp->mc_rcvs, &inst);
}
mc_rcv1 = side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back;
exit:
mc_receiver_release(&mc_rcv_null);
- return mc_rcv1;
+ *out_mc_rcv1 = mc_rcv1;
+ return res;
error:
mc_rcv1 = NULL;
goto exit;
@@ -339,14 +323,13 @@ error:
#undef PRIM_COPY
/* Define the htable_primary data structure */
-#define HTABLE_NAME primary
+#define HTABLE_NAME sampled
#define HTABLE_KEY const struct ssol_instance*
-#define HTABLE_DATA struct mc_per_primary_data
-#define HTABLE_DATA_FUNCTOR_INIT init_mc_per_prim_data
-#define HTABLE_DATA_FUNCTOR_RELEASE release_mc_per_prim_data
-#define HTABLE_DATA_FUNCTOR_COPY copy_mc_per_prim_data
-#define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE copy_and_release_mc_per_prim_data
-#define HTABLE_DATA_FUNCTOR_COPY_AND_CLEAR copy_and_clear_mc_per_prim_data
+#define HTABLE_DATA struct mc_sampled
+#define HTABLE_DATA_FUNCTOR_INIT mc_sampled_init
+#define HTABLE_DATA_FUNCTOR_RELEASE mc_sampled_release
+#define HTABLE_DATA_FUNCTOR_COPY mc_sampled_copy
+#define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE mc_sampled_copy_and_release
#include <rsys/hash_table.h>
/*******************************************************************************
@@ -362,9 +345,9 @@ struct ssol_estimator {
struct mc_data cos_loss; /* TODO compute it */
struct htable_receiver mc_receivers; /* Per receiver MC */
- struct htable_primary global_primaries; /* Per sampled MC */
+ struct htable_sampled mc_sampled; /* Per sampled instance MC */
- double primary_area;
+ double sampled_area;
struct ssol_device* dev;
ref_T ref;
@@ -376,20 +359,67 @@ estimator_create
struct ssol_scene* scene,
struct ssol_estimator** estimator);
-static FINLINE struct mc_receiver_1side*
-estimator_get_mc_receiver
+static FINLINE res_T
+get_mc_receiver_1side
(struct htable_receiver* receivers,
- const struct ssol_instance* instance,
- const enum ssol_side_flag side)
+ const struct ssol_instance* inst,
+ const enum ssol_side_flag side,
+ struct mc_receiver_1side** out_mc_rcv1)
+{
+ struct mc_receiver* mc_rcv = NULL;
+ struct mc_receiver_1side* mc_rcv1 = NULL;
+ struct mc_receiver mc_rcv_null;
+ res_T res = RES_OK;
+ ASSERT(receivers && inst && out_mc_rcv1);
+ ASSERT(inst->receiver_mask & (int)side);
+
+ mc_receiver_init(inst->dev->allocator, &mc_rcv_null);
+
+ mc_rcv = htable_receiver_find(receivers, &inst);
+ if(!mc_rcv) {
+ res = htable_receiver_set(receivers, &inst, &mc_rcv_null);
+ if(res != RES_OK) goto error;
+ mc_rcv = htable_receiver_find(receivers, &inst);
+ }
+
+ mc_rcv1 = side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back;
+exit:
+ mc_receiver_release(&mc_rcv_null);
+ *out_mc_rcv1 = mc_rcv1;
+ return res;
+error:
+ goto exit;
+}
+
+static FINLINE res_T
+get_mc_sampled
+ (struct htable_sampled* sampled,
+ const struct ssol_instance* inst,
+ struct mc_sampled** out_mc_samp)
{
- struct mc_receiver* mc_rcv;
- ASSERT(receivers && instance);
- if(!(instance->receiver_mask & (int)side)) return NULL;
- mc_rcv = htable_receiver_find(receivers, &instance);
- if(!mc_rcv) return NULL;
- return side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back;
+ struct mc_sampled* mc_samp = NULL;
+ struct mc_sampled mc_samp_null;
+ res_T res = RES_OK;
+ ASSERT(sampled && inst && out_mc_samp);
+
+ mc_sampled_init(inst->dev->allocator, &mc_samp_null);
+
+ mc_samp = htable_sampled_find(sampled, &inst);
+ if(!mc_samp) {
+ res = htable_sampled_set(sampled, &inst, &mc_samp_null);
+ if(res != RES_OK) goto error;
+ mc_samp = htable_sampled_find(sampled, &inst);
+ }
+
+exit:
+ mc_sampled_release(&mc_samp_null);
+ *out_mc_samp = mc_samp;
+ return res;
+error:
+ goto exit;
}
+#if 0
static FINLINE struct mc_per_primary_data*
estimator_get_primary_entity_data
(struct htable_primary* primaries,
@@ -411,6 +441,7 @@ estimator_get_prim_recv_data
ASSERT(primary_data && instance);
return estimator_get_mc_receiver(&primary_data->by_receiver, instance, side);
}
+#endif
#endif /* SSOL_ESTIMATOR_C_H */
diff --git a/src/ssol_mc_receiver.c b/src/ssol_mc_receiver.c
@@ -26,15 +26,22 @@ ssol_estimator_get_mc_receiver
const enum ssol_side_flag side,
struct ssol_mc_receiver* rcv)
{
+ const struct mc_receiver* mc_rcv = NULL;
const struct mc_receiver_1side* mc_rcv1 = NULL;
+
if(!estimator || !instance || !rcv
- || (side != SSOL_BACK && side != SSOL_FRONT))
+ || !(instance->receiver_mask & (int)side))
return RES_BAD_ARG;
- /* Check if a receiver is defined for this instance/side */
- mc_rcv1 = estimator_get_mc_receiver(&estimator->mc_receivers, instance, side);
- if(mc_rcv1 == NULL) return RES_BAD_ARG;
+ memset(rcv, 0, sizeof(rcv[0]));
+
+ mc_rcv = htable_receiver_find(&estimator->mc_receivers, &instance);
+ if(!mc_rcv) {
+ /* The receiver has no MC estimation */
+ return RES_OK;
+ }
+ mc_rcv1 = side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back;
#define SETUP_MC_RESULT(Name) { \
const double N = (double)estimator->realisation_count; \
const struct mc_data* data = &mc_rcv1->Name; \
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -47,7 +47,7 @@
struct point {
const struct ssol_instance* inst;
const struct shaded_shape* sshape;
- struct mc_per_primary_data* primary;
+ struct mc_sampled* mc_samp;
struct s3d_primitive prim;
double N[3];
double pos[3];
@@ -79,18 +79,17 @@ static const struct point POINT_NULL = POINT_NULL__;
/*******************************************************************************
* Helper functions
******************************************************************************/
-/* Return 1 if the returned point is lit by the sun and 0 otherwise */
-static int
+static res_T
point_init
(struct point* pt,
struct ssol_scene* scn,
- struct htable_primary* prim_data,
- struct ssol_estimator* estimator,
+ struct htable_sampled* sampled,
struct s3d_scene_view* view_samp,
struct s3d_scene_view* view_rt,
struct ranst_sun_dir* ran_sun_dir,
struct ranst_sun_wl* ran_sun_wl,
- struct ssp_rng* rng)
+ struct ssp_rng* rng,
+ int* is_lit)
{
struct s3d_attrib attr;
struct s3d_hit hit;
@@ -98,6 +97,9 @@ point_init
float dir[3], pos[3], range[2] = { 0, FLT_MAX };
double cos_sun;
size_t id;
+ res_T res = RES_OK;
+ ASSERT(pt && scn && sampled && view_samp && view_rt);
+ ASSERT(ran_sun_dir && ran_sun_wl && rng && is_lit);
/* Sample a point into the scene view */
S3D(scene_view_sample
@@ -132,18 +134,12 @@ point_init
pt->sshape = darray_shaded_shape_cdata_get
(&pt->inst->object->shaded_shapes) + id;
- /* store primary entity related weights */
- pt->primary = estimator_get_primary_entity_data(prim_data, pt->inst);
- if (!pt->primary) {
- struct mc_per_primary_data data;
- init_mc_per_prim_data(estimator->dev->allocator, &data);
- htable_primary_set(prim_data, &pt->inst, &data);
- pt->primary = estimator_get_primary_entity_data(prim_data, pt->inst);
- ASSERT(pt->primary);
- }
- pt->primary->cos_loss.weight += pt->cos_loss;
- pt->primary->cos_loss.sqr_weight += pt->cos_loss * pt->cos_loss;
- pt->primary->nb_samples++;
+ /* Store sampled entity related weights */
+ res = get_mc_sampled(sampled, pt->inst, &pt->mc_samp);
+ if(res != RES_OK) goto error;
+ pt->mc_samp->cos_loss.weight += pt->cos_loss;
+ pt->mc_samp->cos_loss.sqr_weight += pt->cos_loss * pt->cos_loss;
+ pt->mc_samp->nb_samples++;
/* For punched surface, retrieve the sampled position and normal onto the
* quadric surface */
@@ -172,11 +168,15 @@ point_init
f3_minus(dir, f3_set_d3(dir, pt->dir));
f3_set_d3(pos, pt->pos);
S3D(scene_view_trace_ray(view_rt, pos, dir, range, &ray_data, &hit));
- if(!S3D_HIT_NONE(&hit)) return 0;
+ *is_lit = S3D_HIT_NONE(&hit);
+ if(*is_lit) {
+ pt->wl = ranst_sun_wl_get(ran_sun_wl, rng); /* Sample a wavelength */
+ }
- /* Sample a wavelength */
- pt->wl = ranst_sun_wl_get(ran_sun_wl, rng);
- return 1;
+exit:
+ return res;
+error:
+ goto exit;
}
static FINLINE void
@@ -368,8 +368,9 @@ accum_mc_receivers_1side
/* Merge the per primitive MC of the integrated irradiance */
FOR_EACH(i, 0, darray_mc_prim_size_get(&src->mc_prims)) {
src_mc_prim = darray_mc_prim_cdata_get(&src->mc_prims) + i;
- dst_mc_prim = mc_receiver_1side_get_mc_primitive(dst, src_mc_prim->index);
- if(!dst_mc_prim) goto error;
+ res = mc_receiver_1side_get_mc_primitive
+ (dst, src_mc_prim->index, &dst_mc_prim);
+ if(res != RES_OK) goto error;
#define ACCUM_WEIGHT(Name) { \
dst_mc_prim->Name.weight += src_mc_prim->Name.weight; \
dst_mc_prim->Name.sqr_weight += src_mc_prim->Name.sqr_weight; \
@@ -387,9 +388,7 @@ error:
}
static res_T
-accum_mc_per_primary_data
- (struct mc_per_primary_data* dst,
- struct mc_per_primary_data* src)
+accum_mc_sampled(struct mc_sampled* dst, struct mc_sampled* src)
{
struct htable_receiver_iterator it, end;
struct mc_receiver mc_rcv_null;
@@ -403,25 +402,24 @@ accum_mc_per_primary_data
dst->Name.sqr_weight += src->Name.sqr_weight; \
} (void)0
ACCUM_WEIGHT(cos_loss);
- ACCUM_WEIGHT(shadow_loss);
+ ACCUM_WEIGHT(shadowed);
#undef ACCUM_WEIGHT
dst->nb_samples += src->nb_samples;
- dst->nb_failed += src->nb_failed;
/* dst->by_receiver += src->by_receiver; */
- htable_receiver_begin(&src->by_receiver, &it);
- htable_receiver_end(&src->by_receiver, &end);
+ htable_receiver_begin(&src->mc_rcvs, &it);
+ htable_receiver_end(&src->mc_rcvs, &end);
while(!htable_receiver_iterator_eq(&it, &end)) {
struct mc_receiver* src_mc_rcv = htable_receiver_iterator_data_get(&it);
const struct ssol_instance* inst = *htable_receiver_iterator_key_get(&it);
- struct mc_receiver* dst_mc_rcv = htable_receiver_find(&dst->by_receiver, &inst);
+ struct mc_receiver* dst_mc_rcv = htable_receiver_find(&dst->mc_rcvs, &inst);
htable_receiver_iterator_next(&it);
if(!dst_mc_rcv) {
- res = htable_receiver_set(&dst->by_receiver, &inst, &mc_rcv_null);
+ res = htable_receiver_set(&dst->mc_rcvs, &inst, &mc_rcv_null);
if(res != RES_OK) goto error;
- dst_mc_rcv = htable_receiver_find(&dst->by_receiver, &inst);
+ dst_mc_rcv = htable_receiver_find(&dst->mc_rcvs, &inst);
}
if(inst->receiver_mask & (int)SSOL_FRONT) {
@@ -452,7 +450,7 @@ ssol_solve
struct ssol_estimator** out_estimator)
{
struct htable_receiver_iterator r_it, r_end;
- struct htable_primary_iterator p_it, p_end;
+ struct htable_sampled_iterator s_it, s_end;
struct s3d_scene_view* view_rt = NULL;
struct s3d_scene_view* view_samp = NULL;
struct ranst_sun_dir* ran_sun_dir = NULL;
@@ -465,7 +463,7 @@ ssol_solve
struct mc_data* mc_cos_losses = NULL; /* TODO compute it */
size_t* failed_counts = NULL; /* TODO compute it */
struct htable_receiver* mc_rcvs = NULL;
- struct htable_primary* mc_prims = NULL;
+ struct htable_sampled* mc_sampled = NULL;
struct ssol_estimator* estimator = NULL;
int nthreads = 0;
int64_t nrealisations = 0;
@@ -521,7 +519,7 @@ ssol_solve
CREATE(mc_missings);
CREATE(mc_cos_losses);
CREATE(mc_rcvs);
- CREATE(mc_prims);
+ CREATE(mc_sampled);
CREATE(failed_counts);
#undef CREATE
@@ -534,8 +532,8 @@ ssol_solve
htable_receiver_init(scn->dev->allocator, mc_rcvs + i);
res = htable_receiver_copy(mc_rcvs + i, &estimator->mc_receivers);
if(res != RES_OK) goto error;
- htable_primary_init(scn->dev->allocator, mc_prims + i);
- res = htable_primary_copy(mc_prims + i, &estimator->global_primaries);
+ htable_sampled_init(scn->dev->allocator, mc_sampled + i);
+ res = htable_sampled_copy(mc_sampled + i, &estimator->mc_sampled);
if(res != RES_OK) goto error;
}
@@ -550,12 +548,13 @@ ssol_solve
struct mc_data* cos_loss;
size_t* nfails;
struct htable_receiver* receiver;
- struct htable_primary* primary;
+ struct htable_sampled* sampled;
float org[3], dir[3], range[2] = { 0, FLT_MAX };
const int ithread = omp_get_thread_num();
size_t depth = 0;
int is_lit;
int hit_a_receiver = 0;
+ res_T res_local;
if(ATOMIC_GET(&res) != RES_OK) continue; /* An error occurs */
@@ -566,23 +565,27 @@ ssol_solve
cos_loss = mc_cos_losses + ithread;
missing = mc_missings + ithread;
receiver = mc_rcvs + ithread;
- primary = mc_prims + ithread;
+ sampled = mc_sampled + ithread;
nfails = failed_counts + ithread;
/* Find a new starting point of the radiative random walk */
- is_lit = point_init(&pt, scn, primary, estimator, view_samp, view_rt,
- ran_sun_dir, ran_sun_wl, rng);
+ res_local = point_init(&pt, scn, sampled, view_samp, view_rt, ran_sun_dir,
+ ran_sun_wl, rng, &is_lit);
+ if(res_local != RES_OK) {
+ ATOMIC_SET(&res, res_local);
+ continue;
+ }
if(!is_lit) { /* The starting point is not lit */
- pt.primary->shadow_loss.weight += pt.weight;
- pt.primary->shadow_loss.sqr_weight += pt.weight;
+ pt.mc_samp->shadowed.weight += pt.weight;
+ pt.mc_samp->shadowed.sqr_weight += pt.weight;
shadow->weight += pt.weight;
shadow->sqr_weight += pt.weight * pt.weight;
continue;
}
- /* Setup the ray as if it starts from the current point position in order to handle
- * the points that start from a virtual material */
+ /* Setup the ray as if it starts from the current point position in order
+ * to handle the points that start from a virtual material */
f3_set_d3(org, pt.pos);
f3_set_d3(dir, pt.dir);
hit.distance = 0;
@@ -592,15 +595,21 @@ ssol_solve
struct ssol_material* mtl;
if(point_is_receiver(&pt)) {
- const res_T res_local = point_dump(&pt, (size_t)i, depth, output);
struct mc_receiver_1side* mc_rcv1 = NULL;
+ struct mc_receiver_1side* mc_samp_x_rcv1 = NULL;
+
+ res_local = point_dump(&pt, (size_t)i, depth, output);
if(res_local != RES_OK) {
ATOMIC_SET(&res, res_local);
break;
}
/* Per receiver MC accumulation */
- mc_rcv1 = estimator_get_mc_receiver(receiver, pt.inst, pt.side);
+ res_local = get_mc_receiver_1side(receiver, pt.inst, pt.side, &mc_rcv1);
+ if(res_local != RES_OK) {
+ ATOMIC_SET(&res, res_local);
+ break;
+ }
#define ACCUM_WEIGHT(Name, W) { \
mc_rcv1->Name.weight += (W); \
mc_rcv1->Name.sqr_weight += (W)*(W); \
@@ -611,12 +620,30 @@ ssol_solve
ACCUM_WEIGHT(cos_loss, pt.cos_loss);
#undef ACCUM_WEIGHT
+ /* Per-primary/receiver MC accumulation */
+ res_local = mc_sampled_get_mc_receiver_1side
+ (pt.mc_samp, pt.inst, pt.side, &mc_samp_x_rcv1);
+ if(res_local != RES_OK) {
+ ATOMIC_SET(&res, res_local);
+ break;
+ }
+ #define ACCUM_WEIGHT(Name, W) { \
+ mc_samp_x_rcv1->Name.weight += (W); \
+ mc_samp_x_rcv1->Name.sqr_weight += (W)*(W); \
+ } (void)0
+ ACCUM_WEIGHT(integrated_irradiance, pt.weight);
+ ACCUM_WEIGHT(absorptivity_loss, pt.absorptivity_loss);
+ ACCUM_WEIGHT(reflectivity_loss, pt.reflectivity_loss);
+ ACCUM_WEIGHT(cos_loss, pt.cos_loss);
+ #undef ACCUM_WEIGHT
+
/* Per primitive receiver MC accumulation */
if(pt.inst->receiver_per_primitive) {
struct mc_primitive_1side* mc_prim;
- mc_prim = mc_receiver_1side_get_mc_primitive(mc_rcv1, pt.prim.prim_id);
- if(!mc_prim) {
- ATOMIC_SET(&res, RES_MEM_ERR);
+ res_local = mc_receiver_1side_get_mc_primitive
+ (mc_rcv1, pt.prim.prim_id, &mc_prim);
+ if(res_local) {
+ ATOMIC_SET(&res, res_local);
break;
}
#define ACCUM_WEIGHT(Name, W) { \
@@ -629,23 +656,6 @@ ssol_solve
ACCUM_WEIGHT(cos_loss, pt.cos_loss);
#undef ACCUM_WEIGHT
}
-
- /* Per-primary/receiver MC accumulation */
- mc_rcv1 = mc_per_primary_get_mc_receiver(pt.primary, pt.inst, pt.side);
- #define ACCUM_WEIGHT(Name, W) { \
- mc_rcv1->Name.weight += (W); \
- mc_rcv1->Name.sqr_weight += (W)*(W); \
- } (void)0
- if(!mc_rcv1) {
- ATOMIC_SET(&res, RES_MEM_ERR);
- break;
- }
- ACCUM_WEIGHT(integrated_irradiance, pt.weight);
- ACCUM_WEIGHT(absorptivity_loss, pt.absorptivity_loss);
- ACCUM_WEIGHT(reflectivity_loss, pt.reflectivity_loss);
- ACCUM_WEIGHT(cos_loss, pt.cos_loss);
- #undef ACCUM_WEIGHT
-
hit_a_receiver = 1;
}
@@ -659,7 +669,7 @@ ssol_solve
} else {
/* Modulate the point weight wrt to its scattering functions and
* generate an outgoing direction */
- res_T res_local = point_shade(&pt, bsdf, rng, pt.dir);
+ res_local = point_shade(&pt, bsdf, rng, pt.dir);
if(res_local != RES_OK) {
ATOMIC_SET(&res, res_local);
break;
@@ -739,16 +749,16 @@ ssol_solve
}
/* Merge per thread sampled instance MC estimations */
- htable_primary_begin(&estimator->global_primaries, &p_it);
- htable_primary_end(&estimator->global_primaries, &p_end);
- while(!htable_primary_iterator_eq(&p_it, &p_end)) {
- struct mc_per_primary_data* pri_data = htable_primary_iterator_data_get(&p_it);
- const struct ssol_instance* key = *htable_primary_iterator_key_get(&p_it);
- htable_primary_iterator_next(&p_it);
+ htable_sampled_begin(&estimator->mc_sampled, &s_it);
+ htable_sampled_end(&estimator->mc_sampled, &s_end);
+ while(!htable_sampled_iterator_eq(&s_it, &s_end)) {
+ struct mc_sampled* mc_samp = htable_sampled_iterator_data_get(&s_it);
+ const struct ssol_instance* inst = *htable_sampled_iterator_key_get(&s_it);
+ htable_sampled_iterator_next(&s_it);
FOR_EACH(i, 0, nthreads) {
- struct mc_per_primary_data* th_data = htable_primary_find(mc_prims + i, &key);
- res = accum_mc_per_primary_data(pri_data, th_data);
+ struct mc_sampled* mc_samp_thread = htable_sampled_find(mc_sampled + i, &inst);
+ res = accum_mc_sampled(mc_samp, mc_samp_thread);
if(res != RES_OK) goto error;
}
}
@@ -773,9 +783,9 @@ exit:
FOR_EACH(i, 0, nthreads) htable_receiver_release(mc_rcvs + i);
sa_release(mc_rcvs);
}
- if (mc_prims) {
- FOR_EACH(i, 0, nthreads) htable_primary_release(mc_prims + i);
- sa_release(mc_prims);
+ if(mc_sampled) {
+ FOR_EACH(i, 0, nthreads) htable_sampled_release(mc_sampled + i);
+ sa_release(mc_sampled);
}
sa_release(mc_shadows);
sa_release(mc_missings);
diff --git a/src/test_ssol_by_receiver_integration.c b/src/test_ssol_by_receiver_integration.c
@@ -132,26 +132,26 @@ main(int argc, char** argv)
#define N__ 10000
#define S_DNI_cos (4 * 1000 * cos(PI / 4))
-#define GET_RCV_STATUS ssol_estimator_get_mc_receiver
-#define GET_PRIM_X_RCV_STATUS ssol_estimator_get_primary_entity_x_receiver_status
+#define GET_MC_RCV ssol_estimator_get_mc_receiver
+#define GET_MC_SAMP_X_RCV ssol_estimator_get_mc_sampled_x_receiver
CHECK(ssol_solve(scene, rng, N__, NULL, &estimator1), RES_OK);
- CHECK(GET_RCV_STATUS(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK);
+ CHECK(GET_MC_RCV(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK);
printf("Ir(target) = %g +/- %g\n",
mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE);
CHECK(ssol_instance_set_receiver(heliostat, SSOL_FRONT, 0), RES_OK);
CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 2e-1), 1);
CHECK(ssol_solve(scene, rng, 8 * N__, NULL, &estimator2), RES_OK);
- CHECK(GET_RCV_STATUS(estimator2, target, SSOL_FRONT, &mc_rcv), RES_OK);
+ CHECK(GET_MC_RCV(estimator2, target, SSOL_FRONT, &mc_rcv), RES_OK);
printf("Ir(target) = %g +/- %g\n",
mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE);
CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 5e-2), 1);
CHECK(ssol_estimator_ref_put(estimator1), RES_OK);
CHECK(ssol_solve(scene, rng, 3 * N__, NULL, &estimator1), RES_OK);
- CHECK(GET_RCV_STATUS(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK);
+ CHECK(GET_MC_RCV(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK);
printf("Ir(target) = %g +/- %g\n",
mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE);
CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 1e-1), 1);
- CHECK(GET_PRIM_X_RCV_STATUS(estimator1, heliostat, target, SSOL_FRONT, &mc_rcv), RES_OK);
+ CHECK(GET_MC_SAMP_X_RCV(estimator1, heliostat, target, SSOL_FRONT, &mc_rcv), RES_OK);
printf("Ir(heliostat=>target) = %g +/- %g",
mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE);
CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 1e-1), 1);