From 17bbb83eaa0abdb0ca9978cdf0c3136376f5b42e Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Sun, 3 Oct 2010 12:45:11 -0700 Subject: GLUshape: Make the mesh producer publicly available Derive GLUsphereProducer from GLUmeshProducer. This simplifies the implementation somewhat. --- include/glu3.h | 39 ++++++++++++++++++--- src/mesh.cpp | 64 +++++++++++++++++++++-------------- src/sphere.cpp | 105 +++++++++++++-------------------------------------------- 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 @@ -443,10 +443,43 @@ 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); } -- cgit v1.2.3