2 #include <msp/core/application.h>
3 #include <msp/core/getopt.h>
4 #include <msp/datafile/directorysource.h>
5 #include <msp/datafile/packsource.h>
6 #include <msp/fs/stat.h>
7 #include <msp/fs/utils.h>
8 #include <msp/graphics/display.h>
9 #include <msp/graphics/window.h>
10 #include <msp/gl/animatedobject.h>
11 #include <msp/gl/animation.h>
12 #include <msp/gl/animationplayer.h>
13 #include <msp/gl/blend.h>
14 #include <msp/gl/camera.h>
15 #include <msp/gl/device.h>
16 #include <msp/gl/directionallight.h>
17 #include <msp/gl/framebuffer.h>
18 #include <msp/gl/lighting.h>
19 #include <msp/gl/mesh.h>
20 #include <msp/gl/object.h>
21 #include <msp/gl/sequence.h>
22 #include <msp/gl/sequencebuilder.h>
23 #include <msp/gl/sequencetemplate.h>
24 #include <msp/gl/renderer.h>
25 #include <msp/gl/resources.h>
26 #include <msp/gl/simplescene.h>
27 #include <msp/gl/technique.h>
28 #include <msp/gl/windowview.h>
29 #include <msp/input/mouse.h>
30 #include <msp/io/print.h>
31 #include <msp/strings/regex.h>
32 #include <msp/time/timestamp.h>
33 #include <msp/time/utils.h>
38 class Viewer: public RegisteredApplication<Viewer>
43 list<string> resource_locations;
44 string animation_name;
45 string renderable_name;
46 Graphics::WindowOptions wnd_opts;
47 Graphics::GLOptions gl_opts;
49 Options(int, char **);
52 class Resources: public GL::Resources
55 DataFile::DirectorySource dir_source;
56 DataFile::PackSource pack_source;
61 void add_directory(const string &);
62 void add_pack(const string &);
66 Graphics::Display display;
67 Graphics::Window window;
72 GL::Sequence *sequence;
73 GL::Renderable *renderable;
74 GL::AnimatedObject *anim_object;
75 GL::AnimationPlayer *anim_player;
76 GL::DirectionalLight light;
77 GL::Lighting lighting;
85 Time::TimeStamp last_tick;
91 T *load(const string &);
99 void button_press(unsigned);
100 void button_release(unsigned);
101 void axis_motion(unsigned, float, float);
103 void update_camera();
108 Viewer::Options::Options(int argc, char **argv)
113 getopt.add_option('r', "resources", resource_locations, GetOpt::REQUIRED_ARG);
114 getopt.add_option('a', "animation", animation_name, GetOpt::REQUIRED_ARG);
115 getopt.add_option('w', "window-size", window_size, GetOpt::REQUIRED_ARG);
116 getopt.add_argument("renderable", renderable_name);
119 wnd_opts.width = 1024;
120 wnd_opts.height = 768;
121 if (!window_size.empty())
123 RegMatch m = Regex("^([1-9][0-9]*)x([1-9][0-9]*)$").match(window_size);
125 throw usage_error("Invalid window size");
127 wnd_opts.width = lexical_cast<unsigned>(m[1].str);
128 wnd_opts.height = lexical_cast<unsigned>(m[2].str);
130 gl_opts.gl_version_major = Graphics::GLOptions::LATEST_VERSION;
131 gl_opts.core_profile = true;
134 Viewer::Viewer(int argc, char **argv):
136 window(display, opts.wnd_opts),
137 gl_device(window, opts.gl_opts),
151 for(list<string>::const_iterator i=opts.resource_locations.begin(); i!=opts.resource_locations.end(); ++i)
154 resources.add_directory(*i);
157 string ext = FS::extpart(*i);
159 resources.add_pack(*i);
161 DataFile::load(resources, *i);
165 GL::Object *object = 0;
167 string ext = FS::extpart(opts.renderable_name);
171 if(FS::exists(opts.renderable_name))
174 DataFile::load(*mesh, opts.renderable_name);
175 resources.add("__"+opts.renderable_name, mesh);
178 mesh = &resources.get<GL::Mesh>(opts.renderable_name);
180 object = new GL::Object;
181 GL::Technique *tech = new GL::Technique;
183 object->set_mesh(mesh);
184 object->set_technique(tech);
187 resources.add("__.tech", tech);
188 resources.add("__.object", object);
190 else if(ext==".object")
191 renderable = load<GL::Object>(opts.renderable_name);
192 else if(ext==".scene")
194 if(FS::exists(opts.renderable_name))
196 GL::Scene::GenericLoader ldr(resources);
197 IO::BufferedFile in(opts.renderable_name);
198 DataFile::Parser parser(in, opts.renderable_name);
200 renderable = ldr.get_object();
203 renderable = &resources.get<GL::Scene>(opts.renderable_name);
207 GL::SequenceTemplate *tmpl = load<GL::SequenceTemplate>(opts.renderable_name);
208 GL::SequenceBuilder bld(*tmpl);
209 bld.set_debug_name(FS::basename(opts.renderable_name));
210 sequence = bld.build(view);
213 throw usage_error("Unknown renderable type");
215 if(!opts.animation_name.empty())
218 throw usage_error("Must have an object to animate");
220 GL::Animation *anim = load<GL::Animation>(opts.animation_name);
221 anim_player = new GL::AnimationPlayer;
222 anim_object = new GL::AnimatedObject(*object);
223 anim_player->play(*anim_object, *anim);
224 renderable = anim_object;
227 window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Viewer::exit), 0));
228 mouse.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &Viewer::button_press), false));
229 mouse.signal_button_release.connect(sigc::bind_return(sigc::mem_fun(this, &Viewer::button_release), false));
230 mouse.signal_axis_motion.connect(sigc::bind_return(sigc::mem_fun(this, &Viewer::axis_motion), false));
232 light.set_direction(GL::Vector3(0, 0, -1));
233 lighting.attach(light);
235 camera.set_debug_name("Camera");
236 camera.set_up_direction(GL::Vector3(0, 0, 1));
241 sequence = new GL::Sequence();
242 sequence->set_debug_name("Sequence");
243 GL::Sequence::Step &step = sequence->add_step(0, *renderable);
244 step.set_lighting(&lighting);
245 step.set_depth_test(GL::LEQUAL);
248 view.set_content(sequence);
249 view.set_camera(&camera);
253 T *Viewer::load(const string &name)
258 DataFile::load(*thing, name, resources);
259 resources.add("__"+name, thing);
263 return &resources.get<T>(name);
276 return Application::main();
283 Time::TimeStamp t = Time::now();
289 anim_player->tick(dt);
296 void Viewer::button_press(unsigned btn)
305 axis_motion(0, 0, 0);
319 void Viewer::button_release(unsigned btn)
325 void Viewer::axis_motion(unsigned axis, float, float delta)
329 float dx = (axis==0 ? delta : 0);
330 float dy = (axis==1 ? delta : 0);
348 float x = mouse.get_axis_value(0);
349 float y = mouse.get_axis_value(1);
351 light_yaw = yaw+x*M_PI;
352 light_pitch = pitch-y*M_PI;
358 void Viewer::update_camera()
362 float cp = cos(pitch);
363 float sp = sin(pitch);
364 camera.set_position(GL::Vector3(-cy*cp*distance, -sy*cp*distance, -sp*distance));
365 camera.set_depth_clip(distance*0.02, distance*50);
366 camera.look_at(GL::Vector3(0, 0, 0));
369 void Viewer::update_light()
371 float cy = cos(light_yaw);
372 float sy = sin(light_yaw);
373 float cp = cos(light_pitch);
374 float sp = sin(light_pitch);
375 light.set_direction(GL::Vector3(cy*cp, sy*cp, sp));
379 Viewer::Resources::Resources()
381 add_source(dir_source);
382 add_source(pack_source);
385 void Viewer::Resources::add_directory(const string &dir)
387 dir_source.add_directory(dir);
390 void Viewer::Resources::add_pack(const string &pack)
392 pack_source.add_pack_file(pack);