Added corner dirty options to TerrainTechnique, added experimental code paths in GeometryTechnique for accounting for neighbouring corner tiles - optionally compiled out in this check-in.

Changed the normal computation in GeometryTechnique so that it doesn't include diagonals, thus avoid normal jumps at corners.
This commit is contained in:
Robert Osfield 2010-04-09 08:52:40 +00:00
parent d992f6e018
commit fccda08491
2 changed files with 109 additions and 3 deletions

View File

@ -179,8 +179,13 @@ class OSGTERRAIN_EXPORT TerrainTile : public osg::Group
LEFT_EDGE_DIRTY = 1<<2, LEFT_EDGE_DIRTY = 1<<2,
RIGHT_EDGE_DIRTY = 1<<3, RIGHT_EDGE_DIRTY = 1<<3,
TOP_EDGE_DIRTY = 1<<4, TOP_EDGE_DIRTY = 1<<4,
BOTTOM_EDGE_DIRTY = 1<<5, TOP_LEFT_CORNER_DIRTY = 1<<5,
EDGES_DIRTY = LEFT_EDGE_DIRTY | RIGHT_EDGE_DIRTY | TOP_EDGE_DIRTY | BOTTOM_EDGE_DIRTY, TOP_RIGHT_CORNER_DIRTY = 1<<6,
BOTTOM_EDGE_DIRTY = 1<<7,
BOTTOM_LEFT_CORNER_DIRTY = 1<<8,
BOTTOM_RIGHT_CORNER_DIRTY = 1<<9,
EDGES_DIRTY = LEFT_EDGE_DIRTY | RIGHT_EDGE_DIRTY | TOP_EDGE_DIRTY | BOTTOM_EDGE_DIRTY |
TOP_LEFT_CORNER_DIRTY | TOP_RIGHT_CORNER_DIRTY | BOTTOM_LEFT_CORNER_DIRTY | BOTTOM_RIGHT_CORNER_DIRTY,
ALL_DIRTY = IMAGERY_DIRTY | ELEVATION_DIRTY | EDGES_DIRTY ALL_DIRTY = IMAGERY_DIRTY | ELEVATION_DIRTY | EDGES_DIRTY
}; };

View File

