Created
January 10, 2015 14:14
-
-
Save thaenor/4d9531cc9a7d1c34b998 to your computer and use it in GitHub Desktop.
openGL particle rain snow and hail effects
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
// May Ang | |
// [email protected] | |
// CS 161 - Animation & Visualization | |
// Final Project - Rain/Hail/Snow Simulation | |
//source: https://classes.soe.ucsc.edu/cmps161/Winter09/projects/mang/finalproject.html | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <math.h> | |
#include <GL/glut.h> | |
#include <GL/gl.h> | |
#define MAX_PARTICLES 1000 | |
#define WCX 640 | |
#define WCY 480 | |
#define RAIN 0 | |
#define SNOW 1 | |
#define HAIL 2 | |
float slowdown = 2.0; | |
float velocity = 0.0; | |
float zoom = -40.0; | |
float pan = 0.0; | |
float tilt = 0.0; | |
float hailsize = 0.1; | |
int loop; | |
int fall; | |
//floor colors | |
float r = 0.0; | |
float g = 1.0; | |
float b = 0.0; | |
float ground_points[21][21][3]; | |
float ground_colors[21][21][4]; | |
float accum = -10.0; | |
typedef struct { | |
// Life | |
bool alive; // is the particle alive? | |
float life; // particle lifespan | |
float fade; // decay | |
// color | |
float red; | |
float green; | |
float blue; | |
// Position/direction | |
float xpos; | |
float ypos; | |
float zpos; | |
// Velocity/Direction, only goes down in y dir | |
float vel; | |
// Gravity | |
float gravity; | |
}particles; | |
// Paticle System | |
particles par_sys[MAX_PARTICLES]; | |
void normal_keys(unsigned char key, int x, int y) { | |
if (key == 'r') { // Rain | |
fall = RAIN; | |
glutPostRedisplay(); | |
} | |
if (key == 'h') { // Hail | |
fall = HAIL; | |
glutPostRedisplay(); | |
} | |
if (key == 's') { // Snow | |
fall = SNOW; | |
glutPostRedisplay(); | |
} | |
if (key == '=') { //really '+' - make hail bigger | |
hailsize += 0.01; | |
} | |
if (key == '-') { // make hail smaller | |
if (hailsize > 0.1) hailsize -= 0.01; | |
} | |
if (key == ',') { // really '<' slow down | |
if (slowdown > 4.0) slowdown += 0.01; | |
} | |
if (key == '.') { // really '>' speed up | |
if (slowdown > 1.0) slowdown -= 0.01; | |
} | |
if (key == 'q') { // QUIT | |
exit(0); | |
} | |
} | |
void special_keys(int key, int x, int y) { | |
if (key == GLUT_KEY_UP) { | |
zoom += 1.0; | |
} | |
if (key == GLUT_KEY_DOWN) { | |
zoom -= 1.0; | |
} | |
if (key == GLUT_KEY_RIGHT) { | |
pan += 1.0; | |
} | |
if (key == GLUT_KEY_LEFT) { | |
pan -= 1.0; | |
} | |
if (key == GLUT_KEY_PAGE_UP) { | |
tilt -= 1.0; | |
} | |
if (key == GLUT_KEY_PAGE_DOWN) { | |
tilt += 1.0; | |
} | |
} | |
// Initialize/Reset Particles - give them their attributes | |
void initParticles(int i) { | |
par_sys[i].alive = true; | |
par_sys[i].life = 1.0; | |
par_sys[i].fade = float(rand()%100)/1000.0f+0.003f; | |
par_sys[i].xpos = (float) (rand() % 21) - 10; | |
par_sys[i].ypos = 10.0; | |
par_sys[i].zpos = (float) (rand() % 21) - 10; | |
par_sys[i].red = 0.5; | |
par_sys[i].green = 0.5; | |
par_sys[i].blue = 1.0; | |
par_sys[i].vel = velocity; | |
par_sys[i].gravity = -0.8;//-0.8; | |
} | |
void init( ) { | |
int x, z; | |
glShadeModel(GL_SMOOTH); | |
glClearColor(0.0, 0.0, 0.0, 0.0); | |
glClearDepth(1.0); | |
glEnable(GL_DEPTH_TEST); | |
// Ground Verticies | |
// Ground Colors | |
for (z = 0; z < 21; z++) { | |
for (x = 0; x < 21; x++) { | |
ground_points[x][z][0] = x - 10.0; | |
ground_points[x][z][1] = accum; | |
ground_points[x][z][2] = z - 10.0; | |
ground_colors[z][x][0] = r; // red value | |
ground_colors[z][x][1] = g; // green value | |
ground_colors[z][x][2] = b; // blue value | |
ground_colors[z][x][3] = 0.0; // acummulation factor | |
} | |
} | |
// Initialize particles | |
for (loop = 0; loop < MAX_PARTICLES; loop++) { | |
initParticles(loop); | |
} | |
} | |
// For Rain | |
void drawRain() { | |
float x, y, z; | |
for (loop = 0; loop < MAX_PARTICLES; loop=loop+2) { | |
if (par_sys[loop].alive == true) { | |
x = par_sys[loop].xpos; | |
y = par_sys[loop].ypos; | |
z = par_sys[loop].zpos + zoom; | |
// Draw particles | |
glColor3f(0.5, 0.5, 1.0); | |
glBegin(GL_LINES); | |
glVertex3f(x, y, z); | |
glVertex3f(x, y+0.5, z); | |
glEnd(); | |
// Update values | |
//Move | |
// Adjust slowdown for speed! | |
par_sys[loop].ypos += par_sys[loop].vel / (slowdown*1000); | |
par_sys[loop].vel += par_sys[loop].gravity; | |
// Decay | |
par_sys[loop].life -= par_sys[loop].fade; | |
if (par_sys[loop].ypos <= -10) { | |
par_sys[loop].life = -1.0; | |
} | |
//Revive | |
if (par_sys[loop].life < 0.0) { | |
initParticles(loop); | |
} | |
} | |
} | |
} | |
// For Hail | |
void drawHail() { | |
float x, y, z; | |
for (loop = 0; loop < MAX_PARTICLES; loop=loop+2) { | |
if (par_sys[loop].alive == true) { | |
x = par_sys[loop].xpos; | |
y = par_sys[loop].ypos; | |
z = par_sys[loop].zpos + zoom; | |
// Draw particles | |
glColor3f(0.8, 0.8, 0.9); | |
glBegin(GL_QUADS); | |
// Front | |
glVertex3f(x-hailsize, y-hailsize, z+hailsize); // lower left | |
glVertex3f(x-hailsize, y+hailsize, z+hailsize); // upper left | |
glVertex3f(x+hailsize, y+hailsize, z+hailsize); // upper right | |
glVertex3f(x+hailsize, y-hailsize, z+hailsize); // lower left | |
//Left | |
glVertex3f(x-hailsize, y-hailsize, z+hailsize); | |
glVertex3f(x-hailsize, y-hailsize, z-hailsize); | |
glVertex3f(x-hailsize, y+hailsize, z-hailsize); | |
glVertex3f(x-hailsize, y+hailsize, z+hailsize); | |
// Back | |
glVertex3f(x-hailsize, y-hailsize, z-hailsize); | |
glVertex3f(x-hailsize, y+hailsize, z-hailsize); | |
glVertex3f(x+hailsize, y+hailsize, z-hailsize); | |
glVertex3f(x+hailsize, y-hailsize, z-hailsize); | |
//Right | |
glVertex3f(x+hailsize, y+hailsize, z+hailsize); | |
glVertex3f(x+hailsize, y+hailsize, z-hailsize); | |
glVertex3f(x+hailsize, y-hailsize, z-hailsize); | |
glVertex3f(x+hailsize, y-hailsize, z+hailsize); | |
//Top | |
glVertex3f(x-hailsize, y+hailsize, z+hailsize); | |
glVertex3f(x-hailsize, y+hailsize, z-hailsize); | |
glVertex3f(x+hailsize, y+hailsize, z-hailsize); | |
glVertex3f(x+hailsize, y+hailsize, z+hailsize); | |
//Bottom | |
glVertex3f(x-hailsize, y-hailsize, z+hailsize); | |
glVertex3f(x-hailsize, y-hailsize, z-hailsize); | |
glVertex3f(x+hailsize, y-hailsize, z-hailsize); | |
glVertex3f(x+hailsize, y-hailsize, z+hailsize); | |
glEnd(); | |
// Update values | |
//Move | |
if (par_sys[loop].ypos <= -10) { | |
par_sys[loop].vel = par_sys[loop].vel * -1.0; | |
} | |
par_sys[loop].ypos += par_sys[loop].vel / (slowdown*1000); // * 1000 | |
par_sys[loop].vel += par_sys[loop].gravity; | |
// Decay | |
par_sys[loop].life -= par_sys[loop].fade; | |
//Revive | |
if (par_sys[loop].life < 0.0) { | |
initParticles(loop); | |
} | |
} | |
} | |
} | |
// For Snow | |
void drawSnow() { | |
float x, y, z; | |
for (loop = 0; loop < MAX_PARTICLES; loop=loop+2) { | |
if (par_sys[loop].alive == true) { | |
x = par_sys[loop].xpos; | |
y = par_sys[loop].ypos; | |
z = par_sys[loop].zpos + zoom; | |
// Draw particles | |
glColor3f(1.0, 1.0, 1.0); | |
glPushMatrix(); | |
glTranslatef(x, y, z); | |
glutSolidSphere(0.2, 16, 16); | |
glPopMatrix(); | |
// Update values | |
//Move | |
par_sys[loop].ypos += par_sys[loop].vel / (slowdown*1000); | |
par_sys[loop].vel += par_sys[loop].gravity; | |
// Decay | |
par_sys[loop].life -= par_sys[loop].fade; | |
if (par_sys[loop].ypos <= -10) { | |
int zi = z - zoom + 10; | |
int xi = x + 10; | |
ground_colors[zi][xi][0] = 1.0; | |
ground_colors[zi][xi][2] = 1.0; | |
ground_colors[zi][xi][3] += 1.0; | |
if (ground_colors[zi][xi][3] > 1.0) { | |
ground_points[xi][zi][1] += 0.1; | |
} | |
par_sys[loop].life = -1.0; | |
} | |
//Revive | |
if (par_sys[loop].life < 0.0) { | |
initParticles(loop); | |
} | |
} | |
} | |
} | |
// Draw Particles | |
void drawScene( ) { | |
int i, j; | |
float x, y, z; | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
glRotatef(pan, 0.0, 1.0, 0.0); | |
glRotatef(tilt, 1.0, 0.0, 0.0); | |
// GROUND?! | |
glColor3f(r, g, b); | |
glBegin(GL_QUADS); | |
// along z - y const | |
for (i = -10; i+1 < 11; i++) { | |
// along x - y const | |
for (j = -10; j+1 < 11; j++) { | |
glColor3fv(ground_colors[i+10][j+10]); | |
glVertex3f(ground_points[j+10][i+10][0], | |
ground_points[j+10][i+10][1], | |
ground_points[j+10][i+10][2] + zoom); | |
glColor3fv(ground_colors[i+10][j+1+10]); | |
glVertex3f(ground_points[j+1+10][i+10][0], | |
ground_points[j+1+10][i+10][1], | |
ground_points[j+1+10][i+10][2] + zoom); | |
glColor3fv(ground_colors[i+1+10][j+1+10]); | |
glVertex3f(ground_points[j+1+10][i+1+10][0], | |
ground_points[j+1+10][i+1+10][1], | |
ground_points[j+1+10][i+1+10][2] + zoom); | |
glColor3fv(ground_colors[i+1+10][j+10]); | |
glVertex3f(ground_points[j+10][i+1+10][0], | |
ground_points[j+10][i+1+10][1], | |
ground_points[j+10][i+1+10][2] + zoom); | |
} | |
} | |
glEnd(); | |
// Which Particles | |
if (fall == RAIN) { | |
drawRain(); | |
}else if (fall == HAIL) { | |
drawHail(); | |
}else if (fall == SNOW) { | |
drawSnow(); | |
} | |
glutSwapBuffers(); | |
} | |
void reshape(int w, int h) { | |
if (h == 0) h = 1; | |
glViewport(0, 0, w, h); | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
gluPerspective(45, (float) w / (float) h, .1, 200); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
} | |
void idle ( ) { | |
glutPostRedisplay(); | |
} | |
int main (int argc, char** argv) { | |
glutInit(&argc, argv); | |
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE); | |
glutInitWindowSize(WCX, WCY); | |
glutCreateWindow("CMPS 161 - Final Project"); | |
init(); | |
glutDisplayFunc(drawScene); | |
glutReshapeFunc(reshape); | |
glutKeyboardFunc(normal_keys); | |
glutSpecialFunc(special_keys); | |
glutIdleFunc(idle); | |
glutMainLoop(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hey!! i wanted to know how to change the color of snow while it is falling down gradually. ? please help me with this!