diff options
author | jjesswan <90643397+jjesswan@users.noreply.github.com> | 2024-05-10 03:41:50 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-10 03:41:50 -0400 |
commit | b4ca8b708587c540233284beae8d42ff43092580 (patch) | |
tree | 05e7902207c5d22044a76d6374dd220a073c8f69 /src/particlesystem.cpp | |
parent | 80650ec974d661652eceb08616e8659febe2140d (diff) | |
parent | 7c0cd109b098b24279fb17b9a05ab846405d169b (diff) |
Merge pull request #4 from Seb-Park/new_parti
New parti
Diffstat (limited to 'src/particlesystem.cpp')
-rw-r--r-- | src/particlesystem.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/particlesystem.cpp b/src/particlesystem.cpp new file mode 100644 index 0000000..566667f --- /dev/null +++ b/src/particlesystem.cpp @@ -0,0 +1,199 @@ +#include "particlesystem.h" +#include <iostream> + +particlesystem::particlesystem() +{ + +} + +std::pair<double,double> sample_complex_gaussian(){ + double uniform_1 = (double)rand() / (RAND_MAX); + double uniform_2 = (double)rand() / (RAND_MAX); + + // set a lower bound on zero to avoid undefined log(0) + if (uniform_1 == 0) + { + uniform_1 = 1e-10; + } + if (uniform_2 == 0) + { + uniform_2 = 1e-10; + } + + // real and imaginary parts of the complex number + double real = sqrt(-2*log(uniform_1)) * cos(2*M_PI*uniform_2); + double imag = sqrt(-2*log(uniform_1)) * sin(2*M_PI*uniform_2); + + return std::make_pair(real, imag); +} + +float getRandomInRange(float max, float min){ + return min + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(max-min))); + +} + +float getRandomY(){ + return getRandomInRange(.001,.2); +} + + +Eigen::Vector3f particlesystem::getRandomInitialVel(){ + + + std::pair<float, float> r = sample_complex_gaussian(); + return factor*Eigen::Vector3f(r.first, getRandomY(), r.second); +} + +Eigen::Vector3f getInitVel(OceanSpray s){ + float x = getRandomInRange(0,1); + float y = getRandomInRange(0.1, .9); + Eigen::Vector3f v = Eigen::Vector3f(s.slope_vector[0], y, s.slope_vector[1]) + Eigen::Vector3f(x,0,0); + return v*10.f; + //p.vel[1] = 0.1; + + +} + +void particlesystem::init(std::vector<OceanSpray> verts){ + // make sure to set m_verts + setVerts(verts); + + m_particles.reserve(4000); + + for (auto v : m_verts){ + Particle p; + p.pos = Eigen::Vector3f(v.height); + p.life = getRandomInRange(.1,1); + // p.vel = v.slope*factor; + //p.vel = getRandomInitialVel(); + p.vel = getInitVel(v); + + + m_particles.push_back(p); + } + + + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glBindVertexArray(VAO); + + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, m_vertices.size()*sizeof(float), m_vertices.data(), GL_STATIC_DRAW); + + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (void*)0); + + // unbind + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + + +void particlesystem::update(double deltaTime){ + + // add new particles + for (int i=0; i<m_particles.size(); i++){ + int particle_index = getUnusedParticleIndex(); + if (particle_index == -1) continue; + if (particle_index >= m_particles.size() - 1 || particle_index >= m_verts.size() - 1) continue; + respawn_particle(m_particles[particle_index], m_verts[particle_index]); + + } + + + float dt = deltaTime; + // update all particles values + for (Particle &p : m_particles){ + p.life -= deltaTime * getRandomInRange(.1f, .5f); + + // if particle is still alive, update pos + if (p.life >= 0.f){ + float r = getRandomInRange(.5, 1.6f); + p.vel += gravity*dt*r; + p.pos += p.vel * dt * 10.f; +// p.vel[1] -= (p.vel.dot(p.vel) / 2 + gravity[0]) * dt; +// p.pos += p.vel * dt * 10.f; + } + + if (p.pos[1] < 0.f) p.life = 0.f; + + } +} + + + +// finds the first instance of a particle that is dead, and returns its index so it can be replaced +int particlesystem::getUnusedParticleIndex(){ + + // search from last used index + for (int i=lastUsedIndex; i<m_verts.size(); ++i){ + if (m_particles[i].life <= 0.f){ + lastUsedIndex = i; + return i; + } + } + + // otherwise do linear search up to last used + for (int i=0; i<lastUsedIndex; ++i){ + if (m_particles[i].life <= 0.f){ + lastUsedIndex = i; + return i; + } + } + + // if no dead ones found, don't respawn + lastUsedIndex = 0; + //std::cout << "first particle override!" << std::endl; + return -1; +} + +void particlesystem::respawn_particle(Particle &p, OceanSpray s){ + + p.pos = Eigen::Vector3f(s.height); + p.vel = getInitVel(s); + + + // reset life + p.life = 1.f; + +} + +void particlesystem::draw(Shader *shader, Camera m_camera){ + + shader->bind(); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + + // activate texture +// glActiveTexture(GL_TEXTURE10); +// glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_tex); +// glUniform1i(glGetUniformLocation(shader->id(), "cubeMap"), 9); // bind texture at slot 9 + + + // manually set view and projection, for non-translating view + Eigen::Matrix4f projection = m_camera.getProjection(); + Eigen::Matrix4f view = m_camera.getView(); + // view.col(3) = Eigen::Vector4f(0, 0, 0, 0); + + glUniformMatrix4fv(glGetUniformLocation(shader->id(), "view"), 1, GL_FALSE, view.data()); + glUniformMatrix4fv(glGetUniformLocation(shader->id(), "projection"), 1, GL_FALSE, projection.data()); + // shader->setUniform("model", model); + + int i = 0; + for (Particle p : m_particles){ + if (p.life >= 0.f){ + shader->setUniform("offset", p.pos); + shader->setUniform("alpha", p.life); + + glBindVertexArray(VAO); + glDrawArrays(GL_TRIANGLES, 0, m_vertices.size()); + glBindVertexArray(0); + i++; + } + } + shader->unbind(); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + +} |