summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <idr@freedesktop.org>2010-02-15 15:11:11 -0800
committerIan Romanick <idr@freedesktop.org>2010-02-15 15:11:11 -0800
commita37f465e38fc8c1f0855e09ab551efd319e8365b (patch)
treef4578ddc2f8f9b5d5c2513657793a5d01198eae2
parentcc3b0f133fd76fe9822080976533bcf642b9414f (diff)
Add generic routines to generate surfaces of revolution.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/revolve.c116
-rw-r--r--src/revolve.h72
-rw-r--r--src/system.h19
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