#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;
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;
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();
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),
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);
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()
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();
}
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);
+}