Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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::endEditCP(), osg::Plane::getNormal(), osg::TriangleIterator::getPosition(), osg::TriangleIterator::getPositionIndex(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize(), osg::NullFC, p, and osg::MField< FieldTypeT, fieldNameSpace >::size().

Referenced by osg::calcVertexNormals(), osg::VRMLGeometryPointSetDesc::endNode(), osg::VRMLGeometryDesc::endNode(), 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::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::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize(), osg::NullFC, osg::osgcos(), p, osg::Pi, osg::MField< FieldTypeT, fieldNameSpace >::push_back(), osg::MField< FieldTypeT, fieldNameSpace >::size(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::squareLength(), osg::VecStorage3< ValueTypeT >::x(), osg::VecStorage3< ValueTypeT >::y(), and osg::VecStorage3< ValueTypeT >::z().

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::VectorInterface< ValueTypeT, StorageInterfaceT >::cross(), osg::endEditCP(), osg::FaceIterator::getIndexIndex(), osg::FaceIterator::getLength(), osg::FaceIterator::getPosition(), osg::FaceIterator::getPositionIndex(), osg::PrimitiveIterator::getType(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::length(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize(), osg::NullFC, osg::MField< FieldTypeT, fieldNameSpace >::push_back(), and osg::MField< FieldTypeT, fieldNameSpace >::size().

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

Int32 osg::setIndexFromVRMLData GeometryPtr  geo,
std::vector< Int32 > &  coordIndex,
std::vector< Int32 > &  normalIndex,
std::vector< Int32 > &  colorIndex,
std::vector< Int32 > &  texCoordIndex,
bool  convex = true,
bool  ccw = true,
bool  normalPerVertex = true,
bool  colorPerVertex = true,
bool  createNormal = true,
bool  faceSet = true
 

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 936 of file OSGGeoFunctions.cpp.

References osg::setIndexFromIndexedX3DData().

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

00947 {
00948   Int32 primitiveType = faceSet ? GL_POLYGON : GL_LINE;
00949 
00950   return setIndexFromIndexedX3DData ( geoPtr,
00951                                       coordIndex,
00952                                       normalIndex,
00953                                       colorIndex,
00954                                       texCoordIndex,
00955                                       primitiveType,
00956                                       convex,
00957                                       ccw,
00958                                       normalPerVertex,
00959                                       colorPerVertex,
00960                                       createNormal );
00961 }

Int32 osg::setIndexFromIndexedX3DData GeometryPtr  geo,
std::vector< Int32 > &  coordIndex,
std::vector< Int32 > &  normalIndex,
std::vector< Int32 > &  colorIndex,
std::vector< Int32 > &  texCoordIndex,
Int32  primitiveType = GL_POLYGON,
bool  convex = true,
bool  ccw = true,
bool  normalPerVertex = true,
bool  colorPerVertex = true,
bool  createNormal = true
 

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!

define the bag type

defines the Index Types

holds the Index types as str, mainly for log/debug outputs

Definition at line 982 of file OSGGeoFunctions.cpp.

References osg::beginEditCP(), osg::endEditCP(), FDEBUG, FFATAL, FINFO, FNOTICE, FWARNING, and osg::NullFC.

Referenced by osg::setIndexFromVRMLData().

00993 {
00995     typedef std::vector<Int32>  *IndexBagP;
00996 
00998     enum IndexType
00999     {
01000         UNKNOWN_IT          = 0,
01001         EMPTY_IT,
01002         VERTEX_COORD_IT,
01003         VERTEX_IT,
01004         VERTEX_DUP_IT,
01005         VERTEX_CREATE_IT,
01006         PRIMITIVE_IT,
01007         PRIMITIVE_INDEX_IT,
01008         PRIMITIVE_CREATE_IT
01009     };
01010 
01012     static const char *indexTypeStr[] =
01013     {
01014         "UNKNOWN_IT",
01015         "EMPTY_IT",
01016         "VERTEX_COORD_IT",
01017         "VERTEX_IT",
01018         "VERTEX_DUP_IT",
01019         "VERTEX_CREATE_IT",
01020         "PRIMTIVE_IT",
01021         "PRIMITIVE_INDEX_IT",
01022         "PRIMITIVE_CREATE_IT"
01023     };
01024     OSG::GeoPositionsPtr posPtr;
01025     OSG::GeoNormalsPtr normalPtr;
01026     OSG::GeoColorsPtr colorPtr;
01027     OSG::GeoTexCoordsPtr texCoordsPtr;
01028     OSG::GeoPLengthsPtr lensPtr;
01029     OSG::GeoPTypesPtr geoTypePtr;
01030     OSG::GeoIndicesPtr indexPtr;
01031 
01032     //bool faceSet = (primitiveType == GL_POLYGON);
01033     Int32 index, i, pi, typei, mapi, primitiveN = 0, vN = 0;
01034     Int32 pType = 0, localPType;
01035     Int32 maxPType; //  = (faceSet ? 5 : 3);
01036     Int32 minPType; //  = (faceSet ? 3 : 2);
01037     Int32 beginIndex, endIndex, step, len, sysPType = 0;
01038     Int32 piN = 0, ciN = 0, niN = 0, tiN = 0;
01039     Int32 pN = 0, nN = 0, cN = 0, tN = 0, tN1 = 0, tN2 = 0, tN3 = 0;
01040     IndexType indexType[4];
01041     IndexType &coordIT = indexType[0];
01042     IndexType &normalIT = indexType[1];
01043     IndexType &colorIT = indexType[2];
01044     IndexType &textureIT = indexType[3];
01045     Int32 primitiveTypeCount[6];
01046     UInt32 triCount = 0;
01047     Int16 indexMap[4], indexMapID[4];
01048     UInt32 uiNumTextures = 0;
01049 
01050     IndexBagP indexBag[4] =
01051     {
01052         &coordIndex,
01053         &normalIndex,
01054         &colorIndex,
01055         &texCoordIndex
01056     };
01057 
01058     //----------------------------------------------------------------------
01059     // init
01060     coordIT = VERTEX_IT;
01061     indexMap[0] = Geometry::MapPosition;
01062 
01063     //----------------------------------------------------------------------
01064     // set maxPType and minPTypr from primitiveType
01065     switch (primitiveType) {
01066     case GL_POINTS:
01067       minPType = 1;
01068       maxPType = 1;
01069       break;
01070     case GL_LINES:
01071       minPType = 2;
01072       maxPType = 3;
01073       break;
01074     case GL_LINE_STRIP:
01075       minPType = 2;
01076       maxPType = 3;
01077       break;
01078     case GL_LINE_LOOP:
01079       minPType = 2;
01080       maxPType = 3;
01081       break;
01082     case GL_TRIANGLES:
01083       minPType = 3;
01084       maxPType = 3;
01085       break;
01086     case GL_TRIANGLE_STRIP:
01087       minPType = 3;
01088       maxPType = 3;
01089       break;
01090     case GL_TRIANGLE_FAN:
01091       minPType = 3;
01092       maxPType = 3;
01093       break;
01094     case GL_QUADS:
01095       minPType = 3;
01096       maxPType = 4;
01097       break;
01098     case GL_QUAD_STRIP:    
01099       minPType = 3;
01100       maxPType = 4;
01101       break;
01102     case GL_POLYGON:
01103       minPType = 3;
01104       maxPType = 5;
01105       break;
01106     default:
01107       FFATAL (( "Can not fill index; Invalid primitiveType: %d\n",
01108                 primitiveType ));
01109       break;
01110     }
01111       
01112 
01113     //----------------------------------------------------------------------
01114     // get the property pointer and element count
01115     posPtr = geoPtr->getPositions();
01116     pN = ((posPtr == OSG::NullFC) ? 0 : posPtr->getSize());
01117 
01118     normalPtr = geoPtr->getNormals();
01119     nN = ((normalPtr == OSG::NullFC) ? 0 : normalPtr->getSize());
01120 
01121     colorPtr = geoPtr->getColors();
01122     cN = ((colorPtr == OSG::NullFC) ? 0 : colorPtr->getSize());
01123 
01124     texCoordsPtr = geoPtr->getTexCoords();
01125     tN = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01126 
01127     texCoordsPtr = geoPtr->getTexCoords1();
01128     tN1 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01129 
01130     texCoordsPtr = geoPtr->getTexCoords2();
01131     tN2 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01132 
01133     texCoordsPtr = geoPtr->getTexCoords3();
01134     tN3 = ((texCoordsPtr == OSG::NullFC) ? 0 : texCoordsPtr->getSize());
01135 
01136     FDEBUG(("vertex attrib count P/N/C/T: %d/%d/%d/%d\n", pN, nN, cN, tN));
01137 
01138     //----------------------------------------------------------------------
01139     // check the vertex index and count the primitives
01140     primitiveN = index = 0;
01141     for(pType = 0; pType < 6; pType++)
01142         primitiveTypeCount[pType] = 0;
01143 
01144     if(!pN)
01145     {
01146         FINFO(("No points in OSG::setIndexFromVRMLData()\n"));
01147         return 0;
01148     }
01149     else
01150     {
01151         piN = coordIndex.size();
01152         if(piN)
01153         {
01154             for(i = 0; i <= piN; i++)
01155             {
01156                 index = (i == piN) ? -1 : coordIndex[i];
01157                 if((index < 0) && vN)
01158                 {
01159                     primitiveTypeCount[(vN > maxPType) ? maxPType : vN]++;
01160                     primitiveN++;
01161                     vN = 0;
01162                 }
01163                 else
01164                 {
01165                     if(index >= pN && i != piN)
01166                     {
01167                         FWARNING(("Point index (%d/%d) out of range", index, pN));
01168                         coordIndex[i] = 0;
01169                     }
01170 
01171                     vN++;
01172                 }
01173             }
01174         }
01175         else
01176         {
01177             FWARNING(("No coordIndex in OSG::setIndexFromVRMLData()\n"));
01178             return 0;
01179         }
01180     }
01181 
01182     //----------------------------------------------------------------------
01183     // check the normal index
01184     normalIT = UNKNOWN_IT;
01185     niN = normalIndex.size();
01186     if(nN)
01187     {               // have normal elements
01188         if(normalPerVertex)
01189         {
01190             // normal per vertex
01191             if(niN >= piN)
01192             {
01193                 // valid normal index number
01194                 for(i = 0; i < piN; i++)
01195                 {   // check if normal index equals the coord index
01196                     if(normalIndex[i] != coordIndex[i])
01197                     {
01198                         normalIT = VERTEX_IT;
01199                         break;
01200                     }
01201                 }
01202 
01203                 if(normalIT == UNKNOWN_IT)
01204                 {
01205                     // if equal than delete unneeded normal index
01206                     normalIT = VERTEX_DUP_IT;
01207                 }
01208             }
01209             else
01210             {
01211                 // no or not enough normal index
01212                 normalIT = VERTEX_COORD_IT;
01213                 if(niN)
01214                 {
01215                     FWARNING(("Not enough normal index (%d,%d)\n", normalIndex.
01216                                                      size(), piN));
01217                     normalIndex.clear();
01218                 }
01219             }
01220         }
01221         else
01222         {
01223             // normal per primitive
01224             if(niN >= primitiveN)
01225             {
01226                 // use one normal index per primitive
01227                 normalIT = PRIMITIVE_INDEX_IT;
01228             }
01229             else
01230             {
01231                 if(nN >= primitiveN)
01232                 {
01233                     // use one normal per primitive
01234                     normalIT = PRIMITIVE_IT;
01235                 }
01236                 else
01237                 {
01238                     FINFO(("not enough normal index (%d,%d)\n", nN, primitiveN));
01239                 }
01240             }
01241         }
01242     }
01243     else
01244     {
01245         /* not yet !!!
01246 if (createNormal)
01247   if (normalPerVertex)
01248     normalIT = VERTEX_CREATE_IT;
01249   else
01250     normalIT = PRIMITIVE_CREATE_IT;
01251 else
01252 */
01253         normalIT = EMPTY_IT;
01254     }
01255 
01256     //----------------------------------------------------------------------
01257     // check the color index
01258     colorIT = UNKNOWN_IT;
01259     ciN = colorIndex.size();
01260     if(cN)
01261     {               // have color elements
01262         if(colorPerVertex)
01263         {
01264             // color per vertex
01265             if(ciN >= piN)
01266             {
01267                 // valid color index number
01268                 for(i = 0; i < piN; i++)
01269                 {   // check if color index equals the coord index
01270                     if(colorIndex[i] != coordIndex[i])
01271                     {
01272                         colorIT = VERTEX_IT;
01273                         break;
01274                     }
01275                 }
01276 
01277                 if(colorIT == UNKNOWN_IT)
01278                 {
01279                     // if equal than delete unneeded color index
01280                     colorIT = VERTEX_DUP_IT;
01281                 }
01282             }
01283             else
01284             {
01285                 // no or not enough color index
01286                 colorIT = VERTEX_COORD_IT;
01287                 if(ciN)
01288                 {
01289                     FWARNING(("Not enough color index (%d,%d)\n", colorIndex.
01290                                                      size(), piN));
01291                     colorIndex.clear();
01292                 }
01293             }
01294         }
01295         else
01296         {
01297             // color per primitive
01298             if(ciN >= primitiveN)
01299             {
01300                 // use one color index per primitive
01301                 colorIT = PRIMITIVE_INDEX_IT;
01302             }
01303             else
01304             {
01305                 if(cN >= primitiveN)
01306                 {
01307                     // use one color per primitive
01308                     colorIT = PRIMITIVE_IT;
01309                 }
01310                 else
01311                 {
01312                     FINFO(("not enough color index (%d,%d)\n", cN, primitiveN));
01313                 }
01314             }
01315         }
01316     }
01317     else
01318     {
01319         colorIT = EMPTY_IT;
01320     }
01321 
01322     //----------------------------------------------------------------------
01323     // check the texture index
01324     textureIT = UNKNOWN_IT;
01325     tiN = texCoordIndex.size();
01326     if(tN)
01327     {               // have texture elemnts
01328         if(tiN >= piN)
01329         {
01330             // valid texture index number
01331             for(i = 0; i < piN; i++)
01332             {       // check if texture index equals the coord index
01333                 if(texCoordIndex[i] != coordIndex[i])
01334                 {
01335                     textureIT = VERTEX_IT;
01336                     break;
01337                 }
01338             }
01339 
01340             if(textureIT == UNKNOWN_IT)
01341             {
01342                 // if equal than delete unneeded texture index
01343                 textureIT = VERTEX_DUP_IT;
01344             }
01345         }
01346         else
01347         {
01348             // no or not enough texture index
01349             textureIT = VERTEX_COORD_IT;
01350             if(ciN)
01351             {
01352                 FWARNING(("Not enough texCoord index (%d,%d)\n", texCoordIndex.
01353                                              size(), piN));
01354                 texCoordIndex.clear();
01355             }
01356         }
01357     }
01358     else
01359     {
01360         textureIT = EMPTY_IT;
01361     }
01362 
01363     FNOTICE (( "primitiveN:  %d,