• Stars
    star
    103
  • Rank 331,902 (Top 7 %)
  • Language
    JavaScript
  • Created about 11 years ago
  • Updated over 8 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A wave simulation in WebGL

Wave simulation in WebGL

This is a simple WebGL simulation of the 2D wave equation.

Launch the simulation

Architecture

The root HTML file lies at index.html. This includes a basic CSS stylesheet, style.css, for elementary typography, as well as three Javascript files, three.js, TrackballControls.js, and main.js.

We use the de-facto standard three.js WebGL Javascript library as our underlying framework for drawing 3D graphics. This provides basic rendering capabilities. We use the TrackballControls three.js plugin for elementary user interface controls which let the user rotate using drag and drop, zoom in and out using the mouse wheel, and panning using right-click drag and drop.

We use CoffeeScript for our implementation. We chose CoffeeScript for its elegance and simplicity.

The main script file which performs the simulation is main.coffee, which is compiled to Javascript as main.js.

How it works

The code consists of three portions, namely initialization, control handling, and integration. The core of the idea is implemented in the integration part.

Initialization is realized in the init function. The init function begins by creating a standard three.js scene, including a camera, a light, a scene, and the geometry with its materials. The geometry consists of a supporting cube of which the top face is the geometry which we manipulate to generate waves. The top face of the cube is a plane parallel to the xz plane of width and height W and H respectively. It is subdivided into N subquads in each direction, each of whose vertices' position is later manipulated to render waves.

Initialization has a sub-stage which introduces the initial condition of the world - a droplet at the center of the sea.

Control handling is realized in the function hitTest. We use a standard three.js hit testing method. When the user clicks on the screen, we unproject the location of the mouse into the 3D scene and detect the point of the sea that was clicked. We then modify the current waves to accommodate for a new droplet in that location.

The core of the program lies at the function animate and integrate. The animate function is the main loop of the simulation. It requests a rendering of the current graphical scene from three.js and subsequently calls integrate as many times as required to perform the physical simulation. integrate is responsible for the physical aspect of the calculations. It goes through all the vertices of the sea and evaluates their new locations based on certain physical formulae.

Our simulation is all performed at the CPU level. We are able to afford this, as our simulation algorithms are linear with respect to the number of vertices in question. If you want to run this simulation at higher speeds (a larger C2 constant) or resolution (a larger N), we encourage you to fork this project and migrate this simulation from the CPU to the GPU level using shaders for computation.

The math behind it

Modelling

At the beginning, the plane is instantiated as a flat plane parallel to the xz plane. Subsequently, only the y coordinate of each vertex is modified for the simulation. This is a small offset approximation, which ignores conservation of mass and other effects that water often exhibits such as hydraulic jumps. The water molecules can only move up and down - not horizontally. This is unrealistic physically, but works reasonably well for visually appealing results.

Therefore, our waves are modelled using a function y = u(x, z, t) which gives the height of each water molecule on the water surface with respect to its spatial location, given by x and z, and time t. All x, z, and t variables are also discretized to be able to perform the required calculations for our model. This discretization splits up each spacial dimension into N + 1 discrete points, while time is discretized into moments that are close to 16 milliseconds apart. The distance between two consecutive moments in time is denoted dt and may become smaller or larger depending on anomalies on the hosting platform (for example, a user switching tabs or using a CPU-intensive program in parallel). The bounds of our variables are as follows:

t ≥ 0
-W / 2 ≤ x ≤ W / 2
-H / 2 ≤ y ≤ H / 2

We model the surface of the water using the wave equation. Alternative models that we decided not to use could involve the shallow water equations or even the full Navier-Stokes equations simplified to the desired degree. We encourage you to fork this project and play with alternatives.

Initial and boundary conditions

We begin by introducing the initial conditions of the world, a droplet at the center of the sea. The droplet geometry is implemented using a 2D Gaussian distribution. Therefore, our initial conditions are given as follows:

u(x, z, 0) = A exp(-σx²) exp(-σz²)

Where A and σ are constant terms denoted respectively as MAX_Y and SIGMA in the code. As the sea is centered around the point (0, 0, 0), a Gaussian distribution with a zero offset does the job.

Throughout the simulation, we keep the boundary of the sea fixed with a height of zero; these are our boundary conditions. While the Gaussian function is not zero at our finite boundaries, we use an appropriate sigma parameter such that it is close to zero. This introduces a space discontinuity at the boundary, but it works reasonably well for our discretized model. Our boundary conditions are given:

u(-W / 2, -H / 2, t) = u(W / 2, -H / 2, t) = u(-W / 2, H / 2, t) = u(W / 2, H / 2, t) = 0

When the user clicks on a particular location, we unproject the 2D point to retrieve an x and z for the 3D point that was clicked. If multiple points can be unprojected, we choose the one closer to the user. We then superimpose a new 2D Gaussian distribution to the existing function, introducing a time discontinuity through direct position manipulation.

