commit 165c342ef4bdb23f8c539eb7f84521aec44d5f94
parent 1856771104e7eedf6c62237a2a535683e9f865cb
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 6 Sep 2016 15:43:53 +0200
Differentiate the front/back-facing materials
Diffstat:
9 files changed, 106 insertions(+), 82 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -383,7 +383,8 @@ SSOL_API res_T
ssol_object_create
(struct ssol_device* dev,
struct ssol_shape* shape,
- struct ssol_material* mtl,
+ 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
diff --git a/src/ssol_object.c b/src/ssol_object.c
@@ -18,23 +18,13 @@
#include "ssol_object_c.h"
#include "ssol_shape_c.h"
+#include <rsys/ref_count.h>
#include <rsys/rsys.h>
#include <rsys/mem_allocator.h>
-#include <rsys/ref_count.h>
/*******************************************************************************
* Helper functions
******************************************************************************/
-static INLINE res_T
-object_ok(const struct ssol_object* object)
-{
- if(!object
- || !object->shape
- || !object->material)
- return RES_BAD_ARG;
- return RES_OK;
-}
-
static void
object_release(ref_T* ref)
{
@@ -44,7 +34,8 @@ object_release(ref_T* ref)
dev = object->dev;
ASSERT(dev && dev->allocator);
SSOL(shape_ref_put(object->shape));
- SSOL(material_ref_put(object->material));
+ SSOL(material_ref_put(object->mtl_front));
+ SSOL(material_ref_put(object->mtl_back));
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);
@@ -58,28 +49,32 @@ res_T
ssol_object_create
(struct ssol_device* dev,
struct ssol_shape* shape,
- struct ssol_material* material,
+ 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 || !material || !out_object) {
- return RES_BAD_ARG;
+
+ if(!dev || !shape || !mtl_front || !mtl_back || !out_object) {
+ res = RES_BAD_ARG;
+ goto error;
}
- object = (struct ssol_object*)MEM_CALLOC
- (dev->allocator, 1, sizeof(struct ssol_object));
- if (!object) {
+ object = MEM_CALLOC(dev->allocator, 1, sizeof(struct ssol_object));
+ if(!object) {
res = RES_MEM_ERR;
goto error;
}
/* Check if material/shape association is legit: TODO */
SSOL(shape_ref_get(shape));
- SSOL(material_ref_get(material));
+ SSOL(material_ref_get(mtl_front));
+ SSOL(material_ref_get(mtl_back));
SSOL(device_ref_get(dev));
object->dev = dev;
object->shape = shape;
- object->material = material;
+ object->mtl_front = mtl_front;
+ object->mtl_back = mtl_back;
ref_init(&object->ref);
/* Create the Star-3D RT scene to instantiate through the instance */
@@ -95,10 +90,10 @@ ssol_object_create
if(res != RES_OK) goto error;
exit:
- if (out_object) *out_object = object;
+ if(out_object) *out_object = object;
return res;
error:
- if (object) {
+ if(object) {
SSOL(object_ref_put(object));
object = NULL;
}
@@ -108,8 +103,7 @@ error:
res_T
ssol_object_ref_get(struct ssol_object* object)
{
- if (!object)
- return RES_BAD_ARG;
+ if(!object) return RES_BAD_ARG;
ref_get(&object->ref);
return RES_OK;
}
@@ -117,8 +111,7 @@ ssol_object_ref_get(struct ssol_object* object)
res_T
ssol_object_ref_put(struct ssol_object* object)
{
- if (!object)
- return RES_BAD_ARG;
+ if(!object) return RES_BAD_ARG;
ref_put(&object->ref, object_release);
return RES_OK;
}
diff --git a/src/ssol_object_c.h b/src/ssol_object_c.h
@@ -20,7 +20,8 @@
struct ssol_object {
struct ssol_shape* shape;
- struct ssol_material* material;
+ struct ssol_material* mtl_front; /* Front faces material */
+ struct ssol_material* mtl_back; /* Back faces material */
struct s3d_scene* scn_rt; /* RT scene to instantiate */
struct s3d_scene* scn_samp; /* Sampling scene to instantiate */
diff --git a/src/ssol_scene.c b/src/ssol_scene.c
@@ -235,7 +235,8 @@ scene_setup_s3d_sampling_scene(struct ssol_scene* scn)
htable_instance_iterator_next(&it);
/* TODO: keep only primary mirrors */
- if(inst->object->material->type != MATERIAL_MIRROR)
+ if(inst->object->mtl_front->type != MATERIAL_MIRROR
+ && inst->object->mtl_back->type != MATERIAL_MIRROR)
continue;
/* Attach the instantiated s3d sampling shape to the s3d sampling scene */
@@ -274,6 +275,7 @@ hit_filter_function
struct ssol_object_instance* inst;
const char* receiver_name;
struct realisation* rs = realisation;
+ struct ssol_material* mtl;
struct segment* seg;
struct segment* prev;
int front_face = 0;
@@ -293,37 +295,35 @@ hit_filter_function
/* Check if the hit surface is a receiver that registers hit data */
receiver_name = object_instance_get_receiver_name(inst);
- if(receiver_name) {
- 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(rs->data.out_stream,
- "Receiver '%s': %u %u %g %g (%g:%g:%g) (%g:%g:%g) (%g:%g)\n",
- receiver_name,
- (unsigned)rs->rs_id,
- (unsigned)rs->s_idx,
- rs->freq,
- seg->weight,
- SPLIT3(pos),
- SPLIT3(dir),
- SPLIT2(hit->uv));
- }
+
+ front_face = f3_dot(hit->normal, dir) > 0;
+ mtl = front_face ? inst->object->mtl_front : inst->object->mtl_back;
+
+ if(receiver_name && front_face) {
+ float pos[3];
+ f3_add(pos, org, f3_mulf(pos, dir, hit->distance));
+ front_face = 1;
+ fprintf(rs->data.out_stream,
+ "Receiver '%s': %u %u %g %g (%g:%g:%g) (%g:%g:%g) (%g:%g)\n",
+ receiver_name,
+ (unsigned)rs->rs_id,
+ (unsigned)rs->s_idx,
+ rs->freq,
+ seg->weight,
+ SPLIT3(pos),
+ SPLIT3(dir),
+ SPLIT2(hit->uv));
}
/* register success mask */
if(front_face) {
rs->success_mask |= inst->target_mask;
}
-
- if(inst->object->material->type == MATERIAL_VIRTUAL) {
+ if(front_face) {
+ }
+ if(mtl->type == MATERIAL_VIRTUAL) {
return 1; /* Discard virtual material */
}
-
rs->data.instance = inst;
return 0;
}
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -55,7 +55,7 @@ get_quadric(const struct ssol_object_instance* instance)
}
static FINLINE void
-solstice_trace_ray(struct realisation* rs)
+solstice_trace_ray(struct realisation* rs)
{
float org[3], dir[3];
struct segment* seg = current_segment(rs);
@@ -296,12 +296,19 @@ release_realisation(struct realisation* rs)
}
static INLINE struct ssol_material*
-get_material_from_hit(struct ssol_scene* scene, struct s3d_hit* hit)
+get_material_from_hit
+ (struct ssol_scene* scene,
+ const double dir[3],
+ const struct s3d_hit* hit)
{
struct ssol_object_instance* inst;
+ float dirf[3];
+ int front_face;
ASSERT(scene && hit);
inst = *htable_instance_find(&scene->instances_rt, &hit->prim.inst_id);
- return inst->object->material;
+ f3_set_d3(dirf, dir);
+ front_face = f3_dot(dirf, hit->normal) < 0.f;
+ return front_face ? inst->object->mtl_front : inst->object->mtl_back;
}
static void
@@ -327,8 +334,26 @@ sample_point_on_primary_mirror(struct realisation* rs)
rs->start.instance = *htable_instance_find
(&data->scene->instances_samp, &tmp_prim.inst_id);
object = rs->start.instance->object;
- rs->start.material = object->material;
+
+ /* Define which side of the primitive is actually sampled */
+ if(object->mtl_front->type == MATERIAL_MIRROR) {
+ /* If both sides are mirrors, uniformly sample between them */
+ if(object->mtl_back->type == MATERIAL_MIRROR) {
+ if(ssp_rng_canonical_float(data->rng) > 0.5) {
+ rs->start.material = object->mtl_front;
+ } else {
+ rs->start.material = object->mtl_back;
+ }
+ } else {
+ rs->start.material = object->mtl_front;
+ }
+ } else if(object->mtl_back->type == MATERIAL_MIRROR) {
+ rs->start.material = object->mtl_back;
+ } else {
+ FATAL("Unreachable code.\n");
+ }
ASSERT(rs->start.material);
+
switch (object->shape->type) {
case SHAPE_MESH:
/* no projection needed */
@@ -342,7 +367,7 @@ sample_point_on_primary_mirror(struct realisation* rs)
/* cannot self intersect as the sampled mesh is not raytraced */
rs->start.primitive = S3D_PRIMITIVE_NULL;
break;
- default: FATAL("Unreachable code\n"); break;
+ default: FATAL("Unreachable code.\n"); break;
}
}
@@ -416,7 +441,8 @@ receive_sunlight(struct realisation* rs)
}
static res_T
-set_output_pos_and_dir(struct realisation* rs) {
+set_output_pos_and_dir(struct realisation* rs)
+{
struct ssol_material* material;
struct segment* seg = current_segment(rs);
struct segment* prev = previous_segment(rs);
@@ -434,7 +460,7 @@ set_output_pos_and_dir(struct realisation* rs) {
material = rs->start.material;
} else {
d3_set(seg->org, prev->hit_pos);
- material = get_material_from_hit(scene, &prev->hit);
+ material = get_material_from_hit(scene, prev->dir, &prev->hit);
}
CHECK(material->type, MATERIAL_MIRROR);
res = material_shade(material, &rs->data.fragment, rs->freq, rs->data.brdfs);
@@ -470,7 +496,7 @@ propagate(struct realisation* rs)
return;
}
/* should not stop on a virtual surface */
- ASSERT(get_material_from_hit(rs->data.scene, &seg->hit)->type
+ ASSERT(get_material_from_hit(rs->data.scene, seg->dir, &seg->hit)->type
!= MATERIAL_VIRTUAL);
/* offset the impact point and recompute normal if needed */
diff --git a/src/test_ssol_object.c b/src/test_ssol_object.c
@@ -25,7 +25,8 @@ main(int argc, char** argv)
struct mem_allocator allocator;
struct ssol_device* dev;
struct ssol_shape* shape;
- struct ssol_material* material;
+ struct ssol_material* mtl;
+ struct ssol_material* mtl2;
struct ssol_object* object;
(void) argc, (void) argv;
@@ -38,29 +39,31 @@ main(int argc, char** argv)
CHECK(ssol_device_create
(&logger, &allocator, SSOL_NTHREADS_DEFAULT, 0, &dev), RES_OK);
- CHECK(ssol_material_create_virtual(dev, &material), RES_OK);
+ CHECK(ssol_material_create_virtual(dev, &mtl), RES_OK);
+ 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, material, &object), RES_BAD_ARG);
- CHECK(ssol_object_create(dev, NULL, material, &object), RES_BAD_ARG);
- CHECK(ssol_object_create(dev, shape, NULL, &object), RES_BAD_ARG);
- CHECK(ssol_object_create(dev, shape, material, NULL), RES_BAD_ARG);
- CHECK(ssol_object_create(dev, shape, material, &object), 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_ref_get(NULL), RES_BAD_ARG);
CHECK(ssol_object_ref_get(object), RES_OK);
-
CHECK(ssol_object_ref_put(NULL), RES_BAD_ARG);
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_ref_put(object), RES_OK);
CHECK(ssol_shape_ref_put(shape), RES_OK);
- CHECK(ssol_material_ref_put(material), RES_OK);
-
+ CHECK(ssol_material_ref_put(mtl), RES_OK);
+ CHECK(ssol_material_ref_put(mtl2), RES_OK);
CHECK(ssol_device_ref_put(dev), RES_OK);
logger_release(&logger);
-
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
CHECK(mem_allocated_size(), 0);
diff --git a/src/test_ssol_object_instance.c b/src/test_ssol_object_instance.c
@@ -44,7 +44,7 @@ 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, &object), RES_OK);
+ CHECK(ssol_object_create(dev, shape, material, material, &object), RES_OK);
CHECK(ssol_object_instantiate(object, &instance), RES_OK);
diff --git a/src/test_ssol_scene.c b/src/test_ssol_scene.c
@@ -47,7 +47,7 @@ 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, &object), RES_OK);
+ CHECK(ssol_object_create(dev, shape, material, material, &object), RES_OK);
CHECK(ssol_object_instantiate(object, &instance), RES_OK);
CHECK(ssol_object_instance_set_transform(instance, transform), RES_OK);
CHECK(ssol_sun_create_directional(dev, &sun), RES_OK);
diff --git a/src/test_ssol_solver.c b/src/test_ssol_solver.c
@@ -39,8 +39,8 @@ main(int argc, char** argv)
struct ssol_scene* scene;
struct ssol_shape* square;
struct ssol_vertex_data attribs[1];
- struct ssol_material* m_material;
- struct ssol_material* v_material;
+ struct ssol_material* m_mtl;
+ struct ssol_material* v_mtl;
struct ssol_mirror_shader shader;
struct ssol_object* m_object;
struct ssol_object* t_object;
@@ -101,14 +101,14 @@ main(int argc, char** argv)
CHECK(ssol_mesh_setup(square, square_walls_ntris, get_ids,
square_walls_nverts, attribs, 1, (void*)&square_walls_desc), RES_OK);
- CHECK(ssol_material_create_mirror(dev, &m_material), RES_OK);
+ CHECK(ssol_material_create_mirror(dev, &m_mtl), 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_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_material, &m_object), RES_OK);
+ CHECK(ssol_object_create(dev, square, m_mtl, m_mtl, &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);
@@ -120,7 +120,7 @@ main(int argc, char** argv)
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_create(dev, square, v_mtl, v_mtl, &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);
@@ -137,8 +137,8 @@ main(int argc, char** argv)
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_material_ref_put(m_mtl), RES_OK);
+ CHECK(ssol_material_ref_put(v_mtl), RES_OK);
CHECK(ssol_device_ref_put(dev), RES_OK);
CHECK(ssol_scene_ref_put(scene), RES_OK);
CHECK(ssp_rng_ref_put(rng), RES_OK);