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:
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);