if (!_cloudsprites.size()) return;
osg::State& state = *renderInfo.getState();
- osg::Matrix vm = state.getModelViewMatrix();
- //TODO: It isn't clear whether this is worth the perf hit ATM.
+ // If the cloud is already sorted, then it is likely to still be sorted.
+ // Therefore we can avoid re-sorting it for a period. If it is still
+ // sorted after that period, then we can wait for a longer period before
+ // checking again. In this way, only clouds that are changing regularly
+ // are sorted.
- // Transform the viewing direction, represented by the eye space vector (0,0,-1, 0), into model-space
- // (here we simply take the opposite direction and reverse the ordering when sorting)
- osg::Vec3f view_dir(vm(0, 2), vm(1, 2), vm(2, 2)); // Caveat: OpenSceneGraph matrices are transposed!
-
- float p = view_dir*_cloudsprites[0]->position.osg();
- // Do a single iteration of a bubble sort, sorting
- // back to front.
- for(int i = 0; i < _cloudsprites.size() - 1; i++)
+ skip_info->skip_count = (skip_info->skip_count + 1) % skip_info->skip_limit;
+
+ if (skip_info->skip_count == 0)
{
- float q = view_dir*_cloudsprites[i+1]->position.osg();
- if (p > q) {
- CloudSprite c = *_cloudsprites[i];
- *_cloudsprites[i] = *_cloudsprites[i+1];
- *_cloudsprites[i+1] = c;
+ osg::Matrix vm = state.getModelViewMatrix();
+ bool sorted = true;
+
+ // Transform the viewing direction, represented by the eye space vector (0,0,-1, 0), into model-space
+ // (here we simply take the opposite direction and reverse the ordering when sorting)
+ osg::Vec3f view_dir(vm(0, 2), vm(1, 2), vm(2, 2)); // Caveat: OpenSceneGraph matrices are transposed!
+
+ float p = view_dir*_cloudsprites[0]->position.osg();
+ // Do a single iteration of a bubble sort, sorting
+ // back to front.
+ for(int i = 0; i < _cloudsprites.size() - 1; i++)
+ {
+ float q = view_dir*_cloudsprites[i+1]->position.osg();
+ if (p > q) {
+ CloudSprite c = *_cloudsprites[i];
+ *_cloudsprites[i] = *_cloudsprites[i+1];
+ *_cloudsprites[i+1] = c;
+
+ sorted = false;
+ }
+ else
+ p = q;
+ }
+
+ if (sorted)
+ {
+ // This cloud is sorted, so no need to re-sort.
+ // Maximum of every 128 frames (2 - 4 seconds)
+ skip_info->skip_limit = skip_info->skip_limit * 2;
+ if (skip_info->skip_limit > 128)
+ {
+ skip_info->skip_limit = 128;
+ }
}
else
- p = q;
+ {
+ // This cloud is unsorted, so we need to sort next frame
+ skip_info->skip_limit = 1;
+ }
}
const Extensions* extensions = getExtensions(state.getContextID(),true);
_geometry->draw(renderInfo);
}
}
-
+
BoundingBox CloudShaderGeometry::computeBound() const
{
BoundingBox geom_box = _geometry->getBound();
CloudShaderGeometry()
{
setUseDisplayList(false);
+ skip_info = new SkipInfo();
}
CloudShaderGeometry(int vx, int vy) :
varieties_x(vx), varieties_y(vy)
{
setUseDisplayList(false);
+ skip_info = new SkipInfo();
}
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
META_Object(flightgear, CloudShaderGeometry);
+ struct SkipInfo {
+ SkipInfo() : skip_count(0), skip_limit(1) {}
+ int skip_count;
+ int skip_limit;
+ };
+
+ SkipInfo* skip_info;
+
struct CloudSprite {
CloudSprite(SGVec3f& p, int tx, int ty, float w, float h, float s, float ch) :
position(p), texture_index_x(tx), texture_index_y(ty), width(w), height(h), shade(s), cloud_height(ch)
protected:
- virtual ~CloudShaderGeometry() {}
-
+ virtual ~CloudShaderGeometry() {
+ delete skip_info;
+ for (int i = 0; i < _cloudsprites.size(); i++)
+ {
+ delete _cloudsprites[i];
+ }
+ }
};
}
float SGCloudField::fieldSize = 50000.0f;
float SGCloudField::density = 100.0f;
double SGCloudField::timer_dt = 0.0;
-int reposition_count = 0;
sgVec3 SGCloudField::view_vec, SGCloudField::view_X, SGCloudField::view_Y;
void SGCloudField::set_density(float density) {
cld_pos = SGGeoc::fromGeod(SGGeod::fromRad(lon, lat));
} else if (dist > fieldSize) {
// Distance requires repositioning of cloud field.
-
// We can easily work out the direction to reposition
// from the course between the cloud position and the
// camera position.
deltay(0.0),
last_course(0.0),
last_density(0.0),
- defined3D(false)
+ defined3D(false),
+ reposition_count(0)
{
cld_pos = SGGeoc();
- field_root->addChild(field_transform.get());
+ field_root->addChild(field_transform.get());
+ field_root->setName("3D Cloud field root");
osg::ref_ptr<osg::Group> quad_root = new osg::Group();
osg::ref_ptr<osg::LOD> quad[BRANCH_SIZE][BRANCH_SIZE];
transform->setPosition(pos.osg());
transform->addChild(geode.get());
- field_group[x][y]->addChild(transform.get());
+ field_group[x][y]->addChild(transform.get(), true);
}