From df43818ff58074cfdcb2e196a2db9fa22a4f40b4 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 6 Oct 2010 20:55:32 -0700 Subject: Initial commit. lol --- Makefile.am | 24 +++ autogen.sh | 12 ++ configure.ac | 96 ++++++++++ src/Makefile.am | 27 +++ src/bezier.cpp | 34 ++++ src/bezier.h | 60 +++++++ src/main.cpp | 474 +++++++++++++++++++++++++++++++++++++++++++++++++ src/model_consumer.cpp | 143 +++++++++++++++ src/patch_set.h | 49 +++++ src/phong.frag | 20 +++ src/phong.vert | 24 +++ 11 files changed, 963 insertions(+) create mode 100755 Makefile.am create mode 100755 autogen.sh create mode 100755 configure.ac create mode 100755 src/Makefile.am create mode 100755 src/bezier.cpp create mode 100755 src/bezier.h create mode 100755 src/main.cpp create mode 100755 src/model_consumer.cpp create mode 100755 src/patch_set.h create mode 100755 src/phong.frag create mode 100755 src/phong.vert diff --git a/Makefile.am b/Makefile.am new file mode 100755 index 0000000..51d21bb --- /dev/null +++ b/Makefile.am @@ -0,0 +1,24 @@ +# Copyright © 2009 Ian D. Romanick +# All Rights Reserved. +# +# 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 +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL +# AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS 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. + +AUTOMAKE_OPTIONS = foreign +SUBDIRS = src diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..904cd67 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,12 @@ +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? + +$srcdir/configure --enable-maintainer-mode "$@" diff --git a/configure.ac b/configure.ac new file mode 100755 index 0000000..4e7de98 --- /dev/null +++ b/configure.ac @@ -0,0 +1,96 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.61) +AC_INIT(bezier_demo, 2010Q1.1, idr@freedesktop.org, bezier_demo) +AC_CONFIG_SRCDIR([Makefile.am]) +AM_CONFIG_HEADER([config.h]) + +AM_INIT_AUTOMAKE + +AM_MAINTAINER_MODE + +# Checks for programs. +AC_PROG_CXX +AC_PROG_CC +AC_PROG_MAKE_SET +AC_PROG_RANLIB +PKG_PROG_PKG_CONFIG + +# Checks for libraries. + +# Checks for header files. + +# Checks for typedefs, structures, and compiler characteristics. + +# Checks for library functions. +AC_HEADER_STDC + + +# SDL is required for this application. Find its header files and +# libraries. Make sure they exist. + +CPPFLAGS="$CPPFLAGS `sdl-config --cflags`" +LIBS="$LIBS `sdl-config --libs`" + +AC_CHECK_HEADER(SDL.h, [], [exit 1]) + + +# OpenGL is required for this application. Find its header files and +# libraries. Make sure they exist. + +AC_CHECK_HEADER(GL/gl.h, [], [exit 1]) +AC_CHECK_LIB([GL], [glVertexPointer], [], [exit 1]) + + +# GLEW is required for this application. Find its header files and +# libraries. Make sure they exist. + +AC_CHECK_HEADER(GL/glew.h, [], [exit 1]) +AC_CHECK_LIB([GLEW], [glewInit], [], [exit 1], [-lGL]) + +AC_LANG_CPLUSPLUS + +PKG_CHECK_MODULES([GLU3], [glu3]) +AC_SUBST(GLU3_CFLAGS) +AC_SUBST(GLU3_LIBS) + +AC_ARG_ENABLE([debug], + [AS_HELP_STRING([--enable-debug], + [use debug compiler flags and macros @<:@default=disabled@:>@])], + [enable_debug="$enableval"], + [enable_debug=no] +) +if test "x$enable_debug" = xyes; then + DEFINES="$DEFINES -DDEBUG" + if test "x$GCC" = xyes; then + # Remove any -g flags from the command line + CFLAGS=[`echo $CFLAGS | sed 's/-g[^ \t]*[ \t]*//g'`] + CFLAGS="$CFLAGS -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2" + fi + if test "x$GXX" = xyes; then + # Remove any -g flags from the command line + CXXFLAGS=[`echo $CXXFLAGS | sed 's/-g[^ \t]*[ \t]*//g'`] + CXXFLAGS="$CXXFLAGS -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2" + fi +fi + + +if test "x$GCC" = xyes ; then + WARN="-Wall -Wextra -Wunsafe-loop-optimizations -Wstack-protector" +else + WARN="" +fi + +if test "x$GXX" = xyes ; then + WARN="-Wall -Wextra -Wunsafe-loop-optimizations -Wstack-protector" +else + WARN="" +fi + +CFLAGS="$CFLAGS $WARN" +CXXFLAGS="$CXXFLAGS $WARN" + +AC_OUTPUT([Makefile + src/Makefile]) + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100755 index 0000000..c363b8d --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,27 @@ +# Copyright © 2009 Ian D. Romanick +# All Rights Reserved. +# +# 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 +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL +# AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS 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. + +bin_PROGRAMS = camera_demo +camera_demo_SOURCES = main.cpp bezier.cpp model_consumer.cpp + +AM_CXXFLAGS= $(GLU3_CFLAGS) +camera_demo_LDADD = $(GLU3_LIBS) diff --git a/src/bezier.cpp b/src/bezier.cpp new file mode 100755 index 0000000..e3fa37d --- /dev/null +++ b/src/bezier.cpp @@ -0,0 +1,34 @@ +/* + * Copyright © 2009, 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 "bezier.h" + +GLUvec4 +bezier_curve::position(float t) const +{ + /* FINISHME: Implement this function. + */ + GLUvec4 result(0.0, 0.0, 0.0, 0.0); + + return result; +} diff --git a/src/bezier.h b/src/bezier.h new file mode 100755 index 0000000..9bff5e9 --- /dev/null +++ b/src/bezier.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright © 2009, 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 + +class bezier_curve { +public: + bezier_curve(void) { } + + inline bezier_curve(const GLUvec4 *control_points) + { + this->p[0] = control_points[0]; + this->p[1] = control_points[1]; + this->p[2] = control_points[2]; + this->p[3] = control_points[3]; + } + + inline bezier_curve(const GLUvec4 &p0, const GLUvec4 &p1, + const GLUvec4 &p2, const GLUvec4 &p3) + { + this->p[0] = p0; + this->p[1] = p1; + this->p[2] = p2; + this->p[3] = p3; + } + + /** + * Evaluate the position on a curve at a particular parameter value. + */ + GLUvec4 position(float t) const; + + const GLUvec4 &operator[](unsigned i) const + { + return this->p[i]; + } + +private: + GLUvec4 p[4]; +}; diff --git a/src/main.cpp b/src/main.cpp new file mode 100755 index 0000000..b272f67 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,474 @@ +/* + * Copyright © 2009, 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 +#include + +#include + +#include "bezier.h" +#include "patch_set.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) +#define ELEMENTS_OF(x) (sizeof(x) / sizeof(x[0])) + +static SDL_Surface *my_surf = NULL; + +static bool anim = true; +static bool done = false; + +static GLUvec4 eye(0.0, 1.5f, 10.0f, 0.0f); + +/** + * Points in 3-space that the camera must hit. + */ +static const GLUvec4 linear_control_points[] = { + GLUvec4(0.0, 1.5f, 10.0f, 0.0f), + GLUvec4(10.0, 1.5f, 0.0f, 0.0f), + GLUvec4(-30.0, 1.5f, -30.0f, 0.0f), + +}; + +/** + * Basic C0 cameara control curves that hit the points in linear_control_points + * + * FINISHME: Fill these in. + */ +#if 0 +static const bezier_curve camera_curves[] = { + bezier_curve(GLUvec4(...), // start point + GLUvec4(...), // control + GLUvec4(...), // control + GLUvec4(...)), // end point + ... +}; +#endif + +/** + * Control curves from camera_curves "fixed" to be G1. + * + * \sa make_curves_g1 + */ +#if 0 +static bezier_curve camera_curves_G1[ELEMENTS_OF(camera_curves)]; +#endif + +/** + * Control curves from camera_curves "fixed" to be C1. + * + * \sa make_curves_c1 + */ +#if 0 +static bezier_curve camera_curves_C1[ELEMENTS_OF(camera_curves)]; +#endif + +/** + * Positions in 3-space of the spheres. + */ +static const GLUvec4 sphere_locations[] = { + GLUvec4(3.0, 0.0, 0.0, 0.0), + GLUvec4(-3.0, 0.0, 0.0, 0.0), + GLUvec4(0.0, 0.0, 3.0, 0.0), + GLUvec4(0.0, 4.0, 0.0, 0.0), +}; + +static float specular_exponent[ELEMENTS_OF(sphere_locations)] = { + 198.0, + 64.0, + 32.0, + 4.0, +}; + +/** + * Selects the camera control mode. + */ +enum { + camera_linear, + camera_G0, + camera_C1, +} camera_mode = camera_linear; + +static Uint32 t0; + +static GLUmat4 projection_matrix; + +static GLuint prog; +static GLint mvp_location; +static GLint mv_location; +static GLint s_location; + +static patch_set_info *object = NULL; + +static void +Redisplay(const patch_set_info *info) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + const GLUvec4 ref(0.0f, 0.0f, 0.0f, 1.0f); + const GLUvec4 up(0.0f, 1.0f, 0.0f, 0.0f); + const GLUmat4 view(gluLookAt(eye, ref, up)); + + GLUmat4 model(gluRotate(GLUvec4(1.0, 0.0, 0.0, 0.0), 3.0 * M_PI_2)); + + glUseProgram(prog); + glBindBuffer(GL_ARRAY_BUFFER, info->buffer_object); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, info->buffer_object); + + for (unsigned attr = 0; attr < info->num_attribs; attr++) + glVertexAttribPointer(attr, + info->attribs[attr].size, + info->attribs[attr].type, + GL_FALSE, + info->attribs[attr].stride, + BUFFER_OFFSET(info->attribs[attr].base)); + + + for (unsigned i = 0; i < ELEMENTS_OF(sphere_locations); i++) { + const GLUmat4 m(gluTranslate(sphere_locations[i]) + * model); + const GLUmat4 mv(view * m); + const GLUmat4 mvp(projection_matrix * mv); + + glUniform1f(s_location, specular_exponent[i]); + glUniformMatrix4fv(mvp_location, 1, false, (float *) &mvp); + glUniformMatrix4fv(mv_location, 1, false, (float *) &mv); + + glMultiDrawElements(info->mode, info->count, info->type, + (const GLvoid**) info->indices, + info->num_patches); + } + + SDL_GL_SwapBuffers(); +} + + +static void +Idle(void) +{ + static Uint32 last_t = ~0; + Uint32 t = SDL_GetTicks(); + + + if (last_t != (Uint32)~0) { + float dt = (float) (t - last_t) / 1000.0f; + + if (anim) { + static float total_t = 0.0; + + /* FINISHME: Perform some calculations so that the + * FINISHME: timer wraps around to zero when the last + * FINISHME: segment of the camera track is completed. + */ + total_t = fmod(total_t + dt, 10.0); + + /* FINISHME: Based on the timer, determine which + * FINISHME: segment of the camera track is active. + */ + + /* FINISHME: Calculate t_segment as the time within the + * FINISHME: active segment. + */ + + + /* FINISHME: Calculate the camera position from the + * FINISHME: active segement and t_segment. + */ + } + } + + last_t = t; +} + + +/* Load, compile, link, etc. the vertex and fragment programs. + */ +static void +load_and_compile_program_code(const char *shader) +{ + char buf[512]; + + if (!gluInitializeCompiler()) { + printf("GLSL not supported.\n"); + exit(1); + } + + snprintf(buf, sizeof(buf), "../src/%s.vert", shader); + + const char *const vs_code = gluLoadTextFile(buf); + + snprintf(buf, sizeof(buf), "../src/%s.frag", shader); + + const char *const fs_code = gluLoadTextFile(buf); + + char *vs_log = NULL; + char *fs_log = NULL; + GLuint vs = gluCompileShader(GL_VERTEX_SHADER, vs_code, + &vs_log); + GLuint fs = gluCompileShader(GL_FRAGMENT_SHADER, fs_code, + &fs_log); + + if ((vs != 0) && (fs != 0)) { + prog = glCreateProgram(); + + gluAttachShaders(prog, vs, fs, 0); + gluBindAttributes(prog, + "normal", 1, + "tangent", 2, + "uv", 3, + NULL); + if (gluLinkProgram(prog, NULL)) { + glUseProgram(prog); + mvp_location = glGetUniformLocation(prog, "mvp"); + mv_location = glGetUniformLocation(prog, "mv"); + s_location = glGetUniformLocation(prog, "s"); + } else { + glDeleteProgram(prog); + prog = 0; + } + } else { + printf("Vertex shader log:\n"); + if (vs_log != NULL) { + printf("%s\n", vs_log); + gluReleaseInfoLog(vs_log); + } + + printf("Fragment shader log:\n"); + if (fs_log != NULL) { + printf("%s\n", fs_log); + gluReleaseInfoLog(fs_log); + } + } + + gluUnloadTextFile(vs_code); + gluUnloadTextFile(fs_code); +} + + +/** + * Modify the control points of two C0 curves to make the G1 + * + * The curves generated by this function will only modify the neighboring + * control points. This means that the first control point of \c s0 and the + * second control point \c s1 are unmodified. + * + * \param s0 First input curve + * \param s1 Second input curve + * \param d0 First output curve + * \param d1 Second output curve + */ +void +make_curves_G1(const bezier_curve &s0, const bezier_curve &s1, + bezier_curve &d0, bezier_curve &d1) +{ + /* FINISHME: Implement this function. + */ +} + + +/** + * Modify the control points of two C0 curves to make the C1 + * + * The curves generated by this function will only modify the neighboring + * control points. This means that the first control point of \c s0 and the + * second control point \c s1 are unmodified. + * + * \param s0 First input curve + * \param s1 Second input curve + * \param d0 First output curve + * \param d1 Second output curve + */ +void +make_curves_C1(const bezier_curve &s0, const bezier_curve &s1, + bezier_curve &d0, bezier_curve &d1) +{ + /* FINISHME: Implement this function. + */ +} + + +static void +Init(void) +{ + if (!GLEW_VERSION_2_0) { + printf ("Sorry, this demo requires OpenGL 2.0 or later.\n"); + exit(1); + } + + load_and_compile_program_code("phong"); + if (prog == 0) { + exit(1); + } + + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glClearColor(0.3, 0.3, 0.3, 1.0); + + object = generate_sphere(); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); + + printf("GL_RENDERER = %s\n", (const char *) glGetString(GL_RENDERER)); + printf("Keyboard input:\n" + " f: Toggle fullscreen.\n" + " a: Toggle animation of object.\n" + " c: Re-load and compile shader program code.\n" + " ESC: Exit program.\n"); + + /* FINISHME: Invoke make_curves_G1 here to fix the basic curves. + */ + + /* FINISHME: Invoke make_curves_C1 here to fix the basic curves. + */ +} + + +static void +Reshape(int width, int height) +{ + my_surf = SDL_SetVideoMode(width, height, 0, + SDL_OPENGL | SDL_RESIZABLE); + if (my_surf == NULL) { + exit(1); + } + + glewInit(); + + const float aspect = float(width) / float(height); + gluPerspective4f(& projection_matrix, 55.0f * M_PI / 180.0f, + aspect, 5.0f, 56.0f); + + glViewport(0, 0, width, height); +} + + +static void +Key(SDLKey sym, bool state) +{ + if (!state) + return; + + /* FINISHME: Add controls to cycle through the 3 camera control modes. + */ + + switch (sym) { + case SDLK_ESCAPE: + done = true; + break; + + case 'f': + SDL_WM_ToggleFullScreen(my_surf); + break; + + case ' ': + case 'a': + anim = !anim; + break; + + case 'c': + printf("Reloading and compiling program code...\n"); + load_and_compile_program_code("phong"); + break; + + default: + break; + } +} + + +/** + * Push an event each time the timer callback fires. + */ +Uint32 +timer_callback(Uint32 interval, void *not_used) +{ + SDL_Event e; + + (void) not_used; + + e.type = SDL_USEREVENT; + e.user.code = 0; + e.user.data1 = NULL; + e.user.data2 = NULL; + SDL_PushEvent(& e); + + return interval; +} + + +int +main(int argc, char **argv) +{ + (void) argc; + (void) argv; + + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) { + exit(1); + } + + atexit(SDL_Quit); + + Reshape(800, 600); + Init(); + + SDL_TimerID timer_id = SDL_AddTimer(10, timer_callback, NULL); + t0 = SDL_GetTicks(); + + while (!done) { + SDL_Event event; + + SDL_WaitEvent(&event); + do { + switch (event.type) { + case SDL_VIDEORESIZE: + Reshape(event.resize.w, event.resize.h); + break; + + case SDL_QUIT: + done = true; + break; + + case SDL_KEYDOWN: + Key(event.key.keysym.sym, true); + break; + + case SDL_KEYUP: + Key(event.key.keysym.sym, false); + break; + + default: + break; + } + } while (SDL_PollEvent(&event)); + + Idle(); + Redisplay(object); + } + + SDL_RemoveTimer(timer_id); + + SDL_Quit(); + return 0; +} diff --git a/src/model_consumer.cpp b/src/model_consumer.cpp new file mode 100755 index 0000000..39d044f --- /dev/null +++ b/src/model_consumer.cpp @@ -0,0 +1,143 @@ +/* + * 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 +#include +#include "patch_set.h" + +#define ROUND_UP(s, u) (((s + (u - 1)) / u) * u) + +class model_consumer : public GLUshapeConsumer { +public: + model_consumer(void *data, void *first_elt, patch_set_info *info) + : base(data), first_elt(first_elt), info(info), + current_primitive(-1) + { + this->elt = (GLushort *) this->first_elt; + } + + virtual void begin_primitive(GLenum mode, unsigned count) + { + this->info->mode = mode; + + this->current_primitive++; + + const int idx = this->current_primitive; + this->info->count[idx] = count; + this->info->indices[idx] = + (void *)((char *) this->elt - (char *) this->base); + this->info->basevertex[idx] = 0; + } + + virtual void index_batch(const unsigned *idx, unsigned count) + { + for (unsigned i = 0; i < count; i++) + this->elt[i] = GLushort(idx[i]); + + this->elt += count; + } + +private: + void *base; + void *first_elt; + GLushort *elt; + patch_set_info *info; + int current_primitive; +}; + +static patch_set_info * +generate_common(GLUshapeProducer &prod) +{ + patch_set_info *info = new patch_set_info; + + const unsigned num_verts = prod.vertex_count(); + + info->num_attribs = 4; + info->attribs[0].base = (4 * sizeof(GLfloat)) * (0 * num_verts); + info->attribs[0].size = 4; + info->attribs[0].type = GL_FLOAT; + info->attribs[0].stride = 4 * sizeof(GLfloat); + + info->attribs[1].base = (4 * sizeof(GLfloat)) * (1 * num_verts); + info->attribs[1].size = 4; + info->attribs[1].type = GL_FLOAT; + info->attribs[1].stride = 4 * sizeof(GLfloat); + + info->attribs[2].base = (4 * sizeof(GLfloat)) * (2 * num_verts); + info->attribs[2].size = 4; + info->attribs[2].type = GL_FLOAT; + info->attribs[2].stride = 4 * sizeof(GLfloat); + + info->attribs[3].base = (4 * sizeof(GLfloat)) * (3 * num_verts); + info->attribs[3].size = 2; + info->attribs[3].type = GL_FLOAT; + info->attribs[3].stride = 4 * sizeof(GLfloat); + + info->num_patches = prod.primitive_count(); + info->count = new GLsizei[info->num_patches]; + info->type = GL_UNSIGNED_SHORT; + info->indices = new GLvoid*[info->num_patches]; + info->basevertex = new GLint[info->num_patches]; + + + /* The vertex stride needs to be an even multiple of GLUvec4 because + * each GLUvec4 element needs to be sizeof(GLUvec4) aligned. + */ + info->vertex_stride = ROUND_UP((4 * sizeof(GLfloat)) // position + + (4 * sizeof(GLfloat))// normal + + (4 * sizeof(GLfloat))// tangent + + (2 * sizeof(GLfloat)),// tex coord + sizeof(GLUvec4)); + + const size_t size = (info->vertex_stride * num_verts) + + (sizeof(GLushort) * prod.element_count()); + + glGenBuffers(1, & info->buffer_object); + glBindBuffer(GL_ARRAY_BUFFER, info->buffer_object); + glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW); + + GLUvec4 *const p = + (GLUvec4 *) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + model_consumer cons(p, (char *) p + (info->vertex_stride * num_verts), + info); + + cons.position = &p[0 * num_verts]; + cons.normal = &p[1 * num_verts]; + cons.tangent = &p[2 * num_verts]; + cons.uv = &p[3 * num_verts]; + cons.vertex_count = num_verts; + + prod.generate(&cons); + + glUnmapBuffer(GL_ARRAY_BUFFER); + + return info; +} + + +patch_set_info * +generate_sphere(void) +{ + GLUsphereProducer prod(2.0, 16, 10); + + return generate_common(prod); +} diff --git a/src/patch_set.h b/src/patch_set.h new file mode 100755 index 0000000..571d212 --- /dev/null +++ b/src/patch_set.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * 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. + */ + +struct patch_set_info { + unsigned num_patches; + + GLuint buffer_object; + + unsigned vertex_stride; + + unsigned num_attribs; + + struct { + unsigned base; + unsigned size; + GLenum type; + unsigned stride; + } attribs[8]; + + + GLenum mode; + GLsizei *count; + GLenum type; + GLvoid **indices; + GLint *basevertex; +}; + +patch_set_info *generate_sphere(void); diff --git a/src/phong.frag b/src/phong.frag new file mode 100755 index 0000000..3385f68 --- /dev/null +++ b/src/phong.frag @@ -0,0 +1,20 @@ +varying vec4 normal_es; +varying vec4 position_es; +varying vec2 texcoord; + +/* Specular exponent. + */ +uniform float s; + +/* Position of the light in eye-space. + */ +const vec4 light_es = vec4(0.0, 3.0, 0.0, 1.0); + +void main(void) +{ + /* FINISHME: Calculate lighting. + */ + vec4 color = vec4(1.0, 0.0, 0.0, 1.0); + + gl_FragColor = color; +} diff --git a/src/phong.vert b/src/phong.vert new file mode 100755 index 0000000..4e7ca2e --- /dev/null +++ b/src/phong.vert @@ -0,0 +1,24 @@ +uniform mat4 mvp; +uniform mat4 mv; + +attribute vec4 normal; +attribute vec2 uv; + +/* Normal transformed to eye space. + */ +varying vec4 normal_es; + +/* Vertex position transformed to eye space. + */ +varying vec4 position_es; + +void main(void) +{ + gl_Position = mvp * gl_Vertex; + + /* FINISHME: Calculate normal_es. + */ + + /* FINISHME: Calculate position_es. + */ +} -- cgit v1.2.3