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:
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);