From fccda084918683f502dc41374446f6b477198ed0 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 9 Apr 2010 08:52:40 +0000 Subject: [PATCH] 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. --- include/osgTerrain/TerrainTile | 9 ++- src/osgTerrain/GeometryTechnique.cpp | 103 ++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 3 deletions(-) diff --git a/include/osgTerrain/TerrainTile b/include/osgTerrain/TerrainTile index 973852bac..3e8d1ea99 100644 --- a/include/osgTerrain/TerrainTile +++ b/include/osgTerrain/TerrainTile @@ -179,8 +179,13 @@ class OSGTERRAIN_EXPORT TerrainTile : public osg::Group LEFT_EDGE_DIRTY = 1<<2, RIGHT_EDGE_DIRTY = 1<<3, TOP_EDGE_DIRTY = 1<<4, - BOTTOM_EDGE_DIRTY = 1<<5, - EDGES_DIRTY = LEFT_EDGE_DIRTY | RIGHT_EDGE_DIRTY | TOP_EDGE_DIRTY | BOTTOM_EDGE_DIRTY, + TOP_LEFT_CORNER_DIRTY = 1<<5, + 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 }; diff --git a/src/osgTerrain/GeometryTechnique.cpp b/src/osgTerrain/GeometryTechnique.cpp index a2c695367..6f6bab21c 100644 --- a/src/osgTerrain/GeometryTechnique.cpp +++ b/src/osgTerrain/GeometryTechnique.cpp @@ -308,6 +308,53 @@ class VertexNormalGenerator 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; bool center_valid = vertex(c, r, center); if (!center_valid) return false; @@ -800,6 +847,12 @@ void GeometryTechnique::generateGeometry(BufferData& buffer, Locator* masterLoca osg::ref_ptr top_tile = terrain->getTile(TileID(tileID.level, tileID.x, tileID.y+1)); osg::ref_ptr bottom_tile = terrain->getTile(TileID(tileID.level, tileID.x, tileID.y-1)); +#if 0 + osg::ref_ptr top_left_tile = terrain->getTile(TileID(tileID.level, tileID.x-1, tileID.y+1)); + osg::ref_ptr top_right_tile = terrain->getTile(TileID(tileID.level, tileID.x+1, tileID.y+1)); + osg::ref_ptr bottom_left_tile = terrain->getTile(TileID(tileID.level, tileID.x-1, tileID.y-1)); + osg::ref_ptr 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.populateRightBoundary(right_tile.valid() ? right_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 (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()) { @@ -843,7 +902,7 @@ void GeometryTechnique::generateGeometry(BufferData& buffer, Locator* masterLoca } } - if (bottom_tile) + if (bottom_tile.valid()) { if (!(bottom_tile->getTerrainTechnique()->containsNeighbour(_terrainTile))) { @@ -852,6 +911,48 @@ void GeometryTechnique::generateGeometry(BufferData& buffer, Locator* masterLoca 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 skirtVectors = new osg::Vec3Array((*VNG._normals));