#include #include #include #include #include #include "physics.h" #include "global.h" #include "pocket.h" #include "billiard.h" #include "config.h" #include "graphics.h" // Constants const double FIELD_WIDTH = 0.127; const double FIELD_LENGTH = 0.254; GLfloat LightAmbient[] = { 0.2, 0.2, 0.2, 1.0 }; GLfloat LightDiffuse[] = { 0.8, 0.8, 0.8, 1.0 }; GLfloat LightPosition[] = { FIELD_LENGTH / 2.0, FIELD_WIDTH / 2.0, 0.0, 1.0 }; GLdouble eyex = FIELD_LENGTH / 2.0; GLdouble eyey = FIELD_WIDTH / 2.0; GLdouble eyez = 0.1; GLdouble centerx = FIELD_LENGTH / 2.0; GLdouble centery = FIELD_WIDTH / 2.0; GLdouble centerz = -FIELD_LENGTH / 2.0; void graphics::resize(int width, int height) { // We want to use the whole window glViewport(0, 0, width, height); // 3D-specific OpenGL setup // Modify the projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Set up a perspective view based on our window's aspect ratio gluPerspective(45.0f, (GLdouble)width / (GLdouble)height, 0.1f, 100.0f); // Go back to modifying the modelview matrix (the default) glMatrixMode(GL_MODELVIEW); } bool graphics::init() { // Clear the window to black when we start to draw glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Clear the depth buffer to 1.0 glClearDepth(1.0); glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading // Enable texturing glEnable(GL_TEXTURE_2D); // Initialize our light glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient); glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse); glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); // Enable our light glEnable(GL_LIGHT0); // Don't draw polygons that aren't facing us (big speedup on cheap 486s ;) // glEnable(GL_CULL_FACE); // Have we enabled lighting? TDEGlobal::config()->setGroup("Graphics"); if (TDEGlobal::config()->readBoolEntry("Lighting", true)) { // Turn on lighting glEnable(GL_LIGHTING); // Whenever we use glColor(), set the lighting system automatically know what // the new color is. glEnable(GL_COLOR_MATERIAL); } glDepthFunc(GL_LESS); // The Type Of Depth Test To Do glEnable(GL_DEPTH_TEST); // Enables Depth Testing // Makes texturing drawing slight more accurate glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); return true; } void graphics::startDraw() { // Reset our origin, rotation, and scaling glLoadIdentity(); glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); glTranslatef(0.0, 0.0, -FIELD_LENGTH / 2.0); // Set the camera position and angle gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, 0.0, 0.0, 1.0); // Clear our window to the default color set by glClearColor (i.e. black) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void graphics::endDraw() { // Execute any backlogged commands right now glFlush();; } void graphics::lookAt(GLdouble _eyex, GLdouble _eyey, GLdouble _eyez, GLdouble _centerx, GLdouble _centery, GLdouble _centerz) { // Update our internal viewpoint variables // These values are used in startDraw() to update the view // The eye coordinates are where we're looking from eyex = _eyex; eyey = _eyey; eyez = _eyez; // And the center coordinates are what we're looing at centerx = _centerx; centery = _centery; centerz = _centerz; } // Simple OpenGL wrapper void graphics::setColor(double r, double g, double b) { glColor3d(r, g, b); } void graphics::drawScene() { const TQPtrVector& pockets = KueGlobal::physics()->pockets(); const TQPtrVector& billiards = KueGlobal::physics()->billiards(); // Display the billiards and pockets // The pockets are black without a texture graphics::setColor(0.0, 0.0, 0.0); KueTexture::null().makeCurrent(); // Draw all of the textures for (unsigned int i = 0;i < pockets.size();i++) { if (pockets[i]) disc::draw(pockets[i]->positionX(), pockets[i]->positionY(), pockets[i]->radius()); } // Now we need to turn the color to white, // so we don't interfere with the texture // color graphics::setColor(1.0, 1.0, 1.0); for (unsigned int i = 0;i < billiards.size();i++) { if (billiards[i]) { double circ = billiards[i]->radius() * 2.0 * M_PI; double pos_x = billiards[i]->positionX(); double pos_y = billiards[i]->positionY(); double rot_x = fmod(pos_x, circ) / circ * 360.0; double rot_y = fmod(pos_y, circ) / circ * 360.0; billiards[i]->texture().makeCurrent(); sphere::draw(pos_x, pos_y, billiards[i]->radius(), rot_x, rot_y); } } }