solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

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:
Msrc/ssol_shape.c | 258++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/ssol_shape_c.h | 17++---------------
Msrc/test_ssol_shape.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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);