diff --git a/simgear/scene/sky/newcloud.cxx b/simgear/scene/sky/newcloud.cxx index 61dcb8b6..165e1268 100644 --- a/simgear/scene/sky/newcloud.cxx +++ b/simgear/scene/sky/newcloud.cxx @@ -60,13 +60,9 @@ using namespace simgear; using namespace osg; typedef std::map > StateSetMap; -typedef std::vector< osg::ref_ptr > GeodeList; -typedef std::map CloudMap; StateSetMap cloudTextureMap; -static CloudMap cloudMap; double SGNewCloud::sprite_density = 1.0; -unsigned int SGNewCloud::num_flavours = 10; static char vertexShaderSource[] = "#version 120\n" @@ -113,8 +109,8 @@ static char vertexShaderSource[] = " vec4 backlight = 0.9 * gl_LightSource[0].ambient + 0.1 * gl_LightSource[0].diffuse;\n" " gl_FrontColor = mix(backlight, gl_LightSource[0].diffuse, n);\n" " gl_FrontColor += gl_FrontLightModelProduct.sceneColor;\n" -// As we get within 100m of the sprite, it is faded out - " gl_FrontColor.a = smoothstep(10.0, 100.0, fogCoord);\n" +// As we get within 100m of the sprite, it is faded out. Equally at large distances it also fades out. + " gl_FrontColor.a = min(smoothstep(10.0, 100.0, fogCoord), 1 - smoothstep(15000.0, 20000.0, fogCoord));\n" " gl_BackColor = gl_FrontColor;\n" // Fog doesn't affect clouds as much as other objects. " fogFactor = exp( -gl_Fog.density * fogCoord * 0.5);\n" @@ -285,119 +281,86 @@ static float Rnd(float n) { osg::ref_ptr SGNewCloud::genCloud() { - CloudMap::iterator iter = cloudMap.find(name); - osg::ref_ptr geode; + osg::ref_ptr geode = new Geode; + + CloudShaderGeometry* sg = new CloudShaderGeometry(num_textures_x, num_textures_y, max_width, max_height); - // We generate up to num_flavours of different versions - // of the same cloud before we start re-using them. This - // allows us to strike a balance between performance and - // visual complexity. + // Determine how big this specific cloud instance is. Note that we subtract + // the sprite size because the width/height is used to define the limits of + // the center of the sprites, not their edges. + float width = min_width + sg_random() * (max_width - min_width) - min_sprite_width; + float height = min_height + sg_random() * (max_height - min_height) - min_sprite_height; - if (iter == cloudMap.end() || (*iter).second->size() < num_flavours) + // Determine the cull distance. This is used to remove sprites that are too close together. + // The value is squared as we use vector calculations. + float cull_distance_squared = min_sprite_height * min_sprite_height * 0.1f; + + // The number of sprites we actually used is a function of the (user-controlled) density + int n_sprites = num_sprites * sprite_density; + + for (int i = 0; i < n_sprites; i++) { + // Determine the position of the sprite. Rather than being completely random, + // we place them on the surface of a distorted sphere. However, we place + // the first and second sprites on the top and bottom, and the third in the + // center of the sphere (and at maximum size) to ensure good coverage and + // reduce the chance of there being "holes" in our cloud. + float x, y, z; - geode = new Geode; - - CloudShaderGeometry* sg = new CloudShaderGeometry(num_textures_x, num_textures_y, max_width, max_height); - - // Determine how big this specific cloud instance is. Note that we subtract - // the sprite size because the width/height is used to define the limits of - // the center of the sprites, not their edges. - float width = min_width + sg_random() * (max_width - min_width) - min_sprite_width; - float height = min_height + sg_random() * (max_height - min_height) - min_sprite_height; - - // Determine the cull distance. This is used to remove sprites that are too close together. - // The value is squared as we use vector calculations. - float cull_distance_squared = min_sprite_height * min_sprite_height * 0.1f; - - // The number of sprites we actually used is a function of the (user-controlled) density - int n_sprites = num_sprites * sprite_density; - - for (int i = 0; i < n_sprites; i++) - { - // Determine the position of the sprite. Rather than being completely random, - // we place them on the surface of a distorted sphere. However, we place - // the first and second sprites on the top and bottom, and the third in the - // center of the sphere (and at maximum size) to ensure good coverage and - // reduce the chance of there being "holes" in our cloud. - float x, y, z; - - if (i == 0) { - x = 0; - y = 0; - z = height * 0.5f; - } else if (i == 1) { - x = 0; - y = 0; - z = - height * 0.5f; - } else if (i == 2) { - x = 0; - y = 0; - z = 0; - } else { - double theta = sg_random() * SGD_2PI; - double elev = sg_random() * SGD_PI; - x = width * cos(theta) * 0.5f * sin(elev); - y = width * sin(theta) * 0.5f * sin(elev); - z = height * cos(elev) * 0.5f; - } - - SGVec3f *pos = new SGVec3f(x, y, z); - - // Determine the height and width as scaling factors on the minimum size (used to create the quad) - float sprite_width = 1.0f + sg_random() * (max_sprite_width - min_sprite_width) / min_sprite_width; - float sprite_height = 1.0f + sg_random() * (max_sprite_height - min_sprite_height) / min_sprite_height; - - if (i == 2) { - // The center sprite is always maximum size to fill up any holes. - sprite_width = 1.0f + (max_sprite_width - min_sprite_width) / min_sprite_width; - sprite_height = 1.0f + (max_sprite_height - min_sprite_height) / min_sprite_height; - } - - // Determine the sprite texture indexes; - int index_x = (int) floor(sg_random() * num_textures_x); - if (index_x == num_textures_x) { index_x--; } - - int index_y = (int) floor(sg_random() * num_textures_y); - if (index_y == num_textures_y) { index_y--; } - - sg->addSprite(*pos, - index_x, - index_y, - sprite_width, - sprite_height, - bottom_shade, - cull_distance_squared, - height * 0.5f); + if (i == 0) { + x = 0; + y = 0; + z = height * 0.5f; + } else if (i == 1) { + x = 0; + y = 0; + z = - height * 0.5f; + } else if (i == 2) { + x = 0; + y = 0; + z = 0; + } else { + double theta = sg_random() * SGD_2PI; + double elev = sg_random() * SGD_PI; + x = width * cos(theta) * 0.5f * sin(elev); + y = width * sin(theta) * 0.5f * sin(elev); + z = height * cos(elev) * 0.5f; } + SGVec3f *pos = new SGVec3f(x, y, z); + + // Determine the height and width as scaling factors on the minimum size (used to create the quad) + float sprite_width = 1.0f + sg_random() * (max_sprite_width - min_sprite_width) / min_sprite_width; + float sprite_height = 1.0f + sg_random() * (max_sprite_height - min_sprite_height) / min_sprite_height; - sg->setGeometry(quad); - geode->addDrawable(sg); - geode->setName("3D cloud"); - geode->setStateSet(stateSet.get()); - - if (iter == cloudMap.end()) - { - // This is the first of this cloud to be generated. - GeodeList* geodelist = new GeodeList; - geodelist->push_back(geode); - cloudMap.insert(CloudMap::value_type(name, geodelist)); + if (i == 2) { + // The center sprite is always maximum size to fill up any holes. + sprite_width = 1.0f + (max_sprite_width - min_sprite_width) / min_sprite_width; + sprite_height = 1.0f + (max_sprite_height - min_sprite_height) / min_sprite_height; } - else - { - // Add the new cloud to the list of geodes - (*iter).second->push_back(geode); - } - - } else { - int index = sg_random() * num_flavours; - if (index == num_flavours) index--; + // Determine the sprite texture indexes; + int index_x = (int) floor(sg_random() * num_textures_x); + if (index_x == num_textures_x) { index_x--; } - geode = iter->second->at(index); + int index_y = (int) floor(sg_random() * num_textures_y); + if (index_y == num_textures_y) { index_y--; } + + sg->addSprite(*pos, + index_x, + index_y, + sprite_width, + sprite_height, + bottom_shade, + cull_distance_squared, + height * 0.5f); } + sg->setGeometry(quad); + geode->addDrawable(sg); + geode->setName("3D cloud"); + geode->setStateSet(stateSet.get()); + return geode; } diff --git a/simgear/scene/sky/newcloud.hxx b/simgear/scene/sky/newcloud.hxx index fabf073d..be5549ff 100644 --- a/simgear/scene/sky/newcloud.hxx +++ b/simgear/scene/sky/newcloud.hxx @@ -72,19 +72,6 @@ public: sprite_density = d; } - static int getNumFlavours(void) - { - return num_flavours; - } - - // Set the number of flavours of this cloud. - // This is the number of different instances - // to generate. - static void setNumFlavours(int d) - { - num_flavours = d; - } - private: @@ -105,7 +92,6 @@ private: osg::Geometry* quad; osg::ref_ptr stateSet; static double sprite_density; - static unsigned int num_flavours; osg::Geometry* createOrthQuad(float w, float h, int varieties_x, int varieties_y); diff --git a/simgear/scene/sky/sky.cxx b/simgear/scene/sky/sky.cxx index 7ff81da8..ca2c0004 100644 --- a/simgear/scene/sky/sky.cxx +++ b/simgear/scene/sky/sky.cxx @@ -216,15 +216,6 @@ void SGSky::set_3dCloudVisRange(float vis) } } -float SGSky::get_3dCloudNumFlavours() const { - return (float) SGNewCloud::getNumFlavours(); -} - -void SGSky::set_3dCloudNumFlavours(float n) -{ - SGNewCloud::setNumFlavours((int) n); -} - void SGSky::texture_path( const string& path ) { tex_path = SGPath( path ); } diff --git a/simgear/scene/sky/sky.hxx b/simgear/scene/sky/sky.hxx index 9e6a1b1b..4d9199d6 100644 --- a/simgear/scene/sky/sky.hxx +++ b/simgear/scene/sky/sky.hxx @@ -430,14 +430,6 @@ public: */ virtual void set_3dCloudVisRange(float vis); - /** Get 3D cloud number of flavours*/ - virtual float get_3dCloudNumFlavours() const; - - /** Set 3D cloud number of flavours - * @param density 3D cloud number of flavours - */ - virtual void set_3dCloudNumFlavours(float n); - };