X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=tools%2Fviewer.cpp;fp=tools%2Fviewer.cpp;h=bc024e1f642eab1fb1814895aeb0cf3ee6654f7a;hp=0000000000000000000000000000000000000000;hb=c6a6dd3d7dced09e84d6e51bb5db32aa7c6f2c56;hpb=a5bf02196c301faea88d54933d0586da0aadb614 diff --git a/tools/viewer.cpp b/tools/viewer.cpp new file mode 100644 index 00000000..bc024e1f --- /dev/null +++ b/tools/viewer.cpp @@ -0,0 +1,208 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace Msp; + +class Viewer: public RegisteredApplication +{ +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)); +}