solstice-solver

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

commit 39b860435a2ff55cb250df4dc00da69a3c807d8a
parent c082c446783757d3ec794303572fcd53cf097489
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue, 11 Apr 2017 18:22:17 +0200

Add analytic spheres to solver.

Diffstat:
Msrc/ssol.h | 12+++++++++++-
Msrc/ssol_shape.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ssol_shape_c.h | 8++++++++
Msrc/test_ssol_shape.c | 18++++++++++++++++++
4 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/src/ssol.h b/src/ssol.h @@ -239,6 +239,7 @@ static const struct ssol_punched_surface SSOL_PUNCHED_SURFACE_NULL = enum ssol_analytic_type { SSOL_ANALYTIC_CYLINDER, + SSOL_ANALYTIC_SPHERE, SSOL_ANALYTIC_SURFACE_TYPES_COUNT__ }; @@ -248,15 +249,24 @@ struct ssol_analytic_cylinder { unsigned nslices; unsigned nstacks; }; - #define SSOL_ANALYTIC_CYLINDER_NULL__ { -1, -1, 0, 0 } static const struct ssol_analytic_cylinder SSOL_ANALYTIC_CYLINDER_NULL = SSOL_ANALYTIC_CYLINDER_NULL__; +struct ssol_analytic_sphere { + double radius; + unsigned nslices; + unsigned nstacks; +}; +#define SSOL_ANALYTIC_SPHERE_NULL__ { -1, 0 } +static const struct ssol_analytic_sphere SSOL_ANALYTIC_SPHERE_NULL = +SSOL_ANALYTIC_SPHERE_NULL__; + struct ssol_analytic_surface { enum ssol_analytic_type type; union { struct ssol_analytic_cylinder cylinder; + struct ssol_analytic_sphere sphere; } data; /* 3x4 column major transformation of the quadric in object space */ diff --git a/src/ssol_shape.c b/src/ssol_shape.c @@ -153,6 +153,14 @@ check_cylinder(const struct ssol_analytic_cylinder* cylinder) && cylinder->nslices > 2 && cylinder->nstacks > 0; } +static FINLINE int +check_sphere(const struct ssol_analytic_sphere* sphere) +{ + return sphere != NULL + && sphere->radius > 0 + && sphere->nslices > 2 && sphere->nstacks > 0; +} + static INLINE int check_analytic_surface(const struct ssol_analytic_surface* analytic_surface) { @@ -163,6 +171,8 @@ check_analytic_surface(const struct ssol_analytic_surface* analytic_surface) switch(analytic_surface->type) { case SSOL_ANALYTIC_CYLINDER: return check_cylinder(&analytic_surface->data.cylinder); + case SSOL_ANALYTIC_SPHERE: + return check_sphere(&analytic_surface->data.sphere); default: return 0; } } @@ -923,6 +933,15 @@ analytic_cylinder_gradient_local grad[2] = 0; } +static FINLINE void +analytic_sphere_gradient_local +(const double pt[3], + double grad[3]) +{ + ASSERT(pt && grad); + d3_set(grad, pt); +} + static FINLINE int quadric_plane_intersect_local (const double org[3], @@ -1083,6 +1102,30 @@ analytic_cylinder_intersect_local return 1; } +static FINLINE int +analytic_sphere_intersect_local +(const struct priv_analytic_sphere* analytic, + const double org[3], + const double dir[3], + const double hint, + double hit_pt[3], + double grad[3], + double* dist) /* in/out: */ +{ + double dst[2]; + const double a = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]; + const double b = 2 * (org[0] * dir[0] + org[1] * dir[1] + org[2] * dir[2]); + const double c = org[0] * org[0] + org[1] * org[1] + org[2] * org[2] + - analytic->sqr_radius; + const int n = solve_second(a, b, c, hint, dst); + + if (!n) return 0; + d3_add(hit_pt, org, d3_muld(hit_pt, dir, dst[0])); + analytic_sphere_gradient_local(hit_pt, grad); + *dist = *dst; + return 1; +} + static FINLINE void punched_shape_set_z_local(const struct ssol_shape* shape, double pt[3]) { @@ -1201,6 +1244,10 @@ analytic_intersect_local hit = analytic_cylinder_intersect_local (&shape->private_data.cylinder, org, dir, hint, pt, N, dist); break; + case SSOL_ANALYTIC_SPHERE: + hit = analytic_sphere_intersect_local + (&shape->private_data.sphere, org, dir, hint, pt, N, dist); + break; default: FATAL("Unreachable code.\n"); break; } return hit; @@ -1407,6 +1454,7 @@ analytic_setup_s3d_shape_rt switch(shape->private_type.analytic) { case SSOL_ANALYTIC_CYLINDER: ASSERT(shape->private_data.cylinder.nslices < UINT_MAX); + ASSERT(shape->private_data.cylinder.nstacks < UINT_MAX); res = s3dut_create_cylinder( shape->dev->allocator, shape->private_data.cylinder.radius, @@ -1419,6 +1467,20 @@ analytic_setup_s3d_shape_rt goto error; } break; + case SSOL_ANALYTIC_SPHERE: + ASSERT(shape->private_data.sphere.nslices < UINT_MAX); + ASSERT(shape->private_data.sphere.nstacks < UINT_MAX); + res = s3dut_create_sphere( + shape->dev->allocator, + shape->private_data.sphere.radius, + shape->private_data.sphere.nslices, + shape->private_data.sphere.nstacks, + &mesh); + if (res != RES_OK) { + fprintf(stderr, "Could not create the sphere 3D data.\n"); + goto error; + } + break; default: FATAL("Unreachable code.\n"); break; } @@ -1468,6 +1530,18 @@ priv_analytic_cylinder_data_setup } static INLINE void +priv_analytic_sphere_data_setup +(struct priv_analytic_sphere* priv_data, + const struct ssol_analytic_sphere* analytic) +{ + ASSERT(priv_data && analytic); + priv_data->radius = analytic->radius; + priv_data->sqr_radius = analytic->radius * analytic->radius; + priv_data->nslices = analytic->nslices; + priv_data->nstacks = analytic->nstacks; +} + +static INLINE void priv_analytic_data_setup (union private_data* priv_data, const struct ssol_analytic_surface* analytic) @@ -1478,6 +1552,10 @@ priv_analytic_data_setup priv_analytic_cylinder_data_setup (&priv_data->cylinder, &analytic->data.cylinder); break; + case SSOL_ANALYTIC_SPHERE: + priv_analytic_sphere_data_setup + (&priv_data->sphere, &analytic->data.sphere); + break; default: FATAL("Unreachable code\n"); break; } } diff --git a/src/ssol_shape_c.h b/src/ssol_shape_c.h @@ -56,12 +56,20 @@ struct priv_analytic_cylinder { unsigned nstacks; }; +struct priv_analytic_sphere { + double radius; + double sqr_radius; + unsigned nslices; + unsigned nstacks; +}; + union private_data { struct priv_hyperbol_data hyperbol; struct priv_parabol_data parabol; struct priv_pcylinder_data pcylinder; struct priv_hemisphere_data hemisphere; struct priv_analytic_cylinder cylinder; + struct priv_analytic_sphere sphere; }; union private_type { diff --git a/src/test_ssol_shape.c b/src/test_ssol_shape.c @@ -269,6 +269,24 @@ main(int argc, char** argv) CHECK(ssol_analytic_surface_setup(shape, &analytic), RES_BAD_ARG); analytic.data.cylinder.nstacks = 10; + analytic.type = SSOL_ANALYTIC_SPHERE; + analytic.data.sphere.radius = 10; + analytic.data.sphere.nslices = 10; + analytic.data.sphere.nstacks = 10; + CHECK(ssol_analytic_surface_setup(shape, &analytic), RES_OK); + + analytic.data.sphere.radius = 0; + CHECK(ssol_analytic_surface_setup(shape, &analytic), RES_BAD_ARG); + analytic.data.sphere.radius = 10; + + analytic.data.sphere.nslices = 0; + CHECK(ssol_analytic_surface_setup(shape, &analytic), RES_BAD_ARG); + analytic.data.sphere.nslices = 10; + + analytic.data.sphere.nstacks = 0; + CHECK(ssol_analytic_surface_setup(shape, &analytic), RES_BAD_ARG); + analytic.data.sphere.nstacks = 10; + analytic.type = (enum ssol_analytic_type)999; CHECK(ssol_analytic_surface_setup(shape, &analytic), RES_BAD_ARG);