]> git.tdb.fi Git - libs/gl.git/blobdiff - tools/viewer.cpp
Make animation curve creation more generic
[libs/gl.git] / tools / viewer.cpp
index bc024e1f642eab1fb1814895aeb0cf3ee6654f7a..d2a384f4e0b2afc112afd7fe3ea62ac3da676237 100644 (file)
@@ -1,8 +1,14 @@
 #include <cmath>
 #include <msp/core/application.h>
 #include <msp/core/getopt.h>
+#include <msp/datafile/directorysource.h>
+#include <msp/datafile/packsource.h>
+#include <msp/fs/stat.h>
 #include <msp/fs/utils.h>
 #include <msp/graphics/simplewindow.h>
+#include <msp/gl/animatedobject.h>
+#include <msp/gl/animation.h>
+#include <msp/gl/animationplayer.h>
 #include <msp/gl/blend.h>
 #include <msp/gl/camera.h>
 #include <msp/gl/framebuffer.h>
 #include <msp/gl/lighting.h>
 #include <msp/gl/mesh.h>
 #include <msp/gl/object.h>
+#include <msp/gl/renderer.h>
+#include <msp/gl/resources.h>
+#include <msp/gl/simplescene.h>
+#include <msp/gl/technique.h>
 #include <msp/gl/tests.h>
 #include <msp/input/mouse.h>
 #include <msp/io/print.h>
+#include <msp/time/timestamp.h>
+#include <msp/time/utils.h>
 
 using namespace std;
 using namespace Msp;
@@ -20,10 +32,25 @@ using namespace Msp;
 class Viewer: public RegisteredApplication<Viewer>
 {
 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;
+       Resources resources;
+       GL::Renderable *renderable;
+       GL::AnimatedObject *anim_object;
+       GL::AnimationPlayer *anim_player;
        GL::Light light;
        GL::Lighting lighting;
        GL::Camera camera;
@@ -33,9 +60,14 @@ private:
        float light_yaw;
        float light_pitch;
        unsigned dragging;
+       Time::TimeStamp last_tick;
 
 public:
        Viewer(int, char **);
+private:
+       template<typename T>
+       T *load(const string &);
+public:
        ~Viewer();
 
        virtual int main();
@@ -54,8 +86,9 @@ private:
 Viewer::Viewer(int argc, char **argv):
        window(1024, 768, false),
        mouse(window),
-       object(0),
-       mesh(0),
+       renderable(0),
+       anim_object(0),
+       anim_player(0),
        yaw(0),
        pitch(0),
        distance(10),
@@ -63,29 +96,81 @@ Viewer::Viewer(int argc, char **argv):
        light_pitch(0),
        dragging(0)
 {
-       if(argc<2)
-               throw usage_error("Filename must be provided");
+       list<string> 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);
 
-       string fn = argv[1];
-       string ext = FS::extpart(fn);
+       for(list<string>::const_iterator i=resource_locations.begin(); i!=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);
+               }
+       }
 
+       GL::Object *object = 0;
+
+       string ext = FS::extpart(renderable_name);
        if(ext==".mesh")
        {
-               mesh = new GL::Mesh;
-               DataFile::load(*mesh, fn);
+               GL::Mesh *mesh = 0;
+               if(FS::exists(renderable_name))
+               {
+                       mesh = new GL::Mesh;
+                       DataFile::load(*mesh, renderable_name);
+                       resources.add("__"+renderable_name, mesh);
+               }
+               else
+                       mesh = &resources.get<GL::Mesh>(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<GL::Object>(renderable_name);
+       else if(ext==".scene")
        {
-               object = new GL::Object;
-               DataFile::load(*object, fn);
+               GL::SimpleScene *scene = new GL::SimpleScene;
+               DataFile::load(*scene, renderable_name, resources);
+               renderable = scene;
        }
        else
-               throw usage_error("Don't know how to view this file");
+               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<GL::Animation>(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);
@@ -94,10 +179,24 @@ Viewer::Viewer(int argc, char **argv):
        update_camera();
 }
 
+template<typename T>
+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<T>(name);
+}
+
 Viewer::~Viewer()
 {
-       delete object;
-       delete mesh;
+       delete anim_player;
+       delete anim_object;
 }
 
 int Viewer::main()
@@ -108,19 +207,26 @@ int Viewer::main()
 
 void Viewer::tick()
 {
+       if(anim_player)
+       {
+               Time::TimeStamp t = Time::now();
+               Time::TimeDelta dt;
+               if(last_tick)
+                       dt = t-last_tick;
+               last_tick = t;
+
+               anim_player->tick(dt);
+       }
+
        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();
+       GL::Renderer renderer(&camera);
+       renderer.set_lighting(&lighting);
+       renderable->render(renderer);
 
        window.swap_buffers();
 }
@@ -206,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);
+}