]> git.tdb.fi Git - libs/gl.git/commitdiff
Move tools to their own directory as well
authorMikko Rasa <tdb@tdb.fi>
Wed, 7 Sep 2011 19:51:40 +0000 (22:51 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 7 Sep 2011 19:51:40 +0000 (22:51 +0300)
Build
mesh2c.cpp [deleted file]
tools/mesh2c.cpp [new file with mode: 0644]
tools/viewer.cpp [new file with mode: 0644]
viewer.cpp [deleted file]

diff --git a/Build b/Build
index 59a63b4fe7421f2aaad2ba2d5de478e2616bc376..da8e64c0165f4455764de5b5eb93d1af570fcfd5 100644 (file)
--- a/Build
+++ b/Build
@@ -21,7 +21,7 @@ package "mspgl"
 
        program "mesh2c"
        {
 
        program "mesh2c"
        {
-               source "mesh2c.cpp";
+               source "tools/mesh2c.cpp";
                build_info
                {
                        library "mspgl";
                build_info
                {
                        library "mspgl";
@@ -30,7 +30,7 @@ package "mspgl"
 
        program "viewer"
        {
 
        program "viewer"
        {
-               source "viewer.cpp";
+               source "tools/viewer.cpp";
                build_info
                {
                        library "mspgl";
                build_info
                {
                        library "mspgl";
diff --git a/mesh2c.cpp b/mesh2c.cpp
deleted file mode 100644 (file)
index 864fa93..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-#include <msp/core/getopt.h>
-#include <msp/gl/mesh.h>
-#include <msp/io/print.h>
-#include <msp/strings/format.h>
-
-using namespace std;
-using namespace Msp;
-
-const char *types[] =
-{
-       "unsigned char", "GL_UNSIGNED_BYTE",
-       "unsigned short", "GL_UNSIGNED_SHORT",
-       "unsigned", "GL_UNSIGNED_INT"
-};
-
-int main(int argc, char **argv)
-{
-       string prefix;
-       bool render_func = false;
-       bool separate_arrays = false;
-       GetOpt getopt;
-       getopt.add_option('p', "prefix",      prefix,      GetOpt::REQUIRED_ARG);
-       getopt.add_option('r', "render-func", render_func, GetOpt::NO_ARG);
-       getopt.add_option('s', "separate-arrays", separate_arrays, GetOpt::NO_ARG);
-       getopt(argc, argv);
-
-       const vector<string> &args = getopt.get_args();
-       if(args.empty())
-       {
-               IO::print(IO::cerr, "Usage: %s [options] <meshfile>\n", argv[0]);
-               return 1;
-       }
-
-       GL::Mesh mesh;
-       mesh.use_buffers(false);
-       DataFile::load(mesh, args[0]);
-
-       IO::print("/* Exported from %s */\n", args[0]);
-
-       const GL::VertexArray &array = mesh.get_vertices();
-       const GL::VertexFormat &fmt = array.get_format();
-       unsigned stride = fmt.stride();
-       if(separate_arrays)
-       {
-               unsigned offset = 0;
-               for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
-               {
-                       unsigned kind = (*i)>>2;
-                       unsigned size = ((*i)&3)+1;
-                       string name;
-                       switch(kind)
-                       {
-                       case 0:
-                               name = "vertex";
-                               break;
-                       case 1:
-                               name = "normal";
-                               break;
-                       case 2:
-                               name = "color";
-                               break;
-                       case 3:
-                               name = "texcoord";
-                               break;
-                       default:
-                               if(kind<11)
-                                       name = format("texcoord%d", kind-3);
-                               else
-                                       name = format("attrib%d", kind-11);
-                               break;
-                       }
-
-                       IO::print("float %s%s_data[] =\n{", prefix, name);
-                       for(unsigned j=0; j<array.size(); ++j)
-                       {
-                               const float *ptr = array[j]+offset;
-                               IO::print("\n\t");
-                               for(unsigned k=0; k<size; ++k)
-                                       IO::print("%g, ", ptr[k]);
-                       }
-                       IO::print("\n};\n\n");
-
-                       offset += size;
-               }
-       }
-       else
-       {
-               IO::print("float %svertex_data[] =\n{", prefix);
-               for(unsigned i=0; i<array.size(); ++i)
-               {
-                       const float *ptr = array[i];
-                       IO::print("\n\t");
-                       for(unsigned j=0; j<stride; ++j)
-                               IO::print("%g, ", ptr[j]);
-               }
-               IO::print("\n};\n\n");
-       }
-
-       const char **type = 0;
-       if(array.size()<0x100)
-               type = types;
-       else if(array.size()<0x10000)
-               type = types+2;
-       else
-               type = types+4;
-
-       IO::print("%s %sindices[] =\n{", type[0], prefix);
-       for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
-       {
-               unsigned count = i->size();
-               for(unsigned j=0; j<count; ++j)
-               {
-                       if(j%16==0)
-                               IO::print("\n\t");
-                       IO::print("%d, ", i->get_index(j));
-               }
-       }
-       IO::print("\n};\n\n");
-
-       if(render_func)
-               IO::print("void %srender()\n{\n", prefix);
-       else
-               IO::print("/*\nTo render the object, #include this file and add the following code:\n");
-       unsigned offset = 0;
-       for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
-       {
-               unsigned kind = (*i)>>2;
-               unsigned size = ((*i)&3)+1;
-               string source = format("%svertex_data+%d", prefix, offset);
-               switch((*i)>>2)
-               {
-               case 0:
-                       if(separate_arrays)
-                               source = prefix+"vertex_data";
-                       IO::print("\tglVertexPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
-                               size, stride, source);
-                       IO::print("\tglEnableClientState(GL_VERTEX_ARRAY);\n");
-                       break;
-               case 1:
-                       if(separate_arrays)
-                               source = prefix+"normal_data";
-                       IO::print("\tglNormalPointer(GL_FLOAT, %d*sizeof(float), %s);\n",
-                               stride, source);
-                       IO::print("\tglEnableClientState(GL_NORMAL_ARRAY);\n");
-                       break;
-               case 2:
-                       if(separate_arrays)
-                               source = prefix+"color_data";
-                       IO::print("\tglColorPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
-                               size, stride, source);
-                       IO::print("\tglEnableClientState(GL_COLOR_ARRAY);\n");
-                       break;
-               case 3:
-                       if(separate_arrays)
-                               source = prefix+"texcoord_data";
-                       IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
-                               size, stride, source);
-                       IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
-                       break;
-               default:
-                       if(kind<11)
-                       {
-                               if(separate_arrays)
-                                       source = format("%stexcoord%d_data", prefix, kind-3);
-                               IO::print("\tglClientActiveTexture(GL_TEXTURE%d);\n", kind-3);
-                               IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
-                                       size, stride, source);
-                               IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
-                       }
-                       else
-                       {
-                               if(separate_arrays)
-                                       source = format("%sattrib%d_data", prefix, kind-11);
-                               IO::print("\tglVertexAttribPointer(%d, %d, GL_FLOAT, GL_FALSE, %d*sizeof(float), %s);\n",
-                                       kind-11, size, stride, source);
-                               IO::print("\tglEnableVertexAttribArray(%d);\n", kind-11);
-                       }
-                       break;
-               }
-               offset += size;
-       }
-       offset = 0;
-       for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
-       {
-               string mode;
-               switch(i->get_type())
-               {
-               case GL_TRIANGLE_STRIP: mode = "GL_TRIANGLE_STRIP"; break;
-               case GL_TRIANGLES: mode = "GL_TRIANGLES"; break;
-               default: mode = format("%d", i->get_type()); break;
-               }
-               IO::print("\tglDrawElements(%s, %d, %s, %sindices+%d);\n", mode, i->size(), type[1], prefix, offset);
-               offset += i->size();
-       }
-       if(render_func)
-       {
-               IO::print("}\n\n");
-               IO::print("/* To render this object, #include this file and call %srender() */\n", prefix);
-       }
-       else
-               IO::print("*/\n");
-
-       return 0;
-}
diff --git a/tools/mesh2c.cpp b/tools/mesh2c.cpp
new file mode 100644 (file)
index 0000000..864fa93
--- /dev/null
@@ -0,0 +1,204 @@
+#include <msp/core/getopt.h>
+#include <msp/gl/mesh.h>
+#include <msp/io/print.h>
+#include <msp/strings/format.h>
+
+using namespace std;
+using namespace Msp;
+
+const char *types[] =
+{
+       "unsigned char", "GL_UNSIGNED_BYTE",
+       "unsigned short", "GL_UNSIGNED_SHORT",
+       "unsigned", "GL_UNSIGNED_INT"
+};
+
+int main(int argc, char **argv)
+{
+       string prefix;
+       bool render_func = false;
+       bool separate_arrays = false;
+       GetOpt getopt;
+       getopt.add_option('p', "prefix",      prefix,      GetOpt::REQUIRED_ARG);
+       getopt.add_option('r', "render-func", render_func, GetOpt::NO_ARG);
+       getopt.add_option('s', "separate-arrays", separate_arrays, GetOpt::NO_ARG);
+       getopt(argc, argv);
+
+       const vector<string> &args = getopt.get_args();
+       if(args.empty())
+       {
+               IO::print(IO::cerr, "Usage: %s [options] <meshfile>\n", argv[0]);
+               return 1;
+       }
+
+       GL::Mesh mesh;
+       mesh.use_buffers(false);
+       DataFile::load(mesh, args[0]);
+
+       IO::print("/* Exported from %s */\n", args[0]);
+
+       const GL::VertexArray &array = mesh.get_vertices();
+       const GL::VertexFormat &fmt = array.get_format();
+       unsigned stride = fmt.stride();
+       if(separate_arrays)
+       {
+               unsigned offset = 0;
+               for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
+               {
+                       unsigned kind = (*i)>>2;
+                       unsigned size = ((*i)&3)+1;
+                       string name;
+                       switch(kind)
+                       {
+                       case 0:
+                               name = "vertex";
+                               break;
+                       case 1:
+                               name = "normal";
+                               break;
+                       case 2:
+                               name = "color";
+                               break;
+                       case 3:
+                               name = "texcoord";
+                               break;
+                       default:
+                               if(kind<11)
+                                       name = format("texcoord%d", kind-3);
+                               else
+                                       name = format("attrib%d", kind-11);
+                               break;
+                       }
+
+                       IO::print("float %s%s_data[] =\n{", prefix, name);
+                       for(unsigned j=0; j<array.size(); ++j)
+                       {
+                               const float *ptr = array[j]+offset;
+                               IO::print("\n\t");
+                               for(unsigned k=0; k<size; ++k)
+                                       IO::print("%g, ", ptr[k]);
+                       }
+                       IO::print("\n};\n\n");
+
+                       offset += size;
+               }
+       }
+       else
+       {
+               IO::print("float %svertex_data[] =\n{", prefix);
+               for(unsigned i=0; i<array.size(); ++i)
+               {
+                       const float *ptr = array[i];
+                       IO::print("\n\t");
+                       for(unsigned j=0; j<stride; ++j)
+                               IO::print("%g, ", ptr[j]);
+               }
+               IO::print("\n};\n\n");
+       }
+
+       const char **type = 0;
+       if(array.size()<0x100)
+               type = types;
+       else if(array.size()<0x10000)
+               type = types+2;
+       else
+               type = types+4;
+
+       IO::print("%s %sindices[] =\n{", type[0], prefix);
+       for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
+       {
+               unsigned count = i->size();
+               for(unsigned j=0; j<count; ++j)
+               {
+                       if(j%16==0)
+                               IO::print("\n\t");
+                       IO::print("%d, ", i->get_index(j));
+               }
+       }
+       IO::print("\n};\n\n");
+
+       if(render_func)
+               IO::print("void %srender()\n{\n", prefix);
+       else
+               IO::print("/*\nTo render the object, #include this file and add the following code:\n");
+       unsigned offset = 0;
+       for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
+       {
+               unsigned kind = (*i)>>2;
+               unsigned size = ((*i)&3)+1;
+               string source = format("%svertex_data+%d", prefix, offset);
+               switch((*i)>>2)
+               {
+               case 0:
+                       if(separate_arrays)
+                               source = prefix+"vertex_data";
+                       IO::print("\tglVertexPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
+                               size, stride, source);
+                       IO::print("\tglEnableClientState(GL_VERTEX_ARRAY);\n");
+                       break;
+               case 1:
+                       if(separate_arrays)
+                               source = prefix+"normal_data";
+                       IO::print("\tglNormalPointer(GL_FLOAT, %d*sizeof(float), %s);\n",
+                               stride, source);
+                       IO::print("\tglEnableClientState(GL_NORMAL_ARRAY);\n");
+                       break;
+               case 2:
+                       if(separate_arrays)
+                               source = prefix+"color_data";
+                       IO::print("\tglColorPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
+                               size, stride, source);
+                       IO::print("\tglEnableClientState(GL_COLOR_ARRAY);\n");
+                       break;
+               case 3:
+                       if(separate_arrays)
+                               source = prefix+"texcoord_data";
+                       IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
+                               size, stride, source);
+                       IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
+                       break;
+               default:
+                       if(kind<11)
+                       {
+                               if(separate_arrays)
+                                       source = format("%stexcoord%d_data", prefix, kind-3);
+                               IO::print("\tglClientActiveTexture(GL_TEXTURE%d);\n", kind-3);
+                               IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
+                                       size, stride, source);
+                               IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
+                       }
+                       else
+                       {
+                               if(separate_arrays)
+                                       source = format("%sattrib%d_data", prefix, kind-11);
+                               IO::print("\tglVertexAttribPointer(%d, %d, GL_FLOAT, GL_FALSE, %d*sizeof(float), %s);\n",
+                                       kind-11, size, stride, source);
+                               IO::print("\tglEnableVertexAttribArray(%d);\n", kind-11);
+                       }
+                       break;
+               }
+               offset += size;
+       }
+       offset = 0;
+       for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
+       {
+               string mode;
+               switch(i->get_type())
+               {
+               case GL_TRIANGLE_STRIP: mode = "GL_TRIANGLE_STRIP"; break;
+               case GL_TRIANGLES: mode = "GL_TRIANGLES"; break;
+               default: mode = format("%d", i->get_type()); break;
+               }
+               IO::print("\tglDrawElements(%s, %d, %s, %sindices+%d);\n", mode, i->size(), type[1], prefix, offset);
+               offset += i->size();
+       }
+       if(render_func)
+       {
+               IO::print("}\n\n");
+               IO::print("/* To render this object, #include this file and call %srender() */\n", prefix);
+       }
+       else
+               IO::print("*/\n");
+
+       return 0;
+}
diff --git a/tools/viewer.cpp b/tools/viewer.cpp
new file mode 100644 (file)
index 0000000..bc024e1
--- /dev/null
@@ -0,0 +1,208 @@
+#include <cmath>
+#include <msp/core/application.h>
+#include <msp/core/getopt.h>
+#include <msp/fs/utils.h>
+#include <msp/graphics/simplewindow.h>
+#include <msp/gl/blend.h>
+#include <msp/gl/camera.h>
+#include <msp/gl/framebuffer.h>
+#include <msp/gl/light.h>
+#include <msp/gl/lighting.h>
+#include <msp/gl/mesh.h>
+#include <msp/gl/object.h>
+#include <msp/gl/tests.h>
+#include <msp/input/mouse.h>
+#include <msp/io/print.h>
+
+using namespace std;
+using namespace Msp;
+
+class Viewer: public RegisteredApplication<Viewer>
+{
+private:
+       Graphics::SimpleGLWindow window;
+       Input::Mouse mouse;
+       GL::Object *object;
+       GL::Mesh *mesh;
+       GL::Light light;
+       GL::Lighting lighting;
+       GL::Camera camera;
+       float yaw;
+       float pitch;
+       float distance;
+       float light_yaw;
+       float light_pitch;
+       unsigned dragging;
+
+public:
+       Viewer(int, char **);
+       ~Viewer();
+
+       virtual int main();
+private:
+       virtual void tick();
+
+       void button_press(unsigned);
+       void button_release(unsigned);
+       void axis_motion(unsigned, float, float);
+
+       void update_camera();
+       void update_light();
+};
+
+
+Viewer::Viewer(int argc, char **argv):
+       window(1024, 768, false),
+       mouse(window),
+       object(0),
+       mesh(0),
+       yaw(0),
+       pitch(0),
+       distance(10),
+       light_yaw(0),
+       light_pitch(0),
+       dragging(0)
+{
+       if(argc<2)
+               throw usage_error("Filename must be provided");
+
+       string fn = argv[1];
+       string ext = FS::extpart(fn);
+
+       if(ext==".mesh")
+       {
+               mesh = new GL::Mesh;
+               DataFile::load(*mesh, fn);
+       }
+       else if(ext==".object")
+       {
+               object = new GL::Object;
+               DataFile::load(*object, fn);
+       }
+       else
+               throw usage_error("Don't know how to view this file");
+
+       window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Viewer::exit), 0));
+       mouse.signal_button_press.connect(sigc::mem_fun(this, &Viewer::button_press));
+       mouse.signal_button_release.connect(sigc::mem_fun(this, &Viewer::button_release));
+       mouse.signal_axis_motion.connect(sigc::mem_fun(this, &Viewer::axis_motion));
+
+       light.set_position(GL::Vector4(0, 0, 1, 0));
+       lighting.attach(0, light);
+
+       camera.set_up_direction(GL::Vector3(0, 0, 1));
+       update_camera();
+}
+
+Viewer::~Viewer()
+{
+       delete object;
+       delete mesh;
+}
+
+int Viewer::main()
+{
+       window.show();
+       return Application::main();
+}
+
+void Viewer::tick()
+{
+       window.tick();
+
+       GL::Framebuffer::system().clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT);
+
+       camera.apply();
+
+       GL::Bind bind_lighting(lighting);
+       GL::Bind bind_depth(GL::DepthTest::lequal());
+       GL::Bind bind_blend(GL::Blend::alpha());
+       if(object)
+               object->render();
+       else if(mesh)
+               mesh->draw();
+
+       window.swap_buffers();
+}
+
+void Viewer::button_press(unsigned btn)
+{
+       if(btn==1)
+       {
+               dragging = 1;
+       }
+       else if(btn==3)
+       {
+               dragging = 3;
+               axis_motion(0, 0, 0);
+       }
+       else if(btn==4)
+       {
+               distance *= 0.9;
+               update_camera();
+       }
+       else if(btn==5)
+       {
+               distance *= 1.1;
+               update_camera();
+       }
+}
+
+void Viewer::button_release(unsigned btn)
+{
+       if(btn==dragging)
+               dragging = 0;
+}
+
+void Viewer::axis_motion(unsigned axis, float, float delta)
+{
+       if(dragging==1)
+       {
+               float dx = (axis==0 ? delta : 0);
+               float dy = (axis==1 ? delta : 0);
+
+               yaw -= dx*M_PI*2;
+               while(yaw>M_PI)
+                       yaw -= M_PI*2;
+               while(yaw<-M_PI)
+                       yaw += M_PI*2;
+
+               pitch += dy*M_PI;
+               if(pitch>M_PI*0.49)
+                       pitch = M_PI*0.49;
+               if(pitch<-M_PI*0.49)
+                       pitch = -M_PI*0.49;
+
+               update_camera();
+       }
+       else if(dragging==3)
+       {
+               float x = mouse.get_axis_value(0);
+               float y = mouse.get_axis_value(1);
+
+               light_yaw = yaw+x*M_PI;
+               light_pitch = pitch-y*M_PI;
+
+               update_light();
+       }
+}
+
+void Viewer::update_camera()
+{
+       float cy = cos(yaw);
+       float sy = sin(yaw);
+       float cp = cos(pitch);
+       float sp = sin(pitch);
+       camera.set_position(GL::Vector3(-cy*cp*distance, -sy*cp*distance, -sp*distance));
+       camera.set_depth_clip(distance*0.02, distance*50);
+       camera.look_at(GL::Vector3(0, 0, 0));
+}
+
+void Viewer::update_light()
+{
+       float cy = cos(light_yaw);
+       float sy = sin(light_yaw);
+       float cp = cos(light_pitch);
+       float sp = sin(light_pitch);
+       light.set_position(GL::Vector4(-cy*cp, -sy*cp, -sp, 0));
+}
diff --git a/viewer.cpp b/viewer.cpp
deleted file mode 100644 (file)
index bc024e1..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-#include <cmath>
-#include <msp/core/application.h>
-#include <msp/core/getopt.h>
-#include <msp/fs/utils.h>
-#include <msp/graphics/simplewindow.h>
-#include <msp/gl/blend.h>
-#include <msp/gl/camera.h>
-#include <msp/gl/framebuffer.h>
-#include <msp/gl/light.h>
-#include <msp/gl/lighting.h>
-#include <msp/gl/mesh.h>
-#include <msp/gl/object.h>
-#include <msp/gl/tests.h>
-#include <msp/input/mouse.h>
-#include <msp/io/print.h>
-
-using namespace std;
-using namespace Msp;
-
-class Viewer: public RegisteredApplication<Viewer>
-{
-private:
-       Graphics::SimpleGLWindow window;
-       Input::Mouse mouse;
-       GL::Object *object;
-       GL::Mesh *mesh;
-       GL::Light light;
-       GL::Lighting lighting;
-       GL::Camera camera;
-       float yaw;
-       float pitch;
-       float distance;
-       float light_yaw;
-       float light_pitch;
-       unsigned dragging;
-
-public:
-       Viewer(int, char **);
-       ~Viewer();
-
-       virtual int main();
-private:
-       virtual void tick();
-
-       void button_press(unsigned);
-       void button_release(unsigned);
-       void axis_motion(unsigned, float, float);
-
-       void update_camera();
-       void update_light();
-};
-
-
-Viewer::Viewer(int argc, char **argv):
-       window(1024, 768, false),
-       mouse(window),
-       object(0),
-       mesh(0),
-       yaw(0),
-       pitch(0),
-       distance(10),
-       light_yaw(0),
-       light_pitch(0),
-       dragging(0)
-{
-       if(argc<2)
-               throw usage_error("Filename must be provided");
-
-       string fn = argv[1];
-       string ext = FS::extpart(fn);
-
-       if(ext==".mesh")
-       {
-               mesh = new GL::Mesh;
-               DataFile::load(*mesh, fn);
-       }
-       else if(ext==".object")
-       {
-               object = new GL::Object;
-               DataFile::load(*object, fn);
-       }
-       else
-               throw usage_error("Don't know how to view this file");
-
-       window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Viewer::exit), 0));
-       mouse.signal_button_press.connect(sigc::mem_fun(this, &Viewer::button_press));
-       mouse.signal_button_release.connect(sigc::mem_fun(this, &Viewer::button_release));
-       mouse.signal_axis_motion.connect(sigc::mem_fun(this, &Viewer::axis_motion));
-
-       light.set_position(GL::Vector4(0, 0, 1, 0));
-       lighting.attach(0, light);
-
-       camera.set_up_direction(GL::Vector3(0, 0, 1));
-       update_camera();
-}
-
-Viewer::~Viewer()
-{
-       delete object;
-       delete mesh;
-}
-
-int Viewer::main()
-{
-       window.show();
-       return Application::main();
-}
-
-void Viewer::tick()
-{
-       window.tick();
-
-       GL::Framebuffer::system().clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT);
-
-       camera.apply();
-
-       GL::Bind bind_lighting(lighting);
-       GL::Bind bind_depth(GL::DepthTest::lequal());
-       GL::Bind bind_blend(GL::Blend::alpha());
-       if(object)
-               object->render();
-       else if(mesh)
-               mesh->draw();
-
-       window.swap_buffers();
-}
-
-void Viewer::button_press(unsigned btn)
-{
-       if(btn==1)
-       {
-               dragging = 1;
-       }
-       else if(btn==3)
-       {
-               dragging = 3;
-               axis_motion(0, 0, 0);
-       }
-       else if(btn==4)
-       {
-               distance *= 0.9;
-               update_camera();
-       }
-       else if(btn==5)
-       {
-               distance *= 1.1;
-               update_camera();
-       }
-}
-
-void Viewer::button_release(unsigned btn)
-{
-       if(btn==dragging)
-               dragging = 0;
-}
-
-void Viewer::axis_motion(unsigned axis, float, float delta)
-{
-       if(dragging==1)
-       {
-               float dx = (axis==0 ? delta : 0);
-               float dy = (axis==1 ? delta : 0);
-
-               yaw -= dx*M_PI*2;
-               while(yaw>M_PI)
-                       yaw -= M_PI*2;
-               while(yaw<-M_PI)
-                       yaw += M_PI*2;
-
-               pitch += dy*M_PI;
-               if(pitch>M_PI*0.49)
-                       pitch = M_PI*0.49;
-               if(pitch<-M_PI*0.49)
-                       pitch = -M_PI*0.49;
-
-               update_camera();
-       }
-       else if(dragging==3)
-       {
-               float x = mouse.get_axis_value(0);
-               float y = mouse.get_axis_value(1);
-
-               light_yaw = yaw+x*M_PI;
-               light_pitch = pitch-y*M_PI;
-
-               update_light();
-       }
-}
-
-void Viewer::update_camera()
-{
-       float cy = cos(yaw);
-       float sy = sin(yaw);
-       float cp = cos(pitch);
-       float sp = sin(pitch);
-       camera.set_position(GL::Vector3(-cy*cp*distance, -sy*cp*distance, -sp*distance));
-       camera.set_depth_clip(distance*0.02, distance*50);
-       camera.look_at(GL::Vector3(0, 0, 0));
-}
-
-void Viewer::update_light()
-{
-       float cy = cos(light_yaw);
-       float sy = sin(light_yaw);
-       float cp = cos(light_pitch);
-       float sp = sin(light_pitch);
-       light.set_position(GL::Vector4(-cy*cp, -sy*cp, -sp, 0));
-}