summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <idr@freedesktop.org>2010-10-03 12:45:11 -0700
committerIan Romanick <idr@freedesktop.org>2010-10-03 12:45:11 -0700
commit17bbb83eaa0abdb0ca9978cdf0c3136376f5b42e (patch)
tree24cefc1dc97b7d729931848a9a4d08da063efffd
parentcc52e0f2f6d74ae3e24aa39ce1b1169ee82ab55a (diff)
GLUshape: Make the mesh producer publicly available
Derive GLUsphereProducer from GLUmeshProducer. This simplifies the implementation somewhat.
-rw-r--r--include/glu3.h39
-rw-r--r--src/mesh.cpp64
-rw-r--r--src/sphere.cpp105
3 files changed, 97 insertions, 111 deletions
diff --git a/include/glu3.h b/include/glu3.h
index 7613682..100cf4a 100644
--- a/include/glu3.h
+++ b/include/glu3.h
@@ -444,9 +444,42 @@ protected:
/**
+ * Shape generator that generates indices for an NxM mesh
+ *
+ * This shape producer does \b not generate any vertices. It is a utility
+ * producer that generates the indices required to render an NxM mesh.
+ */
+class GLUmeshProducer : public GLUshapeProducer {
+public:
+ /**
+ * Construct a new mesh shape generator
+ *
+ * \param rows Number of rows in the mesh
+ * \param columns Number of columns in the mesh
+ * \param width Total width of the underlying mesh
+ */
+ GLUmeshProducer(unsigned rows, unsigned columns, unsigned width)
+ : rows(rows), columns(columns), width(width)
+ {
+ /* empty */
+ }
+
+ virtual unsigned vertex_count(void) const;
+ virtual unsigned element_count(void) const;
+ virtual unsigned primitive_count(void) const;
+ virtual void generate(GLUshapeConsumer *consumer) const;
+
+protected:
+ unsigned rows;
+ unsigned columns;
+ unsigned width;
+};
+
+
+/**
* Shape generator that generates a sphere.
*/
-class GLUsphereProducer : public GLUshapeProducer {
+class GLUsphereProducer : public GLUmeshProducer {
public:
/**
* Construct a new sphere shape generator
@@ -461,14 +494,10 @@ public:
*/
GLUsphereProducer(GLdouble radius, GLint slices, GLint stacks);
virtual unsigned vertex_count(void) const;
- virtual unsigned element_count(void) const;
- virtual unsigned primitive_count(void) const;
virtual void generate(GLUshapeConsumer *consumer) const;
private:
double radius;
- unsigned slices;
- unsigned stacks;
};
diff --git a/src/mesh.cpp b/src/mesh.cpp
index 2bc04ba..c4789a2 100644
--- a/src/mesh.cpp
+++ b/src/mesh.cpp
@@ -25,55 +25,69 @@
#define Elements(a) (sizeof(a) / sizeof(a[0]))
-#define EMIT_ELT(e) \
- do { \
- elts[count] = (e); \
- count++; \
- if (count >= Elements(elts)) { \
- (*index_cb)(data, elts, count); \
- count = 0; \
- } \
+unsigned
+GLUmeshProducer::vertex_count(void) const
+{
+ return 0;
+}
+
+unsigned
+GLUmeshProducer::element_count(void) const
+{
+ return this->rows * (2 * (this->columns + 1));
+}
+
+unsigned
+GLUmeshProducer::primitive_count(void) const
+{
+ return 1;
+}
+
+#define EMIT_ELT(e) \
+ do { \
+ elts[count] = (e); \
+ count++; \
+ if (count >= Elements(elts)) { \
+ consumer->index_batch(elts, count); \
+ count = 0; \
+ } \
} while (0)
void
-generate_triangle_mesh(unsigned rows, unsigned cols, unsigned width,
- mesh_begin_cb *begin_cb,
- mesh_index_cb *index_cb,
- mesh_end_cb *end_cb,
- void *data)
+GLUmeshProducer::generate(GLUshapeConsumer *consumer) const
{
unsigned elts[64];
unsigned count = 0;
unsigned i;
int j;
- (*begin_cb)(data, GL_TRIANGLE_STRIP, rows * ((2 * cols) + 1));
- for (i = 0; i < rows; i++) {
+ consumer->begin_primitive(GL_TRIANGLE_STRIP, this->element_count());
+ for (i = 0; i < this->rows; i++) {
if ((i & 1) == 0) {
- for (j = 0; j < (int)cols; j++) {
- const unsigned e0 = ((i + 0) * width) + j;
- const unsigned e1 = ((i + 1) * width) + j;
+ for (j = 0; j < (int)this->columns; j++) {
+ const unsigned e0 = ((i + 0) * this->width) + j;
+ const unsigned e1 = ((i + 1) * this->width) + j;
EMIT_ELT(e0);
EMIT_ELT(e1);
}
- EMIT_ELT((width - 1) + ((i + 0) * width));
+ EMIT_ELT((this->width - 1) + ((i + 0) * this->width));
} else {
- for (j = cols - 1; j >= 0; j--) {
- const unsigned e0 = ((i + 0) * width) + j;
- const unsigned e1 = ((i + 1) * width) + j;
+ for (j = this->columns - 1; j >= 0; j--) {
+ const unsigned e0 = ((i + 0) * this->width) + j;
+ const unsigned e1 = ((i + 1) * this->width) + j;
EMIT_ELT(e0);
EMIT_ELT(e1);
}
- EMIT_ELT((i + 0) * width);
+ EMIT_ELT((i + 0) * this->width);
}
}
if (count != 0)
- (*index_cb)(data, elts, count);
+ consumer->index_batch(elts, count);
- (*end_cb)(data);
+ consumer->end_primitive();
}
diff --git a/src/sphere.cpp b/src/sphere.cpp
index fafcb86..1c529b8 100644
--- a/src/sphere.cpp
+++ b/src/sphere.cpp
@@ -25,37 +25,30 @@
#include "mesh.h"
/**
- * \name Call-back functions for sphere generation routine
+ * Call-back function for sphere generation routine
*/
-/*@{*/
static void sphere_revolve_cb(void *data,
const GLUvec4 *position,
const GLUvec4 *normal,
const GLUvec4 *tangent,
- const GLUvec4 *uv);
-
-static void sphere_begin_cb(void *data, GLenum mode, unsigned count);
-
-static void sphere_index_cb(void *data, const unsigned *index, unsigned count);
-
-static void sphere_end_cb(void *data);
-/*@}*/
+ const GLUvec4 *uv,
+ unsigned count);
/**
* GLUsphereProducer decorator to implement call-backs
*
* To generate the sphere data, the \c GLUsphereProducer class interfaces with
- * various C functions that use a call-back mechanism. These call-backs are
- * analogous the \c emit_vertex, \c emit_begin, \c emit_index, and \c emit_end
- * methods that \c GLUsphereProducer subclasses will provide.
+ * a C functions that uses a call-back mechanism. This call-backs is
+ * analogous to \c vertex_batch method that \c GLUshapeConsumer subclasses
+ * will provide.
*
- * However, these methods are all \c protected. As a result the non-class
- * call-back functions cannot call these methods unless they are \c friend
- * functions. It is undesireable to expose the implementation detail in the
- * application-facing header file. This can be worked around by creating a
- * dummy subclass of \c GLUsphereProducer that only contains the \c friend
- * function declarations. Pointers to \c GLUsphereProducer objects can be
- * cast to pointers to \c GLUsphereFriend objects without side-effect.
+ * However, this method is \c protected. As a result the non-class call-back
+ * functions cannot call this method unless it is a \c friend function. It is
+ * undesireable to expose this implementation detail in the application-facing
+ * header file. This can be worked around by creating a dummy subclass of \c
+ * GLUshapeConsumer that only contains the \c friend function declaration.
+ * Pointers to \c GLUshapeConsumer objects can be cast to pointers to
+ * \c GLUconsumerFriend objects without side-effect.
*
* This is arguably a mis-use of the "decorator" pattern, but it is the most
* efficient way to do this.
@@ -65,22 +58,19 @@ class GLUconsumerFriend : public GLUshapeConsumer {
const GLUvec4 *position,
const GLUvec4 *normal,
const GLUvec4 *tangent,
- const GLUvec4 *uv);
-
- friend void sphere_begin_cb(void *data, GLenum mode, unsigned count);
-
- friend void sphere_index_cb(void *data, unsigned index);
-
- friend void sphere_end_cb(void *data);
+ const GLUvec4 *uv,
+ unsigned count);
};
GLUsphereProducer::GLUsphereProducer(GLdouble radius, GLint slices,
GLint stacks)
+ : GLUmeshProducer(slices, stacks + 1, stacks + 1)
{
this->radius = radius;
- this->slices = (slices < 4) ? 4 : (unsigned) slices;
- this->stacks = (stacks < 4) ? 4 : (unsigned) stacks;
+ this->rows = (slices < 4) ? 4 : (unsigned) slices;
+ this->columns = (stacks < 3) ? 4 : (unsigned) (stacks + 1);
+ this->width = this->columns;
}
@@ -91,24 +81,8 @@ GLUsphereProducer::vertex_count(void) const
* of (stacks+1) vertices. There are a total of (slices+1) of these
* lines of vertices.
*/
- return (slices + 1) * (stacks + 1);
-}
-
-
-unsigned
-GLUsphereProducer::primitive_count(void) const
-{
- return 1;
-}
-
-
-unsigned
-GLUsphereProducer::element_count(void) const
-{
- /* Each slice is a triangle strip represented by 2 elements plus
- * 2 elements for each stack;
- */
- return slices * (2 * (stacks + 1));
+
+ return (this->rows + 1) * (this->columns);
}
@@ -122,33 +96,6 @@ sphere_revolve_cb(void *data, const GLUvec4 *position, const GLUvec4 *normal,
}
-static void
-sphere_begin_cb(void *data, GLenum mode, unsigned count)
-{
- GLUconsumerFriend *c = (GLUconsumerFriend *) data;
-
- c->begin_primitive(mode, count);
-}
-
-
-static void
-sphere_index_cb(void *data, const unsigned *index, unsigned count)
-{
- GLUconsumerFriend *c = (GLUconsumerFriend *) data;
-
- c->index_batch(index, count);
-}
-
-
-static void
-sphere_end_cb(void *data)
-{
- GLUconsumerFriend *c = (GLUconsumerFriend *) data;
-
- c->end_primitive();
-}
-
-
void
GLUsphereProducer::generate(GLUshapeConsumer *consumer) const
{
@@ -164,13 +111,9 @@ GLUsphereProducer::generate(GLUshapeConsumer *consumer) const
consumer->vertex_count);
}
- generate_sphere(radius, slices, stacks,
- normals_point_out,
+ generate_sphere(this->radius, this->rows, this->columns - 1,
+ this->normals_point_out,
sphere_revolve_cb, (void *) consumer, &buf);
- generate_triangle_mesh(slices, stacks + 1, stacks + 1,
- sphere_begin_cb,
- sphere_index_cb,
- sphere_end_cb,
- (void *) consumer);
+ GLUmeshProducer::generate(consumer);
}