From bcf727cf5835c3ac7ba1d19cd2132657166aec70 Mon Sep 17 00:00:00 2001 From: torsten Date: Tue, 22 Sep 2009 14:17:45 +0000 Subject: [PATCH 1/5] Catch a possible floating point error in SGGeodesy::SGCartToGeod() for cartesian coordinates close to the geocenter region. --- simgear/math/SGGeodesy.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/simgear/math/SGGeodesy.cxx b/simgear/math/SGGeodesy.cxx index 9971829a..208218b7 100644 --- a/simgear/math/SGGeodesy.cxx +++ b/simgear/math/SGGeodesy.cxx @@ -79,6 +79,17 @@ SGGeodesy::SGCartToGeod(const SGVec3& cart, SGGeod& geod) double Y = cart(1); double Z = cart(2); double XXpYY = X*X+Y*Y; + if( XXpYY + Z*Z < 25 ) { + // This function fails near the geocenter region, so catch that special case here. + // Define the innermost sphere of small radius as earth center and return the + // coordinates 0/0/-EQURAD. It may be any other place on geoide's surface, + // the Northpole, Hawaii or Wentorf. This one was easy to code ;-) + geod.setLongitudeRad( 0.0 ); + geod.setLongitudeRad( 0.0 ); + geod.setElevationM( -EQURAD ); + return; + } + double sqrtXXpYY = sqrt(XXpYY); double p = XXpYY*ra2; double q = Z*Z*(1-e2)*ra2; From dfe41ad984be7d800c1d9d5cad2c52337442f14f Mon Sep 17 00:00:00 2001 From: jmt Date: Sat, 26 Sep 2009 11:44:33 +0000 Subject: [PATCH 2/5] Extend simgear::strutils with convertToLowerCase helper - currently a proxy for osgDB helper of the same name. --- simgear/misc/strutils.cxx | 12 ++++++++++++ simgear/misc/strutils.hxx | 21 ++++++++++----------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/simgear/misc/strutils.cxx b/simgear/misc/strutils.cxx index 8ccb4c50..e836a3c4 100644 --- a/simgear/misc/strutils.cxx +++ b/simgear/misc/strutils.cxx @@ -25,6 +25,11 @@ #include "strutils.hxx" +#include // for convertToLowerCase + +using std::string; +using std::vector; + namespace simgear { namespace strutils { @@ -180,5 +185,12 @@ namespace simgear { return do_strip( s, BOTHSTRIP ); } + string convertToLowerCase(const string& str) + { + // proxy onto osgDB - easy to reimplement here, but let's avoid + // code duplication for the moment. + return osgDB::convertToLowerCase(str); + } + } // end namespace strutils } // end namespace simgear diff --git a/simgear/misc/strutils.hxx b/simgear/misc/strutils.hxx index aa395a25..7c1753ab 100644 --- a/simgear/misc/strutils.hxx +++ b/simgear/misc/strutils.hxx @@ -30,16 +30,12 @@ #include #include - #include -using std::vector; - #include -using std::string; namespace simgear { - namespace strutils { + namespace strutils { // /** // * atof() wrapper for "string" type @@ -64,9 +60,9 @@ namespace simgear { * @param s String to strip. * @return The stripped string. */ - string lstrip( const string& s ); - string rstrip( const string& s ); - string strip( const string& s ); + std::string lstrip( const std::string& s ); + std::string rstrip( const std::string& s ); + std::string strip( const std::string& s ); /** * Split a string into a words using 'sep' as the delimiter string. @@ -79,12 +75,15 @@ namespace simgear { * resulting in at most maxsplit+1 words. * @return Array of words. */ - vector - split( const string& s, + std::vector + split( const std::string& s, const char* sep = 0, int maxsplit = 0 ); - } // end namespace strutils + + std::string convertToLowerCase(const std::string& str); + + } // end namespace strutils } // end namespace simgear #endif // STRUTILS_H From 64756d14d0bed20b61938dd59dad44ef0a4513ba Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Thu, 1 Oct 2009 00:31:36 +0200 Subject: [PATCH 3/5] Back out convertToLowerCase function It brought in an OSG dependency; we'll just use boost::to_lower_copy instead. --- simgear/misc/strutils.cxx | 9 --------- simgear/misc/strutils.hxx | 3 --- 2 files changed, 12 deletions(-) diff --git a/simgear/misc/strutils.cxx b/simgear/misc/strutils.cxx index e836a3c4..d33b0a9d 100644 --- a/simgear/misc/strutils.cxx +++ b/simgear/misc/strutils.cxx @@ -25,8 +25,6 @@ #include "strutils.hxx" -#include // for convertToLowerCase - using std::string; using std::vector; @@ -185,12 +183,5 @@ namespace simgear { return do_strip( s, BOTHSTRIP ); } - string convertToLowerCase(const string& str) - { - // proxy onto osgDB - easy to reimplement here, but let's avoid - // code duplication for the moment. - return osgDB::convertToLowerCase(str); - } - } // end namespace strutils } // end namespace simgear diff --git a/simgear/misc/strutils.hxx b/simgear/misc/strutils.hxx index 7c1753ab..162cdb28 100644 --- a/simgear/misc/strutils.hxx +++ b/simgear/misc/strutils.hxx @@ -79,9 +79,6 @@ namespace simgear { split( const std::string& s, const char* sep = 0, int maxsplit = 0 ); - - - std::string convertToLowerCase(const std::string& str); } // end namespace strutils } // end namespace simgear From 4a5853c1c2c24704847fe360f6709fec9798cf05 Mon Sep 17 00:00:00 2001 From: durk Date: Fri, 2 Oct 2009 05:44:25 +0000 Subject: [PATCH 4/5] Stuart Buchanan: Improvements to the cloudsystem: - A new xml format - Texture indexing based on the position of the sprite in the cloud mass, allowing more control over the texture set. - Improved fog and shading - Better sprite distribution - A more natural distribution of clouds, so no more obvious grids. --- simgear/scene/sky/CloudShaderGeometry.cxx | 17 +++--- simgear/scene/sky/newcloud.cxx | 65 ++++++++++++----------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/simgear/scene/sky/CloudShaderGeometry.cxx b/simgear/scene/sky/CloudShaderGeometry.cxx index 49244faf..10d50acb 100755 --- a/simgear/scene/sky/CloudShaderGeometry.cxx +++ b/simgear/scene/sky/CloudShaderGeometry.cxx @@ -40,7 +40,7 @@ struct SpriteComp bool operator() (const CloudShaderGeometry::SortData::SortItem& lhs, const CloudShaderGeometry::SortData::SortItem& rhs) const { - return lhs.depth < rhs.depth; + return lhs.depth > rhs.depth; } }; } @@ -108,11 +108,11 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const itr != end; ++itr) { const CloudSprite& t = _cloudsprites[itr->idx]; - GLfloat ua1[3] = { (GLfloat)t.texture_index_x/varieties_x, - (GLfloat)t.texture_index_y/varieties_y, - t.width }; - GLfloat ua2[3] = { (GLfloat)t.height, - t.shade, + GLfloat ua1[3] = { (GLfloat) t.texture_index_x/varieties_x, + (GLfloat) t.texture_index_y/varieties_y, + (GLfloat) t.width }; + GLfloat ua2[3] = { (GLfloat) t.height, + (GLfloat) t.shade, (GLfloat) t.cloud_height }; extensions->glVertexAttrib3fv(USR_ATTR_1, ua1 ); extensions->glVertexAttrib3fv(USR_ATTR_2, ua2 ); @@ -126,15 +126,18 @@ void CloudShaderGeometry::addSprite(SGVec3f& p, int tx, int ty, float s, float cull, float cloud_height) { // Only add the sprite if it is further than the cull distance to all other sprites + // except for the center sprite. for (CloudShaderGeometry::CloudSpriteList::iterator iter = _cloudsprites.begin(); iter != _cloudsprites.end(); ++iter) { - if (distSqr(iter->position, p) < cull) { + if ((iter != _cloudsprites.begin()) && + (distSqr(iter->position, p) < cull)) { // Too close - cull it return; } } + _cloudsprites.push_back(CloudSprite(p, tx, ty, w, h, s, cloud_height)); } diff --git a/simgear/scene/sky/newcloud.cxx b/simgear/scene/sky/newcloud.cxx index 1c1b0d24..d641b2c9 100644 --- a/simgear/scene/sky/newcloud.cxx +++ b/simgear/scene/sky/newcloud.cxx @@ -91,23 +91,23 @@ static char vertexShaderSource[] = // Do the matrix multiplication by [ u r w pos]. Assume no // scaling in the homogeneous component of pos. " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" - " gl_Position.xyz = gl_Vertex.x * u * wScale;\n" - " gl_Position.xyz += gl_Vertex.y * r * hScale;\n" - " gl_Position.xyz += gl_Vertex.z * w;\n" + " gl_Position.xyz = gl_Vertex.x * u;\n" + " gl_Position.xyz += gl_Vertex.y * r * wScale;\n" + " gl_Position.xyz += gl_Vertex.z * w * hScale;\n" " gl_Position.xyz += gl_Color.xyz;\n" // Determine a lighting normal based on the vertex position from the // center of the cloud, so that sprite on the opposite side of the cloud to the sun are darker. - " float n = dot(normalize(gl_LightSource[0].position.xyz), normalize(mat3x3(gl_ModelViewMatrix) * gl_Position.xyz));\n" + " float n = dot(normalize(- gl_LightSource[0].position.xyz), normalize(mat3x3(gl_ModelViewMatrix) * (- gl_Position.xyz)));\n" // Determine the position - used for fog and shading calculations " vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Position);\n" " float fogCoord = abs(ecPosition.z);\n" " float fract = smoothstep(0.0, cloud_height, gl_Position.z + cloud_height);\n" // Final position of the sprite " gl_Position = gl_ModelViewProjectionMatrix * gl_Position;\n" -// Limit the normal range from [0,1.0], and apply the shading (vertical factor) - " n = min(smoothstep(-0.5, 0.5, n), shade * (1.0 - fract) + fract);\n" -// This lighting normal is then used to mix between almost pure ambient (0) and diffuse (1.0) light - " vec4 backlight = 0.9 * gl_LightSource[0].ambient + 0.1 * gl_LightSource[0].diffuse;\n" +// Determine the shading of the sprite based on its vertical position and position relative to the sun. + " n = min(smoothstep(-0.5, 0.0, n), fract);\n" +// Determine the shading based on a mixture from the backlight to the front + " vec4 backlight = gl_LightSource[0].diffuse * shade;\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. Equally at large distances it also fades out. @@ -127,7 +127,7 @@ static char fragmentShaderSource[] = " vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);\n" " vec4 finalColor = base * gl_Color;\n" " gl_FragColor.rgb = mix(gl_Fog.color.rgb, finalColor.rgb, fogFactor );\n" - " gl_FragColor.a = finalColor.a;\n" + " gl_FragColor.a = mix(0.0, finalColor.a, fogFactor);\n" "}\n"; SGNewCloud::SGNewCloud(string type, @@ -196,7 +196,7 @@ SGNewCloud::SGNewCloud(string type, // Generate the shader etc, if we don't already have one. if (!program.valid()) { alphaFunc = new AlphaFunc; - alphaFunc->setFunction(AlphaFunc::GREATER,0.05f); + alphaFunc->setFunction(AlphaFunc::GREATER,0.01f); program = new Program; baseTextureSampler = new osg::Uniform("baseTexture", 0); Shader* vertex_shader = new Shader(Shader::VERTEX, vertexShaderSource); @@ -301,27 +301,19 @@ osg::ref_ptr SGNewCloud::genCloud() { // 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; + // The number of sprites we actually use is a function of the (user-controlled) density + int n_sprites = num_sprites * sprite_density * (0.5 + sg_random()); 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. + // the first sprite in the center of the sphere (and at maximum size) to + // ensure good coverage and reduce the chance of there being "holes" in our + 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; @@ -330,26 +322,35 @@ osg::ref_ptr SGNewCloud::genCloud() { 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; + 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) + // 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) { + + // Sprites are never taller than square. + if (sprite_height * min_sprite_height > sprite_width * min_sprite_width) + { + sprite_height = sprite_width * min_sprite_width / min_sprite_height; + } + + if (i == 0) { // 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; + + // 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); + + // The y index depends on the positing of the sprite within the cloud. + // This allows cloud designers to have particular sprites for the base + // and tops of the cloud. + int index_y = (int) floor((z / height + 0.5f) * num_textures_y); if (index_y == num_textures_y) { index_y--; } sg->addSprite(*pos, From e5fac0a01deec74b307cdd5666ff9a14a323e953 Mon Sep 17 00:00:00 2001 From: jmt Date: Tue, 6 Oct 2009 20:05:46 +0000 Subject: [PATCH 5/5] Update the screen-dump code to use osgDB, and hence write out files in more common formats (PNG, JPEG, etc). The PPM writing code is retained for the moment, in case someone other than FG is relying upon it. --- simgear/screen/screen-dump.cxx | 23 +++++++---------------- simgear/screen/screen-dump.hxx | 7 ++++++- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/simgear/screen/screen-dump.cxx b/simgear/screen/screen-dump.cxx index dc5ba7bd..e4e97106 100644 --- a/simgear/screen/screen-dump.cxx +++ b/simgear/screen/screen-dump.cxx @@ -37,7 +37,8 @@ #include -#include +#include +#include #include "screen-dump.hxx" @@ -78,21 +79,11 @@ bool sg_glWritePPMFile(const char *filename, GLubyte *buffer, int win_width, int } -// dump the screen buffer to a ppm file +// dump the screen buffer to a png file bool sg_glDumpWindow(const char *filename, int win_width, int win_height) { - GLubyte *buffer; - bool result; - - buffer = (GLubyte *) malloc(win_width*win_height*RGBA); - - // read window contents from color buffer with glReadPixels - glFinish(); - glReadPixels(0, 0, win_width, win_height, - GL_RGBA, GL_UNSIGNED_BYTE, buffer); - result = sg_glWritePPMFile( filename, buffer, win_width, win_height, - GL_RGBA ); - free(buffer); - - return result; + osg::ref_ptr img(new osg::Image); + img->readPixels(0,0, win_width, win_height, GL_RGB, GL_UNSIGNED_BYTE); + osgDB::writeImageFile(*img, filename); + return true; } diff --git a/simgear/screen/screen-dump.hxx b/simgear/screen/screen-dump.hxx index 25a4c196..375f5398 100644 --- a/simgear/screen/screen-dump.hxx +++ b/simgear/screen/screen-dump.hxx @@ -21,12 +21,15 @@ // // $Id$ +#ifndef SG_SCREEN_DUMP_HXX +#define SG_SCREEN_DUMP_HXX + #include #include /** - * Dump the screen buffer to a ppm file. + * Dump the screen buffer to a PNG file. * @param filename name of file * @param win_width width of our opengl window * @param win_height height of our opengl window @@ -44,3 +47,5 @@ bool sg_glDumpWindow( const char *filename, int win_width, int win_height ); */ bool sg_glWritePPMFile( const char *filename, GLubyte *buffer, int win_width, int win_height, int mode); + +#endif // of SG_SCREEN_DUMP_HXX