#ifndef _CLOUDFIELD_HXX
#define _CLOUDFIELD_HXX
-#include <plib/sg.h>
#include <simgear/compiler.h>
#include <vector>
-#include <osgSim/Impostor>
+#include <map>
+
#include <osgDB/ReaderWriter>
#include <osg/ref_ptr>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Switch>
-#include <osg/Billboard>
+
+namespace osg
+{
+ class Fog;
+ class StateSet;
+ class Vec4f;
+}
#include <simgear/misc/sg_path.hxx>
+#include <simgear/structure/Singleton.hxx>
+#include <simgear/math/SGMath.hxx>
using std::vector;
class SGNewCloud;
+namespace simgear
+{
+ class EffectGeode;
+}
+
+typedef std::map<int, osg::ref_ptr<osg::PositionAttitudeTransform> > CloudHash;
+
/**
- * A layer of 3D clouds.
+ * A layer of 3D clouds, defined by lat/long/alt.
*/
class SGCloudField {
class Cloud {
public:
SGNewCloud *aCloud;
- sgVec3 pos;
+ SGVec3f pos;
bool visible;
};
float Rnd(float);
- // We create a quadtree two levels deep
- static const int BRANCH_SIZE = 16;
- static const int QUADTREE_SIZE = 32;
+ // Radius of the LoD nodes for the dynamic quadtrees.
+ static float RADIUS_LEVEL_1;
+ static float RADIUS_LEVEL_2;
// this is a relative position only, with that we can move all clouds at once
- sgVec3 relative_position;
- // double lon, lat;
+ SGVec3f relative_position;
osg::ref_ptr<osg::Group> field_root;
- osg::ref_ptr<osg::MatrixTransform> field_transform;
- osg::ref_ptr<osg::Switch> field_group[QUADTREE_SIZE][QUADTREE_SIZE];
+ osg::ref_ptr<osg::Group> placed_root;
+ osg::ref_ptr<osg::PositionAttitudeTransform> field_transform;
+ osg::ref_ptr<osg::PositionAttitudeTransform> altitude_transform;
osg::ref_ptr<osg::LOD> field_lod;
- double deltax, deltay, alt;
- double last_course;
- sgSphere field_sphere;
- float last_density;
- SGGeoc cld_pos;
- int reposition_count;
+ osg::Vec3f old_pos;
+ CloudHash cloud_hash;
+
+ struct CloudFog : public simgear::Singleton<CloudFog>
+ {
+ CloudFog();
+ osg::ref_ptr<osg::Fog> fog;
+ };
+
+ void removeCloudFromTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform);
+ void addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform, float lon, float lat, float alt, float x, float y);
+ void applyVisRangeAndCoverage(void);
+
public:
SGCloudField();
~SGCloudField();
void clear(void);
+ bool isDefined3D(void);
// add one cloud, data is not copied, ownership given
- void addCloud( SGVec3f& pos, SGNewCloud *cloud);
+ void addCloud( SGVec3f& pos, osg::ref_ptr<simgear::EffectGeode> cloud);
/**
+ * Add a new cloud with a given index at a specific point defined by lon/lat and an x/y offset
+ */
+ bool addCloud(float lon, float lat, float alt, int index, osg::ref_ptr<simgear::EffectGeode> geode);
+ bool addCloud(float lon, float lat, float alt, float x, float y, int index, osg::ref_ptr<simgear::EffectGeode> geode);
+
+ // Cloud handling functions.
+ bool deleteCloud(int identifier);
+ bool repositionCloud(int identifier, float lon, float lat, float alt);
+ bool repositionCloud(int identifier, float lon, float lat, float alt, float x, float y);
+
+
+ /**
* reposition the cloud layer at the specified origin and
* orientation.
* @param p position vector
* @param lat specifies a rotation about the new Y axis
* @param dt the time elapsed since the last call
* @param asl altitude of the layer
+ * @param speed of cloud layer movement (due to wind)
+ * @param direction of cloud layer movement (due to wind)
*/
bool reposition( const SGVec3f& p, const SGVec3f& up,
- double lon, double lat, double dt, int asl);
+ double lon, double lat, double dt, int asl, float speed, float direction);
osg::Group* getNode() { return field_root.get(); }
- // visibility distance for clouds in meters
- static float CloudVis;
+ // visibility distance for clouds in meters
+ static float CloudVis;
- static sgVec3 view_vec, view_X, view_Y;
+ static SGVec3f view_vec, view_X, view_Y;
- static float density;
- static double timer_dt;
- static float fieldSize;
+ static float view_distance;
+ static double timer_dt;
+ static float fieldSize;
+ static bool wrap;
- bool defined3D;
+ static bool getWrap(void) { return wrap; }
+ static void setWrap(bool w) { wrap = w; }
- static float get_density(void) { return density; }
-
- static void set_density(float density);
-
- void applyDensity(void);
+ static float getVisRange(void) { return view_distance; }
+ static void setVisRange(float d) { view_distance = d; }
+ void applyVisRange(void);
+
+ static osg::Fog* getFog()
+ {
+ return CloudFog::instance()->fog.get();
+ }
+ static void updateFog(double visibility, const osg::Vec4f& color);
};
#endif // _CLOUDFIELD_HXX