osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/engine_seamless/Patch.cpp

Go to the documentation of this file.
00001 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00002  * Copyright 2010 Pelican Ventures, Inc.
00003  * http://osgearth.org
00004  *
00005  * osgEarth is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU Lesser General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00017  */
00018 
00019 #include "Patch"
00020 #include "PatchSet"
00021 
00022 #include <algorithm>
00023 #include <iterator>
00024 
00025 #include <OpenThreads/Mutex>
00026 #include <OpenThreads/ScopedLock>
00027 
00028 #include <osg/Vec3d>
00029 
00030 namespace seamless
00031 {
00032 using namespace osg;
00033 
00034 class MyNodeAcceptOp : public NodeAcceptOp
00035 {
00036 public:
00037     MyNodeAcceptOp(NodeVisitor& nv) : NodeAcceptOp(nv) {}
00038     MyNodeAcceptOp(const NodeAcceptOp& naop) : NodeAcceptOp(naop) {}
00039     template<typename T>
00040     void operator()(T node) { return node->accept(_nv); }
00041 };
00042 
00043 Patch::Patch()
00044     : _errorThreshold(.5f)
00045 {
00046 }
00047 
00048 Patch::Patch(const Patch& rhs, const CopyOp& copyop)
00049     : Node(rhs, copyop), _errorThreshold(rhs._errorThreshold)
00050 {
00051     for (int res = 0; res < 2; ++res)
00052         for (int i = 0; i < 4; ++i)
00053             _trile[res][i]
00054                 = static_cast<Geode*>(copyop(rhs._trile[res][i].get()));
00055     for (int strip = 0; strip < 4; ++strip)
00056         for (int i = 0; i < 4; ++i)
00057             _strip[strip][i]
00058                 = static_cast<Geode*>(copyop(rhs._strip[strip][i].get()));
00059     _data =static_cast<Data*>(copyop(rhs._data.get()));
00060     _patchSet = static_cast<PatchSet*>(copyop(rhs._patchSet.get()));
00061 }
00062 
00063 Patch::~Patch()
00064 {
00065 }
00066 
00067 Patch::Data::Data()
00068 {
00069 }
00070 
00071 Patch::Data::Data(const Patch::Data& rhs, const osg::CopyOp& copyop)
00072     : vertexData(rhs.vertexData, copyop), normalData(rhs.normalData, copyop),
00073       colorData(rhs.colorData, copyop),
00074       secondaryColorData(rhs.secondaryColorData, copyop),
00075       fogCoordData(rhs.fogCoordData, copyop)
00076 {
00077     for (Geometry::ArrayDataList::const_iterator
00078              itr = rhs.texCoordList.begin(), end = rhs.texCoordList.end();
00079          itr !=end;
00080          ++itr)
00081         texCoordList.push_back(Geometry::ArrayData(*itr, copyop));
00082     for (Geometry::ArrayDataList::const_iterator
00083              itr = rhs.vertexAttribList.begin(),
00084              end = rhs.vertexAttribList.end();
00085          itr !=end;
00086          ++itr)
00087         vertexAttribList.push_back(Geometry::ArrayData(*itr, copyop));
00088 }
00089 
00090 void Patch::dirtyVertexData()
00091 {
00092     Geometry::ArrayData& vdata = _data->vertexData;
00093     if (vdata.array.valid())
00094         vdata.array->dirty();
00095 }
00096 
00097 void Patch::Data::getGeometryAttributes(const Geometry* geom)
00098 {
00099     vertexData = geom->getVertexData();
00100     normalData = geom->getNormalData();
00101     colorData = geom->getColorData();
00102     secondaryColorData = geom->getSecondaryColorData();
00103     fogCoordData = geom->getFogCoordData();
00104     texCoordList.clear();
00105     const Geometry::ArrayDataList& texList = geom->getTexCoordArrayList();
00106     std::copy(texList.begin(), texList.end(), std::back_inserter(texCoordList));
00107     vertexAttribList.clear();
00108     const Geometry::ArrayDataList& vaList = geom->getVertexAttribArrayList();
00109     std::copy(vaList.begin(), vaList.end(),
00110               std::back_inserter(vertexAttribList));
00111 }
00112 
00113 void Patch::Data::setGeometryAttributes(Geometry* geom)
00114 {
00115     geom->setVertexData(vertexData);
00116     geom->setNormalData(normalData);
00117     geom->setColorData(colorData);
00118     geom->setSecondaryColorData(secondaryColorData);
00119     geom->setFogCoordData(fogCoordData);
00120     const Geometry::ArrayData emptyData;
00121     unsigned numTexCoords = geom->getNumTexCoordArrays();
00122     for (unsigned i = 0; i < texCoordList.size(); ++i)
00123         geom->setTexCoordData(i, texCoordList[i]);
00124     for (unsigned i = texCoordList.size(); i < numTexCoords; ++i)
00125         geom->setTexCoordData(i, emptyData);
00126     unsigned numVertAttribs = geom->getNumVertexAttribArrays();
00127     for (unsigned i = vertexAttribList.size(); i < vertexAttribList.size(); ++i)
00128         geom->setVertexAttribData(i, vertexAttribList[i]);
00129     for (unsigned i = vertexAttribList.size(); i < numVertAttribs; ++i)
00130         geom->setVertexAttribData(i, emptyData);
00131 }
00132 
00133 void Patch::init()
00134 {
00135     for (int res = 0; res < 2; ++res)
00136     {
00137         for (int trile = 0; trile < 4; ++trile)
00138         {
00139             Geometry* geom = new Geometry;
00140             geom->setUseVertexBufferObjects(true);
00141             _data->setGeometryAttributes(geom);
00142             geom->addPrimitiveSet(_patchSet->trilePset[res][trile]);
00143             _trile[res][trile] = new Geode;
00144             _trile[res][trile]->addDrawable(geom);
00145         }
00146     }
00147     for (int j = 0; j < 4; ++j)
00148     {
00149         for (int i = 0; i < 4; ++i)
00150         {
00151             Geometry* geom = new Geometry;
00152             geom->setUseVertexBufferObjects(true);
00153             _data->setGeometryAttributes(geom);
00154             geom->addPrimitiveSet(_patchSet->stripPset[j][i]);
00155             _strip[j][i] = new Geode;
00156             _strip[j][i]->addDrawable(geom);
00157         }
00158     }
00159 }
00160 
00161 // Find the point closest to P3 on the line segment from P1 to P2
00162 Vec3 closestPointOnSegment(const Vec3& p1, const Vec3& p2, const Vec3& p3)
00163 {
00164     Vec3 vec = p2 - p1;
00165     float len2 = vec.length2();
00166     if (equivalent(len2, 0))
00167         return p1;
00168     float u = ((p3 - p1) * vec) / len2;
00169     if (u <= 0.0)
00170         return p1;
00171     else if (u >= 1.0)
00172         return p2;
00173     else
00174         return p1 + vec * u;
00175 }
00176 
00177 float distanceToSegment(const Vec3& p1, const Vec3& p2, const Vec3& p3)
00178 {
00179     Vec3 pt = closestPointOnSegment(p1, p2, p3);
00180     return (p3 - pt).length();
00181 }
00182 
00183 namespace
00184 {
00185 // Map from edge number to grid coordinates at the end points. The
00186 // values are multiplied by the patch resolution.
00187 int edgeCoords[4][2][2] = {{{0, 0}, {1, 0}},
00188                            {{1, 0}, {1, 1}},
00189                            {{1, 1}, {0, 1}},
00190                            {{0, 1}, {0,0}}};
00191 
00192 // Get the geometric coordinates of edge end points.
00193 inline void getEdge(const Patch* patch, Vec3& p1, Vec3& p2, int edgeNo)
00194 {
00195     PatchSet* ps = patch->getPatchSet();
00196     int psRes = ps->getResolution(); // patch dimension - 1
00197     int coords[2][2];
00198     for (int j = 0; j < 2; ++j)
00199         for (int i = 0; i < 2; ++i)
00200             coords[j][i] = edgeCoords[edgeNo][j][i] * psRes;
00201     Vec3Array* verts
00202         = static_cast<Vec3Array*>(patch->getData()->vertexData.array.get());
00203     p1 = (*verts)[ps->makeIndex(coords[0][0], coords[0][1])];
00204     p2 = (*verts)[ps->makeIndex(coords[1][0], coords[1][1])];
00205 }
00206 }
00207 
00208 float Patch::getEdgeError(const Vec3& eye, int edge)
00209 {
00210     Vec3 p1, p2;
00211     getEdge(this, p1, p2, edge);
00212     float len = (p2 - p1).length();
00213     Vec3 closestPt =  closestPointOnSegment(p1, p2, eye);
00214     float d = (closestPt - eye).length();
00215     return _patchSet->getPrecisionFactor() * len / d;
00216 }
00217 
00218 float Patch::getPatchError(const Vec3& eye)
00219 {
00220     float epsilon = getEdgeError(eye, 0);
00221     for (int i = 1; i < 4; ++i)
00222         epsilon = maximum(epsilon, getEdgeError(eye, i));
00223     return epsilon;
00224 }
00225 void Patch::traverse(NodeVisitor& nv)
00226 {
00227     if (!_trile[0][0].valid())
00228         return;
00229     if (nv.getTraversalMode() == NodeVisitor::TRAVERSE_ALL_CHILDREN)
00230     {
00231         std::for_each(&_trile[0][0], &_trile[1][3] + 1, MyNodeAcceptOp(nv));
00232         std::for_each(&_strip[0][0], &_strip[3][3] + 1, MyNodeAcceptOp(nv));
00233         return;
00234     }
00235     if (nv.getTraversalMode() != NodeVisitor::TRAVERSE_ACTIVE_CHILDREN)
00236         return;
00237     float epsilon[4];
00238     int res[4]; // Resolution of each edge / trile.
00239     // Get error value for edges
00240     Vec3 eye = nv.getViewPoint();
00241     for (int i = 0; i < 4; ++i)
00242     {
00243         epsilon[i] = getEdgeError(eye, i);
00244         if (epsilon[i] > _errorThreshold)
00245             res[i] = 1;
00246         else
00247             res[i] = 0;
00248     }
00249 
00250     for (int i = 0; i < 4; ++i)
00251         _trile[res[i]][i]->accept(nv);
00252     // Now choose a strip
00253     for (int i = 0; i < 4; ++i)
00254     {
00255         // One neighbor is trile i; the other is clockwise.
00256         int neighbor = (i - 1 + 4) % 4;
00257         int strip = res[neighbor] * 2 + res[i];
00258         _strip[strip][i]->accept(nv);
00259     }
00260 }
00261 
00262 BoundingSphere Patch::computeBound() const
00263 {
00264     BoundingSphere bsphere;
00265     if (!_trile[0][0].valid())
00266         return bsphere;
00267     BoundingBox bb;
00268     bb.init();
00269     for (int res = 0; res < 2; ++res)
00270         for (int i = 0; i < 4; ++i)
00271             bb.expandBy(_trile[res][i]->getBoundingBox());
00272     for (int strip = 0; strip < 4; ++strip)
00273         for (int i = 0; i < 4; ++i)
00274             bb.expandBy(_strip[strip][i]->getBoundingBox());
00275     if (!bb.valid())
00276         return bsphere;
00277     bsphere.expandBy(bb);
00278     return bsphere;
00279 }
00280 
00281 void Patch::resizeGLObjectBuffers(unsigned int maxSize)
00282 {
00283     Node::resizeGLObjectBuffers(maxSize);
00284 
00285     if (!_trile[0][0].valid())
00286         return;
00287     for (int res = 0; res < 2; ++res)
00288         for (int i = 0; i < 4; ++i)
00289             _trile[res][i]->resizeGLObjectBuffers(maxSize);
00290 }
00291 
00292 void Patch::releaseGLObjects(State* state) const
00293 {
00294     Node::releaseGLObjects(state);
00295     if (!_trile[0][0].valid())
00296         return;
00297     for (int res = 0; res < 2; ++res)
00298         for (int i = 0; i < 4; ++i)
00299             _trile[res][i]->releaseGLObjects(state);
00300 }
00301 
00302 void Patch::setPatchSet(PatchSet* patchSet)
00303 {
00304     _patchSet = patchSet;
00305 }
00306 
00307 PatchSet* Patch::getPatchSet() const
00308 {
00309     return _patchSet.get();
00310 }
00311 
00312 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines