Last active
December 18, 2015 02:48
-
-
Save DanielOaks/5713561 to your computer and use it in GitHub Desktop.
OpenGL 2/3d particle test. First time doing anything in C/C++ for years, beware
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
// First (proper) try at OpenGL programming, and first bit of C-like stuff | |
// for years, besides a quick dabble in C# ; caveat emptor | |
// | |
// Daniel Oaks 2013, public domain etc | |
// | |
// g++ -Wall -L/usr/lib -lGL -lGLU -lglut --std=c++11 particles.cpp -o particles | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <random> | |
#include <functional> | |
#include <list> | |
#include <GL/glut.h> | |
using namespace std; | |
#define GRAVITY_STRENGTH (-0.2) | |
#define NUMBER_OF_PARTICLES (30) | |
#define PARTICLE_AGE (60) | |
// Holds X, Y, and Z values, of either direction or forces | |
// | |
class Xyz | |
{ | |
private: | |
float x, y, z; | |
public: | |
float getX(); | |
void setX(float value); | |
void affectX(float value); | |
float getY(); | |
void setY(float value); | |
void affectY(float value); | |
float getZ(); | |
void setZ(float value); | |
void affectZ(float value); | |
}; | |
// X | |
float Xyz::getX() | |
{ | |
return x; | |
} | |
void Xyz::setX(float value) | |
{ | |
x = value; | |
} | |
void Xyz::affectX(float value) | |
{ | |
setX(getX() + value); | |
} | |
// Y | |
float Xyz::getY() | |
{ | |
return y; | |
} | |
void Xyz::setY(float value) | |
{ | |
y = value; | |
} | |
void Xyz::affectY(float value) | |
{ | |
setY(getY() + value); | |
} | |
// Z | |
float Xyz::getZ() | |
{ | |
return z; | |
} | |
void Xyz::setZ(float value) | |
{ | |
z = value; | |
} | |
void Xyz::affectZ(float value) | |
{ | |
setZ(getZ() + value); | |
} | |
// Holds a point, the forces affecting it, and allows simple affecting of it | |
// | |
class Point { | |
private: | |
Xyz forces; | |
void initialize(float position_x, float position_y, float position_z); | |
public: | |
Xyz location; | |
long age; | |
Point(float position_x, float position_y, float position_z); | |
void affect_by_forces(float force_on_x, float force_on_y, float force_on_z); | |
void affect_by_gravity(); | |
void tick(); | |
void draw(); | |
}; | |
Point::Point(float position_x, float position_y, float position_z) | |
{ | |
initialize(position_x, position_y, position_z); | |
} | |
void Point::initialize(float position_x, float position_y, float position_z) | |
{ | |
location.setX(position_x); | |
location.setY(position_y); | |
location.setZ(position_z); | |
forces.setX(0.0); | |
forces.setY(0.0); | |
forces.setZ(0.0); | |
age = PARTICLE_AGE; | |
} | |
void Point::affect_by_forces(float force_on_x, float force_on_y, float force_on_z) | |
{ | |
forces.affectX(force_on_x); | |
forces.affectY(force_on_y); | |
forces.affectZ(force_on_z); | |
} | |
void Point::affect_by_gravity() | |
{ | |
forces.affectY(GRAVITY_STRENGTH); | |
} | |
void Point::tick() | |
{ | |
age--; | |
if (age < 0){ | |
age = 0; | |
} | |
location.affectX(forces.getX()); | |
location.affectY(forces.getY()); | |
location.affectZ(forces.getZ()); | |
} | |
void Point::draw() | |
{ | |
glBegin(GL_POINTS); | |
glColor4f (1.0, (age / (float) PARTICLE_AGE), ((age / 2.3) / (float) PARTICLE_AGE), 1.0); | |
glVertex3f(location.getX(), location.getY(), location.getZ()); | |
glEnd(); | |
} | |
// Main program | |
// | |
// our particles | |
list<Point> particle_list; | |
// random! | |
std::default_random_engine generator; | |
std::uniform_real_distribution<double> distribution(-7.0, 7.0); | |
auto random_force = std::bind(distribution, generator); | |
std::default_random_engine grav_generator; | |
std::uniform_real_distribution<double> grav_distribution(3.5, 10.0); | |
auto random_grav_force = std::bind(grav_distribution, grav_generator); | |
// this makes a gradient background, but that seems to slooooooooow | |
// particles down a whole bunch | |
void drawBackground() | |
{ | |
glBegin(GL_QUADS); | |
//red color | |
glColor4f(0.05,0.0,0.2,1.0); | |
glVertex3f(-1000.0, 1000.0,-1050.0); | |
glVertex3f(-1000.0,-1000.0,-1050.0); | |
//blue color | |
glColor4f(0.05,0.0,0.1,1.0); | |
glVertex3f(1000.0,-1000.0,-1050.0); | |
glVertex3f(1000.0, 1000.0,-1050.0); | |
glEnd(); | |
} | |
void changeSize(int w, int h) | |
{ | |
// prevent divide-by-zero, when window height of zero | |
if(h == 0) { | |
h = 1; | |
} | |
float ratio = (1.0 * w) / h; | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
glViewport(0, 0, w, h); | |
gluPerspective(45, ratio, 1, 1060); | |
glMatrixMode(GL_MODELVIEW); | |
} | |
void renderScene(void) { | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
// draw current particles | |
list<Point>::iterator i; | |
for(i=particle_list.begin(); i != particle_list.end(); ++i) { | |
i->affect_by_gravity(); | |
i->tick(); | |
i->draw(); | |
} | |
// add new particle | |
for(int j = 0; j < NUMBER_OF_PARTICLES; j++) { | |
particle_list.push_back(Point(0.0, -30.0, -1000.0)); | |
particle_list.back().affect_by_forces((float) random_force(), (float) random_force() + (float) random_grav_force(), 0.0); | |
} | |
// remove front particle if possible | |
while (particle_list.front().age == 0) { | |
particle_list.pop_front(); | |
} | |
glutSwapBuffers(); | |
} | |
// ticks drawing function, keeps time in sync and all | |
// so yeah, this doesn't do anything yet... shh, I'll fix it later | |
long milliseconds = 0; | |
void idleTick(void) | |
{ | |
renderScene(); | |
} | |
// actually do all our stuff | |
int main(int argc, char **argv) | |
{ | |
// initialize glut | |
glutInit(&argc, argv); | |
glutInitWindowPosition(30, 30); | |
glutInitWindowSize(500, 500); | |
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); | |
glutCreateWindow("So yeah..."); | |
glClearColor(0.06, 0.0, 0.13, 1.0); | |
// callbacks | |
glutDisplayFunc(renderScene); | |
glutReshapeFunc(changeSize); | |
glutIdleFunc(idleTick); | |
// loop | |
glutMainLoop(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment