commit 4fae190e507ceea73f6b0ce7b413dd0846f8d1ee
parent 789f7e128efcac1a7182cb99d60e413c346a4a46
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 16 Mar 2015 16:48:36 +0100
Refactoring of the description of a Mesh
Diffstat:
7 files changed, 366 insertions(+), 264 deletions(-)
diff --git a/src/s3d.h b/src/s3d.h
@@ -54,50 +54,43 @@
#define S3D(Func) s3d_ ## Func
#endif
+#define S3D_KEEP NULL
+
/* Attributes of a shape */
-enum s3d_shape_attrib {
- S3D_SHAPE_POSITION, /* World space position */
- S3D_SHAPE_SHADING_NORMAL, /* World space interpolated vertex normal */
- S3D_SHAPE_GEOMETTRY_NORMAL, /* World space face normal */
- S3D_SHAPE_UV /* Parametric coordinates */
+enum s3d_attrib_usage {
+ S3D_POSITION, /* World space position */
+ S3D_ATTRIB_0, /* Generic attrib 0 */
+ S3D_ATTRIB_1, /* Generic attrib 1 */
+ S3D_ATTRIB_2, /* Generic attrib 2 */
+ S3D_ATTRIB_3, /* Generic attrib 3 */
+ S3D_ATTRIBS_COUNT__,
+ S3D_GEOMETRY_NORMAL /* World space face normal */
};
enum s3d_type {
S3D_FLOAT,
S3D_FLOAT2,
- S3D_FLOAT3
+ S3D_FLOAT3,
+ S3D_FLOAT4
};
struct s3d_attrib {
float value[4];
enum s3d_type type;
+ enum s3d_attrib_usage usage;
};
-/* Descriptor of a triangular mesh */
-struct s3d_trimesh_desc {
- /* # triangles. May be NULL if get_indices is NULL */
- unsigned (*get_tricount)(void*);
- /* Get the 3 vertex indices of the triangle `itri'. May be NULL if the shape
- * was already setuped as a triangular mesh <=> does not update the shape
- * indices */
- void (*get_indices)(const unsigned itri, unsigned ids[3], void*);
- /* Get the 3D position of the vertex `ivert'. May be NULL if the shape was
- * already setuped as a triangular mesh <=> does not update the shape
- * coordinates */
- void (*get_position)(const unsigned ivert, float position[3], void*);
- /* Get the world space normal of `ivert'. May be NULL <=> does not setup
- * normals data to the shape or does not update them */
- void (*get_normal)(const unsigned ivert, float normal[3], void*);
- /* Get the parametric coordinates of `ivert'. May be NULL <=> does not setup
- * uvs data to the shape or does not update them */
- void (*get_uv)(const unsigned ivert, float uv[2], void*);
- /* Pointer to user data; last argument of the previous callbacks */
- void* data;
+struct s3d_vertex_data {
+ enum s3d_attrib_usage usage;
+ enum s3d_type type;
+ void (*get)
+ (const unsigned ivert, /* Index of the vertex */
+ float* value, /* Retrieved attrib value */
+ void* ctx); /* Pointer to user data */
};
-static const struct s3d_trimesh_desc S3D_TRIMESH_DESC_NULL = {
- NULL, NULL, NULL, NULL, NULL, NULL
-};
+static const struct s3d_vertex_data S3D_VERTEX_DATA_NULL =
+{ S3D_ATTRIBS_COUNT__, S3D_FLOAT, NULL };
/* Intersection point */
struct s3d_hit {
@@ -201,11 +194,16 @@ s3d_scene_trace_ray
* Shape API - A shape defines a geometry that can be attached to *one* scene.
******************************************************************************/
S3D_API res_T
-s3d_shape_create
+s3d_shape_create_mesh
(struct s3d_device* dev,
struct s3d_shape** shape);
S3D_API res_T
+s3d_shape_create_group
+ (struct s3d_device* dev,
+ struct s3d_shape **shape);
+
+S3D_API res_T
s3d_shape_ref_get
(struct s3d_shape* shape);
@@ -220,21 +218,6 @@ s3d_shape_enable
(struct s3d_shape* shape,
const char enable);
-/* Setup the shape from a triangular mesh descriptor. The data retrieved
- * through the mesh descriptor must be valid until the end of the function
- * call */
-S3D_API res_T
-s3d_shape_setup_trimesh
- (struct s3d_shape* shape,
- const struct s3d_trimesh_desc* desc);
-
-/* Setup the shape from a scene. Actually the resulting shape is an instance of
- * the scene */
-S3D_API res_T
-s3d_shape_setup_scene
- (struct s3d_shape* shape,
- struct s3d_scene* scene);
-
/* Remove the shape from the scene on which it is attached. No error is
* reported if the shape is not attached to a scene. After its detachment, the
* scene release its reference on the shape */
@@ -252,7 +235,7 @@ s3d_shape_set_transform
S3D_API res_T
s3d_shape_get_attrib
(struct s3d_shape* shape,
- const enum s3d_shape_attrib attr, /* Attribute to retrieve */
+ const enum s3d_attrib_usage attr, /* Attribute to retrieve */
const unsigned iprim, /* Id of the primitive on which `attr' is retrieved */
const float uv[2], /* Barycentric coordinates of `attr' on `iprim' */
struct s3d_attrib* attrib); /* Resulting attrib */
@@ -266,6 +249,22 @@ s3d_shape_sample
unsigned* iprim, /* Sampled primitive */
float uv[2]); /* Sampled barycentric coordinate onto `iprim' */
+S3D_API res_T
+s3d_shape_mesh_setup_indexed_vertices
+ (struct s3d_shape* shape,
+ const unsigned ntris,
+ void (*get_indices)(const unsigned itri, unsigned ids[3], void* ctx),
+ const unsigned nverts,
+ struct s3d_vertex_data attribs[],
+ void* data);
+
+/* Setup the shape from a scene. Actually the resulting shape is an instance of
+ * the scene */
+S3D_API res_T
+s3d_shape_group_setup_scene
+ (struct s3d_shape* shape,
+ struct s3d_scene* scene);
+
END_DECLS
#endif /* S3D_H */
diff --git a/src/s3d_scene.c b/src/s3d_scene.c
@@ -56,9 +56,10 @@ scene_setup(struct s3d_scene* scn)
struct s3d_shape* shape = CONTAINER_OF
(node, struct s3d_shape, scene_attachment);
uint32_t* ids = darray_u32_data_get(&shape->data.mesh.indices);
- float* pos = darray_float_data_get(&shape->data.mesh.positions);
+ float* pos = darray_float_data_get(&shape->data.mesh.attribs[S3D_POSITION]);
const size_t ntris = darray_u32_size_get(&shape->data.mesh.indices)/3;
- const size_t nverts = darray_float_size_get(&shape->data.mesh.positions)/3;
+ const size_t nverts = darray_float_size_get
+ (&shape->data.mesh.attribs[S3D_POSITION])/3;
ASSERT(IS_ALIGNED(ids, 16));
/* The Embree geometry is no more valid */
diff --git a/src/s3d_shape.c b/src/s3d_shape.c
@@ -39,6 +39,19 @@
/*******************************************************************************
* Helper functions
******************************************************************************/
+static INLINE size_t
+get_s3d_type_dimension(const enum s3d_type type)
+{
+ switch(type) {
+ case S3D_FLOAT: return 1;
+ case S3D_FLOAT2: return 2;
+ case S3D_FLOAT3: return 3;
+ case S3D_FLOAT4: return 4;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ return 0;
+}
+
static FINLINE void
shape_delete_rtc_geometry(struct s3d_shape* shape)
{
@@ -50,102 +63,97 @@ shape_delete_rtc_geometry(struct s3d_shape* shape)
static void
mesh_init(struct mem_allocator* allocator, struct mesh* mesh)
{
+ int iattr;
ASSERT(mesh);
darray_u32_init(allocator, &mesh->indices);
- darray_float_init(allocator, &mesh->positions);
- darray_float_init(allocator, &mesh->normals);
- darray_float_init(allocator, &mesh->uvs);
+ FOR_EACH(iattr, 0, S3D_ATTRIBS_COUNT__) {
+ darray_float_init(allocator, &mesh->attribs[iattr]);
+ mesh->attribs_type[iattr] = S3D_FLOAT;
+ }
+ /* The vertex positions are always float3 */
+ mesh->attribs_type[S3D_POSITION] = S3D_FLOAT3;
+
mesh->update_mask = mesh->resize_mask = 0;
}
static void
mesh_release(struct mesh* mesh)
{
+ int iattr;
ASSERT(mesh);
darray_u32_release(&mesh->indices);
- darray_float_release(&mesh->positions);
- darray_float_release(&mesh->normals);
- darray_float_release(&mesh->uvs);
+ FOR_EACH(iattr, 0, S3D_ATTRIBS_COUNT__) {
+ darray_float_release(&mesh->attribs[iattr]);
+ }
}
-static res_T
+static void
mesh_setup_indices
(struct mesh* mesh,
- const struct s3d_trimesh_desc* desc,
- unsigned* nvertices)
+ const unsigned ntris,
+ void (*get_indices)(const unsigned itri, unsigned ids[3], void*),
+ const unsigned nverts,
+ void* data)
{
uint32_t* indices;
- unsigned itri, ntris, nids, nids_prev, nverts;
+ unsigned itri;
+ unsigned nids, nids_prev;
+ unsigned nverts_new;
res_T res;
- ASSERT(mesh && desc && nvertices);
+ ASSERT(mesh && ntris && get_indices && nverts);
+ nids = ntris * 3;
nids_prev = darray_u32_size_get(&mesh->indices);
- if(!desc->get_indices) {
- if(!nids_prev) { /* The indices were not previously setuped */
- return RES_BAD_ARG;
- } else { /* Keep the previously setuped indices */
- nverts = darray_float_size_get(&mesh->positions);
- ASSERT(nverts % 3 == 0);
- *nvertices = nverts / 3;
- return RES_OK;
- }
- }
+ ASSERT(get_indices != S3D_KEEP || nids == nids_prev);
- if(!desc->get_tricount)
- return RES_BAD_ARG;
-
- ntris = desc->get_tricount(desc->data);
- if(!ntris)
- return RES_BAD_ARG;
+ if(get_indices == S3D_KEEP) {
+ ASSERT(nids == nids_prev);
+ return;
+ }
- nids = ntris * 3;
if(nids == nids_prev) {
mesh->update_mask |= (MESH_INDEX_BUFFER & !mesh->resize_mask);
} else {
mesh->resize_mask |= MESH_INDEX_BUFFER;
mesh->update_mask &= !MESH_INDEX_BUFFER;
res = darray_u32_resize(&mesh->indices, nids);
- if(res != RES_OK) return res;
+ if(res != RES_OK) FATAL("Unsufficient memory\n");
}
/* Setup the mesh indices */
indices = darray_u32_data_get(&mesh->indices);
- nverts = 0;
+ nverts_new = 0;
FOR_EACH(itri, 0, ntris) {
uint32_t* ids = indices + itri*3;
int i;
STATIC_ASSERT(sizeof(unsigned) == sizeof(uint32_t), Unexpected_Type);
- desc->get_indices(itri, ids, desc->data);
- FOR_EACH(i, 0, 3) if(ids[i] >= nverts) nverts = ids[i];
+ get_indices(itri, ids, data);
+ FOR_EACH(i, 0, 3) nverts_new = MMAX(nverts_new, ids[i]);
}
- /* Transform nverts from last vertex id to vertices count */
- *nvertices = nverts + 1;
- return RES_OK;
+ /* Transform nverts from the last vertex id to vertices count */
+ ++nverts_new;
+ if(nverts_new > nverts)
+ FATAL("Out of bound indexation\n");
}
-static res_T
+static void
mesh_setup_positions
(struct mesh* mesh,
- const struct s3d_trimesh_desc* desc,
- const unsigned nverts)
+ const unsigned nverts,
+ struct s3d_vertex_data* attr,
+ void* data)
{
float* positions;
- unsigned i, nverts_prev;
+ unsigned ivert, nverts_prev;
res_T res;
- ASSERT(mesh && desc && nverts);
+ ASSERT(mesh && nverts && attr && attr->usage == S3D_POSITION);
- nverts_prev = darray_float_size_get(&mesh->positions);
+ nverts_prev = darray_float_size_get(&mesh->attribs[S3D_POSITION]);
ASSERT(nverts_prev % 3 == 0);
nverts_prev /= 3;
-
- if(!desc->get_position) {
- if(!nverts_prev) { /* The vertex positions were not already setuped */
- return RES_BAD_ARG;
- } else if(nverts != nverts_prev) { /* Inconsistant descriptor */
- return RES_BAD_ARG;
- } else { /* Keep the previous positions */
- return RES_OK;
- }
+ if(attr->get == S3D_KEEP) {
+ ASSERT(nverts == nverts_prev);
+ return;
}
/* Allocate vertex positions */
@@ -154,122 +162,79 @@ mesh_setup_positions
} else {
mesh->resize_mask |= MESH_VERTEX_BUFFER;
mesh->update_mask &= !MESH_VERTEX_BUFFER; /* The vertices are no more updated */
- res = darray_float_resize(&mesh->positions, nverts*3);
- if(res != RES_OK) return res;
+ res = darray_float_resize(&mesh->attribs[S3D_POSITION], nverts*3);
+ if(res != RES_OK) FATAL("Unsufficient memory\n");
}
/* Setup the vertex positions */
- positions = darray_float_data_get(&mesh->positions);
- memset(positions, 0xFF, sizeof(float[3])*nverts);
- FOR_EACH(i, 0, darray_u32_size_get(&mesh->indices)) {
- union { float f; uint32_t i; } ucast;
- const unsigned ivert = darray_u32_cdata_get(&mesh->indices)[i];
- const unsigned ipos = ivert * 3;
-
- ucast.f = positions[ipos];
- if(ucast.i == 0xFFFFFFFF) /* The vertex was not setuped */
- desc->get_position(ivert, positions + ipos, desc->data);
- }
- return RES_OK;
-}
-
-static res_T
-mesh_setup_normals
- (struct mesh* mesh,
- const struct s3d_trimesh_desc* desc,
- const unsigned nverts)
-{
- float* normals;
- unsigned i, nverts_prev;
- res_T res;
- ASSERT(mesh && desc && nverts);
-
- nverts_prev = darray_float_size_get(&mesh->normals);
- ASSERT(nverts_prev % 3 == 0);
- nverts_prev /= 3;
-
- if(!desc->get_normal) {
- if(nverts_prev && nverts != nverts_prev) { /* Inconsistant descriptor */
- return RES_BAD_ARG;
- } else { /* Keep the previous normals or do not setup them */
- return RES_OK;
+ positions = darray_float_data_get(&mesh->attribs[S3D_POSITION]);
+ if(attr->type == S3D_FLOAT3) {
+ FOR_EACH(ivert, 0, nverts) {
+ attr->get(ivert, positions + ivert*3, data);
+ }
+ } else {
+ FOR_EACH(ivert, 0, nverts) {
+ float pos[4];
+ unsigned ipos = ivert * 3;
+ attr->get(ivert, pos, data);
+ switch(attr->type) {
+ case S3D_FLOAT:
+ positions[ipos + 0] = pos[0];
+ positions[ipos + 1] = 0.f;
+ positions[ipos + 2] = 0.f;
+ break;
+ case S3D_FLOAT2:
+ positions[ipos + 0] = pos[0];
+ positions[ipos + 1] = pos[1];
+ positions[ipos + 2] = 0.f;
+ break;
+ case S3D_FLOAT4: /* Homogeneous coordinates */
+ positions[ipos + 0] = pos[0] / pos[3];
+ positions[ipos + 1] = pos[1] / pos[3];
+ positions[ipos + 2] = pos[2] / pos[3];
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
}
}
-
- res = darray_float_resize(&mesh->normals, nverts*3);
- if(res != RES_OK) return res;
-
- /* Setup the vertex normals */
- normals = darray_float_data_get(&mesh->normals);
- memset(normals, 0xFF, sizeof(float[3])*nverts);
- FOR_EACH(i, 0, darray_u32_size_get(&mesh->indices)) {
- union { float f; uint32_t i; } ucast;
- const unsigned ivert = darray_u32_cdata_get(&mesh->indices)[i];
- const unsigned inormal = ivert * 3;
-
- ucast.f = normals[inormal];
- if(ucast.i == 0xFFFFFFFF) /* The normal was not setuped */
- desc->get_normal(ivert, normals + inormal, desc->data);
- }
- return RES_OK;
}
-static res_T
-mesh_setup_uvs
+static void
+mesh_setup_attribs
(struct mesh* mesh,
- const struct s3d_trimesh_desc* desc,
- const unsigned nverts)
+ const unsigned nverts,
+ const struct s3d_vertex_data* attr,
+ void* data)
{
- float* uvs;
- unsigned i, nverts_prev;
+ float* attr_data;
+ size_t attr_dimension;
+ unsigned ivert, nverts_prev;
res_T res;
- ASSERT(mesh && desc && nverts);
-
- nverts_prev = darray_float_size_get(&mesh->uvs);
- ASSERT(nverts_prev % 2 == 0);
- nverts_prev /= 2;
-
- if(!desc->get_uv) {
- if(nverts_prev && nverts != nverts_prev) { /* Inconsistant descriptor */
- return RES_BAD_ARG;
- } else { /* Keep the previous normals or do not setup them */
- return RES_OK;
- }
+ ASSERT(mesh && nverts && attr);
+ ASSERT(attr->usage >= S3D_ATTRIB_0 && attr->usage < S3D_ATTRIBS_COUNT__);
+
+ nverts_prev = darray_float_size_get(&mesh->attribs[attr->usage]);
+ attr_dimension = get_s3d_type_dimension(mesh->attribs_type[attr->usage]);
+ ASSERT(nverts_prev % attr_dimension == 0);
+ nverts_prev /= attr_dimension;
+
+ if(attr->get == S3D_KEEP) {
+ ASSERT(mesh->attribs_type[attr->usage] == attr->type);
+ ASSERT(nverts == nverts_prev);
+ return;
}
- res = darray_float_resize(&mesh->uvs, nverts*2);
- if(res != RES_OK) return res;
+ attr_dimension = get_s3d_type_dimension(attr->type);
+ res = darray_float_resize(&mesh->attribs[attr->usage], nverts*attr_dimension);
+ if(res != RES_OK) FATAL("Unsufficient memory\n");
- /* Setup the vertex normals */
- uvs = darray_float_data_get(&mesh->uvs);
- memset(uvs, 0xFF, sizeof(float[2])*nverts);
- FOR_EACH(i, 0, darray_u32_size_get(&mesh->indices)) {
- union { float f; uint32_t i; } ucast;
- const unsigned ivert = darray_u32_cdata_get(&mesh->indices)[i];
- const unsigned iuv = ivert * 3;
-
- ucast.f = uvs[iuv];
- if(ucast.i == 0xFFFFFFFF) /* The normal was not setuped */
- desc->get_uv(ivert, uvs + iuv, desc->data);
+ /* Setup the vertex attrib */
+ attr_data = darray_float_data_get(&mesh->attribs[attr->usage]);
+ FOR_EACH(ivert, 0, nverts) {
+ attr->get(ivert, attr_data, data);
+ attr_data += attr_dimension;
}
- return RES_OK;
-}
-
-static res_T
-mesh_setup(struct mesh* mesh, const struct s3d_trimesh_desc* desc)
-{
- unsigned nverts;
- res_T res = RES_OK;
-
- res = mesh_setup_indices(mesh, desc, &nverts);
- if(res != RES_OK) return res;
- res = mesh_setup_positions(mesh, desc, nverts);
- if(res != RES_OK) return res;
- res = mesh_setup_normals(mesh, desc, nverts);
- if(res != RES_OK) return res;
- res = mesh_setup_uvs(mesh, desc, nverts);
- if(res != RES_OK) return res;
- return RES_OK;
+ mesh->attribs_type[attr->usage] = attr->type;
}
static void
@@ -278,7 +243,7 @@ shape_release_data(struct s3d_shape* shape)
ASSERT(shape);
switch(shape->type) {
case SHAPE_MESH: mesh_release(&shape->data.mesh); break;
- case SHAPE_NONE: /* DO nothing */ break;
+ case SHAPE_NONE: /* Do nothing */ break;
default: FATAL("Unreachable code\n"); break;
}
shape->type = SHAPE_NONE;
@@ -306,7 +271,8 @@ shape_release(ref_T* ref)
* Exported s3d_shape functions:
******************************************************************************/
res_T
-s3d_shape_create(struct s3d_device* dev, struct s3d_shape** out_shape)
+s3d_shape_create_mesh
+ (struct s3d_device* dev, struct s3d_shape** out_shape)
{
struct s3d_shape* shape = NULL;
res_T res = RES_OK;
@@ -322,7 +288,8 @@ s3d_shape_create(struct s3d_device* dev, struct s3d_shape** out_shape)
goto error;
}
list_init(&shape->scene_attachment);
- shape->type = SHAPE_NONE;
+ mesh_init(dev->allocator, &shape->data.mesh);
+ shape->type = SHAPE_MESH;
shape->rtc_geom = INVALID_RTC_GEOMETRY;
S3D(device_ref_get(dev));
shape->dev = dev;
@@ -371,30 +338,78 @@ s3d_shape_detach(struct s3d_shape* shape)
}
res_T
-s3d_shape_setup_trimesh
+s3d_shape_mesh_setup_indexed_vertices
(struct s3d_shape* shape,
- const struct s3d_trimesh_desc* desc)
+ const unsigned ntris,
+ void (*get_indices)(const unsigned itri, unsigned ids[3], void* ctx),
+ const unsigned nverts,
+ struct s3d_vertex_data attribs[],
+ void* data)
{
+ uint32_t* indices;
+ unsigned itri;
+ unsigned nids, nids_prev;
+ unsigned iattr;
+ unsigned nverts_check, nverts_prev;
+ char has_position = 0;
res_T res = RES_OK;
- if(!shape || !desc) {
+ if(!shape || shape->type != SHAPE_MESH || !ntris || !nverts || !attribs) {
res = RES_BAD_ARG;
goto error;
}
- if(shape->type != SHAPE_MESH) {
- shape_release_data(shape);
- mesh_init(shape->dev->allocator, &shape->data.mesh);
- shape->type = SHAPE_MESH;
+ /* Check indices description */
+ if(get_indices == S3D_KEEP) {
+ const unsigned nids_prev = darray_u32_size_get(&shape->data.mesh.indices);
+ const unsigned ntris_prev = nids_prev / 3;
+ if(ntris_prev != ntris) { /* Inconsistant data */
+ res = RES_BAD_ARG;
+ goto error;
+ }
}
- res = mesh_setup(&shape->data.mesh, desc);
- if(res != RES_OK) goto error;
+ /* Check the vertex data description */
+ iattr = 0;
+ has_position = 0;
+ do {
+ if(attribs[iattr].get == S3D_KEEP) {
+ const enum s3d_attrib_usage attr_usage = attribs[iattr].usage;
+ const enum s3d_type type = attribs[iattr].type;
+ const enum s3d_type type_prev = shape->data.mesh.attribs_type[attr_usage];
+ const struct darray_float* attr = shape->data.mesh.attribs + attr_usage;
+ size_t nverts_prev = darray_float_size_get(attr);
+ nverts_prev /= get_s3d_type_dimension(type_prev);
+ if(type_prev != type || nverts_prev != nverts) { /* Inconsistant data */
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ }
+ if(attribs[iattr].usage == S3D_POSITION)
+ has_position = 1;
+ ++iattr;
+ } while(attribs[iattr].usage != S3D_ATTRIBS_COUNT__);
+
+ if(!has_position) { /* The vertex must have a position */
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Setup indices */
+ if(get_indices != S3D_KEEP) {
+ mesh_setup_indices(&shape->data.mesh, ntris, get_indices, nverts, data);
+ }
+ /* Setup vertex data */
+ for(iattr = 0; attribs[iattr].usage != S3D_ATTRIBS_COUNT__; ++iattr) {
+ if(attribs[iattr].usage == S3D_POSITION) {
+ mesh_setup_positions(&shape->data.mesh, nverts, attribs + iattr, data);
+ } else {
+ mesh_setup_attribs(&shape->data.mesh, nverts, attribs + iattr, data);
+ }
+ }
exit:
return res;
error:
- if(shape && desc)
- shape_release_data(shape);
goto exit;
}
diff --git a/src/s3d_shape_c.h b/src/s3d_shape_c.h
@@ -56,9 +56,8 @@ enum shape_type {
struct mesh { /* Triangular mesh */
darray_u32 indices;
- darray_float positions; /* list of 3 floats */
- darray_float normals; /* list of 3 floats */
- darray_float uvs; /* list of 2 floats */
+ darray_float attribs[S3D_ATTRIBS_COUNT__];
+ enum s3d_type attribs_type[S3D_ATTRIBS_COUNT__];
/* Combination of shape_buffer */
int update_mask; /* Define which shape buffers were updated */
diff --git a/src/test_s3d_cbox.h b/src/test_s3d_cbox.h
@@ -65,7 +65,7 @@ static const float cbox_verts[] = {
314.0f, 456.0f, 330.f,
472.0f, 406.0f, 330.f
};
-const size_t cbox_nverts = sizeof(cbox_verts) / (sizeof(float[3]));
+const unsigned cbox_nverts = (unsigned)(sizeof(cbox_verts)/(sizeof(float[3])));
const uint32_t cbox_ids[] = {
/* Box */
@@ -87,9 +87,10 @@ const uint32_t cbox_ids[] = {
18, 19, 23, 23, 22, 18,
16, 17, 21, 21, 20, 16
};
-const size_t cbox_nids = sizeof(cbox_ids)/sizeof(uint32_t);
+const unsigned cbox_nids = (unsigned)(sizeof(cbox_ids)/sizeof(uint32_t));
+const unsigned cbox_ntris = (unsigned)(sizeof(cbox_ids)/sizeof(uint32_t)/3);
-static unsigned
+static INLINE unsigned
cbox_get_ntris(void* data)
{
(void)data;
@@ -97,7 +98,7 @@ cbox_get_ntris(void* data)
return (unsigned)(cbox_nids / 3);
}
-static void
+static INLINE void
cbox_get_ids(const unsigned itri, unsigned ids[3], void* data)
{
const unsigned id = itri * 3;
@@ -109,7 +110,7 @@ cbox_get_ids(const unsigned itri, unsigned ids[3], void* data)
ids[2] = cbox_ids[id + 2];
}
-static void
+static INLINE void
cbox_get_position(const unsigned ivert, float position[3], void* data)
{
(void)data;
@@ -119,7 +120,7 @@ cbox_get_position(const unsigned ivert, float position[3], void* data)
position[2] = cbox_verts[ivert*3 + 2];
}
-static void
+static INLINE void
cbox_get_normal(const unsigned ivert, float normal[3], void* data)
{
(void)ivert, (void)data;
@@ -128,7 +129,7 @@ cbox_get_normal(const unsigned ivert, float normal[3], void* data)
normal[2] = 0.f;
}
-static void
+static INLINE void
cbox_get_uv(const unsigned ivert, float uv[2], void* data)
{
(void)ivert, (void)data;
diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c
@@ -48,7 +48,7 @@ main(int argc, char** argv)
CHECK(s3d_device_create(NULL, &allocator, &dev), RES_OK);
FOR_EACH(i, 0, nshapes)
- CHECK(s3d_shape_create(dev, shapes + i), RES_OK);
+ CHECK(s3d_shape_create_mesh(dev, shapes + i), RES_OK);
CHECK(s3d_scene_create(NULL, NULL), RES_BAD_ARG);
CHECK(s3d_scene_create(dev, NULL), RES_BAD_ARG);
diff --git a/src/test_s3d_shape.c b/src/test_s3d_shape.c
@@ -40,55 +40,142 @@ main(int argc, char** argv)
struct mem_allocator allocator;
struct s3d_device* dev;
struct s3d_shape* shape;
- struct s3d_trimesh_desc trimesh = S3D_TRIMESH_DESC_NULL;
+ struct s3d_vertex_data attribs[4];
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
CHECK(s3d_device_create(NULL, &allocator, &dev), RES_OK);
- CHECK(s3d_shape_create(NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_shape_create(dev, NULL), RES_BAD_ARG);
- CHECK(s3d_shape_create(NULL, &shape), RES_BAD_ARG);
- CHECK(s3d_shape_create(dev, &shape), RES_OK);
+ CHECK(s3d_shape_create_mesh(NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_create_mesh(dev, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_create_mesh(NULL, &shape), RES_BAD_ARG);
+ CHECK(s3d_shape_create_mesh(dev, &shape), RES_OK);
CHECK(s3d_shape_detach(NULL), RES_BAD_ARG);
CHECK(s3d_shape_detach(shape), RES_OK);
- CHECK(s3d_shape_setup_trimesh(NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_shape_setup_trimesh(shape, NULL), RES_BAD_ARG);
- CHECK(s3d_shape_setup_trimesh(NULL, &trimesh), RES_BAD_ARG);
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_BAD_ARG);
- trimesh.get_tricount = cbox_get_ntris;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_BAD_ARG);
- trimesh.get_indices = cbox_get_ids;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_BAD_ARG);
- trimesh.get_position = cbox_get_position;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK);
- CHECK(s3d_shape_setup_trimesh(NULL, &trimesh), RES_BAD_ARG);
- trimesh.get_normal = cbox_get_normal;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK);
- trimesh.get_uv = cbox_get_uv;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK);
-
- trimesh = S3D_TRIMESH_DESC_NULL;
- trimesh.get_tricount = cbox_get_ntris;
- trimesh.get_indices = cbox_get_ids;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK);
- trimesh.get_tricount = NULL;
- trimesh.get_indices = NULL;
- trimesh.get_position = cbox_get_position;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK);
- trimesh.get_position = NULL;
- trimesh.get_normal = cbox_get_normal;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK);
- trimesh.get_normal = NULL;
- trimesh.get_uv = cbox_get_uv;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK);
-
- trimesh = S3D_TRIMESH_DESC_NULL;
- trimesh.get_indices = cbox_get_ids;
- CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_BAD_ARG);
+ attribs[0].type = S3D_FLOAT3;
+ attribs[0].usage = S3D_POSITION;
+ attribs[0].get = cbox_get_position;
+ attribs[1] = S3D_VERTEX_DATA_NULL;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, 0, NULL, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, 0, NULL, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, cbox_ntris, NULL, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, NULL, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, 0, cbox_get_ids, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, 0, cbox_get_ids, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, cbox_ntris, cbox_get_ids, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, cbox_get_ids, 0, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, 0, NULL, cbox_nverts, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, 0, NULL, cbox_nverts, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, cbox_ntris, NULL, cbox_nverts, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, NULL, cbox_nverts, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, 0, cbox_get_ids, cbox_nverts, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, 0, cbox_get_ids, cbox_nverts, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, cbox_ntris, cbox_get_ids, cbox_nverts, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, cbox_get_ids, cbox_nverts, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, 0, NULL, 0, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, 0, NULL, 0, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, cbox_ntris, NULL, 0, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, NULL, 0, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, 0, cbox_get_ids, 0, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, 0, cbox_get_ids, 0, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, cbox_ntris, cbox_get_ids, 0, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, cbox_get_ids, 0, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, 0, NULL, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, 0, NULL, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, cbox_ntris, NULL, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, NULL, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, 0, cbox_get_ids, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, 0, cbox_get_ids, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (NULL, cbox_ntris, cbox_get_ids, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, cbox_get_ids, cbox_nverts, attribs, NULL), RES_OK);
+
+ attribs[0] = S3D_VERTEX_DATA_NULL;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, cbox_get_ids, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+
+ attribs[0].type = S3D_FLOAT3;
+ attribs[0].usage = S3D_POSITION;
+ attribs[0].get = S3D_KEEP;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, cbox_get_ids, cbox_nverts, attribs, NULL), RES_OK);
+
+ attribs[0].get = cbox_get_position;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, S3D_KEEP, cbox_nverts, attribs, NULL), RES_OK);
+
+ attribs[0].type = S3D_FLOAT3;
+ attribs[0].usage = S3D_ATTRIB_0;
+ attribs[0].get = cbox_get_normal;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, S3D_KEEP, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+
+ attribs[1].type = S3D_FLOAT3;
+ attribs[1].usage = S3D_POSITION;
+ attribs[1].get = S3D_KEEP;
+ attribs[2] = S3D_VERTEX_DATA_NULL;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, S3D_KEEP, cbox_nverts, attribs, NULL), RES_OK);
+
+ attribs[2].type = S3D_FLOAT2;
+ attribs[2].usage = S3D_ATTRIB_2;
+ attribs[2].get = cbox_get_uv;
+ attribs[3] = S3D_VERTEX_DATA_NULL;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, S3D_KEEP, cbox_nverts, attribs, NULL), RES_OK);
+
+ attribs[0].get = S3D_KEEP;
+ attribs[1].get = S3D_KEEP;
+ attribs[2].get = S3D_KEEP;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, 2, S3D_KEEP, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, S3D_KEEP, cbox_nverts+1, attribs, NULL), RES_BAD_ARG);
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, S3D_KEEP, cbox_nverts, attribs, NULL), RES_OK);
+
+ attribs[2].type = S3D_FLOAT3;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, S3D_KEEP, cbox_nverts, attribs, NULL), RES_BAD_ARG);
+
+ attribs[0].get = cbox_get_position;
+ attribs[2] = S3D_VERTEX_DATA_NULL;
+ CHECK(s3d_shape_mesh_setup_indexed_vertices
+ (shape, cbox_ntris, S3D_KEEP, cbox_nverts, attribs, NULL), RES_OK);
CHECK(s3d_shape_ref_get(NULL), RES_BAD_ARG);
CHECK(s3d_shape_ref_get(shape), RES_OK);