X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=tools%2Fviewer.cpp;h=2c950e18e2acc22714ee9d3030ed7467371a0fe0;hp=bc024e1f642eab1fb1814895aeb0cf3ee6654f7a;hb=2b2676392aff2eb6b38c3e463cc67f4d67a4ef8b;hpb=c6a6dd3d7dced09e84d6e51bb5db32aa7c6f2c56 diff --git a/tools/viewer.cpp b/tools/viewer.cpp index bc024e1f..2c950e18 100644 --- a/tools/viewer.cpp +++ b/tools/viewer.cpp @@ -1,8 +1,14 @@ #include #include #include +#include +#include +#include #include #include +#include +#include +#include #include #include #include @@ -10,9 +16,19 @@ #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include using namespace std; using namespace Msp; @@ -20,10 +36,41 @@ using namespace Msp; class Viewer: public RegisteredApplication { private: - Graphics::SimpleGLWindow window; + struct Options + { + list resource_locations; + string animation_name; + string renderable_name; + Graphics::WindowOptions wnd_opts; + Graphics::GLOptions gl_opts; + + Options(int, char **); + }; + + class Resources: public GL::Resources + { + private: + DataFile::DirectorySource dir_source; + DataFile::PackSource pack_source; + + public: + Resources(); + + void add_directory(const string &); + void add_pack(const string &); + }; + + Options opts; + Graphics::Display display; + Graphics::Window window; + Graphics::GLContext gl_ctx; Input::Mouse mouse; - GL::Object *object; - GL::Mesh *mesh; + Resources resources; + GL::WindowView view; + GL::Sequence *sequence; + GL::Renderable *renderable; + GL::AnimatedObject *anim_object; + GL::AnimationPlayer *anim_player; GL::Light light; GL::Lighting lighting; GL::Camera camera; @@ -33,9 +80,14 @@ private: float light_yaw; float light_pitch; unsigned dragging; + Time::TimeStamp last_tick; public: Viewer(int, char **); +private: + template + T *load(const string &); +public: ~Viewer(); virtual int main(); @@ -51,11 +103,42 @@ private: }; +Viewer::Options::Options(int argc, char **argv) +{ + string window_size; + + GetOpt getopt; + getopt.add_option('r', "resources", resource_locations, GetOpt::REQUIRED_ARG); + getopt.add_option('a', "animation", animation_name, GetOpt::REQUIRED_ARG); + getopt.add_option('w', "window-size", window_size, GetOpt::REQUIRED_ARG); + getopt.add_argument("renderable", renderable_name); + getopt(argc, argv); + + wnd_opts.width = 1024; + wnd_opts.height = 768; + if (!window_size.empty()) + { + RegMatch m = Regex("^([1-9][0-9]*)x([1-9][0-9]*)$").match(window_size); + if(!m) + throw usage_error("Invalid window size"); + + wnd_opts.width = lexical_cast(m[1].str); + wnd_opts.height = lexical_cast(m[2].str); + } + gl_opts.gl_version_major = Graphics::GLOptions::LATEST_VERSION; + gl_opts.core_profile = true; +} + Viewer::Viewer(int argc, char **argv): - window(1024, 768, false), + opts(argc, argv), + window(display, opts.wnd_opts), + gl_ctx(window, opts.gl_opts), mouse(window), - object(0), - mesh(0), + view(window, gl_ctx), + sequence(0), + renderable(0), + anim_object(0), + anim_player(0), yaw(0), pitch(0), distance(10), @@ -63,41 +146,124 @@ Viewer::Viewer(int argc, char **argv): light_pitch(0), dragging(0) { - if(argc<2) - throw usage_error("Filename must be provided"); + for(list::const_iterator i=opts.resource_locations.begin(); i!=opts.resource_locations.end(); ++i) + { + if(FS::is_dir(*i)) + resources.add_directory(*i); + else + { + string ext = FS::extpart(*i); + if(ext==".mdp") + resources.add_pack(*i); + else + DataFile::load(resources, *i); + } + } - string fn = argv[1]; - string ext = FS::extpart(fn); + GL::Object *object = 0; + string ext = FS::extpart(opts.renderable_name); if(ext==".mesh") { - mesh = new GL::Mesh; - DataFile::load(*mesh, fn); + GL::Mesh *mesh = 0; + if(FS::exists(opts.renderable_name)) + { + mesh = new GL::Mesh; + DataFile::load(*mesh, opts.renderable_name); + resources.add("__"+opts.renderable_name, mesh); + } + else + mesh = &resources.get(opts.renderable_name); + + object = new GL::Object; + GL::Technique *tech = new GL::Technique; + tech->add_pass(0); + object->set_mesh(mesh); + object->set_technique(tech); + renderable = object; + + resources.add("__.tech", tech); + resources.add("__.object", object); } else if(ext==".object") + renderable = load(opts.renderable_name); + else if(ext==".scene") { - object = new GL::Object; - DataFile::load(*object, fn); + if(FS::exists(opts.renderable_name)) + { + GL::Scene::GenericLoader ldr(resources); + IO::BufferedFile in(opts.renderable_name); + DataFile::Parser parser(in, opts.renderable_name); + ldr.load(parser); + renderable = ldr.get_scene(); + } + else + renderable = &resources.get(opts.renderable_name); + } + else if(ext==".seq") + { + GL::SequenceTemplate *tmpl = load(opts.renderable_name); + GL::SequenceBuilder bld(*tmpl); + sequence = bld.build(view); } else - throw usage_error("Don't know how to view this file"); + throw usage_error("Unknown renderable type"); + + if(!opts.animation_name.empty()) + { + if(!object) + throw usage_error("Must have an object to animate"); + + GL::Animation *anim = load(opts.animation_name); + anim_player = new GL::AnimationPlayer; + anim_object = new GL::AnimatedObject(*object); + anim_player->play(*anim_object, *anim); + renderable = anim_object; + } 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)); + mouse.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &Viewer::button_press), false)); + mouse.signal_button_release.connect(sigc::bind_return(sigc::mem_fun(this, &Viewer::button_release), false)); + mouse.signal_axis_motion.connect(sigc::bind_return(sigc::mem_fun(this, &Viewer::axis_motion), false)); light.set_position(GL::Vector4(0, 0, 1, 0)); - lighting.attach(0, light); + lighting.attach(light); camera.set_up_direction(GL::Vector3(0, 0, 1)); update_camera(); + + if(!sequence) + { + sequence = new GL::Sequence(view); + GL::Sequence::Step &step = sequence->add_step(0, *renderable); + step.set_lighting(&lighting); + step.set_depth_test(GL::LEQUAL); + step.set_blend(GL::Blend(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA)); + } + + view.set_content(sequence); + view.set_camera(&camera); +} + +template +T *Viewer::load(const string &name) +{ + if(FS::exists(name)) + { + T *thing = new T; + DataFile::load(*thing, name, resources); + resources.add("__"+name, thing); + return thing; + } + else + return &resources.get(name); } Viewer::~Viewer() { - delete object; - delete mesh; + delete anim_player; + delete anim_object; + delete sequence; } int Viewer::main() @@ -108,21 +274,19 @@ int Viewer::main() void Viewer::tick() { - window.tick(); - - GL::Framebuffer::system().clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT); - - camera.apply(); + if(anim_player) + { + Time::TimeStamp t = Time::now(); + Time::TimeDelta dt; + if(last_tick) + dt = t-last_tick; + last_tick = t; - 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(); + anim_player->tick(dt); + } - window.swap_buffers(); + display.tick(); + view.render(); } void Viewer::button_press(unsigned btn) @@ -206,3 +370,20 @@ void Viewer::update_light() float sp = sin(light_pitch); light.set_position(GL::Vector4(-cy*cp, -sy*cp, -sp, 0)); } + + +Viewer::Resources::Resources() +{ + add_source(dir_source); + add_source(pack_source); +} + +void Viewer::Resources::add_directory(const string &dir) +{ + dir_source.add_directory(dir); +} + +void Viewer::Resources::add_pack(const string &pack) +{ + pack_source.add_pack_file(pack); +}