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

OSGExtrusionGeometry.inl

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *           Copyright (C) 2000,2001,2002 by the OpenSG Forum                *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 //-----------------------------------------------------------------------------
00040 //                                 Includes                                    
00041 //-----------------------------------------------------------------------------
00042 
00043 
00044 #include "OSGConfig.h"
00045 #include "OSGLog.h"
00046 #include "OSGExtrusionGeometry.h"
00047 
00048 #include <sstream>
00049 
00050 // #define DEBUG_SUBDIVISION
00051 // #define DEBUG_VERTEX_STORE
00052 // #define DEBUG_PROPERTY_STORE
00053 #define DEBUG_PRIMITIVE_STORE
00054 
00055 OSG_BEGIN_NAMESPACE
00056 
00057 
00058 //-----------------------------------------------------------------------------
00059 // Compare operator for vector types. Used to map properties with a
00060 // distance (taken component-wise) of less than Eps to the same index.
00061 //
00062 // Author: jbehr, afischle (cut'n pasted from OSGGeoFunctions.cpp) 
00063 //-----------------------------------------------------------------------------
00064 template<class type>
00065 inline bool ExtrusionSurface::vecless<type>::operator () (const type &a,
00066                                                           const type &b) const
00067 {
00068     UInt32  i;
00069     bool    ret = false;
00070     for(i = 0; i < type::_iSize; i++)
00071     {
00072         if(osgabs(a[i] - b[i]) < Eps)
00073             continue;
00074         if(a[i] > b[i])
00075         {
00076             ret = false;
00077             break;
00078         }
00079         ret = true;
00080         break;
00081     }
00082     return ret;
00083 }
00084 
00085 
00086 //-----------------------------------------------------------------------------
00087 //                     CP to SCP Transformation Helpers                        
00088 //-----------------------------------------------------------------------------
00089 
00090 //-----------------------------------------------------------------------------
00091 // Returns a pair of iterators pointing to spine[i-1] and spine[i+1] depending
00092 // on the topology of the spine. If the spine is closed, iterators are wrapped
00093 // around at the ends. If the spine is open, iterators are saturated at the
00094 // ends, i.e. the -1-th spine element is equal to the 0-th and the n-th is
00095 // equal to the (n-1)-th.
00096 //
00097 // Author: afischle
00098 //-----------------------------------------------------------------------------
00099 inline ExtrusionSurface::Pnt3fConstItPair 
00100 ExtrusionSurface::getPrevAndNextIt(const Pnt3fConstIt &pIt)
00101 {
00102     Pnt3fConstIt prevIt, nextIt;
00103     bool firstPoint = (pIt == _spine.begin()) ? true : false;
00104     bool lastPoint  = (pIt == _spine.end() - 1) ? true : false;
00105 
00106     if(!firstPoint && !lastPoint)   // it's an interior point
00107     {
00108         prevIt = pIt - 1;
00109         nextIt = pIt + 1;
00110     }
00111     else // either it's the first or the last point
00112     {
00113         if(_spineClosed)
00114         {
00115             prevIt = _spine.end() - 2;
00116             nextIt = _spine.begin() + 1;
00117         }
00118         else // spine is open
00119         {
00120             if(firstPoint)
00121             {
00122                 prevIt = _spine.begin();
00123                 nextIt = _spine.begin() + 1;
00124             }
00125             else // last point
00126             {
00127                 prevIt = _spine.end() - 2;
00128                 nextIt = _spine.end() - 1;
00129             }
00130         }
00131     }
00132     return Pnt3fConstItPair(prevIt, nextIt);
00133 }
00134 
00135 
00136 //-----------------------------------------------------------------------------
00137 // Returns the non-normalized y-axis of a CP to SCP transform at pIt
00138 // Author: afischle
00139 //-----------------------------------------------------------------------------
00140 inline Vec3f ExtrusionSurface::calcNonUnitYAxis(const Pnt3fConstIt &pIt)
00141 {
00142     /* X3D Spec:
00143      *
00144      * a. For all points other than the first or last: The Y-axis for spine[i]
00145      *    is found by normalizing the vector defined by
00146      *    (spine[i+1] - spine[i-1]). 
00147      * b. If the spine curve is closed: The SCP for the first and last points
00148      *    is the same and is found using (spine[1] - spine[n-2]) to compute
00149      *    the Y-axis.
00150      * c. If the spine curve is not closed: The Y-axis used for the first point
00151      *    is the vector from spine[0] to spine[1], and for the last it is the 
00152      *    vector from spine[n-2] to spine[n-1].
00153      */
00154 
00155     Pnt3fConstItPair prevAndNextIt = getPrevAndNextIt(pIt);
00156     Vec3f yAxis = *(prevAndNextIt.second) - *(prevAndNextIt.first);
00157     return yAxis;
00158 }
00159 
00160 
00161 //-----------------------------------------------------------------------------
00162 // Returns the non-normalized z-axis of a CP to SCP transform at pIt
00163 // Author: afischle
00164 //-----------------------------------------------------------------------------
00165 inline Vec3f ExtrusionSurface::calcNonUnitZAxis(const Pnt3fConstIt &pIt)
00166 {
00167     /* X3D Spec:
00168      *
00169      * The Z-axis is determined as follows:
00170      *
00171      * d.  For all points other than the first or last: Take the following 
00172      *     cross-product: Z = (spine[i+1] - spine[i]) x (spine[i-1] - spine[i])
00173      * e.  If the spine curve is closed: The SCP for the first and last points 
00174      *     is the same and is found by taking the following cross-product: 
00175      *     Z = (spine[1] - spine[0]) x (spine[n-2] - spine[0]) 
00176      * f.  If the spine curve is not closed: The Z-axis used for the first
00177      *     spine point is the same as the Z-axis for spine[1]. The Z-axis
00178      *     used for the last spine point is the same as the Z-axis for
00179      *     spine[n-2].
00180      * g.  After determining the Z-axis, its dot product with the Z-axis of
00181      *     the previous spine point is computed. If this value is negative,
00182      *     the Z-axis is flipped (multiplied by -1). In most cases,
00183      *     this prevents small changes in the spine segment angles from
00184      *     flipping the cross-section 180 degrees.
00185      */
00186 
00187     Pnt3fConstItPair prevAndNextIt = getPrevAndNextIt(pIt);
00188     Vec3f pToNext, pToPrev;
00189     pToNext = *(prevAndNextIt.second) - *pIt;
00190     pToPrev = *(prevAndNextIt.first) - *pIt;
00191 
00192     // If pIt points to the first or the last point the cross-product below
00193     // is zero because either pToNext or pToPrev is zero in this case.
00194     Vec3f zAxis = pToNext.cross(pToPrev);
00195     return zAxis;
00196 }
00197 
00198 
00199 //-----------------------------------------------------------------------------
00200 // Returns the unit length x-axis of a CP to SCP transform as the cross product
00201 // of the y- and z-axis stored in the matrix pointed to by mIt.
00202 //
00203 // Author: afischle
00204 //-----------------------------------------------------------------------------
00205 inline Vec3f ExtrusionSurface::calcXAxis(const MatrixConstIt &mIt)
00206 {
00207     Vec3f yAxis((*mIt)[1]);
00208     Vec3f zAxis((*mIt)[2]);
00209 
00210     Vec3f xAxis = yAxis.cross(zAxis);
00211     xAxis.normalize();
00212 
00213     return xAxis;
00214 }
00215 
00216 
00217 //-----------------------------------------------------------------------------
00218 //                            Subdivision schemes                              
00219 //-----------------------------------------------------------------------------
00220 
00221 
00222 //-----------------------------------------------------------------------------
00223 // Returns an interpolated vector to be inserted between points b and c,
00224 // obtained by applying the scheme (-1/16, 9/16, 9/16, -1/16)
00225 //
00226 // Author: afischle
00227 //-----------------------------------------------------------------------------
00228 template <class VectorTypeT> 
00229 inline VectorTypeT 
00230 apply4PtScheme(const typename std::vector<VectorTypeT>::const_iterator &a,
00231                const typename std::vector<VectorTypeT>::const_iterator &b,
00232                const typename std::vector<VectorTypeT>::const_iterator &c,
00233                const typename std::vector<VectorTypeT>::const_iterator &d)
00234 {
00235 
00236 #ifdef DEBUG_SUBDIVISION
00237      SLOG << "4ptScheme: interior: "
00238           << "( " << *a << " ) "
00239           << "(_" << *b << "_) " 
00240           << "( " << *c << " ) "
00241           << "( " << *d << " ) "
00242           << endl;
00243 #endif
00244 
00245     // return the weighted sum of the four points (a,b,c,d)
00246     return (-1.f/16.f) * (*a) 
00247         + ( 9.f/16.f) * (*b) 
00248         + ( 9.f/16.f) * (*c) 
00249         + (-1.f/16.f) * (*d);
00250 }
00251 
00252 
00253 //-----------------------------------------------------------------------------
00254 // Returns an interpolated vector to be inserted between points a and b,
00255 // obtained by applying the scheme (3/8, 6/8, -1/8)
00256 //
00257 // Author: afischle
00258 //-----------------------------------------------------------------------------
00259 template <class VectorTypeT>
00260 inline VectorTypeT 
00261 apply3PtScheme(const typename std::vector<VectorTypeT>::const_iterator &a,
00262                const typename std::vector<VectorTypeT>::const_iterator &b,
00263                const typename std::vector<VectorTypeT>::const_iterator &c)
00264 {
00265 
00266 #ifdef DEBUG_SUBDIVISION    
00267      SLOG << "3PtScheme: exterior"
00268           << "( " << *a << " ) "
00269           << "(_" << *b << "_) " 
00270           << "( " << *c << " ) "
00271           << endl;
00272 #endif
00273 
00274     // return the weighted sum of the three points (a,b,c)
00275     return ( 3.f/8.f) * (*a)
00276         + ( 6.f/8.f) * (*b)
00277         + (-1.f/8.f) * (*c);
00278 }
00279 
00280 
00281 //-----------------------------------------------------------------------------
00282 //                        Normals calculation helpers                          
00283 //-----------------------------------------------------------------------------
00284 
00285 
00286 //-----------------------------------------------------------------------------
00287 // Returns the right handed face normal of the triangle ABC if _ccw is true
00288 // and the negated one if _ccw is false.
00289 //
00290 // Author: afischle
00291 //-----------------------------------------------------------------------------
00292 inline Vec3f ExtrusionSurface::calcTriangleFaceNormal(const Pnt3f &a,
00293                                                       const Pnt3f &b,
00294                                                       const Pnt3f &c)
00295 {
00296     Vec3f d1 = b - a;
00297     Vec3f d2 = c - a;
00298     Vec3f faceNormal = _ccw ? d1.cross(d2) : d2.cross(d1);
00299 
00300     return faceNormal;
00301 }
00302 
00303 //-----------------------------------------------------------------------------
00304 // Returns the right handed unit-length face normal of the quad ABCD if _ccw
00305 // is true and the negated one if _ccw is false. If the four corners are not
00306 // the boundary of a surface, the return value is 0.
00307 //
00308 // Author: afischle
00309 //-----------------------------------------------------------------------------
00310 inline Vec3f ExtrusionSurface::calcQuadFaceNormal(const Pnt3f &a,
00311                                                   const Pnt3f &b,
00312                                                   const Pnt3f &c,
00313                                                   const Pnt3f &d)
00314 {
00315     Vec3f faceNormal = calcTriangleFaceNormal(a, b, d);
00316     if(faceNormal.length() > Eps)
00317     {
00318         faceNormal.normalize();
00319         return faceNormal;
00320     }
00321 
00322     faceNormal = calcTriangleFaceNormal(b, c, a);
00323     if(faceNormal.length() > Eps)
00324     {
00325         faceNormal.normalize();
00326         return faceNormal;
00327     }
00328 
00329     faceNormal = calcTriangleFaceNormal(c, d, b);
00330     if(faceNormal.length() > Eps)
00331     {
00332         faceNormal.normalize();
00333         return faceNormal;
00334     }
00335 
00336     // if we get here, the quad is completely degenerate and has no normal
00337     return Vec3f(0.f, 0.f, 0.f);
00338 }
00339 
00340 
00341 //-----------------------------------------------------------------------------
00342 // Calculates the vertex normal of a corner of a quad face. The quadrant
00343 // argument is used to deduce in which quadrant the quad lies from the point of
00344 // view of the vertex. The admissible quadrant arguments are 0,1,2,3.
00345 // The vertex normal is obtained by averaging all normals of adjacent faces
00346 // enclosing an angle less than the _creaseAngle with the face located at
00347 // the specified quadrant of the vertex.
00348 //
00349 // The result is stored in the normal component of the vertex pointed to by
00350 // vPtr.
00351 // 
00352 // Author: afischle
00353 //-----------------------------------------------------------------------------
00354 inline void ExtrusionSurface::calcVertexNormal(Vertex *vPtr, UInt32 quadrant)
00355 {
00356     assert(quadrant < 4);
00357     
00358     Vec3f refFN = vPtr->adjFaceNormals[quadrant];
00359 
00360     // set the vertex normal to the reference face normal
00361     vPtr->normal = refFN;    
00362 
00363     if(_creaseAngle < Eps)
00364     {   
00365         // we don't need to smooth across faces
00366         return;
00367     }
00368 
00369     // we need to smooth the normals
00370     for(UInt32 k = 0; k < 4; k++)
00371     {
00372         if(k != quadrant) // check the other 3 adjacent faces of the vertex 
00373         {
00374             Vec3f fN = vPtr->adjFaceNormals[k];
00375             if(refFN.enclosedAngle(fN) - Eps < _creaseAngle + Eps)
00376             {
00377                 vPtr->normal += fN;
00378             }
00379         }
00380     }
00381 
00382     vPtr->normal.normalize();
00383 }
00384 
00385 //-----------------------------------------------------------------------------
00386 //                          Geometry store helpers                             
00387 //-----------------------------------------------------------------------------
00388 
00389 
00390 
00391 
00392 
00393 //-----------------------------------------------------------------------------
00394 // Determines indices for the position, normal and texCoord components of a
00395 // vertex and stores them into the specified index field container. The indices
00396 // are stored in the following order:
00397 // 
00398 //   1. position index
00399 //   2. normal index (if _createNormals is true)
00400 //   3. texCoord index (if _createTexCoords is true)
00401 // 
00402 // Author: afischle
00403 //-----------------------------------------------------------------------------
00404 inline void ExtrusionSurface::storeVertex(const Vertex &vertex, 
00405                                           const GeoIndicesUI32Ptr indicesPtr)
00406 {
00407     assert(indicesPtr != NullFC);
00408 
00409 #ifdef DEBUG_VERTEX_STORE
00410     std::ostringstream strout;
00411     strout << "OSGExtrusion:storeVertex:Storing:" << std::endl;
00412     strout << "\t[ (Pos: " << vertex.position << ")" << std::endl;
00413 #endif
00414     
00415     // store position
00416     store(vertex.position, _posMap, indicesPtr);
00417 
00418     if(_createNormals)
00419     {
00420 #ifdef DEBUG_VERTEX_STORE        
00421         strout << "\t  (Normal:" << vertex.normal << ")" << std::endl;
00422 #endif
00423         // store normal
00424         store(vertex.normal, _normalMap, indicesPtr);
00425     }
00426     
00427     if(_createTexCoords)
00428     {
00429 #ifdef DEBUG_VERTEX_STORE        
00430         strout << "\t  (TexCoord:" << vertex.texCoord << ")" << std::endl;
00431 #endif
00432         // store texture coordinate
00433         store(vertex.texCoord, _texCoordMap, indicesPtr);
00434     }
00435     
00436     // increase the vertex count of the current primitive
00437     _vertexCount++;
00438     
00439 #ifdef DEBUG_VERTEX_STORE        
00440     strout << "\t  (vc:" << _vertexCount << "/tvc:" << _totalVertexCount << ")]";
00441     SLOG << strout.str() << std::endl;
00442 #endif
00443 }
00444 
00445 
00446 //-----------------------------------------------------------------------------
00447 // Stores the number of vertices of the current primitive and its specified
00448 // type into the specified field length and type field containers.
00449 //
00450 // Author: afischle
00451 //-----------------------------------------------------------------------------
00452 inline void ExtrusionSurface::storePrimitive(GLenum type, 
00453                                              GeoPLengthsUI32Ptr lensPtr, 
00454                                              GeoPTypesUI8Ptr    typesPtr)
00455 {
00456     assert(lensPtr != NullFC);
00457     assert(typesPtr != NullFC);
00458 
00459 #ifdef DEBUG_PRIMITIVE_STORE
00460     switch(type)
00461     {
00462         case GL_TRIANGLE_STRIP:
00463             assert(_vertexCount > 2);
00464             assert(_vertexCount % 2 == 0);
00465             break;
00466 
00467         case GL_TRIANGLE_FAN:
00468             assert(_vertexCount > 2);
00469             break;
00470             
00471         case GL_QUADS:
00472             assert(_vertexCount == 4);
00473             break;
00474             
00475         case GL_LINES:
00476             assert(_vertexCount == 2);
00477             break;
00478     };
00479 #endif
00480     
00481     if(_vertexCount != 0)
00482     {
00483         lensPtr->push_back(_vertexCount);
00484         typesPtr->push_back(type);
00485         _totalVertexCount += _vertexCount;
00486 
00487         // reset vertex count
00488         _vertexCount = 0;
00489 
00490         // increment primitive count (for stats only)
00491         _primitiveCount++;
00492     }
00493     else
00494     {
00495         FFATAL(("OSGExtrusion::storePrimitive: Tried to store empty primitive\n"));
00496     }
00497 }
00498 
00499 
00500 //-----------------------------------------------------------------------------
00501 // Computes a new index of type UInt32 for the specified property and
00502 // stores the (property -> index) pair in the specified pIndexMap of type
00503 // 'PType -> UInt32'. Two properties map to the same index iff their
00504 // componentwise distance is less than Eps.
00505 //
00506 // Author: afischle
00507 //-----------------------------------------------------------------------------
00508 template <typename PType> 
00509 inline UInt32 
00510 ExtrusionSurface::store(PType property, 
00511                         std::map<PType, UInt32, vecless<PType> > &pIndexMap)
00512 {
00513     typedef typename std::map<PType, 
00514                               UInt32,
00515                               vecless<PType> >::iterator   PTypeMapIterator;
00516     typedef typename std::map<PType, 
00517                               UInt32,
00518                               vecless<PType> >::value_type PTypeMapValueType;
00519     
00520     UInt32 newIndex = pIndexMap.size();
00521     const std::pair<PTypeMapIterator, bool>& result
00522         = pIndexMap.insert(PTypeMapValueType(property, newIndex));
00523 
00524 #ifdef DEBUG_PROPERTY_STORE
00525     std::ostringstream strout;
00526     strout << "OSGExtrusion:store: Storing property:" << std::endl;
00527     strout << "\t"
00528            << result.first->first << " -> " << result.first->second
00529            << " (new insert: " << (result.second ? "TRUE" : "FALSE") << ")";
00530     SLOG << strout.str() << std::endl;
00531 #endif
00532 
00533     // return index of property
00534     return result.first->second;
00535 }
00536 
00537 
00538 //-----------------------------------------------------------------------------
00539 // Stores the index of the property argument into the specified map and index
00540 // field container.
00541 //
00542 // Author: afischle
00543 //-----------------------------------------------------------------------------
00544 template <typename PType>
00545 inline void
00546 ExtrusionSurface::store(PType property, 
00547                         std::map<PType, UInt32, vecless<PType> > &propertyIndexMap,
00548                         GeoIndicesUI32Ptr indicesPtr)
00549 {
00550     assert(indicesPtr != NullFC);
00551     indicesPtr->push_back(store(property, propertyIndexMap));
00552 }
00553 
00554 
00555 OSG_END_NAMESPACE
00556 
00557 
00558 #define OSGEXTRUSIONGEOMETRY_INLINE_CVSID "@(#)$Id: OSGExtrusionGeometry.inl,v 1.2 2005/06/02 14:32:16 vossg Exp $"
00559 
00560 
00561 #ifdef DEBUG_SUBDIVISION
00562 #undef DEBUG_SUBDIVISION
00563 #endif
00564 
00565 #ifdef DEBUG_VERTEX_STORE
00566 #undef DEBUG_VERTEX_STORE
00567 #endif
00568 
00569 #ifdef DEBUG_PROPERTY_STORE
00570 #undef DEBUG_PROPERTY_STORE
00571 #endif
00572 
00573 #ifdef DEBUG_PRIMITIVE_STORE
00574 #undef DEBUG_PRIMITIVE_STORE
00575 #endif

Generated on Thu Aug 25 04:04:38 2005 for OpenSG by  doxygen 1.4.3