]> git.tdb.fi Git - libs/gl.git/commitdiff
Add a simple object/mesh viewer application
authorMikko Rasa <tdb@tdb.fi>
Mon, 1 Nov 2010 10:06:53 +0000 (10:06 +0000)
committerMikko Rasa <tdb@tdb.fi>
Mon, 1 Nov 2010 10:06:53 +0000 (10:06 +0000)
Build
viewer.cpp [new file with mode: 0644]

diff --git a/Build b/Build
index 715969236ad3c787f34602b0d997ff9ba57bcddb..f0abdf8e2f4c1c7a4e61ec2a3034cb0eae2bc3a4 100644 (file)
--- a/Build
+++ b/Build
@@ -30,6 +30,16 @@ package "mspgl"
                };
        };
 
+       program "viewer"
+       {
+               source "viewer.cpp";
+               require "mspfs";
+               build_info
+               {
+                       library "mspgl";
+               };
+       };
+
        tarball "@src"
        {
                source "License.txt";
diff --git a/viewer.cpp b/viewer.cpp
new file mode 100644 (file)
index 0000000..5ddda47
--- /dev/null
@@ -0,0 +1,233 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <cmath>
+#include <msp/core/application.h>
+#include <msp/fs/utils.h>
+#include <msp/gbase/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/io/print.h>
+
+using namespace std;
+using namespace Msp;
+
+class Viewer: public Application
+{
+private:
+       Graphics::SimpleGLWindow window;
+       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;
+       int pointer_x;
+       int pointer_y;
+
+       static Application::RegApp<Viewer> reg;
+
+public:
+       Viewer(int, char **);
+
+       virtual int main();
+private:
+       virtual void tick();
+
+       void button_press(int, int, unsigned, unsigned);
+       void button_release(int, int, unsigned, unsigned);
+       void pointer_motion(int, int);
+       void key_press(unsigned, unsigned, wchar_t);
+
+       void update_camera();
+       void update_light();
+
+public:
+       static void usage(const char *, const char *, bool);
+};
+
+
+Application::RegApp<Viewer> Viewer::reg;
+
+Viewer::Viewer(int argc, char **argv):
+       window(1024, 768, false),
+       object(0),
+       mesh(0),
+       yaw(0),
+       pitch(0),
+       distance(10),
+       light_yaw(0),
+       light_pitch(0),
+       dragging(0),
+       pointer_x(0),
+       pointer_y(0)
+{
+       if(argc<2)
+               throw UsageError("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 UsageError("Don't know how to view this file");
+
+       window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Viewer::exit), 0));
+       window.signal_button_press.connect(sigc::mem_fun(this, &Viewer::button_press));
+       window.signal_button_release.connect(sigc::mem_fun(this, &Viewer::button_release));
+       window.signal_pointer_motion.connect(sigc::mem_fun(this, &Viewer::pointer_motion));
+       window.signal_key_press.connect(sigc::mem_fun(this, &Viewer::key_press));
+
+       light.set_position(GL::Vector4(0, 0, 1, 0));
+       lighting.attach(0, light);
+
+       camera.set_up_direction(GL::Vector3(0, 0, 1));
+       camera.set_position(GL::Vector3(distance, 0, 0));
+       camera.look_at(GL::Vector3(0, 0, 0));
+}
+
+int Viewer::main()
+{
+       window.show();
+       return Application::main();
+}
+
+void Viewer::tick()
+{
+       window.get_display().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::usage(const char *err, const char *argv0, bool)
+{
+       if(err)
+               IO::print("%s\n", err);
+       IO::print("Usage: %s <filename>\n", argv0);
+}
+
+void Viewer::button_press(int x, int y, unsigned btn, unsigned)
+{
+       if(btn==1)
+       {
+               dragging = 1;
+               pointer_x = x;
+               pointer_y = y;
+       }
+       else if(btn==3)
+       {
+               dragging = 3;
+               pointer_motion(x, y);
+       }
+       else if(btn==4)
+       {
+               distance *= 0.9;
+               update_camera();
+       }
+       else if(btn==5)
+       {
+               distance *= 1.1;
+               update_camera();
+       }
+}
+
+void Viewer::button_release(int, int, unsigned btn, unsigned)
+{
+       if(btn==dragging)
+               dragging = 0;
+}
+
+void Viewer::pointer_motion(int x, int y)
+{
+       if(dragging==1)
+       {
+               int dx = x-pointer_x;
+               int dy = pointer_y-y;
+
+               yaw -= dx*M_PI*2/window.get_width();
+               while(yaw>M_PI)
+                       yaw -= M_PI*2;
+               while(yaw<-M_PI)
+                       yaw += M_PI*2;
+
+               pitch += dy*M_PI/window.get_height();
+               if(pitch>M_PI*0.49)
+                       pitch = M_PI*0.49;
+               if(pitch<-M_PI*0.49)
+                       pitch = -M_PI*0.49;
+
+               update_camera();
+
+               pointer_x = x;
+               pointer_y = y;
+       }
+       else if(dragging==3)
+       {
+               int dx = x-window.get_width()/2;
+               int dy = window.get_height()/2-y;
+
+               light_yaw = yaw+dx*M_PI/window.get_width();
+               light_pitch = pitch-dy*M_PI/window.get_height();
+
+               update_light();
+       }
+}
+
+void Viewer::key_press(unsigned, unsigned, wchar_t)
+{
+}
+
+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.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));
+}