Geometry Functions
[Geometry]


Classes

struct  IndexDic
class  VolumeDrawWrapper

Draw Functions



void osg::drawVolume (const DynamicVolume &volume)
void osg::drawVolume (const BoxVolume &volume)
void osg::drawVolume (const SphereVolume &volume)
void osg::drawVolume (const FrustumVolume &volume)
void osg::drawVolume (const CylinderVolume &volume)
void osg::dropVolume (DrawActionBase *action, NodePtr node, Color3f col)
void osg::dropVolume (DrawActionBase *action, const DynamicVolume &volume, Color3f col)

Functions

void osg::calcVertexNormals (GeometryPtr geo)
void osg::calcVertexNormals (GeometryPtr geo, Real32 creaseAngle)
void osg::calcFaceNormals (GeometryPtr geo)
Int32 osg::setIndexFromVRMLData (GeometryPtr geoPtr, std::vector< Int32 > &coordIndex, std::vector< Int32 > &normalIndex, std::vector< Int32 > &colorIndex, std::vector< Int32 > &texCoordIndex, bool convex, bool ccw, bool normalPerVertex, bool colorPerVertex, bool createNormal, bool faceSet)
Int32 osg::setIndexFromIndexedX3DData (GeometryPtr geoPtr, std::vector< Int32 > &coordIndex, std::vector< Int32 > &normalIndex, std::vector< Int32 > &colorIndex, std::vector< Int32 > &texCoordIndex, Int32 primitiveType, bool convex, bool ccw, bool normalPerVertex, bool colorPerVertex, bool createNormal)
void osg::calcVertexTexCoords (GeometryPtr geo, Int32 texIndex)
void osg::calcVertexTangents (GeometryPtr geo, Int32 srcTexIndex, Int32 dstAttribTan, Int32 dstAttribBin)
Int32 osg::createOptimizedPrimitives (GeometryPtr geoPtr, UInt32 iteration, bool createStrips, bool createFans, UInt32 minFanEdgeCount, bool colorCode, bool stitchStrips)
void osg::createConvexPrimitives (GeometryPtr geoPtr)
Int32 osg::createSharedIndex (GeometryPtr geoPtr)
Int32 osg::createSingleIndex (GeometryPtr geoPtr)
UInt32 osg::calcPrimitiveCount (GeometryPtr geoPtr, UInt32 &triangle, UInt32 &line, UInt32 &point)
NodePtr osg::calcVertexNormalsGeo (GeometryPtr geo, Real32 length)
NodePtr osg::calcFaceNormalsGeo (GeometryPtr geo, Real32 length)
void osg::separateProperties (GeometryPtr geo)

Detailed Description

The GeoFunctions group contains different different functions to manipulate geometry. See Helper Functions for a description.

Function Documentation

void osg::calcVertexNormals ( GeometryPtr  geo  ) 

calcVertexNormals calculates the normals for the geometry's vertices, see Normal Calculation for a description.

Definition at line 78 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::GeoProperty< GeoPropertyDesc >::create(), osg::endEditCP(), osg::Plane::getNormal(), osg::Geometry::MapNormal, osg::Geometry::MapPosition, osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize(), osg::NullFC, p, and osg::MField< FieldTypeT, fieldNameSpace >::size().

Referenced by osg::calcVertexNormals(), osg::OFFSceneFileType::read(), and osg::OBJSceneFileType::read().

00083 {
00084   //Vec3f vec0, vec1,vec2;
00085   GeoPositionsPtr positionPtr;
00086   GeoNormalsPtr   normalPtr;
00087   Int32 i, ni, pi, pN, p0, p1, p2, skipN = 0;
00088   TriangleIterator tI;
00089   Real32 x,y,z;
00090   std::vector<Vec3f> normalVec;
00091 
00092   if (geo != NullFC) {
00093 
00094     // get the pos bag and pos count
00095     positionPtr = geo->getPositions();
00096     pN = (positionPtr != NullFC) ? positionPtr->getSize() : 0;
00097 
00098     FNOTICE (("Create %d normal \n", pN ));
00099 
00100     if (pN) {
00101 
00102       // init the normal bag
00103       normalVec.resize(pN);
00104       for (i = 0; i < pN; ++i)
00105         normalVec[i].setValues(0,0,0);
00106 
00107       // fill the normal bag
00108       for (tI = geo->beginTriangles(); tI != geo->endTriangles(); ++tI) {
00109 
00110         if ((p0 == p1) || (p1 == p2) || (p2 == p0)) {
00111           skipN++;
00112         }
00113         else {
00114 
00115           // get the tri points
00116           p0 = tI.getPositionIndex(0);
00117           p1 = tI.getPositionIndex(1);
00118           p2 = tI.getPositionIndex(2);
00119           // get the points
00120           // TODO; use assign
00121           Vec3f vec0(tI.getPosition(0));
00122           Vec3f vec1(tI.getPosition(1));
00123           Vec3f vec2(tI.getPosition(2));
00124 
00125           // calc the face normal
00126           vec0 -= vec1;
00127           vec1 -= vec2;
00128           vec0.crossThis(vec1);
00129           vec0.normalize();
00130 
00131           // add the normal
00132           normalVec[p0] += vec0;
00133           normalVec[p1] += vec0;
00134           normalVec[p2] += vec0;
00135         }
00136       }
00137 
00138       // get/create/resize the normal bag
00139       normalPtr = geo->getNormals();
00140       if (normalPtr == NullFC) {
00141         normalPtr = GeoNormals3f::create();
00142         beginEditCP(geo);
00143         {
00144           geo->setNormals( normalPtr );
00145         }
00146         endEditCP(geo);
00147       }
00148 
00149       // get/create/resize the normal bag
00150       normalPtr = geo->getNormals();
00151       if (normalPtr == NullFC) {
00152         normalPtr = GeoNormals3f::create();
00153         beginEditCP(geo);
00154         {
00155           geo->setNormals( normalPtr );
00156         }
00157         endEditCP(geo);
00158       }
00159 
00160       // normalize and copy the result
00161       beginEditCP (normalPtr);
00162       {
00163         // resize the bag
00164         normalPtr->resize(pN);
00165 
00166         // normalize and copy the result
00167         for (i = 0; i < pN; ++i) {
00168           if (normalize)
00169             normalVec[i].normalize();
00170           normalPtr->setValue( normalVec[i], i );
00171         }
00172       }
00173       endEditCP (normalPtr);
00174 
00175       // adapting the indexMapping
00176       pi = geo->calcMappingIndex ( Geometry::MapPosition );
00177       ni = geo->calcMappingIndex ( Geometry::MapNormal   );
00178       if ((geo->getIndexMapping().size() > 1) && (pi >= 0) && (pi != ni)) {
00179 
00180         geo->getIndexMapping(ni) &= ~Geometry::MapNormal;
00181         if (geo->getIndexMapping(ni) == 0) {
00182           FFATAL (("Should delete normal entry; do impl !!!\n" ));
00183           geo->getIndexMapping(ni) = Geometry::MapEmpty;
00184         }
00185         else {
00186           FNOTICE (("Keep mindex mapping after createVertexNormal()\n"));
00187         }
00188 
00189         geo->getIndexMapping(pi) |= Geometry::MapNormal;
00190       }
00191       else {
00192         FNOTICE (("Keep single index mapping after createVertexNormal()\n"));
00193       }
00194     }
00195     else {
00196       FFATAL (("No valid points setting; can not create normal\n"));
00197     }
00198     if (skipN) {
00199       FNOTICE (( "Skip %d invalid triangles in createVertexNormal()\n",
00200                  skipN));
00201     }
00202   }
00203   else {
00204     FFATAL (("No valid geometry; can not create normal\n"));
00205   }
00206 
00207 }
00208 
00209 */
00210 {
00211     GeoNormalsPtr   norms;
00212     typedef std::set<UInt32> IndexSet;
00213     IndexSet used_indices;
00214 
00215     if(geo->getNormals() == NullFC)
00216     {
00217         norms = GeoNormals3f::create();
00218     }
00219     else
00220     {
00221         norms = geo->getNormals();
00222     }
00223     beginEditCP(norms);
00224 
00225     norms->resize(geo->getPositions()->getSize());
00226 
00227     // problem: not all of the points of the property might be used by this
00228     // geometry. If the property has more than 1 users, be careful.
00229     if(norms->getParents().size() > 1)
00230     {
00231         for(TriangleIterator t = geo->beginTriangles(); t != geo->endTriangles();
00232                     ++t)
00233         {
00234             used_indices.insert(t.getPositionIndex(0));
00235             used_indices.insert(t.getPositionIndex(1));
00236             used_indices.insert(t.getPositionIndex(2));
00237         }
00238 
00239         for (IndexSet::iterator i = used_indices.begin();
00240              i != used_indices.end();
00241              ++i)
00242         {
00243             norms->setValue(Vec3f(0, 0, 0), *i);
00244         }
00245     }
00246     else            // just one user, can clear all
00247     {
00248         for(unsigned i = 0; i < geo->getPositions()->getSize(); i++)
00249         {
00250             norms->setValue(Vec3f(0, 0, 0), i);
00251         }
00252     }
00253 
00254     for(TriangleIterator t = geo->beginTriangles(); t != geo->endTriangles();
00255             ++t)
00256     {
00257         Pnt3f p0 = t.getPosition(0);
00258         Pnt3f p1 = t.getPosition(1);
00259         Pnt3f p2 = t.getPosition(2);
00260         Plane p(p0, p1, p2);
00261 
00262         Int32 i0 = t.getPositionIndex(0);
00263         Int32 i1 = t.getPositionIndex(1);
00264         Int32 i2 = t.getPositionIndex(2);
00265         norms->setValue( norms->getValue(i0) + p.getNormal(), i0 );
00266         norms->setValue( norms->getValue(i1) + p.getNormal(), i1 );
00267         norms->setValue( norms->getValue(i2) + p.getNormal(), i2 );
00268     }
00269     if(norms->getParents().size() > 1)
00270     {
00271         std::set < UInt32 >::iterator i = used_indices.begin();
00272         std::set < UInt32 >::iterator end = used_indices.end();
00273 
00274         while(i != end)
00275         {
00276             Vec3f   n = norms->getValue(*i);
00277             n.normalize();
00278             norms->setValue(n, *i);
00279 
00280             ++i;
00281         }
00282     }
00283     else            // just one user, can clear all
00284     {
00285         for(unsigned i = 0; i < geo->getPositions()->getSize(); i++)
00286         {
00287             Vec3f   n = norms->getValue(i);
00288             n.normalize();
00289             norms->setValue(n, i);
00290         }
00291     }
00292     endEditCP(norms);
00293 
00294     beginEditCP(geo);
00295     {
00296         geo->setNormals(norms);
00297 
00298         MFUInt16    &im = geo->getIndexMapping();
00299         if(im.size() > 0)
00300         {
00301             Int16   pi, ni;
00302             pi = geo->calcMappingIndex(Geometry::MapPosition);
00303             ni = geo->calcMappingIndex(Geometry::MapNormal);
00304 
00305             if(ni >= 0)
00306             {
00307                 im[ni] = im[ni] &~Geometry::MapNormal;
00308             }
00309             if(pi >= 0)
00310             {
00311                 im[pi] = im[pi] | Geometry::MapNormal;
00312             }
00313         }
00314     }
00315     endEditCP(geo);
00316 }

void osg::calcVertexNormals ( GeometryPtr  geo,
Real32  creaseAngle 
)

calcVertexNormals calculates the normals for the geometry's vertices, see Normal Calculation for a description.

