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 ddce4015b4e836932b8673fa105ed9c8a3024b15
parent 3eb4f6d701734828f0a77d9850da8dc9f1163990
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu,  6 Apr 2017 12:29:41 +0200

Add and test the s3d_triangle_get_vertex_attrib function

Diffstat:
Msrc/s3d.h | 7+++++++
Msrc/s3d_primitive.c | 93++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/test_s3d_primitive.c | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 156 insertions(+), 20 deletions(-)

diff --git a/src/s3d.h b/src/s3d.h @@ -444,6 +444,13 @@ s3d_primitive_get_transform (const struct s3d_primitive* prim, float transform[12]); /* 3x4 column major matrix */ +S3D_API res_T +s3d_triangle_get_vertex_attrib + (const struct s3d_primitive* prim, + const size_t ivertex, /* in [0..3[ */ + const enum s3d_attrib_usage usage, + struct s3d_attrib* attrib); + /******************************************************************************* * Mesh API - Manage a triangular meshes ******************************************************************************/ diff --git a/src/s3d_primitive.c b/src/s3d_primitive.c @@ -38,6 +38,19 @@ #include <rsys/float33.h> /******************************************************************************* + * Helper functions + ******************************************************************************/ +static int +check_primitive(const struct s3d_primitive* prim) +{ + return prim + && prim->geom_id != S3D_INVALID_ID + && prim->prim_id != S3D_INVALID_ID + && prim->mesh__ != NULL + && (prim->inst_id != S3D_INVALID_ID || prim->inst__ == NULL); +} + +/******************************************************************************* * Exported functions ******************************************************************************/ res_T @@ -54,15 +67,8 @@ s3d_primitive_get_attrib float w; res_T res = RES_OK; - if(!prim || usage == S3D_ATTRIBS_COUNT__ || !uv || !attrib) - return RES_BAD_ARG; - - if(prim->geom_id == S3D_INVALID_ID - || prim->prim_id == S3D_INVALID_ID - || prim->mesh__ == NULL - || (prim->inst_id != S3D_INVALID_ID && prim->inst__ == NULL)) { + if(!check_primitive(prim) || usage == S3D_ATTRIBS_COUNT__ || !uv || !attrib) return RES_BAD_ARG; - } /* Unormalized barycentric coordinates */ w = CLAMP(1.f - uv[0] - uv[1], 0.f, 1.f); @@ -163,8 +169,7 @@ s3d_primitive_has_attrib const enum s3d_attrib_usage attr, char* has_attrib) { - if(!prim - || !has_attrib + if(!check_primitive(prim) || !has_attrib || (attr != S3D_GEOMETRY_NORMAL && (unsigned)attr >= S3D_ATTRIBS_COUNT__)) return RES_BAD_ARG; @@ -187,7 +192,7 @@ s3d_primitive_sample { double sqrt_u; - if(!prim || S3D_PRIMITIVE_EQ(prim, &S3D_PRIMITIVE_NULL) || !st) + if(!check_primitive(prim) || !st) return RES_BAD_ARG; /* Expecting canonic numbers */ @@ -211,7 +216,7 @@ s3d_primitive_compute_area(const struct s3d_primitive* prim, float* area) float E0[3], E1[3], N[3]; struct geometry* geom; - if(!prim || !area || S3D_PRIMITIVE_EQ(prim, &S3D_PRIMITIVE_NULL)) + if(!check_primitive(prim) || !area) return RES_BAD_ARG; geom = (struct geometry*)prim->mesh__; @@ -230,7 +235,7 @@ res_T s3d_primitive_get_transform (const struct s3d_primitive* prim, float transform[12]) { - if(!prim || !transform) + if(!check_primitive(prim) || !transform) return RES_BAD_ARG; if(!prim->inst__) { @@ -249,3 +254,65 @@ s3d_primitive_get_transform return RES_OK; } +res_T +s3d_triangle_get_vertex_attrib + (const struct s3d_primitive* prim, + const size_t ivertex, + const enum s3d_attrib_usage usage, + struct s3d_attrib* attrib) +{ + struct geometry* geom_mesh = NULL; + const float* transform = NULL; + const uint32_t* ids; + + if(!check_primitive(prim) || ivertex > 2 + || (unsigned)usage >= S3D_ATTRIBS_COUNT__ + || !attrib) { + return RES_BAD_ARG; + } + + geom_mesh = (struct geometry*)prim->mesh__; + ASSERT(prim->geom_id == geom_mesh->name); + ASSERT(geom_mesh->type == GEOM_MESH); + + if(prim->inst__ != NULL) { + const struct geometry* geom_inst = (const struct geometry*)prim->inst__; + ASSERT(geom_inst->type == GEOM_INSTANCE); + ASSERT(prim->inst_id == geom_inst->name); + transform = geom_inst->data.instance->transform; + } + + /* The mesh haven't the required mesh attrib */ + if(!geom_mesh->data.mesh->attribs[usage]) { + return RES_BAD_ARG; + } + + /* Out of bound primitive index */ + if(prim->prim_id >= mesh_get_ntris(geom_mesh->data.mesh)) { + return RES_BAD_ARG; + } + ids = mesh_get_ids(geom_mesh->data.mesh) + prim->prim_id * 3/*#triangle ids*/; + attrib->usage = usage; + + if(usage != S3D_POSITION) { + const float* attr; + unsigned i, dim; + attrib->type = geom_mesh->data.mesh->attribs_type[usage]; + /* Fetch attrib data */ + dim = s3d_type_get_dimension(attrib->type); + attr = mesh_get_attr(geom_mesh->data.mesh, usage) + ids[ivertex] * dim; + FOR_EACH(i, 0, dim) attrib->value[i] = attr[i]; + } else { + const float* pos; + attrib->type = S3D_FLOAT3; + /* Fetch data */ + pos = mesh_get_pos(geom_mesh->data.mesh) + ids[ivertex] * 3; + f3_set(attrib->value, pos); + if(transform) { /* Transform the position from local to world space */ + f33_mulf3(attrib->value, transform, attrib->value); /* Rotation */ + f3_add(attrib->value, attrib->value, transform + 9); /* Translation */ + } + } + return RES_OK; +} + diff --git a/src/test_s3d_primitive.c b/src/test_s3d_primitive.c @@ -34,6 +34,7 @@ #include "test_s3d_cbox.h" #include "test_s3d_utils.h" +#include <rsys/float2.h> #include <rsys/float3.h> #include <rsys/math.h> @@ -80,6 +81,17 @@ plane_get_pos(const unsigned ivert, float pos[3], void* data) pos[2] = plane_verts[i + 2]; } +static void +plane_get_uv(const unsigned ivert, float uv[2], void* data) +{ + const unsigned i = ivert*3; + (void)data; + NCHECK(uv, NULL); + CHECK(ivert < plane_nverts, 1); + uv[0] = -plane_verts[i + 0]; + uv[1] = -plane_verts[i + 1]; +} + int main(int argc, char** argv) { @@ -91,7 +103,7 @@ main(int argc, char** argv) struct s3d_shape* plane; struct s3d_attrib attr; struct s3d_primitive prim = S3D_PRIMITIVE_NULL; - struct s3d_vertex_data attribs; + struct s3d_vertex_data attribs[2]; struct cbox_desc desc; size_t nprims; size_t i; @@ -113,20 +125,24 @@ main(int argc, char** argv) CHECK(s3d_shape_get_id(walls, &walls_id), RES_OK); CHECK(s3d_scene_attach_shape(scn, walls), RES_OK); - attribs.usage = S3D_POSITION; - attribs.type = S3D_FLOAT3; - attribs.get = cbox_get_position; + attribs[1].usage = S3D_ATTRIB_0; + attribs[1].type = S3D_FLOAT2; + attribs[1].get = plane_get_uv; + + attribs[0].usage = S3D_POSITION; + attribs[0].type = S3D_FLOAT3; + attribs[0].get = cbox_get_position; ntris = cbox_walls_ntris; nverts = cbox_walls_nverts; desc.vertices = cbox_walls; desc.indices = cbox_walls_ids; CHECK(s3d_mesh_setup_indexed_vertices - (walls, ntris, cbox_get_ids, nverts, &attribs, 1, &desc), RES_OK); + (walls, ntris, cbox_get_ids, nverts, attribs, 1, &desc), RES_OK); - attribs.get = plane_get_pos; + attribs[0].get = plane_get_pos; CHECK(s3d_mesh_setup_indexed_vertices - (plane, plane_ntris, plane_get_ids, plane_nverts, &attribs, 1, NULL), RES_OK); + (plane, plane_ntris, plane_get_ids, plane_nverts, attribs, 2, NULL), RES_OK); CHECK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview), RES_OK); CHECK(s3d_scene_view_sample(scnview, 0, 0, 0, &prim, uv), RES_OK); @@ -190,6 +206,11 @@ main(int argc, char** argv) CHECK(S3D_PRIMITIVE_EQ(&prim, &S3D_PRIMITIVE_NULL), 0); CHECK(s3d_scene_view_ref_put(scnview), RES_OK); + CHECK(s3d_primitive_has_attrib(&prim, S3D_ATTRIB_0, &b), RES_OK); + CHECK(b, 1); + CHECK(s3d_primitive_has_attrib(&prim, S3D_ATTRIB_1, &b), RES_OK); + CHECK(b, 0); + CHECK(s3d_primitive_compute_area(NULL, NULL), RES_BAD_ARG); CHECK(s3d_primitive_compute_area(&prim, NULL), RES_BAD_ARG); CHECK(s3d_primitive_compute_area(NULL, &area), RES_BAD_ARG); @@ -222,6 +243,47 @@ main(int argc, char** argv) CHECK(uv[1] <= 1.f, 1); } + #define GET_VERTEX_ATTR s3d_triangle_get_vertex_attrib + CHECK(GET_VERTEX_ATTR(NULL, 3, S3D_GEOMETRY_NORMAL, NULL), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(&prim, 3, S3D_GEOMETRY_NORMAL, NULL), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(NULL, 0, S3D_GEOMETRY_NORMAL, NULL), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(&prim, 0, S3D_GEOMETRY_NORMAL, NULL), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(NULL, 3, S3D_POSITION, NULL), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(&prim, 3, S3D_POSITION, NULL), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(NULL, 0, S3D_POSITION, NULL), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(&prim, 0, S3D_POSITION, NULL), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(NULL, 3, S3D_GEOMETRY_NORMAL, &attr), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(&prim, 3, S3D_GEOMETRY_NORMAL, &attr), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(NULL, 0, S3D_GEOMETRY_NORMAL, &attr), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(&prim, 0, S3D_GEOMETRY_NORMAL, &attr), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(NULL, 3, S3D_POSITION, &attr), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(&prim, 3, S3D_POSITION, &attr), RES_BAD_ARG); + CHECK(GET_VERTEX_ATTR(NULL, 0, S3D_POSITION, &attr), RES_BAD_ARG); + + CHECK(GET_VERTEX_ATTR(&prim, 0, S3D_POSITION, &attr), RES_OK); + CHECK(attr.type, S3D_FLOAT3); + CHECK(f3_eq_eps(attr.value, plane_verts + plane_ids[0]*3, 1.e-6f), 1); + CHECK(GET_VERTEX_ATTR(&prim, 1, S3D_POSITION, &attr), RES_OK); + CHECK(attr.type, S3D_FLOAT3); + CHECK(f3_eq_eps(attr.value, plane_verts + plane_ids[1]*3, 1.e-6f), 1); + CHECK(GET_VERTEX_ATTR(&prim, 2, S3D_POSITION, &attr), RES_OK); + CHECK(attr.type, S3D_FLOAT3); + CHECK(f3_eq_eps(attr.value, plane_verts + plane_ids[2]*3, 1.e-6f), 1); + + CHECK(GET_VERTEX_ATTR(&prim, 0, S3D_ATTRIB_0, &attr), RES_OK); + CHECK(attr.type, S3D_FLOAT2); + f2_minus(uv, plane_verts + plane_ids[0]*3); + CHECK(f2_eq_eps(attr.value, uv, 1.e-6f), 1); + CHECK(GET_VERTEX_ATTR(&prim, 1, S3D_ATTRIB_0, &attr), RES_OK); + CHECK(attr.type, S3D_FLOAT2); + f2_minus(uv, plane_verts + plane_ids[1]*3); + CHECK(f2_eq_eps(attr.value, uv, 1.e-6f), 1); + CHECK(GET_VERTEX_ATTR(&prim, 2, S3D_ATTRIB_0, &attr), RES_OK); + CHECK(attr.type, S3D_FLOAT2); + f2_minus(uv, plane_verts + plane_ids[2]*3); + CHECK(f2_eq_eps(attr.value, uv, 1.e-6f), 1); + #undef GET_VERTEX_ATTR + CHECK(s3d_device_ref_put(dev), RES_OK); CHECK(s3d_scene_ref_put(scn), RES_OK); CHECK(s3d_shape_ref_put(walls), RES_OK);