@ -308,6 +308,53 @@ class VertexNormalGenerator
inline bool computeNormal(int c, int r, osg::Vec3& n) const inline bool computeNormal(int c, int r, osg::Vec3& n) const
{ {
#if 1
return computeNormalWithNoDiagonals(c,r,n);
#else
return computeNormalWithDiagonals(c,r,n);
#endif
}
inline bool computeNormalWithNoDiagonals(int c, int r, osg::Vec3& n) const
{
osg::Vec3 center;
bool center_valid = vertex(c, r, center);
if (!center_valid) return false;
osg::Vec3 left, right, top, bottom;
bool left_valid = vertex(c-1, r, left);
bool right_valid = vertex(c+1, r, right);
bool bottom_valid = vertex(c, r-1, bottom);
bool top_valid = vertex(c, r+1, top);
osg::Vec3 dx(0.0f,0.0f,0.0f);
osg::Vec3 dy(0.0f,0.0f,0.0f);
osg::Vec3 zero(0.0f,0.0f,0.0f);
if (left_valid)
{
dx = center-left;
}
if (right_valid)
{
dx = right-center;
}
if (bottom_valid)
{
dy += center-bottom;
}
if (top_valid)
{
dy += top-center;
}
if (dx==zero || dy==zero) return false;
n = dx ^ dy;
return n.normalize() != 0.0f;
}
inline bool computeNormalWithDiagonals(int c, int r, osg::Vec3& n) const
{
osg::Vec3 center; osg::Vec3 center;
bool center_valid = vertex(c, r, center); bool center_valid = vertex(c, r, center);
if (!center_valid) return false; if (!center_valid) return false;
@ -800,6 +847,12 @@ void GeometryTechnique::generateGeometry(BufferData& buffer, Locator* masterLoca
osg::ref_ptr<TerrainTile> top_tile = terrain->getTile(TileID(tileID.level, tileID.x, tileID.y+1)); osg::ref_ptr<TerrainTile> top_tile = terrain->getTile(TileID(tileID.level, tileID.x, tileID.y+1));
osg::ref_ptr<TerrainTile> bottom_tile = terrain->getTile(TileID(tileID.level, tileID.x, tileID.y-1)); osg::ref_ptr<TerrainTile> bottom_tile = terrain->getTile(TileID(tileID.level, tileID.x, tileID.y-1));
#if 0
osg::ref_ptr<TerrainTile> top_left_tile = terrain->getTile(TileID(tileID.level, tileID.x-1, tileID.y+1));
osg::ref_ptr<TerrainTile> top_right_tile = terrain->getTile(TileID(tileID.level, tileID.x+1, tileID.y+1));
osg::ref_ptr<TerrainTile> bottom_left_tile = terrain->getTile(TileID(tileID.level, tileID.x-1, tileID.y-1));
osg::ref_ptr<TerrainTile> bottom_right_tile = terrain->getTile(TileID(tileID.level, tileID.x+1, tileID.y-1));
#endif
VNG.populateLeftBoundary(left_tile.valid() ? left_tile->getElevationLayer() : 0); VNG.populateLeftBoundary(left_tile.valid() ? left_tile->getElevationLayer() : 0);
VNG.populateRightBoundary(right_tile.valid() ? right_tile->getElevationLayer() : 0); VNG.populateRightBoundary(right_tile.valid() ? right_tile->getElevationLayer() : 0);
VNG.populateAboveBoundary(top_tile.valid() ? top_tile->getElevationLayer() : 0); VNG.populateAboveBoundary(top_tile.valid() ? top_tile->getElevationLayer() : 0);
@ -814,6 +867,12 @@ void GeometryTechnique::generateGeometry(BufferData& buffer, Locator* masterLoca
if (top_tile.valid()) addNeighbour(top_tile.get()); if (top_tile.valid()) addNeighbour(top_tile.get());
if (bottom_tile.valid()) addNeighbour(bottom_tile.get()); if (bottom_tile.valid()) addNeighbour(bottom_tile.get());
#if 0
if (bottom_left_tile.valid()) addNeighbour(bottom_left_tile.get());
if (bottom_right_tile.valid()) addNeighbour(bottom_right_tile.get());
if (top_left_tile.valid()) addNeighbour(top_left_tile.get());
if (top_right_tile.valid()) addNeighbour(top_right_tile.get());
#endif
if (left_tile.valid()) if (left_tile.valid())
{ {
@ -843,7 +902,7 @@ void GeometryTechnique::generateGeometry(BufferData& buffer, Locator* masterLoca
} }
} }
if (bottom_tile) if (bottom_tile.valid())
{ {
if (!(bottom_tile->getTerrainTechnique()->containsNeighbour(_terrainTile))) if (!(bottom_tile->getTerrainTechnique()->containsNeighbour(_terrainTile)))
{ {
@ -852,6 +911,48 @@ void GeometryTechnique::generateGeometry(BufferData& buffer, Locator* masterLoca
else bottom_tile->setDirtyMask(dirtyMask); else bottom_tile->setDirtyMask(dirtyMask);
} }
} }
#if 0
if (bottom_left_tile.valid())
{
if (!(bottom_left_tile->getTerrainTechnique()->containsNeighbour(_terrainTile)))
{
int dirtyMask = bottom_left_tile->getDirtyMask() | TerrainTile::BOTTOM_LEFT_CORNER_DIRTY;
if (updateNeighboursImmediately) bottom_left_tile->init(dirtyMask, true);
else bottom_left_tile->setDirtyMask(dirtyMask);
}
}
if (bottom_right_tile.valid())
{
if (!(bottom_right_tile->getTerrainTechnique()->containsNeighbour(_terrainTile)))
{
int dirtyMask = bottom_right_tile->getDirtyMask() | TerrainTile::BOTTOM_RIGHT_CORNER_DIRTY;
if (updateNeighboursImmediately) bottom_right_tile->init(dirtyMask, true);
else bottom_right_tile->setDirtyMask(dirtyMask);
}
}
if (top_right_tile.valid())
{
if (!(top_right_tile->getTerrainTechnique()->containsNeighbour(_terrainTile)))
{
int dirtyMask = top_right_tile->getDirtyMask() | TerrainTile::TOP_RIGHT_CORNER_DIRTY;
if (updateNeighboursImmediately) top_right_tile->init(dirtyMask, true);
else top_right_tile->setDirtyMask(dirtyMask);
}
}
if (top_left_tile.valid())
{
if (!(top_left_tile->getTerrainTechnique()->containsNeighbour(_terrainTile)))
{
int dirtyMask = top_left_tile->getDirtyMask() | TerrainTile::TOP_LEFT_CORNER_DIRTY;
if (updateNeighboursImmediately) top_left_tile->init(dirtyMask, true);
else top_left_tile->setDirtyMask(dirtyMask);
}
}
#endif
} }
osg::ref_ptr<osg::Vec3Array> skirtVectors = new osg::Vec3Array((*VNG._normals)); osg::ref_ptr<osg::Vec3Array> skirtVectors = new osg::Vec3Array((*VNG._normals));