- #undef UNICODE
- #include <windows.h>
- #include <iostream>
- #include <vector>
- #include <list>
- #define _USE_MATH_DEFINES
- #define GLUT_DISABLE_ATEXIT_HACK
- #include <math.h>
- #include <ctime>
- #include "GL/glut.h"
- #include <GL/gl.h>
- #include "teksture.h"
- using namespace std;
- static double x, y;
- static double dx = 1;
- static double dy = 0.5;
- static double cr = 0;
- double k;
- struct SParticle
- {
- GLfloat lifetime; //current lifetime of the particle
- GLfloat maximum_lifetime; //time of death of particle
- GLfloat r, g, b; // color values of the particle
- GLfloat xpos, ypos, zpos; // position of the particle
- GLfloat xspeed, yspeed, zspeed; // speed of the particle
- GLfloat ax, ay, az;
- //TODO: add new parameters if needed
- };
- struct SVertex {
- GLfloat tx, ty;
- GLfloat x, y, z;
- };
- const float s = 0.5;
- SVertex bilboard[] =
- {
- { 0, 0, -s, -s, 0 },
- { 0, 1, -s, s, 0 },
- { 1, 1, s, s, 0 },
- { 1, 0, s, -s, 0 }
- };
- const int MAX_PARTICLES = 500;
- list<SParticle> Particles;
- list<SParticle>::iterator particle_iter;
- //TODO: texture for particles - change if You want
- const char texture_name[] = "media//portal1.bmp";
- Ctexture *bilboard_tex;
- //Gaussian random number generator - mean 0.0, standard deviation 1.0
- float NRand()
- {
- static int q = 15;
- static float c1 = (1 << q) - 1;
- static float c2 = ((int)(c1 / 3)) + 1;
- static float c3 = 1.f / c1;
- /* random number in range 0 - 1 not including 1 */
- float random = 0.f;
- /* the white noise */
- float noise = 0.f;
- random = ((float)(rand()) / (float)(RAND_MAX + 1));
- random = (2.f * ((random * c2) + (random * c2) + (random * c2)) - 3.f * (c2 - 1.f)) * c3;
- return random;
- }
- //single bilboard drawing
- void bilboarddrawinglist()
- {
- glNewList(1, GL_COMPILE);
- glPushMatrix();
- // Wlaczamy tablice koordynatow tekstur
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- // Wlaczamy tablice wspolrzednych wierzcholkow
- glEnableClientState(GL_VERTEX_ARRAY);
- glInterleavedArrays(GL_T2F_V3F, 0, (GLvoid*)bilboard);
- glDrawArrays(GL_QUADS, 0, 4);
- glPopMatrix();
- glEndList();
- }
- int initTexture(void)
- {
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- // texture for particle
- bilboard_tex = new Ctexture(texture_name);
- //empty texture, currently not needed
- //tekstury[0] = new Ctexture();
- return true;
- }
- void drawScene(void)
- {
- // Clear screen to background color.
- glClear(GL_COLOR_BUFFER_BIT);
- // Set foreground (or drawing) color.
- glColor3f(1.0, 0.0, 0.0);
- if (bilboard_tex)bilboard_tex->Bind();
- list<SParticle>::iterator currP = Particles.begin();
- //TODO 0: Set proper render states in OpenGL - blending and depth test
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- glDisable(GL_DEPTH_TEST);
- //glEnable() with GL_BLEND, glBlendFunc() with GL_ONE, GL_ONE and glDisable() GL_DEPTH_TEST;
- //notice what happens if they are not set
- //...
- for (unsigned int i = 0; i<Particles.size(); i++, currP++)
- {
- glPushMatrix();
- //Draw particle
- //TODO 1: set particles params like color or size (glColor3f glScalef), position is done for example
- glTranslatef(currP->xpos, currP->ypos, currP->zpos);
- glColor3f(1, 1, 1);
- glScalef(0.1, 0.1, 0.1);
- //...
- //Draw particle
- glCallList(1);
- glPopMatrix();
- }
- glutSwapBuffers();
- }
- // Initialization routine.
- void setup(void)
- {
- x = 0;
- y = 0;
- // Set background (or clearing) color.
- glClearColor(0.0, 0.0, 0.0, 0.0);
- initTexture();
- bilboarddrawinglist();
- }
- // OpenGL window reshape routine.
- void resize(int w, int h)
- {
- // Set viewport size to be entire OpenGL window.
- glViewport(0, 0, (GLsizei)w, (GLsizei)h);
- // Set matrix mode to projection.
- glMatrixMode(GL_PROJECTION);
- // Clear current projection matrix to identity.
- glLoadIdentity();
- // Specify the orthographic (or perpendicular) projection,
- // i.e., define the viewing box.
- gluPerspective(90, (float)w / (float)h, 1, 200);
- //glOrtho(-10.0, 10.0, -10.0, 10.0,-10.0, 10.0);
- //glFrustum(-10.0, 10.0, -10.0, 10.0, 5.0, 100.0);
- // Set matrix mode to modelview.
- glMatrixMode(GL_MODELVIEW);
- // Clear current modelview matrix to identity.
- glLoadIdentity();
- }
- void EmitParticles()
- {
- //TODO 2:
- //Emit particles:
- //set parameters for new particles (SParticle structure),
- //You can add new parameters to the SParticle structure
- //For random numbers use NRand() - Gaussian random number generator - mean 0.0, standard deviation 1.0
- //You should use "for" loop. In each iteration new particle (the variable of type SParticle) should be created.
- //After creation new particle should be pushed front to the list of particles Particles.
- //...
- int pointsCount = 314;
- for (int i = 0; i < pointsCount; i++) {
- SParticle newPart = SParticle();
- newPart.xpos = 5 * sin(i) -10;
- newPart.zpos = 5 * cos(i) -10;
- newPart.ypos = -10;
- newPart.yspeed = 3;
- newPart.zspeed = 0;
- //newPart.az = sin(i) * 4;
- //newPart.ay = 0;
- //newPart.ax = 0;
- newPart.maximum_lifetime = 0.1f + (0.5f + NRand());
- Particles.push_back(newPart);
- }
- }
- void AffectParticles()
- {
- list<SParticle> ParticlesToRemove;
- static std::clock_t oldtime = std::clock();
- std::clock_t newtime = std::clock();
- double timebetweenframes = (double)(newtime - oldtime) / (double)CLOCKS_PER_SEC;
- int frametogrey = 7;
- double greyscale = 0.025;
- particle_iter = Particles.begin();
- while (particle_iter != Particles.end())
- {
- //TODO 3:
- //update particle parameters:
- //position, color (fading color for example), speed(gravity for example)
- //timebetweenframes - delta time, can be used for updating position in current frame like: particle_iter->ypos + particle_iter->yspeed*timebetweenframes
- //particle_iter->lifetime/particle_iter->maximum_lifetime - usefull proportion for changing color and size
- //...
- particle_iter->lifetime += timebetweenframes;
- particle_iter->yspeed += timebetweenframes * particle_iter->ay;
- particle_iter->xspeed += timebetweenframes * particle_iter->ax;
- particle_iter->zspeed += timebetweenframes * particle_iter->az;
- particle_iter->ypos += timebetweenframes * particle_iter->yspeed;
- particle_iter->xpos += timebetweenframes * particle_iter->xspeed;
- particle_iter->zpos += timebetweenframes * particle_iter->zspeed;
- //removing particles
- if (particle_iter->lifetime >= particle_iter->maximum_lifetime)
- {
- //if You need to create particles in place when other died (fireworks particle effect for example)
- //Then You can create them here like in TODO 1
- particle_iter = Particles.erase(particle_iter);
- }
- else
- particle_iter++;
- }
- cout << Particles.size() << endl;
- oldtime = newtime;
- }
- void animate() {
- EmitParticles();
- AffectParticles();
- glutPostRedisplay();
- }
- // Keyboard input processing routine.
- void keyInput(unsigned char key, int x, int y)
- {
- }
- // Mouse callback routine.
- void mouseControl(int button, int state, int x, int y)
- {
- }
- // Main routine: defines window properties, creates window,
- // registers callback routines and begins processing.
- int main(int argc, char **argv)
- {
- // Initialize GLUT.
- glutInit(&argc, argv);
- // Set display mode as single-buffered and RGB color.
- glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
- // Set OpenGL window size.
- glutInitWindowSize(500, 500);
- // Set position of OpenGL window upper-left corner.
- glutInitWindowPosition(100, 100);
- // Create OpenGL window with title.
- glutCreateWindow("Laboratorium GK: 11_OGL");
- // Initialize.
- setup();
- // Register display routine.
- glutDisplayFunc(drawScene);
- // Register reshape routine.
- glutReshapeFunc(resize);
- // Register the mouse and keyboard callback function.
- glutMouseFunc(mouseControl);
- glutKeyboardFunc(keyInput);
- glutIdleFunc(animate);
- // Begin processing.
- glutMainLoop();
- if (bilboard_tex) delete bilboard_tex;
- return 0;
- }