commit c3c23fe4279dd83a43f4d9f6552630405738b5dd
parent 2266dc0f3b71b7b07fc941bd63e723ea05629d73
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Tue, 28 Jun 2016 11:23:43 +0200
One step further with shapes, mainly the punched surface flavour.
Meshing of punched surfaces is still in the TODO list.
Diffstat:
3 files changed, 242 insertions(+), 129 deletions(-)
diff --git a/src/ssol_shape.c b/src/ssol_shape.c
@@ -26,54 +26,126 @@
******************************************************************************/
static void
-shape_mesh_release(ref_T* ref)
+shape_release(ref_T* ref)
{
- struct shape_mesh* mesh;
+ struct ssol_shape* shape;
ASSERT(ref);
+ shape = CONTAINER_OF(ref, struct ssol_shape, ref);
- mesh = CONTAINER_OF(ref, struct shape_mesh, ref);
- if (mesh->shape) S3D(shape_ref_put(mesh->shape));
- ASSERT(mesh->dev && mesh->dev->allocator);
- MEM_RM(mesh->dev->allocator, mesh);
- SSOL(device_ref_put(mesh->dev));
+ ASSERT(shape->dev);
+ s3d_shape_ref_put(shape->shape);
+ SSOL(device_ref_put(shape->dev));
+ MEM_RM(shape->dev->allocator, shape->quadric);
+ MEM_RM(shape->dev->allocator, shape);
}
-static void
-shape_mesh_ref_get(struct shape_mesh* mesh)
-{
- ASSERT(mesh);
- ref_get(&mesh->ref);
+static INLINE res_T
+check_plane_ok(const struct ssol_quadric_plane* plane) {
+ if (!plane)
+ return RES_BAD_ARG;
+ return RES_OK;
}
-static void
-shape_mesh_ref_put(struct shape_mesh* mesh)
-{
- ASSERT(mesh);
- ref_put(&mesh->ref, shape_mesh_release);
+static INLINE res_T
+check_parabol_ok(const struct ssol_quadric_parabol* parabol) {
+ if (!parabol || parabol->focal <= 0)
+ return RES_BAD_ARG;
+ return RES_OK;
}
-static void
-shape_release(ref_T* ref)
+static INLINE res_T
+check_parabolic_cylinder_ok
+ (const struct ssol_quadric_parabolic_cylinder* parabolic_cylinder)
{
- struct ssol_shape* shape;
- ASSERT(ref);
- shape = CONTAINER_OF(ref, struct ssol_shape, ref);
+ if (!parabolic_cylinder || parabolic_cylinder->focal <= 0)
+ return RES_BAD_ARG;
+ return RES_OK;
+}
- switch (shape->type) {
- case SHAPE_NONE:
- break;
- case SHAPE_MESH:
- if (shape->data.mesh) shape_mesh_ref_put(shape->data.mesh);
- break;
- case SHAPE_PUNCHED:
- if (shape->data.punched) /* TODO */;
- break;
- default: FATAL("Unreachable code \n"); break;
+static INLINE res_T
+check_general_quadric_ok(const struct ssol_general_quadric* quadric) {
+ if (!quadric)
+ return RES_BAD_ARG;
+ /* we don't check that the quadric equation has solutions */
+ /* in such case, the quadric is valid but has zero surface */
+ return RES_OK;
+}
+
+static INLINE res_T
+quadric_ok(const struct ssol_quadric* quadric) {
+ if (!quadric)
+ return RES_BAD_ARG;
+ switch (quadric->type) {
+ case SSOL_QUADRIC_PLANE:
+ return check_plane_ok(&quadric->data.plane);
+ case SSOL_QUADRIC_PARABOL:
+ return check_parabol_ok(&quadric->data.parabol);
+ case SSOL_QUADRIC_PARABOLIC_CYLINDER:
+ return check_parabolic_cylinder_ok(&quadric->data.parabolic_cylinder);
+ case SSOL_GENERAL_QUADRIC:
+ return check_general_quadric_ok(&quadric->data.general_quadric);
+ default: return RES_BAD_ARG;
}
+}
- ASSERT(shape->dev);
- MEM_RM(shape->dev->allocator, shape);
- SSOL(device_ref_put(shape->dev));
+static INLINE res_T
+check_circle_ok(const struct ssol_carving_circle* circle) {
+ if (!circle || circle->radius <= 0)
+ return RES_BAD_ARG;
+ return RES_OK;
+}
+
+static INLINE res_T
+check_polygon_ok(const struct ssol_carving_polygon* polygon) {
+ if (!polygon
+ || ! polygon->get
+ || polygon->nb_vertices <= 0)
+ return RES_BAD_ARG;
+ /* we don't check that the polygon defines a not empty area */
+ /* in such case, the quadric is valid but can have zero surface */
+ return RES_OK;
+}
+
+static INLINE res_T
+check_carving_ok(const struct ssol_carving* carving) {
+ if (!carving)
+ return RES_BAD_ARG;
+ switch (carving->type) {
+ case SSOL_CARVING_CIRCLE:
+ return check_circle_ok(&carving->data.circle);
+ case SSOL_CARVING_POLYGON:
+ return check_polygon_ok(&carving->data.polygon);
+ default: return RES_BAD_ARG;
+ }
+}
+
+static INLINE res_T
+punched_surface_ok(const struct ssol_punched_surface* punched_surface) {
+ size_t i;
+ if (!punched_surface
+ || punched_surface->nb_carvings == 0
+ || !punched_surface->carvings
+ || !punched_surface->quadric
+ || quadric_ok(punched_surface->quadric) != RES_OK)
+ return RES_BAD_ARG;
+ for (i = 0; i < punched_surface->nb_carvings; i++) {
+ if (check_carving_ok(&punched_surface->carvings[i]))
+ return RES_BAD_ARG;
+ }
+ /* we don't check that carvings define a non empty area */
+ /* in such case, the quadric is valid but has zero surface */
+ return RES_OK;
+}
+
+static INLINE res_T
+shape_ok(const struct ssol_shape* shape) {
+ if (!shape
+ || !shape->dev
+ || !shape->shape
+ || SHAPE_FIRST_TYPE > shape->type
+ || shape->type > SHAPE_LAST_TYPE)
+ return RES_BAD_ARG;
+ return RES_OK;
}
/*******************************************************************************
@@ -81,12 +153,17 @@ shape_release(ref_T* ref)
******************************************************************************/
static res_T
-shape_create(struct ssol_device* dev, struct ssol_shape** out_shape)
+shape_create
+ (struct ssol_device* dev,
+ struct ssol_shape** out_shape,
+ enum shape_type type)
{
struct ssol_shape* shape = NULL;
res_T res = RES_OK;
- ASSERT(dev && out_shape);
+ if (!dev || !out_shape) {
+ return RES_BAD_ARG;
+ }
shape = (struct ssol_shape*)MEM_CALLOC
(dev->allocator, 1, sizeof(struct ssol_shape));
@@ -95,10 +172,14 @@ shape_create(struct ssol_device* dev, struct ssol_shape** out_shape)
goto error;
}
+ res = s3d_shape_create_mesh(dev->s3d, &shape->shape);
+ if (res != RES_OK)
+ goto error;
+
SSOL(device_ref_get(dev));
shape->dev = dev;
ref_init(&shape->ref);
- shape->type = SHAPE_NONE;
+ shape->type = type;
exit:
if (out_shape) *out_shape = shape;
@@ -112,40 +193,6 @@ error:
}
-static res_T
-shape_mesh_create
-(struct ssol_device* dev,
- struct shape_mesh** out_mesh)
-{
- struct shape_mesh* mesh = NULL;
- res_T res = RES_OK;
-
- mesh = (struct shape_mesh*)MEM_CALLOC
- (dev->allocator, 1, sizeof(struct shape_mesh));
- if (!mesh) {
- res = RES_MEM_ERR;
- goto error;
- }
-
- res = s3d_shape_create_mesh(dev->s3d, &mesh->shape);
- if (res != RES_OK)
- goto error;
-
- SSOL(device_ref_get(dev));
- mesh->dev = dev;
- ref_init(&mesh->ref);
-
-exit:
- if (out_mesh) *out_mesh = mesh;
- return res;
-error:
- if (mesh) {
- shape_mesh_ref_put(mesh);
- mesh = NULL;
- }
- goto exit;
-}
-
/*******************************************************************************
* Exported ssol_shape functions
******************************************************************************/
@@ -155,35 +202,7 @@ ssol_shape_create_mesh
(struct ssol_device* dev,
struct ssol_shape** out_shape)
{
- struct ssol_shape* shape = NULL;
- res_T res = RES_OK;
-
- if (!dev || !out_shape) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- res = shape_create(dev, &shape);
- if (res != RES_OK)
- goto error;
-
- res = shape_mesh_create(dev, &shape->data.mesh);
- if (res != RES_OK)
- goto error;
-
- shape->type = SHAPE_MESH;
- shape->dev = dev;
- ref_init(&shape->ref);
-
-exit:
- if (out_shape) *out_shape = shape;
- return res;
-error:
- if (shape) {
- SSOL(shape_ref_put(shape));
- shape = NULL;
- }
- goto exit;
+ return shape_create(dev, out_shape, SHAPE_MESH);
}
res_T
@@ -191,13 +210,7 @@ ssol_shape_create_punched_surface
(struct ssol_device* dev,
struct ssol_shape** out_shape)
{
- res_T res = RES_OK;
-
- if (!dev || !out_shape) {
- return RES_BAD_ARG;
- }
- /* TODO */
- return res;
+ return shape_create(dev, out_shape, SHAPE_PUNCHED);
}
res_T
@@ -226,11 +239,26 @@ ssol_punched_surface_setup
const struct ssol_punched_surface* punched_surface)
{
res_T res = RES_OK;
+ struct mem_allocator * allocator;
- if (!shape || shape->type != SHAPE_PUNCHED || !punched_surface) {
+ if (shape_ok(shape) != RES_OK
+ || shape->type != SHAPE_PUNCHED
+ || punched_surface_ok(punched_surface) != RES_OK) {
return RES_BAD_ARG;
}
+ ASSERT(shape->ref);
+ ASSERT(shape->dev && shape->dev->allocator && shape->shape);
+
+ /* save quadric for further object instancing */
+ MEM_RM(shape->dev->allocator, shape->quadric);
+ shape->quadric = (struct ssol_quadric*)MEM_CALLOC
+ (shape->dev->allocator, 1, sizeof(struct ssol_quadric));
+ *shape->quadric = *punched_surface->quadric;
+
+ /* mesh the surface: TODO */
+ (void) allocator; /* will be used later */
+
return res;
}
@@ -248,14 +276,16 @@ ssol_mesh_setup
res_T res = RES_OK;
unsigned i;
- if (!shape || shape->type != SHAPE_MESH || !get_indices) {
+ if (shape_ok(shape) != RES_OK
+ || shape->type != SHAPE_MESH
+ || !get_indices) {
return RES_BAD_ARG;
}
if (!ntris || !nverts || !attribs || !nattribs) {
return RES_BAD_ARG;
}
ASSERT(shape->ref);
- ASSERT(shape->dev && shape->dev->allocator && shape->data.mesh);
+ ASSERT(shape->dev && shape->dev->allocator && shape->shape);
_attrib3 = (struct s3d_vertex_data*)MEM_CALLOC
(shape->dev->allocator, nattribs, sizeof(struct s3d_vertex_data));
@@ -271,11 +301,11 @@ ssol_mesh_setup
_attrib3[i].type = S3D_FLOAT3;
break;
case SSOL_NORMAL:
- _attrib3[i].usage = S3D_GEOMETRY_NORMAL;
+ _attrib3[i].usage = S3D_ATTRIB_0;
_attrib3[i].type = S3D_FLOAT3;
break;
case SSOL_TEXCOORD:
- _attrib3[i].usage = S3D_ATTRIB_0;
+ _attrib3[i].usage = S3D_ATTRIB_1;
_attrib3[i].type = S3D_FLOAT2;
break;
default:
@@ -283,7 +313,7 @@ ssol_mesh_setup
break;
}
}
- res = s3d_mesh_setup_indexed_vertices(shape->data.mesh->shape, ntris, get_indices, nverts, _attrib3, nattribs, data);
+ res = s3d_mesh_setup_indexed_vertices(shape->shape, ntris, get_indices, nverts, _attrib3, nattribs, data);
MEM_RM(shape->dev->allocator, _attrib3);
return res;
}
\ No newline at end of file
diff --git a/src/ssol_shape_c.h b/src/ssol_shape_c.h
@@ -27,24 +27,11 @@ enum shape_type {
SHAPE_LAST_TYPE = SHAPE_PUNCHED
};
-struct shape_mesh {
- struct s3d_shape* shape;
-
- struct ssol_device* dev;
- ref_T ref;
-};
-
-struct shape_punched {
- char TODO;
-};
-
struct ssol_shape {
enum shape_type type;
- union {
- struct shape_mesh* mesh;
- struct shape_punched* punched;
- } data;
+ struct s3d_shape* shape;
+ struct ssol_quadric* quadric; /* NULL if type != SHAPE_PUNCHED */
struct ssol_device* dev;
ref_T ref;
diff --git a/src/test_ssol_shape.c b/src/test_ssol_shape.c
@@ -98,6 +98,17 @@ cbox_get_uv(const unsigned ivert, float uv[2], void* data)
uv[1] = 1.f;
}
+static INLINE void
+get_polygon_vertices(const size_t ivert, double position[2], void* ctx)
+{
+ (void) ivert, (void) ctx;
+ position[0] = -1.f;
+ position[1] = 1.f;
+}
+
+/*******************************************************************************
+* test main program
+******************************************************************************/
int
main(int argc, char** argv)
{
@@ -107,6 +118,9 @@ main(int argc, char** argv)
struct ssol_shape* shape;
struct ssol_vertex_data attribs[3];
void* data = (void*) &cbox_walls_desc;
+ struct ssol_punched_surface punched_surface;
+ struct ssol_carving carving;
+ struct ssol_quadric quadric;
(void) argc, (void) argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -145,6 +159,88 @@ main(int argc, char** argv)
CHECK(ssol_mesh_setup(shape, cbox_walls_ntris, cbox_get_ids, cbox_walls_nverts, attribs, 3, data), RES_OK);
CHECK(ssol_shape_ref_put(shape), RES_OK);
+
+ CHECK(ssol_shape_create_punched_surface(NULL, NULL), RES_BAD_ARG);
+ CHECK(ssol_shape_create_punched_surface(dev, NULL), RES_BAD_ARG);
+ CHECK(ssol_shape_create_punched_surface(NULL, &shape), RES_BAD_ARG);
+ CHECK(ssol_shape_create_punched_surface(dev, &shape), RES_OK);
+
+ CHECK(ssol_shape_ref_get(NULL), RES_BAD_ARG);
+ CHECK(ssol_shape_ref_get(shape), RES_OK);
+
+ CHECK(ssol_shape_ref_put(NULL), RES_BAD_ARG);
+ CHECK(ssol_shape_ref_put(shape), RES_OK);
+
+ carving.type = SSOL_CARVING_CIRCLE;
+ carving.internal = 0;
+ carving.data.circle.center[0] = 0;
+ carving.data.circle.center[1] = 0;
+ carving.data.circle.radius = 1;
+ quadric.type = SSOL_QUADRIC_PLANE;
+ punched_surface.nb_carvings = 1;
+ punched_surface.quadric = &quadric;
+ punched_surface.carvings = &carving;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_OK);
+
+ punched_surface.nb_carvings = 0;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ punched_surface.nb_carvings = 1;
+
+ punched_surface.carvings = NULL;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ punched_surface.carvings = &carving;
+
+ punched_surface.quadric = NULL;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ punched_surface.quadric = &quadric;
+
+ quadric.type = (enum ssol_quadric_type)999;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ quadric.type = SSOL_QUADRIC_PLANE;
+
+ carving.type = (enum ssol_carving_type)999;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ carving.type = SSOL_CARVING_CIRCLE;
+
+ carving.data.circle.radius = 0;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ carving.data.circle.radius = 1;
+
+ carving.type = SSOL_CARVING_POLYGON;
+ carving.data.polygon.get = get_polygon_vertices;
+ carving.data.polygon.nb_vertices = 1;
+ carving.data.polygon.context = NULL;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_OK);
+
+ carving.data.polygon.nb_vertices = 0;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ carving.data.polygon.nb_vertices = 1;
+
+ carving.data.polygon.get = NULL;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ carving.data.polygon.get = get_polygon_vertices;
+
+ quadric.type = SSOL_QUADRIC_PARABOL;
+ quadric.data.parabol.focal = 1;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_OK);
+
+ quadric.data.parabol.focal = 0;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ quadric.data.parabol.focal = 1;
+
+ quadric.type = SSOL_QUADRIC_PARABOLIC_CYLINDER;
+ quadric.data.parabolic_cylinder.focal = 1;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_OK);
+
+ quadric.data.parabolic_cylinder.focal = 0;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_BAD_ARG);
+ quadric.data.parabolic_cylinder.focal = 1;
+
+ quadric.type = SSOL_GENERAL_QUADRIC;
+ CHECK(ssol_punched_surface_setup(shape, &punched_surface), RES_OK);
+
+ CHECK(ssol_shape_ref_put(shape), RES_OK);
+
CHECK(ssol_device_ref_put(dev), RES_OK);
logger_release(&logger);