diff options
author | Ian Romanick <idr@freedesktop.org> | 2010-02-15 15:11:11 -0800 |
---|---|---|
committer | Ian Romanick <idr@freedesktop.org> | 2010-02-15 15:11:11 -0800 |
commit | a37f465e38fc8c1f0855e09ab551efd319e8365b (patch) | |
tree | f4578ddc2f8f9b5d5c2513657793a5d01198eae2 | |
parent | cc3b0f133fd76fe9822080976533bcf642b9414f (diff) |
Add generic routines to generate surfaces of revolution.
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/revolve.c | 116 | ||||
-rw-r--r-- | src/revolve.h | 72 | ||||
-rw-r--r-- | src/system.h | 19 |
4 files changed, 208 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 6230523..b84e560 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ AM_CXXFLAGS=-I../include AM_CFLAGS=-I../include lib_LIBRARIES = libGLU3.a -libGLU3_a_SOURCES = matrix.c load_text.c arcball.c +libGLU3_a_SOURCES = matrix.c load_text.c arcball.c revolve.c libGLU3includedir = ${includedir} libGLU3include_HEADERS = ../include/glu3.h ../include/glu3_scalar.h diff --git a/src/revolve.c b/src/revolve.c new file mode 100644 index 0000000..ff41029 --- /dev/null +++ b/src/revolve.c @@ -0,0 +1,116 @@ +/* + * Copyright © 2010 Ian D. Romanick + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "revolve.h" + +void +revolve(const GLUvec4 *points, const GLUvec4 *normals, const float *u, + unsigned num_points, + const GLUvec4 *axis, + unsigned steps, float start_angle, float end_angle, + revolve_cb *cb, void *data) +{ + const float angle_step = (end_angle - start_angle) / (float) steps; + const GLUvec4 tangent = {{ 0.0, 0.0, 1.0, 0.0 }}; + unsigned i; + unsigned j; + + + for (i = 0; i < steps; i++) { + const float a = start_angle + (angle_step * i); + const float v = i / (steps - 1); + GLUmat4 r; + + /* Generate a rotation matrix to rotate the position and the + * normal around the axis by the current angular step. This + * generates the new position and normal. + */ + gluRotate4v(& r, axis, a); + + for (j = 0; j < num_points; j++) { + GLUvec4 p; + GLUvec4 n; + GLUvec4 t; + GLUvec4 uv; + + gluMult4m_4v(& p, & r, & points[j]); + gluMult4m_4v(& n, & r, & normals[j]); + gluMult4m_4v(& t, & r, & tangent); + + uv.values[0] = u[j]; + uv.values[1] = v; + uv.values[2] = 0.0; + uv.values[3] = 0.0; + + (*cb)(data, & p, & n, & t, & uv); + } + } +} + + +void +generate_sphere(double radius, unsigned slices, unsigned stacks, + _Bool normals_point_out, + revolve_cb *cb, void *data) +{ + const GLUvec4 y_axis = {{ 0.0, 1.0, 0.0, 0.0 }}; + GLUvec4 *positions; + GLUvec4 *normals; + float *u; + double latitude_step; + unsigned i; + + positions = (GLUvec4 *) malloc((2 * sizeof(GLUvec4) + sizeof(float)) + * (stacks + 1)); + normals = positions + (stacks + 1); + u = (float *)(normals + (stacks + 1)); + + latitude_step = M_PI / (double)(stacks); + for (i = 0; i < (stacks + 1); i++) { + const double latitude = latitude_step * i; + + normals[i].values[0] = sin(latitude); + normals[i].values[1] = cos(latitude); + normals[i].values[2] = 0.0; + normals[i].values[3] = 0.0; + + gluMult4v_f(& positions[i], + & normals[i], + radius); + positions[i].values[3] = 1.0; + + u[i] = (float) i / (float) stacks; + + if (!normals_point_out) { + normals[i].values[0] = -normals[i].values[0]; + normals[i].values[1] = -normals[i].values[1]; + } + } + + /* Note the rotation is *from* 2pi *to* 0. The counter-clockwise + * rotation ensures that the vertices are generated in the correct + * order to be drawn using triangle strips with back-face culling. + */ + revolve(positions, normals, u, stacks + 1, & y_axis, + slices + 1, 2.0 * M_PI, 0.0, cb, data); +} diff --git a/src/revolve.h b/src/revolve.h new file mode 100644 index 0000000..960a50d --- /dev/null +++ b/src/revolve.h @@ -0,0 +1,72 @@ +/* + * Copyright © 2010 Ian D. Romanick + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "system.h" +#include "glu3.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef void (revolve_cb)(void *data, const GLUvec4 *position, + const GLUvec4 *normal, const GLUvec4 *tangent, + const GLUvec4 *uv); + +/** + * Generate a surface of revolution + * + * \param points Points that define the outline of the shape to be + * revolved. + * \param normals Initial per-vertex normals. + * \param u Per-vertex position in parameter-space along the u-axis. + * \param num_points Number of points in \c points, \c normals, and \c u. + * \param axis Axis around which to rotate. + * \param steps Total number of steps to rotate through. The angle of + * rotation at the first step will be \c start_angle, and + * the angle of rotation at the last step will be + * \c end_angle. + * \param start_angle Initial angle of rotation. + * \param end_angle Final angle of rotation. + * \param cb Per-vertex call-back function. + * \param data User-supplied data pointer passed to the per-vertex + * call-back function. + * + * \note + * Per-vertex tangents are generate based on the assumption that all of the + * initial vertices lie within the X-Y plane and that the axis of revolution + * also lies within the X-Y plane. + */ +extern void +revolve(const GLUvec4 *points, const GLUvec4 *normals, const float *u, + unsigned num_points, + const GLUvec4 *axis, + unsigned steps, float start_angle, float end_angle, + revolve_cb *cb, void *data); + +extern void +generate_sphere(double radius, unsigned slices, unsigned stacks, + bool normals_point_out, revolve_cb *cb, void *data); + +#ifdef __cplusplus +}; +#endif diff --git a/src/system.h b/src/system.h new file mode 100644 index 0000000..39d20d4 --- /dev/null +++ b/src/system.h @@ -0,0 +1,19 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDBOOL_H +# include <stdbool.h> +#else +# ifndef HAVE__BOOL +# ifdef __cplusplus +typedef bool _Bool; +# else +# define _Bool signed char +# endif +# endif +# define bool _Bool +# define false 0 +# define true 1 +# define __bool_true_false_are_defined 1 +#endif |