2017-11-25 21:18:26 +00:00
// Taken from https://github.com/jeschke/water-wave-packets
# pragma once
# include "constants.h"
# include <iostream>
2017-11-26 05:46:30 +00:00
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wint-in-bool-context"
2017-11-25 21:18:26 +00:00
# include <Eigen/Dense>
2017-11-26 05:46:30 +00:00
# pragma GCC diagnostic pop
2017-11-25 21:18:26 +00:00
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 ) ;
} ;