summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <idr@freedesktop.org>2010-02-16 17:07:41 -0800
committerIan Romanick <idr@freedesktop.org>2010-02-16 17:07:41 -0800
commit1419659302c90bfbdbab4cf266f3da4dd8b35601 (patch)
treeb8c895733ecc974101fca31b7e4a373b62c20f2a
parent8443be72504d58179f09e31ebdaf32102cce72ba (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.h107
-rw-r--r--src/sphere.cpp25
-rw-r--r--test/sphere.cpp42
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;
}