commit f2f579aa001224a42e8f2c5c442fd7855e536c8d
parent 5a91dc71a08d1b4f6d6eb01fe451edebd0877241
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Sun, 20 Mar 2016 10:53:33 +0100
Internally add the ellipsoid distribution
Add the support of the ellipsoid schiff geometry (not debugged yet).
This distribution is not handled by the schiff-geometry YAML file
format.
Diffstat:
2 files changed, 106 insertions(+), 1 deletion(-)
diff --git a/src/schiff_geometry.c b/src/schiff_geometry.c
@@ -37,6 +37,20 @@
#include <star/ssp.h>
#include <star/sschiff.h>
+/* 3D Context of an ellipsoid */
+struct ellipsoid_context {
+ /* Precomputed values used to define the radius of the ellipsoid for a
+ * {theta, phi} position :
+ * r = (a*b*c)
+ * / sqrt(b^2*c^2*cos(theta)^2*cos(phi)^2
+ * + a^2*c^2*sin(theta)^2*cos(phi)^2
+ * + a^2*b^2*sin(phi)^2) */
+ double abc; /* a*b*c */
+ double b2c2; /* b^2*c^2 */
+ double a2c2; /* a^2*c^2 */
+ double a2b2; /* a^2*b^2 */
+};
+
/* 3D Context of the sphere geometry */
struct sphere_context {
float radius; /* Sphere radius */
@@ -66,6 +80,7 @@ struct mesh_context {
const struct schiff_geometry* geometry;
enum schiff_geometry_type type;
union {
+ struct ellipsoid_context ellipsoid;
struct cylinder_context cylinder;
struct sphere_context sphere;
struct super_shape_context super_shape;
@@ -172,6 +187,35 @@ geometry_get_indices(const unsigned itri, unsigned ids[3], void* ctx)
}
static void
+ellipsoid_get_position(const unsigned ivert, float vertex[3], void* ctx)
+{
+ struct mesh_context* mesh_ctx = ctx;
+ struct sin_cos angles[2];
+ double sqr_cos_theta;
+ double sqr_cos_phi;
+ double sqr_sin_theta;
+ double sqr_sin_phi;
+ double radius;
+ double tmp;
+ ASSERT(mesh_ctx && mesh_ctx->type == SCHIFF_ELLIPSOID);
+
+ schiff_mesh_get_polar_position(mesh_ctx->mesh, ivert, angles);
+ sqr_cos_theta = angles[0].cosine * angles[0].cosine;
+ sqr_sin_theta = angles[0].sinus * angles[0].sinus;
+ sqr_cos_phi = angles[1].cosine * angles[1].cosine;
+ sqr_sin_phi = angles[1].sinus * angles[1].sinus;
+
+ tmp = mesh_ctx->data.ellipsoid.b2c2 * sqr_cos_theta * sqr_cos_phi
+ + mesh_ctx->data.ellipsoid.a2c2 * sqr_sin_theta * sqr_cos_phi
+ + mesh_ctx->data.ellipsoid.a2b2 * sqr_sin_phi;
+ radius = mesh_ctx->data.ellipsoid.abc / sqrt(tmp);
+
+ vertex[0] = (float)(angles[0].cosine * angles[1].cosine * radius);
+ vertex[1] = (float)(angles[0].sinus * angles[1].cosine * radius);
+ vertex[2] = (float)(angles[1].sinus * radius);
+}
+
+static void
cylinder_get_position(const unsigned ivert, float vertex[3], void* ctx)
{
struct mesh_context* mesh_ctx = ctx;
@@ -222,6 +266,48 @@ super_shape_get_position(const unsigned ivert, float vertex[3], void* ctx)
}
static res_T
+geometry_sample_ellipsoid
+ (struct ssp_rng* rng,
+ const struct schiff_geometry* geom,
+ const struct schiff_mesh* mesh,
+ struct s3d_shape* shape)
+{
+ const struct schiff_ellipsoid* ellipsoid;
+ struct mesh_context mesh_ctx;
+ struct s3d_vertex_data attrib;
+ double a, b, c, a2, b2, c2;
+ size_t nverts, nprims;
+ ASSERT(rng && geom && mesh && shape);
+ ASSERT(geom->type == SCHIFF_ELLIPSOID);
+
+ ellipsoid = &geom->data.ellipsoid;
+
+ a = eval_param(&ellipsoid->a, rng);
+ b = eval_param(&ellipsoid->b, rng);
+ c = eval_param(&ellipsoid->c, rng);
+ a2 = a*a;
+ b2 = b*b;
+ c2 = c*c;
+
+ mesh_ctx.mesh = mesh;
+ mesh_ctx.type = SCHIFF_ELLIPSOID;
+ mesh_ctx.data.ellipsoid.abc = a*b*c;
+ mesh_ctx.data.ellipsoid.b2c2 = b2*c2;
+ mesh_ctx.data.ellipsoid.a2c2 = a2*c2;
+ mesh_ctx.data.ellipsoid.a2b2 = a2*b2;
+
+ attrib.usage = S3D_POSITION;
+ attrib.type = S3D_FLOAT3;
+ attrib.get = ellipsoid_get_position;
+
+ nverts = darray_uint_size_get(&mesh->vertices.polar) / 2/*#theta/phi*/;
+ nprims = darray_uint_size_get(&mesh->indices) / 3/*#indices*/;
+
+ return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims,
+ geometry_get_indices, (unsigned)nverts, &attrib, 1, &mesh_ctx);
+}
+
+static res_T
geometry_sample_cylinder
(struct ssp_rng* rng,
const struct schiff_geometry* geom,
@@ -348,6 +434,9 @@ geometry_sample
mesh = distrib->meshes + isamp;
switch(geom->type) {
+ case SCHIFF_ELLIPSOID:
+ res = geometry_sample_ellipsoid(rng, geom, mesh, shape);
+ break;
case SCHIFF_CYLINDER:
case SCHIFF_CYLINDER_AS_SPHERE:
res = geometry_sample_cylinder(rng, geom, mesh, shape);
@@ -430,6 +519,10 @@ schiff_geometry_distribution_init
/* Generate the mesh template and setup its distribution context */
switch(geoms[i].type) {
+ case SCHIFF_ELLIPSOID:
+ res = schiff_mesh_init_sphere_polar(&mem_default_allocator,
+ &ctx->meshes[i], geoms[i].data.ellipsoid.nslices);
+ break;
case SCHIFF_CYLINDER:
case SCHIFF_CYLINDER_AS_SPHERE:
res = schiff_mesh_init_cylinder(&mem_default_allocator, &ctx->meshes[i],
diff --git a/src/schiff_geometry.h b/src/schiff_geometry.h
@@ -50,6 +50,7 @@ struct schiff_param {
#define SCHIFF_PARAM_DEFAULT__ {SCHIFF_PARAM_CONSTANT, {1.0}}
enum schiff_geometry_type {
+ SCHIFF_ELLIPSOID,
SCHIFF_CYLINDER,
SCHIFF_CYLINDER_AS_SPHERE, /* The cylinder volume is control by a sphere */
SCHIFF_SPHERE,
@@ -57,6 +58,16 @@ enum schiff_geometry_type {
SCHIFF_NONE
};
+struct schiff_ellipsoid {
+ struct schiff_param a;
+ struct schiff_param b;
+ struct schiff_param c;
+ unsigned nslices;
+};
+
+#define SCHIFF_ELLIPSOID_DEFAULT__ \
+ {SCHIFF_PARAM_DEFAULT__, SCHIFF_PARAM_DEFAULT__, SCHIFF_PARAM_DEFAULT__, 64}
+
struct schiff_sphere {
struct schiff_param radius;
unsigned nslices;
@@ -104,13 +115,14 @@ static const struct schiff_super_shape SCHIFF_SUPER_SHAPE_DEFAULT =
struct schiff_geometry {
enum schiff_geometry_type type;
union {
+ struct schiff_ellipsoid ellipsoid;
struct schiff_cylinder cylinder;
struct schiff_sphere sphere;
struct schiff_super_shape super_shape;
} data;
};
-#define SCHIFF_GEOMETRY_NULL__ { SCHIFF_NONE, { SCHIFF_CYLINDER_DEFAULT__ } }
+#define SCHIFF_GEOMETRY_NULL__ { SCHIFF_NONE, { SCHIFF_ELLIPSOID_DEFAULT__ } }
static const struct schiff_geometry SCHIFF_GEOMETRY_NULL =
SCHIFF_GEOMETRY_NULL__;