solstice-solver

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

commit f86f429e5e9a2fe75e2868376282133778c17643
parent 1f552a8ec7190d4f106d5fcb55ad0807f2a213a4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 15 Mar 2017 14:23:53 +0100

Add the "slices_count_hint" parameter to the ssol_quadric data structure

This parameter is used to control the discretisation of the quadric. By
default, the discretisation level is automatically controlled by the
application.

Diffstat:
Msrc/ssol.h | 9+++++++--
Msrc/ssol_shape.c | 152++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/ssol_shape_c.h | 13+++++--------
3 files changed, 104 insertions(+), 70 deletions(-)

diff --git a/src/ssol.h b/src/ssol.h @@ -159,9 +159,9 @@ static const struct ssol_quadric_parabol SSOL_QUADRIC_PARABOL_NULL = SSOL_QUADRIC_PARABOL_NULL__; struct ssol_quadric_hyperbol { - double img_focal, real_focal; /* Define (x^2 + y^2) / a^2 - (z - 1/2)^2 / b^2 + 1 = 0 * with a^2 = f - f^2; b = f -1/2; f = real_focal / (img_focal + real_focal) */ + double img_focal, real_focal; }; #define SSOL_QUADRIC_HYPERBOL_NULL__ { -1.0 , -1.0 } static const struct ssol_quadric_hyperbol SSOL_QUADRIC_HYPERBOL_NULL = @@ -185,13 +185,18 @@ struct ssol_quadric { /* 3x4 column major transformation of the quadric in object space */ double transform[12]; + + /* Hint on the how to discretised */ + size_t slices_count_hint; }; #define SSOL_QUADRIC_DEFAULT__ { \ SSOL_QUADRIC_PLANE, \ {SSOL_QUADRIC_PLANE_DEFAULT__}, \ - {1,0,0, 0,1,0, 0,0,1, 0,0,0} \ + {1,0,0, 0,1,0, 0,0,1, 0,0,0}, \ + SIZE_MAX /* <=> Use default discretisation */ \ } + static const struct ssol_quadric SSOL_QUADRIC_DEFAULT = SSOL_QUADRIC_DEFAULT__; /* Define the contour of a 2D polygon as well as the clipping operation to diff --git a/src/ssol_shape.c b/src/ssol_shape.c @@ -44,7 +44,7 @@ struct mesh_context { struct quadric_mesh_context { const double* coords; const size_t* ids; - const struct priv_quadric_data* quadric; + const union priv_quadric_data* quadric; const double* transform; /* 3x4 column major matrix */ }; @@ -227,7 +227,7 @@ quadric_mesh_parabol_get_pos(const unsigned ivert, float pos[3], void* ctx) ASSERT(pos && ctx); p[0] = msh->coords[i+0]; p[1] = msh->coords[i+1]; - p[2] = parabol_z(p, &msh->quadric->data.parabol); + p[2] = parabol_z(p, &msh->quadric->parabol); /* Transform the position in object space */ d33_muld3(p, msh->transform, p); @@ -245,7 +245,7 @@ quadric_mesh_hyperbol_get_pos(const unsigned ivert, float pos[3], void* ctx) ASSERT(pos && ctx); p[0] = msh->coords[i+0]; p[1] = msh->coords[i+1]; - p[2] = hyperbol_z(p, &msh->quadric->data.hyperbol); + p[2] = hyperbol_z(p, &msh->quadric->hyperbol); /* Transform the position in object space */ d33_muld3(p, msh->transform, p); @@ -264,7 +264,7 @@ quadric_mesh_parabolic_cylinder_get_pos ASSERT(pos && ctx); p[0] = msh->coords[i+0]; p[1] = msh->coords[i+1]; - p[2] = parabolic_cylinder_z(p, &msh->quadric->data.pcylinder); + p[2] = parabolic_cylinder_z(p, &msh->quadric->pcylinder); /* Transform the position in object space */ d33_muld3(p, msh->transform, p); @@ -837,13 +837,13 @@ punched_shape_set_z_local(const struct ssol_shape* shape, double pt[3]) pt[2] = 0; break; case SSOL_QUADRIC_PARABOLIC_CYLINDER: - pt[2] = parabolic_cylinder_z(pt, &shape->priv_quadric.data.pcylinder); + pt[2] = parabolic_cylinder_z(pt, &shape->priv_quadric.pcylinder); break; case SSOL_QUADRIC_PARABOL: - pt[2] = parabol_z(pt, &shape->priv_quadric.data.parabol); + pt[2] = parabol_z(pt, &shape->priv_quadric.parabol); break; case SSOL_QUADRIC_HYPERBOL: - pt[2] = hyperbol_z(pt, &shape->priv_quadric.data.hyperbol); + pt[2] = hyperbol_z(pt, &shape->priv_quadric.hyperbol); break; default: FATAL("Unreachable code\n"); break; } @@ -863,15 +863,15 @@ punched_shape_set_normal_local break; case SSOL_QUADRIC_PARABOLIC_CYLINDER: quadric_parabolic_cylinder_gradient_local - (&shape->priv_quadric.data.pcylinder, pt, normal); + (&shape->priv_quadric.pcylinder, pt, normal); break; case SSOL_QUADRIC_PARABOL: { quadric_parabol_gradient_local - (&shape->priv_quadric.data.parabol, pt, normal); + (&shape->priv_quadric.parabol, pt, normal); break; case SSOL_QUADRIC_HYPERBOL: quadric_hyperbol_gradient_local - (&shape->priv_quadric.data.hyperbol, pt, normal); + (&shape->priv_quadric.hyperbol, pt, normal); break; } default: FATAL("Unreachable code\n"); break; @@ -900,15 +900,15 @@ punched_shape_intersect_local break; case SSOL_QUADRIC_PARABOLIC_CYLINDER: hit = quadric_parabolic_cylinder_intersect_local - (&shape->priv_quadric.data.pcylinder, org, dir, hint, pt, N, dist); + (&shape->priv_quadric.pcylinder, org, dir, hint, pt, N, dist); break; case SSOL_QUADRIC_PARABOL: hit = quadric_parabol_intersect_local - (&shape->priv_quadric.data.parabol, org, dir, hint, pt, N, dist); + (&shape->priv_quadric.parabol, org, dir, hint, pt, N, dist); break; case SSOL_QUADRIC_HYPERBOL: hit = quadric_hyperbol_intersect_local - (&shape->priv_quadric.data.hyperbol, org, dir, hint, pt, N, dist); + (&shape->priv_quadric.hyperbol, org, dir, hint, pt, N, dist); break; default: FATAL("Unreachable code\n"); break; } @@ -930,32 +930,23 @@ shape_release(ref_T* ref) } /* Return the parabol discretisation parameter */ -static INLINE size_t -priv_data_parabol_setup +static FINLINE void +priv_parabol_data_setup (struct priv_parabol_data* data, - struct ssol_quadric_parabol* parabol, - const double lower[3], - const double upper[3]) + const struct ssol_quadric_parabol* parabol) { - double max_z; - ASSERT(data && parabol && lower && upper); - + ASSERT(data && parabol); data->focal = parabol->focal; data->_1_4f = 1 / (4.0 * parabol->focal); - max_z = MMAX(parabol_z(lower, data), parabol_z(upper, data)); - return MMIN(50, (size_t) (3 + sqrt(max_z) * 6)); } -static INLINE size_t -priv_data_hyperbol_setup +static FINLINE void +priv_hyperbol_data_setup (struct priv_hyperbol_data* data, - struct ssol_quadric_hyperbol* hyperbol, - const double lower[3], - const double upper[3]) + const struct ssol_quadric_hyperbol* hyperbol) { double g, f, a2; - double max_z; - ASSERT(data && hyperbol && lower && upper); + ASSERT(data && hyperbol); /* Re-dimensionalize */ g = hyperbol->real_focal + hyperbol->img_focal; @@ -966,25 +957,76 @@ priv_data_hyperbol_setup data->abs_b = g * fabs(f - 0.5); data->_a2_b2 = a2 / (data->abs_b * data->abs_b); data->_1_a2 = 1 / a2; - max_z = MMAX(hyperbol_z(lower, data), hyperbol_z(upper, data)); - return MMIN(50, (size_t) (3 + sqrt(max_z) * 6)); } -static INLINE size_t -priv_data_parabolic_cylinder_setup +static FINLINE void +priv_parabolic_cylinder_data_setup (struct priv_pcylinder_data* data, - struct ssol_quadric_parabolic_cylinder* parabolic_cylinder, + const struct ssol_quadric_parabolic_cylinder* parabolic_cylinder) +{ + ASSERT(data && parabolic_cylinder); + data->focal = parabolic_cylinder->focal; + data->_1_4f = 1 / (4.0 * parabolic_cylinder->focal); +} + +static INLINE void +priv_quadric_data_setup + (union priv_quadric_data* priv_data, + const struct ssol_quadric* quadric) +{ + ASSERT(priv_data && quadric); + switch(quadric->type) { + case SSOL_QUADRIC_PLANE: /* Do nothing */ break; + case SSOL_QUADRIC_PARABOL: + priv_parabol_data_setup + (&priv_data->parabol, &quadric->data.parabol); + break; + case SSOL_QUADRIC_HYPERBOL: + priv_hyperbol_data_setup + (&priv_data->hyperbol, &quadric->data.hyperbol); + break; + case SSOL_QUADRIC_PARABOLIC_CYLINDER: + priv_parabolic_cylinder_data_setup + (&priv_data->pcylinder, &quadric->data.parabolic_cylinder); + break; + default: FATAL("Unreachable code\n"); break; + } +} + +static INLINE size_t +priv_quadric_data_compute_slices_count + (const enum ssol_quadric_type type, + const union priv_quadric_data* priv_data, const double lower[3], const double upper[3]) { + size_t nslices; double max_z; - ASSERT(data && parabolic_cylinder && lower && upper); + ASSERT(priv_data && lower && upper); - data->focal = parabolic_cylinder->focal; - data->_1_4f = 1 / (4.0 * parabolic_cylinder->focal); - max_z = MMAX - (parabolic_cylinder_z(lower, data), parabolic_cylinder_z(upper, data)); - return MMIN(50, (size_t) (3 + sqrt(max_z) * 6)); + switch(type) { + case SSOL_QUADRIC_PLANE: nslices = 50; break; + case SSOL_QUADRIC_PARABOL: + max_z = MMAX + (parabol_z(lower, &priv_data->parabol), + parabol_z(upper, &priv_data->parabol)); + nslices = MMIN(50, (size_t)(3 + sqrt(max_z) * 6)); + break; + case SSOL_QUADRIC_HYPERBOL: + max_z = MMAX + (hyperbol_z(lower, &priv_data->hyperbol), + hyperbol_z(upper, &priv_data->hyperbol)); + nslices = MMIN(50, (size_t)(3 + sqrt(max_z) * 6)); + break; + case SSOL_QUADRIC_PARABOLIC_CYLINDER: + max_z = MMAX + (parabolic_cylinder_z(lower, &priv_data->pcylinder), + parabolic_cylinder_z(upper, &priv_data->pcylinder)); + nslices = MMIN(50, (size_t)(3 + sqrt(max_z) * 6)); + break; + default: FATAL("Unreachable code\n"); break; + } + return nslices; } /******************************************************************************* @@ -1226,25 +1268,15 @@ ssol_punched_surface_setup goto error; } - /* Define the #slices of the discretized quadric & setup internal data */ - switch (psurf->quadric->type) { - case SSOL_QUADRIC_PLANE: - nslices = 1; - break; - case SSOL_QUADRIC_PARABOL: - nslices = priv_data_parabol_setup(&shape->priv_quadric.data.parabol, - &psurf->quadric->data.parabol, lower, upper); - break; - case SSOL_QUADRIC_HYPERBOL: - nslices = priv_data_hyperbol_setup(&shape->priv_quadric.data.hyperbol, - &psurf->quadric->data.hyperbol, lower, upper); - break; - case SSOL_QUADRIC_PARABOLIC_CYLINDER: - nslices = priv_data_parabolic_cylinder_setup - (&shape->priv_quadric.data.pcylinder, - &psurf->quadric->data.parabolic_cylinder,lower, upper); - break; - default: FATAL("Unreachable code\n"); break; + /* Setup internal data */ + priv_quadric_data_setup(&shape->priv_quadric, psurf->quadric); + + /* Define the #slices of the discretized quadric */ + if(psurf->quadric->slices_count_hint != SIZE_MAX) { + nslices = psurf->quadric->slices_count_hint; + } else { + nslices = priv_quadric_data_compute_slices_count + (shape->quadric.type, &shape->priv_quadric, lower, upper); } res = build_triangulated_plane(&coords, &ids, lower, upper, nslices); diff --git a/src/ssol_shape_c.h b/src/ssol_shape_c.h @@ -43,13 +43,10 @@ struct priv_pcylinder_data { double _1_4f; }; -struct priv_quadric_data { - enum ssol_quadric_type type; - union { - struct priv_hyperbol_data hyperbol; - struct priv_parabol_data parabol; - struct priv_pcylinder_data pcylinder; - } data; +union priv_quadric_data { + struct priv_hyperbol_data hyperbol; + struct priv_parabol_data parabol; + struct priv_pcylinder_data pcylinder; }; struct ssol_shape { @@ -57,7 +54,7 @@ struct ssol_shape { struct s3d_shape* shape_rt; /* Star-3D shape to ray-trace */ struct s3d_shape* shape_samp; /* Star-3D shape to sample */ - struct priv_quadric_data priv_quadric; + union priv_quadric_data priv_quadric; struct ssol_quadric quadric; double shape_rt_area, shape_samp_area;