00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 # include <simgear_config.h>
00025 #endif
00026
00027 #include <simgear/compiler.h>
00028
00029 #include <sstream>
00030
00031 #include <math.h>
00032
00033 #include <osg/AlphaFunc>
00034 #include <osg/BlendFunc>
00035 #include <osg/CullFace>
00036 #include <osg/Geode>
00037 #include <osg/Geometry>
00038 #include <osg/Material>
00039 #include <osg/ShadeModel>
00040 #include <osg/TexEnv>
00041 #include <osg/TexEnvCombine>
00042 #include <osg/Texture2D>
00043 #include <osg/TextureCubeMap>
00044 #include <osg/TexMat>
00045 #include <osg/Fog>
00046
00047 #include <simgear/math/sg_random.h>
00048 #include <simgear/misc/PathOptions.hxx>
00049 #include <simgear/debug/logstream.hxx>
00050 #include <simgear/scene/model/model.hxx>
00051 #include <simgear/scene/util/RenderConstants.hxx>
00052 #include <simgear/scene/util/StateAttributeFactory.hxx>
00053 #include <simgear/math/polar3d.hxx>
00054
00055 #include "newcloud.hxx"
00056 #include "cloudfield.hxx"
00057 #include "cloud.hxx"
00058
00059 using namespace simgear;
00060 using namespace osg;
00061
00062 #if defined(__MINGW32__)
00063 #define isnan(x) _isnan(x)
00064 #endif
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #if defined (__CYGWIN__)
00075 #include <ieeefp.h>
00076 #endif
00077
00078 static osg::ref_ptr<osg::StateSet> layer_states[SGCloudLayer::SG_MAX_CLOUD_COVERAGES];
00079 static osg::ref_ptr<osg::StateSet> layer_states2[SGCloudLayer::SG_MAX_CLOUD_COVERAGES];
00080 static osg::ref_ptr<osg::TextureCubeMap> cubeMap;
00081 static bool state_initialized = false;
00082 static bool bump_mapping = false;
00083
00084 bool SGCloudLayer::enable_bump_mapping = false;
00085
00086
00087 static osg::StateSet*
00088 SGMakeState(const SGPath &path, const char* colorTexture,
00089 const char* normalTexture)
00090 {
00091 osg::StateSet *stateSet = new osg::StateSet;
00092
00093 osg::ref_ptr<osgDB::ReaderWriter::Options> options
00094 = makeOptionsFromPath(path);
00095 stateSet->setTextureAttribute(0, SGLoadTexture2D(colorTexture,
00096 options.get()));
00097 stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
00098 StateAttributeFactory* attribFactory = StateAttributeFactory::instance();
00099 stateSet->setAttributeAndModes(attribFactory->getSmoothShadeModel());
00100 stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
00101 stateSet->setAttributeAndModes(attribFactory->getStandardAlphaFunc());
00102 stateSet->setAttributeAndModes(attribFactory->getStandardBlendFunc());
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 return stateSet;
00129 }
00130
00131
00132 SGCloudLayer::SGCloudLayer( const string &tex_path ) :
00133 cloud_root(new osg::Switch),
00134 layer_root(new osg::Switch),
00135 group_top(new osg::Group),
00136 group_bottom(new osg::Group),
00137 layer_transform(new osg::MatrixTransform),
00138 cloud_alpha(1.0),
00139 texture_path(tex_path),
00140 layer_span(0.0),
00141 layer_asl(0.0),
00142 layer_thickness(0.0),
00143 layer_transition(0.0),
00144 layer_coverage(SG_CLOUD_CLEAR),
00145 scale(4000.0),
00146 speed(0.0),
00147 direction(0.0),
00148 last_lon(0.0),
00149 last_lat(0.0)
00150 {
00151
00152
00153
00154
00155
00156 cloud_root->addChild(layer_root.get(), true);
00157 layer_root->addChild(group_bottom.get());
00158 layer_root->addChild(group_top.get());
00159 osg::StateSet *rootSet = layer_root->getOrCreateStateSet();
00160 rootSet->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
00161 rootSet->setTextureAttribute(0, new osg::TexMat);
00162 rootSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
00163
00164 osg::TexEnvCombine* combine0 = new osg::TexEnvCombine;
00165 osg::TexEnvCombine* combine1 = new osg::TexEnvCombine;
00166 combine0->setCombine_RGB(osg::TexEnvCombine::MODULATE);
00167 combine0->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
00168 combine0->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
00169 combine0->setSource1_RGB(osg::TexEnvCombine::TEXTURE0);
00170 combine0->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
00171 combine0->setCombine_Alpha(osg::TexEnvCombine::MODULATE);
00172 combine0->setSource0_Alpha(osg::TexEnvCombine::PREVIOUS);
00173 combine0->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);
00174 combine0->setSource1_Alpha(osg::TexEnvCombine::TEXTURE0);
00175 combine0->setOperand1_Alpha(osg::TexEnvCombine::SRC_ALPHA);
00176
00177 combine1->setCombine_RGB(osg::TexEnvCombine::MODULATE);
00178 combine1->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
00179 combine1->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
00180 combine1->setSource1_RGB(osg::TexEnvCombine::CONSTANT);
00181 combine1->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
00182 combine1->setCombine_Alpha(osg::TexEnvCombine::MODULATE);
00183 combine1->setSource0_Alpha(osg::TexEnvCombine::PREVIOUS);
00184 combine1->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);
00185 combine1->setSource1_Alpha(osg::TexEnvCombine::CONSTANT);
00186 combine1->setOperand1_Alpha(osg::TexEnvCombine::SRC_ALPHA);
00187 combine1->setDataVariance(osg::Object::DYNAMIC);
00188 rootSet->setTextureAttributeAndModes(0, combine0);
00189 rootSet->setTextureAttributeAndModes(1, combine1);
00190 rootSet->setTextureMode(1, GL_TEXTURE_2D, osg::StateAttribute::ON);
00191 rootSet->setTextureAttributeAndModes(1, StateAttributeFactory::instance()
00192 ->getWhiteTexture(),
00193 osg::StateAttribute::ON);
00194 rootSet->setDataVariance(osg::Object::DYNAMIC);
00195
00196 base = osg::Vec2(sg_random(), sg_random());
00197 group_top->addChild(layer_transform.get());
00198 group_bottom->addChild(layer_transform.get());
00199
00200 layer3D = new SGCloudField();
00201 cloud_root->addChild(layer3D->getNode(), false);
00202
00203 rebuild();
00204 }
00205
00206
00207 SGCloudLayer::~SGCloudLayer()
00208 {
00209 delete layer3D;
00210 }
00211
00212 float
00213 SGCloudLayer::getSpan_m () const
00214 {
00215 return layer_span;
00216 }
00217
00218 void
00219 SGCloudLayer::setSpan_m (float span_m)
00220 {
00221 if (span_m != layer_span) {
00222 layer_span = span_m;
00223 rebuild();
00224 }
00225 }
00226
00227 float
00228 SGCloudLayer::getElevation_m () const
00229 {
00230 return layer_asl;
00231 }
00232
00233 void
00234 SGCloudLayer::setElevation_m (float elevation_m, bool set_span)
00235 {
00236 layer_asl = elevation_m;
00237
00238 if (set_span) {
00239 if (elevation_m > 4000)
00240 setSpan_m( elevation_m * 10 );
00241 else
00242 setSpan_m( 40000 );
00243 }
00244 }
00245
00246 float
00247 SGCloudLayer::getThickness_m () const
00248 {
00249 return layer_thickness;
00250 }
00251
00252 void
00253 SGCloudLayer::setThickness_m (float thickness_m)
00254 {
00255 layer_thickness = thickness_m;
00256 }
00257
00258 float
00259 SGCloudLayer::getTransition_m () const
00260 {
00261 return layer_transition;
00262 }
00263
00264 void
00265 SGCloudLayer::setTransition_m (float transition_m)
00266 {
00267 layer_transition = transition_m;
00268 }
00269
00270 SGCloudLayer::Coverage
00271 SGCloudLayer::getCoverage () const
00272 {
00273 return layer_coverage;
00274 }
00275
00276 void
00277 SGCloudLayer::setCoverage (Coverage coverage)
00278 {
00279 if (coverage != layer_coverage) {
00280 layer_coverage = coverage;
00281 rebuild();
00282
00283 double coverage_norm = 0.0;
00284 if( coverage == SG_CLOUD_FEW)
00285 coverage_norm = 2.0/8.0;
00286 else if( coverage == SG_CLOUD_SCATTERED )
00287 coverage_norm = 4.0/8.0;
00288 else if( coverage == SG_CLOUD_BROKEN )
00289 coverage_norm = 6.0/8.0;
00290 else if( coverage == SG_CLOUD_OVERCAST )
00291 coverage_norm = 8.0/8.0;
00292
00293 layer3D->setCoverage(coverage_norm);
00294 layer3D->applyCoverage();
00295 }
00296 }
00297
00298 void
00299 SGCloudLayer::setTextureOffset(const osg::Vec2& offset)
00300 {
00301 osg::StateAttribute* attr = layer_root->getStateSet()
00302 ->getTextureAttribute(0, osg::StateAttribute::TEXMAT);
00303 osg::TexMat* texMat = dynamic_cast<osg::TexMat*>(attr);
00304 if (!texMat)
00305 return;
00306 texMat->setMatrix(osg::Matrix::translate(offset[0], offset[1], 0.0));
00307 }
00308
00309
00310 #ifdef CLOUD_DEBUG
00311 Vec3 cloudColors[] = {Vec3(1.0f, 1.0f, 1.0f), Vec3(1.0f, 0.0f, 0.0f),
00312 Vec3(0.0f, 1.0f, 0.0f), Vec3(0.0f, 0.0f, 1.0f)};
00313 #else
00314 Vec3 cloudColors[] = {Vec3(1.0f, 1.0f, 1.0f), Vec3(1.0f, 1.0f, 1.0f),
00315 Vec3(1.0f, 1.0f, 1.0f), Vec3(1.0f, 1.0f, 1.0f)};
00316 #endif
00317
00318
00319 void
00320 SGCloudLayer::rebuild()
00321 {
00322
00323 if ( !state_initialized ) {
00324 state_initialized = true;
00325
00326 SG_LOG(SG_ASTRO, SG_INFO, "initializing cloud layers");
00327
00328 osg::Texture::Extensions* extensions;
00329 extensions = osg::Texture::getExtensions(0, true);
00330
00331 bump_mapping = extensions->isMultiTexturingSupported() &&
00332 (2 <= extensions->numTextureUnits()) &&
00333 SGIsOpenGLExtensionSupported("GL_ARB_texture_env_combine") &&
00334 SGIsOpenGLExtensionSupported("GL_ARB_texture_env_dot3");
00335
00336 osg::TextureCubeMap::Extensions* extensions2;
00337 extensions2 = osg::TextureCubeMap::getExtensions(0, true);
00338 bump_mapping = bump_mapping && extensions2->isCubeMapSupported();
00339
00340
00341
00342
00343
00344
00345
00346
00347 cubeMap = new osg::TextureCubeMap;
00348 cubeMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
00349 cubeMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
00350 cubeMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
00351 cubeMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
00352 cubeMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
00353
00354 const int size = 32;
00355 const float half_size = 16.0f;
00356 const float offset = 0.5f;
00357 osg::Vec3 zero_normal(0.5, 0.5, 0.5);
00358
00359 osg::Image* image = new osg::Image;
00360 image->allocateImage(size, size, 1, GL_RGB, GL_UNSIGNED_BYTE);
00361 unsigned char *ptr = image->data(0, 0);
00362 for (int j = 0; j < size; j++ ) {
00363 for (int i = 0; i < size; i++ ) {
00364 osg::Vec3 tmp(half_size, -( j + offset - half_size ),
00365 -( i + offset - half_size ) );
00366 tmp.normalize();
00367 tmp = tmp*0.5 - zero_normal;
00368
00369 *ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
00370 *ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
00371 *ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
00372 }
00373 }
00374 cubeMap->setImage(osg::TextureCubeMap::POSITIVE_X, image);
00375
00376 image = new osg::Image;
00377 image->allocateImage(size, size, 1, GL_RGB, GL_UNSIGNED_BYTE);
00378 ptr = image->data(0, 0);
00379 for (int j = 0; j < size; j++ ) {
00380 for (int i = 0; i < size; i++ ) {
00381 osg::Vec3 tmp(-half_size, -( j + offset - half_size ),
00382 ( i + offset - half_size ) );
00383 tmp.normalize();
00384 tmp = tmp*0.5 - zero_normal;
00385
00386 *ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
00387 *ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
00388 *ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
00389 }
00390 }
00391 cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_X, image);
00392
00393 image = new osg::Image;
00394 image->allocateImage(size, size, 1, GL_RGB, GL_UNSIGNED_BYTE);
00395 ptr = image->data(0, 0);
00396 for (int j = 0; j < size; j++ ) {
00397 for (int i = 0; i < size; i++ ) {
00398 osg::Vec3 tmp(( i + offset - half_size ), half_size,
00399 ( j + offset - half_size ) );
00400 tmp.normalize();
00401 tmp = tmp*0.5 - zero_normal;
00402
00403 *ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
00404 *ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
00405 *ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
00406 }
00407 }
00408 cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Y, image);
00409
00410 image = new osg::Image;
00411 image->allocateImage(size, size, 1, GL_RGB, GL_UNSIGNED_BYTE);
00412 ptr = image->data(0, 0);
00413 for (int j = 0; j < size; j++ ) {
00414 for (int i = 0; i < size; i++ ) {
00415 osg::Vec3 tmp(( i + offset - half_size ), -half_size,
00416 -( j + offset - half_size ) );
00417 tmp.normalize();
00418 tmp = tmp*0.5 - zero_normal;
00419
00420 *ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
00421 *ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
00422 *ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
00423 }
00424 }
00425 cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Y, image);
00426
00427 image = new osg::Image;
00428 image->allocateImage(size, size, 1, GL_RGB, GL_UNSIGNED_BYTE);
00429 ptr = image->data(0, 0);
00430 for (int j = 0; j < size; j++ ) {
00431 for (int i = 0; i < size; i++ ) {
00432 osg::Vec3 tmp(( i + offset - half_size ),
00433 -( j + offset - half_size ), half_size );
00434 tmp.normalize();
00435 tmp = tmp*0.5 - zero_normal;
00436
00437 *ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
00438 *ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
00439 *ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
00440 }
00441 }
00442 cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Z, image);
00443
00444 image = new osg::Image;
00445 image->allocateImage(size, size, 1, GL_RGB, GL_UNSIGNED_BYTE);
00446 ptr = image->data(0, 0);
00447 for (int j = 0; j < size; j++ ) {
00448 for (int i = 0; i < size; i++ ) {
00449 osg::Vec3 tmp(-( i + offset - half_size ),
00450 -( j + offset - half_size ), -half_size );
00451 tmp.normalize();
00452 tmp = tmp*0.5 - zero_normal;
00453 *ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
00454 *ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
00455 *ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
00456 }
00457 }
00458 cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Z, image);
00459
00460 osg::StateSet* state;
00461 state = SGMakeState(texture_path, "overcast.png", "overcast_n.png");
00462 layer_states[SG_CLOUD_OVERCAST] = state;
00463 state = SGMakeState(texture_path, "overcast_top.png", "overcast_top_n.png");
00464 layer_states2[SG_CLOUD_OVERCAST] = state;
00465
00466 state = SGMakeState(texture_path, "broken.png", "broken_n.png");
00467 layer_states[SG_CLOUD_BROKEN] = state;
00468 layer_states2[SG_CLOUD_BROKEN] = state;
00469
00470 state = SGMakeState(texture_path, "scattered.png", "scattered_n.png");
00471 layer_states[SG_CLOUD_SCATTERED] = state;
00472 layer_states2[SG_CLOUD_SCATTERED] = state;
00473
00474 state = SGMakeState(texture_path, "few.png", "few_n.png");
00475 layer_states[SG_CLOUD_FEW] = state;
00476 layer_states2[SG_CLOUD_FEW] = state;
00477
00478 state = SGMakeState(texture_path, "cirrus.png", "cirrus_n.png");
00479 layer_states[SG_CLOUD_CIRRUS] = state;
00480 layer_states2[SG_CLOUD_CIRRUS] = state;
00481
00482 layer_states[SG_CLOUD_CLEAR] = 0;
00483 layer_states2[SG_CLOUD_CLEAR] = 0;
00484 osg::CopyOp copyOp;
00485 for (int i = 0; i < SG_MAX_CLOUD_COVERAGES; ++i) {
00486 StateAttributeFactory *saf = StateAttributeFactory::instance();
00487 if (layer_states[i].valid()) {
00488 if (layer_states[i] == layer_states2[i])
00489 layer_states2[i] = static_cast<osg::StateSet*>(layer_states[i]->clone(copyOp));
00490 layer_states[i]->setAttribute(saf ->getCullFaceFront());
00491 layer_states2[i]->setAttribute(saf ->getCullFaceBack());
00492 }
00493 }
00494
00495
00496
00497 }
00498
00499 scale = 4000.0;
00500 last_lon = last_lat = -999.0f;
00501
00502 setTextureOffset(base);
00503
00504 const float layer_scale = layer_span / scale;
00505 const float mpi = SG_PI/4;
00506
00507
00508
00509
00510
00511
00512 const float layer_to_core = (SG_EARTH_RAD * 1000 + layer_asl);
00513 const float layer_angle = 0.5*layer_span / layer_to_core;
00514 const float border_to_core = layer_to_core * cos(layer_angle);
00515 const float alt_diff = layer_to_core - border_to_core;
00516
00517 for (int i = 0; i < 4; i++) {
00518 if ( layer[i] != NULL ) {
00519 layer_transform->removeChild(layer[i].get());
00520 }
00521
00522 vl[i] = new osg::Vec3Array;
00523 cl[i] = new osg::Vec4Array;
00524 tl[i] = new osg::Vec2Array;
00525
00526
00527 osg::Vec3 vertex(layer_span*(i-2)/2, -layer_span,
00528 alt_diff * (sin(i*mpi) - 2));
00529 osg::Vec2 tc(layer_scale * i/4, 0.0f);
00530 osg::Vec4 color(cloudColors[0], (i == 0) ? 0.0f : 0.15f);
00531
00532 cl[i]->push_back(color);
00533 vl[i]->push_back(vertex);
00534 tl[i]->push_back(tc);
00535
00536 for (int j = 0; j < 4; j++) {
00537 vertex = osg::Vec3(layer_span*(i-1)/2, layer_span*(j-2)/2,
00538 alt_diff * (sin((i+1)*mpi) + sin(j*mpi) - 2));
00539 tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale * j/4);
00540 color = osg::Vec4(cloudColors[0],
00541 ( (j == 0) || (i == 3)) ?
00542 ( (j == 0) && (i == 3)) ? 0.0f : 0.15f : 1.0f );
00543
00544 cl[i]->push_back(color);
00545 vl[i]->push_back(vertex);
00546 tl[i]->push_back(tc);
00547
00548 vertex = osg::Vec3(layer_span*(i-2)/2, layer_span*(j-1)/2,
00549 alt_diff * (sin(i*mpi) + sin((j+1)*mpi) - 2) );
00550 tc = osg::Vec2(layer_scale * i/4, layer_scale * (j+1)/4 );
00551 color = osg::Vec4(cloudColors[0],
00552 ((j == 3) || (i == 0)) ?
00553 ((j == 3) && (i == 0)) ? 0.0f : 0.15f : 1.0f );
00554 cl[i]->push_back(color);
00555 vl[i]->push_back(vertex);
00556 tl[i]->push_back(tc);
00557 }
00558
00559 vertex = osg::Vec3(layer_span*(i-1)/2, layer_span,
00560 alt_diff * (sin((i+1)*mpi) - 2));
00561
00562 tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale);
00563
00564 color = osg::Vec4(cloudColors[0], (i == 3) ? 0.0f : 0.15f );
00565
00566 cl[i]->push_back( color );
00567 vl[i]->push_back( vertex );
00568 tl[i]->push_back( tc );
00569
00570 osg::Geometry* geometry = new osg::Geometry;
00571 geometry->setUseDisplayList(false);
00572 geometry->setVertexArray(vl[i].get());
00573 geometry->setNormalBinding(osg::Geometry::BIND_OFF);
00574 geometry->setColorArray(cl[i].get());
00575 geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
00576 geometry->setTexCoordArray(0, tl[i].get());
00577 geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, vl[i]->size()));
00578 layer[i] = new osg::Geode;
00579
00580 std::stringstream sstr;
00581 sstr << "Cloud Layer (" << i << ")";
00582 geometry->setName(sstr.str());
00583 layer[i]->setName(sstr.str());
00584 layer[i]->addDrawable(geometry);
00585 layer_transform->addChild(layer[i].get());
00586 }
00587
00588
00589 if ( layer_states[layer_coverage].valid() ) {
00590 osg::CopyOp copyOp;
00591
00592 osg::StateSet* stateSet = static_cast<osg::StateSet*>(layer_states2[layer_coverage]->clone(copyOp));
00593 stateSet->setDataVariance(osg::Object::DYNAMIC);
00594 group_top->setStateSet(stateSet);
00595 stateSet = static_cast<osg::StateSet*>(layer_states[layer_coverage]->clone(copyOp));
00596 stateSet->setDataVariance(osg::Object::DYNAMIC);
00597 group_bottom->setStateSet(stateSet);
00598 }
00599 }
00600
00601
00602 bool SGCloudLayer::repaint( const SGVec3f& fog_color ) {
00603 osg::Vec4f combineColor(fog_color.osg(), cloud_alpha);
00604 osg::TexEnvCombine* combiner
00605 = dynamic_cast<osg::TexEnvCombine*>(layer_root->getStateSet()
00606 ->getTextureAttribute(1, osg::StateAttribute::TEXENV));
00607 combiner->setConstantColor(combineColor);
00608
00609
00610
00611 return true;
00612 }
00613
00614
00615
00616
00617
00618
00619 bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon, double lat,
00620 double alt, double dt )
00621 {
00622
00623 osg::Vec3 asl_offset(up.osg());
00624 asl_offset.normalize();
00625 if ( alt <= layer_asl ) {
00626 asl_offset *= layer_asl;
00627 } else {
00628 asl_offset *= layer_asl + layer_thickness;
00629 }
00630
00631
00632
00633 asl_offset += p.osg();
00634
00635
00636
00637 osg::Matrix T, LON, LAT;
00638
00639
00640 T.makeTranslate( asl_offset );
00641
00642
00643
00644
00645
00646
00647
00648
00649 LON.makeRotate(lon, osg::Vec3(0, 0, 1));
00650
00651
00652
00653 LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
00654
00655 layer_transform->setMatrix( LAT*LON*T );
00656
00657
00658
00659
00660
00661
00662
00663 group_bottom->getStateSet()->setRenderBinDetails(-(int)layer_asl,
00664 "RenderBin");
00665 group_top->getStateSet()->setRenderBinDetails((int)layer_asl,
00666 "RenderBin");
00667 if ( alt <= layer_asl ) {
00668 layer_root->setSingleChildOn(0);
00669 } else if ( alt >= layer_asl + layer_thickness ) {
00670 layer_root->setSingleChildOn(1);
00671 } else {
00672 layer_root->setAllChildrenOff();
00673 }
00674
00675
00676
00677 if ( last_lon < -900 ) {
00678 last_lon = lon;
00679 last_lat = lat;
00680 }
00681
00682 double sp_dist = speed*dt;
00683
00684 if ( lon != last_lon || lat != last_lat || sp_dist != 0 ) {
00685 Point3D start( last_lon, last_lat, 0.0 );
00686 Point3D dest( lon, lat, 0.0 );
00687 double course = 0.0, dist = 0.0;
00688
00689 calc_gc_course_dist( dest, start, &course, &dist );
00690
00691
00692
00693
00694
00695
00696
00697 if ( isnan(course) ) {
00698 course = last_course;
00699 } else {
00700 last_course = course;
00701 }
00702
00703
00704 double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0;
00705
00706 if (dist > 0.0) {
00707 ax = cos(course) * dist;
00708 ay = sin(course) * dist;
00709 }
00710
00711 if (sp_dist > 0) {
00712 bx = cos((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
00713 by = sin((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
00714 }
00715
00716
00717 double xoff = (ax + bx) / (2 * scale);
00718 double yoff = (ay + by) / (2 * scale);
00719
00720 const float layer_scale = layer_span / scale;
00721
00722
00723 base[0] += xoff;
00724
00725
00726
00727
00728
00729 if ( base[0] > -10.0 && base[0] < 10.0 ) {
00730 base[0] -= (int)base[0];
00731 } else {
00732 SG_LOG(SG_ASTRO, SG_DEBUG,
00733 "Error: base = " << base[0] << "," << base[1] <<
00734 " course = " << course << " dist = " << dist );
00735 base[0] = 0.0;
00736 }
00737
00738 base[1] += yoff;
00739
00740
00741
00742
00743 if ( base[1] > -10.0 && base[1] < 10.0 ) {
00744 base[1] -= (int)base[1];
00745 } else {
00746 SG_LOG(SG_ASTRO, SG_DEBUG,
00747 "Error: base = " << base[0] << "," << base[1] <<
00748 " course = " << course << " dist = " << dist );
00749 base[1] = 0.0;
00750 }
00751
00752
00753
00754 setTextureOffset(base);
00755 last_lon = lon;
00756 last_lat = lat;
00757 }
00758
00759 layer3D->reposition( p, up, lon, lat, dt, layer_asl);
00760 return true;
00761 }
00762
00763 void SGCloudLayer::set_enable3dClouds(bool enable) {
00764
00765 if (layer3D->defined3D && enable) {
00766 cloud_root->setChildValue(layer3D->getNode(), true);
00767 cloud_root->setChildValue(layer_root.get(), false);
00768 } else {
00769 cloud_root->setChildValue(layer3D->getNode(), false);
00770 cloud_root->setChildValue(layer_root.get(), true);
00771 }
00772 }