1 /***********************************************************************
2 WaterTable2 - Class to simulate water flowing over a surface using
3 improved water flow simulation based on Saint-Venant system of partial
4 differenctial equations.
5 Copyright (c) 2012-2016 Oliver Kreylos
7 This file is part of the Augmented Reality Sandbox (SARndbox).
9 The Augmented Reality Sandbox is free software; you can redistribute it
10 and/or modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
14 The Augmented Reality Sandbox is distributed in the hope that it will be
15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License along
20 with the Augmented Reality Sandbox; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 ***********************************************************************/
24 #ifndef WATERTABLE2_INCLUDED
25 #define WATERTABLE2_INCLUDED
28 #include <Misc/FunctionCalls.h>
29 #include <Geometry/Point.h>
30 #include <Geometry/Box.h>
31 #include <Geometry/OrthonormalTransformation.h>
33 #include <GL/Extensions/GLARBShaderObjects.h>
34 #include <GL/GLObject.h>
35 #include <GL/GLContextData.h>
39 /* Forward declarations: */
40 class DepthImageRenderer
;
42 typedef Misc::FunctionCall
<GLContextData
&>
43 AddWaterFunction
; // Type for render functions called to locally add water to the water table
45 class WaterTable2
: public GLObject
{
46 /* Embedded classes: */
48 typedef Geometry::Box
<Scalar
, 3> Box
;
49 typedef Geometry::OrthonormalTransformation
<Scalar
, 3> ONTransform
;
52 struct DataItem
: public GLObject::DataItem
{ // Structure holding per-context state
55 GLuint bathymetryTextureObjects
[2]; // Double-buffered one-component float color texture object holding the vertex-centered bathymetry grid
56 int currentBathymetry
; // Index of bathymetry texture containing the most recent bathymetry grid
57 unsigned int bathymetryVersion
; // Version number of the most recent bathymetry grid
58 GLuint quantityTextureObjects
[3]; // Double-buffered three-component color texture object holding the cell-centered conserved quantity grid (w, hu, hv)
59 int currentQuantity
; // Index of quantity texture containing the most recent conserved quantity grid
60 GLuint derivativeTextureObject
; // Three-component color texture object holding the cell-centered temporal derivative grid
61 GLuint maxStepSizeTextureObjects
[2]; // Double-buffered one-component color texture objects to gather the maximum step size for Runge-Kutta integration steps
62 GLuint waterTextureObject
; // One-component color texture object to add or remove water to/from the conserved quantity grid
63 GLuint bathymetryFramebufferObject
; // Frame buffer used to render the bathymetry surface into the bathymetry grid
64 GLuint derivativeFramebufferObject
; // Frame buffer used for temporal derivative computation
65 GLuint maxStepSizeFramebufferObject
; // Frame buffer used to calculate the maximum integration step size
66 GLuint integrationFramebufferObject
; // Frame buffer used for the Euler and Runge-Kutta integration steps
67 GLuint waterFramebufferObject
; // Frame buffer used for the water rendering step
69 bathymetryShader
; // Shader to update cell-centered conserved quantities after a change to the bathymetry grid
70 GLint bathymetryShaderUniformLocations
[3];
72 waterAdaptShader
; // Shader to adapt a new conserved quantity grid to the current bathymetry grid
73 GLint waterAdaptShaderUniformLocations
[2];
75 derivativeShader
; // Shader to compute face-centered partial fluxes and cell-centered temporal derivatives
76 GLint derivativeShaderUniformLocations
[6];
78 maxStepSizeShader
; // Shader to compute a maximum step size for a subsequent Runge-Kutta integration step
79 GLint maxStepSizeShaderUniformLocations
[2];
80 GLhandleARB boundaryShader
; // Shader to enforce boundary conditions on the quantities grid
81 GLint boundaryShaderUniformLocations
[1];
82 GLhandleARB eulerStepShader
; // Shader to compute an Euler integration step
83 GLint eulerStepShaderUniformLocations
[4];
84 GLhandleARB rungeKuttaStepShader
; // Shader to compute a Runge-Kutta integration step
85 GLint rungeKuttaStepShaderUniformLocations
[5];
86 GLhandleARB waterAddShader
; // Shader to render water adder objects
87 GLint waterAddShaderUniformLocations
[3];
88 GLhandleARB waterShader
; // Shader to add or remove water from the conserved quantities grid
89 GLint waterShaderUniformLocations
[3];
91 /* Constructors and destructors: */
93 virtual ~DataItem(void);
97 GLsizei size
[2]; // Width and height of water table in pixels
98 const DepthImageRenderer
*
99 depthImageRenderer
; // Renderer object used to update the water table's bathymetry grid
100 ONTransform baseTransform
; // Transformation from camera space to upright elevation map space
101 Box domain
; // Domain of elevation map space in rotated camera space
102 GLfloat cellSize
[2]; // Width and height of water table cells in world coordinate units
104 bathymetryPmv
; // Combined projection and modelview matrix to render the current surface into the bathymetry grid
106 waterAddPmv
; // Combined projection and modelview matrix to render water-adding geometry into the water grid
107 GLfloat waterAddPmvMatrix
[16]; // Same, in GLSL-compatible format
108 GLfloat theta
; // Coefficient for minmod flux-limiting differential operator
109 GLfloat g
; // Gravitiational acceleration constant
110 GLfloat epsilon
; // Coefficient for desingularizing division operator
111 GLfloat attenuation
; // Attenuation factor for partial discharges
112 GLfloat maxStepSize
; // Maximum step size for each Runge-Kutta integration step
114 waterTextureTransform
; // Projective transformation from camera space to water level texture space
115 GLfloat waterTextureTransformMatrix
[16]; // Same in GLSL-compatible format
116 std::vector
<const AddWaterFunction
*>
117 renderFunctions
; // A list of functions that are called after each water flow simulation step to locally add or remove water from the water table
118 GLfloat waterDeposit
; // A fixed amount of water added at every iteration of the flow simulation, for evaporation etc.
119 bool dryBoundary
; // Flag whether to enforce dry boundary conditions at the end of each simulation step
121 readBathymetryRequest
; // Request token to read back the current bathymetry grid from the GPU
122 mutable GLfloat
* readBathymetryBuffer
; // Buffer into which to read the current bathymetry grid
124 readBathymetryReply
; // Reply token after reading back the current bathymetry grid
126 /* Private methods: */
127 void calcTransformations(void); // Calculates derived transformations
128 GLfloat
calcDerivative(DataItem
* dataItem
, GLuint quantityTextureObject
,
129 bool calcMaxStepSize
)
130 const; // Calculates the temporal derivative of the conserved quantities in the given texture object and returns maximum step size if flag is true
132 /* Constructors and destructors: */
134 WaterTable2(GLsizei width
, GLsizei height
,
135 const GLfloat sCellSize
[2]); // Creates water table for offline simulation
136 WaterTable2(GLsizei width
, GLsizei height
, const DepthImageRenderer
* sDepthImageRenderer
,
138 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
139 virtual ~WaterTable2(void);
141 /* Methods from GLObject: */
142 virtual void initContext(GLContextData
& contextData
) const;
145 const GLsizei
* getSize(void) const { // Returns the size of the water table
148 const ONTransform
& getBaseTransform(void)
149 const { // Returns the transformation from camera space to upright elevation map space
150 return baseTransform
;
152 const Box
& getDomain(void) const { // Returns the water table's domain in rotated camera space
155 const GLfloat
* getCellSize(void) const { // Returns the water table's cell size
158 GLfloat
getAttenuation(void) const { // Returns the attenuation factor for partial discharges
161 bool getDryBoundary(void)
162 const { // Returns true if dry boundaries are enforced after every simulation step
165 void setElevationRange(Scalar newMin
,
166 Scalar newMax
); // Sets the range of possible elevations in the water table
167 void setAttenuation(GLfloat newAttenuation
); // Sets the attenuation factor for partial discharges
168 void setMaxStepSize(GLfloat
169 newMaxStepSize
); // Sets the maximum step size for all subsequent integration steps
170 const PTransform
& getWaterTextureTransform(void)
171 const { // Returns the matrix transforming from camera space into water texture space
172 return waterTextureTransform
;
174 void addRenderFunction(const AddWaterFunction
*
175 newRenderFunction
); // Adds a render function to the list; object remains owned by caller
176 void removeRenderFunction(const AddWaterFunction
*
177 removeRenderFunction
); // Removes the given render function from the list but does not delete it
178 GLfloat
getWaterDeposit(void)
179 const { // Returns the current amount of water deposited on every simulation step
182 void setWaterDeposit(GLfloat newWaterDeposit
); // Sets the amount of deposited water
183 void setDryBoundary(bool newDryBoundary
); // Enables or disables enforcement of dry boundaries
184 void updateBathymetry(GLContextData
& contextData
)
185 const; // Prepares the water table for subsequent calls to the runSimulationStep() method
186 void updateBathymetry(const GLfloat
* bathymetryGrid
,
187 GLContextData
& contextData
)
188 const; // Updates the bathymetry directly with a vertex-centered elevation grid of grid size minus 1
189 void setWaterLevel(const GLfloat
* waterGrid
,
190 GLContextData
& contextData
)
191 const; // Sets the current water level to the given grid, and resets flux components to zero
192 GLfloat
runSimulationStep(bool forceStepSize
,
193 GLContextData
& contextData
)
194 const; // 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
195 void bindBathymetryTexture(GLContextData
& contextData
)
196 const; // Binds the bathymetry texture object to the active texture unit
197 void bindQuantityTexture(GLContextData
& contextData
)
198 const; // Binds the most recent conserved quantities texture object to the active texture unit
199 void uploadWaterTextureTransform(GLint location
)
200 const; // Uploads the water texture transformation into the GLSL 4x4 matrix at the given uniform location
201 GLsizei
getBathymetrySize(int index
) const { // Returns the width or height of the bathymetry grid
202 return size
[index
] - 1;
204 bool requestBathymetry(GLfloat
*
205 newReadBathymetryBuffer
); // Requests reading back the current bathymetry grid from the GPU during the next rendering cycle; returns true if request can be granted
206 bool haveBathymetry(void)
207 const { // Returns true if the most recent bathymetry request has been fulfilled
208 return readBathymetryReply
== readBathymetryRequest
;