Merge branches 'toresten/geofix', 'jmt/lcase', 'stuart/clouds' and 'jmt/dump'
This commit is contained in:
@@ -79,6 +79,17 @@ SGGeodesy::SGCartToGeod(const SGVec3<double>& 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;
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
#include "strutils.hxx"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace simgear {
|
||||
namespace strutils {
|
||||
|
||||
|
||||
@@ -30,16 +30,12 @@
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <vector>
|
||||
using std::vector;
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
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,12 @@ namespace simgear {
|
||||
* resulting in at most maxsplit+1 words.
|
||||
* @return Array of words.
|
||||
*/
|
||||
vector<string>
|
||||
split( const string& s,
|
||||
std::vector<std::string>
|
||||
split( const std::string& s,
|
||||
const char* sep = 0,
|
||||
int maxsplit = 0 );
|
||||
|
||||
} // end namespace strutils
|
||||
|
||||
} // end namespace strutils
|
||||
} // end namespace simgear
|
||||
|
||||
#endif // STRUTILS_H
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Geode> 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<Geode> 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,
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <osg/GL>
|
||||
#include <osg/Image>
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
#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<osg::Image> img(new osg::Image);
|
||||
img->readPixels(0,0, win_width, win_height, GL_RGB, GL_UNSIGNED_BYTE);
|
||||
osgDB::writeImageFile(*img, filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,15 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifndef SG_SCREEN_DUMP_HXX
|
||||
#define SG_SCREEN_DUMP_HXX
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <osg/GL>
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
Reference in New Issue
Block a user