X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fsky%2Fcloudfield.cxx;h=8d83037d918d1d9a7b5565e408bb6b7aacca1cbb;hb=ccbc5abec63e508261b6d4bdbd5b1f780d233fc8;hp=bdd64aa3286758c22b5f5008c95648b7a9a14e05;hpb=100927f16cd44f4a343ea72995dfd6e19b58a749;p=simgear.git diff --git a/simgear/scene/sky/cloudfield.cxx b/simgear/scene/sky/cloudfield.cxx index bdd64aa3..8d83037d 100644 --- a/simgear/scene/sky/cloudfield.cxx +++ b/simgear/scene/sky/cloudfield.cxx @@ -16,7 +16,7 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include @@ -37,26 +37,52 @@ SG_USING_STD(vector); #include +#include "sky.hxx" #include "newcloud.hxx" #include "cloudfield.hxx" +#if defined(__MINGW32__) +#define isnan(x) _isnan(x) +#endif + +#if defined (__FreeBSD__) +# if __FreeBSD_version < 500000 + extern "C" { + inline int isnan(double r) { return !(r <= 0 || r >= 0); } + } +# endif +#endif + + +#if defined (__CYGWIN__) +#include +#endif + static list_of_culledCloud inViewClouds; // visibility distance for clouds in meters float SGCloudField::CloudVis = 25000.0f; -bool SGCloudField::enable3D = true; +bool SGCloudField::enable3D = false; // fieldSize must be > CloudVis or we can destroy the impostor cache // a cloud must only be seen once or the impostor will be generated for each of his positions -double SGCloudField::fieldSize = 27000.0; +double SGCloudField::fieldSize = 50000.0; float SGCloudField::density = 100.0; +double SGCloudField::timer_dt = 0.0; +sgVec3 SGCloudField::view_vec, SGCloudField::view_X, SGCloudField::view_Y; + static int last_cache_size = 1*1024; static int cacheResolution = 64; +static sgVec3 last_sunlight={0.0f, 0.0f, 0.0f}; int SGCloudField::get_CacheResolution(void) { +#if 0 return cacheResolution; +#endif + return 0; } void SGCloudField::set_CacheResolution(int resolutionPixels) { +#if 0 if(cacheResolution == resolutionPixels) return; cacheResolution = resolutionPixels; @@ -66,13 +92,18 @@ void SGCloudField::set_CacheResolution(int resolutionPixels) { count = 1; SGNewCloud::cldCache->setCacheSize(count, cacheResolution); } +#endif } int SGCloudField::get_CacheSize(void) { +#if 0 return SGNewCloud::cldCache->queryCacheSize(); +#endif + return 0; } void SGCloudField::set_CacheSize(int sizeKb) { +#if 0 // apply in rendering option dialog if(last_cache_size == sizeKb) return; @@ -84,30 +115,40 @@ void SGCloudField::set_CacheSize(int sizeKb) { int count = last_cache_size * 1024 / (cacheResolution * cacheResolution * 4); if(count == 0) count = 1; -// SGNewCloud::cldCache->setCacheSize(sizeKb); SGNewCloud::cldCache->setCacheSize(count, cacheResolution); } +#endif } void SGCloudField::set_CloudVis(float distance) { +#if 0 if( distance <= fieldSize ) SGCloudField::CloudVis = distance; +#endif } void SGCloudField::set_density(float density) { +#if 0 SGCloudField::density = density; +#endif } void SGCloudField::set_enable3dClouds(bool enable) { +#if 0 if(enable3D == enable) return; enable3D = enable; if(enable) { - SGNewCloud::cldCache->setCacheSize(last_cache_size); + int count = last_cache_size * 1024 / (cacheResolution * cacheResolution * 4); + if(count == 0) + count = 1; + SGNewCloud::cldCache->setCacheSize(count, cacheResolution); } else { SGNewCloud::cldCache->setCacheSize(0); } +#endif } // reposition the cloud layer at the specified origin and orientation -void SGCloudField::reposition( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double dt) { +void SGCloudField::reposition( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double dt, float direction, float speed) { +#if 0 sgMat4 T1, LON, LAT; sgVec3 axis; @@ -134,8 +175,6 @@ void SGCloudField::reposition( sgVec3 p, sgVec3 up, double lon, double lat, doub this->alt = alt; // simulate clouds movement from wind - double speed = 10.0f; - double direction = 45.0; double sp_dist = speed*dt; if (sp_dist > 0) { double bx = cos((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist; @@ -180,30 +219,57 @@ void SGCloudField::reposition( sgVec3 p, sgVec3 up, double lon, double lat, doub // correct the frustum with the right far plane ssgContext *context = ssgGetCurrentContext(); frustum = *context->getFrustum(); - frustum.setFOV(55.0,0); + + float w, h; + sgEnviro.getFOV( w, h ); + frustum.setFOV( w, h ); frustum.setNearFar(1.0, CloudVis); + timer_dt = dt; +#endif } SGCloudField::SGCloudField() : - last_density(0.0), deltax(0.0), deltay(0.0), - last_course(0.0) + last_course(0.0), + last_density(0.0), + draw_in_3d(true) { +#if 0 sgSetVec3( relative_position, 0,0,0); theField.reserve(200); inViewClouds.reserve(200); + sg_srandom_time_10(); +#else + draw_in_3d = false; +#endif } SGCloudField::~SGCloudField() { +#if 0 list_of_Cloud::iterator iCloud; for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) { delete iCloud->aCloud; } theField.clear(); +#endif } +void SGCloudField::clear(void) { +#if 0 + list_of_Cloud::iterator iCloud; + for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) { + delete iCloud->aCloud; + } + theField.clear(); + // force a recompute of density on first redraw + last_density = 0.0; + // true to come back in set density after layer is built + draw_in_3d = true; +#endif +} + // use a table or else we see poping when moving the slider... static int densTable[][10] = { {0,0,0,0,0,0,0,0,0,0}, @@ -221,64 +287,88 @@ static int densTable[][10] = { // set the visible flag depending on density void SGCloudField::applyDensity(void) { +#if 0 int row = (int) (density / 10.0); int col = 0; + sgBox fieldBox; + list_of_Cloud::iterator iCloud; for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) { if(++col > 9) col = 0; if( densTable[row][col] ) { iCloud->visible = true; + fieldBox.extend( *iCloud->aCloud->getCenter() ); } else iCloud->visible = false; } last_density = density; + draw_in_3d = ( theField.size() != 0); + sgVec3 center; + sgSubVec3( center, fieldBox.getMax(), fieldBox.getMin() ); + sgScaleVec3( center, 0.5f ); + center[1] = 0.0f; + field_sphere.setCenter( center ); + field_sphere.setRadius( fieldSize * 0.5f * 1.414f ); +#endif } // add one cloud, data is not copied, ownership given void SGCloudField::addCloud( sgVec3 pos, SGNewCloud *cloud) { +#if 0 Cloud cl; - sgCopyVec3( cl.pos, pos ); cl.aCloud = cloud; cl.visible = true; cloud->SetPos( pos ); + sgCopyVec3( cl.pos, *cloud->getCenter() ); theField.push_back( cl ); +#endif } static float Rnd(float n) { - return n * (-0.5f + rand() / (float) RAND_MAX); + return n * (-0.5f + sg_random()); } // for debug only // build a field of cloud of size 25x25 km, its a grid of 11x11 clouds void SGCloudField::buildTestLayer(void) { - +#if 0 const float s = 2250.0f; for( int z = -5 ; z <= 5 ; z++) { for( int x = -5 ; x <= 5 ; x++ ) { - SGNewCloud *cloud = new SGNewCloud; + SGNewCloud *cloud = new SGNewCloud(SGNewCloud::CLFamilly_cu); cloud->new_cu(); sgVec3 pos = {(x+Rnd(0.7)) * s, 750.0f, (z+Rnd(0.7)) * s}; addCloud(pos, cloud); } } applyDensity(); +#endif } // cull all clouds of a tiled field void SGCloudField::cullClouds(sgVec3 eyePos, sgMat4 mat) { +#if 0 list_of_Cloud::iterator iCloud; - // TODO:cull the field before culling the clouds in the field (should eliminate 3 fields) + sgSphere tile_sphere; + tile_sphere.setRadius( field_sphere.getRadius() ); + sgVec3 tile_center; + sgSubVec3( tile_center, field_sphere.getCenter(), eyePos ); + tile_sphere.setCenter( tile_center ); + tile_sphere.orthoXform(mat); + if( frustum.contains( & tile_sphere ) == SG_OUTSIDE ) + return; + for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) { sgVec3 dist; sgSphere sphere; if( ! iCloud->visible ) continue; sgSubVec3( dist, iCloud->pos, eyePos ); - sphere.setCenter(dist[0], dist[2], dist[1]); + sphere.setCenter(dist[0], dist[2], dist[1] + eyePos[1]); float radius = iCloud->aCloud->getRadius(); sphere.setRadius(radius); sphere.orthoXform(mat); @@ -289,12 +379,14 @@ void SGCloudField::cullClouds(sgVec3 eyePos, sgMat4 mat) { sgCopyVec3( tmp.eyePos, eyePos ); // save distance for later sort, opposite distance because we want back to front tmp.dist = - squareDist; + tmp.heading = -SG_PI/2.0 - atan2( dist[0], dist[2] ); // + SG_PI; + tmp.alt = iCloud->pos[1]; inViewClouds.push_back(tmp); if( squareDist - radius*radius < 100*100 ) sgEnviro.set_view_in_cloud(true); } } - +#endif } @@ -302,7 +394,14 @@ void SGCloudField::cullClouds(sgVec3 eyePos, sgMat4 mat) { // because no field can have an infinite size (and we don't want to reach his border) // we draw this field and adjacent fields. // adjacent fields are not real, its the same field displaced by some offset -void SGCloudField::Render(void) { +void SGCloudField::Render(float *sun_color) { + // sun_color used to depend on an extern SGSky *thesky definition + // above. However, this is bad form for a library and it's much + // more clean to just pass in the needed value. For reference, here is + // the old way that sun_color was fetched ... + // float *sun_color = thesky->get_sun_color(); + +#if 0 sgVec3 eyePos; double relx, rely; @@ -314,9 +413,11 @@ void SGCloudField::Render(void) { applyDensity(); } - // ask the impostor cache to do some cleanup - // TODO:don't do that for every field - SGNewCloud::cldCache->startNewFrame(); + if( ! draw_in_3d ) + return; + + if( ! SGNewCloud::cldCache->isRttAvailable() ) + return; inViewClouds.clear(); @@ -330,14 +431,26 @@ void SGCloudField::Render(void) { sgVec3 lightVec; ssgGetLight( 0 )->getPosition( lightVec ); sgXformVec3( lightVec, invtrans ); - sgCopyVec3( SGNewCloud::modelSunDir, lightVec ); + sgSetVec3( SGNewCloud::modelSunDir, lightVec[0], lightVec[2], lightVec[1]); - // try to find the lighting data (buggy) + // try to find the lighting data (not accurate) sgVec4 diffuse, ambient; ssgGetLight( 0 )->getColour( GL_DIFFUSE, diffuse ); ssgGetLight( 0 )->getColour( GL_AMBIENT, ambient ); - sgScaleVec3 ( SGNewCloud::sunlight, diffuse , 0.70f); - sgScaleVec3 ( SGNewCloud::ambLight, ambient , 0.60f); +// sgScaleVec3 ( SGNewCloud::sunlight, diffuse , 1.0f); + sgScaleVec3 ( SGNewCloud::ambLight, ambient , 1.1f); + // trying something else : clouds are more yellow/red at dawn/dusk + // and added a bit of blue ambient + sgScaleVec3 ( SGNewCloud::sunlight, sun_color , 0.4f); + SGNewCloud::ambLight[2] += 0.1f; + + sgVec3 delta_light; + sgSubVec3(delta_light, last_sunlight, SGNewCloud::sunlight); + if( (fabs(delta_light[0]) + fabs(delta_light[1]) + fabs(delta_light[2])) > 0.05f ) { + sgCopyVec3( last_sunlight, SGNewCloud::sunlight ); + // force the redraw of all the impostors + SGNewCloud::cldCache->invalidateCache(); + } // voodoo things on the matrix stack ssgGetModelviewMatrix( modelview ); @@ -346,14 +459,17 @@ void SGCloudField::Render(void) { // cloud fields are tiled on the flat earth // compute the position in the tile - relx = -fmod( deltax + relative_position[SG_X] + tmp[3][0], fieldSize ); - rely = -fmod( deltay + relative_position[SG_Y] + tmp[3][1], fieldSize ); + relx = fmod( deltax + relative_position[SG_X], fieldSize ); + rely = fmod( deltay + relative_position[SG_Y], fieldSize ); + + relx = fmod( relx + fieldSize, fieldSize ); + rely = fmod( rely + fieldSize, fieldSize ); + sgSetVec3( eyePos, relx, alt, rely); - sgSetVec3( eyePos, -relx, alt, -rely); + sgSetVec3( view_X, tmp[0][0], tmp[1][0], tmp[2][0] ); + sgSetVec3( view_Y, tmp[0][1], tmp[1][1], tmp[2][1] ); + sgSetVec3( view_vec, tmp[0][2], tmp[1][2], tmp[2][2] ); - tmp[3][2] = 0; - tmp[3][0] = 0; - tmp[3][1] = 0; ssgLoadModelviewMatrix( tmp ); /* flat earth @@ -385,9 +501,10 @@ void SGCloudField::Render(void) { glAlphaFunc(GL_GREATER, 0.0f); glDisable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); + glDepthMask( GL_FALSE ); glEnable(GL_SMOOTH); glEnable(GL_BLEND); - glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); glEnable( GL_TEXTURE_2D ); glDisable( GL_FOG ); glDisable(GL_LIGHTING); @@ -398,6 +515,8 @@ void SGCloudField::Render(void) { for( iCloud = inViewClouds.begin() ; iCloud != inViewClouds.end() ; iCloud++ ) { // iCloud->aCloud->drawContainers(); iCloud->aCloud->Render(iCloud->eyePos); + sgEnviro.callback_cloud(iCloud->heading, iCloud->alt, + iCloud->aCloud->getRadius(), iCloud->aCloud->getFamilly(), - iCloud->dist, iCloud->aCloud->getId()); } glBindTexture(GL_TEXTURE_2D, 0); @@ -409,6 +528,5 @@ void SGCloudField::Render(void) { ssgLoadModelviewMatrix( modelview ); glPopMatrix(); - +#endif } -