Created
August 10, 2012 10:55
-
-
Save bitdewy/3313366 to your computer and use it in GitHub Desktop.
openGL practice - stars
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <map> | |
#include <vector> | |
#include <boost/bind.hpp> | |
#include <boost/function.hpp> | |
#include <boost/noncopyable.hpp> | |
#include <boost/scoped_array.hpp> | |
#include <gl/glut.h> | |
#include <gl/SOIL.h> | |
class KeyboardManger : boost::noncopyable | |
{ | |
public: | |
typedef boost::function<void ()> KeyPressAction; | |
typedef std::map<int, KeyPressAction> KeyActionsMap; | |
KeyboardManger() {} | |
~KeyboardManger() {} | |
void setKeyPressAction(int key, const KeyPressAction& func) { | |
actions_map_.insert(std::pair<int, KeyPressAction>(key, func)); | |
} | |
void processKey(int key) const | |
{ | |
auto it = actions_map_.find(key); | |
if (it != actions_map_.end()) | |
it->second(); | |
else | |
std::cerr << "can't process key " << key << std::endl; | |
} | |
private: | |
KeyActionsMap actions_map_; | |
}; | |
static KeyboardManger normalKeyManager; | |
static KeyboardManger specialKeyManager; | |
struct MovementManager : boost::noncopyable | |
{ | |
MovementManager() | |
: xrotate_(90.f), yrotate_(.0f), zoom_(-15.f) | |
{} | |
~MovementManager() {} | |
void xRotateP() { xrotate_ += .5f; } | |
void xRotateN() { xrotate_ -= .5f; } | |
void yRotateP() { yrotate_ += .5f; } | |
void yRotateN() { yrotate_ -= .5f; } | |
void approach() { | |
if (zoom_ < -4.f) zoom_ += .2f; | |
} | |
void depart() { | |
if (zoom_ > -50.f) zoom_ -= .2f; | |
} | |
GLfloat xrotate_; | |
GLfloat yrotate_; | |
GLfloat zoom_; | |
}; | |
static MovementManager movement; | |
template <typename T, size_t N> | |
struct dimensional | |
{ | |
T& operator[](size_t index) { return data[index]; } | |
const T at(size_t index) const { | |
if (index < 0 || index > N - 1) | |
throw std::out_of_range("index out of range"); | |
return data[index]; | |
} | |
T data[N]; | |
}; | |
template <typename T> | |
class _3D | |
{ | |
public: | |
_3D(T&& arg0, T&& arg1, T&& arg2) { | |
inner_[0] = arg0; | |
inner_[1] = arg1; | |
inner_[2] = arg2; | |
} | |
T& operator[](size_t index) { return inner_.operator[](index); } | |
const T at(size_t index) const { return inner_.at(index); } | |
const T* data() const { return inner_.data; } | |
private: | |
dimensional<T, 3> inner_; | |
}; | |
class Star | |
{ | |
public: | |
Star() | |
: distance_(.0f), angle_(.0f), color_(0, 0, 0) | |
{} | |
~Star() {} | |
void setDistance(GLfloat d) { distance_ = d; } | |
GLfloat distance() const { return distance_; } | |
void setAngle(GLfloat a) { angle_ = a; } | |
GLfloat angle() const { return angle_; } | |
void radomColor() { | |
std::for_each(&color_[0], &color_[0] + sizeof(color_), | |
[](GLubyte& mono){ | |
mono = rand() % 0x100; | |
}); | |
} | |
void draw() { | |
glBegin(GL_QUADS); | |
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); | |
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f); | |
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); | |
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f); | |
glEnd(); | |
} | |
GLubyte R() const { return color_.at(0); } | |
GLubyte G() const { return color_.at(1); } | |
GLubyte B() const { return color_.at(2); } | |
static void addSpin(GLfloat angle) { spin_ += angle; } | |
static GLfloat spin() { return spin_; } | |
private: | |
GLfloat distance_; | |
GLfloat angle_; | |
_3D<GLubyte> color_; | |
static GLfloat spin_; | |
}; | |
GLfloat Star::spin_ = .0f; | |
template <size_t N> | |
class StarManager | |
{ | |
public: | |
StarManager() : twinkle_(false), stars_(new Star[N]) { | |
radomInitStars(); | |
} | |
~StarManager() {} | |
void updateStarPos(size_t i) { | |
stars_[i].addSpin(.01f); | |
GLfloat a = stars[i].angle(); | |
stars_[i].setAngle(a + static_cast<GLfloat>(i) / N); | |
GLfloat dist = stars_[i].distance(); | |
GLfloat inc = .01f; | |
if (dist < inc) { | |
inc = -5.f; | |
stars_[i].radomColor(); | |
} | |
stars_[i].setDistance(dist - inc); | |
} | |
void switchTwinkle() { twinkle_ = !twinkle_; } | |
bool twinkle() const { return twinkle_; } | |
size_t count() const { return N; } | |
Star& operator[](size_t index) const { | |
return stars_[index]; | |
} | |
private: | |
void radomInitStars() { | |
std::for_each(&stars_[0], &stars_[0] + N, | |
[&](Star& s){ | |
s.setDistance(static_cast<GLfloat>(&s - &stars_[0]) / N * 5.f); | |
s.radomColor(); | |
}); | |
} | |
bool twinkle_; | |
boost::scoped_array<Star> stars_; | |
}; | |
static const int kStarCount = 50; | |
static StarManager<kStarCount> stars; | |
class TexturesMangager : boost::noncopyable | |
{ | |
public: | |
TexturesMangager() | |
: texture_index_(0) | |
{} | |
bool addTexture(const char* bitmapFile, | |
GLint minFilter, GLint magFilter, GLuint flags) { | |
auto texture = SOIL_load_OGL_texture(bitmapFile, | |
SOIL_LOAD_AUTO, | |
SOIL_CREATE_NEW_ID, | |
flags); | |
if(texture == 0) | |
return false; | |
glBindTexture(GL_TEXTURE_2D, texture); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); | |
textures_.push_back(texture); | |
return true; | |
} | |
void selectNextTexture() { | |
texture_index_ += 1; | |
if (texture_index_ >= textures_.size()) | |
texture_index_ = 0; | |
glBindTexture(GL_TEXTURE_2D, textures_.at(texture_index_)); | |
} | |
private: | |
size_t texture_index_; | |
std::vector<GLuint> textures_; | |
}; | |
static TexturesMangager textures; | |
GLvoid setKeyActions() | |
{ | |
specialKeyManager.setKeyPressAction(GLUT_KEY_UP, | |
boost::bind(&MovementManager::xRotateN, &movement)); | |
specialKeyManager.setKeyPressAction(GLUT_KEY_DOWN, | |
boost::bind(&MovementManager::xRotateP, &movement)); | |
specialKeyManager.setKeyPressAction(GLUT_KEY_LEFT, | |
boost::bind(&MovementManager::yRotateN, &movement)); | |
specialKeyManager.setKeyPressAction(GLUT_KEY_RIGHT, | |
boost::bind(&MovementManager::yRotateP, &movement)); | |
specialKeyManager.setKeyPressAction(GLUT_KEY_PAGE_UP, | |
boost::bind(&MovementManager::depart, &movement)); | |
specialKeyManager.setKeyPressAction(GLUT_KEY_PAGE_DOWN, | |
boost::bind(&MovementManager::approach, &movement)); | |
normalKeyManager.setKeyPressAction('t', | |
boost::bind(&StarManager<kStarCount>::switchTwinkle, &stars)); | |
normalKeyManager.setKeyPressAction(27, boost::bind(&exit, 0)); | |
} | |
GLvoid display() | |
{ | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
std::for_each(&stars[0], &stars[0] + stars.count(), | |
[](Star& s){ | |
glLoadIdentity(); | |
glTranslatef(.0f, .0f, movement.zoom_); | |
glRotatef(movement.xrotate_, 1.f, .0f, .0f); | |
glRotatef(s.angle(), .0f, 1.f, .0f); | |
glTranslatef(s.distance(), .0f, .0f); | |
glRotatef(-s.angle(), .0f, 1.f, .0f); | |
glRotatef(-movement.xrotate_, 1.f, .0f, .0f); | |
size_t index = &s - &stars[0]; | |
if (stars.twinkle()) { | |
size_t i = stars.count() - 1 - index; | |
glColor4ub(stars[i].R(), stars[i].G(), stars[i].B(), 255); | |
s.draw(); | |
} | |
glRotatef(s.spin(), .0f, .0f, 1.f); | |
glColor4ub(s.R(), s.G(), s.B(), 0xFF); | |
s.draw(); | |
stars.updateStarPos(index); | |
}); | |
glFlush(); | |
} | |
GLvoid refresh(GLint) | |
{ | |
glutPostRedisplay(); | |
glutTimerFunc(20, refresh, 0); | |
} | |
GLvoid reshape(GLsizei width, GLsizei height) | |
{ | |
glViewport(0, 0, width, height); | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
gluPerspective(45., static_cast<GLdouble>(width)/height, .1, 100.); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
} | |
inline GLvoid processNormalKeyPress(unsigned char key, int x, int y) | |
{ | |
normalKeyManager.processKey(static_cast<int>(key)); | |
} | |
inline GLvoid processSpecialKeyPress(int key, int x, int y) | |
{ | |
specialKeyManager.processKey(key); | |
} | |
GLvoid initGL(GLvoid) | |
{ | |
textures.addTexture("Data/star.bmp", | |
GL_LINEAR, GL_LINEAR, SOIL_FLAG_INVERT_Y); | |
textures.selectNextTexture(); | |
glEnable(GL_TEXTURE_2D); | |
glShadeModel(GL_SMOOTH); | |
glClearDepth(1.); | |
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); | |
glClearColor(.0f, .0f, .0f, .5f); | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE); | |
glEnable(GL_BLEND); | |
setKeyActions(); | |
} | |
int main(int argc, char** argv) | |
{ | |
glutInit(&argc, argv); | |
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); | |
glutInitWindowSize(500, 500); | |
glutInitWindowPosition(150, 150); | |
glutCreateWindow("bitdewy openGL practice"); | |
glutReshapeFunc(reshape); | |
glutKeyboardFunc(processNormalKeyPress); | |
glutSpecialFunc(processSpecialKeyPress); | |
initGL(); | |
glutDisplayFunc(display); | |
glutTimerFunc(50, refresh, 0); | |
glutMainLoop(); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Code isn't compiling.there is an error.