-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathWaterTable2.h
239 lines (217 loc) · 14.4 KB
/
WaterTable2.h
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/***********************************************************************
WaterTable2 - Class to simulate water flowing over a surface using
improved water flow simulation based on Saint-Venant system of partial
differenctial equations.
Copyright (c) 2012-2016 Oliver Kreylos
This file is part of the Augmented Reality Sandbox (SARndbox).
The Augmented Reality Sandbox is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The Augmented Reality Sandbox is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along
with the Augmented Reality Sandbox; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
***********************************************************************/
#ifndef WATERTABLE2_INCLUDED
#define WATERTABLE2_INCLUDED
#include <vector>
#include <Misc/FunctionCalls.h>
#include <Geometry/Point.h>
#include <Geometry/Box.h>
#include <Geometry/OrthonormalTransformation.h>
#include <GL/gl.h>
#include <GL/Extensions/GLARBShaderObjects.h>
#include <GL/GLObject.h>
#include <GL/GLContextData.h>
#include "Types.h"
/* Forward declarations: */
class DepthImageRenderer;
typedef Misc::FunctionCall<GLContextData&> AddWaterFunction; // Type for render functions called to locally add water to the water table
class WaterTable2:public GLObject
{
/* Embedded classes: */
public:
typedef Geometry::Box<Scalar,3> Box;
typedef Geometry::OrthonormalTransformation<Scalar,3> ONTransform;
private:
struct DataItem:public GLObject::DataItem // Structure holding per-context state
{
/* Elements: */
public:
GLuint bathymetryTextureObjects[2]; // Double-buffered one-component float color texture object holding the vertex-centered bathymetry grid
int currentBathymetry; // Index of bathymetry texture containing the most recent bathymetry grid
unsigned int bathymetryVersion; // Version number of the most recent bathymetry grid
GLuint quantityTextureObjects[3]; // Double-buffered three-component color texture object holding the cell-centered conserved quantity grid (w, hu, hv)
int currentQuantity; // Index of quantity texture containing the most recent conserved quantity grid
GLuint derivativeTextureObject; // Three-component color texture object holding the cell-centered temporal derivative grid
GLuint maxStepSizeTextureObjects[2]; // Double-buffered one-component color texture objects to gather the maximum step size for Runge-Kutta integration steps
GLuint waterTextureObject; // One-component color texture object to add or remove water to/from the conserved quantity grid
GLuint bathymetryFramebufferObject; // Frame buffer used to render the bathymetry surface into the bathymetry grid
GLuint derivativeFramebufferObject; // Frame buffer used for temporal derivative computation
GLuint maxStepSizeFramebufferObject; // Frame buffer used to calculate the maximum integration step size
GLuint integrationFramebufferObject; // Frame buffer used for the Euler and Runge-Kutta integration steps
GLuint waterFramebufferObject; // Frame buffer used for the water rendering step
GLhandleARB bathymetryShader; // Shader to update cell-centered conserved quantities after a change to the bathymetry grid
GLint bathymetryShaderUniformLocations[5];
GLhandleARB waterAdaptShader; // Shader to adapt a new conserved quantity grid to the current bathymetry grid
GLint waterAdaptShaderUniformLocations[2];
GLhandleARB derivativeShader; // Shader to compute face-centered partial fluxes and cell-centered temporal derivatives
GLint derivativeShaderUniformLocations[6];
GLhandleARB maxStepSizeShader; // Shader to compute a maximum step size for a subsequent Runge-Kutta integration step
GLint maxStepSizeShaderUniformLocations[2];
GLhandleARB boundaryShader; // Shader to enforce boundary conditions on the quantities grid
GLint boundaryShaderUniformLocations[1];
GLhandleARB eulerStepShader; // Shader to compute an Euler integration step
GLint eulerStepShaderUniformLocations[4];
GLhandleARB rungeKuttaStepShader; // Shader to compute a Runge-Kutta integration step
GLint rungeKuttaStepShaderUniformLocations[5];
GLhandleARB waterAddShader; // Shader to render water adder objects
GLint waterAddShaderUniformLocations[3];
GLhandleARB waterShader; // Shader to add or remove water from the conserved quantities grid
GLint waterShaderUniformLocations[3];
/* Vegetation shaders */
GLuint vegetationTextureObject; // One-component float color texture object holding the vertex-centered vegetation grid
GLuint hydrationTextureObject; // One-component float color color texture object holding the vertex-centered hydration grid
GLuint randomTextureObject; // One-component float texture object holding random values between 0 and 1
GLuint vegetationFramebufferObject; // Frame buffer used for hydration computation
GLuint hydrationFramebufferObject; // Frame buffer used for vegetation computation
GLhandleARB vegetationShader; // Shader to update cell-centered vegetation values
GLint vegetationShaderUniformLocations[10];
GLhandleARB hydrationShader; // Shader to compute hydration values
GLint hydrationShaderUniformLocations[2];
/* Slope shaders */
GLuint slopeTextureObject; // One-component float color texture object holding the vertex-centered slope grid
GLuint slopeFramebufferObject; // Frame buffer used for slope computation
GLint slopeShader; // Shader to compute slope values
GLint slopeShaderUniformLocations[3];
/* Constructors and destructors: */
DataItem(void);
virtual ~DataItem(void);
};
/* Elements: */
GLsizei size[2]; // Width and height of water table in pixels
const DepthImageRenderer* depthImageRenderer; // Renderer object used to update the water table's bathymetry grid
float* randomGrid; // A random grid of float values between 0 and 1 of water table size
ONTransform baseTransform; // Transformation from camera space to upright elevation map space
Box domain; // Domain of elevation map space in rotated camera space
GLfloat cellSize[2]; // Width and height of water table cells in world coordinate units
PTransform bathymetryPmv; // Combined projection and modelview matrix to render the current surface into the bathymetry grid
PTransform waterAddPmv; // Combined projection and modelview matrix to render water-adding geometry into the water grid
GLfloat waterAddPmvMatrix[16]; // Same, in GLSL-compatible format
GLfloat theta; // Coefficient for minmod flux-limiting differential operator
GLfloat g; // Gravitiational acceleration constant
GLfloat epsilon; // Coefficient for desingularizing division operator
GLfloat attenuation; // Attenuation factor for partial discharges
GLfloat maxStepSize; // Maximum step size for each Runge-Kutta integration step
PTransform waterTextureTransform; // Projective transformation from camera space to water level texture space
GLfloat waterTextureTransformMatrix[16]; // Same in GLSL-compatible format
std::vector<const AddWaterFunction*> renderFunctions; // A list of functions that are called after each water flow simulation step to locally add or remove water from the water table
std::vector<const AddWaterFunction*> renderVegetationFunctions; // A list of functions that are called after each vegetation simulation step to locally add or remove vegetation
GLfloat waterDeposit; // A fixed amount of water added at every iteration of the flow simulation, for evaporation etc.
GLfloat baseWaterLevel; // Base water level relative to the base plane
GLfloat oldBaseWaterLevel; // Previous base water level relative to the base plane
int numBathymetryCalls; // Keep track of number of calls to updateBathymetry until minBathymetryCalls
int minNumBathymetryCalls; // Minimum number of calls to updateBathymetry to fully initialize sandbox bathymetry
bool dryBoundary; // Flag whether to enforce dry boundary conditions at the end of each simulation step
unsigned int readBathymetryRequest; // Request token to read back the current bathymetry grid from the GPU
mutable GLfloat* readBathymetryBuffer; // Bufafer into which to read the current bathymetry grid
mutable unsigned int readBathymetryReply; // Reply token after reading back the current bathymetry grid
/* Vegetation simulation parameters */
GLfloat vegetationRange; // Minimum distance from another piece of vegetation to grow new vegetation (in pixels)
GLfloat hydrationThreshold; // Minimum value of hydration to grow new vegetation
GLfloat vegetationGrowthRate; // Growth rate of vegetation
bool clearVeg; // Flag whether to clear all of the vegetation
/* Private methods: */
void loadRandomGrid(); // Loads a random grid of water table size into randomGrid
void calcTransformations(void); // Calculates derived transformations
GLfloat calcDerivative(DataItem* dataItem,GLuint quantityTextureObject,bool calcMaxStepSize) const; // Calculates the temporal derivative of the conserved quantities in the given texture object and returns maximum step size if flag is true
/* Constructors and destructors: */
public:
WaterTable2(GLsizei width,GLsizei height,const GLfloat sCellSize[2]); // Creates water table for offline simulation
WaterTable2(GLsizei width,GLsizei height,const DepthImageRenderer* sDepthImageRenderer,const Point basePlaneCorners[4]); // Creates a water table of the given size in pixels, for the base plane quadrilateral defined by the depth image renderer's plane equation and four corner points
virtual ~WaterTable2(void);
/* Methods from GLObject: */
virtual void initContext(GLContextData& contextData) const;
/* New methods: */
const GLsizei* getSize(void) const // Returns the size of the water table
{
return size;
}
const ONTransform& getBaseTransform(void) const // Returns the transformation from camera space to upright elevation map space
{
return baseTransform;
}
const Box& getDomain(void) const // Returns the water table's domain in rotated camera space
{
return domain;
}
const GLfloat* getCellSize(void) const // Returns the water table's cell size
{
return cellSize;
}
GLfloat getAttenuation(void) const // Returns the attenuation factor for partial discharges
{
return attenuation;
}
GLfloat getBaseWaterLevel(void) const // Returns the base water level
{
return baseWaterLevel;
}
bool getDryBoundary(void) const // Returns true if dry boundaries are enforced after every simulation step
{
return dryBoundary;
}
bool getClearVegetation(void) // Returns the clear vegetation flag
{
return clearVeg;
}
void setElevationRange(Scalar newMin,Scalar newMax); // Sets the range of possible elevations in the water table
void setAttenuation(GLfloat newAttenuation); // Sets the attenuation factor for partial discharges
void setMaxStepSize(GLfloat newMaxStepSize); // Sets the maximum step size for all subsequent integration steps
void setBaseWaterLevel(GLfloat newBaseWaterLevel); // Sets the base water level
void setVegetationGrowth(GLfloat newVegetationGrowthRate); // Sets the vegetation growth rate
void setHydrationThreshold(GLfloat newHydrationThreshold); // Sets the hydration threshold for vegetation growth
void setClearVegetation(bool newClearVegetetation); // Sets the flag to clear vegetation
const PTransform& getWaterTextureTransform(void) const // Returns the matrix transforming from camera space into water texture space
{
return waterTextureTransform;
}
void addRenderFunction(const AddWaterFunction* newRenderFunction); // Adds a render function to the list; object remains owned by caller
void removeRenderFunction(const AddWaterFunction* removeRenderFunction); // Removes the given render function from the list but does not delete it
void addVegetationRenderFunction(const AddWaterFunction* newRenderFunction); // Adds a render function to the list; object remains owned by caller
void removeVegetationRenderFunction(const AddWaterFunction* removeRenderFunction); // Removes the given render function from the list but does not delete it
GLfloat getWaterDeposit(void) const // Returns the current amount of water deposited on every simulation step
{
return waterDeposit;
}
void setWaterDeposit(GLfloat newWaterDeposit); // Sets the amount of deposited water
void setDryBoundary(bool newDryBoundary); // Enables or disables enforcement of dry boundaries
void updateBathymetry(GLContextData& contextData); // Prepares the water table for subsequent calls to the runSimulationStep() method
void updateBathymetry(const GLfloat* bathymetryGrid,GLContextData& contextData) const; // Updates the bathymetry directly with a vertex-centered elevation grid of grid size minus 1
void setWaterLevel(const GLfloat* waterGrid,GLContextData& contextData) const; // Sets the current water level to the given grid, and resets flux components to zero
GLfloat runSimulationStep(bool forceStepSize,GLContextData& contextData); // Runs a water flow simulation step, always uses maxStepSize if flag is true (may lead to instability); returns step size taken by Runge-Kutta integration step
void runVegetationSimulation(GLContextData& contextData); // Runs a vegetation growth simulation step
void bindBathymetryTexture(GLContextData& contextData) const; // Binds the bathymetry texture object to the active texture unit
void bindQuantityTexture(GLContextData& contextData) const; // Binds the most recent conserved quantities texture object to the active texture unit
void bindVegetationTexture(GLContextData& contextData) const; // Binds the vegetation texture object
void bindSlopeTexture(GLContextData& contextData) const;
void uploadWaterTextureTransform(GLint location) const; // Uploads the water texture transformation into the GLSL 4x4 matrix at the given uniform location
GLsizei getBathymetrySize(int index) const // Returns the width or height of the bathymetry grid
{
return size[index]-1;
}
bool requestBathymetry(GLfloat* newReadBathymetryBuffer); // Requests reading back the current bathymetry grid from the GPU during the next rendering cycle; returns true if request can be granted
bool haveBathymetry(void) const // Returns true if the most recent bathymetry request has been fulfilled
{
return readBathymetryReply==readBathymetryRequest;
}
bool bathymetryIsInitialized(void)
{
return numBathymetryCalls==minNumBathymetryCalls;
}
};
#endif