commit c5413f89bb43accb1391f744c959de088bd10021
parent 44a09ed7a455324f95aa80b45c01049a0dac242e
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Thu, 16 Feb 2017 14:42:58 +0100
Change way areas are computed.
Diffstat:
12 files changed, 127 insertions(+), 77 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -564,6 +564,12 @@ SSOL_API res_T
ssol_object_clear
(struct ssol_object* object);
+/* Retrieve the area of the object */
+SSOL_API res_T
+ssol_object_get_area
+ (const struct ssol_object* object,
+ double* area);
+
/*******************************************************************************
* Object Instance API - Clone of an object with a set of per instance data as
* world transformation, material parameters, etc. Note that the object
@@ -607,6 +613,12 @@ ssol_instance_get_id
(const struct ssol_instance* instance,
uint32_t* id);
+/* Retrieve the area of the instance */
+SSOL_API res_T
+ssol_instance_get_area
+ (const struct ssol_instance* instance,
+ double* area);
+
/*******************************************************************************
* Param buffer API
******************************************************************************/
@@ -796,16 +808,6 @@ ssol_estimator_get_failed_count
(const struct ssol_estimator* estimator,
size_t* count);
-SSOL_API res_T
-ssol_estimator_get_sampled_area
- (const struct ssol_estimator* estimator,
- double* area);
-
-SSOL_API res_T
-ssol_estimator_get_primary_area
- (const struct ssol_estimator* estimator,
- double* area);
-
/*******************************************************************************
* Miscellaneous functions
******************************************************************************/
diff --git a/src/ssol_estimator.c b/src/ssol_estimator.c
@@ -254,26 +254,6 @@ ssol_estimator_get_failed_count
return RES_OK;
}
-res_T
-ssol_estimator_get_sampled_area
- (const struct ssol_estimator* estimator,
- double* area)
-{
- if (!estimator || !area) return RES_BAD_ARG;
- *area = estimator->sampled_area;
- return RES_OK;
-}
-
-res_T
-ssol_estimator_get_primary_area
- (const struct ssol_estimator* estimator,
- double* area)
-{
- if (!estimator || !area) return RES_BAD_ARG;
- *area = estimator->primary_area;
- return RES_OK;
-}
-
/*******************************************************************************
* Local function
******************************************************************************/
diff --git a/src/ssol_estimator_c.h b/src/ssol_estimator_c.h
@@ -101,7 +101,7 @@ struct mc_per_primary_data {
struct mc_data cos_loss;
struct mc_data shadow_loss;
double area;
- double base_sun_cos;
+ double sun_cos;
size_t nb_samples;
size_t nb_failed;
/* by-receptor data for this entity */
@@ -115,7 +115,7 @@ init_mc_per_prim_data
{
ASSERT(alloc && data);
data->area = 0;
- data->base_sun_cos = 0;
+ data->sun_cos = 0;
data->cos_loss = MC_DATA_NULL;
data->shadow_loss = MC_DATA_NULL;
data->nb_samples = 0;
@@ -132,7 +132,7 @@ release_mc_per_prim_data(struct mc_per_primary_data* data)
#define PRIM_COPY(Dst, Src) {\
Dst->area = Src->area;\
- Dst->base_sun_cos = Src->base_sun_cos;\
+ Dst->sun_cos = Src->sun_cos;\
Dst->nb_failed = Src->nb_failed;\
Dst->nb_samples = Src->nb_samples;\
Dst->shadow_loss = Src->shadow_loss;\
@@ -206,7 +206,7 @@ struct ssol_estimator {
/* per-primary entity MC computations */
struct htable_primary global_primaries;
/* scene areas */
- double sampled_area, primary_area;
+ double primary_area;
struct ssol_device* dev;
ref_T ref;
@@ -234,8 +234,8 @@ estimator_get_receiver_data
static FINLINE struct mc_per_primary_data*
estimator_get_primary_entity_data
-(struct htable_primary* primaries,
- const struct ssol_instance* instance)
+ (struct htable_primary* primaries,
+ const struct ssol_instance* instance)
{
struct mc_per_primary_data* data;
ASSERT(primaries && instance);
diff --git a/src/ssol_instance.c b/src/ssol_instance.c
@@ -84,10 +84,12 @@ ssol_object_instantiate
/* Create the Star-3D instance to ray-trace */
res = s3d_scene_instantiate(object->scn_rt, &instance->shape_rt);
if(res != RES_OK) goto error;
+ instance->shape_rt_area = object->scn_rt_area;
/* Create the Star-3D instance to sample */
res = s3d_scene_instantiate(object->scn_samp, &instance->shape_samp);
if(res != RES_OK) goto error;
+ instance->shape_samp_area = object->scn_samp_area;
exit:
if(out_instance) *out_instance = instance;
@@ -181,3 +183,13 @@ ssol_instance_get_id(const struct ssol_instance* instance, uint32_t* id)
return RES_OK;
}
+res_T
+ssol_instance_get_area
+ (const struct ssol_instance* instance,
+ double* area)
+{
+ if (!instance || !area) return RES_BAD_ARG;;
+ /* the area of the 3D surface */
+ *area = instance->shape_rt_area;
+ return RES_OK;
+}
diff --git a/src/ssol_instance_c.h b/src/ssol_instance_c.h
@@ -24,6 +24,7 @@ struct ssol_instance {
struct ssol_object* object; /* Instantiated object */
struct s3d_shape* shape_rt; /* Instantiated Star-3D shape to ray-trace */
struct s3d_shape* shape_samp; /* Instantiated Star-3D shape to sample */
+ double shape_rt_area, shape_samp_area;
double transform[12]; /* Column major 4x3 affine transformation */
int receiver_mask; /* Combination of ssol_face_flag */
int sample; /* Define whether or not the instance should be sampled */
diff --git a/src/ssol_object.c b/src/ssol_object.c
@@ -137,11 +137,13 @@ ssol_object_add_shaded_shape
res = s3d_scene_attach_shape(object->scn_rt, shape->shape_rt);
if(res != RES_OK) goto error;
mask |= BIT(ATTACH_S3D_RT);
+ object->scn_rt_area += shape->shape_rt_area;
/* 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);
+ object->scn_samp_area += shape->shape_samp_area;
/* Ask for a shaded shape identifier */
i = darray_shaded_shape_size_get(&object->shaded_shapes);
@@ -207,6 +209,8 @@ ssol_object_clear(struct ssol_object* obj)
darray_shaded_shape_clear(&obj->shaded_shapes);
htable_shaded_shape_clear(&obj->shaded_shapes_rt);
htable_shaded_shape_clear(&obj->shaded_shapes_samp);
+
+ obj->scn_rt_area = 0;
S3D(scene_clear(obj->scn_rt));
S3D(scene_clear(obj->scn_samp));
@@ -214,3 +218,13 @@ ssol_object_clear(struct ssol_object* obj)
return RES_OK;
}
+res_T
+ssol_object_get_area
+(const struct ssol_object* object,
+ double* area)
+{
+ if (!object || !area) return RES_BAD_ARG;;
+ /* the area of the 3D surface */
+ *area = object->scn_rt_area;
+ return RES_OK;
+}
+\ No newline at end of file
diff --git a/src/ssol_object_c.h b/src/ssol_object_c.h
@@ -47,6 +47,7 @@ struct ssol_object {
struct s3d_scene* scn_rt; /* RT scene to instantiate */
struct s3d_scene* scn_samp; /* Sampling scene to instantiate */
+ double scn_rt_area, scn_samp_area;
struct ssol_device* dev;
ref_T ref;
diff --git a/src/ssol_scene.c b/src/ssol_scene.c
@@ -45,7 +45,6 @@ scene_release(ref_T* ref)
SSOL(scene_clear(scene));
if(scene->scn_rt) S3D(scene_ref_put(scene->scn_rt));
if(scene->scn_samp) S3D(scene_ref_put(scene->scn_samp));
- if(scene->scn_prim) S3D(scene_ref_put(scene->scn_prim));
if(scene->sun) SSOL(sun_ref_put(scene->sun));
if(scene->atmosphere) SSOL(atmosphere_ref_put(scene->atmosphere));
htable_instance_release(&scene->instances_rt);
@@ -84,8 +83,6 @@ ssol_scene_create
if(res != RES_OK) goto error;
res = s3d_scene_create(dev->s3d, &scene->scn_samp);
if(res != RES_OK) goto error;
- res = s3d_scene_create(dev->s3d, &scene->scn_prim);
- if(res != RES_OK) goto error;
exit:
if(out_scene) *out_scene = scene;
@@ -195,7 +192,6 @@ ssol_scene_clear(struct ssol_scene* scene)
htable_instance_clear(&scene->instances_samp);
S3D(scene_clear(scene->scn_rt));
S3D(scene_clear(scene->scn_samp));
- S3D(scene_clear(scene->scn_prim));
if (scene->sun) ssol_scene_detach_sun(scene, scene->sun);
if (scene->atmosphere)
ssol_scene_detach_atmosphere(scene, scene->atmosphere);
@@ -280,25 +276,25 @@ res_T
scene_create_s3d_views
(struct ssol_scene* scn,
struct s3d_scene_view** out_view_rt,
- struct s3d_scene_view** out_view_samp,
- struct s3d_scene_view** out_view_prim)
+ struct s3d_scene_view** out_view_samp)
{
struct htable_instance_iterator it, end;
struct s3d_scene_view* view_rt = NULL;
struct s3d_scene_view* view_samp = NULL;
- struct s3d_scene_view* view_prim = NULL;
int has_sampled = 0;
int has_receiver = 0;
res_T res = RES_OK;
ASSERT(scn && out_view_rt && out_view_samp);
S3D(scene_clear(scn->scn_samp));
- S3D(scene_clear(scn->scn_prim));
htable_instance_clear(&scn->instances_samp);
htable_instance_begin(&scn->instances_rt, &it);
htable_instance_end(&scn->instances_rt, &end);
+ scn->sampled_area = 0;
+ scn->primary_area = 0;
+
while (!htable_instance_iterator_eq(&it, &end)) {
struct ssol_instance* inst = *htable_instance_iterator_data_get(&it);
unsigned id;
@@ -310,6 +306,9 @@ scene_create_s3d_views
if(!inst->sample) continue;
+ scn->sampled_area += inst->shape_samp_area;
+ scn->primary_area += inst->shape_rt_area;
+
/* Note that geometries with virtual material can be sampled without risk
* since the solver avoid to shade them and simply pursue the primary ray */
has_sampled = 1;
@@ -318,9 +317,6 @@ scene_create_s3d_views
res = s3d_scene_attach_shape(scn->scn_samp, inst->shape_samp);
if(res != RES_OK) goto error;
- /* Attach the instantiated s3d raytraced shape to the s3d primary scene */
- res = s3d_scene_attach_shape(scn->scn_prim, inst->shape_rt);
- if(res != RES_OK) goto error;
/* Register the instantiated s3d sampling shape */
S3D(shape_get_id(inst->shape_samp, &id));
@@ -346,13 +342,10 @@ scene_create_s3d_views
if(res != RES_OK) goto error;
res = s3d_scene_view_create(scn->scn_samp, S3D_SAMPLE, &view_samp);
if(res != RES_OK) goto error;
- res = s3d_scene_view_create(scn->scn_prim, S3D_SAMPLE, &view_prim);
- if (res != RES_OK) goto error;
exit:
*out_view_rt = view_rt;
*out_view_samp = view_samp;
- *out_view_prim = view_prim;
return res;
error:
S3D(scene_clear(scn->scn_samp));
@@ -365,10 +358,6 @@ error:
S3D(scene_view_ref_put(view_samp));
view_samp = NULL;
}
- if (view_prim) {
- S3D(scene_view_ref_put(view_prim));
- view_prim = NULL;
- }
goto exit;
}
diff --git a/src/ssol_scene_c.h b/src/ssol_scene_c.h
@@ -42,11 +42,12 @@ struct ssol_scene {
struct s3d_scene* scn_rt; /* S3D scene to ray trace */
struct s3d_scene* scn_samp; /* S3D scene to sample */
- struct s3d_scene* scn_prim; /* S3D scene of primary objects */
struct ssol_sun* sun; /* Sun of the scene */
struct ssol_atmosphere* atmosphere; /* Atmosphere of the scene */
+ double sampled_area, primary_area; /* scene areas */
+
struct ssol_device* dev;
ref_T ref;
};
@@ -57,8 +58,7 @@ extern LOCAL_SYM res_T
scene_create_s3d_views
(struct ssol_scene* scn,
struct s3d_scene_view** view_rt,
- struct s3d_scene_view** view_samp,
- struct s3d_scene_view** out_view_prim);
+ struct s3d_scene_view** view_samp);
#endif /* SSOL_SCENE_C_H */
diff --git a/src/ssol_shape.c b/src/ssol_shape.c
@@ -415,6 +415,42 @@ error:
goto exit;
}
+static double
+mesh_compute_area
+ (const unsigned ntris,
+ void (*get_indices)(const unsigned itri, unsigned ids[3], void* data),
+ const unsigned nverts,
+ void (*get_position)(const unsigned ivert, float position[3], void* data),
+ void* ctx)
+{
+ unsigned itri;
+ double area = 0;
+
+ FOR_EACH(itri, 0, ntris) {
+ float v0[3], v1[3], v2[3];
+ double E0[3], E1[3], N[3];
+ double V0[3], V1[3], V2[3];
+ unsigned IDS[3];
+
+ get_indices(itri, IDS, ctx);
+ ASSERT(IDS[0] < nverts);
+ ASSERT(IDS[1] < nverts);
+ ASSERT(IDS[2] < nverts);
+
+ get_position(IDS[0], v0, ctx);
+ get_position(IDS[1], v1, ctx);
+ get_position(IDS[2], v2, ctx);
+ d3_set_f3(V0, v0);
+ d3_set_f3(V1, v1);
+ d3_set_f3(V2, v2);
+ d3_sub(E0, V1, V0);
+ d3_sub(E1, V2, V0);
+
+ area += d3_len(d3_cross(N, E0, E1));
+ }
+ return area * 0.5;
+}
+
/* 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 */
@@ -423,12 +459,14 @@ quadric_setup_s3d_shape_rt
(const struct ssol_quadric* quadric,
const struct darray_double* coords,
const struct darray_size_t* ids,
- struct s3d_shape* shape)
+ struct s3d_shape* shape,
+ double * rt_area)
{
struct quadric_mesh_context ctx;
struct s3d_vertex_data vdata;
unsigned nverts;
unsigned ntris;
+ res_T res;
ASSERT(quadric && coords && ids && shape);
ASSERT(darray_double_size_get(coords)%2 == 0);
ASSERT(darray_size_t_size_get(ids)%3 == 0);
@@ -458,8 +496,12 @@ quadric_setup_s3d_shape_rt
default: FATAL("Unreachable code.\n"); break;
}
- return s3d_mesh_setup_indexed_vertices
+ res = s3d_mesh_setup_indexed_vertices
(shape, ntris, quadric_mesh_get_ids, nverts, &vdata, 1, &ctx);
+ if (res != RES_OK) return res;
+ *rt_area = mesh_compute_area
+ (ntris, quadric_mesh_get_ids, nverts, quadric_mesh_parabol_get_pos, &ctx);
+ return RES_OK;
}
/* Setup the Star-3D shape of the quadric to sample, i.e. the clipped 2D
@@ -469,12 +511,14 @@ quadric_setup_s3d_shape_samp
(const struct ssol_quadric* quadric,
const struct darray_double* coords,
const struct darray_size_t* ids,
- struct s3d_shape* shape)
+ struct s3d_shape* shape,
+ double *samp_area)
{
struct quadric_mesh_context ctx;
struct s3d_vertex_data vdata;
unsigned nverts;
unsigned ntris;
+ res_T res;
ASSERT(coords && ids && shape);
ASSERT(darray_double_size_get(coords)%2 == 0);
ASSERT(darray_size_t_size_get(ids)%3 == 0);
@@ -490,8 +534,12 @@ quadric_setup_s3d_shape_samp
vdata.usage = S3D_POSITION;
vdata.type = S3D_FLOAT3;
vdata.get = quadric_mesh_plane_get_pos;
- return s3d_mesh_setup_indexed_vertices
+ res = s3d_mesh_setup_indexed_vertices
(shape, ntris, quadric_mesh_get_ids, nverts, &vdata, 1, &ctx);
+ if (res != RES_OK) return res;
+ *samp_area = mesh_compute_area
+ (ntris, quadric_mesh_get_ids, nverts, quadric_mesh_plane_get_pos, &ctx);
+ return RES_OK;
}
static res_T
@@ -979,11 +1027,12 @@ ssol_punched_surface_setup
/* Setup the Star-3D shape to ray-trace */
res = quadric_setup_s3d_shape_rt
- (psurf->quadric, &coords, &ids, shape->shape_rt);
+ (psurf->quadric, &coords, &ids, shape->shape_rt, &shape->shape_rt_area);
if(res != RES_OK) goto error;
/* Setup the Star-3D shape to sample */
- res = quadric_setup_s3d_shape_samp(psurf->quadric, &coords, &ids, shape->shape_samp);
+ res = quadric_setup_s3d_shape_samp
+ (psurf->quadric, &coords, &ids, shape->shape_samp, &shape->shape_samp_area);
if(res != RES_OK) goto error;
exit:
@@ -1005,6 +1054,7 @@ ssol_mesh_setup
void* data)
{
struct s3d_vertex_data attrs[SSOL_ATTRIBS_COUNT__];
+ void (*get_position)(const unsigned ivert, float position[3], void* data) = NULL;
res_T res = RES_OK;
unsigned i;
@@ -1030,6 +1080,8 @@ ssol_mesh_setup
case SSOL_POSITION:
attrs[i].usage = SSOL_TO_S3D_POSITION;
attrs[i].type = S3D_FLOAT3;
+ ASSERT(!get_position);
+ get_position = attrs[i].get;
break;
case SSOL_NORMAL:
attrs[i].usage = SSOL_TO_S3D_NORMAL;
@@ -1042,13 +1094,17 @@ ssol_mesh_setup
default: FATAL("Unreachable code.\n"); break;
}
}
+ ASSERT(get_position);
+
res = s3d_mesh_setup_indexed_vertices
(shape->shape_rt, ntris, get_indices, nverts, attrs, nattribs, data);
if(res != RES_OK) goto error;
+ shape->shape_rt_area = mesh_compute_area(ntris, get_indices, nverts, get_position, data);
/* 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;
+ shape->shape_samp_area = shape->shape_rt_area;
exit:
return res;
diff --git a/src/ssol_shape_c.h b/src/ssol_shape_c.h
@@ -32,6 +32,7 @@ struct ssol_shape {
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;
+ double shape_rt_area, shape_samp_area;
struct ssol_device* dev;
ref_T ref;
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -121,8 +121,8 @@ point_init
/* Initialise the Monte Carlo weight */
cos_sun = fabs(d3_dot(pt->N, pt->dir));
- pt->weight = scn->sun->dni * estimator->sampled_area * cos_sun;
- pt->cos_loss = scn->sun->dni * estimator->sampled_area * (1 - cos_sun);
+ pt->weight = scn->sun->dni * scn->sampled_area * cos_sun;
+ pt->cos_loss = scn->sun->dni * scn->sampled_area * (1 - cos_sun);
pt->absorptivity_loss = pt->reflectivity_loss = 0;
/* Retrieve the sampled instance and shaded shape */
@@ -359,7 +359,6 @@ ssol_solve
struct htable_primary_iterator p_it, p_end;
struct s3d_scene_view* view_rt = NULL;
struct s3d_scene_view* view_samp = NULL;
- struct s3d_scene_view* view_prim = NULL;
struct ranst_sun_dir* ran_sun_dir = NULL;
struct ranst_sun_wl* ran_sun_wl = NULL;
struct ssf_bsdf** bsdfs = NULL;
@@ -371,7 +370,6 @@ ssol_solve
struct htable_receiver* mc_rcvs = NULL;
struct htable_primary* mc_prims = NULL;
struct ssol_estimator* estimator = NULL;
- float area;
int nthreads = 0;
int64_t nrealisations = 0;
int i = 0;
@@ -397,23 +395,19 @@ ssol_solve
if(res != RES_OK) goto error;
/* Create data structures shared by all threads */
- res = scene_create_s3d_views(scn, &view_rt, &view_samp, &view_prim);
+ res = scene_create_s3d_views(scn, &view_rt, &view_samp);
if(res != RES_OK) goto error;
res = sun_create_distributions(scn->sun, &ran_sun_dir, &ran_sun_wl);
if(res != RES_OK) goto error;
- /* Create the estimator */
- res = estimator_create(scn->dev, scn, &estimator);
- if (res != RES_OK) goto error;
- S3D(scene_view_compute_area(view_samp, &area));
- estimator->sampled_area = area;
- S3D(scene_view_compute_area(view_prim, &area));
- estimator->primary_area = area;
-
/* Create a RNG proxy from the submitted RNG state */
res = ssp_rng_proxy_create_from_rng
(scn->dev->allocator, rng_state, scn->dev->nthreads, &rng_proxy);
if(res != RES_OK) goto error;
+
+ /* Create the estimator */
+ res = estimator_create(scn->dev, scn, &estimator);
+ if (res != RES_OK) goto error;
/* Create per thread data structures */
#define CREATE(Data) { \
@@ -680,7 +674,6 @@ ssol_solve
exit:
if(view_rt) S3D(scene_view_ref_put(view_rt));
if(view_samp) S3D(scene_view_ref_put(view_samp));
- if(view_prim) S3D(scene_view_ref_put(view_prim));
if(ran_sun_dir) ranst_sun_dir_ref_put(ran_sun_dir);
if(ran_sun_wl) ranst_sun_wl_ref_put(ran_sun_wl);
if(rng_proxy) SSP(rng_proxy_ref_put(rng_proxy));