00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "common/wave_ex.h"
00022
00023 #include "bvh/bvh.h"
00024 #include "glut-font/glut-font.h"
00025 #include "perf/perf.h"
00026 #include "util/file.h"
00027 #include "wave-glut/camera.h"
00028 #include "wave-glut/glut_2d.h"
00029 #include "wave-glut/wave-glut.h"
00030
00031
00032 static const int s_defaultWidth = 800;
00033 static const int s_defaultHeight = 600;
00034
00035 static int s_retval = 0;
00036
00037 static float s_delta = 1;
00038
00039 static const float s_d2Rotate = 0.25;
00040 static float s_dRotate = 0;
00041
00042 static const int s_maxLight = 4;
00043
00044 static int s_names = 0;
00045
00046 static int s_animSpeed = 0;
00047 static int s_maxSpeed = 2;
00048
00049
00050 static smart_ptr<perf::Timer> s_overallTimer;
00051
00052
00053
00054
00055
00056
00057
00058
00059 static const char *
00060 getSpeed
00061 (
00062 void
00063 )
00064 throw()
00065 {
00066 switch (s_animSpeed) {
00067 case 0: return "stopped";
00068 case 1: return "slow";
00069 case 2: return "normal";
00070 }
00071
00072 return "bogus";
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 class BvhHost : public glut::Host {
00085 public:
00086 BvhHost(void) throw() : m_nodes(NULL) { }
00087 ~BvhHost(void) throw() { }
00088
00089
00090 void init(void);
00091 void display(IN int w, IN int h);
00092 int shutdown(void);
00093 eBehavior keyboard(IN int key, IN int mods);
00094 eBehavior specialKey(IN int key, IN int mods);
00095
00096
00097 static smart_ptr<glut::Host> create(IN const char * directory) {
00098 ASSERT(directory, "null");
00099
00100 smart_ptr<BvhHost> local = new BvhHost;
00101 ASSERT(local, "out of memory");
00102
00103 local->m_dir = directory;
00104
00105 return local;
00106 }
00107
00108 private:
00109
00110 void loadSkeleton(void);
00111 void drawSkeleton(void);
00112
00113
00114 std::string m_file;
00115 std::string m_dir;
00116 VecString m_files;
00117 int m_currFile;
00118 smart_ptr<bvh::Skeleton> m_skeleton;
00119 glut::Viewer m_viewer;
00120 bvh::node_position_t * m_nodes;
00121 int m_nNodes;
00122 perf::time_t m_prevTime;
00123 perf::time_t m_currTime;
00124 float m_animTime;
00125 };
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 void
00136 BvhHost::init
00137 (
00138 void
00139 )
00140 {
00141
00142 walkDirectoryTree(m_dir.c_str(), "bvh", m_files);
00143 DPRINTF("Found %d BVH files", (int) m_files.size());
00144
00145
00146 m_currFile = 0;
00147
00148
00149 this->loadSkeleton();
00150
00151
00152
00153
00154 m_viewer.setPosition(point3d_t(0, 0, -100.0));
00155 }
00156
00157
00158 void
00159 BvhHost::display
00160 (
00161 IN int width,
00162 IN int height
00163 )
00164 {
00165 perf::Timer timer("display");
00166
00167
00168 m_prevTime = m_currTime;
00169
00170
00171 m_currTime = perf::getNow();
00172 static glut::fps_t s_fps(m_currTime);
00173 s_fps.tick(m_currTime);
00174
00175
00176 glClearColor(0.0, 0.0, 0.0, 0.0);
00177 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00178
00179
00180 glut::camera_t camera;
00181 glut::setOpenGLProjection(camera);
00182 glut::setOpenGLViewer(m_viewer);
00183
00184
00185 static float angle = 0.0;
00186 angle += s_dRotate;
00187 glRotatef(angle, 0.0, 1.0, 0.0);
00188
00189
00190 this->drawSkeleton();
00191
00192
00193 glDisable(GL_LIGHTING);
00194
00195
00196 glColor3f(0, 0, 1);
00197 glBegin(GL_LINES);
00198 glVertex3f(0, 1, 0);
00199 glVertex3f(0, 2, 0);
00200 glEnd();
00201
00202 glColor3f(1, 0, 0);
00203 glBegin(GL_LINES);
00204 glVertex3f(1, 0, 0);
00205 glVertex3f(2, 0, 0);
00206 glEnd();
00207
00208 glColor3f(0, 1, 0);
00209 glBegin(GL_LINES);
00210 glVertex3f(0, 0, 1);
00211 glVertex3f(0, 0, 2);
00212 glEnd();
00213
00214
00215
00216
00217
00218
00219
00220 int textHeight = 14;
00221 int lineSpace = 2;
00222 int lineHeight = textHeight + lineSpace;
00223 glColor3f(1.0, 1.0, 1.0);
00224 glut::push2D(width, height);
00225 char buffer[128];
00226
00227 sprintf(buffer, "%s", m_file.c_str());
00228 glut::Font * font = glut::getDefaultFont();
00229 font->display(1, lineHeight, 0, buffer);
00230
00231 sprintf(buffer, "%4.1lf fps", s_fps.getFPS());
00232 font->display(1, 2 * lineHeight, 0, buffer);
00233
00234 sprintf(buffer, "(r/R)otate: %5.2lf degrees/frame", s_dRotate);
00235 font->display(width - 300, height - lineSpace, 0, buffer);
00236
00237 sprintf(buffer, "(a)nimation time: %5.2fs (%s)", m_animTime, getSpeed());
00238 font->display(1, height - lineSpace, 0, buffer);
00239
00240 sprintf(buffer, "(n)ames: %s", (s_names ? "yes" : "no"));
00241 font->display(1, height - lineHeight, 0, buffer);
00242
00243 point3d_t pos = m_viewer.getPosition();
00244 sprintf(buffer, "position: (%f, %f, %f)", pos.x, pos.y, pos.z);
00245 font->display(width - 450, lineHeight, 0, buffer);
00246
00247 glut::pop2D();
00248 }
00249
00250
00251
00252 int
00253 BvhHost::shutdown
00254 (
00255 void
00256 )
00257 {
00258 s_overallTimer = NULL;
00259 perf::dumpTimingSummary(std::cerr);
00260 return 0;
00261 }
00262
00263
00264
00265 glut::Host::eBehavior
00266 BvhHost::keyboard
00267 (
00268 IN int key,
00269 IN int mods
00270 )
00271 {
00272 switch (key) {
00273 case 'q':
00274 case 27:
00275 return eExit;
00276
00277 case 'a':
00278 s_animSpeed++;
00279 if (s_animSpeed > s_maxSpeed) {
00280 s_animSpeed = 0;
00281 }
00282 break;
00283
00284 case 'r':
00285 s_dRotate += s_d2Rotate;
00286 break;
00287
00288 case 'R':
00289 s_dRotate -= s_d2Rotate;
00290 break;
00291
00292 case '+':
00293 case '=':
00294 m_viewer.move(s_delta, 0, 0);
00295 break;
00296
00297 case '-':
00298 m_viewer.move(-s_delta, 0, 0);
00299 break;
00300
00301 case 'n':
00302 s_names = 1 - s_names;
00303 break;
00304 }
00305
00306 return eContinue;
00307 }
00308
00309
00310
00311 glut::Host::eBehavior
00312 BvhHost::specialKey
00313 (
00314 IN int key,
00315 IN int mods
00316 )
00317 {
00318 int deltaF = 0;
00319
00320 switch (key) {
00321 case GLUT_KEY_UP:
00322 m_viewer.move(0, 0, s_delta);
00323 break;
00324
00325 case GLUT_KEY_DOWN:
00326 m_viewer.move(0, 0, -s_delta);
00327 break;
00328
00329 case GLUT_KEY_LEFT:
00330 m_viewer.move(0, -s_delta, 0);
00331 break;
00332
00333 case GLUT_KEY_RIGHT:
00334 m_viewer.move(0, s_delta, 0);
00335 break;
00336
00337 case GLUT_KEY_PAGE_UP:
00338 deltaF = -1;
00339 break;
00340
00341 case GLUT_KEY_PAGE_DOWN:
00342 deltaF = +1;
00343 break;
00344
00345 }
00346
00347 if (deltaF) {
00348 m_currFile += deltaF;
00349 if (m_currFile < 0) {
00350 m_currFile = m_files.size() - 1;
00351 } else if (m_currFile >= (int) m_files.size()) {
00352 m_currFile = 0;
00353 }
00354 this->loadSkeleton();
00355 }
00356
00357 return eContinue;
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 void
00369 BvhHost::loadSkeleton
00370 (
00371 void
00372 )
00373 {
00374 if (m_nodes) {
00375 delete[] m_nodes;
00376 m_nodes = NULL;
00377 }
00378 m_skeleton = NULL;
00379 m_currFile = m_currFile % m_files.size();
00380
00381
00382 m_file = m_files[m_currFile];
00383
00384 std::string path = m_dir;
00385 path += "/";
00386 path += m_file;
00387 m_skeleton = bvh::Skeleton::load(path.c_str());
00388 ASSERT(m_skeleton, "null");
00389 }
00390
00391
00392
00393 void
00394 BvhHost::drawSkeleton
00395 (
00396 void
00397 )
00398 {
00399 perf::Timer timer("drawSkeleton");
00400 if (!m_skeleton)
00401 return;
00402
00403 float deltaT = float(m_currTime.getSeconds() - m_prevTime.getSeconds());
00404 if (1 == s_animSpeed) {
00405 m_animTime += 0.2 * deltaT;
00406 } else if (2 == s_animSpeed) {
00407 m_animTime += deltaT;
00408 }
00409
00410
00411 if (!m_nodes) {
00412 m_nNodes = m_skeleton->getNodeCount(0);
00413 ASSERT(m_nNodes > 0, "bad node count: %d", m_nNodes);
00414
00415 m_nodes = new bvh::node_position_t[m_nNodes];
00416 ASSERT(m_nodes, "out of memory");
00417
00418 m_animTime = 0.0;
00419 }
00420
00421
00422 m_skeleton->getNodePositions(0, m_animTime, m_nodes);
00423
00424
00425 point3d_t avg(0, 0, 0);
00426 for (int i = 0; i < m_nNodes; ++i) {
00427 const bvh::node_position_t&n = m_nodes[i];
00428 avg += n.pos;
00429 }
00430 avg *= (1.0 / m_nNodes);
00431 avg.clear();
00432
00433
00434 float dx = 0.25;
00435 glut::Font * font = glut::getDefaultFont();
00436 for (int i = 0; i < m_nNodes; ++i) {
00437 const bvh::node_position_t&n = m_nodes[i];
00438
00439 point3d_t r = n.pos - avg;
00440
00441
00442 glMatrixMode(GL_MODELVIEW);
00443 glPushMatrix();
00444 glColor3f(0.4, 0.4, 0.4);
00445 glTranslatef(r.x, r.y, r.z);
00446 glutSolidSphere(dx, 8, 8);
00447 glPopMatrix();
00448
00449 if (s_names) {
00450 glColor3f(0, 1, 0);
00451 font->display(r.x, r.y, r.z, n.name);
00452 }
00453
00454
00455 if (n.parent) {
00456 point3d_t q = n.parent->pos - avg;
00457
00458 glColor3f(0.8, 0.3, 0.1);
00459 glBegin(GL_LINES);
00460 glVertex3f(q.x + dx, q.y, q.z);
00461 glVertex3f(r.x + dx, r.y, r.z);
00462 glVertex3f(q.x - dx, q.y, q.z);
00463 glVertex3f(r.x - dx, r.y, r.z);
00464 glVertex3f(q.x, q.y, q.z + dx);
00465 glVertex3f(r.x, r.y, r.z + dx);
00466 glVertex3f(q.x, q.y, q.z - dx);
00467 glVertex3f(r.x, r.y, r.z - dx);
00468 glVertex3f(q.x, q.y + dx, q.z);
00469 glVertex3f(r.x, r.y + dx, r.z);
00470 glVertex3f(q.x, q.y - dx, q.z);
00471 glVertex3f(r.x, r.y - dx, r.z);
00472 glEnd();
00473 }
00474 }
00475 }
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 int
00486 main
00487 (
00488 IN int argc,
00489 IN const char * argv[]
00490 )
00491 {
00492 ASSERT(2 == argc, "Usage: bvhViewer <directory>");
00493 const char * directory = argv[1];
00494
00495 try {
00496 s_overallTimer = new perf::Timer("overall timer");
00497 ASSERT(s_overallTimer, "null");
00498
00499
00500 smart_ptr<glut::Host> host = BvhHost::create(directory);
00501 ASSERT(host, "null");
00502
00503
00504 std::string title = "BVH Viewer: ";
00505 title += directory;
00506
00507 glut::start(argc, argv, s_defaultWidth, s_defaultHeight,
00508 title.c_str(), NULL, host);
00509
00510 } catch (std::exception& e) {
00511 DPRINTF("Exception: %s", e.what());
00512 s_retval = 1;
00513 }
00514
00515 return 1;
00516 }
00517