summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <idr@freedesktop.org>2010-10-02 12:16:31 -0700
committerIan Romanick <idr@freedesktop.org>2010-10-02 14:58:38 -0700
commitfbb781a415ac83b14c107061939977bf2b79368e (patch)
treeb41652ab7b122d11683e60815bba59563314cc51
parent73a53f2912a5312ce6d51dc2324167f79501ef62 (diff)
GLUshape: Simplify / optimize GLUshapeConsumer interface
Now applications can supply buffers in the GLUshapeConsumer object that the producer routines will automatically fill in. In addition, the vertex handler method in GLUshapeConsumer will receive a batch of vertices instead of one at a time.
-rw-r--r--include/glu3.h25
-rw-r--r--src/Makefile.am3
-rw-r--r--src/buffer.c76
-rw-r--r--src/buffer.h71
-rw-r--r--src/cube.cpp89
-rw-r--r--src/revolve.c41
-rw-r--r--src/revolve.h6
-rw-r--r--src/sphere.cpp14
8 files changed, 271 insertions, 54 deletions
diff --git a/include/glu3.h b/include/glu3.h
index 4b18c13..cc63725 100644
--- a/include/glu3.h
+++ b/include/glu3.h
@@ -333,6 +333,31 @@ public:
* End an index primitive previously started with begin_primitive
*/
virtual void end_primitive(void) = 0;
+
+ /**
+ * Buffer storage for vertex data
+ *
+ * During production of vertices, data will be stored in any buffers
+ * supplied here. Data for buffers not supplied here (i.e., buffers
+ * that have \c NULL pointers) will still be supplied to the
+ * \c vertex_batch method. These buffers will only be used if
+ * \c vertex_count is non-zero.
+ *
+ * In many cases this may allow simplification of the \c vertex_batch
+ * method. If the application wants non-interleaved data stored as
+ * sets of four \c GLfloat values for each channel, pointers to
+ * application allocated buffers (or mapped vertex buffer objects) can
+ * be supplied here. The \c vertex_batch method may then be a no-op.
+ */
+ /*@{*/
+ GLUvec4 *position; /**< Optional buffer for position data. */
+ GLUvec4 *normal; /**< Optional buffer for normal data. */
+ GLUvec4 *tangent; /**< Optional buffer for tangent data. */
+ GLUvec4 *uv; /**< Optional buffer for UV data. */
+ unsigned vertex_count; /**< Number of GLUvec4 elements pointed to by
+ * each non- \c NULL pointer.
+ */
+ /*@}*/
};
diff --git a/src/Makefile.am b/src/Makefile.am
index b165515..84a4fae 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,7 +25,8 @@ AM_CFLAGS=-I../include
lib_LIBRARIES = libGLU3.a
libGLU3_a_SOURCES = matrix.c load_text.c arcball.c revolve.c mesh.c \
- sphere.cpp cube.cpp shader.c mesh.h revolve.h system.h
+ sphere.cpp cube.cpp shader.c mesh.h revolve.h system.h \
+ buffer.c buffer.h
libGLU3includedir = ${includedir}
libGLU3include_HEADERS = ../include/glu3.h ../include/glu3_scalar.h
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644
index 0000000..7acb94e
--- /dev/null
+++ b/src/buffer.c
@@ -0,0 +1,76 @@
+/*
+ * 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 <stdlib.h>
+#include "buffer.h"
+
+void
+cb_buffer_init(struct cb_buffer *buf, GLUvec4 *pos,
+ GLUvec4 *nrm, GLUvec4 *tng, GLUvec4 *uv,
+ unsigned size)
+{
+ memset(buf, 0, sizeof(*buf));
+
+ buf->pos = pos;
+ buf->nrm = nrm;
+ buf->tng = tng;
+ buf->uv = uv;
+ buf->size = size;
+
+ if (buf->pos == NULL) {
+ buf->pos = malloc(sizeof(GLUvec4) * buf->size);
+ buf->free_pos = true;
+ }
+
+ if (buf->nrm == NULL) {
+ buf->nrm = malloc(sizeof(GLUvec4) * buf->size);
+ buf->free_nrm = true;
+ }
+
+ if (buf->tng == NULL) {
+ buf->tng = malloc(sizeof(GLUvec4) * buf->size);
+ buf->free_tng = true;
+ }
+
+ if (buf->uv == NULL) {
+ buf->uv = malloc(sizeof(GLUvec4) * buf->size);
+ buf->free_uv = true;
+ }
+}
+
+void
+cb_buffer_destroy(struct cb_buffer *buf)
+{
+ if (buf->free_pos)
+ free(buf->pos);
+
+ if (buf->free_nrm)
+ free(buf->nrm);
+
+ if (buf->free_tng)
+ free(buf->tng);
+
+ if (buf->free_uv)
+ free(buf->uv);
+
+ memset(buf, 0, sizeof(*buf));
+}
diff --git a/src/buffer.h b/src/buffer.h
new file mode 100644
index 0000000..b5e7bb8
--- /dev/null
+++ b/src/buffer.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef GLU3_BUFFER_H
+#define GLU3_BUFFER_H
+
+#include "system.h"
+#include "glu3.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct cb_buffer {
+ GLUvec4 *pos;
+ GLUvec4 *nrm;
+ GLUvec4 *tng;
+ GLUvec4 *uv;
+ unsigned size;
+ unsigned used;
+
+ unsigned free_pos:1;
+ unsigned free_nrm:1;
+ unsigned free_tng:1;
+ unsigned free_uv:1;
+};
+
+extern void cb_buffer_init(struct cb_buffer *buf, GLUvec4 *pos,
+ GLUvec4 *nrm, GLUvec4 *tng, GLUvec4 *uv,
+ unsigned size);
+
+extern void cb_buffer_destroy(struct cb_buffer *buf);
+
+#define CB_BUFFER_APPEND(cb, p, n, t, u) \
+ do { \
+ (cb).pos[(cb).used] = (p); \
+ (cb).nrm[(cb).used] = (n); \
+ (cb).tng[(cb).used] = (t); \
+ (cb).uv[(cb).used] = (u); \
+ (cb).used += 1; \
+ } while (0)
+
+#define CB_BUFFER_IS_FULL(cb) ((cb).used >= (cb).size)
+#define CB_BUFFER_IS_EMPTY(cb) ((cb).used == 0)
+#define CB_BUFFER_MAKE_EMPTY(cb) ((cb).used = 0)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* GLU3_BUFFER_H */
diff --git a/src/cube.cpp b/src/cube.cpp
index c1a3b96..39361f7 100644
--- a/src/cube.cpp
+++ b/src/cube.cpp
@@ -21,6 +21,7 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "glu3.h"
+#include "buffer.h"
GLUcubeProducer::GLUcubeProducer(double radius) :
radius(radius)
@@ -117,38 +118,70 @@ GLUcubeProducer::generate(GLUshapeConsumer *consumer) const
GLUvec4 nrm[3 * Elements(p)];
GLUvec4 tng[3 * Elements(p)];
GLUvec4 uv[3 * Elements(p)];
- unsigned j = 0;
+ cb_buffer buf;
+
+ if (consumer->vertex_count > 0) {
+ cb_buffer_init(&buf,
+ consumer->position,
+ consumer->normal,
+ consumer->tangent,
+ consumer->uv,
+ consumer->vertex_count);
+ } else {
+ cb_buffer_init(&buf, pos, nrm, tng, uv, 3 * Elements(p));
+ }
for (unsigned i = 0; i < Elements(p); i++) {
- pos[j] = p[i];
- nrm[j] = GLUvec4(p[i].values[0], 0.0, 0.0, 0.0);
- tng[j] = GLUvec4(0.0, 0.0, p[i].values[0], 0.0);
- uv[j] = GLUvec4((p[i].values[2] + 1.0) * 0.5,
- (p[i].values[1] + 1.0) * 0.5,
- 0.0,
- 0.0);
- j++;
-
- pos[j] = p[i];
- nrm[j] = GLUvec4(0.0, p[i].values[1], 0.0, 0.0);
- tng[j] = GLUvec4(p[i].values[1], 0.0, 0.0, 0.0);
- uv[j] = GLUvec4((p[i].values[0] + 1.0) * 0.5,
- (p[i].values[2] + 1.0) * 0.5,
- 0.0,
- 0.0);
- j++;
-
- pos[j] = p[i];
- nrm[j] = GLUvec4(0.0, 0.0, p[i].values[2], 0.0);
- tng[j] = GLUvec4(p[i].values[2], 0.0, 0.0, 0.0);
- uv[j] = GLUvec4((p[i].values[0] + 1.0) * 0.5,
- (p[i].values[1] + 1.0) * 0.5,
- 0.0,
- 0.0);
- j++;
+ CB_BUFFER_APPEND(buf,
+ p[i],
+ GLUvec4(p[i].values[0], 0.0, 0.0, 0.0),
+ GLUvec4(0.0, 0.0, p[i].values[0], 0.0),
+ GLUvec4((p[i].values[2] + 1.0) * 0.5,
+ (p[i].values[1] + 1.0) * 0.5,
+ 0.0,
+ 0.0));
+ if (CB_BUFFER_IS_FULL(buf)) {
+ consumer->vertex_batch(buf.pos, buf.nrm, buf.tng,
+ buf.uv, buf.used);
+ CB_BUFFER_MAKE_EMPTY(buf);
+ }
+
+
+ CB_BUFFER_APPEND(buf,
+ p[i],
+ GLUvec4(0.0, p[i].values[1], 0.0, 0.0),
+ GLUvec4(p[i].values[1], 0.0, 0.0, 0.0),
+ GLUvec4((p[i].values[0] + 1.0) * 0.5,
+ (p[i].values[2] + 1.0) * 0.5,
+ 0.0,
+ 0.0));
+ if (CB_BUFFER_IS_FULL(buf)) {
+ consumer->vertex_batch(buf.pos, buf.nrm, buf.tng,
+ buf.uv, buf.used);
+ CB_BUFFER_MAKE_EMPTY(buf);
+ }
+
+
+ CB_BUFFER_APPEND(buf,
+ p[i],
+ GLUvec4(0.0, 0.0, p[i].values[2], 0.0),
+ GLUvec4(p[i].values[2], 0.0, 0.0, 0.0),
+ GLUvec4((p[i].values[0] + 1.0) * 0.5,
+ (p[i].values[1] + 1.0) * 0.5,
+ 0.0,
+ 0.0));
+ if (CB_BUFFER_IS_FULL(buf)) {
+ consumer->vertex_batch(buf.pos, buf.nrm, buf.tng,
+ buf.uv, buf.used);
+ CB_BUFFER_MAKE_EMPTY(buf);
+ }
}
- consumer->vertex_batch(pos, nrm, tng, uv, j);
+ if (!CB_BUFFER_IS_EMPTY(buf)) {
+ consumer->vertex_batch(buf.pos, buf.nrm, buf.tng, buf.uv,
+ buf.used);
+ CB_BUFFER_MAKE_EMPTY(buf);
+ }
consumer->begin_primitive(GL_TRIANGLES);
diff --git a/src/revolve.c b/src/revolve.c
index f6a170a..71285ac 100644
--- a/src/revolve.c
+++ b/src/revolve.c
@@ -34,20 +34,14 @@ 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)
+ revolve_cb *cb, void *data, struct cb_buffer *buf)
{
const float angle_step = (end_angle - start_angle) / (float) (steps - 1);
const GLUvec4 tangent = {{ 0.0, 0.0, 1.0, 0.0 }};
- GLUvec4 p[64];
- GLUvec4 n[64];
- GLUvec4 t[64];
- GLUvec4 uv[64];
- unsigned idx;
unsigned i;
unsigned j;
- idx = 0;
for (i = 0; i < steps; i++) {
const float a = start_angle + (angle_step * i);
const float v = (float) i / (float) (steps - 1);
@@ -60,33 +54,36 @@ revolve(const GLUvec4 *points, const GLUvec4 *normals, const float *u,
gluRotate4v(& r, axis, a);
for (j = 0; j < num_points; j++) {
- gluMult4m_4v(& p[idx], & r, & points[j]);
- gluMult4m_4v(& n[idx], & r, & normals[j]);
- gluMult4m_4v(& t[idx], & r, & tangent);
+ gluMult4m_4v(& buf->pos[buf->used], & r, & points[j]);
+ gluMult4m_4v(& buf->nrm[buf->used], & r, & normals[j]);
+ gluMult4m_4v(& buf->tng[buf->used], & r, & tangent);
- uv[idx].values[0] = u[j];
- uv[idx].values[1] = v;
- uv[idx].values[2] = 0.0;
- uv[idx].values[3] = 0.0;
+ buf->uv[buf->used].values[0] = u[j];
+ buf->uv[buf->used].values[1] = v;
+ buf->uv[buf->used].values[2] = 0.0;
+ buf->uv[buf->used].values[3] = 0.0;
- idx++;
+ buf->used++;
- if (idx >= 64) {
- (*cb)(data, p, n, t, uv, idx);
- idx = 0;
+ if (CB_BUFFER_IS_FULL(*buf)) {
+ (*cb)(data, buf->pos, buf->nrm, buf->tng,
+ buf->uv, buf->used);
+ CB_BUFFER_MAKE_EMPTY(*buf);
}
}
}
- if (idx > 0)
- (*cb)(data, p, n, t, uv, idx);
+ if (!CB_BUFFER_IS_EMPTY(*buf)) {
+ (*cb)(data, buf->pos, buf->nrm, buf->tng, buf->uv, buf->used);
+ CB_BUFFER_MAKE_EMPTY(*buf);
+ }
}
void
generate_sphere(double radius, unsigned slices, unsigned stacks,
_Bool normals_point_out,
- revolve_cb *cb, void *data)
+ revolve_cb *cb, void *data, struct cb_buffer *buf)
{
const GLUvec4 y_axis = {{ 0.0, 1.0, 0.0, 0.0 }};
GLUvec4 *positions;
@@ -127,5 +124,5 @@ generate_sphere(double radius, unsigned slices, unsigned stacks,
* 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);
+ slices + 1, 2.0 * M_PI, 0.0, cb, data, buf);
}
diff --git a/src/revolve.h b/src/revolve.h
index dafbc9e..7d02cff 100644
--- a/src/revolve.h
+++ b/src/revolve.h
@@ -23,6 +23,7 @@
#include "system.h"
#include "glu3.h"
+#include "buffer.h"
#if defined(__cplusplus)
extern "C" {
@@ -61,11 +62,12 @@ 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);
+ revolve_cb *cb, void *data, struct cb_buffer *buf);
extern void
generate_sphere(double radius, unsigned slices, unsigned stacks,
- bool normals_point_out, revolve_cb *cb, void *data);
+ bool normals_point_out, revolve_cb *cb, void *data,
+ struct cb_buffer *buf);
#ifdef __cplusplus
};
diff --git a/src/sphere.cpp b/src/sphere.cpp
index 79a733a..be8bf70 100644
--- a/src/sphere.cpp
+++ b/src/sphere.cpp
@@ -152,9 +152,21 @@ sphere_end_cb(void *data)
void
GLUsphereProducer::generate(GLUshapeConsumer *consumer) const
{
+ GLUvec4 data[4 * 16];
+ cb_buffer buf;
+
+ if (consumer->vertex_count == 0) {
+ cb_buffer_init(&buf, &data[0], &data[16], &data[32],
+ &data[48], 16);
+ } else {
+ cb_buffer_init(&buf, consumer->position, consumer->normal,
+ consumer->tangent, consumer->uv,
+ consumer->vertex_count);
+ }
+
generate_sphere(radius, slices, stacks,
normals_point_out,
- sphere_revolve_cb, (void *) consumer);
+ sphere_revolve_cb, (void *) consumer, &buf);
generate_triangle_mesh(slices, stacks + 1, stacks + 1,
sphere_begin_cb,