commit de54c65f9878b2e1c8a3aef6c2d9d33618010cdb
parent 67e48a4f266a890680e9e778af5e660666de6643
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Tue, 14 Mar 2017 18:30:02 +0100
Add normal to shapes and objects.
Diffstat:
6 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -318,6 +318,7 @@ struct ssol_mc_receiver {
struct ssol_mc_sampled {
struct ssol_mc_result shadowed;
+ double n[3]; /* normals */
size_t nb_samples;
};
@@ -679,6 +680,12 @@ ssol_object_get_area
(const struct ssol_object* object,
double* area);
+/* Retrieve the normal of the object */
+SSOL_API res_T
+ssol_object_get_normal
+ (const struct ssol_object* object,
+ double normal[3]);
+
/*******************************************************************************
* Object Instance API - Clone of an object with a set of per instance data as
* world transformation, material parameters, etc. Note that the object
diff --git a/src/ssol_object.c b/src/ssol_object.c
@@ -23,6 +23,7 @@
#include <rsys/ref_count.h>
#include <rsys/rsys.h>
#include <rsys/mem_allocator.h>
+#include <rsys/double3.h>
/*******************************************************************************
* Helper functions
@@ -164,6 +165,7 @@ ssol_object_add_shaded_shape
/* Setup the object shaded shape */
object->scn_rt_area += shape->shape_rt_area;
object->scn_samp_area += shape->shape_samp_area;
+ d3_add(object->n, object->n, shape->n);
SSOL(shape_ref_get(shape));
SSOL(material_ref_get(front));
SSOL(material_ref_get(back));
@@ -214,6 +216,7 @@ ssol_object_clear(struct ssol_object* obj)
obj->scn_rt_area = 0;
obj->scn_samp_area = 0;
+ d3_splat(obj->n, 0);
S3D(scene_clear(obj->scn_rt));
S3D(scene_clear(obj->scn_samp));
@@ -230,3 +233,13 @@ ssol_object_get_area(const struct ssol_object* object, double* area)
return RES_OK;
}
+res_T
+ssol_object_get_normal
+ (const struct ssol_object* object,
+ double normal[3])
+{
+ if (!object || !normal) return RES_BAD_ARG;;
+ /* the area of the 3D surface */
+ d3_set(normal, object->n);
+ return RES_OK;
+}
+\ No newline at end of file
diff --git a/src/ssol_object_c.h b/src/ssol_object_c.h
@@ -48,6 +48,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;
+ double n[3]; /* sum of normals */
struct ssol_device* dev;
ref_T ref;
diff --git a/src/ssol_shape.c b/src/ssol_shape.c
@@ -474,12 +474,14 @@ mesh_compute_area
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)
+ void* ctx,
+ double* normal)
{
unsigned itri;
double area = 0;
(void)nverts;
+ if(normal) d3_splat(normal, 0);
FOR_EACH(itri, 0, ntris) {
float v0[3], v1[3], v2[3];
double E0[3], E1[3], N[3];
@@ -501,7 +503,9 @@ mesh_compute_area
d3_sub(E1, V2, V0);
area += d3_len(d3_cross(N, E0, E1));
+ if(normal) d3_add(normal, normal, N);
}
+ if (normal) d3_muld(normal, normal, 0.5);
return area * 0.5;
}
@@ -559,7 +563,7 @@ quadric_setup_s3d_shape_rt
ASSERT(vdata.get);
*rt_area = mesh_compute_area
- (ntris, quadric_mesh_get_ids, nverts, vdata.get, &ctx);
+ (ntris, quadric_mesh_get_ids, nverts, vdata.get, &ctx, NULL);
return RES_OK;
}
@@ -597,7 +601,7 @@ quadric_setup_s3d_shape_samp
(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);
+ (ntris, quadric_mesh_get_ids, nverts, quadric_mesh_plane_get_pos, &ctx, NULL);
return RES_OK;
}
@@ -1144,6 +1148,7 @@ ssol_punched_surface_setup
struct darray_double coords;
struct darray_size_t ids;
size_t nslices;
+ double n;
res_T res = RES_OK;
darray_double_init(shape->dev->allocator, &coords);
@@ -1232,6 +1237,10 @@ ssol_punched_surface_setup
res = quadric_setup_s3d_shape_samp
(psurf->quadric, &coords, &ids, shape->shape_samp, &shape->shape_samp_area);
if(res != RES_OK) goto error;
+ /* the normal to the quadric is known */
+ n = psurf->quadric->type == SSOL_QUADRIC_HYPERBOL
+ ? -shape->shape_samp_area : shape->shape_samp_area;
+ d3(shape->n, 0, 0, n);
exit:
darray_double_release(&coords);
@@ -1298,7 +1307,7 @@ ssol_mesh_setup
(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);
+ mesh_compute_area(ntris, get_indices, nverts, get_position, data, shape->n);
/* 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);
diff --git a/src/ssol_shape_c.h b/src/ssol_shape_c.h
@@ -60,6 +60,7 @@ struct ssol_shape {
struct priv_quadric_data priv_quadric;
struct ssol_quadric quadric;
double shape_rt_area, shape_samp_area;
+ double n[3]; /* sum of normals */
struct ssol_device* dev;
ref_T ref;
diff --git a/src/test_ssol_object.c b/src/test_ssol_object.c
@@ -26,6 +26,7 @@ main(int argc, char** argv)
struct ssol_material* mtl;
struct ssol_material* mtl2;
struct ssol_object* object;
+ double a, n[3];
(void) argc, (void) argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -73,6 +74,14 @@ main(int argc, char** argv)
CHECK(ssol_object_clear(NULL), RES_BAD_ARG);
CHECK(ssol_object_clear(object), RES_OK);
+ CHECK(ssol_object_get_area(object, NULL), RES_BAD_ARG);
+ CHECK(ssol_object_get_area(NULL, &a), RES_BAD_ARG);
+ CHECK(ssol_object_get_area(object, &a), RES_OK);
+
+ CHECK(ssol_object_get_normal(object, NULL), RES_BAD_ARG);
+ CHECK(ssol_object_get_normal(NULL, n), RES_BAD_ARG);
+ CHECK(ssol_object_get_normal(object, n), RES_OK);
+
CHECK(ssol_object_ref_put(object), RES_OK);
CHECK(ssol_shape_ref_put(shape), RES_OK);
CHECK(ssol_shape_ref_put(shape2), RES_OK);