diff options
author | Ian Romanick <idr@freedesktop.org> | 2010-10-02 12:16:31 -0700 |
---|---|---|
committer | Ian Romanick <idr@freedesktop.org> | 2010-10-02 14:58:38 -0700 |
commit | fbb781a415ac83b14c107061939977bf2b79368e (patch) | |
tree | b41652ab7b122d11683e60815bba59563314cc51 | |
parent | 73a53f2912a5312ce6d51dc2324167f79501ef62 (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.h | 25 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/buffer.c | 76 | ||||
-rw-r--r-- | src/buffer.h | 71 | ||||
-rw-r--r-- | src/cube.cpp | 89 | ||||
-rw-r--r-- | src/revolve.c | 41 | ||||
-rw-r--r-- | src/revolve.h | 6 | ||||
-rw-r--r-- | src/sphere.cpp | 14 |
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, |