// Description: // Block View GL smooth rotation // // Copyright (C) 2003 Frank Becker // // This program is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software // Foundation; either version 2 of the License, or (at your option) any later // version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details // #include "SDL.h" #include #include #include #include #include #include #include #include #include #include #include "BlockViewGLSmooth.hpp" const int VIDEO_ORTHO_WIDTH=1000; const int VIDEO_ORTHO_HEIGHT=750; const float GAMEOVERROTSPEED = 1.0f; BlockViewGLSmooth::BlockViewGLSmooth( BlockModel &model): BlockViewGL(model), _useAALines(false), _gameOverAngle(0.0), _blockFace(0) { XTRACE(); ConfigS::instance()->getBoolean( "aalines", _useAALines); FontManagerS::instance()->reload(); } BlockViewGLSmooth::~BlockViewGLSmooth() { XTRACE(); delete _blockFace; } bool BlockViewGLSmooth::init( void) { bool status = BlockViewGL::init(); if( status) { _smallFont = FontManagerS::instance()->getFont( "bitmaps/arial-small"); if( !_smallFont) { LOG_ERROR << "Unable to get font... (arial-small)" << endl; SDL_QuitSubSystem( SDL_INIT_VIDEO); status = false; } if( !ResourceManagerS::instance()->selectResource( // string("bitmaps/Biohazard3.png"))) string("bitmaps/biohazard.png"))) { LOG_WARNING << "blockPic1.png not found." << endl; return false; } ziStream &bminfile1 = ResourceManagerS::instance()->getInputStream(); SDL_RWops *src = RWops_from_ziStream( bminfile1); SDL_Surface *img1 = IMG_LoadPNG_RW( src); _blockFace = new GLTexture( GL_TEXTURE_2D, img1, false); SDL_FreeRW(src); } return status; } void BlockViewGLSmooth::close( void) { FontManagerS::cleanup(); BlockViewGL::close(); } void BlockViewGLSmooth::update( void) { if( GameState::isAlive) { BlockViewSmooth::update(); } else { _gameOverAngle += GAMEOVERROTSPEED; } } void BlockViewGLSmooth::draw( void) { int blockView = min(_width, _height); glViewport(0,0, blockView, blockView); glEnable( GL_DEPTH_TEST); glEnable( GL_LIGHTING); glEnable( GL_LIGHT0); glShadeModel(GL_SMOOTH); glEnable( GL_NORMALIZE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable( GL_COLOR_MATERIAL ); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); const float fov = 53.13; glFrustum( (3.0/3.0)*(-2.0*tan(fov * M_PI / 360.0)), //xmin (3.0/3.0)*( 2.0*tan(fov * M_PI / 360.0)), //xmax -2.0*tan(fov * M_PI / 360.0), //ymin 2.0*tan(fov * M_PI / 360.0), //ymax 2.0, //znear 2000.0); //zfar glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // glTranslatef( -_cameraX, -_cameraY, -_cameraZ ); glTranslatef( 0, 0,-100); GLfloat light_position[] = { -100.0, 100.0, 100.0, 1.0 }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); #if 0 //show light position glColor4f( 1.0, 1.0, 1.0, 1.0 ); glBegin(GL_QUADS); glNormal3f( 0,0,1); glVertex3f( 40.0, 40.0, -150.0); glVertex3f( 40.0, 60.0, -150.0); glVertex3f( 60.0, 60.0, -150.0); glVertex3f( 60.0, 40.0, -150.0); glEnd(); #endif int w = _model.getWidth(); int h = _model.getHeight(); int d = _model.getDepth(); _squaresize = 200.0f / (float)(max(w,h)); float bottom = -120.0f -((float)d *_squaresize); if( _useAALines) { //AA lines glHint(GL_NICEST,GL_LINE_SMOOTH_HINT); glEnable( GL_LINE_SMOOTH); } // -- Draw the shaft glDisable(GL_DEPTH_TEST); drawShaft(); glEnable(GL_DEPTH_TEST); // -- Draw all the locked elements glPushMatrix(); if( !GameState::isAlive) { float gf = GameState::frameFraction; float interpAngle = _gameOverAngle + (GAMEOVERROTSPEED*gf); glRotatef( interpAngle, 0,0,1); } ElementList::iterator i; glTranslatef( 0-_squaresize*(w-1)/2.0f, 0-_squaresize*(h-1)/2.0f, 0+bottom + _squaresize/2.0f); ElementList &lockedElementList = _model.getLockedElementList(); for( i=lockedElementList.begin(); i!=lockedElementList.end(); i++) { Point3Di *p = *i; drawElement( p, true); } glPopMatrix(); if( GameState::isAlive) { // -- Draw the block glPushMatrix(); // glDisable( GL_LIGHTING); Point3D &interpOffset = getInterpolatedOffset(); glTranslatef( interpOffset.x*_squaresize-_squaresize*(w-1)/2.0f, interpOffset.y*_squaresize-_squaresize*(h-1)/2.0f, interpOffset.z*_squaresize+bottom + _squaresize/2.0f); Point3D ¤tAxis = getCurrentAxis(); Point3D &prevAxis = getPrevAxis(); glRotatef( getInterpolatedAngle(), currentAxis.x, currentAxis.y, currentAxis.z); glRotatef( getPrevAngle(), prevAxis.x, prevAxis.y, prevAxis.z); ElementList &elementList = _model.getElementListNorm(); for( i=elementList.begin(); i!=elementList.end(); i++) { Point3Di *p = *i; drawElement( p, false); } // glEnable( GL_LIGHTING); glPopMatrix(); } else { float gf = GameState::frameFraction; float interpAngle = _gameOverAngle + (GAMEOVERROTSPEED*gf); glRotatef( interpAngle, 0,1,0); glDisable( GL_LIGHTING); glColor4f(1.0,1.0,1.0,1.0); string gameOver = "Game Over!"; _smallFont->DrawString( gameOver.c_str() , -40, 10.0, 0.4, 0.4); string getOut = "Press ESC to exit"; _smallFont->DrawString( getOut.c_str() , -14, 0.0, 0.1, 0.1); glEnable( GL_LIGHTING); } //--- glViewport(blockView,0, _width-blockView, blockView); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum( (1.0/4.0)*(-2.0*tan(fov * M_PI / 360.0)), //xmin (1.0/4.0)*( 2.0*tan(fov * M_PI / 360.0)), //xmax -2.0*tan(fov * M_PI / 360.0), //ymin 2.0*tan(fov * M_PI / 360.0), //ymax 2.0, //znear 2000.0); //zfar glMatrixMode(GL_MODELVIEW); glLoadIdentity(); drawIndicator(); //--- glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-0.5,VIDEO_ORTHO_WIDTH/4+0.5,-0.5,VIDEO_ORTHO_HEIGHT+0.5, -1000.0, 1000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); FPS::Update(); glColor4f(1.0,1.0,1.0,1.0); _smallFont->DrawString( FPS::GetFPSString(), 0, 20, 1.0, 1.0); char num[30]; sprintf( num, "Score: %d", _model.getScore()); _smallFont->DrawString( num, 0, 70, 0.6, 1.0); sprintf( num, "Blocks: %d", _model.getElementCount()); _smallFont->DrawString( num, 0, 120, 0.6, 1.0); sprintf( num, "Level: %d", _model.getLevel()); _smallFont->DrawString( num, 0, 170, 0.6, 1.0); glColor4f(1.0,1.0,1.0,0.5); string cr = "Copyright (C) 2004 by Frank Becker"; _smallFont->DrawString( cr.c_str() , 0, VIDEO_ORTHO_HEIGHT-20.0, 0.4, 0.4); glColor4f(1.0,1.0,1.0,0.5); string gVersion = "v"+GAMEVERSION; float width = _smallFont->GetWidth( gVersion.c_str(), 0.6); _smallFont->DrawString( gVersion.c_str() , (VIDEO_ORTHO_WIDTH/4)-width, 5.0, 0.6, 0.4); SDL_GL_SwapBuffers( ); } void BlockViewGLSmooth::drawIndicator( void) { #if 0 static float r=0; r+= 0.1; glTranslatef( -10, -10,-100); glRotatef( r, 0,1,0); #else glTranslatef( -5, -7,-50); #endif for( int i=0; i<_model.getDepth(); i++) { int count = _model.numBlocksInPlane( i); if( !count) glColor4f( 0.2, 0.2, 0.2, 1.0 ); else setColor( i); glBegin(GL_QUADS); glNormal3f(-1, 1, 1); glVertex3f(-1, (float)i*2.5+1.0, 1); glNormal3f( 1, 1,-1); glVertex3f( 1, (float)i*2.5+1.0, 1); glNormal3f( 1,-1,-1); glVertex3f( 1, (float)i*2.5-1.0, 1); glNormal3f(-1,-1, 1); glVertex3f(-1, (float)i*2.5-1.0, 1); #if 0 glNormal3f(-1, 1, 1); glVertex3f(-1, i*3+1, 1); glNormal3f( 1, 1, 1); glVertex3f( 1, i*3+1, 1); glNormal3f( 1,-1, 1); glVertex3f( 1, i*3-1, 1); glNormal3f(-1,-1, 1); glVertex3f(-1, i*3-1, 1); glNormal3f( 1, 1, 1); glVertex3f( 1, i*3+1, 1); glNormal3f( 1,-1, 1); glVertex3f( 1, i*3-1, 1); glNormal3f( 1,-1,-1); glVertex3f( 1, i*3-1,-1); glNormal3f( 1, 1,-1); glVertex3f( 1, i*3+1,-1); glNormal3f( 1, 1,-1); glVertex3f( 1, i*3+1,-1); glNormal3f(-1, 1,-1); glVertex3f(-1, i*3+1,-1); glNormal3f(-1,-1,-1); glVertex3f(-1, i*3-1,-1); glNormal3f( 1,-1,-1); glVertex3f( 1, i*3-1,-1); glNormal3f(-1, 1,-1); glVertex3f(-1, i*3+1,-1); glNormal3f(-1, 1, 1); glVertex3f(-1, i*3+1, 1); glNormal3f(-1,-1, 1); glVertex3f(-1, i*3-1, 1); glNormal3f(-1,-1,-1); glVertex3f(-1, i*3-1,-1); #endif glEnd(); } } void BlockViewGLSmooth::drawShaft( void) { int w = _model.getWidth(); int h = _model.getHeight(); int d = _model.getDepth(); float tilesize = _squaresize*0.80f; float halfgapsize = (_squaresize-tilesize)/2.0f; float bottom = -120.0f -((float)d *_squaresize); glPushMatrix(); if( !GameState::isAlive) { float gf = GameState::frameFraction; float interpAngle = _gameOverAngle + (GAMEOVERROTSPEED*gf); glRotatef( interpAngle, 0,0,1); } glTranslatef( 0,0,bottom); glBegin(GL_QUADS); glColor4f( 0.0, 1.0, 0.0, 0.5 ); for( int x=0; xx)*_squaresize; float yp = (p->y)*_squaresize; float zp = (p->z)*_squaresize; float halftilesize = (_squaresize*0.80f)/2.0f; float xpm = xp-halftilesize; float xpp = xp+halftilesize; float ypm = yp-halftilesize; float ypp = yp+halftilesize; float zpm = zp-halftilesize; float zpp = zp+halftilesize; float halfmtilesize = (_squaresize*0.60f)/2.0f; float xpmm = xp-halfmtilesize; float xpmp = xp+halfmtilesize; float ypmm = yp-halfmtilesize; float ypmp = yp+halfmtilesize; float zpmm = zp-halfmtilesize; float zpmp = zp+halfmtilesize; if( isLocked) { setColor( p->z); } if( isLocked) { glBegin(GL_QUADS); glNormal3f(-1,-1,1); glVertex3f( xpm, ypm, zpm); glNormal3f( 1,-1,1); glVertex3f( xpp, ypm, zpm); glNormal3f( 1, 1,1); glVertex3f( xpp, ypp, zpm); glNormal3f(-1, 1,1); glVertex3f( xpm, ypp, zpm); glNormal3f(-1, 1,-1); glVertex3f( xpm, ypp, zpp); glNormal3f( 1, 1,-1); glVertex3f( xpp, ypp, zpp); glNormal3f( 1,-1,-1); glVertex3f( xpp, ypm, zpp); glNormal3f(-1,-1,-1); glVertex3f( xpm, ypm, zpp); glEnd(); } else { // glDisable( GL_DEPTH_TEST); glColor4f( 1.0, 1.0, 0.3, 0.8 ); float dx= 1.0/512.0; _blockFace->bind(); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glNormal3f( 0,0,1); glTexCoord2f( dx ,dx ); glVertex3f( xpmm, ypmm, zpmm); glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmp, ypmm, zpmm); glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmp, ypmp, zpmm); glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmm, ypmp, zpmm); glNormal3f( 0,0,-1); glTexCoord2f( dx ,dx ); glVertex3f( xpmm, ypmp, zpmp); glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmp, ypmp, zpmp); glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmp, ypmm, zpmp); glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmm, ypmm, zpmp); glNormal3f( 0, 1,0); glTexCoord2f( dx ,dx ); glVertex3f( xpmp, ypmm, zpmm); glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmm, ypmm, zpmm); glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmm, ypmm, zpmp); glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmp, ypmm, zpmp); glNormal3f( 0,-1,0); glTexCoord2f( dx ,dx ); glVertex3f( xpmp, ypmp, zpmp); glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmm, ypmp, zpmp); glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmm, ypmp, zpmm); glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmp, ypmp, zpmm); glNormal3f( 1,0,0); glTexCoord2f( dx ,dx ); glVertex3f( xpmm, ypmm, zpmm); glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmm, ypmp, zpmm); glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmm, ypmp, zpmp); glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmm, ypmm, zpmp); glNormal3f(-1,0,0); glTexCoord2f( dx ,dx ); glVertex3f( xpmp, ypmm, zpmp); glTexCoord2f( 1.0-dx,dx ); glVertex3f( xpmp, ypmp, zpmp); glTexCoord2f( 1.0-dx,1.0-dx );glVertex3f( xpmp, ypmp, zpmm); glTexCoord2f( dx ,1.0-dx );glVertex3f( xpmp, ypmm, zpmm); glEnd(); glDisable(GL_TEXTURE_2D); // glEnable( GL_DEPTH_TEST); } if( !isLocked) { glDisable( GL_LIGHTING); // glLineWidth(2.0f); glColor4f( 1.0, 1.0, 0.0, 1.0 ); glBegin(GL_LINE_LOOP); glNormal3f( 0,0,1); glVertex3f( xpm, ypm, zpm); glVertex3f( xpp, ypm, zpm); glVertex3f( xpp, ypp, zpm); glVertex3f( xpm, ypp, zpm); glEnd(); glBegin(GL_LINE_LOOP); glNormal3f( 0,0,-1); glVertex3f( xpm, ypm, zpp); glVertex3f( xpp, ypm, zpp); glVertex3f( xpp, ypp, zpp); glVertex3f( xpm, ypp, zpp); glEnd(); glBegin(GL_LINE_LOOP); glNormal3f( 0, 1,0); glVertex3f( xpp, ypm, zpm); glVertex3f( xpm, ypm, zpm); glVertex3f( xpm, ypm, zpp); glVertex3f( xpp, ypm, zpp); glEnd(); glBegin(GL_LINE_LOOP); glNormal3f( 0,-1,0); glVertex3f( xpp, ypp, zpp); glVertex3f( xpm, ypp, zpp); glVertex3f( xpm, ypp, zpm); glVertex3f( xpp, ypp, zpm); glEnd(); glEnable( GL_LIGHTING); } }