150 lines
7.4 KiB
C++
150 lines
7.4 KiB
C++
// Taken from https://github.com/jeschke/water-wave-packets
|
|
#pragma once
|
|
|
|
#include "constants.h"
|
|
|
|
#include <iostream>
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wint-in-bool-context"
|
|
#include <Eigen/Dense>
|
|
#pragma GCC diagnostic pop
|
|
|
|
using namespace Eigen;
|
|
using namespace std;
|
|
|
|
|
|
// simulation parameters
|
|
#define PACKET_SPLIT_ANGLE 0.95105f // direction angle variation threshold: 0.95105=18 degree
|
|
#define PACKET_SPLIT_DISPERSION 0.3f // if the fastest wave in a packet traveled PACKET_SPLIT_DISPERSION*Envelopesize ahead, or the slowest by the same amount behind, subdivide this packet into two wavelength intervals
|
|
#define PACKET_KILL_AMPLITUDE_DERIV 0.0001f // waves below this maximum amplitude derivative gets killed
|
|
#define PACKET_BLEND_TRAVEL_FACTOR 1.0f // in order to be fully blended (appear or disappear), any wave must travel PACKET_BLEND_TRAVEL_FACTOR times "envelope size" in space (1.0 is standard)
|
|
#define PACKET_ENVELOPE_SIZE_FACTOR 3.0f // size of the envelope relative to wavelength (determines how many "bumps" appear)
|
|
#define PACKET_ENVELOPE_MINSIZE 0.02f // minimum envelope size in meters (smallest expected feature)
|
|
#define PACKET_ENVELOPE_MAXSIZE 10.0f // maximum envelope size in meters (largest expected feature)
|
|
#define PACKET_BOUNCE_FREQSPLIT true // (boolean) should a wave packet produce smaller waves at a bounce/reflection (->widen the wavelength interval of this packet)?
|
|
#define PACKET_BOUNCE_FREQSPLIT_K 31.4f // if k_L is smaller than this value (lambda = 20cm), the wave is (potentially) split after a bounce
|
|
#define MAX_SPEEDNESS 0.07f // all wave amplitudes a are limited to a <= MAX_SPEEDNESS*2.0*M_PI/k
|
|
|
|
// physical parameters
|
|
#define SIGMA 0.074f // surface tension N/m at 20 grad celsius
|
|
#define GRAVITY 9.81f // GRAVITY m/s^2
|
|
#define DENSITY 998.2071f // water density at 20 degree celsius
|
|
#define KINEMATIC_VISCOSITY 0.0000089f // kinematic viscosity
|
|
#define PACKET_SLOWAVE_K 143.1405792f // k of the slowest possible wave packet
|
|
#define PACKET_SLOWAVE_W0 40.2646141f // w_0 of the slowest possible wave packet
|
|
|
|
// memory management
|
|
#define PACKET_BUFFER_DELTA 500000 // initial number of vertices, packet memory will be increased on demand by this stepsize
|
|
|
|
|
|
|
|
|
|
struct WAVE_PACKET
|
|
{
|
|
// positions, directions, speed of the tracked vertices
|
|
Vector2f pos1,pos2,pos3; // 2D position
|
|
Vector2f dir1,dir2,dir3; // current movement direction
|
|
float speed1,speed2,speed3; // speed of the particle
|
|
Vector2f pOld1,pOld2,pOld3; // position in last timestep (needed to handle bouncing)
|
|
Vector2f dOld1,dOld2,dOld3; // direction in last timestep (needed to handle bouncing)
|
|
float sOld1,sOld2,sOld3; // speed in last timestep (needed to handle bouncing)
|
|
Vector2f midPos; // middle position (tracked each timestep, used for rendering)
|
|
Vector2f travelDir; // travel direction (tracked each timestep, used for rendering)
|
|
float bending; // point used for circular arc bending of the wave function inside envelope
|
|
|
|
// bouncing and sliding
|
|
bool bounced1, bounced2, bounced3; // indicates if this vertex bounced in this timestep
|
|
bool sliding3; // indicates if the 3rd vertex is "sliding" (used for diffraction)
|
|
bool use3rd; // indicates if the third vertex is present (it marks a (potential) sliding point)
|
|
// wave function related
|
|
float phase; // phase of the representative wave inside the envelope, phase speed vs. group speed
|
|
float phOld; // old phase
|
|
float E; // wave energy flux for this packet (determines amplitude)
|
|
float envelope; // envelope size for this packet
|
|
float k,w0; // w0 = angular frequency, k = current wavenumber
|
|
float k_L,w0_L,k_H,w0_H; // w0 = angular frequency, k = current wavenumber, L/H are for lower/upper boundary
|
|
float d_L,d_H; // d = travel distance to reference wave (gets accumulated over time), L/H are for lower/upper boundary
|
|
float ampOld; // amplitude from last timestep, will be smoothly adjusted in each timestep to meet current desired amplitude
|
|
float dAmp; // amplitude change in each timestep (depends on desired waveheight so all waves (dis)appear with same speed)
|
|
// serial deletion step variable
|
|
bool toDelete; // used internally for parallel deletion criterion computation
|
|
public:
|
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
|
};
|
|
|
|
|
|
|
|
struct GHOST_PACKET
|
|
{
|
|
Vector2f pos; // 2D position
|
|
Vector2f dir; // current movement direction
|
|
float speed; // speed of the packet
|
|
float envelope; // envelope size for this packet
|
|
float bending; // point used for circular arc bending of the wave function inside envelope
|
|
float k; // k = current (representative) wavenumber(s)
|
|
float phase; // phase of the representative wave inside the envelope
|
|
float dPhase; // phase speed relative to group speed inside the envelope
|
|
float ampOld; // amplitude from last timestep, will be smoothly adjusted in each timestep to meet current desired amplitude
|
|
float dAmp; // change in amplitude in each timestep (waves travel PACKET_BLEND_TRAVEL_FACTOR*envelopesize in space until they disappear)
|
|
public:
|
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
|
};
|
|
|
|
|
|
class Packets
|
|
{
|
|
public:
|
|
// scene
|
|
int m_groundSizeX, m_groundSizeY; // pixel size of the ground texture
|
|
float *m_ground; // texture containing the water depth and land (0.95)
|
|
float *m_distMap; // distance map of the boundary map
|
|
Vector2f *m_gndDeriv;
|
|
Vector2f *m_bndDeriv;
|
|
|
|
// packet managing
|
|
WAVE_PACKET *m_packet; // wave packet data
|
|
GHOST_PACKET*m_ghostPacket; // ghost packet data
|
|
int m_packetBudget; // this can be changed any time (soft budget)
|
|
int m_packetNum; // current size of the buffer used for packets / ghosts
|
|
float m_softDampFactor;
|
|
int *m_usedPacket;
|
|
int m_usedPackets;
|
|
int *m_freePacket;
|
|
int m_freePackets;
|
|
int *m_usedGhost;
|
|
int m_usedGhosts;
|
|
int *m_freeGhost;
|
|
int m_freeGhosts;
|
|
|
|
// simulation
|
|
float m_time;
|
|
float m_oldTime;
|
|
float m_elapsedTime;
|
|
|
|
public:
|
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
|
Packets(int packetBudget);
|
|
~Packets(void);
|
|
void Reset();
|
|
float GetBoundaryDist(Vector2f &p);
|
|
Vector2f GetBoundaryNormal(Vector2f &p);
|
|
float GetGroundVal(Vector2f &p);
|
|
Vector2f GetGroundNormal(Vector2f &p);
|
|
float GetWaterDepth(Vector2f &p);
|
|
void UpdateTime(float dTime);
|
|
void ExpandWavePacketMemory(int targetNum);
|
|
int GetFreePackedID();
|
|
void DeletePacket(int id);
|
|
int GetFreeGhostID();
|
|
void DeleteGhost(int id);
|
|
void CreatePacket(float pos1x, float pos1y, float pos2x, float pos2y, float dir1x, float dir1y, float dir2x, float dir2y, float k_L, float k_H, float E);
|
|
void CreateLinearWavefront(float xPos, float yPos, float dirx, float diry, float crestlength, float lambda_L, float lambda_H, float E);
|
|
void CreateSpreadingPacket(float xPos, float yPos, float dirx, float diry, float spreadFactor, float crestlength, float lambda_L, float lambda_H, float E);
|
|
void CreateCircularWavefront(float xPos, float yPos, float radius, float lambda_L, float lambda_H, float E);
|
|
void GetWaveParameters(float waterDepth, float w0, float kIn, float &k_out, float &speed_out);
|
|
float GetPhaseSpeed(float w_0, float kIn);
|
|
float GetWaveAmplitude(float area, float E, float k);
|
|
float GetIntersectionDistance(Vector2f pos1, Vector2f dir1, Vector2f pos2, Vector2f dir2);
|
|
bool AdvectPacketVertex(float elapsedTime, Vector2f &posIn, Vector2f &dirIn, float w0, float &kIn, float &speedIn, Vector2f &posOut, Vector2f &dirOut, float &speedOut);
|
|
void AdvectWavePackets(float dTime);
|
|
};
|