Skip to content

Instantly share code, notes, and snippets.

@bitdewy
Created August 10, 2012 10:55
Show Gist options
  • Save bitdewy/3313366 to your computer and use it in GitHub Desktop.
Save bitdewy/3313366 to your computer and use it in GitHub Desktop.
openGL practice - stars
#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;
}
@Manzurul-1998
Copy link

Code isn't compiling.there is an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment