star-3d

Surface structuring for efficient 3D geometric queries
git clone git://git.meso-star.fr/star-3d.git
Log | Files | Refs | README | LICENSE

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:
Msrc/s3d.h | 5+++++
Msrc/s3d_instance.c | 32+++++++++++++++++++++++++++++---
Msrc/s3d_instance.h | 4++++
Msrc/s3d_mesh.c | 31+++++++++++++++++++++++++++++++
Msrc/s3d_mesh.h | 4++++
Msrc/s3d_shape.c | 17+++++++++++++++++
Msrc/test_s3d_shape.c | 11+++++++++++
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