#include <osg/TexEnv>
#include <osg/Texture2D>
#include <osg/TextureCubeMap>
+#include <osg/TexMat>
#include <simgear/math/sg_random.h>
#include <simgear/debug/logstream.hxx>
// make an StateSet for a cloud layer given the named texture
static osg::StateSet*
-SGMakeState(const SGPath &path, const char* colorTexture, const char* normalTexture)
+SGMakeState(const SGPath &path, const char* colorTexture,
+ const char* normalTexture)
{
osg::StateSet *stateSet = new osg::StateSet;
{
layer_root->addChild(group_bottom.get());
layer_root->addChild(group_top.get());
+ // Force the cloud layers into recursive bins of bin 4.
+ osg::StateSet *rootSet = layer_root->getOrCreateStateSet();
+ rootSet->setRenderBinDetails(4, "RenderBin");
+ rootSet->setTextureAttribute(0, new osg::TexMat());
+ base = osg::Vec2(sg_random(), sg_random());
group_top->addChild(layer_transform.get());
group_bottom->addChild(layer_transform.get());
}
}
+void
+SGCloudLayer::setTextureOffset(const osg::Vec2& offset)
+{
+ osg::StateAttribute* attr = layer_root->getStateSet()
+ ->getTextureAttribute(0, osg::StateAttribute::TEXMAT);
+ osg::TexMat* texMat = dynamic_cast<osg::TexMat*>(attr);
+ if (!texMat)
+ return;
+ texMat->setMatrix(osg::Matrix::translate(offset[0], offset[1], 0.0));
+}
+
// build the cloud object
void
SGCloudLayer::rebuild()
scale = 4000.0;
last_lon = last_lat = -999.0f;
-
- base = osg::Vec2(sg_random(), sg_random());
-
+
+ setTextureOffset(base);
// build the cloud layer
const float layer_scale = layer_span / scale;
const float mpi = SG_PI/4;
osg::Vec3 vertex(layer_span*(i-2)/2, -layer_span,
alt_diff * (sin(i*mpi) - 2));
- osg::Vec2 tc(base[0] + layer_scale * i/4, base[1]);
+ osg::Vec2 tc(layer_scale * i/4, 0.0f);
osg::Vec4 color(1.0f, 1.0f, 1.0f, (i == 0) ? 0.0f : 0.15f);
cl[i]->push_back(color);
for (int j = 0; j < 4; j++) {
vertex = osg::Vec3(layer_span*(i-1)/2, layer_span*(j-2)/2,
alt_diff * (sin((i+1)*mpi) + sin(j*mpi) - 2));
- tc = osg::Vec2(base[0] + layer_scale * (i+1)/4,
- base[1] + layer_scale * j/4);
+ tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale * j/4);
color = osg::Vec4(1.0f, 1.0f, 1.0f,
( (j == 0) || (i == 3)) ?
( (j == 0) && (i == 3)) ? 0.0f : 0.15f : 1.0f );
vertex = osg::Vec3(layer_span*(i-2)/2, layer_span*(j-1)/2,
alt_diff * (sin(i*mpi) + sin((j+1)*mpi) - 2) );
- tc = osg::Vec2(base[0] + layer_scale * i/4,
- base[1] + layer_scale * (j+1)/4 );
+ tc = osg::Vec2(layer_scale * i/4, layer_scale * (j+1)/4 );
color = osg::Vec4(1.0f, 1.0f, 1.0f,
((j == 3) || (i == 0)) ?
((j == 3) && (i == 0)) ? 0.0f : 0.15f : 1.0f );
vertex = osg::Vec3(layer_span*(i-1)/2, layer_span,
alt_diff * (sin((i+1)*mpi) - 2));
- tc = osg::Vec2(base[0] + layer_scale * (i+1)/4,
- base[1] + layer_scale);
+ tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale);
color = osg::Vec4(1.0f, 1.0f, 1.0f, (i == 3) ? 0.0f : 0.15f );
if ( layer_states[layer_coverage].valid() ) {
osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_ALL
& ~osg::CopyOp::DEEP_COPY_TEXTURES);
-
+ // render bin will be set in reposition
osg::StateSet* stateSet = static_cast<osg::StateSet*>(layer_states2[layer_coverage]->clone(copyOp));
- // OSGFIXME
- stateSet->setRenderBinDetails(4, "RenderBin");
+ stateSet->setDataVariance(osg::Object::DYNAMIC);
group_top->setStateSet(stateSet);
stateSet = static_cast<osg::StateSet*>(layer_states2[layer_coverage]->clone(copyOp));
- stateSet->setRenderBinDetails(4, "RenderBin");
+ stateSet->setDataVariance(osg::Object::DYNAMIC);
group_bottom->setStateSet(stateSet);
}
}
LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
layer_transform->setMatrix( LAT*LON*T );
-
+ // The layers need to be drawn in order because they are
+ // translucent, but OSG transparency sorting doesn't work because
+ // the cloud polys are huge. However, the ordering is simple: the
+ // bottom polys should be drawn from high altitude to low, and the
+ // top polygons from low to high. The altitude can be used
+ // directly to order the polygons!
+ layer_root->getChild(0)->getStateSet()->setRenderBinDetails(-(int)layer_asl,
+ "RenderBin");
+ layer_root->getChild(1)->getStateSet()->setRenderBinDetails((int)layer_asl,
+ "RenderBin");
if ( alt <= layer_asl ) {
layer_root->setSingleChildOn(0);
- } else {
+ } else if ( alt >= layer_asl + layer_thickness ) {
layer_root->setSingleChildOn(1);
+ } else {
+ layer_root->setAllChildrenOff();
}
+
// now calculate update texture coordinates
if ( last_lon < -900 ) {
// cout << "base = " << base[0] << "," << base[1] << endl;
- for (int i = 0; i < 4; i++) {
- (*tl[i])[0] = base + osg::Vec2(i, 0)*layer_scale/4;
- for (int j = 0; j < 4; j++) {
- (*tl[i])[j*2+1] = base + osg::Vec2(i+1, j)*layer_scale/4;
- (*tl[i])[j*2+2] = base + osg::Vec2(i, j+1)*layer_scale/4;
- }
- (*tl[i])[9] = base + osg::Vec2(i+1, 4)*layer_scale/4;
- }
-
+ setTextureOffset(base);
last_lon = lon;
last_lat = lat;
}