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 <simgear/structure/OSGVersion.hxx>
00034 #include <osg/AlphaFunc>
00035 #include <osg/BlendFunc>
00036 #include <osg/CullFace>
00037 #include <osg/Geode>
00038 #include <osg/Geometry>
00039 #include <osg/Material>
00040 #include <osg/ShadeModel>
00041 #include <osg/TexEnv>
00042 #include <osg/TexEnvCombine>
00043 #include <osg/Texture2D>
00044 #include <osg/TextureCubeMap>
00045 #include <osg/TexMat>
00046 #include <osg/Fog>
00047 #if SG_OSG_MIN_VERSION_REQUIRED(2,9,5)
00048 #include <osgDB/Options>
00049 #endif
00050
00051 #include <simgear/math/sg_random.h>
00052 #include <simgear/misc/PathOptions.hxx>
00053 #include <simgear/debug/logstream.hxx>
00054 #include <simgear/scene/model/model.hxx>
00055 #include <simgear/scene/util/RenderConstants.hxx>
00056 #include <simgear/scene/util/StateAttributeFactory.hxx>
00057 #include <simgear/math/polar3d.hxx>
00058
00059 #include "newcloud.hxx"
00060 #include "cloudfield.hxx"
00061 #include "cloud.hxx"
00062
00063 using namespace simgear;
00064 using namespace osg;
00065
00066 #if defined(__MINGW32__)
00067 #define isnan(x) _isnan(x)
00068 #endif
00069
00070
00071
00072
00073
00074
00075
00076
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 #if 1
00485
00486
00487 osg::CopyOp copyOp;
00488 for (int i = 0; i < SG_MAX_CLOUD_COVERAGES; ++i) {
00489 StateAttributeFactory *saf = StateAttributeFactory::instance();
00490 if (layer_states[i].valid()) {
00491 if (layer_states[i] == layer_states2[i])
00492 layer_states2[i] = static_cast<osg::StateSet*>(layer_states[i]->clone(copyOp));
00493 layer_states[i]->setAttribute(saf ->getCullFaceFront());
00494 layer_states2[i]->setAttribute(saf ->getCullFaceBack());
00495 }
00496 }
00497 #endif
00498 }
00499
00500 scale = 4000.0;
00501 last_lon = last_lat = -999.0f;
00502
00503 setTextureOffset(base);
00504
00505 const float layer_scale = layer_span / scale;
00506 const float mpi = SG_PI/4;
00507
00508
00509
00510
00511
00512
00513 const float layer_to_core = (SG_EARTH_RAD * 1000 + layer_asl);
00514 const float layer_angle = 0.5*layer_span / layer_to_core;
00515 const float border_to_core = layer_to_core * cos(layer_angle);
00516 const float alt_diff = layer_to_core - border_to_core;
00517
00518 for (int i = 0; i < 4; i++) {
00519 if ( layer[i] != NULL ) {
00520 layer_transform->removeChild(layer[i].get());
00521 }
00522
00523 vl[i] = new osg::Vec3Array;
00524 cl[i] = new osg::Vec4Array;
00525 tl[i] = new osg::Vec2Array;
00526
00527
00528 osg::Vec3 vertex(layer_span*(i-2)/2, -layer_span,
00529 alt_diff * (sin(i*mpi) - 2));
00530 osg::Vec2 tc(layer_scale * i/4, 0.0f);
00531 osg::Vec4 color(cloudColors[0], (i == 0) ? 0.0f : 0.15f);
00532
00533 cl[i]->push_back(color);
00534 vl[i]->push_back(vertex);
00535 tl[i]->push_back(tc);
00536
00537 for (int j = 0; j < 4; j++) {
00538 vertex = osg::Vec3(layer_span*(i-1)/2, layer_span*(j-2)/2,
00539 alt_diff * (sin((i+1)*mpi) + sin(j*mpi) - 2));
00540 tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale * j/4);
00541 color = osg::Vec4(cloudColors[0],
00542 ( (j == 0) || (i == 3)) ?
00543 ( (j == 0) && (i == 3)) ? 0.0f : 0.15f : 1.0f );
00544
00545 cl[i]->push_back(color);
00546 vl[i]->push_back(vertex);
00547 tl[i]->push_back(tc);
00548
00549 vertex = osg::Vec3(layer_span*(i-2)/2, layer_span*(j-1)/2,
00550 alt_diff * (sin(i*mpi) + sin((j+1)*mpi) - 2) );
00551 tc = osg::Vec2(layer_scale * i/4, layer_scale * (j+1)/4 );
00552 color = osg::Vec4(cloudColors[0],
00553 ((j == 3) || (i == 0)) ?
00554 ((j == 3) && (i == 0)) ? 0.0f : 0.15f : 1.0f );
00555 cl[i]->push_back(color);
00556 vl[i]->push_back(vertex);
00557 tl[i]->push_back(tc);
00558 }
00559
00560 vertex = osg::Vec3(layer_span*(i-1)/2, layer_span,
00561 alt_diff * (sin((i+1)*mpi) - 2));
00562
00563 tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale);
00564
00565 color = osg::Vec4(cloudColors[0], (i == 3) ? 0.0f : 0.15f );
00566
00567 cl[i]->push_back( color );
00568 vl[i]->push_back( vertex );
00569 tl[i]->push_back( tc );
00570
00571 osg::Geometry* geometry = new osg::Geometry;
00572 geometry->setUseDisplayList(false);
00573 geometry->setVertexArray(vl[i].get());
00574 geometry->setNormalBinding(osg::Geometry::BIND_OFF);
00575 geometry->setColorArray(cl[i].get());
00576 geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
00577 geometry->setTexCoordArray(0, tl[i].get());
00578 geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, vl[i]->size()));
00579 layer[i] = new osg::Geode;
00580
00581 std::stringstream sstr;
00582 sstr << "Cloud Layer (" << i << ")";
00583 geometry->setName(sstr.str());
00584 layer[i]->setName(sstr.str());
00585 layer[i]->addDrawable(geometry);
00586 layer_transform->addChild(layer[i].get());
00587 }
00588
00589
00590 if ( layer_states[layer_coverage].valid() ) {
00591 osg::CopyOp copyOp;
00592
00593 osg::StateSet* stateSet = static_cast<osg::StateSet*>(layer_states2[layer_coverage]->clone(copyOp));
00594 stateSet->setDataVariance(osg::Object::DYNAMIC);
00595 group_top->setStateSet(stateSet);
00596 stateSet = static_cast<osg::StateSet*>(layer_states[layer_coverage]->clone(copyOp));
00597 stateSet->setDataVariance(osg::Object::DYNAMIC);
00598 group_bottom->setStateSet(stateSet);
00599 }
00600 }
00601
00602
00603 bool SGCloudLayer::repaint( const SGVec3f& fog_color ) {
00604 osg::Vec4f combineColor(toOsg(fog_color), cloud_alpha);
00605 osg::TexEnvCombine* combiner
00606 = dynamic_cast<osg::TexEnvCombine*>(layer_root->getStateSet()
00607 ->getTextureAttribute(1, osg::StateAttribute::TEXENV));
00608 combiner->setConstantColor(combineColor);
00609
00610
00611
00612 return true;
00613 }
00614
00615
00616
00617
00618
00619
00620 bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon, double lat,
00621 double alt, double dt )
00622 {
00623
00624 osg::Vec3 asl_offset(toOsg(up));
00625 asl_offset.normalize();
00626 if ( alt <= layer_asl ) {
00627 asl_offset *= layer_asl;
00628 } else {
00629 asl_offset *= layer_asl + layer_thickness;
00630 }
00631
00632
00633
00634 asl_offset += toOsg(p);
00635
00636
00637
00638 osg::Matrix T, LON, LAT;
00639
00640
00641 T.makeTranslate( asl_offset );
00642
00643
00644
00645
00646
00647
00648
00649
00650 LON.makeRotate(lon, osg::Vec3(0, 0, 1));
00651
00652
00653
00654 LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
00655
00656 layer_transform->setMatrix( LAT*LON*T );
00657
00658
00659
00660
00661
00662
00663
00664 group_bottom->getStateSet()->setRenderBinDetails(-(int)layer_asl,
00665 "RenderBin");
00666 group_top->getStateSet()->setRenderBinDetails((int)layer_asl,
00667 "RenderBin");
00668 if ( alt <= layer_asl ) {
00669 layer_root->setSingleChildOn(0);
00670 } else if ( alt >= layer_asl + layer_thickness ) {
00671 layer_root->setSingleChildOn(1);
00672 } else {
00673 layer_root->setAllChildrenOff();
00674 }
00675
00676
00677
00678 if ( last_lon < -900 ) {
00679 last_lon = lon;
00680 last_lat = lat;
00681 }
00682
00683 double sp_dist = speed*dt;
00684
00685 if ( lon != last_lon || lat != last_lat || sp_dist != 0 ) {
00686 Point3D start( last_lon, last_lat, 0.0 );
00687 Point3D dest( lon, lat, 0.0 );
00688 double course = 0.0, dist = 0.0;
00689
00690 calc_gc_course_dist( dest, start, &course, &dist );
00691
00692
00693
00694
00695
00696
00697
00698 if ( isnan(course) ) {
00699 course = last_course;
00700 } else {
00701 last_course = course;
00702 }
00703
00704
00705 double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0;
00706
00707 if (dist > 0.0) {
00708 ax = cos(course) * dist;
00709 ay = sin(course) * dist;
00710 }
00711
00712 if (sp_dist > 0) {
00713 bx = cos((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
00714 by = sin((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
00715 }
00716
00717
00718 double xoff = (ax + bx) / (2 * scale);
00719 double yoff = (ay + by) / (2 * scale);
00720
00721
00722
00723
00724 base[0] += xoff;
00725
00726
00727
00728
00729
00730 if ( base[0] > -10.0 && base[0] < 10.0 ) {
00731 base[0] -= (int)base[0];
00732 } else {
00733 SG_LOG(SG_ASTRO, SG_DEBUG,
00734 "Error: base = " << base[0] << "," << base[1] <<
00735 " course = " << course << " dist = " << dist );
00736 base[0] = 0.0;
00737 }
00738
00739 base[1] += yoff;
00740
00741
00742
00743
00744 if ( base[1] > -10.0 && base[1] < 10.0 ) {
00745 base[1] -= (int)base[1];
00746 } else {
00747 SG_LOG(SG_ASTRO, SG_DEBUG,
00748 "Error: base = " << base[0] << "," << base[1] <<
00749 " course = " << course << " dist = " << dist );
00750 base[1] = 0.0;
00751 }
00752
00753
00754
00755 setTextureOffset(base);
00756 last_lon = lon;
00757 last_lat = lat;
00758 }
00759
00760 layer3D->reposition( p, up, lon, lat, dt, layer_asl);
00761 return true;
00762 }
00763
00764 void SGCloudLayer::set_enable3dClouds(bool enable) {
00765
00766 if (layer3D->defined3D && enable) {
00767 cloud_root->setChildValue(layer3D->getNode(), true);
00768 cloud_root->setChildValue(layer_root.get(), false);
00769 } else {
00770 cloud_root->setChildValue(layer3D->getNode(), false);
00771 cloud_root->setChildValue(layer_root.get(), true);
00772 }
00773 }