commit 2d88b9297ff2e0b60079e844c4f24306a7c50e14
parent 6bcdc78bd3d4a622aadb501e95808c34c3659493
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 9 Nov 2015 09:50:25 +0100
Optimise the generation of the super shape mesh
The sinus and cosine of the theta/phi angles are precomputed and stored
into the mesh and indexed by the indices of the theta/phi angles.
Diffstat:
3 files changed, 112 insertions(+), 69 deletions(-)
diff --git a/src/schiff_geometry.c b/src/schiff_geometry.c
@@ -141,9 +141,7 @@ static void
super_shape_get_position(const unsigned ivert, float vertex[3], void* ctx)
{
struct geometry_context* geom = ctx;
- float angles[2];
- double cos_angles[2];
- double sin_angles[2];
+ struct sin_cos angles[2];
double uv[2];
int iform;
ASSERT(geom && geom->type == SCHIFF_SUPER_SHAPE);
@@ -154,21 +152,17 @@ super_shape_get_position(const unsigned ivert, float vertex[3], void* ctx)
double m, k, g;
double* form = geom->data.super_shape.formulas[iform];
- m = cos(form[M] * angles[iform] / 4.0);
+ m = cos(form[M] * angles[iform].angle / 4.0);
m = fabs(m) / form[A];
- k = sin(form[M] * angles[iform] / 4.0);
+ k = sin(form[M] * angles[iform].angle / 4.0);
k = fabs(k) / form[B];
g = pow(m, form[N1]) + pow(k, form[N2]);
uv[iform] = pow(g, (-1.0/form[N0]));
-
- cos_angles[iform] = cos(angles[iform]);
- sin_angles[iform] = sin(angles[iform]);
}
- vertex[0] = (float)(uv[0] * cos_angles[0] * uv[1] * cos_angles[1]);
- vertex[1] = (float)(uv[0] * sin_angles[0] * uv[1] * cos_angles[1]);
- vertex[2] = (float)(uv[1] * sin_angles[1]);
-
+ vertex[0] = (float)(uv[0] * angles[0].cosine * uv[1] * angles[1].cosine);
+ vertex[1] = (float)(uv[0] * angles[0].sinus * uv[1] * angles[1].cosine);
+ vertex[2] = (float)(uv[1] * angles[1].sinus);
}
static res_T
@@ -202,7 +196,7 @@ geometry_sample_cylinder
mtl->get_property = get_material_property;
mtl->material = distrib->properties;
- nverts = darray_float_size_get(&distrib->mesh->vertices) / 3/*#coords*/;
+ nverts = darray_float_size_get(&distrib->mesh->vertices.cartesian) / 3/*#coords*/;
nprims = darray_uint_size_get(&distrib->mesh->indices) / 3/*#indices per prim*/;
return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims,
@@ -235,7 +229,7 @@ geometry_sample_sphere
mtl->get_property = get_material_property;
mtl->material = distrib->properties;
- nverts = darray_float_size_get(&distrib->mesh->vertices) / 3/*#coords*/;
+ nverts = darray_float_size_get(&distrib->mesh->vertices.cartesian) / 3/*#coords*/;
nprims = darray_uint_size_get(&distrib->mesh->indices) / 3/*#indices*/;
return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims,
@@ -287,7 +281,7 @@ geometry_sample_super_shape
mtl->get_property = get_material_property;
mtl->material = distrib->properties;
- nverts = darray_float_size_get(&distrib->mesh->vertices) / 2/*#theta/phi*/;
+ nverts = darray_uint_size_get(&distrib->mesh->vertices.polar) / 2/*#theta/phi*/;
nprims = darray_uint_size_get(&distrib->mesh->indices) / 3/*#indices*/;
return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims,
diff --git a/src/schiff_mesh.c b/src/schiff_mesh.c
@@ -31,12 +31,6 @@
#include <rsys/float2.h>
#include <rsys/float3.h>
-struct sin_cos { double sinus, cosine; };
-
-#define DARRAY_NAME sincos
-#define DARRAY_DATA struct sin_cos
-#include <rsys/dynamic_array.h>
-
/*******************************************************************************
* Helper functions
******************************************************************************/
@@ -98,8 +92,6 @@ schiff_mesh_init_sphere
const unsigned nphis = (unsigned)(((double)nthetas + 0.5) / 2.0);
const double step_theta = 2*PI / (double)nthetas;
const double step_phi = PI / (double)nphis;
- struct darray_sincos sincos_thetas;
- struct darray_sincos sincos_phis;
size_t nverts;
size_t ntris;
size_t i;
@@ -108,56 +100,59 @@ schiff_mesh_init_sphere
ASSERT(allocator && sphere && nthetas);
sphere->coordinates = SCHIFF_CARTESIAN;
- darray_float_init(allocator, &sphere->vertices);
+ darray_float_init(allocator, &sphere->vertices.cartesian);
darray_uint_init(allocator, &sphere->indices);
- darray_sincos_init(allocator, &sincos_thetas);
- darray_sincos_init(allocator, &sincos_phis);
+ darray_sincos_init(allocator, &sphere->thetas);
+ darray_sincos_init(allocator, &sphere->phis);
nverts = nthetas*(nphis-1)/* #contour verts */ + 2/* polar verts */;
ntris = 2*nthetas*(nphis-2)/* #contour tris */ + 2*nthetas/* #polar tris */;
- res = darray_float_resize(&sphere->vertices, nverts * 3/*#coords per vert*/);
+ res = darray_float_resize(&sphere->vertices.cartesian, nverts * 3/*#coords*/);
if(res != RES_OK) goto error;
res = darray_uint_resize(&sphere->indices, ntris * 3/*#indices per tri*/);
if(res != RES_OK) goto error;
- res = darray_sincos_resize(&sincos_thetas, nthetas);
+ res = darray_sincos_resize(&sphere->thetas, nthetas);
if(res != RES_OK) goto error;
- res = darray_sincos_resize(&sincos_phis, nphis);
+ res = darray_sincos_resize(&sphere->phis, nphis);
if(res != RES_OK) goto error;
/* Precompute the cosine/sinus of the theta/phi angles */
FOR_EACH(itheta, 0, nthetas) {
const double theta = -PI + (double)itheta * step_theta;
- darray_sincos_data_get(&sincos_thetas)[itheta].sinus = sin(theta);
- darray_sincos_data_get(&sincos_thetas)[itheta].cosine = cos(theta);
+ darray_sincos_data_get(&sphere->thetas)[itheta].angle = theta;
+ darray_sincos_data_get(&sphere->thetas)[itheta].sinus = (float)sin(theta);
+ darray_sincos_data_get(&sphere->thetas)[itheta].cosine = (float)cos(theta);
}
FOR_EACH(iphi, 0, nphis-1) {
const double phi = -PI/2 + (double)(iphi + 1) * step_phi;
- darray_sincos_data_get(&sincos_phis)[iphi].sinus = sin(phi);
- darray_sincos_data_get(&sincos_phis)[iphi].cosine = cos(phi);
+ darray_sincos_data_get(&sphere->phis)[iphi].angle = (float)phi;
+ darray_sincos_data_get(&sphere->phis)[iphi].sinus = (float)sin(phi);
+ darray_sincos_data_get(&sphere->phis)[iphi].cosine = (float)cos(phi);
}
/* Build the contour vertices */
i = 0;
FOR_EACH(itheta, 0, nthetas) {
- const struct sin_cos* theta = darray_sincos_data_get(&sincos_thetas) + itheta;
+ const struct sin_cos* theta = darray_sincos_data_get(&sphere->thetas) + itheta;
FOR_EACH(iphi, 0, nphis-1) {
- const struct sin_cos* phi = darray_sincos_data_get(&sincos_phis) + iphi;
- darray_float_data_get(&sphere->vertices)[i++] = (float)(theta->cosine * phi->cosine);
- darray_float_data_get(&sphere->vertices)[i++] = (float)(theta->sinus * phi->cosine);
- darray_float_data_get(&sphere->vertices)[i++] = (float)phi->sinus;
+ const struct sin_cos* phi = darray_sincos_data_get(&sphere->phis) + iphi;
+ darray_float_data_get(&sphere->vertices.cartesian)[i++] =
+ (float)(theta->cosine * phi->cosine);
+ darray_float_data_get(&sphere->vertices.cartesian)[i++] =
+ (float)(theta->sinus * phi->cosine);
+ darray_float_data_get(&sphere->vertices.cartesian)[i++] =
+ (float)phi->sinus;
}
}
/* Setup polar vertices */
- f3(darray_float_data_get(&sphere->vertices) + i + 0, 0.f, 0.f,-1.f);
- f3(darray_float_data_get(&sphere->vertices) + i + 3, 0.f, 0.f, 1.f);
+ f3(darray_float_data_get(&sphere->vertices.cartesian) + i+0, 0.f, 0.f,-1.f);
+ f3(darray_float_data_get(&sphere->vertices.cartesian) + i+3, 0.f, 0.f, 1.f);
/* Define the indices of the sphere */
setup_sphere_indices(&sphere->indices, nthetas, nphis);
exit:
- darray_sincos_release(&sincos_thetas);
- darray_sincos_release(&sincos_phis);
return res;
error:
schiff_mesh_release(sphere);
@@ -182,30 +177,58 @@ schiff_mesh_init_sphere_polar
ASSERT(allocator && sphere && nthetas);
sphere->coordinates = SCHIFF_POLAR;
- darray_float_init(allocator, &sphere->vertices);
+ darray_uint_init(allocator, &sphere->vertices.polar);
darray_uint_init(allocator, &sphere->indices);
+ darray_sincos_init(allocator, &sphere->thetas);
+ darray_sincos_init(allocator, &sphere->phis);
nverts = nthetas*(nphis-1)/* #contour verts */ + 2/* polar verts */;
ntris = 2*nthetas*(nphis-2)/* #contour tris */ + 2*nthetas/* #polar tris */;
- res = darray_float_resize(&sphere->vertices, nverts * 2/* theta phi*/);
+ res = darray_uint_resize(&sphere->vertices.polar, nverts * 2/* theta phi*/);
if(res != RES_OK) goto error;
res = darray_uint_resize(&sphere->indices, ntris * 3/*#indices per tri*/);
if(res != RES_OK) goto error;
+ res = darray_sincos_resize(&sphere->thetas, nthetas);
+ if(res != RES_OK) goto error;
+ res = darray_sincos_resize(&sphere->phis, nphis + 1/*Polar*/);
+ if(res != RES_OK) goto error;
+
+ /* Cosine/Sinus of the theta/phi contour angles */
+ FOR_EACH(itheta, 0, nthetas) {
+ const double theta = -PI + (double)itheta * step_theta;
+ darray_sincos_data_get(&sphere->thetas)[itheta].angle = theta;
+ darray_sincos_data_get(&sphere->thetas)[itheta].sinus = (float)sin(theta);
+ darray_sincos_data_get(&sphere->thetas)[itheta].cosine = (float)cos(theta);
+ }
+ FOR_EACH(iphi, 0, nphis-1) {
+ const double phi = -PI/2 + (double)(iphi + 1) * step_phi;
+ darray_sincos_data_get(&sphere->phis)[iphi].angle = (float)phi;
+ darray_sincos_data_get(&sphere->phis)[iphi].sinus = (float)sin(phi);
+ darray_sincos_data_get(&sphere->phis)[iphi].cosine = (float)cos(phi);
+ }
+
+ /* Cosine/Sinus of the theta/phi polar angles */
+ darray_sincos_data_get(&sphere->phis)[nphis-1].angle =-(float)PI/2;
+ darray_sincos_data_get(&sphere->phis)[nphis-1].sinus =-1.f;
+ darray_sincos_data_get(&sphere->phis)[nphis-1].cosine = 0.f;
+ darray_sincos_data_get(&sphere->phis)[nphis-0].angle = (float)PI/2;
+ darray_sincos_data_get(&sphere->phis)[nphis-0].sinus = 1.f;
+ darray_sincos_data_get(&sphere->phis)[nphis-0].cosine = 0.f;
/* Build the contour vertices */
i = 0;
FOR_EACH(itheta, 0, nthetas) {
- const double theta = -PI + (double)itheta * step_theta;
FOR_EACH(iphi, 0, nphis-1) {
- const double phi = -PI/2 + (double)(iphi + 1) * step_phi;
- darray_float_data_get(&sphere->vertices)[i++] = (float)theta;
- darray_float_data_get(&sphere->vertices)[i++] = (float)phi;
+ darray_uint_data_get(&sphere->vertices.polar)[i++] = itheta;
+ darray_uint_data_get(&sphere->vertices.polar)[i++] = iphi;
}
}
/* Setup polar vertices */
- f2(darray_float_data_get(&sphere->vertices) + i+0,-(float)PI,-(float)PI/2.0);
- f2(darray_float_data_get(&sphere->vertices) + i+2, (float)PI, (float)PI/2.0);
+ darray_uint_data_get(&sphere->vertices.polar)[i++] = 0;
+ darray_uint_data_get(&sphere->vertices.polar)[i++] = nphis-1;
+ darray_uint_data_get(&sphere->vertices.polar)[i++] = 0;
+ darray_uint_data_get(&sphere->vertices.polar)[i++] = nphis-0;
/* Define the indices of the sphere */
setup_sphere_indices(&sphere->indices, nthetas, nphis);
@@ -231,13 +254,13 @@ schiff_mesh_init_cylinder
ASSERT(allocator && cylinder && nsteps);
cylinder->coordinates = SCHIFF_CARTESIAN;
- darray_float_init(allocator, &cylinder->vertices);
+ darray_float_init(allocator, &cylinder->vertices.cartesian);
darray_uint_init(allocator, &cylinder->indices);
nverts = nsteps*2/* #contour verts */ + 2/* #polar verts */;
ntris = nsteps*2/* #contour tris */ + 2*nsteps/* #caop tris */;
- res = darray_float_resize(&cylinder->vertices, nverts*3/*#coords per vert*/);
+ res = darray_float_resize(&cylinder->vertices.cartesian, nverts*3/*#coords*/);
if(res != RES_OK) goto error;
res = darray_uint_resize(&cylinder->indices, ntris*3/*#indices per tri*/);
if(res != RES_OK) goto error;
@@ -247,13 +270,13 @@ schiff_mesh_init_cylinder
const float theta = (float)(i* step);
const float x = (float)cos(theta);
const float y = (float)sin(theta);
- f3(darray_float_data_get(&cylinder->vertices) + (i*2 + 0)*3, x, y, 0.f);
- f3(darray_float_data_get(&cylinder->vertices) + (i*2 + 1)*3, x, y, 1.f);
+ f3(darray_float_data_get(&cylinder->vertices.cartesian)+(i*2+0)*3, x,y,0);
+ f3(darray_float_data_get(&cylinder->vertices.cartesian)+(i*2+1)*3, x,y,1);
}
/* "Polar" vertices */
- f3(darray_float_data_get(&cylinder->vertices) + (i*2 + 0)*3, 0.f, 0.f, 0.f);
- f3(darray_float_data_get(&cylinder->vertices) + (i*2 + 1)*3, 0.f, 0.f, 1.f);
+ f3(darray_float_data_get(&cylinder->vertices.cartesian)+(i*2+0)*3, 0,0,0);
+ f3(darray_float_data_get(&cylinder->vertices.cartesian)+(i*2+1)*3, 0,0,1);
/* Contour primitives */
FOR_EACH(i, 0, nsteps) {
@@ -297,7 +320,17 @@ void
schiff_mesh_release(struct schiff_mesh* mesh)
{
ASSERT(mesh);
- darray_float_release(&mesh->vertices);
+ switch(mesh->coordinates) {
+ case SCHIFF_CARTESIAN:
+ darray_float_release(&mesh->vertices.cartesian);
+ break;
+ case SCHIFF_POLAR:
+ darray_uint_release(&mesh->vertices.polar);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
darray_uint_release(&mesh->indices);
+ darray_sincos_release(&mesh->thetas);
+ darray_sincos_release(&mesh->phis);
}
diff --git a/src/schiff_mesh.h b/src/schiff_mesh.h
@@ -32,15 +32,28 @@
#include <rsys/dynamic_array_float.h>
#include <rsys/dynamic_array_uint.h>
+struct sin_cos { double angle, sinus, cosine; };
+
+#define DARRAY_NAME sincos
+#define DARRAY_DATA struct sin_cos
+#include <rsys/dynamic_array.h>
+
enum schiff_coordinates {
SCHIFF_POLAR,
SCHIFF_CARTESIAN
};
struct schiff_mesh {
- struct darray_float vertices;
- struct darray_uint indices;
enum schiff_coordinates coordinates;
+ union {
+ struct darray_float cartesian;
+ struct darray_uint polar;
+ } vertices;
+ struct darray_uint indices;
+
+ /* Used only by polar coordinates */
+ struct darray_sincos thetas; /* List of thetas, cos(theta) , sin(theta) */
+ struct darray_sincos phis; /* List of phis, cos(phi), sin(phi) */
};
extern LOCAL_SYM res_T
@@ -88,25 +101,28 @@ schiff_mesh_get_cartesian_position
{
const size_t i = ivert * 3;
ASSERT(mesh && vertex && mesh->coordinates == SCHIFF_CARTESIAN);
- ASSERT(darray_float_size_get(&mesh->vertices) % 3 == 0);
- ASSERT(ivert < darray_float_size_get(&mesh->vertices) / 3);
- vertex[0] = darray_float_data_get(&mesh->vertices)[i + 0];
- vertex[1] = darray_float_data_get(&mesh->vertices)[i + 1];
- vertex[2] = darray_float_data_get(&mesh->vertices)[i + 2];
+ ASSERT(darray_float_size_get(&mesh->vertices.cartesian) % 3 == 0);
+ ASSERT(ivert < darray_float_size_get(&mesh->vertices.cartesian) / 3);
+ vertex[0] = darray_float_data_get(&mesh->vertices.cartesian)[i + 0];
+ vertex[1] = darray_float_data_get(&mesh->vertices.cartesian)[i + 1];
+ vertex[2] = darray_float_data_get(&mesh->vertices.cartesian)[i + 2];
}
static INLINE void
schiff_mesh_get_polar_position
(struct schiff_mesh* mesh,
const unsigned ivert,
- float angles[2]) /* theta, phi */
+ struct sin_cos angles[2])
{
const size_t i = ivert * 2;
+ const unsigned* iangles;
ASSERT(mesh && angles && mesh->coordinates == SCHIFF_POLAR);
- ASSERT(darray_float_size_get(&mesh->vertices) % 2 == 0);
- ASSERT(ivert < darray_float_size_get(&mesh->vertices) / 2);
- angles[0] = darray_float_data_get(&mesh->vertices)[i + 0];
- angles[1] = darray_float_data_get(&mesh->vertices)[i + 1];
+ ASSERT(darray_uint_size_get(&mesh->vertices.polar) % 2 == 0);
+ ASSERT(ivert < darray_uint_size_get(&mesh->vertices.polar) / 2);
+
+ iangles = darray_uint_cdata_get(&mesh->vertices.polar) + i;
+ angles[0] = darray_sincos_data_get(&mesh->thetas)[iangles[0]];
+ angles[1] = darray_sincos_data_get(&mesh->phis)[iangles[1]];
}
#endif /* SBOX_SCHIFF_MESH_H */