X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=tools%2Fviewer.cpp;h=d2a384f4e0b2afc112afd7fe3ea62ac3da676237;hp=db2b99e1869d22c6a5bb19b642c4697e5c494e66;hb=ff85f90d33023d908c534b0bf5d9a65e9fc2cce2;hpb=de1e1703104cc7501f6826ada98e1dc11c60eb74 diff --git a/tools/viewer.cpp b/tools/viewer.cpp index db2b99e1..d2a384f4 100644 --- a/tools/viewer.cpp +++ b/tools/viewer.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -13,6 +16,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -25,11 +32,23 @@ using namespace Msp; class Viewer: public RegisteredApplication { private: + 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 &); + }; + Graphics::SimpleGLWindow window; Input::Mouse mouse; - GL::Object *object; - GL::Mesh *mesh; - GL::Animation *animation; + Resources resources; + GL::Renderable *renderable; GL::AnimatedObject *anim_object; GL::AnimationPlayer *anim_player; GL::Light light; @@ -45,6 +64,10 @@ private: public: Viewer(int, char **); +private: + template + T *load(const string &); +public: ~Viewer(); virtual int main(); @@ -63,9 +86,7 @@ private: Viewer::Viewer(int argc, char **argv): window(1024, 768, false), mouse(window), - object(0), - mesh(0), - animation(0), + renderable(0), anim_object(0), anim_player(0), yaw(0), @@ -75,49 +96,81 @@ Viewer::Viewer(int argc, char **argv): light_pitch(0), dragging(0) { - if(argc<2) - throw usage_error("Filename must be provided"); - - for(int i=1; i resource_locations; + string animation_name; + string renderable_name; + GetOpt getopt; + getopt.add_option('r', "resources", resource_locations, GetOpt::REQUIRED_ARG); + getopt.add_option('a', "animation", animation_name, GetOpt::REQUIRED_ARG); + getopt.add_argument("renderable", renderable_name); + getopt(argc, argv); + + for(list::const_iterator i=resource_locations.begin(); i!=resource_locations.end(); ++i) { - string fn = argv[i]; - string ext = FS::extpart(fn); - - if(ext==".mesh") + if(FS::is_dir(*i)) + resources.add_directory(*i); + else { - if(mesh || object) - throw usage_error("Only one mesh or object may be specified"); - - mesh = new GL::Mesh; - DataFile::load(*mesh, fn); + string ext = FS::extpart(*i); + if(ext==".mdp") + resources.add_pack(*i); + else + DataFile::load(resources, *i); } - else if(ext==".object") - { - if(mesh || object) - throw usage_error("Only one mesh or object may be specified"); + } - object = new GL::Object; - DataFile::load(*object, fn); - } - else if(ext==".anim") + GL::Object *object = 0; + + string ext = FS::extpart(renderable_name); + if(ext==".mesh") + { + GL::Mesh *mesh = 0; + if(FS::exists(renderable_name)) { - if(!object) - throw usage_error("An object must be provided for animation"); - - animation = new GL::Animation; - DataFile::load(*animation, argv[2]); - anim_object = new GL::AnimatedObject(*object); - anim_player = new GL::AnimationPlayer; - anim_player->play(*anim_object, *animation); + mesh = new GL::Mesh; + DataFile::load(*mesh, renderable_name); + resources.add("__"+renderable_name, mesh); } else - throw usage_error("Don't know how to view this file"); + mesh = &resources.get(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(renderable_name); + else if(ext==".scene") + { + GL::SimpleScene *scene = new GL::SimpleScene; + DataFile::load(*scene, renderable_name, resources); + renderable = scene; + } + else + throw usage_error("Unknown renderable type"); + + if(!animation_name.empty()) + { + if(!object) + throw usage_error("Must have an object to animate"); + + GL::Animation *anim = load(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); @@ -126,10 +179,24 @@ Viewer::Viewer(int argc, char **argv): update_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; } int Viewer::main() @@ -155,17 +222,11 @@ void Viewer::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(anim_object) - anim_object->render(); - else if(object) - object->render(); - else if(mesh) - mesh->draw(); + GL::Renderer renderer(&camera); + renderer.set_lighting(&lighting); + renderable->render(renderer); window.swap_buffers(); } @@ -251,3 +312,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); +}