/* Libraries we use */ #include #include #include #include #include "wfobj/WFObj.hh" #include "TextureCache/TextureCache.hh" using namespace std; /* Some definitions */ #define WIDTH 800 #define HEIGHT 800 #define TITLE "Josh's Wavefront Object Viewer" TextureCache textureCache; GLuint loadTexture(const char * filename) { return textureCache.load(filename); } class Viewer { public: Viewer(const char * filename); void run(); private: void initgl(); void display(); void setProjection(); WFObj m_obj; GLuint m_list; float m_rotationMatrix[16]; int m_startx, m_starty; bool m_dragging; float m_dist; }; /* The program's main entry point */ int main(int argc, char * argv[]) { if (argc < 2) { cerr << "Usage: " << argv[0] << " " << endl; return -1; } if (SDL_Init(SDL_INIT_VIDEO)) { printf("Failed to initialize SDL!\n"); return -2; } atexit(SDL_Quit); SDL_Surface * screen; SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if (!(screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_OPENGL))) { printf("Failed to set video mode!\n"); SDL_Quit(); return -3; } SDL_WM_SetCaption(TITLE, TITLE); Viewer v(argv[1]); v.run(); return 0; } Viewer::Viewer(const char * filename) { m_dist = 5.0; m_dragging = false; m_obj.load(filename, &loadTexture); m_list = m_obj.render(); /* Print out the object's size */ const float * aabb = m_obj.getAABB(); cout << "Object width: " << (aabb[3]-aabb[0]) << endl; cout << "Object depth: " << (aabb[4]-aabb[1]) << endl; cout << "Object height: " << (aabb[5]-aabb[2]) << endl; } void Viewer::initgl() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_CULL_FACE); glViewport(0, 0, WIDTH, HEIGHT); setProjection(); glLoadIdentity(); glGetFloatv(GL_MODELVIEW_MATRIX, m_rotationMatrix); // float pos[] = {0.0, -1.0, 0.0, 0.0}; // glLightfv(GL_LIGHT0, GL_POSITION, pos); GLfloat lightAmbient[] = {0.2, 0.2, 0.2, 1}; glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); } void Viewer::setProjection() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat)WIDTH/(GLfloat)WIDTH, 0.01, 10000.0); // gluLookAt(0, m_dist, 0, 0, 0, 0, 0, 0, 1); glMatrixMode(GL_MODELVIEW); } void Viewer::display() { glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glLoadIdentity(); gluLookAt(0, -m_dist, 0, 0, 0, 0, 0, 0, 1); glMultMatrixf(m_rotationMatrix); if (m_list) glCallList(m_list); SDL_GL_SwapBuffers(); } void Viewer::run() { initgl(); display(); SDL_Event event; while (SDL_WaitEvent(&event)) { if (event.type == SDL_QUIT) break; else if (event.type == SDL_KEYDOWN) { if (event.key.keysym.sym == SDLK_ESCAPE) break; if (event.key.keysym.sym == SDLK_q) break; } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { if (event.button.state == SDL_PRESSED) { m_dragging = true; m_startx = event.button.x; m_starty = event.button.y; } } else if (event.button.button == 4) { m_dist *= 0.85; if (m_dist < 1.0f) m_dist = 1.0f; setProjection(); display(); } else if (event.button.button == 5) { m_dist *= 1.2; setProjection(); display(); } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { m_dragging = false; } } else if (event.type == SDL_MOUSEMOTION) { if (m_dragging) { glLoadIdentity(); glRotatef(event.motion.y - m_starty, 1, 0, 0); glRotatef(event.motion.x - m_startx, 0, 0, 1); glMultMatrixf(m_rotationMatrix); glGetFloatv(GL_MODELVIEW_MATRIX, m_rotationMatrix); m_startx = event.motion.x; m_starty = event.motion.y; display(); } } } }