> Something has changed in the environment manager which means that clouds
> generateion is now inconsistent. I'm still tracking it down, as my recent
> changes shouldn't have affected this.

Well, the cause was a bug in my code, but it didn't expose itself until we moved
to multiple cameras. The attached patch fixes the problem.

I've also put in a new heuristic to improve the frame-rate. Clouds that are already sorted
are likely to still be sorted in subsequent frames. Therefore I've put in a back-off
mechanism for the bubble-sort pass. This should mean that if you stay completely
stationary, once the clouds become sorted they will eventually only perform a
bubble sort pass every 128 frames.
This commit is contained in:
fredb
2008-11-26 07:28:10 +00:00
parent bad80521a8
commit fa7490fb38
5 changed files with 70 additions and 26 deletions

View File

@@ -37,27 +37,56 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
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);
@@ -74,7 +103,7 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
_geometry->draw(renderInfo);
}
}
BoundingBox CloudShaderGeometry::computeBound() const
{
BoundingBox geom_box = _geometry->getBound();

View File

@@ -52,12 +52,14 @@ class CloudShaderGeometry : public osg::Drawable
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.*/
@@ -66,6 +68,14 @@ class CloudShaderGeometry : public osg::Drawable
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)
@@ -128,8 +138,13 @@ class CloudShaderGeometry : public osg::Drawable
protected:
virtual ~CloudShaderGeometry() {}
virtual ~CloudShaderGeometry() {
delete skip_info;
for (int i = 0; i < _cloudsprites.size(); i++)
{
delete _cloudsprites[i];
}
}
};
}

View File

@@ -731,7 +731,7 @@ void SGCloudLayer::set_enable3dClouds(bool enable) {
} else {
cloud_root->setChildValue(layer3D->getNode(), false);
cloud_root->setChildValue(layer_root.get(), true);
}
}
}
void SGCloudLayer::applyDensity() {

View File

@@ -64,7 +64,6 @@ using std::vector;
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) {
@@ -99,7 +98,6 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
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.
@@ -141,10 +139,12 @@ SGCloudField::SGCloudField() :
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];
@@ -263,5 +263,5 @@ void SGCloudField::addCloud( SGVec3f& pos, SGNewCloud *cloud) {
transform->setPosition(pos.osg());
transform->addChild(geode.get());
field_group[x][y]->addChild(transform.get());
field_group[x][y]->addChild(transform.get(), true);
}

View File

@@ -75,7 +75,7 @@ private:
sgSphere field_sphere;
float last_density;
SGGeoc cld_pos;
int reposition_count;
public:
SGCloudField();