Added support for equalizing the normals along tile boundaries.
This commit is contained in:
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 OpenThreadsWin32.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgforest.exe" /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib"
|
||||
# ADD LINK32 OpenThreadsWin32.lib opengl32.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgforest.exe" /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "Example osgforest - Win32 Debug"
|
||||
|
||||
@@ -76,7 +76,7 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 OpenThreadsWin32d.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgforestd.exe" /pdbtype:sept /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib"
|
||||
# ADD LINK32 OpenThreadsWin32d.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgforestd.exe" /pdbtype:sept /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib"
|
||||
# SUBTRACT LINK32 /incremental:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
@@ -568,6 +568,8 @@ class OSG_EXPORT HeightField : public Shape
|
||||
|
||||
Vec3 getNormal(unsigned int c,unsigned int r) const;
|
||||
|
||||
Vec2 getHeightDelta(unsigned int c,unsigned int r) const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~HeightField();
|
||||
|
||||
@@ -735,6 +735,8 @@ class OSGTERRAIN_EXPORT DataSet : public osg::Referenced
|
||||
void addRequiredResolutions(CompositeSource* sourceGraph);
|
||||
|
||||
void readFrom(CompositeSource* sourceGraph);
|
||||
|
||||
void allocateEdgeNormals();
|
||||
|
||||
void equalizeCorner(Position position);
|
||||
void equalizeEdge(Position position);
|
||||
@@ -801,6 +803,9 @@ class OSGTERRAIN_EXPORT DataSet : public osg::Referenced
|
||||
float _terrain_maxSourceResolutionY;
|
||||
|
||||
bool _complete;
|
||||
|
||||
typedef std::vector<osg::Vec2> HeightDeltaList;
|
||||
HeightDeltaList _heightDeltas[NUMBER_OF_POSITIONS];
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -37,8 +37,7 @@ void HeightField::allocate(unsigned int numColumns,unsigned int numRows)
|
||||
Vec3 HeightField::getNormal(unsigned int c,unsigned int r) const
|
||||
{
|
||||
// four point normal generation.
|
||||
|
||||
float dz_dx;
|
||||
float dz_dx;
|
||||
if (c==0)
|
||||
{
|
||||
dz_dx = (getHeight(c+1,r)-getHeight(c,r))/getXInterval();
|
||||
@@ -72,4 +71,37 @@ Vec3 HeightField::getNormal(unsigned int c,unsigned int r) const
|
||||
return normal;
|
||||
}
|
||||
|
||||
Vec2 HeightField::getHeightDelta(unsigned int c,unsigned int r) const
|
||||
{
|
||||
// four point normal generation.
|
||||
Vec2 heightDelta;
|
||||
if (c==0)
|
||||
{
|
||||
heightDelta.x() = (getHeight(c+1,r)-getHeight(c,r));
|
||||
}
|
||||
else if (c==getNumColumns()-1)
|
||||
{
|
||||
heightDelta.x() = (getHeight(c,r)-getHeight(c-1,r));
|
||||
}
|
||||
else // assume 0<c<_numColumns-1
|
||||
{
|
||||
heightDelta.x() = 0.5f*(getHeight(c+1,r)-getHeight(c-1,r));
|
||||
}
|
||||
|
||||
if (r==0)
|
||||
{
|
||||
heightDelta.y() = (getHeight(c,r+1)-getHeight(c,r));
|
||||
}
|
||||
else if (r==getNumRows()-1)
|
||||
{
|
||||
heightDelta.y() = (getHeight(c,r)-getHeight(c,r-1));
|
||||
}
|
||||
else // assume 0<r<_numRows-1
|
||||
{
|
||||
heightDelta.y() = 0.5f*(getHeight(c,r+1)-getHeight(c,r-1));
|
||||
}
|
||||
|
||||
return heightDelta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -163,8 +163,6 @@ void UFOManipulator::init(const GUIEventAdapter&, GUIActionAdapter&)
|
||||
{
|
||||
//home(ea.time());
|
||||
|
||||
puts( "INIT" ) ;
|
||||
|
||||
_stop();
|
||||
}
|
||||
|
||||
|
||||
@@ -1602,6 +1602,14 @@ void DataSet::DestinationTile::checkNeighbouringTiles()
|
||||
}
|
||||
}
|
||||
|
||||
void DataSet::DestinationTile::allocateEdgeNormals()
|
||||
{
|
||||
osg::HeightField* hf = _terrain->_heightField.get();
|
||||
if (!hf) return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DataSet::DestinationTile::equalizeCorner(Position position)
|
||||
{
|
||||
// don't need to equalize if already done.
|
||||
@@ -1735,7 +1743,7 @@ void DataSet::DestinationTile::equalizeCorner(Position position)
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::pair<osg::HeightField*,Position> HeightFieldCornerPair;
|
||||
typedef std::pair<osg::HeightField*,TileCornerPair> HeightFieldCornerPair;
|
||||
typedef std::vector<HeightFieldCornerPair> HeightFieldCornerList;
|
||||
HeightFieldCornerList heightFieldsToProcess;
|
||||
|
||||
@@ -1746,7 +1754,7 @@ void DataSet::DestinationTile::equalizeCorner(Position position)
|
||||
TileCornerPair& tcp = *itr;
|
||||
if (tcp.first->_terrain.valid() && tcp.first->_terrain->_heightField.valid())
|
||||
{
|
||||
heightFieldsToProcess.push_back(HeightFieldCornerPair(tcp.first->_terrain->_heightField.get(),tcp.second));
|
||||
heightFieldsToProcess.push_back(HeightFieldCornerPair(tcp.first->_terrain->_heightField.get(),tcp));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1754,26 +1762,31 @@ void DataSet::DestinationTile::equalizeCorner(Position position)
|
||||
if (heightFieldsToProcess.size()>1)
|
||||
{
|
||||
float height = 0;
|
||||
// accumulate heights.
|
||||
osg::Vec2 heightDelta;
|
||||
// accumulate heights & normals
|
||||
HeightFieldCornerList::iterator hitr;
|
||||
for(hitr=heightFieldsToProcess.begin();
|
||||
hitr!=heightFieldsToProcess.end();
|
||||
++hitr)
|
||||
{
|
||||
HeightFieldCornerPair& hfcp = *hitr;
|
||||
switch(hfcp.second)
|
||||
switch(hfcp.second.second)
|
||||
{
|
||||
case LEFT_BELOW:
|
||||
height += hfcp.first->getHeight(0,0);
|
||||
heightDelta += hfcp.first->getHeightDelta(0,0);
|
||||
break;
|
||||
case BELOW_RIGHT:
|
||||
height += hfcp.first->getHeight(hfcp.first->getNumColumns()-1,0);
|
||||
heightDelta += hfcp.first->getHeightDelta(hfcp.first->getNumColumns()-1,0);
|
||||
break;
|
||||
case RIGHT_ABOVE:
|
||||
height += hfcp.first->getHeight(hfcp.first->getNumColumns()-1,hfcp.first->getNumRows()-1);
|
||||
heightDelta += hfcp.first->getHeightDelta(hfcp.first->getNumColumns()-1,hfcp.first->getNumRows()-1);
|
||||
break;
|
||||
case ABOVE_LEFT:
|
||||
height += hfcp.first->getHeight(0,hfcp.first->getNumRows()-1);
|
||||
heightDelta += hfcp.first->getHeightDelta(0,hfcp.first->getNumRows()-1);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
@@ -1782,14 +1795,17 @@ void DataSet::DestinationTile::equalizeCorner(Position position)
|
||||
|
||||
// divide them.
|
||||
height /= heightFieldsToProcess.size();
|
||||
heightDelta /= heightFieldsToProcess.size();
|
||||
|
||||
// apply height to corners.
|
||||
|
||||
// apply height and normals to corners.
|
||||
for(hitr=heightFieldsToProcess.begin();
|
||||
hitr!=heightFieldsToProcess.end();
|
||||
++hitr)
|
||||
{
|
||||
HeightFieldCornerPair& hfcp = *hitr;
|
||||
switch(hfcp.second)
|
||||
TileCornerPair& tcp = hfcp.second;
|
||||
switch(tcp.second)
|
||||
{
|
||||
case LEFT_BELOW:
|
||||
hfcp.first->setHeight(0,0,height);
|
||||
@@ -1806,6 +1822,8 @@ void DataSet::DestinationTile::equalizeCorner(Position position)
|
||||
default :
|
||||
break;
|
||||
}
|
||||
tcp.first->_heightDeltas[tcp.second].clear();
|
||||
tcp.first->_heightDeltas[tcp.second].push_back(heightDelta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1967,30 +1985,68 @@ void DataSet::DestinationTile::equalizeEdge(Position position)
|
||||
unsigned int delta2 = 0;
|
||||
int num = 0;
|
||||
|
||||
unsigned int i1 = 0;
|
||||
unsigned int j1 = 0;
|
||||
unsigned int i2 = 0;
|
||||
unsigned int j2 = 0;
|
||||
unsigned int deltai = 0;
|
||||
unsigned int deltaj = 0;
|
||||
|
||||
switch(position)
|
||||
{
|
||||
case LEFT:
|
||||
i1 = 0;
|
||||
j1 = 1;
|
||||
i2 = heightField2->getNumColumns()-1;
|
||||
j2 = 1;
|
||||
deltai = 0;
|
||||
deltaj = 1;
|
||||
|
||||
data1 = &(heightField1->getHeight(0,1)); // LEFT hand side
|
||||
delta1 = heightField1->getNumColumns();
|
||||
data2 = &(heightField2->getHeight(heightField2->getNumColumns()-1,1)); // RIGHT hand side
|
||||
delta2 = heightField2->getNumColumns();
|
||||
num = (heightField1->getNumRows()==heightField2->getNumRows())?heightField1->getNumRows()-2:0; // note miss out corners.
|
||||
break;
|
||||
|
||||
case BELOW:
|
||||
i1 = 1;
|
||||
j1 = 0;
|
||||
i2 = 1;
|
||||
j2 = heightField2->getNumRows()-1;
|
||||
deltai = 1;
|
||||
deltaj = 0;
|
||||
|
||||
data1 = &(heightField1->getHeight(1,0)); // BELOW hand side
|
||||
delta1 = 1;
|
||||
data2 = &(heightField2->getHeight(1,heightField2->getNumRows()-1)); // ABOVE hand side
|
||||
delta2 = 1;
|
||||
num = (heightField1->getNumColumns()==heightField2->getNumColumns())?heightField1->getNumColumns()-2:0; // note miss out corners.
|
||||
break;
|
||||
|
||||
case RIGHT:
|
||||
i1 = heightField1->getNumColumns()-1;
|
||||
j1 = 1;
|
||||
i2 = 0;
|
||||
j2 = 1;
|
||||
deltai = 0;
|
||||
deltaj = 1;
|
||||
|
||||
data1 = &(heightField1->getHeight(heightField1->getNumColumns()-1,1)); // LEFT hand side
|
||||
delta1 = heightField1->getNumColumns();
|
||||
data2 = &(heightField2->getHeight(0,1)); // LEFT hand side
|
||||
delta2 = heightField2->getNumColumns();
|
||||
num = (heightField1->getNumRows()==heightField2->getNumRows())?heightField1->getNumRows()-2:0; // note miss out corners.
|
||||
break;
|
||||
|
||||
case ABOVE:
|
||||
i1 = 1;
|
||||
j1 = heightField1->getNumRows()-1;
|
||||
i2 = 1;
|
||||
j2 = 0;
|
||||
deltai = 1;
|
||||
deltaj = 0;
|
||||
|
||||
data1 = &(heightField1->getHeight(1,heightField1->getNumRows()-1)); // ABOVE hand side
|
||||
delta1 = 1;
|
||||
data2 = &(heightField2->getHeight(1,0)); // BELOW hand side
|
||||
@@ -2000,20 +2056,41 @@ void DataSet::DestinationTile::equalizeEdge(Position position)
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
_heightDeltas[position].clear();
|
||||
_heightDeltas[position].reserve(num);
|
||||
tile2->_heightDeltas[(position+4)%NUMBER_OF_POSITIONS].clear();
|
||||
tile2->_heightDeltas[(position+4)%NUMBER_OF_POSITIONS].reserve(num);
|
||||
|
||||
for(int i=0;i<num;++i)
|
||||
{
|
||||
// equalize height
|
||||
float z = (*data1 + *data2)/2.0f;
|
||||
|
||||
//my_notify(osg::INFO)<<" equalizing height"<<std::endl;
|
||||
|
||||
*data1 = z;
|
||||
*data2 = z;
|
||||
|
||||
data1 += delta1;
|
||||
data2 += delta2;
|
||||
|
||||
// equailize normals
|
||||
osg::Vec2 heightDelta = (heightField1->getHeightDelta(i1,j1) +
|
||||
heightField2->getHeightDelta(i2,j2))*0.5f;
|
||||
|
||||
// pass the normals on to the tiles.
|
||||
_heightDeltas[position].push_back(heightDelta);
|
||||
tile2->_heightDeltas[(position+4)%NUMBER_OF_POSITIONS].push_back(heightDelta);
|
||||
|
||||
i1 += deltai;
|
||||
i2 += deltai;
|
||||
j1 += deltaj;
|
||||
j2 += deltaj;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2486,9 +2563,7 @@ osg::Node* DataSet::DestinationTile::createPolygonal()
|
||||
{
|
||||
skirtVector.set(0.0f,0.0f,-skirtLength);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned int vi=0;
|
||||
unsigned int r,c;
|
||||
|
||||
@@ -2556,7 +2631,11 @@ osg::Node* DataSet::DestinationTile::createPolygonal()
|
||||
}
|
||||
|
||||
// note normal will need rotating.
|
||||
if (n.valid()) (*(n.get()))[vi] = grid->getNormal(c,r);
|
||||
if (n.valid())
|
||||
{
|
||||
(*n)[vi] = grid->getNormal(c,r);
|
||||
|
||||
}
|
||||
|
||||
t[vi].x() = (c==numColumns-1)? 1.0f : (float)(c)/(float)(numColumns-1);
|
||||
t[vi].y() = (r==numRows-1)? 1.0f : (float)(r)/(float)(numRows-1);
|
||||
@@ -2643,7 +2722,7 @@ osg::Node* DataSet::DestinationTile::createPolygonal()
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
#if 1
|
||||
osgUtil::SmoothingVisitor sv;
|
||||
sv.smooth(*geometry); // this will replace the normal vector with a new one
|
||||
|
||||
@@ -2651,7 +2730,144 @@ osg::Node* DataSet::DestinationTile::createPolygonal()
|
||||
n = geometry->getNormalArray();
|
||||
if (n.valid() && n->size()!=numVertices) n->resize(numVertices);
|
||||
#endif
|
||||
// now apply the normals computed through equalization
|
||||
for(unsigned int position=0; position<NUMBER_OF_POSITIONS; ++position)
|
||||
{
|
||||
if (!_heightDeltas[position].empty())
|
||||
{
|
||||
// we have normal to apply
|
||||
unsigned int i=0;
|
||||
unsigned int j=0;
|
||||
unsigned int deltai=0;
|
||||
unsigned int deltaj=0;
|
||||
switch(position)
|
||||
{
|
||||
case LEFT:
|
||||
i = 0;
|
||||
j = 1;
|
||||
deltai = 0;
|
||||
deltaj = 1;
|
||||
break;
|
||||
case LEFT_BELOW:
|
||||
i = 0;
|
||||
j = 0;
|
||||
deltai = 0;
|
||||
deltaj = 0;
|
||||
break;
|
||||
case BELOW:
|
||||
i = 1;
|
||||
j = 0;
|
||||
deltai = 1;
|
||||
deltaj = 0;
|
||||
break;
|
||||
case BELOW_RIGHT:
|
||||
i = numColumns-1;
|
||||
j = 0;
|
||||
deltai = 0;
|
||||
deltaj = 0;
|
||||
break;
|
||||
case RIGHT:
|
||||
i = numColumns-1;
|
||||
j = 1;
|
||||
deltai = 0;
|
||||
deltaj = 1;
|
||||
break;
|
||||
case RIGHT_ABOVE:
|
||||
i = numColumns-1;
|
||||
j = numRows-1;
|
||||
deltai = 0;
|
||||
deltaj = 0;
|
||||
break;
|
||||
case ABOVE:
|
||||
i = 1;
|
||||
j = numRows-1;
|
||||
deltai = 1;
|
||||
deltaj = 0;
|
||||
break;
|
||||
case ABOVE_LEFT:
|
||||
i = 0;
|
||||
j = numRows-1;
|
||||
deltai = 0;
|
||||
deltaj = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// need to reproject normals.
|
||||
for(HeightDeltaList::iterator itr = _heightDeltas[position].begin();
|
||||
itr != _heightDeltas[position].end();
|
||||
++itr, i += deltai, j += deltaj)
|
||||
{
|
||||
osg::Vec3& normal = (*n)[i + j*numColumns];
|
||||
osg::Vec2 heightDelta = *itr;
|
||||
|
||||
if (mapLatLongsToXYZ)
|
||||
{
|
||||
|
||||
double X = orig_X + delta_X*(double)i;
|
||||
double Y = orig_Y + delta_Y*(double)j;
|
||||
double Z = orig_Z + grid->getHeight(i,j);
|
||||
osg::Matrixd normalLocalToWorld;
|
||||
et->computeLocalToWorldTransformFromLatLongHeight(osg::DegreesToRadians(Y),osg::DegreesToRadians(X),Z,normalLocalToWorld);
|
||||
osg::Matrixd normalToLocalReferenceFrame(normalLocalToWorld*worldToLocal);
|
||||
|
||||
// need to compute the x and y delta for this point in space.
|
||||
double X0, Y0, Z0;
|
||||
double X1, Y1, Z1;
|
||||
double X2, Y2, Z2;
|
||||
|
||||
et->convertLatLongHeightToXYZ(osg::DegreesToRadians(Y),osg::DegreesToRadians(X),Z,
|
||||
X0,Y0,Z0);
|
||||
|
||||
et->convertLatLongHeightToXYZ(osg::DegreesToRadians(Y),osg::DegreesToRadians(X+delta_X),Z,
|
||||
X1,Y1,Z1);
|
||||
|
||||
et->convertLatLongHeightToXYZ(osg::DegreesToRadians(Y+delta_Y),osg::DegreesToRadians(X),Z,
|
||||
X2,Y2,Z2);
|
||||
|
||||
X1 -= X0;
|
||||
Y1 -= Y0;
|
||||
Z1 -= Z0;
|
||||
|
||||
X2 -= X0;
|
||||
Y2 -= Y0;
|
||||
Z2 -= Z0;
|
||||
|
||||
float xInterval = sqrt(X1*X1 + Y1*Y1 + Z1*Z1);
|
||||
float yInterval = sqrt(X2*X2 + Y2*Y2 + Z2*Z2);
|
||||
|
||||
// need to set up the normal from the scaled heightDelta.
|
||||
normal.x() = -heightDelta.x() / xInterval;
|
||||
normal.y() = -heightDelta.y() / yInterval;
|
||||
normal.z() = 1.0f;
|
||||
|
||||
normal = osg::Matrixd::transform3x3(normal,normalToLocalReferenceFrame);
|
||||
normal.normalize();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
normal.x() = -heightDelta.x() / grid->getXInterval();
|
||||
normal.y() = -heightDelta.y() / grid->getYInterval();
|
||||
normal.z() = 1.0f;
|
||||
normal.normalize();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::cout<<"Normals"<<std::endl;
|
||||
for(osg::Vec3Array::iterator nitr = n->begin();
|
||||
nitr != n->end();
|
||||
++nitr)
|
||||
{
|
||||
osg::Vec3& normal = *nitr;
|
||||
std::cout<<" Local normal = "<<normal<< " vs "<<transformed_center_normal<<std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (useClusterCullingCallback)
|
||||
{
|
||||
@@ -2791,13 +3007,14 @@ osg::Node* DataSet::DestinationTile::createPolygonal()
|
||||
osgDB::writeNodeFile(*geode,"NodeBeforeSimplification.osg");
|
||||
}
|
||||
|
||||
#if 1
|
||||
unsigned int targetMaxNumVertices = 2048;
|
||||
float sample_ratio = (numVertices <= targetMaxNumVertices) ? 1.0f : (float)targetMaxNumVertices/(float)numVertices;
|
||||
|
||||
osgUtil::Simplifier simplifier(sample_ratio,geometry->getBound().radius()/2000.0f);
|
||||
|
||||
simplifier.simplify(*geometry, pointsToProtectDuringSimplification); // this will replace the normal vector with a new one
|
||||
|
||||
#endif
|
||||
|
||||
osgUtil::TriStripVisitor tsv;
|
||||
tsv.setMinStripSize(3);
|
||||
|
||||
Reference in New Issue
Block a user