#include <simgear/compiler.h>
#include <vector>
+#include <map>
#include <osgDB/ReaderWriter>
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 {
bool visible;
};
- float Rnd(float);
+ 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
SGVec3f relative_position;
- // double lon, lat;
- osg::ref_ptr<osg::Group> field_root;
- osg::ref_ptr<osg::MatrixTransform> field_transform;
- osg::ref_ptr<osg::PositionAttitudeTransform> altitude_transform;
- osg::ref_ptr<osg::Switch> field_group[QUADTREE_SIZE][QUADTREE_SIZE];
- osg::ref_ptr<osg::LOD> quad[BRANCH_SIZE][BRANCH_SIZE];
-
- osg::ref_ptr<osg::LOD> field_lod;
-
- double deltax, deltay, alt;
- double last_course;
- float last_coverage;
- float coverage;
- SGGeoc cld_pos;
- int reposition_count;
- struct CloudFog : public simgear::Singleton<CloudFog>
- {
- CloudFog();
- osg::ref_ptr<osg::Fog> fog;
- };
+ osg::ref_ptr<osg::Group> field_root;
+ 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;
+
+ 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 addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform, SGGeod loc, float x, float y);
+ void addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform, SGGeod loc);
+ 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);
/**
- * reposition the cloud layer at the specified origin and
- * orientation.
- * @param p position vector
- * @param up the local up vector
- * @param lon specifies a rotation about the Z axis
- * @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
- */
- bool reposition( const SGVec3f& p, const SGVec3f& up,
- double lon, double lat, double dt, int asl);
-
- osg::Group* getNode() { return field_root.get(); }
-
- // visibility distance for clouds in meters
- static float CloudVis;
-
- static SGVec3f view_vec, view_X, view_Y;
-
- static float view_distance;
- static double timer_dt;
- static float fieldSize;
-
- bool defined3D;
-
- float getCoverage(void) { return coverage; }
- void setCoverage(float c) { coverage = c; }
-
- static float getVisRange(void) { return view_distance; }
- static void setVisRange(float d) { view_distance = d; }
-
- void applyCoverage(void);
- void applyVisRange(void);
-
- static osg::Fog* getFog()
- {
- return CloudFog::instance()->fog.get();
- }
- static void updateFog(double visibility, const osg::Vec4f& color);
+ * 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 up the local up vector
+ * @param lon specifies a rotation about the Z axis
+ * @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, float speed, float direction);
+
+ osg::Group* getNode() { return field_root.get(); }
+
+ // visibility distance for clouds in meters
+ static float CloudVis;
+
+ static SGVec3f view_vec, view_X, view_Y;
+
+ static float view_distance;
+ static double timer_dt;
+ static float fieldSize;
+ static bool wrap;
+
+ static bool getWrap(void) { return wrap; }
+ static void setWrap(bool w) { wrap = w; }
+
+ 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