#include
#include
#include
#include
#define _USE_MATH_DEFINES
#define GLUT_DISABLE_ATEXIT_HACK
#include
#include
#include "GL/glut.h"
#include
#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
list
//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
//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
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
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;
}