commit 617cc197d9c3b90196aad0674d28c4107f88d50f
parent 507c5813afe8e4c9c27362c1de7ed0794ac0a718
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 2 Sep 2016 08:58:05 +0200
Merge remote-tracking branch 'origin/master'
Diffstat:
14 files changed, 706 insertions(+), 374 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -424,6 +424,11 @@ ssol_object_instance_set_receiver
const char* name); /* May be NULL <=> it is no more a receiver */
SSOL_API res_T
+ssol_object_instance_set_target_mask
+ (struct ssol_object_instance* instance,
+ const uint32_t mask);
+
+SSOL_API res_T
ssol_object_instance_is_attached
(struct ssol_object_instance* instance,
char* is_attached);
diff --git a/src/ssol_c.h b/src/ssol_c.h
@@ -23,16 +23,6 @@
#define SSOL_TO_S3D_NORMAL S3D_ATTRIB_0
#define SSOL_TO_S3D_TEXCOORD S3D_ATTRIB_1
-struct ray_data {
- struct ssol_scene* scene; /* Scene in which the ray is traced */
- struct s3d_primitive prim_from; /* Primitive from which the ray starts */
- unsigned path_id; /* Identifier of the path to which the ray belongs to */
- unsigned ray_id; /* Identifier of the ray into the path */
- double radiance; /* Current path radiance in W.sr^-1.m^-2 */
- double wavelength; /* Wavelength of the current path in nanometer */
- FILE* stream;
-};
-
static FINLINE enum s3d_attrib_usage
ssol_to_s3d_attrib_usage(const enum ssol_attrib_usage usage)
{
@@ -49,7 +39,7 @@ hit_filter_function
(const struct s3d_hit* hit,
const float org[3],
const float dir[3],
- void* ray_data,
+ void* realization,
void* filter_data);
#endif /* SSOL_C_H */
diff --git a/src/ssol_material.c b/src/ssol_material.c
@@ -231,6 +231,7 @@ surface_fragment_setup
float transform[12];
float vec[3];
+ /* TODO: review this code */
S3D(primitive_get_attrib(primitive, SSOL_TO_S3D_NORMAL, uv, &attr));
ASSERT(attr.type == S3D_FLOAT3);
diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h
@@ -20,6 +20,8 @@
struct brdf_composite;
struct s3d_hit;
+struct s3d_primitive;
+struct ssol_device;
struct surface_fragment {
double dir[3]; /* World space incoming direction */
diff --git a/src/ssol_object_instance.c b/src/ssol_object_instance.c
@@ -74,6 +74,7 @@ ssol_object_instantiate
instance->dev = dev;
instance->object = object;
+ instance->target_mask = 0;
str_init(dev->allocator, &instance->receiver_name);
SSOL(object_ref_get(object));
SSOL(device_ref_get(dev));
@@ -145,6 +146,18 @@ ssol_object_instance_set_receiver
}
res_T
+ssol_object_instance_set_target_mask
+ (struct ssol_object_instance* instance,
+ const uint32_t mask)
+{
+ if (!instance)
+ return RES_BAD_ARG;
+
+ instance->target_mask = mask;
+ return RES_OK;
+}
+
+res_T
ssol_object_instance_is_attached
(struct ssol_object_instance* instance, char* is_attached)
{
diff --git a/src/ssol_object_instance_c.h b/src/ssol_object_instance_c.h
@@ -25,6 +25,7 @@ struct ssol_object_instance
struct ssol_object* object; /* Instantiated object */
struct s3d_shape* s3d_shape; /* Instantiated Star-3D shape */
struct str receiver_name; /* Empty if not a receiver */
+ uint32_t target_mask;
struct ssol_device* dev;
ref_T ref;
@@ -53,4 +54,11 @@ object_instance_get_receiver_name(const struct ssol_object_instance* instance)
? NULL : str_cget(&instance->receiver_name);
}
+static INLINE uint32_t
+object_instance_get_target_mask(const struct ssol_object_instance* instance)
+{
+ ASSERT(instance);
+ return instance->target_mask;
+}
+
#endif /* SSOL_OBJECT_INSTANCE_C_H */
diff --git a/src/ssol_scene.c b/src/ssol_scene.c
@@ -16,6 +16,7 @@
#include "ssol.h"
#include "ssol_c.h"
#include "ssol_scene_c.h"
+#include "ssol_solver_c.h"
#include "ssol_sun_c.h"
#include "ssol_device_c.h"
#include "ssol_material_c.h"
@@ -39,7 +40,7 @@ scene_release(ref_T* ref)
dev = scene->dev;
ASSERT(dev && dev->allocator);
SSOL(scene_clear(scene));
- if (scene->s3d_scn) S3D(scene_ref_put(scene->s3d_scn));
+ if (scene->s3d_raytracing_scn) S3D(scene_ref_put(scene->s3d_raytracing_scn));
if (scene->s3d_sampling_scn) S3D(scene_ref_put(scene->s3d_sampling_scn));
if(scene->sun) SSOL(sun_ref_put(scene->sun));
htable_instance_release(&scene->instances);
@@ -72,7 +73,7 @@ ssol_scene_create
scene->dev = dev;
ref_init(&scene->ref);
- res = s3d_scene_create(dev->s3d, &scene->s3d_scn);
+ res = s3d_scene_create(dev->s3d, &scene->s3d_raytracing_scn);
if (res != RES_OK) goto error;
res = s3d_scene_create(dev->s3d, &scene->s3d_sampling_scn);
@@ -116,8 +117,8 @@ ssol_scene_attach_object_instance
if(!scene || !instance) return RES_BAD_ARG;
shape = object_instance_get_s3d_shape(instance);
- /* Try to attach the instantiated s3d shape to s3d scene */
- res = s3d_scene_attach_shape(scene->s3d_scn, shape);
+ /* attach the instantiated s3d shape to s3d scene */
+ res = s3d_scene_attach_shape(scene->s3d_raytracing_scn, shape);
if(res != RES_OK) return res;
/* Register the instance against the scene */
@@ -125,7 +126,7 @@ ssol_scene_attach_object_instance
ASSERT(!htable_instance_find(&scene->instances, &id));
res = htable_instance_set(&scene->instances, &id, &instance);
if(res != RES_OK) {
- S3D(scene_detach_shape(scene->s3d_scn, shape));
+ S3D(scene_detach_shape(scene->s3d_raytracing_scn, shape));
return res;
}
SSOL(object_instance_ref_get(instance));
@@ -159,7 +160,7 @@ ssol_scene_detach_object_instance
/* Detach the object instance */
n = htable_instance_erase(&scene->instances, &id);
ASSERT(n == 1);
- S3D(scene_detach_shape(scene->s3d_scn, shape));
+ S3D(scene_detach_shape(scene->s3d_raytracing_scn, shape));
SSOL(object_instance_ref_put(instance));
return RES_OK;
@@ -176,12 +177,12 @@ ssol_scene_clear(struct ssol_scene* scene)
while(!htable_instance_iterator_eq(&it, &it_end)) {
struct ssol_object_instance* inst;
inst = *htable_instance_iterator_data_get(&it);
- S3D(scene_detach_shape(scene->s3d_scn, object_instance_get_s3d_shape(inst)));
+ S3D(scene_detach_shape(scene->s3d_raytracing_scn, object_instance_get_s3d_shape(inst)));
SSOL(object_instance_ref_put(inst));
htable_instance_iterator_next(&it);
}
htable_instance_clear(&scene->instances);
- S3D(scene_clear(scene->s3d_scn));
+ S3D(scene_clear(scene->s3d_raytracing_scn));
if(scene->sun)
ssol_scene_detach_sun(scene, scene->sun);
return RES_OK;
@@ -218,10 +219,10 @@ ssol_scene_detach_sun(struct ssol_scene* scene, struct ssol_sun* sun)
* Local functions
******************************************************************************/
struct s3d_scene*
-scene_get_s3d_scene(const struct ssol_scene* scn)
+scene_get_s3d_raytracing_scn(const struct ssol_scene* scn)
{
ASSERT(scn);
- return scn->s3d_scn;
+ return scn->s3d_raytracing_scn;
}
struct s3d_scene*
@@ -251,46 +252,66 @@ hit_filter_function
(const struct s3d_hit* hit,
const float org[3],
const float dir[3],
- void* ray_data,
+ void* realization,
void* filter_data)
{
- struct ray_data* rdata = ray_data;
struct ssol_object_instance* instance;
struct ssol_material* material;
const char* receiver_name;
- (void)org, (void)dir, (void)filter_data;
- ASSERT(rdata);
-
- if(!ray_data) return 0;
-
- if(S3D_PRIMITIVE_EQ(&hit->prim, &rdata->prim_from))
+ struct realisation* rz = realization;
+ struct segment* seg;
+ struct segment* prev;
+ int front_face = 0;
+
+ (void) filter_data;
+ ASSERT(rz);
+ prev = previous_segment(rz);
+ seg = current_segment(rz);
+ ASSERT(seg);
+
+ /* TODO: need to detect self intersect at the instance level,
+ using front/back face to avoid false self intersect events */
+ if(prev && S3D_PRIMITIVE_EQ(&hit->prim, &prev->hit.prim))
return 1; /* Discard self intersection */
- instance = scene_get_object_instance_from_s3d_hit(rdata->scene, hit);
+ instance = scene_get_object_instance_from_s3d_hit(rz->data.scene, hit);
/* Check if the hit surface is a receiver that registers hit data */
receiver_name = object_instance_get_receiver_name(instance);
if(receiver_name) {
- struct surface_fragment frag;
- float tmp[3];
- f3_set(tmp, f3_add(tmp, org, f3_mulf(tmp, dir, hit->distance)));
- surface_fragment_setup(&frag, tmp, dir, hit->normal, &hit->prim, hit->uv);
- fprintf(rdata->stream, "%s %u %u %g %g (%g:%g:%g) (%g:%g:%g) (%g:%g)\n",
- receiver_name,
- rdata->path_id,
- rdata->ray_id,
- rdata->wavelength,
- rdata->radiance,
- SPLIT3(frag.pos),
- SPLIT3(frag.dir),
- SPLIT2(frag.uv));
+ float cos_in;
+ /* check normal orientation */
+ cos_in = f3_dot(hit->normal, dir);
+ if (cos_in < 0) {
+ float pos[3];
+
+ f3_set(pos, f3_add(pos, org, f3_mulf(pos, dir, hit->distance)));
+ front_face = 1;
+ fprintf(rz->data.out_stream,
+ "Receiver '%s': %u %u %g %g (%g:%g:%g) (%g:%g:%g) (%g:%g)\n",
+ receiver_name,
+ (unsigned)rz->rz_id,
+ (unsigned)rz->s_idx,
+ rz->freq,
+ seg->weight,
+ SPLIT3(pos),
+ SPLIT3(dir),
+ SPLIT2(hit->uv));
+ }
}
+ /* register success mask */
+ if (front_face)
+ rz->success_mask |= object_instance_get_target_mask(instance);
+
material = object_get_material(object_instance_get_object(instance));
+
if(material_get_type(material) == MATERIAL_VIRTUAL) {
return 1; /* Discard virtual material */
}
+ rz->data.instance = instance;
+
return 0;
}
diff --git a/src/ssol_scene_c.h b/src/ssol_scene_c.h
@@ -29,7 +29,7 @@
struct ssol_scene
{
struct htable_instance instances;
- struct s3d_scene* s3d_scn;
+ struct s3d_scene* s3d_raytracing_scn;
struct s3d_scene* s3d_sampling_scn;
struct ssol_sun* sun;
@@ -45,7 +45,7 @@ struct ssol_sun;
struct ssol_device;
extern LOCAL_SYM struct s3d_scene*
-scene_get_s3d_scene
+scene_get_s3d_raytracing_scn
(const struct ssol_scene* scn);
extern LOCAL_SYM struct s3d_scene*
diff --git a/src/ssol_shape.c b/src/ssol_shape.c
@@ -148,7 +148,7 @@ shape_create
goto error;
}
- /* create a s3d_scene to hold a mesh */
+ /* create a s3d_shape to hold a mesh */
res = s3d_shape_create_mesh(dev->s3d, &shape->s3d_shape);
if(res != RES_OK) goto error;
res = s3d_mesh_set_hit_filter_function
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "ssol.h"
+#include "ssol_c.h"
#include "ssol_solver_c.h"
#include "ssol_device_c.h"
#include "ssol_scene_c.h"
@@ -31,17 +32,9 @@
#include <rsys/double3.h>
#include <rsys/double44.h>
-#include <star/ssp.h>
+#define END_TEXT__ { "NONE", "SUCCESS", "SHADOW", "POINTING", "MISSING", "BLOCKED", "ERROR" };
-enum realization_termination {
- TERM_NONE,
- TERM_SHADOW,
- TERM_MISSING,
- TERM_BLOCKED,
- TERM_ERR,
-
- TERM_COUNT__
-};
+static const char* END_TEXT[] = END_TEXT__;
enum realization_mode {
MODE_NONE,
@@ -51,32 +44,9 @@ enum realization_mode {
MODE_COUNT__
};
-struct segment {
- double weight;
- float range[2];
- struct s3d_hit hit;
- /* TODO: use double? */
- float org[3], dir[4];
- float hit_pos[3];
-};
-
-#include <rsys/dynamic_array.h>
-#define DARRAY_DATA struct segment
-#define DARRAY_NAME segment
-#include <rsys/dynamic_array.h>
-
-struct realisation {
- enum realization_termination end;
- enum realization_mode mode;
- struct darray_segment segments;
- struct segment sun_segment;
- double freq, final_weight;
- size_t s_idx;
-};
-
/*******************************************************************************
- * Helper functions
- ******************************************************************************/
+* Helper functions
+******************************************************************************/
static INLINE int
is_instance_punched(const struct ssol_object_instance* instance)
{
@@ -98,252 +68,11 @@ get_3dscene(const struct ssol_object_instance* instance)
return instance->object->s3d_scn;
}
-static res_T
-init_solver_data(struct ssol_scene* scene, struct solver_data* data)
-{
- res_T res = RES_OK;
-
- if (!data || !scene) return RES_BAD_ARG;
-
- data->scene = scene;
- /* create 2 s3d_scene_view for raytracing and sampling */
- res = set_views(data);
- if (res != RES_OK) goto error;
- /* create sun distributions */
- res = set_sun_distributions(data);
- if (res != RES_OK) goto error;
-
-exit:
- return res;
-error:
- /* TODO: clear data */
- goto exit;
-}
-
-static struct segment*
-current_segment(struct realisation* rz)
-{
- ASSERT(rz);
- ASSERT(rz->s_idx < darray_segment_size_get(&rz->segments));
- return darray_segment_data_get(&rz->segments) + rz->s_idx;
-}
-
-static res_T
-next_segment(struct realisation* rz)
-{
- ASSERT(rz);
- ++rz->s_idx;
- if (rz->s_idx >= darray_segment_size_get(&rz->segments))
- return darray_segment_resize(&rz->segments, rz->s_idx + 1);
- return RES_OK;
-}
-
-static void
-reset_realization(struct realisation* rz)
-{
- ASSERT(rz);
- rz->s_idx = 0;
- rz->s_idx = 0;
- rz->end = TERM_NONE;
- rz->mode = MODE_STD;
-}
-
-static res_T
-init_realization(struct mem_allocator* allocator, struct realisation* rz)
-{
- ASSERT(rz);
- darray_segment_init(allocator, &rz->segments);
- /* set a first size; will grow up with time if needed */
- return darray_segment_resize(&rz->segments, 16);
-}
-
-static void
-clear_realization(struct realisation* rz)
-{
- ASSERT(rz);
- darray_segment_clear(&rz->segments);
-}
-
-static void
-reset_segment(struct segment* seg)
-{
- ASSERT(seg);
- seg->range[0] = 0;
- seg->range[1] = FLT_MAX;
- seg->hit = S3D_HIT_NULL;
-}
-
-static struct ssol_material*
-get_material_from_hit(struct ssol_scene* scene, struct s3d_hit* hit)
-{
- struct ssol_object_instance* instance;
- struct ssol_object* object;
- struct ssol_material* material;
- ASSERT(scene && hit);
- instance = scene_get_object_instance_from_s3d_hit(scene, hit);
- ASSERT(instance);
- object = object_instance_get_object(instance);
- ASSERT(object);
- material = object_get_material(object);
- ASSERT(material);
- return material;
-}
-
-/*******************************************************************************
- * Exported function
- ******************************************************************************/
-res_T
-ssol_solve
- (struct ssol_scene* scene,
- struct ssp_rng* rng,
- const size_t realisations_count,
- FILE* output)
-{
- struct solver_data data;
- struct brdf_composite* brdfs = NULL;
- struct s3d_primitive primitive;
- struct s3d_attrib attrib;
- float uv[2];
- const struct ssol_sun* sun = NULL;
- struct realisation rz;
- size_t r;
- double _dir[3];
- res_T res = RES_OK;
-
- struct ssol_device* device = NULL;
-
- if (!scene || !rng || !output || !realisations_count)
- return RES_BAD_ARG;
-
- /* init realization */
- device = scene_get_device(scene);
- ASSERT(device && device->allocator);
- res = init_realization(device->allocator, &rz);
- if (res != RES_OK) goto error;
-
- res = brdf_composite_create(device, &brdfs);
- if (res != RES_OK) goto error;
-
- /* init scene representation data */
- res = init_solver_data(scene, &data);
- if (res != RES_OK) goto error;
-
- sun = scene_get_sun(scene);
- rz.sun_segment.weight = sun_get_dni(sun);
- for (r = 0; r < realisations_count; r++) {
- struct segment* prev = NULL;
- struct segment* seg = &rz.sun_segment;
- struct surface_fragment fragment;
- float r1, r2, r3;
- float sundir[3];
- float normal[3];
- /* reset realization */
- reset_realization(&rz);
-
- /* sample a point on the reflectors */
- r1 = ssp_rng_canonical_float(rng);
- r2 = ssp_rng_canonical_float(rng);
- r3 = ssp_rng_canonical_float(rng);
- S3D(scene_view_sample(data.sample_view, r1, r2, r3, &primitive, uv));
- S3D(primitive_get_attrib(&primitive, S3D_POSITION, uv, &attrib));
- CHECK(attrib.type, S3D_FLOAT3);
-
- /* sample an input dir from the sun */
- ranst_sun_dir_get(data.sun_dir_ran, rng, _dir);
-
- /* setup sun segment in the reverse direction to detect shadows */
- reset_segment(seg);
- f3_set(seg->org, attrib.value);
- f3_set_d3(sundir, _dir);
- f3_mulf(seg->dir, sundir, -1);
- CHECK(f3_is_normalized(seg->dir), 1);
-
- /* sample a frequency */
- rz.freq = ssp_ranst_piecewise_linear_get(data.sun_spectrum_ran, rng);
-
- /* check if the point receives sunlight */
- /* TODO: need only an occlusion test */
- S3D(scene_view_trace_ray
- (data.trace_view, seg->org, seg->dir, seg->range, NULL, &seg->hit));
- if (!S3D_HIT_NONE(&seg->hit)) {
- rz.final_weight = 0;
- rz.end = TERM_SHADOW;
- }
-
- /* fill fragment from starting point */
- S3D(primitive_get_attrib(&primitive, S3D_GEOMETRY_NORMAL, uv, &attrib));
- CHECK(attrib.type, S3D_FLOAT3);
- f3_set(normal, attrib.value);
- surface_fragment_setup(&fragment, seg->org, sundir, normal, &primitive, uv);
-
- /* start propagating from rz.sun_segment.hit_pos */
- while (rz.end == TERM_NONE) {
- struct ssol_material* material;
- float tmp[3];
-
- prev = seg;
- seg = current_segment(&rz);
- reset_segment(seg);
-
- /* the current segment starts at prev->hit_pos */
- f3_set(seg->org, prev->hit_pos);
-
- /* compute the output direction from the material */
- material = get_material_from_hit(scene, &prev->hit);
- CHECK(material_get_type(material), MATERIAL_MIRROR);
- res = material_shade(material, &fragment, rz.freq, brdfs);
- if (res != RES_OK) {
- rz.end = TERM_ERR;
- goto error;
- }
- f3_set_d3(tmp, fragment.Ns);
- seg->weight = prev->weight *
- brdf_composite_sample(brdfs, rng, prev->dir, tmp, seg->dir);
-
- /* then check if the ray hits something */
- S3D(scene_view_trace_ray
- (data.trace_view, seg->org, seg->dir, seg->range, NULL, &seg->hit));
- if (S3D_HIT_NONE(&seg->hit)) {
- rz.final_weight = 0;
- rz.end = TERM_MISSING;
- continue;
- }
- /* should not stop on a virtual surface */
- ASSERT(material_get_type(get_material_from_hit(scene, &seg->hit))
- != MATERIAL_VIRTUAL);
-
- /* fill fragment from hit and loop */
- f3_add(tmp, seg->org, f3_mulf(tmp, seg->dir, seg->hit.distance));
- surface_fragment_setup
- (&fragment, tmp, seg->dir, seg->hit.normal, &seg->hit.prim, seg->hit.uv);
-
- /* continue propagation with next segment */
- res = next_segment(&rz);
- if (res != RES_OK) {
- rz.end = TERM_ERR;
- goto error;
- }
- }
- rz.final_weight = seg->weight;
-
- fprintf(output, "%d %g %g\n", rz.end, rz.final_weight, rz.freq);
- continue;
- }
-
-exit:
- /* TODO: release data */
- clear_realization(&rz);
- return res;
-error:
- goto exit;
-}
-
/*******************************************************************************
* Local functions
******************************************************************************/
res_T
-set_sun_distributions(struct solver_data* data)
-{
+set_sun_distributions(struct solver_data* data) {
struct ssol_spectrum* spectrum;
struct ssol_device* dev;
const struct ssol_sun* sun;
@@ -351,7 +80,6 @@ set_sun_distributions(struct solver_data* data)
const double* intensities;
res_T res = RES_OK;
size_t sz;
-
if (!data) return RES_BAD_ARG;
ASSERT(data->scene);
@@ -403,12 +131,22 @@ error:
goto exit;
}
+static void
+release_solver_data(struct solver_data* data) {
+ ASSERT(data);
+ if (data->trace_view) s3d_scene_view_ref_put(data->trace_view);
+ if (data->sample_view) s3d_scene_view_ref_put(data->sample_view);
+ if (data->sun_dir_ran) ranst_sun_dir_ref_put(data->sun_dir_ran);
+ if (data->sun_spectrum_ran) ssp_ranst_piecewise_linear_ref_put(data->sun_spectrum_ran);
+ if (data->brdfs) brdf_composite_ref_put(data->brdfs);
+ *data = SOLVER_DATA_NULL;
+}
+
res_T
-set_views(struct solver_data* data)
-{
+set_views(struct solver_data* data) {
res_T res = RES_OK;
struct ssol_scene* scene;
- struct s3d_scene* raytrace_scene;
+ struct s3d_scene* raytracing_scene;
struct s3d_scene* sampling_scene;
struct htable_instance_iterator it, it_end;
int mirror_found = 0;
@@ -417,26 +155,42 @@ set_views(struct solver_data* data)
scene = data->scene;
ASSERT(scene);
- raytrace_scene = scene_get_s3d_scene(scene);
- ASSERT(raytrace_scene);
+ raytracing_scene = scene_get_s3d_raytracing_scn(scene);
+ ASSERT(raytracing_scene);
sampling_scene = scene_get_s3d_sampling_scn(scene);
ASSERT(sampling_scene);
/* feed sampling s3d_scene */
S3D(scene_clear(sampling_scene));
- htable_instance_begin(&scene->instances, &it);
htable_instance_end(&scene->instances, &it_end);
- while (!htable_instance_iterator_eq(&it, &it_end)) {
+ for (
+ htable_instance_begin(&scene->instances, &it);
+ !htable_instance_iterator_eq(&it, &it_end);
+ htable_instance_iterator_next(&it))
+ {
struct ssol_object_instance* inst;
struct ssol_material* mat;
+ struct ssol_object* object;
inst = *htable_instance_iterator_data_get(&it);
- /* keep only primary mirrors */
+
+ /* TODO: keep only primary mirrors */
mat = inst->object->material;
if (material_get_type(mat) != MATERIAL_MIRROR)
continue;
mirror_found = 1;
- res = s3d_scene_attach_shape(sampling_scene, inst->s3d_shape);
+
+ object = object_instance_get_object(inst);
+ switch (object->shape->type) {
+ case SHAPE_MESH:
+ /* the same mesh is used for sampling and raytracing */
+ res = s3d_scene_attach_shape(sampling_scene, inst->s3d_shape);
+ break;
+ case SHAPE_PUNCHED:
+ /* use the carving's mesh for sampling */
+ FATAL("TODO\n");
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
if (res != RES_OK) goto error;
- htable_instance_iterator_next(&it);
}
if (!mirror_found) {
res = RES_BAD_ARG;
@@ -444,7 +198,7 @@ set_views(struct solver_data* data)
goto error;
}
/* create views from scenes */
- res = s3d_scene_view_create(raytrace_scene, S3D_TRACE, &data->trace_view);
+ res = s3d_scene_view_create(raytracing_scene, S3D_TRACE, &data->trace_view);
if (res != RES_OK) goto error;
res = s3d_scene_view_create(sampling_scene, S3D_SAMPLE, &data->sample_view);
if (res != RES_OK) goto error;
@@ -452,8 +206,422 @@ set_views(struct solver_data* data)
exit:
return res;
error:
- /* TODO: clear data */
+ release_solver_data(data);
goto exit;
}
+struct segment*
+previous_segment(struct realisation* rz)
+{
+ size_t idx;
+ ASSERT(rz);
+ if (!rz->s_idx) return NULL;
+ idx = rz->s_idx - 1;
+ ASSERT(idx < darray_segment_size_get(&rz->segments));
+ return darray_segment_data_get(&rz->segments) + idx;
+}
+
+struct segment*
+sun_segment(struct realisation* rz)
+{
+ struct segment* seg;
+ ASSERT(rz);
+ seg = darray_segment_data_get(&rz->segments);
+ ASSERT(seg);
+ return seg;
+}
+
+struct segment*
+current_segment(struct realisation* rz)
+{
+ struct segment* seg;
+ ASSERT(rz);
+ ASSERT(rz->s_idx < darray_segment_size_get(&rz->segments));
+ seg = darray_segment_data_get(&rz->segments) + rz->s_idx;
+ ASSERT(seg);
+ return seg;
+}
+res_T
+next_segment(struct realisation* rz)
+{
+ res_T res = RES_OK;
+ ASSERT(rz);
+ ++rz->s_idx;
+ if (rz->s_idx >= darray_segment_size_get(&rz->segments)) {
+ res = darray_segment_resize(&rz->segments, rz->s_idx + 1);
+ if (res != RES_OK) return res;
+ }
+ reset_segment(current_segment(rz));
+ return RES_OK;
+}
+
+/* TODO: move to Star3D */
+static INLINE void s3d_invalidate_hit(struct s3d_hit* hit) {
+ ASSERT(hit);
+ hit->distance = FLT_MAX;
+}
+
+void
+reset_segment(struct segment* seg)
+{
+ ASSERT(seg);
+ seg->range[0] = 0;
+ seg->range[1] = FLT_MAX;
+ s3d_invalidate_hit(&seg->hit);
+}
+
+static void
+reset_starting_point(struct starting_point* start)
+{
+ ASSERT(start);
+ start->primitive = S3D_PRIMITIVE_NULL;
+}
+
+static void
+reset_realization(size_t cpt, struct realisation* rz)
+{
+ rz->s_idx = 0;
+ rz->s_idx = 0;
+ rz->end = TERM_NONE;
+ rz->mode = MODE_STD;
+ rz->rz_id = cpt;
+ rz->success_mask = 0;
+ reset_starting_point(&rz->start);
+ brdf_composite_clear(rz->data.brdfs);
+ rz->data.instance = NULL;
+ /* reset sun segment (always used) */
+ reset_segment(sun_segment(rz));
+}
+
+static res_T
+init_realization
+ (struct ssol_scene* scene,
+ struct ssp_rng* rng,
+ FILE* out,
+ struct realisation* rz)
+{
+ res_T res = RES_OK;
+ struct ssol_device* device;
+
+ if (!scene || !rng || !rz) return RES_BAD_ARG;
+
+ device = scene_get_device(scene);
+ ASSERT(device && device->allocator);
+
+ darray_segment_init(device->allocator, &rz->segments);
+ /* set a first size; will grow up with time if needed */
+ res = darray_segment_resize(&rz->segments, 16);
+ if (res != RES_OK) goto error;
+
+ rz->data = SOLVER_DATA_NULL;
+ rz->data.scene = scene;
+ rz->data.rng = rng;
+ rz->data.out_stream = out;
+ /* create 2 s3d_scene_view for raytracing and sampling */
+ res = set_views(&rz->data);
+ if (res != RES_OK) goto error;
+ /* create sun distributions */
+ res = set_sun_distributions(&rz->data);
+ if (res != RES_OK) goto error;
+ res = brdf_composite_create(device, &rz->data.brdfs);
+ if (res != RES_OK) goto error;
+
+exit:
+ return res;
+error:
+ release_solver_data(&rz->data);
+ goto exit;
+}
+
+static void
+release_realization(struct realisation* rz)
+{
+ ASSERT(rz);
+ release_solver_data(&rz->data);
+ darray_segment_release(&rz->segments);
+}
+
+static struct ssol_material*
+get_material_from_hit(struct ssol_scene* scene, struct s3d_hit* hit) {
+ struct ssol_object_instance* instance;
+ struct ssol_object* object;
+ struct ssol_material* material;
+ ASSERT(scene && hit);
+ instance = scene_get_object_instance_from_s3d_hit(scene, hit);
+ ASSERT(instance);
+ object = object_instance_get_object(instance);
+ ASSERT(object);
+ material = object_get_material(object);
+ ASSERT(material);
+ return material;
+}
+
+static void
+sample_point_on_primary_mirror(struct realisation* rz)
+{
+ struct s3d_attrib attrib;
+ struct ssol_object* object;
+ float r1, r2, r3;
+ struct solver_data* data;
+ struct segment* seg = sun_segment(rz);
+ struct s3d_primitive tmp_prim;
+
+ data = &rz->data;
+ ASSERT(data->rng && data->sample_view && data->scene);
+ /* sample a point on a primary mirror's carving */
+ r1 = ssp_rng_canonical_float(data->rng);
+ r2 = ssp_rng_canonical_float(data->rng);
+ r3 = ssp_rng_canonical_float(data->rng);
+ S3D(scene_view_sample(data->sample_view, r1, r2, r3, &tmp_prim, rz->start.uv));
+ S3D(primitive_get_attrib(&tmp_prim, S3D_POSITION, rz->start.uv, &attrib));
+ CHECK(attrib.type, S3D_FLOAT3);
+ /* find the solstice shape and project the sampled point on the mirror */
+ rz->start.instance =
+ *htable_instance_find(&data->scene->instances, &tmp_prim.inst_id);
+ ASSERT(rz->start.instance);
+ object = object_instance_get_object(rz->start.instance);
+ ASSERT(object && object->shape);
+ rz->start.material = object_get_material(object);
+ ASSERT(rz->start.material);
+ switch (object->shape->type) {
+ case SHAPE_MESH:
+ /* no projection needed */
+ f3_set(seg->org, attrib.value);
+ /* to avoid self intersect */
+ rz->start.primitive = tmp_prim;
+ break;
+ case SHAPE_PUNCHED:
+ /* project the sampled point on the quadric */
+ FATAL("TODO\n");
+ /* cannot self intersect as the sampled mesh is not raytraced */
+ rz->start.primitive = S3D_PRIMITIVE_NULL;
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+}
+
+static void
+sample_input_sundir(struct realisation* rz)
+{
+ ASSERT(rz);
+ ranst_sun_dir_get(rz->data.sun_dir_ran, rz->data.rng, rz->start.sundir);
+}
+
+static void
+sample_wavelength(struct realisation* rz)
+{
+ ASSERT(rz);
+ rz->freq = ssp_ranst_piecewise_linear_get(rz->data.sun_spectrum_ran, rz->data.rng);
+}
+
+static int
+receive_sunlight(struct realisation* rz)
+{
+ float sundir_f[3];
+ struct s3d_attrib attrib;
+ struct segment* seg = sun_segment(rz);
+ int receives;
+ const char* receiver_name;
+
+ f3_set_d3(sundir_f, rz->start.sundir);
+ f3_mulf(seg->dir, sundir_f, -1);
+ CHECK(f3_is_normalized(seg->dir), 1);
+ /* check normal orientation */
+ S3D(primitive_get_attrib(&rz->start.primitive, S3D_GEOMETRY_NORMAL, rz->start.uv, &attrib));
+ CHECK(attrib.type, S3D_FLOAT3);
+ /* fill fragment from starting point; must use sundir_f, not seg->dir */
+ surface_fragment_setup(&rz->data.fragment, seg->org, sundir_f, attrib.value, &rz->start.primitive, rz->start.uv);
+ /* check normal orientation */
+ rz->start.cos_sun = d3_dot(rz->data.fragment.Ng, rz->start.sundir);
+ if (rz->start.cos_sun >= 0)
+ return 0;
+ /* check occlusion, avoiding self intersect */
+ seg->hit.prim = rz->start.primitive;
+ /* TODO (in s3d): need an occlusion test */
+ S3D(scene_view_trace_ray(rz->data.trace_view, seg->org, seg->dir, seg->range, rz, &seg->hit));
+ receives = S3D_HIT_NONE(&seg->hit);
+ if (!receives) return receives;
+
+ /* if the sampled instance is a receiver, register the sampled point */
+ receiver_name = object_instance_get_receiver_name(rz->start.instance);
+ if (receiver_name) {
+ /* normal orientation has already been checked */
+ fprintf(rz->data.out_stream,
+ "Receiver '%s': %u %u %g %g (%g:%g:%g) (%g:%g:%g) (%g:%g)\n",
+ receiver_name,
+ (unsigned) rz->rz_id,
+ (unsigned) rz->s_idx,
+ rz->freq,
+ seg->weight,
+ SPLIT3(seg->org),
+ SPLIT3(sundir_f),
+ SPLIT2(rz->start.uv));
+ }
+
+ /* register success mask (normal orientation has already been checked) */
+ rz->success_mask |= object_instance_get_target_mask(rz->start.instance);
+
+ /* restaure self intersect information for further visibility test
+ (previous call to trace_ray overwrote prim) */
+ seg->hit.prim = rz->start.primitive;
+
+ return receives;
+}
+
+static res_T
+set_output_pos_and_dir(struct realisation* rz) {
+ struct ssol_material* material;
+ struct segment* seg = current_segment(rz);
+ struct segment* prev = previous_segment(rz);
+ struct ssol_scene* scene = rz->data.scene;
+ float tmp[3];
+ int fst_segment;
+ res_T res = RES_OK;
+
+ /* next_segment should have been called */
+ ASSERT(prev);
+
+ fst_segment = (prev == sun_segment(rz));
+
+ if (fst_segment) {
+ f3_set(seg->org, prev->org);
+ material = rz->start.material;
+ }
+ else {
+ f3_set(seg->org, prev->hit_pos);
+ material = get_material_from_hit(scene, &prev->hit);
+ }
+ CHECK(material_get_type(material), MATERIAL_MIRROR);
+ res = material_shade(material, &rz->data.fragment, rz->freq, rz->data.brdfs);
+ if (res != RES_OK) {
+ rz->end = TERM_ERR;
+ return res;
+ }
+ f3_set_d3(tmp, rz->data.fragment.Ns);
+
+ if (fst_segment) {
+ float sundir_f[3];
+ const struct ssol_sun* sun = scene_get_sun(rz->data.scene);
+ ASSERT(-1 <= rz->start.cos_sun && rz->start.cos_sun <= 0);
+ f3_set_d3(sundir_f, rz->start.sundir);
+ seg->weight = sun_get_dni(sun)
+ * brdf_composite_sample(rz->data.brdfs, rz->data.rng, sundir_f, tmp, seg->dir)
+ * -rz->start.cos_sun;
+ }
+ else {
+ seg->weight = prev->weight *
+ brdf_composite_sample(rz->data.brdfs, rz->data.rng, prev->dir, tmp, seg->dir);
+ }
+ return res;
+}
+
+static void
+propagate(struct realisation* rz)
+{
+ struct segment* seg = current_segment(rz);
+ struct ssol_scene* scene = rz->data.scene;
+
+ /* check if the ray hits something */
+ S3D(scene_view_trace_ray(rz->data.trace_view, seg->org, seg->dir, seg->range, rz, &seg->hit));
+ if (S3D_HIT_NONE(&seg->hit)) {
+ rz->end = TERM_MISSING;
+ return;
+ }
+ /* should not stop on a virtual surface */
+ ASSERT(material_get_type(get_material_from_hit(scene, &seg->hit))
+ != MATERIAL_VIRTUAL);
+
+ /* offset the impact point and recompute normal if needed */
+ ASSERT(rz->data.instance);
+ switch (rz->data.instance->object->shape->type) {
+ case SHAPE_MESH:
+ /* no postprocess needed */
+ break;
+ case SHAPE_PUNCHED:
+ /* project the impact point on the quadric */
+ FATAL("TODO\n");
+ /* compute normal to quadric */
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+
+ /* fill fragment from hit and loop */
+ f3_set(seg->hit_pos, f3_add(seg->hit_pos, seg->org, f3_mulf(seg->hit_pos, seg->dir, seg->hit.distance)));
+ surface_fragment_setup(&rz->data.fragment, seg->hit_pos, seg->dir, seg->hit.normal, &seg->hit.prim, seg->hit.uv);
+}
+
+/*******************************************************************************
+ * Exported function
+ ******************************************************************************/
+res_T
+ssol_solve
+ (struct ssol_scene* scene,
+ struct ssp_rng* rng,
+ const size_t realisations_count,
+ FILE* output)
+{
+ struct realisation rz;
+ size_t r;
+ res_T res = RES_OK;
+
+ struct ssol_device* device = NULL;
+
+ if (!scene || !rng || !output || !realisations_count)
+ return RES_BAD_ARG;
+
+ device = scene_get_device(scene);
+ ASSERT(device && device->allocator);
+
+ /* init realization */
+ res = init_realization(scene, rng, output, &rz);
+ if (res != RES_OK) goto error;
+
+ for (r = 0; r < realisations_count; r++) {
+ /* reset realization */
+ reset_realization(r, &rz);
+
+ /* sample a point on a primary mirror */
+ sample_point_on_primary_mirror(&rz);
+
+ /* sample an input dir from the sun */
+ sample_input_sundir(&rz);
+
+ /* sample a frequency */
+ sample_wavelength(&rz);
+
+ /* check if the point receives sun light */
+ if (!receive_sunlight(&rz)) {
+ rz.end = rz.start.cos_sun >= 0 ? TERM_POINTING : TERM_SHADOW;
+ }
+ else {
+ /* start propagating from mirror */
+ do {
+ if (RES_OK != next_segment(&rz)) {
+ rz.end = TERM_ERR;
+ }
+ else {
+ /* set next segment and propagate */
+ set_output_pos_and_dir(&rz);
+ propagate(&rz);
+ }
+ } while (rz.end == TERM_NONE);
+ }
+
+ /* propagation ended */
+ if (rz.success_mask)
+ fprintf(output, "Realization %u succeeded: 0x%0x\n", (unsigned)r, rz.success_mask);
+ else
+ fprintf(output, "Realization %u failed: %s\n", (unsigned)r, END_TEXT[rz.end]);
+
+ /* next realization */
+ continue;
+ }
+
+exit:
+ release_realization(&rz);
+ return res;
+error:
+ /* TODO: release data */
+ goto exit;
+}
diff --git a/src/ssol_solver_c.h b/src/ssol_solver_c.h
@@ -17,12 +17,16 @@
#define SSOL_SOLVER_C_H
#include "ssol_ranst_sun_dir.h"
+#include "ssol_material_c.h"
+#include "ssol_c.h"
#include <rsys/ref_count.h>
#include <rsys/list.h>
#include <rsys/dynamic_array.h>
#include <star/ssp.h>
+#include <star/s3d.h>
+
#define DARRAY_NAME quadric
#define DARRAY_DATA struct ssol_quadric
@@ -32,8 +36,45 @@
#define DARRAY_DATA struct s3d_shape*
#include <rsys/dynamic_array.h>
+enum realization_termination {
+ TERM_NONE,
+ TERM_SUCCESS,
+ TERM_SHADOW,
+ TERM_POINTING,
+ TERM_MISSING,
+ TERM_BLOCKED,
+ TERM_ERR,
+
+ TERM_COUNT__
+};
+
+struct segment {
+ double weight;
+ float range[2];
+ struct s3d_hit hit;
+ /* TODO: use double? */
+ float org[3], dir[4];
+ float hit_pos[3];
+};
+
+struct starting_point {
+ struct ssol_object_instance* instance;
+ struct ssol_material* material;
+ struct s3d_primitive primitive;
+ double sundir[3];
+ double cos_sun;
+ float uv[2];
+};
+
+#include <rsys/dynamic_array.h>
+#define DARRAY_DATA struct segment
+#define DARRAY_NAME segment
+#include <rsys/dynamic_array.h>
+
struct solver_data {
struct ssol_scene* scene;
+ struct ssp_rng* rng;
+ FILE* out_stream;
/* the s3d_scene_view used for raytracing */
struct s3d_scene_view* trace_view;
/* the s3d_scene_view used for sampling */
@@ -41,9 +82,27 @@ struct solver_data {
/* the random distributions for sun sampling */
struct ranst_sun_dir* sun_dir_ran;
struct ssp_ranst_piecewise_linear* sun_spectrum_ran;
+ /* tmp data used for propagation */
+ struct brdf_composite* brdfs;
+ struct ssol_object_instance* instance;
+ struct surface_fragment fragment;
};
-/* TODO: refcount management for data */
+#define SOLVER_DATA_NULL__ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+struct realisation {
+ enum realization_termination end;
+ enum realization_mode mode;
+ struct darray_segment segments;
+ struct starting_point start;
+ struct solver_data data;
+ double freq;
+ size_t s_idx;
+ size_t rz_id;
+ uint32_t success_mask;
+};
+
+static const struct solver_data SOLVER_DATA_NULL = SOLVER_DATA_NULL__;
extern LOCAL_SYM res_T
set_sun_distributions(struct solver_data* data);
@@ -51,5 +110,20 @@ set_sun_distributions(struct solver_data* data);
extern LOCAL_SYM res_T
set_views(struct solver_data* data);
+extern LOCAL_SYM struct segment*
+previous_segment(struct realisation* rz);
+
+extern LOCAL_SYM struct segment*
+sun_segment(struct realisation* rz);
+
+extern LOCAL_SYM struct segment*
+current_segment(struct realisation* rz);
+
+extern LOCAL_SYM res_T
+next_segment(struct realisation* rz);
+
+extern LOCAL_SYM void
+reset_segment(struct segment* seg);
+
#endif /* SSOL_SOLVER_C_H */
diff --git a/src/test_ssol_geometries.h b/src/test_ssol_geometries.h
@@ -25,18 +25,20 @@ struct desc {
* Plane
******************************************************************************/
-static const float plane_walls [] = {
+static const float square_walls [] = {
-1, -1, 0,
- 1, -1, 0,
- 1, 1, 0,
+ 1, -1, 0,
+ 1, 1, 0,
-1, 1, 0
};
-const unsigned plane_walls_nverts = sizeof(plane_walls) / sizeof(float[3]);
+const unsigned square_walls_nverts = sizeof(square_walls) / sizeof(float[3]);
-const unsigned plane_walls_ids [] = {
- 0, 1, 2, 2, 3, 0
+const unsigned square_walls_ids [] = {
+ 0, 2, 1, 2, 0, 3
};
-const unsigned plane_walls_ntris = sizeof(plane_walls_ids) / sizeof(unsigned[3]);
+const unsigned square_walls_ntris = sizeof(square_walls_ids) / sizeof(unsigned[3]);
+
+static struct desc square_walls_desc = { square_walls, square_walls_ids };
/*******************************************************************************
* Box
diff --git a/src/test_ssol_object_instance.c b/src/test_ssol_object_instance.c
@@ -63,6 +63,11 @@ main(int argc, char** argv)
CHECK(ssol_object_instance_set_receiver(instance, "receiver 0"), RES_OK);
CHECK(ssol_object_instance_set_receiver(instance, NULL), RES_OK);
+ CHECK(ssol_object_instance_set_target_mask(NULL, 1), RES_BAD_ARG);
+ CHECK(ssol_object_instance_set_target_mask(instance, 1), RES_OK);
+ CHECK(ssol_object_instance_set_target_mask(instance, 0), RES_OK);
+ CHECK(ssol_object_instance_set_target_mask(instance, 0x10), RES_OK);
+
CHECK(ssol_object_instance_ref_put(instance), RES_OK);
CHECK(ssol_object_ref_put(object), RES_OK);
diff --git a/src/test_ssol_solver.c b/src/test_ssol_solver.c
@@ -16,14 +16,19 @@
#include "ssol.h"
#include "test_ssol_utils.h"
#include "test_ssol_geometries.h"
+#include "test_ssol_materials.h"
#include "ssol_solver_c.h"
#include <rsys/logger.h>
-#include <rsys/double3.h>
+#include <rsys/double33.h>
#include <star/ssp.h>
+
+
+#include <star/s3d.h>
+
/*******************************************************************************
* test main program
******************************************************************************/
@@ -35,19 +40,36 @@ main(int argc, char** argv)
struct ssol_device* dev;
struct ssp_rng* rng;
struct ssol_scene* scene;
- struct ssol_shape* shape;
- struct ssol_vertex_data attribs[3];
- struct ssol_material* material;
+ struct ssol_shape* square;
+ struct ssol_vertex_data attribs[1];
+ struct ssol_material* m_material;
+ struct ssol_material* v_material;
struct ssol_mirror_shader shader;
- struct ssol_object* object;
- struct ssol_object_instance* instance;
+ struct ssol_object* m_object;
+ struct ssol_object* t_object;
+ struct ssol_object_instance* heliostat;
+ struct ssol_object_instance* secondary;
+ struct ssol_object_instance* target;
struct ssol_sun* sun;
struct ssol_spectrum* spectrum;
double dir[3];
double frequencies[3] = { 1, 2, 3 };
double intensities[3] = { 1, 0.8, 1 };
+ double transform1[12]; /* 3x4 column major matrix */
+ double transform2[12]; /* 3x4 column major matrix */
+
(void) argc, (void) argv;
+ d33_splat(transform1, 0);
+ d3_splat(transform1 + 9, 0);
+ d33_rotation_pitch(transform1, PI); /* flip faces: invert normal */
+ transform1[9] = 2; /* +2 offset along X axis */
+ transform1[11] = 2; /* +2 offset along Z axis */
+
+ d33_set_identity(transform2);
+ d3_splat(transform2 + 9, 0);
+ transform2[9] = 4; /* +4 offset along X axis */
+
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
CHECK(logger_init(&allocator, &logger), RES_OK);
@@ -62,7 +84,7 @@ main(int argc, char** argv)
CHECK(ssol_spectrum_create(dev, &spectrum), RES_OK);
CHECK(ssol_spectrum_setup(spectrum, frequencies, intensities, 3), RES_OK);
CHECK(ssol_sun_create_directional(dev, &sun), RES_OK);
- CHECK(ssol_sun_set_direction(sun, d3(dir, 0, 0, -10)), RES_OK);
+ CHECK(ssol_sun_set_direction(sun, d3(dir, 1, 0, -1)), RES_OK);
CHECK(ssol_sun_set_spectrum(sun, spectrum), RES_OK);
CHECK(ssol_sun_set_dni(sun, 1000), RES_OK);
CHECK(ssol_scene_create(dev, &scene), RES_OK);
@@ -75,34 +97,55 @@ main(int argc, char** argv)
CHECK(ssol_solve(scene, rng, 10, stdout), RES_BAD_ARG); /* no geometry */
/* create scene content */
- CHECK(ssol_shape_create_mesh(dev, &shape), RES_OK);
+
+ CHECK(ssol_shape_create_mesh(dev, &square), RES_OK);
attribs[0].usage = SSOL_POSITION;
attribs[0].get = get_position;
- attribs[1].usage = SSOL_NORMAL;
- attribs[1].get = get_normal;
- attribs[2].usage = SSOL_TEXCOORD;
- attribs[2].get = get_uv;
- CHECK(ssol_mesh_setup(shape, box_walls_ntris, get_ids, box_walls_nverts,
- attribs, 3, &box_walls_desc), RES_OK);
- CHECK(ssol_material_create_mirror(dev, &material), RES_OK);
- CHECK(ssol_mirror_set_shader(material, &shader), RES_OK);
- CHECK(ssol_object_create(dev, shape, material, &object), RES_OK);
- CHECK(ssol_object_instantiate(object, &instance), RES_OK);
- CHECK(ssol_scene_attach_object_instance(scene, instance), RES_OK);
-
- CHECK(ssol_solve(scene, rng, 10, stdout), RES_OK);
-
- CHECK(ssol_scene_detach_object_instance(scene, instance), RES_OK);
-
- CHECK(ssol_object_instance_ref_put(instance), RES_OK);
- CHECK(ssol_object_ref_put(object), RES_OK);
- CHECK(ssol_shape_ref_put(shape), RES_OK);
- CHECK(ssol_material_ref_put(material), RES_OK);
+ CHECK(ssol_mesh_setup
+ (square, square_walls_ntris, get_ids, square_walls_nverts, attribs, 1, &square_walls_desc), RES_OK);
+
+ CHECK(ssol_material_create_mirror(dev, &m_material), RES_OK);
+ shader.normal = get_shader_normal;
+ shader.reflectivity = get_shader_reflectivity;
+ shader.roughness = get_shader_roughness;
+ CHECK(ssol_mirror_set_shader(m_material, &shader), RES_OK);
+ CHECK(ssol_material_create_virtual(dev, &v_material), RES_OK);
+
+ CHECK(ssol_object_create(dev, square, m_material, &m_object), RES_OK);
+ CHECK(ssol_object_instantiate(m_object, &heliostat), RES_OK);
+ CHECK(ssol_object_instance_set_receiver(heliostat, "miroir"), RES_OK);
+ CHECK(ssol_object_instance_set_target_mask(heliostat, 0x1), RES_OK);
+ CHECK(ssol_scene_attach_object_instance(scene, heliostat), RES_OK);
+
+ CHECK(ssol_object_instantiate(m_object, &secondary), RES_OK);
+ CHECK(ssol_object_instance_set_receiver(secondary, "secondaire"), RES_OK);
+ CHECK(ssol_object_instance_set_transform(secondary, transform1), RES_OK);
+ CHECK(ssol_object_instance_set_target_mask(secondary, 0x2), RES_OK);
+ CHECK(ssol_scene_attach_object_instance(scene, secondary), RES_OK);
+
+ CHECK(ssol_object_create(dev, square, v_material, &t_object), RES_OK);
+ CHECK(ssol_object_instantiate(t_object, &target), RES_OK);
+ CHECK(ssol_object_instance_set_transform(target, transform2), RES_OK);
+ CHECK(ssol_object_instance_set_receiver(target, "cible"), RES_OK);
+ CHECK(ssol_object_instance_set_target_mask(target, 0x4), RES_OK);
+ CHECK(ssol_scene_attach_object_instance(scene, target), RES_OK);
+
+ CHECK(ssol_solve(scene, rng, 20, stdout), RES_OK);
+
+ /* free data */
+
+ CHECK(ssol_object_instance_ref_put(heliostat), RES_OK);
+ CHECK(ssol_object_instance_ref_put(secondary), RES_OK);
+ CHECK(ssol_object_instance_ref_put(target), RES_OK);
+ CHECK(ssol_object_ref_put(m_object), RES_OK);
+ CHECK(ssol_object_ref_put(t_object), RES_OK);
+ CHECK(ssol_shape_ref_put(square), RES_OK);
+ CHECK(ssol_material_ref_put(m_material), RES_OK);
+ CHECK(ssol_material_ref_put(v_material), RES_OK);
CHECK(ssol_device_ref_put(dev), RES_OK);
- CHECK(ssol_scene_clear(scene), RES_OK);
+ CHECK(ssol_scene_ref_put(scene), RES_OK);
CHECK(ssp_rng_ref_put(rng), RES_OK);
CHECK(ssol_spectrum_ref_put(spectrum), RES_OK);
- CHECK(ssol_scene_detach_sun(scene, sun), RES_OK);
CHECK(ssol_sun_ref_put(sun), RES_OK);
logger_release(&logger);