416 lines
15 KiB
Plaintext
416 lines
15 KiB
Plaintext
/*
|
|
* This source file is part of the osgOcean library
|
|
*
|
|
* Copyright (C) 2009 Kim Bale
|
|
* Copyright (C) 2009 The University of Hull, UK
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 3 of the License, or (at your option) any later
|
|
* version.
|
|
|
|
* This program 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 Lesser General Public License for more details.
|
|
* http://www.gnu.org/copyleft/lesser.txt.
|
|
*/
|
|
|
|
#pragma once
|
|
#include <osgOcean/Export>
|
|
#include <osgOcean/OceanTechnique>
|
|
#include <osgOcean/FFTSimulation>
|
|
#include <osgOcean/OceanTile>
|
|
|
|
#include <osg/Texture2D>
|
|
#include <osg/TextureCubeMap>
|
|
#include <osgDB/ReadFile>
|
|
|
|
#include <vector>
|
|
|
|
namespace osgOcean
|
|
{
|
|
class OSGOCEAN_EXPORT FFTOceanTechnique : public OceanTechnique
|
|
{
|
|
protected:
|
|
unsigned int _tileSize; /**< Size of FFT grid 2^n ie 128,64,32 etc. */
|
|
unsigned int _noiseTileSize; /**< Size of Noise FFT grid */
|
|
unsigned int _tileResolution; /**< Size of tile in world width/height. */
|
|
float _tileResInv; /**< 1 / _tileResoltion; */
|
|
unsigned int _noiseTileRes; /**< Size of noise tile in world width/height. */
|
|
unsigned int _numTiles; /**< Number of tiles on width/height. */
|
|
float _pointSpacing; /**< Spacing between points in real world. */
|
|
osg::Vec2f _windDirection; /**< Direction of wind. */
|
|
osg::Vec2f _noiseWindDir; /**< Direction of wind for noise tile. */
|
|
float _windSpeed; /**< Wind speed m/s */
|
|
float _noiseWindSpeed; /**< Wind speed for noise tile m/s */
|
|
float _waveScale; /**< Wave scale modifier. */
|
|
float _noiseWaveScale; /**< Wave scale modifier for noise tile. */
|
|
float _depth; /**< Depth (m). */
|
|
float _reflDampFactor; /**< Dampen waves going against the wind */
|
|
float _cycleTime; /**< Time before the ocean tiles loop. */
|
|
float _choppyFactor; /**< Amount of chop to add. */
|
|
bool _isChoppy; /**< Enable choppy waves generation. */
|
|
bool _isEndless; /**< Set whether the ocean is of fixed size. */
|
|
|
|
osg::Vec2f _startPos; /**< Start position of the surface ( -half width, half height ). */
|
|
|
|
const float _THRESHOLD; /**< Pixel threshold. */
|
|
const float _VRES; /**< Vertical resolution. */
|
|
float _C; /**< C constant. */
|
|
|
|
unsigned int _numLevels; /**< Number of mipmap levels. */
|
|
unsigned int _oldFrame; /**< Last ocean frame number. */
|
|
|
|
const unsigned int _NUMFRAMES; /**< Number of frames in the animation cycle */
|
|
|
|
osg::Vec4f _lightColor; /**< Color of the sun */
|
|
osg::Vec3f _waveTopColor; /**< Color for the upwelling shading. */
|
|
osg::Vec3f _waveBottomColor; /**< Color for the upwelling shading. */
|
|
bool _useCrestFoam; /**< Crest foam flag. */
|
|
float _foamCapTop; /**< Maximum height for foam caps. */
|
|
float _foamCapBottom; /**< Minimum height for foam caps. */
|
|
float _averageHeight; /**< Average height over the total tiles. */
|
|
float _maxHeight; /**< Maximum height over the total tiles. */
|
|
float _fresnelMul; /**< Fresnel multiplier uniform, typical values: (0.5-0.8). */
|
|
|
|
bool _isStateDirty;
|
|
|
|
std::vector<float> _minDist; /**< Minimum distances used for mipmap selection */
|
|
|
|
osg::ref_ptr<osg::TextureCubeMap> _environmentMap; /**< Cubemap used for refractions/reflections */
|
|
|
|
enum TEXTURE_UNITS{ ENV_MAP=0,REFLECT_MAP=1,REFRACT_MAP=2,REFRACTDEPTH_MAP=3,NORMAL_MAP=4,FOG_MAP=5,FOAM_MAP=6 };
|
|
|
|
public:
|
|
FFTOceanTechnique(unsigned int FFTGridSize,
|
|
unsigned int resolution,
|
|
unsigned int numTiles,
|
|
const osg::Vec2f& windDirection,
|
|
float windSpeed,
|
|
float depth,
|
|
float reflectionDamping,
|
|
float waveScale,
|
|
bool isChoppy,
|
|
float choppyFactor,
|
|
float animLoopTime,
|
|
unsigned int numFrames );
|
|
|
|
FFTOceanTechnique( const FFTOceanTechnique& copy,
|
|
const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY );
|
|
|
|
virtual const char* libraryName() const { return "osgOcean"; }
|
|
virtual const char* className() const { return "FFTOceanTechnique"; }
|
|
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const FFTOceanTechnique*>(obj) != 0; }
|
|
|
|
protected:
|
|
virtual ~FFTOceanTechnique(void);
|
|
|
|
public:
|
|
/**
|
|
* Returns the height at the given point (in local space). If the
|
|
* address of a Vec3f is passed in the normal argument, the normal at
|
|
* that position will be calculated and stored in it.
|
|
*/
|
|
virtual float getSurfaceHeightAt(float x, float y, osg::Vec3f* normal = NULL);
|
|
|
|
/**
|
|
* Checks for mipmap or frame changes and updates the geometry accordingly.
|
|
* Will rebuild state or geometry if found to be dirty.
|
|
*/
|
|
virtual void update( unsigned int frame, const double& dt, const osg::Vec3f& eye )=0;
|
|
|
|
protected:
|
|
/**
|
|
* Convenience method for creating a Texture2D based on an image file path.
|
|
*/
|
|
osg::Texture2D* createTexture( const std::string& path, osg::Texture::WrapMode wrap );
|
|
|
|
// -------------------------------------------------------------
|
|
// inline accessors/mutators
|
|
// -------------------------------------------------------------
|
|
|
|
public:
|
|
inline void setEnvironmentMap( osg::TextureCubeMap* environmentMap ){
|
|
_environmentMap = environmentMap;
|
|
_isStateDirty = true;
|
|
}
|
|
|
|
inline void setWaveTopColor( const osg::Vec3f& color ){
|
|
_waveTopColor = color;
|
|
_isStateDirty = true;
|
|
}
|
|
|
|
inline const osg::Vec3f& getWaveTopColor( void ) const {
|
|
return _waveTopColor;
|
|
}
|
|
|
|
inline void setWaveBottomColor( const osg::Vec3f& color ){
|
|
_waveBottomColor = color;
|
|
_isStateDirty = true;
|
|
}
|
|
|
|
inline const osg::Vec3f& getWaveBottomColor( void ) const {
|
|
return _waveTopColor;
|
|
}
|
|
|
|
inline void setLightColor( const osg::Vec4f& color ){
|
|
_lightColor = color;
|
|
_isStateDirty = true;
|
|
}
|
|
|
|
inline osg::Vec4f getLightColor() const{
|
|
return _lightColor;
|
|
}
|
|
|
|
inline void enableCrestFoam( bool enable ){
|
|
_useCrestFoam = enable;
|
|
_isStateDirty = true;
|
|
}
|
|
|
|
inline bool isCrestFoamEnabled() const{
|
|
return _useCrestFoam;
|
|
}
|
|
|
|
inline void setFoamBottomHeight( float height ){
|
|
_foamCapBottom = height;
|
|
_isStateDirty = true;
|
|
}
|
|
|
|
inline void setFoamTopHeight( float height ){
|
|
_foamCapTop = height;
|
|
_isStateDirty = true;
|
|
}
|
|
|
|
inline void setFresnelMultiplier( float mul ){
|
|
_fresnelMul = mul;
|
|
_isStateDirty = true;
|
|
}
|
|
|
|
/**
|
|
* Enable/Disable endless ocean.
|
|
* Dirties geometry by default, pass dirty=false to dirty yourself later.
|
|
*/
|
|
inline void enableEndlessOcean( bool enable, bool dirty = true ){
|
|
_isEndless = enable;
|
|
if (dirty) _isDirty = true;
|
|
}
|
|
|
|
inline bool isEndlessOceanEnabled() const{
|
|
return _isEndless;
|
|
}
|
|
|
|
/** Returns the average height over the whole surface (in local space)*/
|
|
inline float getSurfaceHeight( void ) const {
|
|
return _averageHeight;
|
|
}
|
|
|
|
/** Returns the maximum height over the whole surface (in local space)*/
|
|
inline float getMaximumHeight( void ) const {
|
|
return _maxHeight;
|
|
}
|
|
|
|
/**
|
|
* Enable/Disable choppy wave geometry.
|
|
* Dirties geometry by default, pass dirty=false to dirty yourself later.
|
|
*/
|
|
inline void setIsChoppy(bool isChoppy, bool dirty = true){
|
|
_isChoppy = isChoppy;
|
|
if (dirty) _isDirty = true;
|
|
}
|
|
|
|
inline bool isChoppy(void) const{
|
|
return _isChoppy;
|
|
}
|
|
|
|
/**
|
|
* Change the choppy factor.
|
|
* Dirties geometry by default, pass dirty=false to dirty yourself later.
|
|
*/
|
|
inline void setChoppyFactor(float choppyFactor, bool dirty = true){
|
|
_choppyFactor = choppyFactor;
|
|
if (dirty) _isDirty = true;
|
|
}
|
|
|
|
inline float getChoppyFactor() const{
|
|
return _choppyFactor;
|
|
}
|
|
|
|
/**
|
|
* Tweak the wave scale factor.
|
|
* Typically a very small value: ~1e-8.
|
|
* Dirties geometry by default, pass dirty=false to dirty yourself later.
|
|
*/
|
|
inline void setWaveScaleFactor( float scale, bool dirty = true ){
|
|
_waveScale = scale;
|
|
if (dirty) _isDirty = true;
|
|
}
|
|
|
|
inline float getWaveScaleFactor( void ) const {
|
|
return _waveScale;
|
|
}
|
|
|
|
/**
|
|
* Change the wind direction.
|
|
* Dirties geometry by default, pass dirty=false to dirty yourself later.
|
|
*/
|
|
inline void setWindDirection(const osg::Vec2f& windDir, bool dirty = true){
|
|
_windDirection = windDir;
|
|
if (dirty) _isDirty = true;
|
|
}
|
|
|
|
inline osg::Vec2f getWindDirection() const{
|
|
return _windDirection;
|
|
}
|
|
|
|
/**
|
|
* Change the wind speed.
|
|
* Dirties geometry by default, pass dirty=false to dirty yourself later.
|
|
*/
|
|
inline void setWindSpeed(const float windSpeed, bool dirty = true){
|
|
_windSpeed = windSpeed;
|
|
if (dirty) _isDirty = true;
|
|
}
|
|
|
|
inline float getWindSpeed() const{
|
|
return _windSpeed;
|
|
}
|
|
|
|
inline void setDepth(const float depth, bool dirty = true){
|
|
_depth = depth;
|
|
if (dirty) _isDirty = true;
|
|
}
|
|
|
|
inline float getDepth() const{
|
|
return _depth;
|
|
}
|
|
|
|
/**
|
|
* Sets the parameters for a custom noise map for use in the fragment shader.
|
|
* @param FFTSize is the size of the FFT grid that will be used and thus the size of the resulting texture. Values must be 2^n.
|
|
* Dirties the stateset.
|
|
*/
|
|
inline void setNoiseMapParams( unsigned int FFTSize,
|
|
const osg::Vec2f& windDir,
|
|
float windSpeed,
|
|
float waveScale,
|
|
float tileResolution )
|
|
{
|
|
_noiseTileSize = FFTSize;
|
|
_noiseWindDir = windDir;
|
|
_noiseWindSpeed = windSpeed;
|
|
_noiseWaveScale = waveScale;
|
|
_noiseTileRes = tileResolution;
|
|
|
|
_isStateDirty = true;
|
|
}
|
|
|
|
/**
|
|
* Linear interpolation of 3 RGBA colors.
|
|
* @return interpolated color (vec4)
|
|
*/
|
|
inline osg::Vec4f colorLerp (const osg::Vec4f& c0, const osg::Vec4f& c1, const osg::Vec4f& c2) const
|
|
{
|
|
return osg::Vec4f(
|
|
c1[0]*(1-c0[0]) + c2[0]*c0[0],
|
|
c1[1]*(1-c0[1]) + c2[1]*c0[1],
|
|
c1[2]*(1-c0[2]) + c2[2]*c0[2],
|
|
c1[3]*(1-c0[3]) + c2[3]*c0[3]
|
|
);
|
|
}
|
|
|
|
protected:
|
|
// --------------------------------------------------------
|
|
// OceanDataType
|
|
// --------------------------------------------------------
|
|
|
|
/**
|
|
* Data structure to store data needed for animation callback.
|
|
*/
|
|
class OSGOCEAN_EXPORT OceanDataType: public osg::Referenced
|
|
{
|
|
private:
|
|
osgOcean::FFTOceanTechnique& _oceanSurface;
|
|
const unsigned int _NUMFRAMES;
|
|
osg::Vec3f _eye;
|
|
double _time;
|
|
const unsigned int _FPS;
|
|
double _msPerFrame;
|
|
unsigned int _frame;
|
|
double _oldTime;
|
|
double _newTime;
|
|
|
|
public:
|
|
OceanDataType( FFTOceanTechnique& ocean, unsigned int numFrames, unsigned int fps );
|
|
OceanDataType( const OceanDataType& copy, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY );
|
|
|
|
inline void setEye( const osg::Vec3f& eye ){ _eye = eye; }
|
|
void updateOcean( double simulationTime );
|
|
};
|
|
|
|
public:
|
|
// --------------------------------------------------------
|
|
// OceanAnimationCallback
|
|
// --------------------------------------------------------
|
|
|
|
/**
|
|
* Cull/Update Animation callback. Override its operator() to customize
|
|
* how the ocean is updated.
|
|
*/
|
|
class OSGOCEAN_EXPORT OceanAnimationCallback: public osg::NodeCallback
|
|
{
|
|
public:
|
|
/**
|
|
* Override this to be able to call update() with specified dt.
|
|
* Don't forget to call traverse(node, nv); as for any update
|
|
* callback in OSG.
|
|
*/
|
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
|
|
|
protected:
|
|
/**
|
|
* Pass simulationTime < 0.0 to update with the real elapsed time,
|
|
* else will use specified simulationTime in seconds.
|
|
* @see FFTOceanSurface::update();
|
|
*/
|
|
void update(osg::Node* node, osg::NodeVisitor* nv, double simulationTime = -1.0);
|
|
};
|
|
|
|
/**
|
|
* Set a different animation callback than the default one.
|
|
*/
|
|
void setOceanAnimationCallback(OceanAnimationCallback* callback);
|
|
|
|
/**
|
|
* Get the animation callback.
|
|
*/
|
|
OceanAnimationCallback* getOceanAnimationCallback();
|
|
|
|
// --------------------------------------------------------
|
|
// EventHandler
|
|
// --------------------------------------------------------
|
|
|
|
/**
|
|
* This class overrides OceanTechnique::EventHandler to provide
|
|
* support for manipulating this particular subclass of
|
|
* OceanTechnique. Note that the method signatures are identical,
|
|
* and that the FFTOceanSurface will be accessed through the base
|
|
* class OceanTechnique pointer.
|
|
*/
|
|
class EventHandler : public OceanTechnique::EventHandler
|
|
{
|
|
public:
|
|
EventHandler(FFTOceanTechnique* oceanSurface);
|
|
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* object, osg::NodeVisitor* nv);
|
|
virtual void getUsage(osg::ApplicationUsage& usage) const;
|
|
protected:
|
|
bool _autoDirty;
|
|
};
|
|
|
|
virtual OceanTechnique::EventHandler* getEventHandler()
|
|
{
|
|
if (!_eventHandler.valid())
|
|
_eventHandler = new FFTOceanTechnique::EventHandler(this);
|
|
return _eventHandler.get();
|
|
}
|
|
};
|
|
} |