diff options
author | Ian Romanick <idr@freedesktop.org> | 2010-02-16 17:07:41 -0800 |
---|---|---|
committer | Ian Romanick <idr@freedesktop.org> | 2010-02-16 17:07:41 -0800 |
commit | 1419659302c90bfbdbab4cf266f3da4dd8b35601 (patch) | |
tree | b8c895733ecc974101fca31b7e4a373b62c20f2a | |
parent | 8443be72504d58179f09e31ebdaf32102cce72ba (diff) |
GLUshape: Split GLUshape into GLUshapeConsumer and GLUshape
Put the responsibility for storing the data in a separate consumer
class. As a result, applications that want to store data from
n GLUshape subclasses in the same manner need only create one subclass
(of GLUshapeConsumer) instead of n (of GLUshape).
-rw-r--r-- | include/glu3.h | 107 | ||||
-rw-r--r-- | src/sphere.cpp | 25 | ||||
-rw-r--r-- | test/sphere.cpp | 42 |
3 files changed, 92 insertions, 82 deletions
diff --git a/include/glu3.h b/include/glu3.h index 95be831..6e809e5 100644 --- a/include/glu3.h +++ b/include/glu3.h @@ -270,23 +270,62 @@ struct GLUarcball { #ifdef __cplusplus /** - * Base class of a shape generators. + * Consumer for shape data generated by a GLUshape object * - * Base class defines the interface for all shape generators. Concrete shape - * generator class are expected to implement: + * Objects of this class and its descenents are used to consume data generated + * by \c GLUshape. The \c GLUshape object is responsible for the format of + * the data generate, and the \c GLUshapeConsumer object is repsonsible for + * storing that data. * - * * \c vertex_count - * * \c element_count - * * \c primitive_count - * * \c generate + * This splits the functionality of the classic GLU's \c GLUquadric structure. * - * Consumers of generated data are expected to subclass concrete shape - * generators. These classes are expected to implement: + * \sa GLUshape + */ +class GLUshapeConsumer { +public: + /** + * Emit an individual vertex + * + * \param position Object-space position of the vertex. + * \param normal Object-space normal of the vertex. + * \param tangent Object-space tangent of the vertex. + * \param uv Parameter-space position of the vertex. The + * per-vertex values will range from (0,0,0,0) to + * (1, 1, 0, 0). + */ + virtual void vertex(const GLUvec4 &position, + const GLUvec4 &normal, + const GLUvec4 &tangent, + const GLUvec4 &uv) = 0; + + /** + * Start a new indexed primitive. + * + * \param mode GL primitive drawing mode used for this primitive + */ + virtual void begin_primitive(GLenum mode) = 0; + + /** + * Emit an element index for drawing + */ + virtual void index(unsigned idx) = 0; + + /** + * End an index primitive previously started with begin_primitive + */ + virtual void end_primitive(void) = 0; +}; + + +/** + * Base class of a shape generators. * - * * \c emit_vertex - * * \c emit_begin - * * \c emit_index - * * \c emit_end + * Base class defines the interface for all shape generators. Each concrete + * subclass is responsible for providing the pure virtual query and data + * generation methods. Data produced by a shape generator is pushed to a + * \c GLUshapeConsumer as it is generated. + * + * \sa GLUshapeConsumer */ class GLUshape { public: @@ -337,49 +376,17 @@ public: * Generate the primitive * * Causes the data for the primitive to be generated. This will result - * in the \c emit_vertex, \c emit_begin, \c emit_index, and \c emit_end - * methods to be invoked with the data as it is generated. + * in the \c vertex, \c begin_primitive, \c index, and \c end_primitive + * methods of \c consumer being invoked with the data as it is + * generated. */ - virtual void generate(void) = 0; + virtual void generate(GLUshapeConsumer *consumer) const = 0; protected: GLUshape(void) : normals_point_out(true), normals_per_vertex(true) { } - - /** - * Callback function used to emit individual vertices. - * - * \param position Object-space position of the vertex. - * \param normal Object-space normal of the vertex. - * \param tangent Object-space tangent of the vertex. - * \param uv Parameter-space position of the vertex. The - * per-vertex values will range from (0,0,0,0) to - * (1, 1, 0, 0). - */ - virtual void emit_vertex(const GLUvec4 &position, - const GLUvec4 &normal, - const GLUvec4 &tangent, - const GLUvec4 &uv) = 0; - - /** - * Start a new indexed primitive. - * - * \param mode GL primitive drawing mode used for this primitive - */ - virtual void emit_begin(GLenum mode) = 0; - - /** - * Callback function used to emit element indices used for drawing - */ - virtual void emit_index(unsigned idx) = 0; - - /** - * End an index primitive previously started with emit_begin. - */ - virtual void emit_end(void) = 0; - bool normals_point_out; bool normals_per_vertex; }; @@ -405,7 +412,7 @@ public: virtual unsigned vertex_count(void) const; virtual unsigned element_count(void) const; virtual unsigned primitive_count(void) const; - virtual void generate(void); + virtual void generate(GLUshapeConsumer *consumer) const; private: double radius; diff --git a/src/sphere.cpp b/src/sphere.cpp index f51160e..ecd7db8 100644 --- a/src/sphere.cpp +++ b/src/sphere.cpp @@ -1,5 +1,4 @@ /* - * Copyright © 2010 Ian D. Romanick * * Permission is hereby granted, free of charge, to any person obtaining a @@ -61,7 +60,7 @@ static void sphere_end_cb(void *data); * This is arguably a mis-use of the "decorator" pattern, but it is the most * efficient way to do this. */ -class GLUsphereFriend : public GLUsphere { +class GLUconsumerFriend : public GLUshapeConsumer { friend void sphere_revolve_cb(void *data, const GLUvec4 *position, const GLUvec4 *normal, @@ -119,49 +118,49 @@ static void sphere_revolve_cb(void *data, const GLUvec4 *position, const GLUvec4 *normal, const GLUvec4 *tangent, const GLUvec4 *uv) { - GLUsphereFriend *s = (GLUsphereFriend *) data; + GLUconsumerFriend *c = (GLUconsumerFriend *) data; - s->emit_vertex(*position, *normal, *tangent, *uv); + c->vertex(*position, *normal, *tangent, *uv); } static void sphere_begin_cb(void *data, GLenum mode) { - GLUsphereFriend *s = (GLUsphereFriend *) data; + GLUconsumerFriend *c = (GLUconsumerFriend *) data; - s->emit_begin(mode); + c->begin_primitive(mode); } static void sphere_index_cb(void *data, unsigned index) { - GLUsphereFriend *s = (GLUsphereFriend *) data; + GLUconsumerFriend *c = (GLUconsumerFriend *) data; - s->emit_index(index); + c->index(index); } static void sphere_end_cb(void *data) { - GLUsphereFriend *s = (GLUsphereFriend *) data; + GLUconsumerFriend *c = (GLUconsumerFriend *) data; - s->emit_end(); + c->end_primitive(); } void -GLUsphere::generate(void) +GLUsphere::generate(GLUshapeConsumer *consumer) const { generate_sphere(radius, slices, stacks, normals_point_out, - sphere_revolve_cb, (void *) this); + sphere_revolve_cb, (void *) consumer); generate_triangle_mesh(slices, stacks + 1, stacks + 1, sphere_begin_cb, sphere_index_cb, sphere_end_cb, - (void *) this); + (void *) consumer); } diff --git a/test/sphere.cpp b/test/sphere.cpp index 9f5d94a..adcce4e 100644 --- a/test/sphere.cpp +++ b/test/sphere.cpp @@ -2,12 +2,13 @@ #include <cstdio> #include "glu3.h" -class check_sphere : public GLUsphere { +class check_sphere : public GLUshapeConsumer { public: - check_sphere(double r, int sl, int st) : - GLUsphere(r, sl, st), pass(true), vert(0), - prim(0), elts(0), r(r), mode(0) + check_sphere(const GLUshape &shape, double r) : + pass(true), vert(0), prim(0), elts(0), r(r), mode(0) { + primitive_count = shape.primitive_count(); + vertex_count = shape.vertex_count(); } bool pass; @@ -17,8 +18,10 @@ public: double r; GLenum mode; -protected: - virtual void emit_vertex(const GLUvec4 &position, + unsigned vertex_count; + unsigned primitive_count; + + virtual void vertex(const GLUvec4 &position, const GLUvec4 &normal, const GLUvec4 &tangent, const GLUvec4 &tex_coord) @@ -96,7 +99,7 @@ protected: vert++; } - virtual void emit_begin(GLenum mode) + virtual void begin_primitive(GLenum mode) { printf("prim %u: begin\n", prim); @@ -107,7 +110,7 @@ protected: pass = false; } - if (prim == primitive_count()) { + if (prim == primitive_count) { printf("prim %u: too many primitives\n", prim); pass = false; @@ -129,20 +132,20 @@ protected: this->mode = mode; } - virtual void emit_index(unsigned idx) + virtual void index(unsigned idx) { printf("prim %u, elt %u: %u\n", prim, elts, idx); - if (idx >= vertex_count()) { + if (idx >= vertex_count) { printf("prim %u, elt %u: bad elt %u > %u\n", - prim, elts, idx, vertex_count() - 1); + prim, elts, idx, vertex_count - 1); pass = false; } elts++; } - virtual void emit_end(void) + virtual void end_primitive(void) { printf("prim %u: end\n", prim); @@ -161,12 +164,13 @@ protected: int main(int argc, char **argv) { - check_sphere s(4.0, 5, 5); - - s.generate(); - assert(s.pass); - assert(s.vert == s.vertex_count()); - assert(s.prim == s.primitive_count()); - assert(s.elts == s.element_count()); + GLUsphere s(4.0, 5, 5); + check_sphere c(s, 4.0); + + s.generate(& c); + assert(c.pass); + assert(c.vert == s.vertex_count()); + assert(c.prim == s.primitive_count()); + assert(c.elts == s.element_count()); return 0; } |