summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjjesswan <90643397+jjesswan@users.noreply.github.com>2024-05-10 03:41:50 -0400
committerGitHub <noreply@github.com>2024-05-10 03:41:50 -0400
commitb4ca8b708587c540233284beae8d42ff43092580 (patch)
tree05e7902207c5d22044a76d6374dd220a073c8f69 /src
parent80650ec974d661652eceb08616e8659febe2140d (diff)
parent7c0cd109b098b24279fb17b9a05ab846405d169b (diff)
Merge pull request #4 from Seb-Park/new_parti
New parti
Diffstat (limited to 'src')
-rw-r--r--src/arap.h4
-rwxr-xr-xsrc/glwidget.cpp11
-rwxr-xr-xsrc/glwidget.h4
-rw-r--r--src/ocean/ocean_alt.cpp17
-rw-r--r--src/ocean/ocean_alt.h19
-rw-r--r--src/particlesystem.cpp199
-rw-r--r--src/particlesystem.h84
7 files changed, 332 insertions, 6 deletions
diff --git a/src/arap.h b/src/arap.h
index 39b2076..f9dd81e 100644
--- a/src/arap.h
+++ b/src/arap.h
@@ -32,6 +32,9 @@ public:
void move(int vertex, Eigen::Vector3f pos);
void update(double seconds);
+ ocean_alt m_ocean;
+
+
// ================== Students, If You Choose To Modify The Code Below, It's On You
@@ -96,7 +99,6 @@ public:
int m_num_iterations;
const char * m_mesh_path;
- ocean_alt m_ocean;
double m_time = 0.00;
double m_timestep = 0.3;
diff --git a/src/glwidget.cpp b/src/glwidget.cpp
index 6466e24..f8547a6 100755
--- a/src/glwidget.cpp
+++ b/src/glwidget.cpp
@@ -97,6 +97,8 @@ void GLWidget::initializeGL()
m_colorShader = new Shader(":resources/shaders/color.vert", ":resources/shaders/color.frag");
m_foamShader = new Shader(":resources/shaders/foam.vert", ":resources/shaders/foam.frag");
m_skyboxShader = new Shader(":resources/shaders/skybox.vert", ":resources/shaders/skybox.frag");
+ m_particleShader = new Shader(":resources/shaders/particles.vert", ":resources/shaders/particles.frag");
+
m_halftone_tex = loadTextureFromFile(":resources/images/halftone.png").textureID;
@@ -198,6 +200,10 @@ void GLWidget::initializeGL()
m_deltaTimeProvider.start();
m_intervalTimer.start(1000 / 60);
+ // OCEAN SPRAY
+ m_arap.update(0); // important to get initial heights
+ m_particles.init(m_arap.m_ocean.m_heights);
+
}
void GLWidget::paintCaustics() {
@@ -458,6 +464,8 @@ void GLWidget::paintGL()
m_skybox.draw(m_skyboxShader, m_camera);
+ m_particles.draw(m_particleShader, m_camera);
+
@@ -684,7 +692,10 @@ void GLWidget::tick()
float deltaSeconds = m_deltaTimeProvider.restart() / 1000.f;
m_arap.update(deltaSeconds);
// rotate skybox
+ m_particles.setVerts(m_arap.m_ocean.m_heights);
m_skybox.update(deltaSeconds);
+ m_particles.update(deltaSeconds);
+
// Move camera
auto look = m_camera.getLook();
diff --git a/src/glwidget.h b/src/glwidget.h
index 60cca66..50d6347 100755
--- a/src/glwidget.h
+++ b/src/glwidget.h
@@ -1,6 +1,8 @@
#pragma once
#include "skybox.h"
+#include "particlesystem.h"
+
#include <GL/glew.h>
@@ -70,6 +72,7 @@ private:
Shader *m_colorShader;
Shader *m_foamShader;
Shader *m_skyboxShader;
+ Shader *m_particleShader;
@@ -122,4 +125,5 @@ private:
int m_lastSelectedVertex = -1;
skybox m_skybox;
+ particlesystem m_particles;
};
diff --git a/src/ocean/ocean_alt.cpp b/src/ocean/ocean_alt.cpp
index 7523c94..751fca5 100644
--- a/src/ocean/ocean_alt.cpp
+++ b/src/ocean/ocean_alt.cpp
@@ -319,6 +319,7 @@ void ocean_alt::update_ocean()
// reset normals & vertices arrays for the single tile
m_vertices = std::vector<Eigen::Vector3f>(N);
m_normals = std::vector<Eigen::Vector3f>(N);
+ m_heights.clear();
for (int i = 0; i < N; i++){
Eigen::Vector2d horiz_pos = spacing*m_waveIndexConstants[i].base_horiz_pos;
Eigen::Vector2d amplitude = m_current_h[i];
@@ -357,15 +358,20 @@ void ocean_alt::update_ocean()
Eigen::Vector2d disp = lambda*Eigen::Vector2d(m_displacements_x[i][0], m_displacements_z[i][0])
+ Eigen::Vector2d(vertex_displacement, vertex_displacement); // set corner at 0,0 for retiling
+ Eigen::Vector3f v = Eigen::Vector3f(horiz_pos[0] + disp[0], height, horiz_pos[1] + disp[1]);
// for final vertex position, use the real number component of amplitude vector
- m_vertices[i] = {horiz_pos[0] + disp[0], height, horiz_pos[1] + disp[1]};
+ m_vertices[i] = v;
m_normals[i] = norm.normalized();//Eigen::Vector3f(-slope[0], 1.0, -slope[1]).normalized();
//std::cout << "normal: " << m_normals[i] << std::endl
Eigen::Vector2i m_n = index_1d_to_2d(i);
// m_foam_constants.wavelengths[i] = 2.f* M_PI * m_slopes[i].dot(m_slopes[i]) / Lx;
+// float h_0 = m_waveIndexConstants[i].h0_prime[0]; // min*.2f;
+// float h_max = max*.001f; // the smaller the constant, the more foam there is
+// float waveheight = (height - h_0 ) / (h_max - h_0);
+// m_foam_constants.wavelengths[i] = waveheight;
float h_0 = 0; // min*.2f;
float h_max = max*.35f; // the smaller the constant, the more foam there is
m_foam_constants.wavelengths[i] = (height - h_0 ) / (h_max - h_0);
@@ -375,6 +381,15 @@ void ocean_alt::update_ocean()
// std::cout << m_foam_constants.wavelengths[i] << std::endl;
// }
+ if (m_foam_constants.wavelengths[i] >= height_threshold){
+ //std::cout << "push" << std::endl;
+ OceanSpray s;
+ s.height = v;
+ s.slope = norm;
+ s.slope_vector = Eigen::Vector2f(m_slopes_x[i][0], m_slopes_z[i][0]);
+ //std::cout << s.slope_vector << std::endl;
+ m_heights.push_back(s);
+ }
}
diff --git a/src/ocean/ocean_alt.h b/src/ocean/ocean_alt.h
index 9c5e4e2..7e293f9 100644
--- a/src/ocean/ocean_alt.h
+++ b/src/ocean/ocean_alt.h
@@ -27,6 +27,13 @@ struct FoamConstants{
std::vector<Eigen::Vector2f> texCoords;
};
+struct OceanSpray{
+ Eigen::Vector3f height;
+ Eigen::Vector3f slope;
+ Eigen::Vector2f slope_vector;
+
+};
+
class ocean_alt
{
public:
@@ -43,6 +50,8 @@ public:
}
std::vector<Eigen::Vector3f> m_vertices; // current displacement vector for each K
+ std::vector<OceanSpray> m_heights; // stores height above threshold
+
@@ -71,8 +80,8 @@ private:
const double Lx = 512.0;
const double Lz = 512.0;
- const int num_rows = 256;
- const int num_cols = 256;
+ const int num_rows = 256;
+ const int num_cols = 256;
const int num_tiles_x = 1;
const int num_tiles_z = 1;
@@ -83,8 +92,8 @@ private:
const double lambda = .5; // how much displacement matters
const double spacing = 1.0; // spacing between grid points
- const double A = 10000; // numeric constant for the Phillips spectrum
- const double V = 500; // wind speed
+ const double A = 10000; // numeric constant for the Phillips spectrum
+ const double V = 100; // wind speed
const double gravity = 9.81;
const double L = V*V/gravity;
const Eigen::Vector2d omega_wind = Eigen::Vector2d(1.0, 0.0); // wind direction, used in Phillips equation
@@ -102,6 +111,8 @@ private:
// FOR FOAM:
FoamConstants m_foam_constants;
+ float height_threshold = 2.f;
+
float max = 0;
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);
+
+
+}
diff --git a/src/particlesystem.h b/src/particlesystem.h
new file mode 100644
index 0000000..d3b0b8f
--- /dev/null
+++ b/src/particlesystem.h
@@ -0,0 +1,84 @@
+
+#ifndef PARTICLESYSTEM_H
+#define PARTICLESYSTEM_H
+
+#include "ocean/ocean_alt.h"
+#include <iostream>
+#define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
+#define EIGEN_DONT_VECTORIZE
+#include "graphics/shader.h"
+#include "graphics/camera.h"
+
+#include <Eigen/Core>
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+#include <Eigen/Geometry>
+
+struct Particle{
+ Eigen::Vector3f pos = Eigen::Vector3f(0,0,0);
+ Eigen::Vector3f vel = Eigen::Vector3f(0,2000,0);
+
+ Eigen::Vector4f color = Eigen::Vector4f(1,1,1,1);
+ float life = 1.f;
+
+};
+
+class particlesystem
+{
+public:
+ particlesystem();
+
+ void update(double deltaTime);
+ void draw(Shader *skybox_shader, Camera m_camera);
+ void draw(Shader *shader, Camera m_camera, std::vector<Eigen::Vector3f> verts, Eigen::Matrix4f model);
+
+ void init(std::vector<OceanSpray> verts);
+
+ void setVerts(std::vector<OceanSpray> verts){
+ //std::cout << "VERTS SIZE:" << verts.size() << std::endl;
+ m_verts = verts;
+
+ }
+
+
+
+private:
+ int m_amount = 500;
+ int m_new_amount = 100; // new particles per frame
+ int lastUsedIndex = 0;
+ Eigen::Vector3f gravity = Eigen::Vector3f(0,-9.81f,0);
+ float factor = 40.f; // velocity multiplier
+
+
+
+ void respawn_particle(Particle &p, OceanSpray new_pos);
+ int getUnusedParticleIndex();
+ Eigen::Vector3f getRandomInitialVel();
+
+
+
+
+ float d = 2.f;
+ std::vector<float> m_vertices = {
+ -d, d,
+ d,d,
+ -d, -d,
+ d, d,
+ d, -d,
+ -d, -d
+ };
+
+ GLuint VAO, VBO; // holds quad shape
+
+
+
+
+
+
+ std::vector<Particle> m_particles;
+
+ std::vector<OceanSpray> m_verts;
+
+};
+
+#endif // PARTICLESYSTEM_H