143 lines
4.4 KiB
C
143 lines
4.4 KiB
C
|
#pragma once
|
|||
|
#include "glew.h"
|
|||
|
#include <GLFW/glfw3.h>
|
|||
|
#include "glm.hpp"
|
|||
|
#include <list>
|
|||
|
#include "ext.hpp"
|
|||
|
|
|||
|
|
|||
|
struct Particle
|
|||
|
{
|
|||
|
public:
|
|||
|
float birthTime;
|
|||
|
glm::vec3 startPosition;
|
|||
|
glm::vec3 direction;
|
|||
|
glm::vec3 randomPointOnCircle;
|
|||
|
|
|||
|
float getAge(float time) {
|
|||
|
return time - birthTime;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
class ParticleSystem
|
|||
|
{
|
|||
|
private:
|
|||
|
std::list<Particle> particles;
|
|||
|
GLuint VBO;
|
|||
|
GLuint VAO;
|
|||
|
GLfloat vertices[9];
|
|||
|
float lastGenerated = -1.f;
|
|||
|
|
|||
|
bool shouldGenerateNewParticle(float time) {
|
|||
|
return lastGenerated == -1.f || time - lastGenerated > generationInterval;
|
|||
|
}
|
|||
|
|
|||
|
glm::vec3 generateRandomPointOnCircle() {
|
|||
|
float distanceFromCenter = static_cast <float> (rand()) / static_cast <float> (RAND_MAX/sourceRadius);
|
|||
|
float radians = static_cast <float> (rand()) / static_cast <float> (RAND_MAX / 6.28f);
|
|||
|
|
|||
|
glm::vec3 referenceVector(0.0f, 1.0f, 0.0f);
|
|||
|
glm::vec3 output = glm::normalize(glm::cross(sourceDirection, referenceVector)) * distanceFromCenter;
|
|||
|
|
|||
|
glm::mat4 rotationMatrix = glm::rotate(glm::mat4(1.0f), radians, sourceDirection);
|
|||
|
output = glm::vec3(rotationMatrix * glm::vec4(output, 1.0f));
|
|||
|
|
|||
|
return output;
|
|||
|
}
|
|||
|
|
|||
|
void generateNewParticle(float time) {
|
|||
|
Particle newParticle;
|
|||
|
newParticle.birthTime = time;
|
|||
|
newParticle.startPosition = sourcePosition;
|
|||
|
newParticle.randomPointOnCircle = generateRandomPointOnCircle();
|
|||
|
newParticle.direction = sourceDirection;
|
|||
|
particles.push_back(newParticle);
|
|||
|
lastGenerated = time;
|
|||
|
}
|
|||
|
|
|||
|
void deleteOld(float time) {
|
|||
|
auto it = particles.begin();
|
|||
|
|
|||
|
while (it != particles.end()) {
|
|||
|
if ((*it).getAge(time) > lifetime) {
|
|||
|
it = particles.erase(it);
|
|||
|
}
|
|||
|
else {
|
|||
|
++it;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
glm::vec3 calculateParticleColor(float age) {
|
|||
|
float rate = glm::clamp(age / lifetime, 0.f, 1.f);
|
|||
|
glm::vec3 mixedColor = (1.0f - rate) * startColor + rate * endColor;
|
|||
|
return mixedColor;
|
|||
|
}
|
|||
|
|
|||
|
public:
|
|||
|
glm::vec3 sourcePosition;
|
|||
|
float sourceRadius = 0.02f;
|
|||
|
glm::vec3 sourceDirection = glm::vec3(1.f, 0.f, 0.f);
|
|||
|
float generationInterval = 0.0025f;
|
|||
|
float lifetime = 0.5f;
|
|||
|
float speed = 100.f;
|
|||
|
glm::vec3 startColor = glm::vec3(1.f, 0.f, 0.f);
|
|||
|
glm::vec3 endColor = glm::vec3(1.f, 1.f, 0.f);
|
|||
|
|
|||
|
ParticleSystem() {
|
|||
|
// Inicjalizacja wierzcho<68>k<EFBFBD>w tr<74>jk<6A>ta w 3D
|
|||
|
vertices[0] = -0.5f; vertices[1] = -0.5f; vertices[2] = 0.0f;
|
|||
|
vertices[3] = 0.5f; vertices[4] = -0.5f; vertices[5] = 0.0f;
|
|||
|
vertices[6] = 0.0f; vertices[7] = 0.5f; vertices[8] = 0.0f;
|
|||
|
|
|||
|
glGenBuffers(1, &VBO);
|
|||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
|||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
|||
|
|
|||
|
glGenVertexArrays(1, &VAO);
|
|||
|
glBindVertexArray(VAO);
|
|||
|
|
|||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
|||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
|
|||
|
glEnableVertexAttribArray(0);
|
|||
|
|
|||
|
glBindVertexArray(0);
|
|||
|
}
|
|||
|
|
|||
|
void drawParticles(GLuint program, glm::mat4 view, glm::mat4 projection, float time) {
|
|||
|
if (shouldGenerateNewParticle(time)) {
|
|||
|
generateNewParticle(time);
|
|||
|
}
|
|||
|
|
|||
|
deleteOld(time);
|
|||
|
|
|||
|
glUseProgram(program);
|
|||
|
GLuint modelLoc = glGetUniformLocation(program, "model");
|
|||
|
GLuint viewLoc = glGetUniformLocation(program, "view");
|
|||
|
GLuint projectionLoc = glGetUniformLocation(program, "projection");
|
|||
|
GLuint colorLoc = glGetUniformLocation(program, "color");
|
|||
|
|
|||
|
int i = 0;
|
|||
|
for (auto particle : particles) {
|
|||
|
glm::vec3 color = calculateParticleColor(particle.getAge(time));
|
|||
|
glUniform3f(colorLoc, color.x, color.y, color.z);
|
|||
|
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
|||
|
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
|||
|
|
|||
|
glm::mat4 model = glm::translate(glm::mat4(1.0f), sourcePosition + particle.randomPointOnCircle);
|
|||
|
model = glm::scale(model, glm::vec3(0.005f, 0.005f, 0.005f));
|
|||
|
model = glm::translate(model, particle.direction * speed * (time - particle.birthTime));
|
|||
|
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
|||
|
|
|||
|
glBindVertexArray(VAO);
|
|||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
|||
|
i++;
|
|||
|
}
|
|||
|
|
|||
|
glBindVertexArray(0);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|