Wave Equation
Numerical simulation of the wave equation using JavaThis applet shows a water effect. The effect is calculated in real time using a solution of the wave equations by means of finite differences. More about the wave equation can be found at the wikipedia.
Implementation details
Consider an area equally sampled in x and y directions. The water heights are stored in an two-dimensional array. All values are stored as integer values. In order to calculate the wave effect you need 2 arrays. One is representing the state of the wave field in the current time step, the other is representing the wave field in the previous timestep. The wave heights of the next time step can be calculated by applying the following formula to every cell of the array:
NewHeights[x, y] = (( CurrentHeights[x-1, y+1]
+ CurrentHeights[x , y+1]
+ CurrentHeights[x+1, y+1]
+ CurrentHeights[x-1, y ]
+ CurrentHeights[x+1, y ]
+ CurrentHeights[x-1, y-1]
+ CurrentHeights[x , y-1]
+ CurrentHeights[x+1, y-1] ) DIV 2 ) -
PreviousHeights[x, y];
This means that the wave heights in the next time step depend only on the current water heights of the neigboring cells and the water height of the cell in question one timestep ago.
What these few lines do is a simplified solution of the wave equation, a partial differential equation. This algorithm does not provide an exact solution but it does provide a very fast solution.
After calculation the water heights one can apply a very simple form of raytracing. Not physically correct of course but again very fast and realistically looking. For every cell of the height array one can calculate the gradient. The gradient vector contains of the first derivation in x and y direction:
dx = CurrentHeights[x, y] - CurrentHeights[x+1, y ]; dy = CurrentHeights[x, y] - CurrentHeights[x , y+1];
Using this vector you can calculate the position of the pixel in an underlying image. (This image must be preload of course) The position results from the x,y position with the scaled gradient applied as a displacement:
iOffX = x + (dx>>4); iOffY = y + (dy>>4);
So instead of displaying the height value directly you transform it into a displacement vector and apply it to an underlying image. If you finally increase the pixel color depending on the legth of the x or y component of the gradient vector you add a realistically looking light.
Download and Useage
Download jar file
Download source code
(requires Netbeans)
In order to use the applet add the following lines to your html code:
<object classid="java:waves.class" type="application/x-java-applet" width="400" height="400">
<param name="archive" value="JWaves.jar"/>
<param name="code" value="waves.class"/>
<param name="pixsize" value="1"/>
<param name="sleep" value="10"/>
<param name="raindrops" value="true"/>
<param name="preview" value="false"/>
<param name="showfps" value="false"/>
<param name="sourceheight" value="2000"/>
</object>
The following table lists the applet parameters and their meaning:
| Parameter | Meaning |
|---|---|
| pixsize | The size of a pixel |
| sleep | Time to wait after each frame (in milli seconds) |
| raindrops | If this flag is set random raindrops are falling permanently |
| preview | If this value is true the applet looks like an image only moving when the mouse is over the applet. |
| showfps | If this flag is the frames per second are displayed in the upper left corner |
| sourceheight | The height of the waterwaves beeing created |
Related Links
- A good article on the topic is: The Water Effect Explained by Roy Willemse on gamedev.net