From bdd9a8e26efad3ba349e4ffd58171cfee3cacfb0 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 1 Nov 2010 10:06:53 +0000 Subject: [PATCH] Add a simple object/mesh viewer application --- Build | 10 +++ viewer.cpp | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 viewer.cpp diff --git a/Build b/Build index 71596923..f0abdf8e 100644 --- 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 index 00000000..5ddda479 --- /dev/null +++ b/viewer.cpp @@ -0,0 +1,233 @@ +/* $Id$ + +This file is part of libmspgl +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 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::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 \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)); +} -- 2.43.0