+#include <vector>
+
+using std::vector;
+
+
+typedef struct {
+ SGVec3d pt;
+ int depth;
+ int prev;
+} lt_tree_seg;
+
+#define MAX_RAIN_SLICE 200
+static float rainpos[MAX_RAIN_SLICE];
+#define MAX_LT_TREE_SEG 400
+
+#define DFL_MIN_LIGHT 0.35
+SGVec3f SGEnviro::min_light(DFL_MIN_LIGHT, DFL_MIN_LIGHT, DFL_MIN_LIGHT);
+#define DFL_STREAK_BRIGHT_NEARMOST_LAYER 0.9
+float SGEnviro::streak_bright_nearmost_layer = DFL_STREAK_BRIGHT_NEARMOST_LAYER;
+#define DFL_STREAK_BRIGHT_FARMOST_LAYER 0.5
+float SGEnviro::streak_bright_farmost_layer = DFL_STREAK_BRIGHT_FARMOST_LAYER;
+#define DFL_STREAK_PERIOD_MAX 2.5
+float SGEnviro::streak_period_max = DFL_STREAK_PERIOD_MAX;
+#define DFL_STREAK_PERIOD_CHANGE_PER_KT 0.005
+float SGEnviro::streak_period_change_per_kt = DFL_STREAK_PERIOD_CHANGE_PER_KT;
+#define DFL_STREAK_PERIOD_MIN 1.0
+float SGEnviro::streak_period_min = DFL_STREAK_PERIOD_MIN;
+#define DFL_STREAK_LENGTH_MIN 0.03
+float SGEnviro::streak_length_min = DFL_STREAK_LENGTH_MIN;
+#define DFL_STREAK_LENGTH_CHANGE_PER_KT 0.0005
+float SGEnviro::streak_length_change_per_kt = DFL_STREAK_LENGTH_CHANGE_PER_KT;
+#define DFL_STREAK_LENGTH_MAX 0.1
+float SGEnviro::streak_length_max = DFL_STREAK_LENGTH_MAX;
+#define DFL_STREAK_COUNT_MIN 40
+int SGEnviro::streak_count_min = DFL_STREAK_COUNT_MIN;
+#define DFL_STREAK_COUNT_MAX 190
+#if (DFL_STREAK_COUNT_MAX > MAX_RAIN_SLICE)
+#error "Bad default!"
+#endif
+int SGEnviro::streak_count_max = DFL_STREAK_COUNT_MAX;
+#define DFL_CONE_BASE_RADIUS 15.0
+float SGEnviro::cone_base_radius = DFL_CONE_BASE_RADIUS;
+#define DFL_CONE_HEIGHT 30.0
+float SGEnviro::cone_height = DFL_CONE_HEIGHT;
+
+
+void SGEnviro::config(const SGPropertyNode* n)
+{
+ if (!n)
+ return;
+
+ const float ml = n->getFloatValue("min-light", DFL_MIN_LIGHT);
+ min_light = SGVec3f(ml, ml, ml);
+
+ streak_bright_nearmost_layer = n->getFloatValue(
+ "streak-brightness-nearmost-layer",
+ DFL_STREAK_BRIGHT_NEARMOST_LAYER);
+ streak_bright_farmost_layer = n->getFloatValue(
+ "streak-brightness-farmost-layer",
+ DFL_STREAK_BRIGHT_FARMOST_LAYER);
+
+ streak_period_max = n->getFloatValue(
+ "streak-period-max",
+ DFL_STREAK_PERIOD_MAX);
+ streak_period_min = n->getFloatValue(
+ "streak-period-min",
+ DFL_STREAK_PERIOD_MIN);
+ streak_period_change_per_kt = n->getFloatValue(
+ "streak-period-change-per-kt",
+ DFL_STREAK_PERIOD_CHANGE_PER_KT);
+
+ streak_length_max = n->getFloatValue(
+ "streak-length-max",
+ DFL_STREAK_LENGTH_MAX);
+ streak_length_min = n->getFloatValue(
+ "streak-length-min",
+ DFL_STREAK_LENGTH_MIN);
+ streak_length_change_per_kt = n->getFloatValue(
+ "streak-length-change-per-kt",
+ DFL_STREAK_LENGTH_CHANGE_PER_KT);
+
+ streak_count_min = n->getIntValue(
+ "streak-count-min", DFL_STREAK_COUNT_MIN);
+ streak_count_max = n->getIntValue(
+ "streak-count-max", DFL_STREAK_COUNT_MAX);
+ if (streak_count_max > MAX_RAIN_SLICE)
+ streak_count_max = MAX_RAIN_SLICE;
+
+ cone_base_radius = n->getFloatValue(
+ "cone-base-radius", DFL_CONE_BASE_RADIUS);
+ cone_height = n->getFloatValue("cone_height", DFL_CONE_HEIGHT);
+}
+
+
+/**
+ * A class to render lightnings.
+ */
+class SGLightning {
+public:
+ /**
+ * Build a new lightning.
+ * The lightning has a limited life time. It will also play a thunder sounder once.
+ * @param lon lon longitude in degree
+ * @param lat lat latitude in degree
+ * @param alt asl of top of lightning
+ */
+ SGLightning(double lon, double lat, double alt);
+ ~SGLightning();
+ void lt_Render(void);
+ void lt_build(void);
+ void lt_build_tree_branch(int tree_nr, SGVec3d &start, float energy, int nbseg, float segsize);
+
+ // contains all the segments of the lightning
+ lt_tree_seg lt_tree[MAX_LT_TREE_SEG];
+ // segment count
+ int nb_tree;
+ // position of lightning
+ double lon, lat, alt;
+ int sequence_count;
+ // time to live
+ double age;
+};
+
+typedef vector<SGLightning *> list_of_lightning;
+static list_of_lightning lightnings;
+