commit 4bb93ba6016e7a58372347e0bd7686b6aeb858f6
parent 230c96562e070530c6d11f36f24a62463a770047
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 27 Jul 2015 16:04:08 +0200
Add and test the s3d_shape_compute_area function
This function returns the area of a shape. If the shape is an
instantiated scene, the returned value is the accumulated area of the
instantiated shapes.
Diffstat:
7 files changed, 101 insertions(+), 3 deletions(-)
diff --git a/src/s3d.h b/src/s3d.h
@@ -337,6 +337,11 @@ s3d_shape_primitives_count
(struct s3d_shape* shape,
size_t* primitives_count);
+S3D_API res_T
+s3d_shape_compute_area
+ (struct s3d_shape* shape,
+ float* area);
+
/*******************************************************************************
* Sampler API
******************************************************************************/
diff --git a/src/s3d_instance.c b/src/s3d_instance.c
@@ -108,17 +108,43 @@ instance_ref_put(struct instance* inst)
size_t
instance_get_ntris(struct instance* inst)
{
- size_t ntris = 0;
struct list_node* node;
+ size_t ntris = 0;
LIST_FOR_EACH(node, &inst->scene->shapes) {
struct s3d_shape* shape = CONTAINER_OF
(node, struct s3d_shape, scene_attachment);
switch(shape->type) {
- case SHAPE_INSTANCE: ntris += instance_get_ntris(shape->data.instance); break;
- case SHAPE_MESH: ntris += mesh_get_ntris(shape->data.mesh); break;
+ case SHAPE_INSTANCE:
+ ntris += instance_get_ntris(shape->data.instance);
+ break;
+ case SHAPE_MESH:
+ ntris += mesh_get_ntris(shape->data.mesh);
+ break;
default: FATAL("Unreachable code\n"); break;
}
}
return ntris;
}
+float
+instance_compute_area(struct instance* inst)
+{
+ struct list_node* node;
+ float area = 0.f;
+ ASSERT(inst);
+ LIST_FOR_EACH(node, &inst->scene->shapes) {
+ struct s3d_shape* shape = CONTAINER_OF
+ (node, struct s3d_shape, scene_attachment);
+ switch(shape->type) {
+ case SHAPE_INSTANCE:
+ area += instance_compute_area(shape->data.instance);
+ break;
+ case SHAPE_MESH:
+ area += mesh_compute_area(shape->data.mesh);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ }
+ return area;
+}
+
diff --git a/src/s3d_instance.h b/src/s3d_instance.h
@@ -66,5 +66,9 @@ extern LOCAL_SYM size_t
instance_get_ntris
(struct instance* inst);
+extern LOCAL_SYM float
+instance_compute_area
+ (struct instance* inst);
+
#endif /* S3D_INSTANCE_H */
diff --git a/src/s3d_mesh.c b/src/s3d_mesh.c
@@ -34,6 +34,8 @@
#include "s3d_device_c.h"
#include "s3d_mesh.h"
+#include <rsys/float3.h>
+
/*******************************************************************************
* Helper functions
******************************************************************************/
@@ -330,6 +332,35 @@ mesh_get_attr(struct mesh* mesh, const enum s3d_attrib_usage usage)
return darray_float_data_get(&mesh->attribs[usage]->data);
}
+float
+mesh_compute_area(struct mesh* mesh)
+{
+ const uint32_t* ids;
+ const float* pos;
+ size_t itri, ntris;
+ float area = 0.f;
+ ASSERT(mesh);
+
+ ntris = mesh_get_ntris(mesh);
+ if(!ntris)
+ return 0.f;
+
+ ids = mesh_get_ids(mesh);
+ pos = mesh_get_pos(mesh);
+
+ FOR_EACH(itri, 0, ntris) {
+ float E0[3], E1[3], N[3];
+ const size_t id = itri * 3/*#ids per faces*/;
+ const float* v0 = pos + ids[id+0]*3/*#coords*/;
+ const float* v1 = pos + ids[id+1]*3/*#coords*/;
+ const float* v2 = pos + ids[id+2]*3/*#coords*/;
+ f3_sub(E0, v1, v0);
+ f3_sub(E1, v2, v0);
+ area += f3_len(f3_cross(N, E0, E1)) * 0.5f;
+ }
+ return area;
+}
+
res_T
mesh_setup_indexed_vertices
(struct mesh* mesh,
diff --git a/src/s3d_mesh.h b/src/s3d_mesh.h
@@ -112,6 +112,10 @@ mesh_get_attr
(struct mesh* mesh,
const enum s3d_attrib_usage usage);
+extern LOCAL_SYM float
+mesh_compute_area
+ (struct mesh* mesh);
+
extern LOCAL_SYM res_T
mesh_setup_indexed_vertices
(struct mesh* mesh,
diff --git a/src/s3d_shape.c b/src/s3d_shape.c
@@ -242,6 +242,23 @@ s3d_shape_primitives_count(struct s3d_shape* shape, size_t* nprims)
}
res_T
+s3d_shape_compute_area(struct s3d_shape* shape, float* area)
+{
+ if(!shape || !area)
+ return RES_BAD_ARG;
+ switch(shape->type) {
+ case SHAPE_MESH:
+ *area = mesh_compute_area(shape->data.mesh);
+ break;
+ case SHAPE_INSTANCE:
+ *area = instance_compute_area(shape->data.instance);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ return RES_OK;
+}
+
+res_T
s3d_instance_set_position
(struct s3d_shape* shape, const float position[3])
{
diff --git a/src/test_s3d_shape.c b/src/test_s3d_shape.c
@@ -34,6 +34,8 @@
#include "test_s3d_cbox.h"
#include "test_s3d_utils.h"
+#include <rsys/math.h>
+
int
main(int argc, char** argv)
{
@@ -45,6 +47,7 @@ main(int argc, char** argv)
struct s3d_vertex_data attribs[4];
size_t nprims;
float pos[3];
+ float area;
const unsigned cbox_ntris = sizeof(cbox_walls_ids) / sizeof(unsigned[3]);
const unsigned cbox_nverts = sizeof(cbox_walls) / sizeof(float[3]);
unsigned id;
@@ -80,6 +83,12 @@ main(int argc, char** argv)
CHECK(s3d_shape_primitives_count(shape, &nprims), RES_OK);
CHECK(nprims, 0);
+ CHECK(s3d_shape_compute_area(NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_compute_area(shape, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_compute_area(NULL, &area), RES_BAD_ARG);
+ CHECK(s3d_shape_compute_area(shape, &area), RES_OK);
+ CHECK(area, 0.f);
+
CHECK(s3d_scene_attach_shape(NULL, NULL), RES_BAD_ARG);
CHECK(s3d_scene_attach_shape(scn, NULL), RES_BAD_ARG);
CHECK(s3d_scene_attach_shape(NULL, shape), RES_BAD_ARG);
@@ -165,6 +174,8 @@ main(int argc, char** argv)
CHECK(s3d_shape_primitives_count(shape, &nprims), RES_OK);
CHECK(nprims, 10);
+ CHECK(s3d_shape_compute_area(shape, &area), RES_OK);
+ CHECK(eq_epsf(area, 1532296.f, 1.e-6f), 1);
attribs[0] = S3D_VERTEX_DATA_NULL;
CHECK(s3d_mesh_setup_indexed_vertices