-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
194 lines (185 loc) · 9.45 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>1D Height Field Fluid</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<link type="text/css" href="main.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<h1>1D Height Field Fluid</h1>
<div class="description">
This is a 1D implementaion of <a href="https://matthias-research.github.io/pages/publications/publications.html">Matthias Müllers</a> Height Field Fluid algorithm presented at the <a href="https://www.gdcvault.com/play/203/Fast-Water-Simulation-for-Games">Games Developers Conference 2008</a>. It is based on the 2D wave equation
$$ u_{tt}=c^2\nabla^2u $$
in form of a partial differential equation of second order. \( u_{tt}=c^2u_{xx} \) for the 1D case.<br>
In short, the algorithm steps are based on particle calculations in respect to Newtons second law of
motion \( a=f/m \)
<pre>
<code>
LOOP
compute force
velocity += force/mass * time step
position += velocity * time step
ENDLOOP
</code>
</pre>
which translates to the actual program code
<pre>
<code>
FORALL i
f = c^2*(u[i-1] + u[i+1] – 2u[i])/h^2
v[i] = v[i] + f*dt
u_new[i] = u[i] + v[i]*dt
ENDFOR
u = u_new
</code>
</pre>
This implementaion uses WebGL and was built with the help of <a href="https://webglfundamentals.org/">webglfundamentals.org</a>. Feel free to change the parameters.
</div>
<hr>
<h2>Parameters</h2>
<div class="inputs">
<label>Canvas height: </label><span id="canvasHeight"></span>
<label>Canvas width: </label><span id="canvasWidth"></span><br><br>
<div class="mb-3 row">
<label class="col-5 col-form-label" for="initialWaterHeight">Initial water height:</label>
<div class="col-7">
<input class="form-control" type="number" id="initialWaterHeight" name="initialWaterHeight" type=number min=10>
</div>
</div>
<div class="mb-3 row">
<label class="col-5 col-form-label" for="waveColumnsCount">Wave columns count:</label>
<div class="col-7">
<input class="form-control" type="number" id="waveColumnsCount" name="waveColumnsCount" type=number min=10>
</div>
</div>
<div class="mb-3 row">
<label class="col-5 col-form-label" for="waveVelocity">c:</label>
<div class="col-7">
<input class="form-control" type="number" id="waveVelocity" name="waveVelocity" type=number step=0.01 min=0.01>
</div>
<small class="col-7 offset-5">(wave velocity, condition: c < h/dt)</small>
</div>
<div class="mb-3 row">
<label class="col-5 col-form-label">h:</label>
<div class="col-7">
<input class="form-control-plaintext" type="text" readonly id="waveColumsWidth">
</div>
<small class="col-7 offset-5">(wave column width)</small>
</div>
<div class="mb-3 row">
<label class="col-5 col-form-label" for="dampingScaling">s:</label>
<div class="col-7">
<input class="form-control" type="number" id="dampingScaling" name="dampingScaling" type=number step=0.01 min=0.01 max=1>
</div>
<small class="col-7 offset-5">(damping scaling, condition: s < 1)</small>
</div>
<div class="mb-3 row">
<label class="col-5 col-form-label" for="deltaTime">dt:</label>
<div class="col-7">
<input class="form-control" type="number" id="deltaTime" name="deltaTime" type=number step=0.01 min=0.01>
</div>
<small class="col-7 offset-5">(simulation delta time, condition: dt < h/c)</small>
</div>
<div class="mb-3 row">
<label class="col-5 col-form-label">Boundary condition:</label>
<div class="col-7 col-form-label">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="inlineRadioOptions" id="boundaryReflacting" value="option1"
checked>
<label class="form-check-label" for="boundaryReflacting">Reflacting</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="inlineRadioOptions" id="boundaryWraping"
value="option2">
<label class="form-check-label" for="boundaryWraping">Wraping</label>
</div>
</div>
</div>
<label class="mb-3">Create wave by:</label>
<div class="mb-3 row">
<div class="col-5 col-form-label">
<input class="form-check-input" type="radio" name="exampleRadios" id="changeHeightRadio" value="option1"
checked>
<label class="form-check-label" for="changeHeightRadio">
Adding water
</label>
</div>
<div class="col-7">
<input class="form-control" type="number" id="changeHeight" name="changeHeight" type=number min=1>
</div>
<small class="col-12">This changes the height of a column. There will be no water loss or gain because the implementation will
add or substract water to the surrounding columns.</small>
</div>
<div class="mb-3 row">
<div class="col-5 col-form-label">
<input class="form-check-input" type="radio" name="exampleRadios" id="changeForceRadio" value="option2">
<label class="form-check-label" for="changeForceRadio">
Applying force
</label>
</div>
<div class="col-7">
<input class="form-control" type="number" id="changeForce" name="changeForce" type=number min=-100>
</div>
<small class="col-12">This changes the velocity of a column. There will be water loss or gain. No implementation to stop this is in place.</small>
</div>
<div class="mb-3 row">
<label class="col-5 col-form-label" for="autoPlayInterval">Time between cycle calls (ms):</label>
<div class="col-7">
<input class="form-control" type="number" id="autoPlayInterval" name="autoPlayInterval" type=number step=1 min=20>
</div>
</div>
<button id="applyButton" onclick="onClickApply()" class="btn btn-outline-primary">Apply</button>
</div>
<hr>
<h2>Simulation</h2>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="flexSwitchCheckDefault"
onclick="onDebugViewSwitch(this);">
<label class="form-check-label" for="flexSwitchCheckDefault">Debug view</label>
</div>
<div class="card" id="debug-view-container" hidden=true>
<div class="card-body">
<h5 class="card-title">Debug view</h5>
<h6 class="card-subtitle mb-2 text-muted">u array</h6>
<p class="card-text" id="debug-u-array"></p>
<h6 class="card-subtitle mb-2 text-muted">v array</h6>
<p class="card-text" id="debug-v-array"></p>
</div>
</div>
<p>
Click on a column to create a wave.
</p>
<div class="buttons">
<button id="cycleButton" onclick="onClickCycle()" class="btn btn-outline-secondary">Cycle</button>
<button id="toggleAutoPlayButton" onclick="onClickToogleAutoPlay()" class="btn btn-outline-primary">Start</button>
</div>
<div class="canvas-container">
<canvas id="canvas"></canvas>
</div>
</div>
</body>
<script id="vertex-shader-2d" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform mat3 u_matrix;
void main() {
// Multiply the position by the matrix.
gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
}
</script>
<script id="fragment-shader-2d" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 u_color;
void main() {
gl_FragColor = u_color;
}
</script>
<script src="lib/webgl-utils.js"></script>
<script src="lib/m3.js"></script>
<script src="main.js"></script>
</html>