Definition at line 385 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::calcVertexNormals(), osg::GeoProperty< GeoPropertyDesc >::create(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::crossThis(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::dot(), osg::endEditCP(), FINFO, FWARNING, osg::TriangleIterator::getIndex(), osg::TriangleIterator::getIndexIndex(), osg::TriangleIterator::getNormalIndex(), osg::TriangleIterator::getPosition(), osg::TriangleIterator::getPositionIndex(), osg::Geometry::MapColor, osg::Geometry::MapNormal, osg::Geometry::MapPosition, osg::Geometry::MapTexCoords, osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize(), osg::NullFC, osg::osgcos(), p, osg::Pi, osg::MField< FieldTypeT, fieldNameSpace >::push_back(), osg::MField< FieldTypeT, fieldNameSpace >::size(), and osg::VectorInterface< ValueTypeT, StorageInterfaceT >::squareLength().

Referenced by osg::VRMLGeometryPointSetDesc::endNode(), and osg::VRMLGeometryDesc::endNode().

00387 {
00388     GeoNormalsPtr   norms;
00389     GeoPositionsPtr positions;
00390 
00391     if(creaseAngle >= Pi)
00392     {
00393         calcVertexNormals(geo);
00394         return;
00395     }
00396 
00397     // Get the positions property
00398     if(geo->getPositions() == NullFC)
00399     {
00400         FINFO(("Geo without positions in calcVertexNormals()\n"));
00401         return;
00402     }
00403     else
00404     {
00405         positions = geo->getPositions();
00406     }
00407 
00408     if(positions->size() < 3)
00409     {
00410         FINFO(("Geo with less than 3 positions in calcVertexNormals()\n"));
00411         return;
00412     }
00413 
00414     // Get normal property, create if needed
00415     if(geo->getNormals() == NullFC)
00416     {
00417         norms = GeoNormals3f::create();
00418     }
00419     else
00420     {
00421         norms = geo->getNormals();
00422     }
00423 
00424     // need to set it early, is used below
00425     beginEditCP(geo);
00426     {
00427         geo->setNormals(norms);
00428     }
00429 
00430     endEditCP(geo);
00431 
00432     // Do the normals have their own index?
00433     MFUInt16        &im = geo->getIndexMapping();
00434     Int16           ni = geo->calcMappingIndex(Geometry::MapNormal);
00435     GeoIndicesPtr   ip = geo->getIndices();
00436     
00437     // HACK but without indices it crashes.
00438     if(ip == NullFC || ip->size() == 0)
00439     {
00440         FINFO(("Geo without indices in calcVertexNormals()\n"));
00441         return;
00442     }
00443 
00444     UInt32          nind = ip->size() / (im.size() ? im.size() : 1);
00445     int             imsize = 0;
00446     if(ni < 0 || im[ni] != Geometry::MapNormal)
00447     {
00448         // normals need their own index
00449         if(ni >= 0)
00450         {
00451             im[ni] = im[ni] &~Geometry::MapNormal;
00452         }
00453 
00454         // need to be multi-indexed?
00455         if(im.size() == 0)
00456         {
00457             UInt32  map = Geometry::MapPosition;
00458 
00459             if(geo->getTexCoords() != NullFC)
00460                 map |= Geometry::MapTexCoords;
00461 
00462             if(geo->getColors() != NullFC)
00463                 map |= Geometry::MapColor;
00464 
00465             im.push_back(map);
00466         }
00467 
00468         ni = im.size();
00469         im.push_back(Geometry::MapNormal);
00470 
00471         // add an entry to the indices for the normals
00472         imsize = im.size();
00473 
00474         beginEditCP(ip);
00475         ip->resize(nind * imsize);
00476 
00477         for(UInt32 i = nind - 1; i > 0; --i)
00478         {
00479             for(Int16 j = imsize - 2; j >= 0; --j)
00480             {
00481                 UInt32  val;
00482                 ip->getValue(val, i * (imsize - 1) + j);
00483                 ip->setValue(val, i * imsize + j);
00484             }
00485 
00486             ip->setValue(i, i * imsize + imsize - 1);
00487         }
00488 
00489         ip->setValue(0, imsize - 1);
00490         endEditCP(ip);
00491     }
00492     else            // set the normal indices
00493     {
00494         imsize = im.size();
00495         beginEditCP(ip);
00496         for(UInt32 i = 0; i < nind; ++i)
00497         {
00498             ip->setValue(i, i * imsize + ni);
00499         }
00500 
00501         endEditCP(ip);
00502     }
00503 
00504     // now calc the normals
00505     // if creaseAngle is 0, it's simple: every face uses its own.
00506     if(creaseAngle == 0)
00507     {
00508         beginEditCP(norms);
00509         beginEditCP(ip);
00510 
00511         norms->resize(nind);
00512 
00513         for(TriangleIterator ti = geo->beginTriangles();
00514                     ti != geo->endTriangles(); ++ti)
00515         {
00516             Vec3f   d1 = ti.getPosition(1) - ti.getPosition(0);
00517             Vec3f   d2 = ti.getPosition(2) - ti.getPosition(0);
00518             d1.crossThis(d2);
00519 
00520             d1.normalize();
00521 
00522             norms->setValue(d1, ti.getNormalIndex(0));
00523             norms->setValue(d1, ti.getNormalIndex(1));
00524             norms->setValue(d1, ti.getNormalIndex(2));
00525         }
00526 
00527         endEditCP(norms);
00528         endEditCP(ip);
00529         return;
00530     }
00531 
00532     // creaseAngle > 0, need to calculate
00533 #if 0
00534     // orig pngMap based code (written by dirk)
00535     // collect a map from points to faces using this point
00536     // collect the face normals in a separate vector
00537     std::vector < Vec3f > faceNormals;
00538     std::multimap<Pnt3f, UInt32, vecless<Pnt3f> > pntMap;
00539 
00540     TriangleIterator    ti;
00541 
00542     for(ti = geo->beginTriangles(); ti != geo->endTriangles(); ++ti)
00543     {
00544         Vec3f   d1 = ti.getPosition(1) - ti.getPosition(0);
00545         Vec3f   d2 = ti.getPosition(2) - ti.getPosition(0);
00546         d1.crossThis(d2);
00547 
00548         d1.normalize();
00549         faceNormals.push_back(d1);
00550 
00551         pntMap.insert(std::pair< Pnt3f, UInt32 > 
00552                         (ti.getPosition(0), faceNormals.size() - 1));
00553         pntMap.insert(std::pair< Pnt3f, UInt32 > 
00554                         (ti.getPosition(1), faceNormals.size() - 1));
00555         pntMap.insert(std::pair< Pnt3f, UInt32 > 
00556                         (ti.getPosition(2), faceNormals.size() - 1));
00557     }
00558 
00559     // now walk through the geometry again and calc the normals
00560     beginEditCP(norms);
00561     beginEditCP(ip);
00562 
00563     norms->resize(nind);
00564 
00565     Real32  cosCrease = osgcos(creaseAngle);
00566 
00567     for(ti = geo->beginTriangles(); ti != geo->endTriangles(); ++ti)
00568     {
00569         Int32   tind = ti.getIndex();
00570         Vec3f   mynorm = faceNormals[tind];
00571 
00572         std::multimap<Pnt3f, UInt32, vecless<Pnt3f> >::iterator st, en;
00573 
00574         for(UInt16 i = 0; i < 3; ++i)
00575         {
00576             // calculate the normal: average all different normals
00577             // that use a point. Simple addition or weighted addition
00578             // doesn't work, as it depends on the triangulation
00579             // of the object. :(
00580             std::set<Vec3f, vecless<Vec3f> > normset;
00581 
00582             st = pntMap.lower_bound(ti.getPosition(i));
00583             en = pntMap.upper_bound(ti.getPosition(i));
00584 
00585             for(; st != en; st++)
00586             {
00587                 if(mynorm.dot(faceNormals[(*st).second]) > cosCrease)
00588                 {
00589                     normset.insert(faceNormals[(*st).second]);
00590                 }
00591             }
00592 
00593             Vec3f                                               norm(0, 0, 0);
00594             typedef std::set<Vec3f, vecless<Vec3f> >::iterator  NormSetIt;
00595 
00596             for(NormSetIt it = normset.begin(); it != normset.end(); ++it)
00597             {
00598                 norm += (*it);
00599             }
00600 
00601             norm.normalize();
00602             norms->setValue(norm, ti.getNormalIndex(i));
00603         }
00604     }
00605 
00606     endEditCP(ip);
00607     endEditCP(norms);
00608 
00609 #else
00610     // opt + normal share code (written by jbehr)
00611     // collect a map from points to faces using this point
00612     // collect the face normals in a separate vector
00613     //FLOG (("Run calcVertexNormals(%g)\n", creaseAngle));
00614     std::vector < Vec3f > faceNormals;
00615     std::vector < std::vector < UInt32 > > pntFaceDic;
00616 
00617     TriangleIterator ti;
00618     UInt32 i, pN = positions->size();
00619 
00620     pntFaceDic.resize(pN);
00621     for(ti = geo->beginTriangles(), i = 0; ti != geo->endTriangles(); ++ti, ++i)
00622     {
00623         Int32 v0 = ti.getPositionIndex(0);
00624         Int32 v1 = ti.getPositionIndex(1);
00625         Int32 v2 = ti.getPositionIndex(2);
00626 
00627         if(v0 != v1 && v0 != v2)
00628         {
00629             Vec3f d1 = ti.getPosition(1) - ti.getPosition(0);
00630             Vec3f d2 = ti.getPosition(2) - ti.getPosition(0);
00631             d1.crossThis(d2);
00632 
00633             if(d1.squareLength() >= 0)
00634             {
00635                 d1.normalize();
00636                 faceNormals.push_back(d1);
00637 
00638                 pntFaceDic[ti.getPositionIndex(0)].push_back(i);
00639                 pntFaceDic[ti.getPositionIndex(1)].push_back(i);
00640                 pntFaceDic[ti.getPositionIndex(2)].push_back(i);
00641             }
00642             else
00643             {
00644                 faceNormals.push_back(Vec3f(0, 0, 0));
00645             }
00646         }
00647         else
00648         {
00649             faceNormals.push_back(Vec3f(0, 0, 0));
00650         }
00651     }
00652 
00653     // now walk through the geometry again and calc the normals
00654     beginEditCP(norms);
00655     beginEditCP(ip);
00656 
00657     norms->clear();
00658 
00659     Real32 cosCrease = osgcos(creaseAngle);
00660     Vec3f norm;
00661     std::vector < UInt32 > normset;
00662     std::vector < std::map < std::vector < UInt32 > , UInt32 > > normDic;
00663     std::map < std::vector < UInt32 > , UInt32 >::iterator ndI;
00664 
00665     UInt32 normalIndex = 0;
00666 
00667     normDic.resize(pN);
00668 
00669     for(ti = geo->beginTriangles(); ti != geo->endTriangles(); ++ti)
00670     {
00671         Int32 tind = ti.getIndex();
00672         Vec3f faceNorm(faceNormals[tind]);
00673 
00674         if(faceNorm.squareLength() != 0.0)
00675         {
00676             for(UInt16 i = 0; i < 3; ++i)
00677             {
00678                 // calculate the normal: average all different normals
00679                 // that use a point. Simple addition or weighted addition
00680                 // doesn't work, as it depends on the triangulation
00681                 // of the object. :(
00682                 UInt32 p = ti.getPositionIndex(i);
00683                 UInt32 pf, f, fN = pntFaceDic[p].size();
00684                 UInt32 n, nN;
00685 
00686                 normset.clear();
00687                 for(f = 0; f < fN; f++)
00688                 {
00689                     if(((pf = pntFaceDic[p][f]) == tind) ||
00690                        (faceNorm.dot(faceNormals[pf]) > cosCrease))
00691                         normset.push_back(pf);
00692                 }
00693 
00694                 if((nN = normset.size()))
00695                 {
00696                     // find normal
00697                     //std::sort ( normset.begin(), normset.end() );
00698                     ndI = normDic[p].find(normset);
00699                     if(ndI == normDic[p].end())
00700                     {
00701                         norm = faceNormals[normset[0]];
00702                         for(n = 1; n < nN; ++n)
00703                             norm += faceNormals[normset[n]];
00704                         norm.normalize();
00705                         normalIndex = norms->size();
00706                         norms->push_back(norm);
00707                         normDic[p][normset] = normalIndex;
00708                     }
00709                     else
00710                     {
00711                         normalIndex = ndI->second;
00712                     }
00713                 }
00714                 else
00715                 {
00716                     // keep normalIndex
00717                     FWARNING(("Empty normset for %d faces pos %d: %f/%f/%f\n",
00718                                fN, i, ti.getPosition(i).x(),
00719                                ti.getPosition(i).y(), ti.getPosition(i).z()
00720                             ));
00721                 }
00722 
00723                 ip->setValue(normalIndex, ti.getIndexIndex(i) + ni);
00724             }
00725         }
00726         else
00727         {
00728             // keep normal for degenerated triangle
00729 
00730             normalIndex = norms->size();
00731             norms->push_back(norm);
00732             
00733             ip->setValue ( normalIndex, ti.getIndexIndex(0) + ni );
00734             ip->setValue ( normalIndex, ti.getIndexIndex(1) + ni );
00735             ip->setValue ( normalIndex, ti.getIndexIndex(2) + ni );
00736         }
00737     }
00738 
00739     endEditCP(ip);
00740     endEditCP(norms);
00741 #endif
00742 }

void osg::calcFaceNormals ( GeometryPtr  geo  ) 

calcFaceNormals calculates the normals for the geometry's faces, see Normal Calculation for a description.

Definition at line 754 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::GeoProperty< GeoPropertyDesc >::create(), osg::endEditCP(), FINFO, osg::FaceIterator::getIndexIndex(), osg::FaceIterator::getLength(), osg::FaceIterator::getPosition(), osg::FaceIterator::getPositionIndex(), osg::PrimitiveIterator::getType(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::length(), osg::Geometry::MapNormal, osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize(), osg::NullFC, osg::MField< FieldTypeT, fieldNameSpace >::push_back(), and osg::MField< FieldTypeT, fieldNameSpace >::size().

00755 {
00756     if(geo->getPositions() == NullFC ||
00757        geo->getPositions()->size() == 0)
00758     {
00759         FINFO(("Geo without positions in calcFaceNormals()\n"));
00760         return;
00761     }
00762 
00763     GeoIndicesPtr newIndex = GeoIndicesUI32::create();
00764     GeoNormalsPtr newNormals = GeoNormals3f::create();
00765     Vec3f normal;
00766 
00767     FaceIterator faceIter = geo->beginFaces();
00768     GeoIndicesPtr oldIndex = geo->getIndices();
00769 
00770     if(oldIndex != NullFC)
00771     {
00772         //Indexed
00773         if(geo->getIndexMapping().size() > 0)
00774         {
00775             //MULTI INDEXED
00776             beginEditCP(newIndex);
00777 
00778             MFUInt16    &oldIndexMap = geo->getIndexMapping();
00779             UInt32 oldIMSize = oldIndexMap.size();
00780             for(UInt32 i = 0; i < oldIndex->getSize() / oldIMSize; ++i)
00781             {
00782                 for(UInt32 k = 0; k < oldIMSize; ++k)
00783                 {
00784                     newIndex->push_back(oldIndex->getValue(i * oldIMSize + k));
00785                 }
00786 
00787                 newIndex->push_back(0);                                 //placeholder for normal index
00788             }
00789 
00790             beginEditCP(newNormals);
00791             for(UInt32 faceCnt = 0; faceIter != geo->endFaces();
00792                             ++faceIter, ++faceCnt)
00793             {
00794                 if(faceIter.getLength() == 3)
00795                 {
00796                     //Face is a Triangle
00797                     normal =
00798                         (
00799                             faceIter.getPosition(1) -
00800                             faceIter.getPosition(0)
00801                         ).cross(faceIter.getPosition(2) - faceIter.getPosition(0));
00802                     normal.normalize();
00803                 }
00804                 else
00805                 {
00806                     //Face must be a Quad then
00807                     normal =
00808                         (
00809                             faceIter.getPosition(1) -
00810                             faceIter.getPosition(0)
00811                         ).cross(faceIter.getPosition(2) - faceIter.getPosition(0));
00812                     if(normal.length() == 0)
00813                     {
00814                         //Quad is degenerate, choose different points for normal
00815                         normal =
00816                             (
00817                                 faceIter.getPosition(1) -
00818                                 faceIter.getPosition(2)
00819                             ).cross(faceIter.getPosition(3) -
00820                                                                 faceIter.getPosition(2));
00821                     }
00822 
00823                     normal.normalize();
00824                 }
00825 
00826                 newNormals->push_back(normal);                          //put the normal into the storage
00827                 UInt32 base;
00828                 switch(faceIter.getType())
00829                 {
00830                 case GL_TRIANGLE_STRIP:
00831                     base = faceIter.getIndexIndex(2);                   //get last point's position in index field
00832                     newIndex->setValue(faceCnt, base + (base / oldIMSize) + oldIMSize);
00833                     break;
00834                 case GL_TRIANGLE_FAN:
00835                     base = faceIter.getIndexIndex(2);                   //get last point's position in index field
00836                     newIndex->setValue(faceCnt, base + (base / oldIMSize) + oldIMSize);
00837                     break;
00838                 case GL_QUAD_STRIP:
00839                     base = faceIter.getIndexIndex(3);                   //get last point's position in index field
00840                     newIndex->setValue(faceCnt, base + (base / oldIMSize) + oldIMSize);
00841                     break;
00842                 default:
00843                     for(UInt32 i = 0; i < faceIter.getLength(); ++i)
00844                     {
00845                         base = faceIter.getIndexIndex(i);
00846                         newIndex->setValue(faceCnt,
00847                                                                    base + (base / oldIMSize) + oldIMSize);
00848                     }
00849                     break;
00850                 }
00851             }
00852 
00853             endEditCP(newNormals);
00854             endEditCP(newIndex);
00855 
00856             beginEditCP(geo);
00857 
00858             Int16 ni;
00859             ni = geo->calcMappingIndex(Geometry::MapNormal);
00860             if(ni != -1)
00861             {
00862                 oldIndexMap[ni] = oldIndexMap[ni] &~Geometry::MapNormal;
00863             }
00864 
00865             oldIndexMap.push_back(Geometry::MapNormal);
00866             geo->setNormals(newNormals);
00867             geo->setIndices(newIndex);
00868             endEditCP(geo);
00869             return;
00870         }
00871     }
00872 
00873     //SINGLE INDEXED or NON INDEXED
00874     //UInt32 pointCnt = 0;
00875     newNormals->resize(geo->getPositions()->getSize());
00876     for(; faceIter != geo->endFaces(); ++faceIter)
00877     {
00878         if(faceIter.getLength() == 3)
00879         {
00880             //Face is a Triangle
00881             normal = (faceIter.getPosition(1) - faceIter.getPosition(0)).cross(faceIter.getPosition(2) - faceIter.getPosition(0));
00882             normal.normalize();
00883         }
00884         else
00885         {
00886             //Face must be a Quad then
00887             normal = (faceIter.getPosition(1) - faceIter.getPosition(0)).cross(faceIter.getPosition(2) - faceIter.getPosition(0));
00888             if(normal.length() == 0)
00889             {
00890                 //Quad is degenerate, choose different points for normal
00891                 normal =
00892                     (
00893                         faceIter.getPosition(1) -
00894                         faceIter.getPosition(2)
00895                     ).cross(faceIter.getPosition(3) - faceIter.getPosition(2));
00896             }
00897 
00898             normal.normalize();
00899         }
00900 
00901         switch(faceIter.getType())
00902         {
00903         case GL_TRIANGLE_STRIP:
00904             newNormals->setValue(normal, faceIter.getPositionIndex(2));
00905             break;
00906         case GL_TRIANGLE_FAN:
00907             newNormals->setValue(normal, faceIter.getPositionIndex(2));
00908             break;
00909         case GL_QUAD_STRIP:
00910             newNormals->setValue(normal, faceIter.getPositionIndex(3));
00911             break;
00912         default:
00913             for(UInt32 i = 0; i < faceIter.getLength(); ++i)
00914             {
00915                 newNormals->setValue(normal, faceIter.getPositionIndex(i));
00916             }
00917             break;
00918         }
00919 
00920         beginEditCP(geo);
00921         geo->setNormals(newNormals);
00922         endEditCP(geo);
00923     }
00924 }

Int32 osg::setIndexFromVRMLData ( GeometryPtr  geoPtr,
std::vector< Int32 > &  coordIndex,
std::vector< Int32 > &  normalIndex,
std::vector< Int32 > &  colorIndex,
std::vector< Int32 > &  texCoordIndex,
bool  convex,
bool  ccw,
bool  normalPerVertex,
bool  colorPerVertex,
bool  createNormal,
bool  faceSet 
)

setIndexFromVRMLData creates an osg::Geometry's interleaved index data from VRML-style separate indices, see Geometry Creation for a description.

coordIndex, normalIndex, colorIndex and texCoordIndex are VRML97-style indices. ccw sets whether poylgons are defined counter-clockwise or clockwise, normalPerVertex and colorPerVertex specify bindings, and faceSet defines whether a VRML IndexedFaceSet or an IndexedLineSet is being generated. See the VRML97 specification at http://www.web3d.org for details.

Note: the convex and createNormals parameters are ignored right now!

Definition at line 943 of file OSGGeoFunctions.cpp.

References osg::setIndexFromIndexedX3DData().

Referenced by osg::VRMLGeometryPointSetDesc::endNode(), and osg::VRMLGeometryDesc::endNode().

00954 {
00955   Int32 primitiveType = faceSet ? GL_POLYGON : GL_LINE_STRIP;
00956 
00957   return setIndexFromIndexedX3DData ( geoPtr,
00958                                       coordIndex,
00959                                       normalIndex,
00960                                       colorIndex,
00961                                       texCoordIndex,
00962                                       primitiveType,
00963                                       convex,
00964                                       ccw,
00965                                       normalPerVertex,
00966                                       colorPerVertex,
00967                                       createNormal );
00968 }

Int32 osg::setIndexFromIndexedX3DData ( GeometryPtr  geoPtr,
std::vector< Int32 > &  coordIndex,
std::vector< Int32 > &  normalIndex,
std::vector< Int32 > &  colorIndex,
std::vector< Int32 > &  texCoordIndex,
Int32  primitiveType,
bool  convex,
bool  ccw,
bool  normalPerVertex,
bool  colorPerVertex,
bool  createNormal 
)

setIndexFromIndexedX3DData creates an osg::Geometry's interleaved index data from X3D-style separate indices, see Geometry Creation for a description.

The primitiveType defines the GL-Primtive (e.g. GL_LINE, GL_TRIANGLE_STRIP, GL_POLYGON) which should be used.

coordIndex, normalIndex, colorIndex and texCoordIndex are X3D-style indices. ccw sets whether poylgons are defined counter-clockwise or clockwise, normalPerVertex and colorPerVertex specify bindings. See the X3D specification at http://www.web3d.org for details.

Note: the convex and createNormals parameters are ignored right now!

Definition at line 989 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::endEditCP(), FDEBUG, FFATAL, FINFO, FNOTICE, FWARNING, osg::Geometry::MapColor, osg::Geometry::MapNormal, osg::Geometry::MapPosition, osg::Geometry::MapTexCoords, osg::Geometry::MapTexCoords1, osg::Geometry::MapTexCoords2, osg::Geometry::MapTexCoords3, osg::Geometry::MapTexCoords4, osg::Geometry::MapTexCoords5, osg::Geometry::MapTexCoords6, osg::Geometry::MapTexCoords7, and osg::NullFC.

Referenced by osg::setIndexFromVRMLData().

01000 {
01002     typedef std::vector<Int32>  *IndexBagP;
01003 
01005     enum IndexType
01006     {
01007         UNKNOWN_IT          = 0,
01008         EMPTY_IT,
01009         VERTEX_COORD_IT,
01010         VERTEX_IT,
01011         VERTEX_DUP_IT,
01012         VERTEX_CREATE_IT,
01013         PRIMITIVE_IT,
01014         PRIMITIVE_INDEX_IT,
01015         PRIMITIVE_CREATE_IT
01016     };
01017 
01019     static const char *indexTypeStr[] =
01020     {
01021         "UNKNOWN_IT",
01022         "EMPTY_IT",
01023         "VERTEX_COORD_IT",
01024         "VERTEX_IT",
01025         "VERTEX_DUP_IT",
01026         "VERTEX_CREATE_IT",
01027         "PRIMTIVE_IT",
01028         "PRIMITIVE_INDEX_IT",
01029         "PRIMITIVE_CREATE_IT"
01030     };
01031     OSG::GeoPositionsPtr posPtr;
01032     OSG::GeoNormalsPtr normalPtr;
01033     OSG::GeoColorsPtr colorPtr;
01034     OSG::GeoTexCoordsPtr texCoordsPtr;
01035     OSG::GeoPLengthsPtr lensPtr;
01036     OSG::GeoPTypesPtr geoTypePtr;
01037     OSG::GeoIndicesPtr indexPtr;
01038 
01039     //bool faceSet = (primitiveType == GL_POLYGON);
01040     Int32 index, i, pi, typei, mapi, primitiveN = 0, vN = 0;
01041     Int32 pType = 0, localPType;
01042     Int32 maxPType; //  = (faceSet ? 5 : 3);
01043     Int32 minPType; //  = (faceSet ? 3 : 2);
01044     Int32 beginIndex, endIndex, step, len, sysPType = 0;
01045     Int32 piN = 0, ciN = 0, niN = 0, tiN = 0;
01046     Int32 pN = 0, nN = 0, cN = 0, tN = 0, tN1 = 0, tN2 = 0, tN3 = 0,
01047           tN4 = 0, tN5 = 0, tN6 = 0, tN7 = 0;
01048     IndexType indexType[4];
01049     IndexType &coordIT = indexType[0];
01050     IndexType &normalIT = indexType[1];
01051     IndexType &colorIT = indexType[2];
01052     IndexType &textureIT = indexType[3];
01053     Int32 primitiveTypeCount[6];
01054     UInt32 triCount = 0;
01055     Int16 indexMap[4], indexMapID[4];
01056     UInt32 uiNumTextures = 0;
01057 
01058     IndexBagP indexBag[4] =
01059     {
01060         &coordIndex,
01061         &normalIndex,
01062         &colorIndex,
01063         &texCoordIndex
01064     };
01065 
01066     //----------------------------------------------------------------------
01067     // init
01068     coordIT = VERTEX_IT;
01069     indexMap[0] = Geometry::MapPosition;
01070 
01071     //----------------------------------------------------------------------
01072     // set maxPType and minPTypr from primitiveType
01073     switch (primitiveType) {
01074     case GL_POINTS:
01075       minPType = 1;
01076       maxPType = 1;
01077       break;
01078     case GL_LINES:
01079       minPType = 2;
01080       maxPType = 3;
01081       break;
01082     case GL_LINE_STRIP:
01083       minPType = 2;
01084       maxPType = 3;
01085       break;
01086     case GL_LINE_LOOP:
01087       minPType = 2;
01088       maxPType = 3;
01089       break;
01090     case GL_TRIANGLES:
01091       minPType = 3;
01092       maxPType = 3;
01093       break;
01094     case GL_TRIANGLE_STRIP:
01095       minPType = 3;
01096       maxPType = 3;
01097       break;
01098     case GL_TRIANGLE_FAN:
01099       minPType = 3;
01100       maxPType = 3;
01101       break;
01102     case GL_QUADS:
01103       minPType = 3;
01104       maxPType = 4;
01105       break;
01106     case GL_QUAD_STRIP:    
01107       minPType = 3;
01108       maxPType = 4;
01109       break;
01110     case GL_POLYGON:
01111       minPType = 3;
01112       maxPType = 5;
01113       break;
01114     default:
01115       FFATAL (( "Can not fill index; Invalid primitiveType: %d\n",
01116                 primitiveType ));
01117       break;
01118     }
01119       
01120 
01121     //----------------------------------------------------------------------
01122     // get the property pointer and element count
01123     posPtr = geoPtr->getPositions();
01124     pN = ((posPtr == OSG::NullFC) ? 0 : posPtr->getSize());
01125 
01126     normalPtr = geoPtr->getNormals();
01127     nN = ((normalPtr == OSG::NullFC) ? 0 : normalPtr->getSize());
01128 
01129     colorPtr = geoPtr->getColors();
01130     cN = ((colorPtr == OSG::NullFC) ? 0 : colorPtr->getSize());
01131 
01132     texCoordsPtr = geoPtr->getTexCoords();
01133     tN = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01134 
01135     texCoordsPtr = geoPtr->getTexCoords1();
01136     tN1 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01137 
01138     texCoordsPtr = geoPtr->getTexCoords2();
01139     tN2 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01140 
01141     texCoordsPtr = geoPtr->getTexCoords3();
01142     tN3 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01143 
01144     texCoordsPtr = geoPtr->getTexCoords4();
01145     tN4 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01146 
01147     texCoordsPtr = geoPtr->getTexCoords5();
01148     tN5 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01149 
01150     texCoordsPtr = geoPtr->getTexCoords6();
01151     tN6 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01152 
01153     texCoordsPtr = geoPtr->getTexCoords7();
01154     tN7 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01155 
01156     FDEBUG(("vertex attrib count P/N/C/T: %d/%d/%d/%d\n", pN, nN, cN, tN));
01157 
01158     //----------------------------------------------------------------------
01159     // check the vertex index and count the primitives
01160     primitiveN = index = 0;
01161     for(pType = 0; pType < 6; pType++)
01162         primitiveTypeCount[pType] = 0;
01163 
01164     if(!pN)
01165     {
01166         FINFO(("No points in OSG::setIndexFromVRMLData()\n"));
01167         return 0;
01168     }
01169     else
01170     {
01171         piN = coordIndex.size();
01172         if(piN)
01173         {
01174             for(i = 0; i <= piN; i++)
01175             {
01176                 index = (i == piN) ? -1 : coordIndex[i];
01177                 if((index < 0) && vN)
01178                 {
01179                     primitiveTypeCount[(vN > maxPType) ? maxPType : vN]++;
01180                     primitiveN++;
01181                     vN = 0;
01182                 }
01183                 else
01184                 {
01185                     if(index >= pN && i != piN)
01186                     {
01187                         FWARNING(("Point index (%d/%d) out of range", index, pN));
01188                         coordIndex[i] = 0;
01189                     }
01190 
01191                     vN++;
01192                 }
01193             }
01194         }
01195         else
01196         {
01197             FWARNING(("No coordIndex in OSG::setIndexFromVRMLData()\n"));
01198             return 0;
01199         }
01200     }
01201 
01202     //----------------------------------------------------------------------
01203     // check the normal index
01204     normalIT = UNKNOWN_IT;
01205     niN = normalIndex.size();
01206     if(nN)
01207     {               // have normal elements
01208         if(normalPerVertex)
01209         {
01210             // normal per vertex
01211             if(niN >= piN)
01212             {
01213                 // valid normal index number
01214                 for(i = 0; i < piN; i++)
01215                 {   // check if normal index equals the coord index
01216                     if(normalIndex[i] != coordIndex[i])
01217                     {
01218                         normalIT = VERTEX_IT;
01219                         break;
01220                     }
01221                 }
01222 
01223                 if(normalIT == UNKNOWN_IT)
01224                 {
01225                     // if equal than delete unneeded normal index
01226                     normalIT = VERTEX_DUP_IT;
01227                 }
01228             }
01229             else
01230             {
01231                 // no or not enough normal index
01232                 normalIT = VERTEX_COORD_IT;
01233                 if(niN)
01234                 {
01235                     FWARNING(("Not enough normal index (%d,%d)\n", normalIndex.
01236                                                      size(), piN));
01237                     normalIndex.clear();
01238                 }
01239             }
01240         }
01241         else
01242         {
01243             // normal per primitive
01244             if(niN >= primitiveN)
01245             {
01246                 // use one normal index per primitive
01247                 normalIT = PRIMITIVE_INDEX_IT;
01248             }
01249             else
01250             {
01251                 if(nN >= primitiveN)
01252                 {
01253                     // use one normal per primitive
01254                     normalIT = PRIMITIVE_IT;
01255                 }
01256                 else
01257                 {
01258                     FINFO(("not enough normal index (%d,%d)\n", nN, primitiveN));
01259                 }
01260             }
01261         }
01262     }
01263     else
01264     {
01265         /* not yet !!!
01266 if (createNormal)
01267   if (normalPerVertex)
01268     normalIT = VERTEX_CREATE_IT;
01269   else
01270     normalIT = PRIMITIVE_CREATE_IT;
01271 else
01272 */
01273         normalIT = EMPTY_IT;
01274     }
01275 
01276     //----------------------------------------------------------------------
01277     // check the color index
01278     colorIT = UNKNOWN_IT;
01279     ciN = colorIndex.size();
01280     if(cN)
01281     {               // have color elements
01282         if(colorPerVertex)
01283         {
01284             // color per vertex
01285             if(ciN >= piN)
01286             {
01287                 // valid color index number
01288                 for(i = 0; i < piN; i++)
01289                 {   // check if color index equals the coord index
01290                     if(colorIndex[i] != coordIndex[i])
01291                     {
01292                         colorIT = VERTEX_IT;
01293                         break;
01294                     }
01295                 }
01296 
01297                 if(colorIT == UNKNOWN_IT)
01298                 {
01299                     // if equal than delete unneeded color index
01300                     colorIT = VERTEX_DUP_IT;
01301                 }
01302             }
01303             else
01304             {
01305                 // no or not enough color index
01306                 colorIT = VERTEX_COORD_IT;
01307                 if(ciN)
01308                 {
01309                     FWARNING(("Not enough color index (%d,%d)\n", colorIndex.
01310                                                      size(), piN));
01311                     colorIndex.clear();
01312                 }
01313             }
01314         }
01315         else
01316         {
01317             // color per primitive
01318             if(ciN >= primitiveN)
01319             {
01320                 // use one color index per primitive
01321                 colorIT = PRIMITIVE_INDEX_IT;
01322             }
01323             else
01324             {
01325                 if(cN >= primitiveN)
01326                 {
01327                     // use one color per primitive
01328                     colorIT = PRIMITIVE_IT;
01329                 }
01330                 else
01331                 {
01332                     FINFO(("not enough color index (%d,%d)\n", cN, primitiveN));
01333                 }
01334             }
01335         }
01336     }
01337     else
01338     {
01339         colorIT = EMPTY_IT;
01340     }
01341 
01342     //----------------------------------------------------------------------
01343     // check the texture index
01344     textureIT = UNKNOWN_IT;
01345     tiN = texCoordIndex.size();
01346     if(tN)
01347     {               // have texture elemnts
01348         if(tiN >= piN)
01349         {
01350             // valid texture index number
01351             for(i = 0; i < piN; i++)
01352             {       // check if texture index equals the coord index
01353                 if(texCoordIndex[i] != coordIndex[i])
01354                 {
01355                     textureIT = VERTEX_IT;
01356                     break;
01357                 }
01358             }
01359 
01360             if(textureIT == UNKNOWN_IT)
01361             {
01362                 // if equal than delete unneeded texture index
01363                 textureIT = VERTEX_DUP_IT;
01364             }
01365         }
01366         else
01367         {
01368             // no or not enough texture index
01369             textureIT = VERTEX_COORD_IT;
01370             if(ciN)
01371             {
01372                 FWARNING(("Not enough texCoord index (%d,%d)\n", texCoordIndex.
01373                                              size(), piN));
01374                 texCoordIndex.clear();
01375             }
01376         }
01377     }
01378     else
01379     {
01380         textureIT = EMPTY_IT;
01381     }
01382 
01383     FNOTICE (( "primitiveN:  %d, %d, 0/%d 1/%d 2/%d 3/%d 4/%d 5/%d\n",
01384             primitiveType,
01385             primitiveN, primitiveTypeCount[0],
01386             primitiveTypeCount[1], primitiveTypeCount[2],
01387             primitiveTypeCount[3], primitiveTypeCount[4],
01388             primitiveTypeCount[5]));
01389     
01390     FNOTICE (( "IndexType: coord: %s, color: %s, normal: %s, texture: %s \n",
01391             indexTypeStr[coordIT], indexTypeStr[colorIT], 
01392             indexTypeStr[normalIT], indexTypeStr[textureIT]));
01393 
01394     //----------------------------------------------------------------------
01395     // check/create the indexPtr/lengthsPtr/geoTypePtr
01396     indexPtr = geoPtr->getIndices();
01397     if(indexPtr == OSG::NullFC)
01398     {
01399         indexPtr = OSG::GeoIndicesUI32::create();
01400     }
01401     else
01402     {
01403         OSG::beginEditCP(indexPtr);
01404         indexPtr->clear();
01405         OSG::endEditCP(indexPtr);
01406     }
01407 
01408     lensPtr = geoPtr->getLengths();
01409     if(lensPtr == OSG::NullFC)
01410     {
01411         lensPtr = OSG::GeoPLengthsUI32::create();
01412     }
01413     else
01414     {
01415         OSG::beginEditCP(lensPtr);
01416         lensPtr->clear();
01417         OSG::endEditCP(lensPtr);
01418     }
01419 
01420     geoTypePtr = geoPtr->getTypes();
01421     if(geoTypePtr == OSG::NullFC)
01422     {
01423         geoTypePtr = OSG::GeoPTypesUI8::create();
01424     }
01425     else
01426     {
01427         OSG::beginEditCP(geoTypePtr);
01428         geoTypePtr->clear();
01429         OSG::endEditCP(geoTypePtr);
01430     }
01431 
01432     //----------------------------------------------------------------------
01433     // create the index mapping
01434     indexMapID[0] = Geometry::MapPosition;
01435     indexMapID[1] = Geometry::MapNormal;
01436     indexMapID[2] = Geometry::MapColor;
01437     indexMapID[3] = Geometry::MapTexCoords;
01438 
01439     for(mapi = i = 1; i <= 3; i++)
01440     {
01441         indexMap[i] = 0;
01442         switch(indexType[i])
01443         {
01444         case UNKNOWN_IT:
01445         case EMPTY_IT:
01446             break;
01447         case VERTEX_COORD_IT:
01448         case VERTEX_DUP_IT:
01449             //case VERTEX_CREATE_IT:
01450             indexMap[0] |= indexMapID[i];
01451             break;
01452         case VERTEX_IT:
01453         case PRIMITIVE_IT:
01454         case PRIMITIVE_INDEX_IT:
01455             //case PRIMITIVE_CREATE_IT:
01456             indexMap[mapi++] = indexMapID[i];
01457             break;
01458         default:    //X_CREATE_IT
01459             break;
01460         }
01461     }
01462 
01463     //----------------------------------------------------------------------
01464     // set lens/geoType/index/mapping the index mapping
01465     OSG::beginEditCP(geoPtr);
01466     {
01467         geoPtr->setLengths(lensPtr);
01468         geoPtr->setTypes(geoTypePtr);
01469         geoPtr->setIndices(indexPtr);
01470         geoPtr->getIndexMapping().clear();
01471 
01472         // TODO: check for multiindex mapping ?
01473         // if (indexMap[1])
01474         for(i = 0; ((i <= 3) && indexMap[i]); i++)
01475         {
01476             if(i == 0)
01477             {
01478                 if(indexMap[i] & Geometry::MapTexCoords)
01479                 {
01480                     ++uiNumTextures;
01481                     
01482                     if(tN1 != 0)
01483                     {
01484                         indexMap[i] |= Geometry::MapTexCoords1;
01485                     }
01486                     
01487                     if(tN2 != 0)
01488                     {
01489                         indexMap[i] |= Geometry::MapTexCoords2;
01490                     }
01491                     
01492                     if(tN3 != 0)
01493                     {
01494                         indexMap[i] |= Geometry::MapTexCoords3;
01495                     }
01496                     
01497                     if(tN4 != 0)
01498                     {
01499                         indexMap[i] |= Geometry::MapTexCoords4;
01500                     }
01501                     
01502                     if(tN5 != 0)
01503                     {
01504                         indexMap[i] |= Geometry::MapTexCoords5;
01505                     }
01506                     
01507                     if(tN6 != 0)
01508                     {
01509                         indexMap[i] |= Geometry::MapTexCoords6;
01510                     }
01511                     
01512                     if(tN7 != 0)
01513                     {
01514                         indexMap[i] |= Geometry::MapTexCoords7;
01515                     }
01516                 }
01517 
01518                 geoPtr->getIndexMapping().push_back(indexMap[i]);
01519             }
01520             else
01521             {
01522                 geoPtr->getIndexMapping().push_back(indexMap[i]);
01523                 
01524                 if(indexMap[i] & Geometry::MapTexCoords)
01525                 {
01526                     ++uiNumTextures;
01527                     
01528                     if(tN1 != 0)
01529                     {
01530                         geoPtr->getIndexMapping().push_back(
01531                             Geometry::MapTexCoords1);
01532                         
01533                         ++uiNumTextures;
01534                     }
01535                     
01536                     if(tN2 != 0)
01537                     {
01538                         geoPtr->getIndexMapping().push_back(
01539                             Geometry::MapTexCoords2);
01540                         
01541                         ++uiNumTextures;
01542                     }
01543                     
01544                     if(tN3 != 0)
01545                     {
01546                         geoPtr->getIndexMapping().push_back(
01547                             Geometry::MapTexCoords3);
01548                         
01549                         ++uiNumTextures;
01550                     }
01551                     
01552                     if(tN4 != 0)
01553                     {
01554                         geoPtr->getIndexMapping().push_back(
01555                             Geometry::MapTexCoords4);
01556                         
01557                         ++uiNumTextures;
01558                     }
01559                     
01560                     if(tN5 != 0)
01561                     {
01562                         geoPtr->getIndexMapping().push_back(
01563                             Geometry::MapTexCoords5);
01564                         
01565                         ++uiNumTextures;
01566                     }
01567                     
01568                     if(tN6 != 0)
01569                     {
01570                         geoPtr->getIndexMapping().push_back(
01571                             Geometry::MapTexCoords6);
01572                         
01573                         ++uiNumTextures;
01574                     }
01575                     
01576                     if(tN7 != 0)
01577                     {
01578                         geoPtr->getIndexMapping().push_back(
01579                             Geometry::MapTexCoords7);
01580                         
01581                         ++uiNumTextures;
01582                     }
01583                 }
01584             }
01585         }
01586     }
01587     OSG::endEditCP(geoPtr);
01588 
01589     //----------------------------------------------------------------------
01590     // create index face/line data
01591     OSG::beginEditCP(indexPtr);
01592     OSG::beginEditCP(lensPtr);
01593     OSG::beginEditCP(geoTypePtr);
01594 
01595     for(pType = minPType; pType <= maxPType; pType++)
01596     {
01597         // check for the pType count
01598         if(primitiveTypeCount[pType])
01599         {
01600             // calc len/sysPType
01601           
01602             if(pType < maxPType)
01603             {
01604                 len = primitiveTypeCount[pType] * pType;
01605                 switch (pType) 
01606                 {
01607                   case 1:
01608                     sysPType = GL_POINTS;
01609                     break;
01610                   case 2:
01611                     sysPType = GL_LINES;
01612                     break;
01613                   case 3:
01614                     sysPType = GL_TRIANGLES;
01615                     break;
01616                   case 4:
01617                     sysPType = GL_QUADS;
01618                     break;
01619                 }
01620             }
01621             else
01622             { 
01623                 sysPType = 0;
01624             }
01625 
01626             // set len/sysPType
01627             if(sysPType)
01628             {
01629               lensPtr->push_back(len);
01630               geoTypePtr->push_back(sysPType);
01631             }
01632 
01633             primitiveN = 0;
01634             beginIndex = endIndex = -1;
01635             for(i = 0; i <= piN; i++)
01636             {
01637                 if(((i == piN) && (coordIndex[i - 1] >= 0)) ||
01638                                    ((i < piN) && (coordIndex[i] < 0)))
01639                 {
01640                     len = i - beginIndex;
01641                     if(ccw)
01642                     {
01643                         endIndex = i;
01644                         step = 1;
01645                     }
01646                     else
01647                     {
01648                         endIndex = beginIndex - 1;
01649                         beginIndex = i - 1;
01650                         step = -1;
01651                     }
01652 
01653                     localPType = (len > maxPType) ? maxPType : len;
01654                     if((beginIndex >= 0) && (localPType == pType))
01655                     {
01656                         if(len >= maxPType)
01657                         {
01658                             sysPType = primitiveType;
01659                             lensPtr->push_back(len);
01660                             geoTypePtr->push_back(sysPType);
01661                         }
01662 
01663                         // add index data
01664                         for(pi = beginIndex; pi != endIndex; pi += step)
01665                         {
01666                             indexPtr->push_back(coordIndex[pi]);
01667                             for(mapi = 1; (mapi <= 3) && (indexMap[mapi]);
01668                                                             mapi++)
01669                             {
01670                                 for(typei = 1; typei <= 3; typei++)
01671                                 {
01672                                     if(indexMap[mapi] & indexMapID[typei])
01673                                     {
01674                                         switch(indexType[typei])
01675                                         {
01676                                         case UNKNOWN_IT:
01677                                         case EMPTY_IT:
01678                                         case VERTEX_COORD_IT:
01679                                         case VERTEX_DUP_IT:
01680                                             FFATAL(("Fatal index mapping error \n"));
01681                                             break;
01682                                         case VERTEX_IT:
01683                                             index = (*indexBag[typei])[pi];
01684                                             break;
01685                                         case PRIMITIVE_IT:
01686                                             index = primitiveN;
01687                                             break;
01688                                         case PRIMITIVE_INDEX_IT:
01689                                             index = (*indexBag[typei])[primitiveN];
01690                                             break;
01691                                         default:                        //X_CREATE_IT
01692                                             break;
01693                                         }
01694 
01695                                         indexPtr->push_back(index);
01696                                         
01697                                         if(indexMap[mapi] & Geometry::MapTexCoords)
01698                                         {
01699                                             for(UInt32 ti = 0; ti < uiNumTextures - 1; ++ti)
01700                                             {
01701                                                 indexPtr->push_back(index);
01702                                             }
01703                                         }
01704                                     }
01705                                     
01706                                 }
01707                             }
01708                         }
01709 
01710                         triCount += len - 2;
01711                     }
01712 
01713                     primitiveN++;
01714                     beginIndex = endIndex = -1;
01715                 }
01716                 else if(beginIndex < 0)
01717                     beginIndex = i;
01718             }
01719         }
01720     }
01721 
01722     OSG::endEditCP(geoTypePtr);
01723     OSG::endEditCP(lensPtr);
01724     OSG::endEditCP(indexPtr);
01725 
01726     return triCount;
01727 }

void osg::calcVertexTexCoords ( GeometryPtr  geo,
Int32  texIndex 
)

calcVertexTexCoords calculates the texCoords for the geometry's vertices, see PageSystemGeoFunctionsCalcTexCoords for a description.

Definition at line 1788 of file OSGGeoFunctions.cpp.

References osg::MField< FieldTypeT, fieldNameSpace >::begin(), osg::beginEditCP(), osg::GeoProperty< GeoPropertyDesc >::create(), osg::endEditCP(), osg::MField< FieldTypeT, fieldNameSpace >::erase(), FFATAL, FWARNING, osg::DynamicVolume::getBounds(), osg::Geometry::MapPosition, osg::Geometry::MapTexCoords, osg::Geometry::MapTexCoords1, osg::Geometry::MapTexCoords2, osg::Geometry::MapTexCoords3, osg::Geometry::MapTexCoords4, osg::Geometry::MapTexCoords5, osg::Geometry::MapTexCoords6, osg::Geometry::MapTexCoords7, osg::NullFC, osg::MField< FieldTypeT, fieldNameSpace >::push_back(), and osg::MField< FieldTypeT, fieldNameSpace >::size().

01789 {
01790     struct Key {
01791         Real32 value;
01792         Int32 pos;
01793     } key[3], rem;
01794 
01795     Int32 S = -1, T = -1, n = 3, i, j; 
01796     Real32 sDenom, tDenom, sMin, tMin;
01797     
01798     MFUInt16 &im = geo->getIndexMapping();
01799     UInt16 mapTex = 0;
01800 
01801     GeoIndicesPtr ip = geo->getIndices();
01802     GeoPositionsPtr posP = geo->getPositions();
01803     GeoTexCoordsPtr texP;
01804 
01805     if (posP == NullFC || !posP->size() || ip == NullFC || !ip->size())
01806     {
01807         FFATAL(("Geo without indices/ positions in calcVertexTexCoords()\n"));
01808         return;
01809     }
01810     
01811     for (MFNodePtr::iterator pnI = geo->getMFParents()->begin();
01812          pnI != geo->getMFParents()->end(); ++pnI)
01813     {
01814         NodePtr node = *pnI;
01815 
01816         if (node != NullFC)
01817         {
01818             DynamicVolume &dVol = node->getVolume(true);
01819             Pnt3f min, max;
01820             dVol.getBounds(min, max);
01821     
01822             Vec3f dia(max - min);
01823             for (i=0; i<3; i++)
01824             {
01825                 key[i].value = dia[i];
01826                 key[i].pos = i;
01827             }
01828     
01829             for (i=1; i<n; i++)
01830             {
01831                 for (j=n-1; j>=i; j--)
01832                 {
01833                     if (key[j-1].value > key[j].value)
01834                     {
01835                         rem = key[j];
01836                         key[j] = key[j-1];
01837                         key[j-1] = rem;
01838                     }
01839                 }
01840             }
01841     
01842             S = key[2].pos;
01843             T = key[1].pos;
01844             sDenom = dia[S];
01845             tDenom = dia[T];
01846             sMin = min[S];
01847             tMin = min[T];
01848     
01849             break;
01850         }
01851     }
01852 
01853     if (S < 0 || T < 0)
01854     {
01855         FFATAL(("Geo without parents in calcVertexTexCoords()\n"));
01856         return;
01857     }
01858 
01859     switch (texIndex)
01860     {
01861         case 0:
01862             if (geo->getTexCoords() == osg::NullFC)
01863             {
01864                 texP = GeoTexCoords2f::create();
01865                 beginEditCP(geo);
01866                     geo->setTexCoords(texP);
01867                 endEditCP(geo);
01868             }
01869             else
01870             {
01871                 texP = geo->getTexCoords();
01872             }
01873             mapTex = Geometry::MapTexCoords;
01874             break;
01875         case 1:
01876             if (geo->getTexCoords1() == osg::NullFC)
01877             {
01878                 texP = GeoTexCoords2f::create();
01879                 beginEditCP(geo);
01880                     geo->setTexCoords1(texP);
01881                 endEditCP(geo);
01882             }
01883             else
01884             {
01885                 texP = geo->getTexCoords1();
01886             }
01887             mapTex = Geometry::MapTexCoords1;
01888             break;
01889         case 2:
01890             if (geo->getTexCoords2() == osg::NullFC)
01891             {
01892                 texP = GeoTexCoords2f::create();
01893                 beginEditCP(geo);
01894                     geo->setTexCoords2(texP);
01895                 endEditCP(geo);
01896             }
01897             else
01898             {
01899                 texP = geo->getTexCoords2();
01900             }
01901             mapTex = Geometry::MapTexCoords2;
01902             break;
01903         case 3:
01904             if (geo->getTexCoords3() == osg::NullFC)
01905             {
01906                 texP = GeoTexCoords2f::create();
01907                 beginEditCP(geo);
01908                     geo->setTexCoords3(texP);
01909                 endEditCP(geo);
01910             }
01911             else
01912             {
01913                 texP = geo->getTexCoords3();
01914             }
01915             mapTex = Geometry::MapTexCoords3;
01916             break;
01917         case 4:
01918             if (geo->getTexCoords4() == osg::NullFC)
01919             {
01920                 texP = GeoTexCoords2f::create();
01921                 beginEditCP(geo);
01922                     geo->setTexCoords4(texP);
01923                 endEditCP(geo);
01924             }
01925             else
01926             {
01927                 texP = geo->getTexCoords4();
01928             }
01929             mapTex = Geometry::MapTexCoords4;
01930             break;
01931         case 5:
01932             if (geo->getTexCoords5() == osg::NullFC)
01933             {
01934                 texP = GeoTexCoords2f::create();
01935                 beginEditCP(geo);
01936                     geo->setTexCoords5(texP);
01937                 endEditCP(geo);
01938             }
01939             else
01940             {
01941                 texP = geo->getTexCoords5();
01942             }
01943             mapTex = Geometry::MapTexCoords5;
01944             break;
01945         case 6:
01946             if (geo->getTexCoords6() == osg::NullFC)
01947             {
01948                 texP = GeoTexCoords2f::create();
01949                 beginEditCP(geo);
01950                     geo->setTexCoords6(texP);
01951                 endEditCP(geo);
01952             }
01953             else
01954             {
01955                 texP = geo->getTexCoords6();
01956             }
01957             mapTex = Geometry::MapTexCoords6;
01958             break;
01959         case 7:
01960             if (geo->getTexCoords7() == osg::NullFC)
01961             {
01962                 texP = GeoTexCoords2f::create();
01963                 beginEditCP(geo);
01964                     geo->setTexCoords7(texP);
01965                 endEditCP(geo);
01966             }
01967             else
01968             {
01969                 texP = geo->getTexCoords7();
01970             }
01971             mapTex = Geometry::MapTexCoords7;
01972             break;
01973         default:
01974             FWARNING(("Parameters are [0|1|2|3|4|5|6|7] in calcVertexTexCoords()\n"));
01975             return;
01976     }
01977 
01978     Int16 niTex = geo->calcMappingIndex(mapTex),
01979           niPos = geo->calcMappingIndex(Geometry::MapPosition);
01980     Int32 len = posP->size(), indexMapSize = im.size(), imsize = 0, ibsize;
01981     UInt32 nind = ip->size() / (indexMapSize ? indexMapSize : 1);
01982         
01983     Pnt3f point;
01984     Vec2f texCoord;
01985 
01986     if (indexMapSize > 1)
01987     {
01988         MFUInt16::iterator imIt = im.begin();
01989         std::vector<UInt32> indexBuffer;
01990 
01991         if (niTex >= 0)
01992             im[niTex] = im[niTex] &~ mapTex;
01993 
01994         im.push_back(mapTex);
01995 
01996         for (i=0; i<nind; i++)
01997         {
01998             for (j=0; j<indexMapSize; j++)
01999             {
02000                 if (j != niTex || im[niTex] >= 1)
02001                     indexBuffer.push_back(ip->getValue(i*indexMapSize + j));
02002             }
02003             indexBuffer.push_back(ip->getValue(i*indexMapSize + niPos));
02004         }
02005 
02006         if (niTex >= 0 && im[niTex] < 1)
02007             im.erase(imIt + niTex);
02008             
02009         imsize = im.size();
02010         ibsize = indexBuffer.size();
02011 
02012         beginEditCP(ip);
02013         {
02014             ip->clear();
02015 
02016             if (imsize != indexMapSize)
02017                 ip->resize(ibsize);
02018 
02019             for (i=0; i<ibsize; i++)
02020                 ip->setValue(indexBuffer[i], i);
02021         }
02022         endEditCP(ip);
02023 
02024         niTex = imsize ? imsize - 1 : 0;
02025     }
02026 
02027     beginEditCP(texP);
02028     {
02029         niPos = geo->calcMappingIndex(Geometry::MapPosition);
02030         niPos = (niPos >= 0) ? niPos : 0;
02031         
02032         if (texP->size() != len)
02033             texP->resize(len);
02034 
02035         beginEditCP(ip);
02036         {
02037             for (i=0; i<len; i++)
02038             {
02039                 posP->getValue(point, i);
02040     
02041                 texCoord[0] = (point[S] - sMin) / sDenom;
02042                 texCoord[1] = (point[T] - tMin) / tDenom;
02043 
02044                 texP->setValue(texCoord, i);
02045             }
02046         }
02047         endEditCP(ip);
02048     }
02049     endEditCP(texP);
02050 }

void osg::calcVertexTangents ( GeometryPtr  geo,
Int32  srcTexIndex,
Int32  dstAttribTan,
Int32  dstAttribBin 
)

calcVertexTangents calculates the tangents/ binormals for the geometry's vertices, see PageSystemGeoFunctionsCalcTangents for a description.

Definition at line 2059 of file OSGGeoFunctions.cpp.

References B, osg::MField< FieldTypeT, fieldNameSpace >::begin(), osg::beginEditCP(), osg::GeometryBase::ColorsFieldId, osg::GeoProperty< GeoPropertyDesc >::create(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::cross(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::dot(), osg::endEditCP(), IndexDic::entry(), osg::MField< FieldTypeT, fieldNameSpace >::erase(), FFATAL, FWARNING, osg::TriangleIterator::getIndexIndex(), osg::TriangleIterator::getNormal(), osg::TriangleIterator::getPosition(), osg::TriangleIterator::getPositionIndex(), osg::TriangleIterator::getTexCoords(), osg::TriangleIterator::getTexCoords1(), osg::TriangleIterator::getTexCoords2(), osg::TriangleIterator::getTexCoords3(), osg::TriangleIterator::getTexCoords4(), osg::TriangleIterator::getTexCoords5(), osg::TriangleIterator::getTexCoords6(), osg::TriangleIterator::getTexCoords7(), osg::GeometryBase::IndexMappingFieldMask, osg::GeometryBase::IndicesFieldMask, osg::Geometry::MapNormal, osg::Geometry::MapPosition, osg::Geometry::MapTexCoords, osg::Geometry::MapTexCoords1, osg::Geometry::MapTexCoords2, osg::Geometry::MapTexCoords3, osg::Geometry::MapTexCoords4, osg::Geometry::MapTexCoords5, osg::Geometry::MapTexCoords6, osg::Geometry::MapTexCoords7, osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize(), osg::GeometryBase::NormalsFieldId, osg::NullFC, osg::GeometryBase::PositionsFieldId, osg::MField< FieldTypeT, fieldNameSpace >::push_back(), osg::GeometryBase::SecondaryColorsFieldId, osg::MField< FieldTypeT, fieldNameSpace >::size(), osg::GeometryBase::TexCoords1FieldId, osg::GeometryBase::TexCoords2FieldId, osg::GeometryBase::TexCoords3FieldId, osg::GeometryBase::TexCoords4FieldId, osg::GeometryBase::TexCoords5FieldId, osg::GeometryBase::TexCoords6FieldId, osg::GeometryBase::TexCoords7FieldId, and osg::GeometryBase::TexCoordsFieldId.

02063 {
02064     GeoTexCoords4fPtr tangentP, binormalP;
02065     std::vector<Vec3f> tangent, binormal, normal;
02066     UInt16 mapTan = 0, mapBin = 0, mapTex = 0;
02067     
02068     // fallback in case of user error: use none mode
02069     if (dstAttribTan == dstAttribBin)
02070         dstAttribBin = -1;
02071     
02072     switch (srcTexIndex) 
02073     {
02074         case 0:
02075             mapTex = Geometry::MapTexCoords;
02076             break;
02077         case 1:
02078             mapTex = Geometry::MapTexCoords1;
02079             break;
02080         case 2:
02081             mapTex = Geometry::MapTexCoords2;
02082             break;
02083         case 3:
02084             mapTex = Geometry::MapTexCoords3;
02085             break;
02086         case 4:
02087             mapTex = Geometry::MapTexCoords4;
02088             break;
02089         case 5:
02090             mapTex = Geometry::MapTexCoords5;
02091             break;
02092         case 6:
02093             mapTex = Geometry::MapTexCoords6;
02094             break;
02095         case 7:
02096             mapTex = Geometry::MapTexCoords7;
02097             break;
02098         default:
02099             FWARNING(("Currently only 8 TexCoords allowed in GeoPtr\n"));  
02100             srcTexIndex = 0;
02101             mapTex = Geometry::MapTexCoords;
02102             break;
02103     }
02104   
02105     switch (dstAttribTan) 
02106     {    
02107         case Geometry::TexCoordsFieldId:
02108             beginEditCP(geo);
02109             {
02110                 // because we need more than 2 coords, as is usual,
02111                 // it is safer & easier to set a new texCoordsPtr 
02112                 tangentP = GeoTexCoords4f::create();
02113                 geo->setTexCoords(tangentP);
02114             }
02115             endEditCP(geo);
02116             mapTan = Geometry::MapTexCoords;
02117             break;
02118         case Geometry::TexCoords1FieldId:
02119             beginEditCP(geo);
02120             {
02121                 tangentP = GeoTexCoords4f::create();
02122                 geo->setTexCoords1(tangentP);
02123             }
02124             endEditCP(geo);
02125             mapTan = Geometry::MapTexCoords1;
02126             break;
02127         case Geometry::TexCoords2FieldId:
02128             beginEditCP(geo);
02129             {
02130                 tangentP = GeoTexCoords4f::create();
02131                 geo->setTexCoords2(tangentP);
02132             }
02133             endEditCP(geo);
02134             mapTan = Geometry::MapTexCoords2;
02135             break;
02136         case Geometry::TexCoords3FieldId:
02137             beginEditCP(geo);
02138             {
02139                 tangentP = GeoTexCoords4f::create();
02140                 geo->setTexCoords3(tangentP);
02141             }
02142             endEditCP(geo);
02143             mapTan = Geometry::MapTexCoords3;
02144             break;
02145         case Geometry::TexCoords4FieldId:
02146             beginEditCP(geo);
02147             {
02148                 tangentP = GeoTexCoords4f::create();
02149                 geo->setTexCoords4(tangentP);
02150             }
02151             endEditCP(geo);
02152             mapTan = Geometry::MapTexCoords4;
02153             break;
02154         case Geometry::TexCoords5FieldId:
02155             beginEditCP(geo);
02156             {
02157                 tangentP = GeoTexCoords4f::create();
02158                 geo->setTexCoords5(tangentP);
02159             }
02160             endEditCP(geo);
02161             mapTan = Geometry::MapTexCoords5;
02162             break;
02163         case Geometry::TexCoords6FieldId:
02164             beginEditCP(geo);
02165             {
02166                 tangentP = GeoTexCoords4f::create();
02167                 geo->setTexCoords6(tangentP);
02168             }
02169             endEditCP(geo);
02170             mapTan = Geometry::MapTexCoords6;
02171             break;
02172         case Geometry::TexCoords7FieldId:
02173             beginEditCP(geo);
02174             {
02175                 tangentP = GeoTexCoords4f::create();
02176                 geo->setTexCoords7(tangentP);
02177             }
02178             endEditCP(geo);
02179             mapTan = Geometry::MapTexCoords7;
02180             break;
02181 
02182         case Geometry::PositionsFieldId:
02183         case Geometry::NormalsFieldId:
02184         case Geometry::ColorsFieldId:
02185         case Geometry::SecondaryColorsFieldId:
02186             FWARNING(("Case currently not treated, using NONE\n"));     
02187             dstAttribTan = -1;
02188               
02189         case -1:
02190             tangentP = GeoTexCoords4f::create();    // to be deleted
02191             break;
02192     }
02193     
02194     switch (dstAttribBin) 
02195     {
02196         case Geometry::TexCoordsFieldId:
02197             beginEditCP(geo);
02198             {
02199                 binormalP = GeoTexCoords4f::create();
02200                 geo->setTexCoords(binormalP);
02201             }
02202             endEditCP(geo);
02203             mapBin = Geometry::MapTexCoords;
02204             break;
02205         case Geometry::TexCoords1FieldId:
02206             beginEditCP(geo);
02207             {
02208                 binormalP = GeoTexCoords4f::create();
02209                 geo->setTexCoords1(binormalP);
02210             }
02211             endEditCP(geo);
02212             mapBin = Geometry::MapTexCoords1;
02213             break;
02214         case Geometry::TexCoords2FieldId:
02215             beginEditCP(geo);
02216             {
02217                 binormalP = GeoTexCoords4f::create();
02218                 geo->setTexCoords2(binormalP);
02219             }
02220             endEditCP(geo);
02221             mapBin = Geometry::MapTexCoords2;
02222             break;
02223         case Geometry::TexCoords3FieldId:
02224             beginEditCP(geo);
02225             {
02226                 binormalP = GeoTexCoords4f::create();
02227                 geo->setTexCoords3(binormalP);
02228             }
02229             endEditCP(geo);
02230             mapBin = Geometry::MapTexCoords3;
02231             break;
02232         case Geometry::TexCoords4FieldId:
02233             beginEditCP(geo);
02234             {
02235                 binormalP = GeoTexCoords4f::create();
02236                 geo->setTexCoords4(binormalP);
02237             }
02238             endEditCP(geo);
02239             mapBin = Geometry::MapTexCoords4;
02240             break;
02241         case Geometry::TexCoords5FieldId:
02242             beginEditCP(geo);
02243             {
02244                 binormalP = GeoTexCoords4f::create();
02245                 geo->setTexCoords5(binormalP);
02246             }
02247             endEditCP(geo);
02248             mapBin = Geometry::MapTexCoords5;
02249             break;
02250         case Geometry::TexCoords6FieldId:
02251             beginEditCP(geo);
02252             {
02253                 binormalP = GeoTexCoords4f::create();
02254                 geo->setTexCoords6(binormalP);
02255             }
02256             endEditCP(geo);
02257             mapBin = Geometry::MapTexCoords6;
02258             break;
02259         case Geometry::TexCoords7FieldId:
02260             beginEditCP(geo);
02261             {
02262                 binormalP = GeoTexCoords4f::create();
02263                 geo->setTexCoords7(binormalP);
02264             }
02265             endEditCP(geo);
02266             mapBin = Geometry::MapTexCoords7;
02267             break;
02268 
02269         case Geometry::PositionsFieldId:
02270         case Geometry::NormalsFieldId:
02271         case Geometry::ColorsFieldId:
02272         case Geometry::SecondaryColorsFieldId:
02273             FWARNING(("Case currently not treated, using NONE\n")); 
02274             dstAttribBin = -1;
02275                   
02276         case -1:
02277             binormalP = GeoTexCoords4f::create();
02278             break;
02279     }
02280     
02281     // can't eval what combination was meant
02282     if ( srcTexIndex < 0 || srcTexIndex > 3 || 
02283         (dstAttribTan == -1 && dstAttribBin == -1)) 
02284     {
02285         FFATAL(("Index set not supported in calcVertexTangents()\n"));
02286         return;
02287     }
02288     
02289     GeoIndicesPtr ip = geo->getIndices();
02290         
02291     // HACK but without indices it crashes
02292     if (ip == NullFC || ip->size() == 0) 
02293     {
02294         FFATAL(("Geo without indices in calcVertexTangents()\n"));
02295         return;
02296     }
02297     
02298     GeoPositionsPtr positions = geo->getPositions();
02299     
02300     // Get the positions property
02301     if (positions == NullFC) 
02302     {
02303         FFATAL(("Geo without positions in calcVertexTangents()\n"));
02304         return;
02305     }
02306 
02307     MFUInt16 &im = geo->getIndexMapping();
02308     Int16 niTan = (mapTan > 0) ? geo->calcMappingIndex(mapTan) : -1,
02309           niBin = (mapBin > 0) ? geo->calcMappingIndex(mapBin) : -1;
02310           
02311     Int32 indexMapSize = im.size(), j, imsize = 0;
02312     UInt32 i, val, nind = ip->size() / (indexMapSize ? indexMapSize : 1);
02313     bool multiIndex = (indexMapSize > 1) ? true : false;
02314     
02315     beginEditCP(geo, Geometry::IndexMappingFieldMask |
02316                      Geometry::IndicesFieldMask );
02317    
02318     if (multiIndex) 
02319     {
02320         // separate the attrib's index if exist
02321         if (niTan >= 0) 
02322             im[niTan] = im[niTan] & ~mapTan;
02323         if (niBin >= 0)
02324             im[niBin] = im[niBin] & ~mapBin; 
02325             
02326         // if im[ni] < 1 erase because index is unused
02327         MFUInt16::iterator imIt = im.begin();
02328         if (niTan == niBin) 
02329         {
02330             if (niTan >= 0 && im[niTan] < 1)
02331                 im.erase(imIt + niTan);
02332             else 
02333                 niTan = niBin = -1;    // not deleted
02334         }
02335         else if (niTan < niBin) 
02336         {
02337             if (niBin >= 0 && im[niBin] < 1)
02338                 im.erase(imIt + niBin);
02339             else 
02340                 niBin = -1;
02341             if (niTan >= 0 && im[niTan] < 1)
02342                 im.erase(imIt + niTan);
02343             else 
02344                 niTan = -1;
02345         }
02346         else 
02347         {
02348             if (niTan >= 0 && im[niTan] < 1)
02349                 im.erase(imIt + niTan);
02350             else 
02351                 niTan = -1;
02352             if (niBin >= 0 && im[niBin] < 1)
02353                 im.erase(imIt + niBin);
02354             else 
02355                 niBin = -1;
02356         }
02357 
02358         // create new mapping for attribs
02359         UInt16 map = 0;
02360         if (mapTan > 0)
02361             map |= mapTan;
02362         if (mapBin > 0)
02363             map |= mapBin;
02364         if (map > 0)
02365             im.push_back(map);
02366         imsize = im.size();
02367 
02368         // add an entry to the indices for the attribs        
02369         std::vector<UInt32> indexBuffer;
02370         int status, l = 0, g = 0, ibSize;
02371         
02372         if (niTan < 0 && niBin < 0) 
02373         {
02374             status = 0;
02375         }
02376         else if (niBin < 0 && niTan >= 0 || 
02377                  niBin >= 0 && niTan < 0 ||
02378                  niBin >= 0 && niBin == niTan) 
02379         {
02380             status = 1;
02381             l = (niBin < niTan) ? niTan : niBin;
02382         }
02383         else /*if (niBin > 0 && niTan > 0)*/ 
02384         {
02385             status = 2;
02386             l = (niBin < niTan) ? niBin : niTan;
02387             g = (niBin < niTan) ? niTan : niBin;
02388         }
02389         
02390         // discard positions l and g and provide index for tangent|binormal
02391         for (i=0; i<nind; i++) 
02392         {
02393             for (j=0; j<indexMapSize; j++) 
02394             {
02395                 switch (status) 
02396                 {
02397                     case 0:
02398                         indexBuffer.push_back(ip->getValue(i*indexMapSize+j));
02399                         break;
02400                     case 1: 
02401                         if (j != l)
02402                             indexBuffer.push_back(ip->getValue(i*indexMapSize+j));
02403                         break;
02404                     case 2:
02405                         if (j != l && j != g)
02406                             indexBuffer.push_back(ip->getValue(i*indexMapSize+j));
02407                         break;
02408                 }
02409             }
02410             indexBuffer.push_back(0);    // will be tangent|binormal index
02411         }
02412         ibSize = indexBuffer.size();
02413         
02414         beginEditCP(ip);
02415         {
02416             ip->clear();
02417             ip->resize(ibSize);
02418 
02419             for (i=0; i<ibSize; i++) 
02420                 ip->setValue(indexBuffer[i], i);
02421         }
02422         endEditCP(ip);
02423         
02424     } // multiIndex
02425     else
02426     {
02427         // add index map for single index.
02428         if(im.size() > 0)
02429             im[0] |= (mapTan | mapBin);
02430     }
02431 
02432     endEditCP(geo, Geometry::IndexMappingFieldMask |
02433                    Geometry::IndicesFieldMask );
02434     
02435     TriangleIterator tI;
02436     IndexDic indexDic;
02437     Int32 k, index, v[3];
02438     Vec4f vect(0, 0, 0, 0);
02439     
02440     std::vector<Int32>indexVec;
02441     Int16 niPos  = geo->calcMappingIndex(Geometry::MapPosition),
02442           niNorm = geo->calcMappingIndex(Geometry::MapNormal),
02443           niTex  = geo->calcMappingIndex(mapTex);
02444     
02445     indexVec.resize(3);    
02446     
02447     beginEditCP(ip);
02448 
02449     // calc max index.
02450     UInt32 maxindex = 0;
02451     for(i=0;i<ip->size();++i)
02452         maxindex = ip->getValue(i) > maxindex ? ip->getValue(i) : maxindex;
02453 
02454     // init property arrays
02455     // amz we can't use the indices size (nind) here!
02456     tangent.resize(maxindex + 1);
02457     binormal.resize(maxindex + 1);
02458     normal.resize(maxindex + 1);
02459 
02460     for (tI=geo->beginTriangles(), i=0; tI!=geo->endTriangles(); ++tI, ++i) 
02461     {         
02462         // first, get index for every vertex
02463         for (k=0; k<3; ++k) 
02464         {
02465             index = tI.getIndexIndex(k);
02466             
02467             if (multiIndex) 
02468             {
02469                 // make vertex unique with resp. to Position, Normal, TexCoord
02470                 for (j=0; j<imsize; j++) 
02471                 {
02472                     if (j == niPos || j == niNorm || j == niTex)
02473                         indexVec[j] = ip->getValue(index + j);
02474                 }
02475                 v[k] = indexDic.entry(indexVec);
02476             }
02477             else 
02478             {
02479                 v[k] = tI.getPositionIndex(k); //index;
02480             }
02481         }
02482         
02483         // second, calculate tangent and binormal for every tri
02484         Int32 v0 = tI.getPositionIndex(0),
02485               v1 = tI.getPositionIndex(1),
02486               v2 = tI.getPositionIndex(2);
02487         Vec2f t0, t1, t2, tex1, tex2;
02488         Vec3f edge1, edge2, sdir, tdir;
02489         
02490         switch (srcTexIndex) 
02491         {
02492             case 0:
02493                 t0 = tI.getTexCoords(0);
02494                 t1 = tI.getTexCoords(1);
02495                 t2 = tI.getTexCoords(2);
02496                 break;
02497             case 1:
02498                 t0 = tI.getTexCoords1(0);
02499                 t1 = tI.getTexCoords1(1);
02500                 t2 = tI.getTexCoords1(2);
02501                 break;
02502             case 2:
02503                 t0 = tI.getTexCoords2(0);
02504                 t1 = tI.getTexCoords2(1);
02505                 t2 = tI.getTexCoords2(2);
02506                 break;
02507             case 3:
02508                 t0 = tI.getTexCoords3(0);
02509                 t1 = tI.getTexCoords3(1);
02510                 t2 = tI.getTexCoords3(2);
02511                 break;
02512             case 4:
02513                 t0 = tI.getTexCoords4(0);
02514                 t1 = tI.getTexCoords4(1);
02515                 t2 = tI.getTexCoords4(2);
02516                 break;
02517             case 5:
02518                 t0 = tI.getTexCoords5(0);
02519                 t1 = tI.getTexCoords5(1);
02520                 t2 = tI.getTexCoords5(2);
02521                 break;
02522             case 6:
02523                 t0 = tI.getTexCoords6(0);
02524                 t1 = tI.getTexCoords6(1);
02525                 t2 = tI.getTexCoords6(2);
02526                 break;
02527             case 7:
02528                 t0 = tI.getTexCoords7(0);
02529                 t1 = tI.getTexCoords7(1);
02530                 t2 = tI.getTexCoords7(2);
02531                 break;
02532         }
02533         
02534         edge1 = tI.getPosition(1) - tI.getPosition(0),
02535         edge2 = tI.getPosition(2) - tI.getPosition(0);
02536         tex1 = t1 - t0;
02537         tex2 = t2 - t0;
02538 
02539         // in rare cases this is zero!
02540         Real32 invDet = (tex1[0]*tex2[1] - tex2[0]*tex1[1]);
02541         if(invDet != 0.0f)
02542             invDet = 1.0f / invDet;
02543         else
02544             invDet = 0.0f;
02545 
02546         sdir = invDet * (tex2[1]*edge1 - tex1[1]*edge2);    // tangent
02547         tdir = invDet * (tex1[0]*edge2 - tex2[0]*edge1);    // binormal
02548         
02549         // set value for every vertex
02550         int tanOffset = (imsize == 0) ? 0 : imsize-1;
02551         
02552         for (k=0; k<3; ++k) 
02553         {
02554             tangent[v[k]] += sdir;
02555             binormal[v[k]] += tdir;
02556             normal[v[k]] = tI.getNormal(k);
02557             ip->setValue(v[k], tI.getIndexIndex(k) + tanOffset); 
02558         }
02559     }
02560     endEditCP(ip);
02561     
02562     // orthogonalize vectors (Gram-Schmidt) and calc handedness    
02563     Vec3f T, B, N;
02564     Real32 sign = 0, l1, l2;
02565     tangentP->clear();
02566     binormalP->clear();
02567 
02568     beginEditCP(tangentP);
02569     beginEditCP(binormalP);
02570 
02571     for (i=0;i < tangent.size();++i)
02572     {
02573         T = tangent [i];
02574         B = binormal[i];
02575         N = normal  [i];    // must be normalized: n*n = 1
02576 
02577         sign = ((N.cross(T)).dot(B) < 0) ? -1 : 1;
02578         
02579         T = T - N.dot(T) * N;
02580         T.normalize();
02581         B = B - N.dot(B) * N - T.dot(B) * T;
02582         B.normalize(); 
02583         
02584         vect.setValues(T[0], T[1], T[2], sign);
02585         tangentP->getField().push_back(vect); 
02586         
02587         vect.setValues(B[0], B[1], B[2], sign);
02588         binormalP->getField().push_back(vect); 
02589     }
02590 
02591     endEditCP(tangentP);
02592     endEditCP(binormalP);
02593 }

Int32 osg::createOptimizedPrimitives ( GeometryPtr  geoPtr,
UInt32  iteration,
bool  createStrips,
bool  createFans,
UInt32  minFanEdgeCount,
bool  colorCode,
bool  stitchStrips 
)

createOptimizedPrimitives changes the Geometry to make it faster to render by creating triangle strips and fans, see Geometry Optimization for a description.

geoPtr is the Geometry to optimize and iteration is the number of iteratiosn that are tried to find the best solution. createStripes and createFans defines whether stripes, fans or both should be created, with minFanEdgeCount giving the number of adjacent edges a vertex need to be considered for a fan. For visualising the results, a random colorCode can be assigned to each generated primitive.

It returns the number of vertex transformations needed to render the Geometry.

Definition at line 2614 of file OSGGeoFunctions.cpp.

References osg::HalfEdgeGraph::addTriangle(), osg::beginEditCP(), osg::HalfEdgeGraph::calcOptPrim(), osg::calcPrimitiveCount(), osg::endEditCP(), IndexDic::entry(), IndexDic::entryCount(), FDEBUG, FINFO, FNOTICE, FWARNING, osg::HalfEdgeGraph::getPrimitive(), osg::getSystemTime(), osg::NullFC, osg::osgMin(), osg::HalfEdgeGraph::primitiveCount(), osg::HalfEdgeGraph::reserve(), and osg::HalfEdgeGraph::verify().

Referenced by osg::StripeGraphOp::travNodeEnter().

02621 {
02622     if (geoPtr == NullFC)
02623     {
02624         return 0;
02625     }
02626 
02627     HalfEdgeGraph graph;
02628 
02629     UInt32 cost = 0, startCost, bestCost = 0, worstCost = 0, best = 0;
02630 
02631     GeoPLengthsPtr lensPtr;
02632     GeoPTypesPtr geoTypePtr;
02633     Time time, inputT, optimizeT, outputT;
02634 
02635     IndexDic indexDic;
02636     int invalidTriCount = 0;
02637 
02638     GeoPositionsPtr posPtr = geoPtr->getPositions();
02639     UInt32 pN = ((posPtr == OSG::NullFC) ? 0 : posPtr->getSize());
02640     UInt32 indexMapSize = (geoPtr->getIndexMapping().size());
02641     bool remapIndex = (indexMapSize > 1) ? true : false;
02642 
02643     UInt32 triN, lineN, pointN;
02644     calcPrimitiveCount(geoPtr, triN, lineN, pointN);
02645 
02646     GeoIndicesPtr indexPtr = geoPtr->getIndices();
02647 
02648     // Calculate startCost.
02649     if(indexPtr == NullFC)
02650         startCost = pN;
02651     else
02652     {
02653         if(indexMapSize)
02654         {
02655             startCost = indexPtr->size() / indexMapSize;
02656         }
02657         else
02658             startCost = indexPtr->size();
02659     }
02660 
02661     // Leave early if we have no indices or positions.
02662     if (pN == 0 || indexPtr == NullFC)
02663     {
02664         return 0;
02665     }
02666     
02667     FDEBUG(("GeoOpt: start/tri cost: %d/%d imp: %d tri/line/point: %d/%d/%d\n",
02668             startCost, (triN * 3), indexMapSize, triN, lineN, pointN));
02669 
02670     inputT = getSystemTime();
02671 
02672     invalidTriCount = 0;
02673     
02674     if (!remapIndex && (pN > (triN * 3))) 
02675     {
02676         FINFO (( "Force index remap for unusual vertex/tri count: %d/%d\n",
02677                     pN, triN ));
02678         indexMapSize = 1;
02679         remapIndex = true;
02680     }
02681 
02682     if(remapIndex)
02683     {
02684         graph.reserve(triN * 3, triN, 8);
02685         std::vector < Int32 > indexVec(indexMapSize);
02686         UInt32 triCount = 0;
02687         for(TriangleIterator tI = geoPtr->beginTriangles(); (triCount < triN) && (tI != geoPtr->endTriangles());
02688                         ++tI)
02689         {
02690             Int32 v[3];
02691             for(Int32 i = 0; i < 3; i++)
02692             {
02693                 Int32 index = tI.getIndexIndex(i);
02694                 for(Int32 j = 0; j < indexMapSize; j++)
02695                 {
02696                     indexVec[j] = indexPtr->getValue(index + j);
02697                 }
02698 
02699                 v[i] = indexDic.entry(indexVec);
02700             }
02701 
02702             invalidTriCount += graph.addTriangle(v[0], v[1], v[2]) ? 0 : 1;
02703             ++triCount;
02704         }
02705 
02706         FDEBUG(("Multi-index dic entry: %d/%d\n", indexDic.entryCount(),
02707                                 (triN * 3)));
02708     }
02709     else
02710     {
02711         graph.reserve(osgMin(pN, triN * 3), triN, 8);
02712         UInt32 triCount = 0;
02713         for(TriangleIterator tI = geoPtr->beginTriangles(); (triCount < triN) && (tI != geoPtr->endTriangles());
02714                         ++tI)
02715         {
02716             invalidTriCount += graph.addTriangle(tI.getPositionIndex(0),
02717                                                  tI.getPositionIndex(1),
02718                                                  tI.getPositionIndex(2)) ? 0 : 1;
02719             ++triCount;
02720         }
02721     }
02722 
02723     if(invalidTriCount)
02724     {
02725         FNOTICE(("%d invalid tri during halfegde construction found\n",
02726                                  invalidTriCount));
02727     }
02728 
02729 #ifdef OSG_DEBUG
02730         graph.verify();
02731 #endif
02732 
02733     time = getSystemTime();
02734     inputT = time - inputT;
02735     optimizeT = time;
02736     bestCost = triN * 3 + 1;
02737     worstCost = 0;
02738     cost = graph.calcOptPrim(iteration, createStrips, createFans, minFanEdgeCount);
02739     if(cost)
02740     {
02741         if(cost < bestCost)
02742             bestCost = cost;
02743 
02744         if(cost > worstCost)
02745             worstCost = cost;
02746     }
02747     else
02748     {
02749         bestCost = worstCost = 0;
02750     }
02751 
02752     // valid result
02753     if(bestCost && (bestCost < startCost))
02754     {
02755         // check/create the indexPtr/lengthsPtr/geoTypePtr
02756         OSG::beginEditCP(geoPtr, OSG::Geometry::LengthsFieldMask |
02757                                      OSG::Geometry::TypesFieldMask);
02758 
02759         lensPtr = geoPtr->getLengths();
02760         if(lensPtr == OSG::NullFC)
02761         {
02762             lensPtr = OSG::GeoPLengthsUI32::create();
02763             geoPtr->setLengths(lensPtr);
02764         }
02765 
02766         geoTypePtr = geoPtr->getTypes();
02767         if(geoTypePtr == OSG::NullFC)
02768         {
02769             geoTypePtr = OSG::GeoPTypesUI8::create();
02770             geoPtr->setTypes(geoTypePtr);
02771         }
02772 
02773         OSG::endEditCP(geoPtr, OSG::Geometry::LengthsFieldMask |
02774                                OSG::Geometry::TypesFieldMask);
02775 
02776         time = getSystemTime();
02777         optimizeT = time - optimizeT;
02778         outputT = time;
02779 
02780         beginEditCP(lensPtr);
02781         beginEditCP(geoTypePtr);
02782         beginEditCP(indexPtr);
02783 
02784         lensPtr->clear();
02785         geoTypePtr->clear();
02786         indexPtr->clear();
02787 
02788         FDEBUG(("Start graph.getPrimitive() loop (triN: %d)\n", triN));
02789 
02790         UInt32 numPrimitives = graph.primitiveCount();
02791         std::vector<std::vector<UInt32> > primIndex(numPrimitives);
02792 
02793         const Int32 typeVec[] = { GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN };
02794         const Int32 typeN = sizeof(typeVec) / sizeof(Int32);
02795 
02796         cost = 0;
02797 
02798         for(Int32 t = 0; t < typeN; ++t)
02799         {
02800             UInt32 triCount = 0;
02801 
02802             bool stitch = false;
02803             UInt32 windingCorrection = 0;
02804             UInt32 lastTriStripIndex = 0;
02805             UInt32 totalTriStripLength = 0;
02806 
02807             for(Int32 i = 0; i < Int32(numPrimitives); ++i)
02808             {
02809                 graph.getPrimitive(primIndex[i], typeVec[t]);
02810                 const Int32 n = primIndex[i].size();
02811                 cost += n;
02812 
02813                 if(!n)
02814                 {
02815                     break;
02816                 }
02817 
02818                 if(typeVec[t] == GL_TRIANGLES)
02819                 {
02820                     triCount += (n / 3);
02821                 }
02822                 else if (typeVec[t] == GL_TRIANGLE_STRIP)
02823                 {
02824                     if (stitchStrips)
02825                     {
02826                         if (stitch)
02827                         {
02828                             // add the previous index and the first of the
02829                             // new one, but make sure winding is still correct.
02830                             if (remapIndex)
02831                             {
02832                                 for (int j = 0; j < 1 + windingCorrection; ++j)
02833                                 {
02834                                     for (int k = 0; k < indexMapSize; ++k)
02835                                     {
02836                                         indexPtr->push_back(indexDic.entry(lastTriStripIndex)[k]);
02837                                     }
02838                                 }
02839                                 for (int k = 0; k < indexMapSize; ++k)
02840                                 {
02841                                     indexPtr->push_back(indexDic.entry(primIndex[i][0])[k]);
02842                                 }
02843                             }
02844                             else
02845                             {
02846                                 for (int j = 0; j < 1 + windingCorrection; ++j)
02847                                 {
02848                                     indexPtr->push_back(lastTriStripIndex);
02849                                 }
02850                                 indexPtr->push_back(primIndex[i][0]);
02851                             }
02852                             totalTriStripLength += 2 + windingCorrection;
02853                         }
02854                         stitch = true;
02855                         windingCorrection = n % 2;
02856                         lastTriStripIndex = primIndex[i][n - 1];
02857                     }
02858                     else
02859                     {
02860                         lensPtr->push_back(n);
02861                         geoTypePtr->push_back(typeVec[t]);
02862                     }
02863                 }
02864                 else
02865                 {
02866                     lensPtr->push_back(n);
02867                     geoTypePtr->push_back(typeVec[t]);
02868                 }
02869 
02870                 if(remapIndex)
02871                 {
02872                     for(Int32 j = 0; j < n; ++j)
02873                     {
02874                         for(Int32 k = 0; k < indexMapSize; ++k)
02875                         {
02876                             Int32 index = indexDic.entry(primIndex[i][j])[k];
02877                             indexPtr->push_back(index);
02878                         }
02879                     }
02880                 }
02881                 else
02882                 {
02883                     for(Int32 j = 0; j < n; ++j)
02884                     {
02885                         indexPtr->push_back(primIndex[i][j]);
02886                     }
02887                 }
02888                 totalTriStripLength += n;
02889             }
02890 
02891             if(triCount && typeVec[t] == GL_TRIANGLES)
02892             {
02893                 lensPtr->push_back(triCount * 3);
02894                 geoTypePtr->push_back(GL_TRIANGLES);
02895             }
02896 
02897             if(stitchStrips && totalTriStripLength &&
02898                typeVec[t] == GL_TRIANGLE_STRIP)
02899             {
02900                 lensPtr->push_back(totalTriStripLength);
02901                 geoTypePtr->push_back(GL_TRIANGLE_STRIP);
02902             }
02903         }
02904 
02905         endEditCP(lensPtr);
02906         endEditCP(geoTypePtr);
02907         endEditCP(indexPtr);
02908 
02909         time = getSystemTime();
02910         outputT = time - outputT;
02911 
02912         FNOTICE(("Graph in/opt/out timing: %g/%g/%g \n", inputT, optimizeT,
02913                                 outputT));
02914 
02915         if(cost != bestCost)
02916         {
02917             FWARNING(("cost != bestCost: %d/%d; we lost some nodes !\n",
02918                                        cost, bestCost));
02919         }
02920         else
02921         {
02922             FINFO(("OptResult: %2g%%, Sampling (%di): cost %d/%d \n",
02923                                         double(double(bestCost) / double(
02924                                             startCost) * 100.0
02925                                 ), iteration, bestCost, worstCost));
02926         }
02927     }
02928     else
02929     {
02930         FINFO(("startCost (%d) <= bestCost (%d), triCost(%d); keep geo data\n",
02931                         startCost, bestCost, (triN * 3)));
02932     }
02933 
02934     return bestCost;
02935 }

void osg::createConvexPrimitives ( GeometryPtr  geoPtr  ) 

createConvexPrimitives iterates over all primitives of the passed geometry tesselating them with the aid of the GLU tesselator. As a result every planar polygon is tesselated into a sequence of triangles covering it.

In case of nonplanar Polygons the results are not guaranteed to be correct.

Simple, i.e non-indexed geometries are not supported.

Definition at line 3005 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::GeoProperty< GeoPropertyDesc >::create(), osg::FCPtr< BasePtrTypeT, FieldContainerTypeT >::dcast(), osg::endEditCP(), FDEBUG, FFATAL, FINFO, FWARNING, osg::PrimitiveIterator::getIndex(), osg::PrimitiveIterator::getIndexIndex(), osg::PrimitiveIterator::getLength(), osg::PrimitiveIterator::getType(), GLenum, osg::gluTessBeginDataCB(), gluTessEdgeFlagCB(), gluTessEndCB(), gluTessErrorCB(), osg::gluTessVertexDataCB(), and osg::NullFC.

Referenced by osg::VRMLGeometryDesc::endNode().

03006 {
03007   FINFO(("Entering createConvexPrimitives()\n"));
03008 
03009     GLenum windingRule = GLU_TESS_WINDING_ODD;
03010 
03011   OSG::GeoIndicesUI32Ptr       indexPtr;
03012   OSG::GeoIndicesUI32Ptr       newIndexPtr = GeoIndicesUI32::create();
03013   OSG::GeoPTypesPtr            newTypesPtr = GeoPTypesUI8::create();
03014   OSG::GeoPLengthsPtr          newLengthsPtr  = GeoPLengthsUI32::create();
03015 
03016   bool indexed = true;
03017 
03018   std::vector< UInt32 >    inIndexV;
03019   std::vector< UInt32 >    outIndexV;
03020   std::vector< GLdouble >  positionV;
03021 
03022   inIndexV.reserve(4096);  
03023   outIndexV.reserve(4096);
03024   positionV.reserve(4096);
03025 
03026   if(geoPtr == NullFC)
03027   {
03028       FINFO(("Invalid geoPtr in createConvexPrimitives()\n"));
03029       return;
03030   }
03031 
03032   //scan the geometry for GL_POLYGONs
03033   bool containsPolygon = false; 
03034   PrimitiveIterator primI = geoPtr->beginPrimitives();
03035   for(;primI != geoPtr->endPrimitives(); ++primI)
03036   {
03037       if(primI.getType() == GL_POLYGON)
03038       {
03039           containsPolygon = true;
03040           break;
03041       }
03042   }
03043 
03044   // skip geometry if it doesn't contain a GL_POLYGON
03045   if(!containsPolygon)
03046   {
03047       FINFO(("Geometry with no GL_POLYGONs in createConvexPrimitives:\n"));
03048       FINFO(("Nothing to do for createConvexPrimitives: Returning\n"));
03049       return;
03050   }
03051 
03052   // determine whether the geometry is indexed
03053   indexPtr =  GeoIndicesUI32Ptr::dcast(geoPtr->getIndices());
03054   indexed = (indexPtr == NullFC) ?  false : true;
03055   FDEBUG(("Indexed: %d\n",indexed));
03056 
03057   // skip geometry if it is empty or not indexed
03058   if(!indexed)
03059   {
03060       FINFO(("Skipping nonindexed geometry in createConvexPrimitives()\n"));
03061       return;
03062   }
03063   else
03064   {
03065       if(geoPtr->getIndices()->size() == 0)
03066       {
03067           FINFO(("Skipping empty geometry in createConvexPrimitives()\n")); 
03068           return;
03069       }
03070   }
03071 
03072   // convert function pointers to the type expected by the GLU Tesselator
03073   OSGGLUfuncptr gluTessBeginDataCBPtr = 
03074     reinterpret_cast<OSGGLUfuncptr>(gluTessBeginDataCB);
03075 
03076   OSGGLUfuncptr gluTessEdgeFlagCBPtr = 
03077     reinterpret_cast<OSGGLUfuncptr>(gluTessEdgeFlagCB);
03078 
03079   OSGGLUfuncptr gluTessVertexDataCBPtr = 
03080     reinterpret_cast<OSGGLUfuncptr>(gluTessVertexDataCB);
03081 
03082   OSGGLUfuncptr gluTessEndCBPtr = 
03083     reinterpret_cast<OSGGLUfuncptr>(gluTessEndCB);
03084 
03085   OSGGLUfuncptr gluTessErrorCBPtr = 
03086     reinterpret_cast<OSGGLUfuncptr>(gluTessErrorCB);
03087 
03088   // create and setup a new GLU Tesselator
03089   FDEBUG(("gluNewTess()\n"));
03090   GLUtesselator* tess = gluNewTess();
03091 
03092   if(tess == NULL)
03093   {
03094       FFATAL(("Creation of GLUtesselator failed\n"));
03095       return;
03096   }
03097   else
03098     FINFO(("Created GLU Tesselator (%p)\n", tess));
03099 
03100   // set the specified winding rule
03101   FDEBUG(("gluTessProperty(%p, GLU_TESS_WINDING_RULE, %d)\n",
03102           tess, windingRule));
03103   gluTessProperty(tess, GLU_TESS_WINDING_RULE, windingRule);
03104 
03105   // register self defined GLU Tesselator callback methods
03106   FDEBUG(("gluTessCallback(%p, GLU_TESS_ERROR, %p)\n", 
03107           tess, gluTessErrorCBPtr));
03108   gluTessCallback(tess, GLU_TESS_ERROR, gluTessErrorCBPtr);
03109 
03110   FDEBUG(("gluTessCallback(%p, GLU_TESS_BEGIN_DATA, %p)\n", 
03111           tess, gluTessBeginDataCBPtr));
03112   gluTessCallback(tess, GLU_TESS_BEGIN_DATA, gluTessBeginDataCBPtr);
03113 
03114   FDEBUG(("gluTessCallback(%p, GLU_TESS_EDGE_FLAG, %p)\n",
03115           tess, gluTessEdgeFlagCBPtr));
03116   gluTessCallback(tess, GLU_TESS_EDGE_FLAG, gluTessEdgeFlagCBPtr);
03117 
03118   FDEBUG(("gluTessCallback(%p, GLU_TESS_VERTEX_DATA, %p)\n",
03119           tess, gluTessVertexDataCBPtr));
03120   gluTessCallback(tess, GLU_TESS_VERTEX_DATA, gluTessVertexDataCBPtr);
03121 
03122   FDEBUG(("gluTessCallback(%p, GLU_TESS_END, %p)\n",
03123           tess, gluTessEndCBPtr));
03124   gluTessCallback(tess, GLU_TESS_END, gluTessEndCBPtr);
03125 
03126   beginEditCP(newTypesPtr);
03127   beginEditCP(newIndexPtr);
03128   beginEditCP(newLengthsPtr);
03129 
03130   primI = geoPtr->beginPrimitives();
03131   for(;primI != geoPtr->endPrimitives(); ++primI)
03132   {
03133       FDEBUG(("Primitive index: %d\n", primI.getIndex()));
03134       
03135       // if the primitive is not of type GL_POLYGON just copy its contents
03136       if(primI.getType() != GL_POLYGON)
03137       {
03138           FDEBUG(("Not a GL_POLYGON. Copying properties\n"));
03139           if(!indexed)
03140           {
03141               FWARNING(("createConvexPrimitives(): Nonindexed geometries are not implemented!\n"));
03142           }
03143           else
03144           {
03145               newTypesPtr->push_back(primI.getType());
03146 
03147               // maybe we should use memcpy here instead of explicitly copying
03148               // each multiindex
03149               for(UInt32 i = 0; i < primI.getLength(); i++)
03150               {
03151                   Int32 curIndex = primI.getIndexIndex(i);
03152                   for(UInt32 j = 0; j < geoPtr->getIndexMapping().size(); j++)
03153                   {
03154                       UInt32 val = indexPtr->getValue(curIndex + j);
03155                       newIndexPtr->push_back(val);
03156                   }
03157               }
03158               newLengthsPtr->push_back(primI.getLength());
03159           }
03160       }
03161       // Process GL_POLYGONs i.e. tesselate them
03162       else
03163       {
03164           FDEBUG(("Tesselating GL_POLYGON (PrimitiveIndex: %d, Vertices %d)\n",
03165                  primI.getIndex(), primI.getLength()));
03166 
03167           inIndexV.clear();  
03168           outIndexV.clear();
03169           positionV.clear();
03170           
03171           for(UInt32 i = 0; i < primI.getLength(); i++)
03172           {
03173               // Convert the vertices to double precision
03174               // (the tesselator expects them that way)
03175               positionV.push_back(static_cast< GLdouble >(primI.
03176                                                           getPosition(i)[0]));
03177               positionV.push_back(static_cast< GLdouble >(primI.
03178                                                           getPosition(i)[1]));
03179               positionV.push_back(static_cast< GLdouble >(primI.
03180                                                           getPosition(i)[2]));
03181 
03182               // Store the start index of the current multi index
03183               // to pass it as "meta data" to the tesselator later on
03184               UInt32 curIndex = indexed ? primI.getIndexIndex(i) : i;
03185               inIndexV.push_back(curIndex);
03186           }
03187 
03188 #ifdef OSG_DEBUG          
03189 
03190           for(UInt32 i = 0; i < primI.getLength(); i++) 
03191                     {
03192 
03193             int index = inIndexV.at(i);
03194             double x  = positionV.at(3*i); 
03195             double y  = positionV.at(3*i + 1); 
03196             double z  = positionV.at(3*i + 2);
03197 
03198             FDEBUG(("Position index: %i Position: (%f,%f,%f)\n", 
03199                     index, x, y, z));
03200           }
03201 #endif
03202 
03203           // cast the address of the std::vector which stores the 
03204           // tesselator output to a GLvoid *
03205           GLvoid* outIndexPtr = reinterpret_cast< GLvoid* >(&outIndexV);
03206 
03207           FDEBUG(("gluTessBeginPolygon(%p, %p)\n", tess, outIndexPtr));
03208           gluTessBeginPolygon(tess, outIndexPtr);
03209 
03210           FDEBUG(("gluTessBeginContour(%p)\n", tess));
03211           gluTessBeginContour(tess);
03212 
03213 
03214           for(UInt32 i = 0; i <  primI.getLength(); i++)
03215           {
03216               GLvoid* curIndexPtr = reinterpret_cast< GLvoid* >(&inIndexV[i]);
03217               FDEBUG(("gluTessVertex(%p, %p, %p)\n",
03218                       tess, &positionV[i * 3], curIndexPtr));
03219 
03220               // feed the prepared position data and the according beginning 
03221               // of its multiindex in the index property to the tesselator
03222               gluTessVertex(tess, &positionV[i * 3], curIndexPtr);
03223           }
03224 
03225           FDEBUG(("gluTessEndContour(%p)\n", tess));
03226           gluTessEndContour(tess);
03227 
03228           FDEBUG(("gluTessEndPolygon(%p)\n", tess));
03229           // trigger the tesselator action
03230           gluTessEndPolygon(tess); 
03231 
03232           newTypesPtr->push_back(GL_TRIANGLES);
03233           
03234           if(!indexed)
03235           {
03236               FWARNING(("createConvexPrimitives(): Nonindexed geometries are not implemented!\n"));
03237           }
03238           else
03239           {
03240               FDEBUG(("Rebuilding multi indices ...\n"));
03241               // copy the indices gathered during the tesselator run
03242               // into a new index container
03243               for(UInt32 i = 0; i < outIndexV.size(); i++)
03244               {
03245                   UInt32 vII = outIndexV[i];
03246                   for(UInt32 j = 0; j < geoPtr->getIndexMapping().size(); j++)
03247                   {
03248                       FDEBUG(("Index in tesselated data %d\n",vII + j));
03249                       Int32 curIndex = indexPtr->getValue(vII + j);
03250                       
03251                       FDEBUG(("newIndexPtr->push_back(%d)\n", curIndex));
03252                       newIndexPtr->push_back(curIndex);
03253                   }
03254               }
03255           }
03256           FINFO(("Vertex count: %d/%d (before/after tesselation)\n",
03257                  primI.getLength(), outIndexV.size()));
03258           newLengthsPtr->push_back(outIndexV.size());
03259       }
03260   }
03261   
03262   endEditCP(newTypesPtr);
03263   endEditCP(newIndexPtr);
03264   endEditCP(newLengthsPtr);
03265   
03266   beginEditCP(geoPtr);
03267 
03268   // update the geometry properties 
03269   geoPtr->setTypes(newTypesPtr);
03270   geoPtr->setIndices(newIndexPtr);
03271   geoPtr->setLengths(newLengthsPtr);
03272   
03273   endEditCP(geoPtr);
03274     
03275   FDEBUG(("gluDeleteTess(%p)\n", tess));
03276   gluDeleteTess(tess);
03277 
03278   FDEBUG(("Exiting from createConvexPrimitives()\n"));
03279 }

Int32 osg::createSharedIndex ( GeometryPtr  geoPtr  ) 

createSharedIndex tries to merge identical elements in the Geometry's Properties, see Geometry Optimization for a description.

Definition at line 3288 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::GeoProperty< GeoPropertyDesc >::create(), osg::endEditCP(), FFATAL, FINFO, FNOTICE, FWARNING, osg::GeoPropertyArrayInterface::getData(), osg::GeoPropertyArrayInterface::getDimension(), osg::GeoPropertyArrayInterface::getFormatSize(), osg::GeoPropertyArrayInterface::getStride(), iN, osg::Geometry::MapEmpty, osg::NullFC, and osg::GeoPropertyArrayInterface::size().

Referenced by osg::VRMLGeometryDesc::endNode(), osg::MergeGraphOp::processGeometries(), osg::OFFSceneFileType::read(), osg::OBJSceneFileType::read(), and osg::StripeGraphOp::travNodeEnter().

03289 {
03290 #ifndef OSG_SUPPORT_NO_GEO_INTERFACE
03291     UInt32 indexSharedCount = 0, dataRemapCount = 0, indexRemapCount = 0;
03292     UInt32 i, iN, index, si, sN;
03293     UInt32 indexMapSize, indexBlock = 0, masterDSize;
03294     GeoPropertyArrayInterface *masterProp = 0, *slaveProp = 0;
03295     UInt8 *masterData;
03296     std::vector < UInt32 > slaveDSizeVec;
03297     std::vector < UInt8 * > slaveDataVec;
03298 
03299     UInt16 mapMask, propMask, masterPropMask;
03300     typedef std::pair<UInt8 *, UInt32> Mem;
03301     Mem mem;
03302     std::map<Mem, UInt32, memless<Mem> > memMap;
03303     std::map<Mem, UInt32, memless<Mem> >::iterator mmI;
03304 
03305     GeoIndicesPtr indexPtr;
03306     UChar8 *dataElem;
03307     std::vector < Int32 > indexRemap;
03308 
03309     if(geoPtr != NullFC)
03310     {
03311         if(geoPtr->getPositions() != NullFC)
03312         {
03313             // check/create indexPtr
03314             iN = geoPtr->getPositions()->size();
03315             indexPtr = geoPtr->getIndices();
03316             if(indexPtr == NullFC)
03317             {
03318                 indexPtr = GeoIndicesUI32::create();
03319                 indexPtr->resize(iN);
03320                 for(i = 0; i < iN; i++)
03321                     indexPtr->setValue(i, i);
03322                 beginEditCP(geoPtr);
03323                 {
03324                     geoPtr->setIndices(indexPtr);
03325                 }
03326 
03327                 endEditCP(geoPtr);
03328             }
03329         }
03330         else
03331         {
03332             FNOTICE(("Invalid geoPtr->getPositions() in createSharedIndex()\n"));
03333         }
03334     }
03335     else
03336     {
03337         FNOTICE(("Invalid geoPtr in createSharedIndex()\n"));
03338     }
03339 
03340     if(indexPtr != NullFC)
03341     {
03342         // get the index count
03343         indexMapSize = geoPtr->getIndexMapping().size();
03344 
03345         // find first propMask;
03346         if(indexMapSize)
03347         {
03348             propMask = geoPtr->getIndexMapping()[0];
03349         }
03350         else
03351         {
03352             // no index geo; find valid property
03353             for(mapMask = 1, propMask = 0; mapMask && mapMask != Geometry::MapEmpty;
03354                             mapMask <<= 1)
03355             {
03356                 if(geoPtr->getProperty(mapMask))
03357                     propMask |= mapMask;
03358             }
03359 
03360             indexMapSize = 1;
03361         }
03362 
03363         // remap the index for a single index block
03364         for(indexBlock = 0; propMask;)
03365         {
03366             // reset stat counter
03367             indexSharedCount = 0;
03368             dataRemapCount = 0;
03369             indexRemapCount = 0;
03370 
03371             // find master property
03372             for(masterPropMask = 1; (propMask & masterPropMask) == 0;)
03373                 masterPropMask <<= 1;
03374 
03375             if((masterProp = geoPtr->getProperty(masterPropMask)) &&
03376                            (masterData = masterProp->getData()))
03377             {
03378                 // calc master data element size
03379                 masterDSize = masterProp->getFormatSize() *
03380                     masterProp->getDimension() +
03381                     masterProp->getStride();
03382 
03383                 // find and store slave property data and size
03384                 slaveDataVec.clear();
03385                 slaveDSizeVec.clear();
03386                 for(mapMask = 1; mapMask && mapMask != Geometry::MapEmpty;
03387                                     mapMask <<= 1)
03388                 {
03389                     if((mapMask != masterPropMask) && (mapMask & propMask))
03390                     {
03391                         if((slaveProp = geoPtr->getProperty(mapMask & propMask)))
03392                         {
03393                             slaveDataVec.push_back(slaveProp->getData());
03394                             slaveDSizeVec.push_back(slaveProp->getFormatSize() *
03395                                                                                 slaveProp->getDimension());
03396                         }
03397                         else
03398                         {
03399                             FWARNING(("Invalid slaveProp %d\n", (mapMask & propMask)
03400                                                        ));
03401                         }
03402                     }
03403                 }
03404 
03405                 sN = slaveDataVec.size();
03406                 iN = indexPtr->size() / indexMapSize;
03407                 memMap.clear();
03408                 indexRemap.clear();
03409                 indexRemap.resize(masterProp->size(), -1);
03410                 mem.second = masterProp->getFormatSize() * masterProp->getDimension();
03411 
03412                 for(i = 0; i < iN; i++)
03413                 {
03414                     index = indexPtr->getValue(i * indexMapSize + indexBlock);
03415                     if(indexRemap[index] >= 0)
03416                     {
03417                         if(indexRemap[index] == index)
03418                         {
03419                             indexSharedCount++;
03420                         }
03421                         else
03422                         {
03423                             indexPtr->setValue(indexRemap[index],
03424                                                                            i * indexMapSize + indexBlock);
03425                             indexRemapCount++;
03426                         }
03427                     }
03428                     else
03429                     {
03430                         // find/include the data block
03431                         dataElem = masterData + (index * masterDSize);
03432                         mem.first = dataElem;
03433                         mmI = memMap.find(mem);
03434                         if(mmI == memMap.end())
03435                         {
03436                             // index not found; store new data/index
03437                             memMap[mem] = index;
03438                             indexRemap[index] = index;
03439                         }
03440                         else
03441                         {
03442                             // data found; check slave property
03443                             for(si = 0; si < sN; si++)
03444                             {
03445                                 if(memcmp(slaveDataVec[si] + 
03446                                              (index * slaveDSizeVec[si]),
03447                                           slaveDataVec[si] +
03448                                              (mmI->second * slaveDSizeVec[si]),
03449                                           slaveDSizeVec[si]))
03450                                     break;
03451                             }
03452 
03453                             if(si == sN)
03454                             {
03455                                 // no or valid slave data; remap the index
03456                                 indexPtr->setValue(mmI->second,
03457                                                 i * indexMapSize + indexBlock);
03458                                 indexRemap[index] = mmI->second;
03459                                 dataRemapCount++;
03460                             }
03461                             else
03462                             {
03463                                 // invalid slave data; cannot remap index
03464                                 indexRemap[index] = index;
03465                             }
03466                         }
03467                     }
03468                 }
03469             }
03470             else
03471             {
03472                 FWARNING(("Invalid masterProp %p, mask: %d, block: %d\n",
03473                                            masterProp, propMask, indexBlock));
03474             }
03475 
03476             FINFO(("Create sharedIndex: %d/%d pass; "
03477                      "data/index remap: %d/%d \n",
03478                             indexBlock, int(propMask), dataRemapCount, 
03479                             indexRemapCount));
03480 
03481             // get next propery Mask
03482             if(++indexBlock < indexMapSize)
03483             {
03484                 propMask = geoPtr->getIndexMapping()[indexBlock];
03485             }
03486             else
03487                 propMask = 0;
03488         }
03489     }
03490 
03491     return indexRemapCount + dataRemapCount;
03492 
03493 #else
03494     FFATAL(("Cannot run createSharedIndex: NO_GEO_INFACE\n"));
03495     return -1;
03496 #endif
03497 }

Int32 osg::createSingleIndex ( GeometryPtr  geoPtr  ) 

createSingleIndex manipulates the Geometry's Properties to only use a single index, see Geometry Optimization for a description.

It returns the number of property values kept.

Definition at line 3508 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::endEditCP(), IndexDic::entry(), IndexDic::entryCount(), FFATAL, FWARNING, osg::GeoPropertyArrayInterface::getData(), osg::GeoPropertyArrayInterface::getDimension(), osg::GeoPropertyArrayInterface::getFormatSize(), osg::GeoPropertyArrayInterface::getStride(), osg::GeometryBase::IndexMappingFieldMask, osg::GeometryBase::IndicesFieldMask, osg::NullFC, osg::GeoPropertyArrayInterface::resize(), and osg::GeoPropertyArrayInterface::size().

03509 {
03510 #ifndef OSG_SUPPORT_NO_GEO_INTERFACE
03511     Int16 mask, maskID, finalMask = 0;
03512     Int32 indexMapSize, indexCount, i, j, vCount = 0;
03513     Int32 index;
03514     Int32 memSize, valueSize;
03515     UInt8 *pData, *data;
03516     GeoIndicesPtr indexPtr;
03517     IndexDic indexDic;
03518     std::vector < Int32 >
03519 
03520     indexVec, sIndex;
03521     GeoPropertyArrayInterface *pP = 0;
03522 
03523     if((geoPtr != NullFC) &&
03524            (indexMapSize = (geoPtr->getIndexMapping().size())))
03525     {
03526         beginEditCP(geoPtr, Geometry::IndexMappingFieldMask |
03527                             Geometry::IndicesFieldMask);
03528 
03529         indexPtr = geoPtr->getIndices();
03530         indexVec.resize(indexMapSize);
03531 
03532         // fill the indexDic
03533         if(indexPtr != NullFC)
03534         {
03535             indexCount = indexPtr->size() / indexMapSize;
03536             sIndex.resize(indexCount);
03537             for(i = 0; i < indexCount; i++)
03538             {
03539                 for(j = 0; j < indexMapSize; j++)
03540                 {
03541                     indexVec[j] = indexPtr->getValue(i * indexMapSize + j);
03542                 }
03543 
03544                 sIndex[i] = indexDic.entry(indexVec);
03545             }
03546 
03547             vCount = indexDic.entryCount();
03548         }
03549         else
03550             vCount = 0;
03551 
03552         // sort/copy property values
03553         finalMask = 0;
03554         if(vCount)
03555         {
03556             for(i = 0; i < indexMapSize; i++)
03557             {
03558                 mask = geoPtr->getIndexMapping()[i];
03559                 for(maskID = 1; maskID; maskID <<= 1)
03560                 {
03561                     if((mask & maskID) && (pP = geoPtr->getProperty(maskID)))
03562                     {
03563                         valueSize = pP->getFormatSize() *
03564                             pP->getDimension() +
03565                             pP->getStride();
03566                         finalMask |= maskID;
03567                         memSize = pP->size() * valueSize;
03568                         data = new UInt8[memSize];
03569                         pData = pP->getData();
03570                         memcpy(data, pData, memSize);
03571                         pP->resize(vCount);
03572                         pData = pP->getData();
03573                         for(j = 0; j < vCount; j++)
03574                         {
03575                             index = indexDic.entry(j)[i];
03576                             memcpy(pData + (valueSize * j),
03577                                                                data + (valueSize * index),
03578                                                                valueSize);
03579                         }
03580 
03581                         delete[] data;
03582                     }
03583                 }
03584             }
03585         }
03586 
03587         // copy single index and set the single mask
03588         if(finalMask)
03589         {
03590             indexPtr->clear();
03591             for(i = 0; i < indexCount; i++)
03592             {
03593                 indexPtr->push_back(sIndex[i]);
03594             }
03595 
03596             geoPtr->getIndexMapping().clear();
03597             geoPtr->getIndexMapping().push_back(finalMask);
03598         }
03599         else
03600         {
03601             FWARNING(("No valid finalMask in createSingleIndex()\n"));
03602         }
03603 
03604         endEditCP(geoPtr, Geometry::IndexMappingFieldMask |
03605                           Geometry::IndicesFieldMask);
03606     }
03607 
03608     return vCount;
03609 
03610 #else
03611     FFATAL(("Cannot run createSingleIndex: NO_GEO_INFACE\n"));
03612     return -1;
03613 #endif
03614 }

UInt32 osg::calcPrimitiveCount ( GeometryPtr  geoPtr,
UInt32 &  triangle,
UInt32 &  line,
UInt32 &  point 
)

calcPrimitiveCount calculates some statistical information about the Geometry, see Geometry Optimization for a description.

It returns the sum of the primitives found, and the separate counts in teh passed-in references.

Definition at line 3626 of file OSGGeoFunctions.cpp.

References osg::FCPtr< BasePtrTypeT, FieldContainerTypeT >::dcast(), FINFO, FWARNING, and osg::NullFC.

Referenced by osg::createOptimizedPrimitives(), and osg::Geometry::drawPrimitives().

03630 {
03631     GeoPTypesUI8Ptr geoTypePtr;
03632     GeoPLengthsUI32Ptr lens32Ptr;
03633     GeoPLengthsUI16Ptr lens16Ptr;
03634     GeoPTypesUI8Ptr::StoredObjectType::StoredFieldType::iterator typeI, endTypeI;
03635     GeoPLengthsUI32Ptr::StoredObjectType::StoredFieldType::iterator len32I;
03636     GeoPLengthsUI16Ptr::StoredObjectType::StoredFieldType::iterator len16I;
03637 
03638     UInt32 lN, tN, len, type;
03639 
03640     // TODO; should we really reset the values ?
03641     triangle = line = point = 0;
03642 
03643     if(geoPtr == OSG::NullFC)
03644     {
03645         FINFO(("No geo in calcPrimitiveCount\n"));
03646     }
03647     else
03648     {
03649         lens32Ptr = GeoPLengthsUI32Ptr::dcast(geoPtr->getLengths());
03650     
03651         if(lens32Ptr == NullFC)
03652         {
03653             lens16Ptr = GeoPLengthsUI16Ptr::dcast(geoPtr->getLengths());
03654             lN = (lens16Ptr == OSG::NullFC) ? 0 : lens16Ptr->getSize();
03655         }
03656         else
03657         {
03658             lN = (lens32Ptr == OSG::NullFC) ? 0 : lens32Ptr->getSize();
03659         }
03660 
03661         geoTypePtr = GeoPTypesUI8Ptr::dcast(geoPtr->getTypes());
03662         tN = (geoTypePtr == OSG::NullFC) ? 0 : geoTypePtr->getSize();
03663 
03664         if((tN == 0) || (lN != 0 && tN != lN) || (lN == 0 && tN != 1))
03665         {
03666             return 0;
03667         }
03668 
03669         typeI = geoTypePtr->getField().begin();
03670         if(lN != 0)
03671         {
03672             if(lens32Ptr != NullFC)
03673                 len32I = lens32Ptr->getField().begin();
03674             else
03675                 len16I = lens16Ptr->getField().begin();
03676         }
03677 
03678         endTypeI = geoTypePtr->getField().end();
03679         while(typeI != endTypeI)
03680         {
03681             type = *typeI;
03682             if(lN != 0)
03683             {
03684                 if(lens32Ptr != NullFC)
03685                     len = *len32I;
03686                 else
03687                     len = *len16I;
03688             }
03689             else
03690             {
03691                 GeoPositionsPtr pos = geoPtr->getPositions();
03692 
03693                 if(pos == OSG::NullFC)
03694                 {
03695                     FINFO(("calcPrimitiveCount: no Points!\n"));
03696                     return 0;
03697                 }
03698 
03699                 len = pos->size();
03700             }
03701 
03702             switch(type)
03703             {
03704             case GL_POINTS:
03705                 point += len;
03706                 break;
03707             case GL_LINES:
03708                 line += len / 2;
03709                 break;
03710             case GL_LINE_LOOP:
03711                 line += len;
03712                 break;
03713             case GL_LINE_STRIP:
03714                 line += len - 1;
03715                 break;
03716             case GL_TRIANGLES:
03717                 triangle += len / 3;
03718                 break;
03719             case GL_TRIANGLE_STRIP:
03720                 triangle += len - 2;
03721                 break;
03722             case GL_TRIANGLE_FAN:
03723                 triangle += len - 2;
03724                 break;
03725             case GL_QUADS:
03726                 triangle += len / 2;
03727                 break;
03728             case GL_QUAD_STRIP:
03729                 triangle += len - 2;
03730                 break;
03731             case GL_POLYGON:
03732                 triangle += len - 2;
03733                 break;
03734             default:
03735                 FWARNING(("calcPrimitiveCount(): Invalid geoType: %d\n", type));
03736                 break;
03737             }
03738 
03739             ++typeI;
03740             if (lN > 0)
03741             {
03742                 if(lens32Ptr != NullFC)
03743                     ++len32I;
03744                 else if(lens16Ptr != NullFC)
03745                     ++len16I;
03746             }
03747         }
03748     }
03749 
03750     return triangle + line + point;
03751 }

NodePtr osg::calcVertexNormalsGeo ( GeometryPtr  geo,
Real32  length 
)

calcVertexNormalsGeo creates a geometry object that shows the geo's normals, see Normal Visualisation for a description.

geo is the geometry whose normals should be displayed, length is the length of the normals. The new geometry is created in the local coordinate system of geo.

Definition at line 3766 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::GeometryBase::create(), osg::GeoProperty< GeoPropertyDesc >::create(), osg::endEditCP(), osg::PrimitiveIterator::getLength(), osg::PrimitiveIterator::getNormal(), osg::PrimitiveIterator::getPosition(), and osg::makeNodeFor().

03767 {
03768     GeoPositions3f::PtrType pnts = GeoPositions3f::create();
03769     // calculate
03770     beginEditCP(pnts);
03771 
03772     PrimitiveIterator   pi(geo);
03773 
03774     if(1 /* no easy way to check right now */ )
03775     {
03776         for(pi = geo->beginPrimitives(); pi != geo->endPrimitives(); ++pi)
03777         {
03778             for(UInt32 k = 0; k < pi.getLength(); k++)
03779             {
03780                 pnts->push_back(pi.getPosition(k));
03781                 pnts->push_back(pi.getPosition(k) + length * pi.getNormal(k));
03782             }
03783         }
03784     }
03785     else
03786     {
03787         Pnt3f   center(0, 0, 0);
03788 
03789         for(pi = geo->beginPrimitives(); pi != geo->endPrimitives(); ++pi)
03790         {
03791             for(UInt32 k = 0; k < pi.getLength(); k++)
03792             {
03793                 center[0] += pi.getPosition(k)[0];
03794                 center[1] += pi.getPosition(k)[1];
03795                 center[2] += pi.getPosition(k)[2];
03796             }
03797 
03798             pnts->push_back(center);
03799             pnts->push_back(center + length * pi.getNormal(0));
03800         }
03801     }
03802 
03803     endEditCP(pnts);
03804 
03805     GeoPTypesPtr type = GeoPTypesUI8::create();
03806     beginEditCP(type);
03807     type->push_back(GL_LINES);
03808     endEditCP(type);
03809 
03810     GeoPLengthsPtr lens = GeoPLengthsUI32::create();
03811     beginEditCP(lens);
03812     lens->push_back(pnts->getSize());
03813     endEditCP(lens);
03814 
03815     GeometryPtr g = Geometry::create();
03816     beginEditCP(g);
03817     g->setTypes(type);
03818     g->setLengths(lens);
03819     g->setPositions(pnts);
03820     endEditCP(g);
03821 
03822     return makeNodeFor(g);
03823 }

NodePtr osg::calcFaceNormalsGeo ( GeometryPtr  geo,
Real32  length 
)

calcFaceNormalsGeo creates a geometry object that shows the geo's normals, see Normal Visualisation for a description.

geo is the geometry whose normals should be displayed, length is the length of the normals. The new geometry is created in the local coordinate system of geo.

Definition at line 3840 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::GeoProperty< GeoPropertyDesc >::create(), osg::GeometryBase::create(), osg::Node::create(), osg::endEditCP(), osg::FaceIterator::getLength(), osg::FaceIterator::getNormal(), osg::FaceIterator::getPosition(), osg::PrimitiveIterator::getType(), and p.

03841 {
03842     NodePtr p = Node::create();
03843     GeometryPtr g = Geometry::create();
03844     GeoPositions3f::PtrType pnts = GeoPositions3f::create();
03845     GeoIndicesUI32Ptr index = GeoIndicesUI32::create();
03846     GeoPTypesPtr type = GeoPTypesUI8::create();
03847     GeoPLengthsPtr lens = GeoPLengthsUI32::create();
03848 
03849     // calculate
03850     FaceIterator faceIter = geo->beginFaces();
03851     Pnt3f center;
03852 
03853     beginEditCP(pnts);
03854     for(; faceIter != geo->endFaces(); ++faceIter)
03855     {
03856         center[0] = 0;
03857         center[1] = 0;
03858         center[2] = 0;
03859         for(UInt16 i = 0; i < faceIter.getLength(); ++i)
03860         {
03861             center[0] += faceIter.getPosition(i)[0] / faceIter.getLength();
03862             center[1] += faceIter.getPosition(i)[1] / faceIter.getLength();
03863             center[2] += faceIter.getPosition(i)[2] / faceIter.getLength();
03864         }
03865 
03866         pnts->push_back(center);
03867         switch(faceIter.getType())
03868         {
03869         case GL_TRIANGLE_STRIP:
03870             pnts->push_back(center + length * faceIter.getNormal(2));
03871             break;
03872         case GL_TRIANGLE_FAN:
03873             pnts->push_back(center + length * faceIter.getNormal(2));
03874             break;
03875         case GL_QUAD_STRIP:
03876             pnts->push_back(center + length * faceIter.getNormal(3));
03877             break;
03878         default:
03879             //does not matter which point's normal
03880             pnts->push_back(center + length * faceIter.getNormal(0));
03881             break;
03882         }
03883     }
03884 
03885     endEditCP(pnts);
03886 
03887     beginEditCP(index);
03888     for(UInt32 i = 0; i < pnts->getSize(); i++)
03889         index->push_back(i);
03890     endEditCP(index);
03891 
03892     beginEditCP(type);
03893     type->push_back(GL_LINES);
03894     endEditCP(type);
03895 
03896     beginEditCP(lens);
03897     lens->push_back(index->getSize());
03898     endEditCP(lens);
03899 
03900     beginEditCP(g);
03901     g->setTypes(type);
03902     g->setLengths(lens);
03903     g->setIndices(index);
03904     g->setPositions(pnts);
03905     endEditCP(g);
03906 
03907     beginEditCP(p);
03908     p->setCore(g);
03909     endEditCP(p);
03910 
03911     return p;
03912 }

void osg::separateProperties ( GeometryPtr  geo  ) 

Separates shared geometry properties.

Definition at line 3975 of file OSGGeoFunctions.cpp.

References separateProperty.

03976 {
03977     separateProperty(PTypes, Types)
03978     separateProperty(PLengths, Lengths)
03979     separateProperty(Positions, Positions)
03980     separateProperty(Normals, Normals)
03981     separateProperty(Colors, Colors)
03982     separateProperty(Colors, SecondaryColors)
03983     separateProperty(TexCoords, TexCoords)
03984     separateProperty(TexCoords, TexCoords1)
03985     separateProperty(TexCoords, TexCoords2)
03986     separateProperty(TexCoords, TexCoords3)
03987     separateProperty(TexCoords, TexCoords4)
03988     separateProperty(TexCoords, TexCoords5)
03989     separateProperty(TexCoords, TexCoords6)
03990     separateProperty(TexCoords, TexCoords7)
03991     separateProperty(Indices, Indices)
03992 }

void osg::drawVolume ( const DynamicVolume volume  ) 

Draw the given DynamicVolume using direct OpenGL calls.

Definition at line 65 of file OSGVolumeDraw.cpp.

References osg::DynamicVolume::getInstance().

Referenced by VolumeDrawWrapper::draw(), and osg::DrawActionBase::stop().

00066 {
00067     const Volume *v = &volume.getInstance();
00068     const BoxVolume *bv;
00069     const SphereVolume *sv;
00070     const CylinderVolume *cv;
00071     const FrustumVolume *fv;
00072 
00073     if((bv = dynamic_cast<const BoxVolume*>(v)))
00074     {
00075         drawVolume(*bv);
00076     }
00077     else if((sv = dynamic_cast<const SphereVolume*>(v)))
00078     {
00079         drawVolume(*sv);
00080     }
00081     else if((cv = dynamic_cast<const CylinderVolume*>(v)))
00082     {
00083         drawVolume(*cv);
00084     }
00085     else if((fv = dynamic_cast<const FrustumVolume*>(v)))
00086     {
00087         drawVolume(*fv);
00088     }
00089 }

void osg::drawVolume ( const BoxVolume volume  ) 

Draw the given BoxVolume using direct OpenGL calls.

Definition at line 95 of file OSGVolumeDraw.cpp.

References osg::BoxVolume::getBounds().

00096 {
00097     Pnt3f min,max;
00098     volume.getBounds(min, max);
00099 
00100     glBegin(GL_LINE_LOOP);
00101     glVertex3f(min[0], min[1], min[2]);   
00102     glVertex3f(max[0], min[1], min[2]);   
00103     glVertex3f(max[0], max[1], min[2]);   
00104     glVertex3f(min[0], max[1], min[2]);   
00105     glVertex3f(min[0], min[1], min[2]);   
00106     glVertex3f(min[0], min[1], max[2]);   
00107     glVertex3f(max[0], min[1], max[2]);   
00108     glVertex3f(max[0], max[1], max[2]);   
00109     glVertex3f(min[0], max[1], max[2]);   
00110     glVertex3f(min[0], min[1], max[2]);   
00111     glEnd();
00112 
00113     glBegin(GL_LINES);
00114     glVertex3f(min[0], max[1], min[2]);   
00115     glVertex3f(min[0], max[1], max[2]);   
00116     glVertex3f(max[0], max[1], min[2]);   
00117     glVertex3f(max[0], max[1], max[2]);   
00118     glVertex3f(max[0], min[1], min[2]);   
00119     glVertex3f(max[0], min[1], max[2]);   
00120     glEnd();
00121 
00122     return;
00123 }

void osg::drawVolume ( const SphereVolume volume  ) 

Draw the given SphereVolume using direct OpenGL calls.

NOTE: Not implemented yet!

Definition at line 131 of file OSGVolumeDraw.cpp.

References FWARNING.

00132 {
00133     FWARNING(("drawVolume(SphereVolume): not implemented yet!\n"));
00134     return;
00135 }

void osg::drawVolume ( const FrustumVolume volume  ) 

Draw the given FrustumVolume using direct OpenGL calls by intersecting near/far with the pairwise intersection of left/right and top/bottom.

Definition at line 142 of file OSGVolumeDraw.cpp.

References FWARNING, osg::FrustumVolume::getBottom(), osg::FrustumVolume::getFar(), osg::FrustumVolume::getLeft(), osg::FrustumVolume::getNear(), osg::FrustumVolume::getRight(), osg::FrustumVolume::getTop(), osg::Plane::intersect(), and osg::Plane::intersectInfinite().

00143 {
00144     Line lines[4];
00145     
00146     // calc the intersection lines between left/right/bottom/top
00147     if(volume.getLeft().intersect(volume.getTop(), lines[0]) == false)
00148     {
00149         FWARNING(("drawVolume(Frustum): left & top parallel ?!?\n"));
00150         return;
00151     }
00152     
00153     if(volume.getLeft().intersect(volume.getBottom(), lines[1]) == false)
00154     {
00155         FWARNING(("drawVolume(Frustum): left & bottom parallel ?!?\n"));
00156         return;
00157     }
00158     
00159     if(volume.getRight().intersect(volume.getTop(), lines[2]) == false)
00160     {
00161         FWARNING(("drawVolume(Frustum): right & top parallel ?!?\n"));
00162         return;
00163     }
00164     
00165     if(volume.getRight().intersect(volume.getBottom(), lines[3]) == false)
00166     {
00167         FWARNING(("drawVolume(Frustum): right & bottom parallel ?!?\n"));
00168         return;
00169     }
00170     
00171     // calc the intersection points
00172     Pnt3f pnts[8];
00173     
00174     if(volume.getNear().intersectInfinite(lines[0], pnts[0]) == false)
00175     {
00176         FWARNING(("drawVolume(Frustum): near & left/top parallel ?!?\n"));
00177         return;
00178     }
00179     
00180     if(volume.getFar().intersectInfinite(lines[0], pnts[1]) == false)
00181     {
00182         FWARNING(("drawVolume(Frustum): far & left/top parallel ?!?\n"));
00183         return;
00184     }
00185     
00186     if(volume.getNear().intersectInfinite(lines[1], pnts[2]) == false)
00187     {
00188         FWARNING(("drawVolume(Frustum): near & left/bottom parallel ?!?\n"));
00189         return;
00190     }
00191     
00192     if(volume.getFar().intersectInfinite(lines[1], pnts[3]) == false)
00193     {
00194         FWARNING(("drawVolume(Frustum): far & left/bottom parallel ?!?\n"));
00195         return;
00196     }
00197     
00198     if(volume.getNear().intersectInfinite(lines[2], pnts[4]) == false)
00199     {
00200         FWARNING(("drawVolume(Frustum): near & right/top parallel ?!?\n"));
00201         return;
00202     }
00203     
00204     if(volume.getFar().intersectInfinite(lines[2], pnts[5]) == false)
00205     {
00206         FWARNING(("drawVolume(Frustum): far & right/top parallel ?!?\n"));
00207         return;
00208     }
00209     
00210     if(volume.getNear().intersectInfinite(lines[3], pnts[6]) == false)
00211     {
00212         FWARNING(("drawVolume(Frustum): near & right/bottom parallel ?!?\n"));
00213         return;
00214     }
00215     
00216     if(volume.getFar().intersectInfinite(lines[3], pnts[7]) == false)
00217     {
00218         FWARNING(("drawVolume(Frustum): far & right/bottom parallel ?!?\n"));
00219         return;
00220     }
00221     
00222     // got the points, draw them
00223 
00224     glBegin(GL_LINE_LOOP);
00225     glVertex3fv(pnts[0].getValues());
00226     glVertex3fv(pnts[1].getValues());
00227     glVertex3fv(pnts[3].getValues());
00228     glVertex3fv(pnts[2].getValues());
00229     glVertex3fv(pnts[6].getValues());
00230     glVertex3fv(pnts[7].getValues());
00231     glVertex3fv(pnts[5].getValues());
00232     glVertex3fv(pnts[4].getValues());
00233     glEnd();
00234 
00235     glBegin(GL_LINES);
00236     glVertex3fv(pnts[0].getValues());
00237     glVertex3fv(pnts[2].getValues());
00238     glVertex3fv(pnts[1].getValues());
00239     glVertex3fv(pnts[5].getValues());
00240     glVertex3fv(pnts[2].getValues());
00241     glVertex3fv(pnts[6].getValues());
00242     glVertex3fv(pnts[4].getValues());
00243     glVertex3fv(pnts[6].getValues());
00244     glEnd();
00245 
00246     return;
00247 }

void osg::drawVolume ( const CylinderVolume volume  ) 

Draw the given CylinderVolume using direct OpenGL calls.

NOTE: Not implemented yet!

Definition at line 255 of file OSGVolumeDraw.cpp.

References FWARNING.

00256 {
00257     FWARNING(("drawVolume(CylinderVolume): not implemented yet!\n"));
00258     return;
00259 }

void osg::dropVolume ( DrawActionBase action,
NodePtr  node,
Color3f  col 
)

Draw the local Bounding Volume of the current Node given in the Action.

Definition at line 316 of file OSGVolumeDraw.cpp.

References VolumeDrawWrapper::drop().

Referenced by osg::ProxyGroup::draw(), osg::RenderAction::pushVisibility(), and osg::DrawActionBase::selectVisibles().

00317 {
00318     VolumeDrawWrapper::drop(action, node, col);
00319     return;
00320 }

void osg::dropVolume ( DrawActionBase action,
const DynamicVolume volume,
Color3f  col 
)

Draw the volume.

Definition at line 326 of file OSGVolumeDraw.cpp.

References VolumeDrawWrapper::drop().

00327 {
00328     VolumeDrawWrapper::drop(action, volume, col);
00329     return;
00330 }


Generated on Mon Mar 17 12:02:56 2008 for OpenSG by  doxygen 1.5.5