Partial differential equation

The simulation runs by integrating the wave equation, a partial differential equation in three variables, at each moment in time. The equation forms the core of the simulation and is given below:

∇² u = ∂²u / ∂t²

Where ∇² denotes the Laplace operator. In our case, as our independent spatial variables are x and z, the Laplacian is given as follows:

∇²u = Δu = ∂²u / ∂x² + ∂²u / ∂z²

Where ∂ denotes a partial derivative. Intuitively, therefore, the wave equation says that the vertical acceleration of a water particle is proportional to the local spatial curvature of the wave at that point in time.

Integration

Between every two moments, we run an iterated Euler integration method. Iterated means that if dt is too large, we break it into smaller dt's and run Euler's method on those, to avoid numerical instability. We encourage you to fork this project and improve the integration method by converting it to a lower-error Runge-Kutta integration method. This will allow higher simulation speeds with lower iteration resolution, while maintaining numerical stability.

Euler's method essentially linearly approximates the differential equations. We use the second finite differences in space evaluated as 2nd order central difference approximations:

∂²u / ∂x² ≃ u(x + 1, z, t) - 2u(x, z, t) + u(x - 1, z, t)
∂²u / ∂z² ≃ u(x, z + 1, t) - 2u(x, z, t) + u(x, z - 1, t)

We then find the acceleration as the sum of these:

∂²u / ∂t² = ∂²u / ∂x² + ∂²u / ∂z²

Finally, the speed and position are evaluated using linear approximations:

∂u / ∂t ≃ dt ∂²u / ∂t²
u ≃ dt ∂u / ∂t

Notice that dt is a finite number, since time is discretized. These are all evaluated for the next moment in time based on the current moment in time. To achieve the separation of moments in time, we perform a two-step process: In the first pass, we evaluate the new positions of the particles without altering the current positions of the particles. In the second pass, we update the locations of the particles based on our previous calculations. In this way, a moment in time does not affect itself.

Proportionality and non-homogeneous term

The above equation is modified to introduce a proportionality factor, C², which the Laplacian is multiplied with to control the wave propagation rate, or the relationship between space and time.

Finally, the wave equation is made non-homogeneous by introducing a damping term proportional to the current speed of each particle. This helps to reduce the energy of the waves as time goes by, essentially making the waves eventually vanish unless the user keeps interacting with them.

Under these modifications, the final partial differential equation becomes:

∇² u = C² ∂²u / ∂t² - D ∂u / ∂t

Where C² and D are constants denoted in the code as C2 and DAMPING respectively.

About the authors

Petros Aggelatos and Dionysis Zindros are Electrical and Computer Engineering students mastering in Computer Science at the National Technical University of Athens. We made this little demo for our own enjoyment, as we love computer graphics and physics, and to demonstrate some applications of the partial differential equations course of our school.

License

Copyright (C) 2013 Petros Aggelatos & Dionysis Zindros - {petrosagg,dionyziz}@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

More Repositories

1

stream.js

A tiny stand-alone Javascript library for streams
JavaScript
555
star
2

canvas-tetris

A 2D tetris game in HTML5 canvas
JavaScript
430
star
3

oath

A programmer's oath
PHP
75
star
4

Automata

An editor for deterministic finite automata
JavaScript
51
star
5

popow

Research and implementation for non-interactive blockchain proofs of proofs of work
HTML
49
star
6

complexity-article

A Gentle Introduction to Algorithm Complexity Analysis
PHP
28
star
7

config

My Linux configuration files
Vim Script
23
star
8

blockchain-book

"Blockchain Foundations" lecture notes
TeX
23
star
9

ting

A chat system
JavaScript
19
star
10

canvas-cube

A 3d cube in plain HTML5 canvas
JavaScript
13
star
11

thesis

My PhD thesis
TeX
12
star
12

marabu-course

A website for a blockchain course
JavaScript
12
star
13

zino

A social network
PHP
12
star
14

endofcodes

A game of coding
PHP
11
star
15

minibay

Accessible music
Python
10
star
16

dbpanel

A minimalistic database management webapp for MySQL in PHP
PHP
9
star
17

tictactoe

A tictactoe game in Javascript
HTML
9
star
18

Life

Minimalistic journal-keeping platform for my own use in PHP
PHP
9
star
19

channel

Code examples from my YouTube channel
JavaScript
8
star
20

hackme

The website describing my bounty hunt game.
HTML
7
star
21

minireddit

A minimalistic viewer of reddit images
JavaScript
7
star
22

advent-of-code

My Advent of Code solutions
Python
7
star
23

bitcoinschool

The bitcoin school website
CSS
6
star
24

horus

Hours of Horus paper
TeX
6
star
25

tidyarxiv

A script to cleanup your paper before uploading it to arXiv
Python
6
star
26

