solstice-solver

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

commit 053635aebe2bc73de546c776936971f03e56cad8
parent ec328b0b6cb74b50e51e7f259fcdcbb54c841995
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue,  4 Apr 2017 18:53:02 +0200

Introduce the ability to define an hemisphere with any carving.

The projected disk is added as an implicit carving with AND semantics.

Diffstat:
Msrc/ssol_shape.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 70 insertions(+), 23 deletions(-)

diff --git a/src/ssol_shape.c b/src/ssol_shape.c @@ -48,6 +48,12 @@ struct quadric_mesh_context { const double* transform; /* 3x4 column major matrix */ }; +struct get_ctx { + size_t nbvert; + double two_pi_over_nbvert; + double radius; +}; + /******************************************************************************* * Helper functions ******************************************************************************/ @@ -236,7 +242,7 @@ hemisphere_z const double z2 = hemisphere->sqr_radius - r2; /* manage numerical unaccuracy */ ASSERT(z2 >= -hemisphere->sqr_radius * FLT_EPSILON); - return (z2 > 0) ? -sqrt(z2) + hemisphere->radius : 0; + return (z2 > 0) ? -sqrt(z2) + hemisphere->radius : hemisphere->radius; } static void @@ -1130,17 +1136,39 @@ priv_quadric_data_compute_slices_count parabolic_cylinder_z(upper, &priv_data->pcylinder)); nslices = MMIN(50, (size_t)(3 + sqrt(max_z) * 6)); break; - case SSOL_QUADRIC_HEMISPHERE: + case SSOL_QUADRIC_HEMISPHERE: { + /* need to clamp the range */ + double l[2], u[2]; + double r; + d2_set(u, upper); + r = d2_dot(u, u); + if (r > priv_data->hemisphere.sqr_radius) + d2_muld(u, u, sqrt(priv_data->hemisphere.sqr_radius / r)); + d2_set(l, lower); + r = d2_dot(l, l); + if (r > priv_data->hemisphere.sqr_radius) + d2_muld(l, l, sqrt(priv_data->hemisphere.sqr_radius / r)); max_z = MMAX - (hemisphere_z(lower, &priv_data->hemisphere), - hemisphere_z(upper, &priv_data->hemisphere)); + (hemisphere_z(l, &priv_data->hemisphere), + hemisphere_z(u, &priv_data->hemisphere)); nslices = MMIN(50, (size_t)(3 + sqrt(max_z) * 6)); break; + } default: FATAL("Unreachable code\n"); break; } return nslices; } +static void +get_circular(const size_t ivert, double position[2], void* ctx) +{ + struct get_ctx* data = (struct get_ctx*)ctx; + const double a = (double)ivert * data->two_pi_over_nbvert; + ASSERT(ivert < data->nbvert); + position[0] = data->radius * cos(a); + position[1] = data->radius * sin(a); +} + /******************************************************************************* * Local functions ******************************************************************************/ @@ -1355,7 +1383,8 @@ ssol_punched_surface_setup double lower[2], upper[2]; /* Carvings AABB */ struct darray_double coords; struct darray_size_t ids; - size_t nslices; + struct ssol_carving* tmp_carvings = NULL; + size_t nslices, tmp_carvings_count; res_T res = RES_OK; darray_double_init(shape->dev->allocator, &coords); @@ -1371,7 +1400,38 @@ ssol_punched_surface_setup /* Save quadric for further object instancing */ shape->quadric = *psurf->quadric; - carvings_compute_aabb(psurf->carvings, psurf->nb_carvings, lower, upper); + if(psurf->quadric->type == SSOL_QUADRIC_HEMISPHERE) { + size_t c; + struct get_ctx ctx; + tmp_carvings = (struct ssol_carving*)MEM_CALLOC + (shape->dev->allocator, 1 + psurf->nb_carvings, sizeof(struct ssol_carving)); + if(!tmp_carvings) { + res = RES_MEM_ERR; + goto error; + } + /* add the implicit circular carving */ + tmp_carvings[0].get = &get_circular; + tmp_carvings[0].nb_vertices = + (psurf->quadric->slices_count_hint == SIZE_MAX) ? + 64 : 8 * psurf->quadric->slices_count_hint; + tmp_carvings[0].operation = SSOL_AND; + tmp_carvings[0].context = &ctx; + for (c = 0; c < psurf->nb_carvings; c++) { + tmp_carvings[c + 1] = psurf->carvings[c]; + } + ctx.nbvert = tmp_carvings[0].nb_vertices; + ctx.two_pi_over_nbvert = 2 * PI / (double)ctx.nbvert; + ctx.radius = shape->quadric.data.hemisphere.radius; + tmp_carvings_count = psurf->nb_carvings + 1; + ((struct ssol_punched_surface*)psurf)->carvings = tmp_carvings; + ((struct ssol_punched_surface*)psurf)->nb_carvings = tmp_carvings_count; + } + else { + tmp_carvings = psurf->carvings; + tmp_carvings_count = psurf->nb_carvings; + } + + carvings_compute_aabb(tmp_carvings, tmp_carvings_count, lower, upper); if(aabb_is_degenerated(lower, upper)) { log_error(shape->dev, "%s: infinite or null punched surface.\n", @@ -1380,22 +1440,6 @@ ssol_punched_surface_setup goto error; } - /* Hemispheres are special quadrics as they are not defined everywhere. - * As a results, we have to check that all the clipped region is inside - * the disk defined by radius */ - if(psurf->quadric->type == SSOL_QUADRIC_HEMISPHERE) { - if ( - fabs(lower[0]) >= psurf->quadric->data.hemisphere.radius - || fabs(lower[1]) >= psurf->quadric->data.hemisphere.radius - || fabs(upper[0]) >= psurf->quadric->data.hemisphere.radius - || fabs(upper[1]) >= psurf->quadric->data.hemisphere.radius - ) - { - res = RES_BAD_ARG; - goto error; - } - } - /* Setup internal data */ priv_quadric_data_setup(&shape->priv_quadric, psurf->quadric); @@ -1411,7 +1455,7 @@ ssol_punched_surface_setup if(res != RES_OK) goto error; res = clip_triangulated_plane - (&coords, &ids, shape->dev->scpr_mesh, psurf->carvings, psurf->nb_carvings); + (&coords, &ids, shape->dev->scpr_mesh, tmp_carvings, tmp_carvings_count); if(res != RES_OK) goto error; /* Setup the Star-3D shape to ray-trace */ @@ -1425,6 +1469,9 @@ ssol_punched_surface_setup if(res != RES_OK) goto error; exit: + if(tmp_carvings && tmp_carvings != psurf->carvings) { + MEM_RM(shape->dev->allocator, tmp_carvings); + } darray_double_release(&coords); darray_size_t_release(&ids); return res;