variable-nipopows

Non-Interactive Proofs of Proof-of-Work in Chains of Variable Difficulty
TeX
6
star
27

git-class

A 4h class to teach git and GitHub
6
star
28

project-euler

My solutions to projecteuler.net
C++
6
star
29

crypto-class

Material for crypto-class.gr
Python
5
star
30

popos

Proofs of Proof-of-Stake with Sublinear Complexity
TeX
5
star
31

sidechains-pow

Proof-of-work Sidechains paper
TeX
5
star
32

brick

An implementation of Brick Ethereum channels in Solidity
JavaScript
5
star
33

ntua-crypto

Cryptography class notes and projects, dissertation work
TeX
5
star
34

w3sync

A web application deployment system
PHP
4
star
35

pyderive

Symbolic derivation tool
Python
4
star
36

webgl-mandelbrot

A WebGL rendering of the Mandelbrot set
HTML
4
star
37

howto-smart-questions-gr

How to ask smart questions in Greek
PHP
4
star
38

kseri

Kseri implementation in python
Python
4
star
39

balls-experiment

Experimenting with collision detection & response
JavaScript
4
star
40

ntua-algo

Algorithms exercises for NTUA
C++
4
star
41

webgl-seminar

Code examples and slides for our 2 hour seminar on WebGL (AUTH and NTUA)
JavaScript
4
star
42

malibu

A JavaScript node for the marabu coin
TypeScript
3
star
43

xclaim-synthwave

JavaScript
3
star
44

pandemic

A simple pandemic simulator in Python
Python
3
star
45

ntua-ai

Artificial intelligence homework for NTUA
C++
3
star
46

crypto-algorithms

A scratch area for various crypto algorithm implementations
C++
3
star
47

linear-js

A linear algebra library in ECMAScript 6
JavaScript
3
star
48

infinite-blockchains

A treatment of blockchains in the unbounded setting
TeX
3
star
49

webgl-parthenon

A WebGL implementation of a simple rendering of the Parthenon monument in Athens, Greece
JavaScript
3
star
50

ntua-os

Operating Systems lab assignments for the National Technical University of Athens
C
3
star
51

rollerblade

Blockchain reliability
TeX
2
star
52

ntua-ml

Machine learning homework for NTUA
MATLAB
2
star
53

rocket-simulator

TypeScript
2
star
54

node-irc

An IRC client for Windows
Visual Basic
2
star
55

di-computability

Solutions to computability exercises in the di (alma) grad course
TeX
2
star
56

ntua-kernel

Kernel programming homework for NTUA
C
2
star
57

cador

A Vilundo chat server
C++
2
star
58

ntua-db

Database project for NTUA
JavaScript
2
star
59

alive

Old, slow, simple 3D rendering engine in PHP
PHP
2
star
60

blockchain-signalling

Election meddling and fair signalling for soft/hard forks
TeX
2
star
61

stanford-db

Stanford database class (db-class.org)
2
star
62

llama

A llama implementation in Python
Python
2
star
63

minesweeper-js

A minesweeper game in Javascript
JavaScript
2
star
64

set-theory

Set theory exercises for the set theory master course of UoA ALMA
TeX
2
star
65

beautiful

Making Javascript Beautiful contest
JavaScript
2
star
66

gender-unicorn

The gender unicorn website
HTML
2
star
67

bouncing-ball

A bouncing ball in HTML5
JavaScript
1
star
68

xkcd-wallpaper

A python scripts that changes your wallpaper to a random xkcd comic daily
Python
1
star
69

codejam

Google Code Jam solutions
C++
1
star
70

deliverakias

HTML
1
star
71

rabbit

A rapid application development PHP framework
PHP
1
star
72

Vectorjs

JS Library for Vectors
JavaScript
1
star
73

cv

Curriculum Vitae
TeX
1
star
74

spider

A web spider in python
1
star
75

recursion-thm

A recursion theorem compiler in JS
JavaScript
1
star
76

marabu-explorer

An explorer for the Marabu blockchain
TypeScript
1
star
77

dionyziz.com

Personal website
HTML
1
star
78

hanoi

A towers of hanoi visualization
JavaScript
1
star
79

blogcube

A blogging system in PHP
PHP
1
star
80

hellenico

My solutions to the Hellenico algorithmic problems
C++
1
star
81

spoj

My solutions to SPOJ
C++
1
star
82

usaco

My solutions to USACO
C++
1
star
83

stanford-ml

Homework repository for Stanford machine learning class (http://ml-class.org)
MATLAB
1
star
84

bubble-trouble

An HTML5 clone of the popular bubble-trouble arcade game
JavaScript
1
star
85

webgl-tetris

A 3D tetris game in WebGL
JavaScript
1
star
86

html5-snake

HTML5 snake game in coffeescript
CoffeeScript
1
star