osg::ExtrusionSurface Class Reference

Encapsulates the data of an X3D extrusion surface Not intended to be directly used. Use construction functions makeExtrusion and makeExtrusionGeo instead.

#include <OSGExtrusionGeometry.h>

List of all members.

Public Member Functions

Constructors


 ExtrusionSurface (const std::vector< Pnt2f > &crossSection, const std::vector< Quaternion > &orientation, const std::vector< Vec2f > &scale, const std::vector< Pnt3f > &spine, Real32 creaseAngle=0.f, bool beginCap=true, bool endCap=true, bool ccw=true, bool convex=true, bool buildNormal=true, bool buildTexCoord=true)
 Constructor initializing an extrusion surface.
Access


GeometryPtr createGeometry (UInt32 nSubDivisions)
 Creates a multi-indexed Geometry representing the extrusion surface Invoked by the construction function makeExtrusionGeo and makeExtrusion.

Private Types

typedef std::vector< Pnt3f >
::const_iterator 
Pnt3fConstIt
typedef std::vector< Matrix >
::const_iterator 
MatrixConstIt
typedef std::pair
< Pnt3fConstIt, Pnt3fConstIt
Pnt3fConstItPair
typedef std::vector
< std::vector< Vertex > > 
VertexGrid
typedef std::map< Pnt3f,
UInt32, vecless< Pnt3f > > 
PositionMap
typedef std::map< Vec3f,
UInt32, vecless< Vec3f > > 
NormalMap
typedef std::map< Vec2f,
UInt32, vecless< Vec2f > > 
TexCoordMap

Private Member Functions

 ExtrusionSurface (const ExtrusionSurface &source)
 prohibit default function (move to 'public' if needed)
void operator= (const ExtrusionSurface &source)
 prohibit default function (move to 'public' if needed)
void calcXAxes (void)
void calcYAxes (void)
void calcZAxes (void)
void calcTransforms (void)
void calcSweepSurfacePositions (void)
void calcSweepSurfaceFaceNormals (void)
void calcSweepSurfaceTexCoords (void)
void determineTopology (void)
void initGrid (void)
bool verifyInput (void)
void refineCrossSection (UInt32 nTimes)
void refineOrientation (UInt32 nTimes)
void refineScale (UInt32 nTimes)
void refineSpine (UInt32 nTimes)
void storeConvexCap (UInt32 spineIndex, bool invertNormal, GeoIndicesUI32Ptr indicesPtr, GeoPLengthsUI32Ptr lensPtr, GeoPTypesUI8Ptr typesPtr)
void storeSweepSurfaceWithNormals (GeoIndicesUI32Ptr indicesPtr, GeoPLengthsUI32Ptr lensPtr, GeoPTypesUI8Ptr typesPtr)
void storeSweepSurfaceWithoutNormals (GeoIndicesUI32Ptr indicesPtr, GeoPLengthsUI32Ptr lensPtr, GeoPTypesUI8Ptr typesPtr)
void storeMaps (GeoPositions3fPtr positionsPtr, GeoNormals3fPtr normalsPtr, GeoTexCoords2fPtr texCoordsPtr)
void storeVertex (const Vertex &vertex, GeoIndicesUI32Ptr indicesPtr)
void storePrimitive (GLenum type, GeoPLengthsUI32Ptr lensPtr, GeoPTypesUI8Ptr typesPtr)
template<typename PType>
UInt32 store (PType property, std::map< PType, UInt32, vecless< PType > > &propertyIndexMap)
template<typename PType>
void store (const PType property, std::map< PType, UInt32, vecless< PType > > &propertyIndexMap, GeoIndicesUI32Ptr indicesPtr)
Pnt3fConstItPair getPrevAndNextIt (const Pnt3fConstIt &pIt)
Vec3f calcNonUnitYAxis (const Pnt3fConstIt &pIt)
Vec3f calcNonUnitZAxis (const Pnt3fConstIt &pIt)
Vec3f calcXAxis (const MatrixConstIt &pIt)
Vec3f calcTriangleFaceNormal (const Pnt3f &a, const Pnt3f &b, const Pnt3f &c)
Vec3f calcQuadFaceNormal (const Pnt3f &a, const Pnt3f &b, const Pnt3f &c, const Pnt3f &d)
void calcVertexNormal (Vertex *vertexPtr, UInt32 faceIndex)
bool isLeft (const Pnt2f &a, const Pnt2f &b)
Real32 computeMinYAbs (const std::vector< Pnt2f > &contour, Real32 alpha)
Real32 calcBetterRotationAngle (const std::vector< Pnt2f > &contour, UInt32 nAngles)
bool calcOptimizedContour (const std::vector< Pnt2f > &contour, const Pnt2f &point, std::vector< Pnt2f > *optimizedContour)
Int32 calcWindingNumber (const std::vector< Pnt2f > &contour, const Pnt2f &point)
void storeFaceNormalGeo (GeoIndicesUI32Ptr indicesPtr, GeoPLengthsUI32Ptr lensPtr, GeoPTypesUI8Ptr typesPtr)
void storeVertexNormalGeo (GeoIndicesUI32Ptr indicesPtr, GeoPLengthsUI32Ptr lensPtr, GeoPTypesUI8Ptr typesPtr)
Constructors


 ExtrusionSurface (void)
 prohibit default function (move to 'public' if needed)

Private Attributes

std::vector< Pnt2f_crossSection
std::vector< Quaternion_orientation
std::vector< Vec2f_scale
std::vector< Pnt3f_spine
Real32 _creaseAngle
bool _beginCap
bool _endCap
bool _ccw
bool _convex
bool _crossSectionClosed
bool _spineClosed
bool _spineCollinear
bool _revolutionSurface
bool _createNormals
bool _createTexCoords
std::vector< Matrix_transform
VertexGrid _grid
PositionMap _posMap
NormalMap _normalMap
TexCoordMap _texCoordMap
UInt32 _vertexCount
UInt32 _totalVertexCount
UInt32 _primitiveCount

Classes

struct  Vertex


Detailed Description

Definition at line 140 of file OSGExtrusionGeometry.h.


Member Typedef Documentation

typedef std::vector<Pnt3f>::const_iterator osg::ExtrusionSurface::Pnt3fConstIt [private]

Definition at line 249 of file OSGExtrusionGeometry.h.

typedef std::vector<Matrix>::const_iterator osg::ExtrusionSurface::MatrixConstIt [private]

Definition at line 250 of file OSGExtrusionGeometry.h.

Definition at line 251 of file OSGExtrusionGeometry.h.

typedef std::vector< std::vector< Vertex > > osg::ExtrusionSurface::VertexGrid [private]

Definition at line 253 of file OSGExtrusionGeometry.h.

typedef std::map<Pnt3f, UInt32, vecless<Pnt3f> > osg::ExtrusionSurface::PositionMap [private]

Definition at line 255 of file OSGExtrusionGeometry.h.

typedef std::map<Vec3f, UInt32, vecless<Vec3f> > osg::ExtrusionSurface::NormalMap [private]

Definition at line 256 of file OSGExtrusionGeometry.h.

typedef std::map<Vec2f, UInt32, vecless<Vec2f> > osg::ExtrusionSurface::TexCoordMap [private]

Definition at line 257 of file OSGExtrusionGeometry.h.


Constructor & Destructor Documentation

ExtrusionSurface::ExtrusionSurface ( const std::vector< Pnt2f > &  crossSection,
const std::vector< Quaternion > &  orientation,
const std::vector< Vec2f > &  scale,
const std::vector< Pnt3f > &  spine,
Real32  creaseAngle = 0.f,
bool  beginCap = true,
bool  endCap = true,
bool  ccw = true,
bool  convex = true,
bool  buildNormal = true,
bool  buildTexCoord = true 
)

Parameters:
crossSection The cross-section of the sweep surface
orientation The orientation rotating the cross-section out of the XZ-plane
scale The scale values scaling the cross-section
spine The spine curve along which the cross-section is extruded
creaseAngle Determines when normals are smoothed between adjacent quads
beginCap Determines whether a begin cap is to created
endCap Determines whether an end cap is to be created
ccw Determines the ordering of the primitive vertices with respect to the generated normals
convex Determines whether the cross-section is convex
buildNormal Determines whether normals are calculated
buildTexCoord Determines whether texture coordinates are created

Definition at line 125 of file OSGExtrusionGeometry.cpp.

References _crossSection, _orientation, _scale, _spine, osg::DEF_CROSS_SECTION, osg::DEF_N_CROSS_SECTION_POINTS, osg::DEF_N_ORIENTATION_PARAMS, osg::DEF_N_SCALE_PARAMS, osg::DEF_N_SPINE_POINTS, osg::DEF_ORIENTATION, osg::DEF_SCALE, osg::DEF_SPINE, and FDEBUG.

00135                                                        :
00136 
00137     _creaseAngle(creaseAngle),
00138     _beginCap(beginCap),
00139     _endCap(endCap),
00140     _ccw(ccw),
00141     _convex(convex),
00142     _createNormals(buildNormal),
00143     _createTexCoords(buildTexCoord),
00144     _primitiveCount(0),
00145     _vertexCount(0),
00146     _totalVertexCount(0)
00147 {
00148     // initialize cross section
00149     if(!crossSection.empty()) 
00150     {
00151         // copy argument
00152         _crossSection.assign(crossSection.begin(), crossSection.end());
00153     }
00154     else
00155     {
00156         // copy default
00157         FDEBUG(("OSGExtrusion: Empty cross section. Using default.\n"));
00158         for(UInt32 i = 0; i < DEF_N_CROSS_SECTION_POINTS; i++)
00159             _crossSection.push_back(Pnt2f(DEF_CROSS_SECTION[i]));
00160     }
00161 
00162     // initialize orientations
00163     if(!orientation.empty())
00164     {
00165         // copy argument
00166         _orientation.assign(orientation.begin(), orientation.end());
00167     }
00168     else
00169     {
00170         // copy default
00171         FDEBUG(("OSGExtrusion: Empty orientation. Using default.\n"));
00172         for(UInt32 i = 0; i < DEF_N_ORIENTATION_PARAMS; i++)
00173             _orientation.push_back(Quaternion(Vec3f(DEF_ORIENTATION[i]),
00174                                               DEF_ORIENTATION[i][3]));
00175     }
00176     
00177     // initialize scale parameters
00178     if(!scale.empty())
00179     {
00180         // copy argument
00181         _scale.assign(scale.begin(), scale.end());
00182     }
00183     else
00184     {
00185         // copy default
00186         FDEBUG(("OSGExtrusion: Empty scale parameter. Using default.\n"));
00187         for(UInt32 i = 0; i < DEF_N_SCALE_PARAMS; i++)
00188             _scale.push_back(Vec2f(DEF_SCALE[i]));
00189     }
00190 
00191 
00192     // initialize spine
00193     if(!spine.empty())
00194     {
00195         // copy argument
00196         _spine.assign(spine.begin(), spine.end());
00197     }
00198     else
00199     {
00200         // copy default
00201         FDEBUG(("OSGExtrusion: Empty spine. Using default.\n"));
00202         for(UInt32 i = 0; i < DEF_N_SPINE_POINTS; i++)
00203             _spine.push_back(Pnt3f(DEF_SPINE[i]));
00204     }
00205 }

osg::ExtrusionSurface::ExtrusionSurface ( void   )  [private]

osg::ExtrusionSurface::ExtrusionSurface ( const ExtrusionSurface source  )  [private]


Member Function Documentation

GeometryPtr ExtrusionSurface::createGeometry ( UInt32  nSubDivisions  ) 

Parameters:
nSubDivisions The number of subdivisions to apply
Returns:
A pointer to a newly created geometry containing the surface

Definition at line 1477 of file OSGExtrusionGeometry.cpp.

References _beginCap, _convex, _createNormals, _createTexCoords, _endCap, _normalMap, _orientation, _posMap, _primitiveCount, _spine, _texCoordMap, _totalVertexCount, osg::beginEditCP(), calcSweepSurfacePositions(), calcSweepSurfaceTexCoords(), osg::GeometryBase::create(), osg::GeoProperty< GeoPropertyDesc >::create(), determineTopology(), osg::endEditCP(), FDEBUG, FFATAL, FINFO, FWARNING, osg::GeoProperty< GeoPropertyDesc >::GeoPropDataFieldMask, osg::GeometryBase::IndexMappingFieldMask, osg::GeometryBase::IndicesFieldMask, initGrid(), osg::GeometryBase::LengthsFieldMask, osg::Geometry::MapNormal, osg::Geometry::MapPosition, osg::Geometry::MapTexCoords, osg::GeometryBase::NormalsFieldMask, osg::NullFC, osg::GeometryBase::PositionsFieldMask, refineCrossSection(), refineScale(), refineSpine(), SINFO, storeConvexCap(), storeFaceNormalGeo(), storeMaps(), storeSweepSurfaceWithNormals(), storeSweepSurfaceWithoutNormals(), storeVertexNormalGeo(), osg::GeometryBase::TexCoordsFieldMask, osg::GeometryBase::TypesFieldMask, and verifyInput().

Referenced by osg::makeExtrusionGeo().

01478 {
01479     // do some sanity checks on and determines the topology
01480     // of the _spine and _crossSection member fields
01481     if(!verifyInput())
01482     {
01483         FWARNING(("OSGExtrusion:createGeometry: Invalid input. Returning NullFC\n"));
01484         return NullFC;
01485     }
01486 
01487     // initialize topology flags (i.e spine/_crossSection closure)
01488     determineTopology();
01489     
01490     // optionally subdivide input data
01491     if(nSubdivs > 0)
01492     {
01493         refineCrossSection(nSubdivs);
01494 
01495         if(_orientation.size() == 1)
01496         {
01497             refineSpine(nSubdivs);
01498             refineScale(nSubdivs);
01499         }
01500         else // more than 1 orientation
01501         {
01502             // It'd be necessary to refine the orientations in order to get
01503             // a consistent result, but this is not implemented yet.
01504             FINFO(("OSGExtrusion:createGeometry: Too many orientations. Not refining along spine\n"));
01505         }
01506     }
01507 
01508     // allocate vertex grid structure
01509     initGrid();
01510     calcSweepSurfacePositions();
01511 
01512     if(_createTexCoords)
01513     {
01514         calcSweepSurfaceTexCoords();
01515     }
01516 
01517     // create opensg geometry field containers
01518     GeoPositions3fPtr  posPtr     = GeoPositions3f::create();
01519     GeoPLengthsUI32Ptr lensPtr    = GeoPLengthsUI32::create();
01520     GeoIndicesUI32Ptr  indicesPtr = GeoIndicesUI32::create();
01521     GeoPTypesUI8Ptr    typesPtr   = GeoPTypesUI8::create();
01522     GeoNormals3fPtr    normalsPtr = NullFC;
01523     GeoTexCoords2fPtr  texPtr     = NullFC;
01524 
01525     if(_createNormals)
01526         normalsPtr = GeoNormals3f::create();
01527 
01528     if(_createTexCoords)
01529         texPtr = GeoTexCoords2f::create();
01530 
01531     beginEditCP(indicesPtr, GeoIndicesUI32::GeoPropDataFieldMask);
01532     beginEditCP(lensPtr,    GeoPLengthsUI32::GeoPropDataFieldMask);
01533     beginEditCP(typesPtr,   GeoPTypesUI8::GeoPropDataFieldMask);
01534 
01535     if(_createNormals)
01536     {
01537         // store sweep surface as triangle strips with vertex normals
01538         storeSweepSurfaceWithNormals(indicesPtr, lensPtr, typesPtr);
01539     }
01540     else
01541     {
01542         // store sweep surface as triangle strips without vertex normals
01543         storeSweepSurfaceWithoutNormals(indicesPtr, lensPtr, typesPtr);
01544     }
01545 
01546     if(_convex)
01547     {
01548         // calculate and store caps as triangle fans
01549         if(_beginCap)
01550         {
01551             FDEBUG(("OSGExtrusion:createGeometry: Creating begin cap\n"));
01552             storeConvexCap(0,           // spine section 0 
01553                            true,        // flip normal
01554                            indicesPtr, 
01555                            lensPtr, 
01556                            typesPtr);
01557         }
01558         
01559         if(_endCap)
01560         {
01561             FDEBUG(("OSGExtrusion:createGeometry: Creating end cap\n"));
01562             storeConvexCap(_spine.size() - 1,  // last spine section
01563                            false,              // don't flip normal
01564                            indicesPtr,
01565                            lensPtr, 
01566                            typesPtr);
01567         }
01568     }
01569     else // non-convex case
01570     {
01571         FFATAL(("OSGExtrusion:createGeometry: Support for non-convex caps not implemented\n"));
01572     }
01573     
01574 #ifdef DEBUG_VERTEX_NORMALS
01575     // add surface normals for debugging purposes
01576     storeVertexNormalGeo(indicesPtr, lensPtr, typesPtr);
01577 #endif
01578 
01579 #ifdef DEBUG_FACE_NORMALS
01580     // add sweep surface face normals for debugging purposes
01581     storeFaceNormalGeo(indicesPtr, lensPtr, typesPtr);
01582 #endif    
01583 
01584     endEditCP(indicesPtr, GeoIndicesUI32::GeoPropDataFieldMask);
01585     endEditCP(lensPtr,    GeoPLengthsUI32::GeoPropDataFieldMask);
01586     endEditCP(typesPtr,   GeoPTypesUI8::GeoPropDataFieldMask);
01587 
01588     // store the shared vertex data into the vertex data field containers
01589     storeMaps(posPtr, normalsPtr, texPtr);
01590 
01591     // create a new OpenSG geometry
01592     GeometryPtr geoPtr = Geometry::create();
01593 
01594     beginEditCP(geoPtr, Geometry::TypesFieldMask  |
01595                 Geometry::LengthsFieldMask        |
01596                 Geometry::IndicesFieldMask        |
01597                 Geometry::IndexMappingFieldMask   |
01598                 Geometry::PositionsFieldMask      |
01599                 Geometry::NormalsFieldMask        |
01600                 Geometry::TexCoordsFieldMask      );
01601 
01602     // The interleaved multi-index blocks have one of the following 
01603     // layouts (depending on _createNormals and _createTexCoords):
01604     //
01605     // 1. (Position)                  
01606     // 2. (Position, Normal)
01607     // 3. (Position, TexCoord)        
01608     // 4. (Position, Normal, TexCoord)
01609     geoPtr->getIndexMapping().push_back(Geometry::MapPosition);
01610     if(_createNormals)
01611         geoPtr->getIndexMapping().push_back(Geometry::MapNormal);
01612     if(_createTexCoords)
01613         geoPtr->getIndexMapping().push_back(Geometry::MapTexCoords);
01614 
01615     // set primitive data field containers
01616     geoPtr->setLengths(lensPtr);
01617     geoPtr->setIndices(indicesPtr);
01618     geoPtr->setTypes(typesPtr);
01619    
01620     // set vertex data field containers
01621     geoPtr->setPositions(posPtr);
01622     geoPtr->setNormals(normalsPtr);
01623     geoPtr->setTexCoords(texPtr);
01624    
01625     endEditCP(geoPtr, Geometry::TypesFieldMask  |
01626               Geometry::LengthsFieldMask        |
01627               Geometry::IndicesFieldMask        |
01628               Geometry::IndexMappingFieldMask   |
01629               Geometry::PositionsFieldMask      |
01630               Geometry::NormalsFieldMask        |
01631               Geometry::TexCoordsFieldMask      );
01632 
01633 
01634     SINFO << "OSGExtrusion:createGeometry: Stats: ("
01635           << _primitiveCount     << '/'
01636           << _totalVertexCount   << '/'
01637           << _posMap.size() << '/'
01638           << _normalMap.size()   << '/'
01639           << _texCoordMap.size() << ')'
01640           << "(Prims/Verts/Pos/Norms/TexCoords)"
01641           << std::endl; 
01642         
01643     return geoPtr;
01644 }

void osg::ExtrusionSurface::operator= ( const ExtrusionSurface source  )  [private]

void ExtrusionSurface::calcXAxes ( void   )  [inline, private]

Calculates the X-Axes of the CP to SCP transforms

Definition at line 331 of file OSGExtrusionGeometry.cpp.

References _revolutionSurface, _spineCollinear, _transform, and calcXAxis().

Referenced by calcTransforms().

00332 {
00333     std::vector<Matrix>::iterator tIt = _transform.begin();
00334 
00335     // Either of the two cases below implies the cross product of
00336     // the y- and the z-axis vanish (and so do all x-axes)
00337     if(!_spineCollinear && !_revolutionSurface)
00338     {
00339         for(; tIt != _transform.end(); ++tIt)
00340         {
00341             Vec3f xAxis = calcXAxis(tIt);
00342             (*tIt)[0].setValue(xAxis);
00343         }
00344     }
00345     else
00346     {
00347         (*tIt)[0].setValue(Vec3f(0.f, 0.f, 0.f));
00348     }
00349 }

void ExtrusionSurface::calcYAxes ( void   )  [inline, private]

Calculates the Y-Axes of the CP to SCP transforms

Definition at line 361 of file OSGExtrusionGeometry.cpp.

References _revolutionSurface, _spine, _transform, calcNonUnitYAxis(), osg::Eps, FDEBUG, osg::VectorInterface< ValueTypeT, StorageInterfaceT >::length(), and osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize().

Referenced by calcTransforms().

00362 {
00363     bool yAxisDefined = false;
00364 
00365     std::vector<Pnt3f>::const_iterator  spineIt = _spine.begin();
00366     std::vector<Matrix>::iterator tIt = _transform.begin();
00367     for(; spineIt != _spine.end(); ++spineIt, ++tIt)
00368     {
00369         Vec3f yAxis = calcNonUnitYAxis(spineIt);
00370         if(yAxis.length() > Eps) // we have found a valid tangent
00371         {
00372             yAxis.normalize();
00373             if(!yAxisDefined)
00374             {
00375                 FDEBUG(("OSGExtrusion:calcYAxes: yAxis is defined\n"));
00376                 yAxisDefined = true;
00377 
00378                 // assign found y-axis to all transforms
00379                 // up to and including the current one
00380                 std::vector<Matrix>::iterator yIt;
00381                 for(yIt = _transform.begin(); yIt != (tIt + 1); ++yIt)
00382                     (*yIt)[1].setValue(yAxis);
00383             }
00384             else 
00385             {
00386                 // assign found y-axis to the current transform only
00387                 (*tIt)[1].setValue(yAxis);
00388             }
00389         }
00390         else if(yAxisDefined)
00391         {
00392             // reuse y-axis determined during last step
00393             (*tIt)[1] = (*(tIt - 1))[1];
00394         }
00395     }
00396 
00397     // all spine points coincided => surface of revolution
00398     _revolutionSurface = !yAxisDefined;
00399 }

void ExtrusionSurface::calcZAxes ( void   )  [inline, private]

Calculates the Z-Axes of the CP to SCP transforms

Definition at line 410 of file OSGExtrusionGeometry.cpp.

References _spine, _spineCollinear, _transform, calcNonUnitZAxis(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::dot(), osg::Eps, FDEBUG, osg::VectorInterface< ValueTypeT, StorageInterfaceT >::length(), osg::PointInterface< ValueTypeT, StorageInterfaceT >::negate(), and osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize().

Referenced by calcTransforms().

00411 {
00412     bool zAxisDefined = false;
00413     
00414     std::vector<Pnt3f>::const_iterator  spineIt = _spine.begin();
00415     std::vector<Matrix>::iterator tIt = _transform.begin();
00416     for(; spineIt != _spine.end(); ++spineIt, ++tIt)
00417     {
00418         Vec3f zAxis = calcNonUnitZAxis(spineIt);
00419         if(zAxis.length() > Eps)
00420         {
00421             zAxis.normalize();
00422             if(!zAxisDefined)
00423             {
00424                 FDEBUG(("OSGExtrusion:calcZAxes: zAxis is defined\n"));
00425                 zAxisDefined = true;
00426                 
00427                 // set the current z-Axis for the current transform
00428                 (*tIt)[2].setValue(zAxis);
00429 
00430                 // assign found z-axis to all previous transforms
00431                 std::vector<Matrix>::iterator zIt;
00432                 for(zIt = _transform.begin(); zIt != tIt; ++zIt)
00433                 {
00434                     (*zIt)[2].setValue(zAxis);
00435                 }
00436             }
00437             else // assign found z-axis to this basis _only_
00438             {
00439                 (*tIt)[2].setValue(zAxis);
00440 
00441                 // as the zAxis is defined tIt - 1 contains a valid value 
00442                 Vec3f prevZAxis((*(tIt - 1))[2][0],
00443                                 (*(tIt - 1))[2][1],
00444                                 (*(tIt - 1))[2][2]);
00445 
00446                 // check whether the z-axis needs to be flipped
00447                 if(prevZAxis.dot(zAxis) + Eps < 0.f)
00448                 {
00449                     FDEBUG(("OSGExtrusion:calcZAxes: Flipping z-axis\n"));
00450                     zAxis.negate();
00451                 }
00452 
00453                 // assign zAxis to current transform
00454                 (*tIt)[2].setValue(zAxis);
00455             }
00456         }
00457         else if(zAxisDefined)
00458         {
00459             // reuse previous value
00460             (*tIt)[2] = (*(tIt - 1))[2];
00461         }
00462     } // end for
00463 
00464     // All cross products vanished => spine has no non-collinear part
00465     // and is thus composed of collinear parts and revolutions only
00466     _spineCollinear = !zAxisDefined;
00467 }

void ExtrusionSurface::calcTransforms ( void   )  [private]

Calculates the affine transformations from CP to SCP

Definition at line 480 of file OSGExtrusionGeometry.cpp.

References _orientation, _revolutionSurface, _scale, _spine, _spineCollinear, _transform, calcXAxes(), calcYAxes(), calcZAxes(), FDEBUG, osg::QuaternionBase< ValueTypeT >::getValue(), osg::TransformationMatrix< ValueTypeT >::multLeft(), and osg::QuaternionBase< ValueTypeT >::setValue().

Referenced by calcSweepSurfacePositions().

00481 {
00482     _transform.clear();
00483 
00484     // initialize the transformations with Id
00485     _transform.resize(_spine.size());
00486 
00487     /* X3D Spec:
00488      * The SCP is computed by first computing its Y-axis and Z-axis, then 
00489      * taking the cross product of these to determine the X-axis. These three 
00490      * axes are then used to determine the rotation value needed to rotate the
00491      * Y=0 plane to the SCP. This results in a plane that is the approximate 
00492      * tangent of the spine at each point, as shown in Figure 13.5.
00493      */
00494     calcZAxes(); // sets bool _spineCollinear
00495     calcYAxes(); // sets bool _revolutionSurface
00496 
00497     // We need to make a difference between surfaces having at least
00498     // one non-trivial collinear part in their spine and surfaces created
00499     // by pure revolution of the crossection.
00500     if(_revolutionSurface)
00501     {
00502         _spineCollinear = false;
00503     }
00504     calcXAxes(); // uses _spineCollinear and _revolutionSurface
00505 
00506     /* X3D Spec:
00507      *
00508      * If the entire spine is collinear, the SCP is computed by finding the 
00509      * rotation of a vector along the positive Y-axis (v1) to the vector formed
00510      * by the spine points (v2). The Y=0 plane is then rotated by this value.
00511      *
00512      * If two points are coincident, they both have the same SCP. If each point
00513      * has a different orientation value, then the surface is constructed by 
00514      * connecting edges of the cross-sections as normal. This is useful in 
00515      * creating revolved surfaces.
00516      */
00517     Matrix rotation; // m = Id and thus ok for revolution case
00518     if(_spineCollinear && !_revolutionSurface)
00519     {
00520         // calculate the rotation that rotates the y unit vector to the
00521         // direction of the spine.
00522         Vec3f v1(0.f, 1.f, 0.f);
00523         Vec3f v2(_transform[0][1]);
00524             
00525         Quaternion q;
00526         q.setValue(v1, v2);
00527         q.getValue(rotation);
00528     }
00529 
00530     std::vector<Matrix>::iterator tIt             = _transform.begin();
00531     std::vector<Pnt3f>::const_iterator spineIt    = _spine.begin();
00532     std::vector<Vec2f>::const_iterator scaleIt    = _scale.begin(); 
00533     std::vector<Quaternion>::const_iterator rotIt = _orientation.begin();
00534 
00535     // calculate an affine transformation for the cross-section at
00536     // each spine point
00537     for(; spineIt != _spine.end(); ++spineIt, ++tIt)
00538     {
00539         // special cases
00540         if(_spineCollinear || _revolutionSurface)
00541         {
00542             // defines the x,y and z-axes in this case
00543             *tIt = rotation;
00544         }        
00545 
00546         // setup transform of the CP
00547         Matrix cSPlaneTransform;
00548 
00549         // Scale the x- and z-axes
00550         cSPlaneTransform[0] *= (*scaleIt)[0];
00551         cSPlaneTransform[2] *= (*scaleIt)[1];
00552 
00553         // apply orientation
00554         Matrix orientationMatrix;
00555         rotIt->getValue(orientationMatrix);
00556         cSPlaneTransform.multLeft(orientationMatrix);
00557 
00558         tIt->mult(cSPlaneTransform);
00559 
00560         // affine translation to the spine point
00561         tIt->setTranslate(*spineIt);
00562         
00563         // The affine transformation *tIt should now
00564         //
00565         //   1. scale the CP
00566         //   2. apply the orientation to the CP        
00567         //   2. translate the origin to spine[i]
00568         //
00569         // in exactly this order.
00570 
00571         /* X3D Spec quotation:
00572          *
00573          * If the number of scale or orientation values is greater than the
00574          * number of spine points, the excess values are ignored. If they 
00575          * contain one value, it is applied at all spine points. The 
00576          * results are undefined if the number of scale or orientation 
00577          * values is greater than one but less than the number of spine 
00578          * points. The scale values shall be positive.
00579          */
00580         
00581         // always use last available value
00582         if(rotIt + 1   != _orientation.end()) { ++rotIt;   }
00583         if(scaleIt + 1 != _scale.end())       { ++scaleIt; }
00584     }
00585 
00586     FDEBUG(("OSGExtrusion:calcTransforms: spine collinear: %s\n", 
00587             (_spineCollinear ? "true" : "false")));
00588 
00589     FDEBUG(("OSGExtrusion:calcTransforms: revolution surface: %s\n",
00590             (_revolutionSurface ? "true" : "false")));
00591 }

void ExtrusionSurface::calcSweepSurfacePositions ( void   )  [private]

Calculates the positions of the sweep surface and stores them in the _grid

Definition at line 624 of file OSGExtrusionGeometry.cpp.

References _crossSection, _grid, _posMap, _spine, _transform, calcTransforms(), osg::Eps, FDEBUG, FFATAL, FWARNING, initGrid(), p, and SWARNING.

Referenced by createGeometry().

00625 {
00626     FDEBUG(("OSGExtrusion:calcSweepSurfacePositions: Calculation vertex positions\n"));
00627 
00628     if(_grid.size() < _spine.size())
00629     {
00630         FFATAL(("OSGExtrusion:calcSweepSurfacePositions: Grid not initialized\n"));
00631         return;
00632     }
00633 
00634     _posMap.clear();
00635 
00636     // compute transformation matrices
00637     calcTransforms();
00638 
00639     if(_grid.size() < _spine.size()) // grid not yet or incorrectly initialized
00640     {
00641         initGrid();
00642     }
00643 
00644     std::vector<Matrix>::iterator transIt = _transform.begin();
00645     VertexGrid::iterator gridRowIt = _grid.begin();
00646 
00647     // iterate over the spine points
00648     for(Int32 i = 0; i < _spine.size(); i++, ++gridRowIt)
00649     {
00650         if(transIt->det3() < Eps) // degenerate transform
00651         {
00652             FWARNING(("OSGExtrusion:calcSurfacePositions: Degenerate transformation matrix\n"));
00653             SWARNING << "Degenerate transform[" << i << "]:\n "
00654                      << *transIt << std::endl;
00655         }
00656 
00657         std::vector<Vertex>::iterator gridColIt = gridRowIt->begin();
00658         std::vector<Pnt2f>::iterator crossIt;
00659 
00660         // iterate over the cross-section curve
00661         for(crossIt = _crossSection.begin(); crossIt != _crossSection.end();
00662             ++crossIt, ++gridColIt)
00663         {
00664             Pnt3f p = Pnt3f((*crossIt)[0], 0.f, (*crossIt)[1]);
00665 
00666             // apply "CP to SCP"-transform
00667             transIt->multMatrixPnt(p, gridColIt->position);
00668         }
00669 
00670         // always use last defined transformation matrix
00671         if(transIt + 1 != _transform.end()) { ++transIt; }
00672     }
00673 }

void ExtrusionSurface::calcSweepSurfaceFaceNormals ( void   )  [private]

Calculates the face normals of the sweep surface and stores them in the _grid

Definition at line 748 of file OSGExtrusionGeometry.cpp.

References _crossSection, _crossSectionClosed, _grid, _spine, _spineClosed, calcQuadFaceNormal(), FDEBUG, and FFATAL.

Referenced by storeSweepSurfaceWithNormals().

00749 {
00750     FDEBUG(("OSGExtrusion:calcSweepSurfaceFaceNormals: Calculating sweep surface face normals\n"));
00751 
00752     if(_grid.size() < _spine.size())
00753     {
00754         FFATAL(("OSGExtrusion:calcSweepSurfaceFaceNormals: Grid not initialized\n"));
00755         return;
00756     }
00757     
00758     // calculate face normals
00759     for(UInt32 i = 0; i < _spine.size(); ++i)
00760     {
00761         UInt32 iPrev, iNext;
00762 
00763         // determine adjacent row indices
00764         if(_spineClosed)
00765         {
00766             // first point == last point
00767             iPrev = (i != 0) ? i - 1 : _spine.size() - 2;
00768             iNext = (i != _spine.size() - 1) ? i + 1 : 1;
00769         }
00770         else
00771         {
00772             iPrev = (i != 0) ? i - 1 : 0;
00773             iNext = (i != _spine.size() - 1) ? i + 1 : i;
00774         }
00775 
00776         for(UInt32 j = 0; j < _crossSection.size(); ++j)
00777         {
00778             Vec3f n;
00779             UInt32 jPrev, jNext;
00780 
00781             // determine adjacent column indices
00782             if(_crossSectionClosed)
00783             {
00784                 // first point == last point
00785                 jPrev = (j != 0) ? j - 1 : _crossSection.size() - 2;
00786                 jNext = (j != _crossSection.size() - 1) ? j + 1 : 1;
00787             }
00788             else
00789             {
00790                 jPrev = (j != 0) ? j - 1 : 0;
00791                 jNext = (j != _crossSection.size() - 1) ? j + 1 : j;
00792             }
00793 
00794             // upper right face normal (1st quadrant)
00795             _grid[i][j].adjFaceNormals[0] =
00796                 calcQuadFaceNormal(_grid[i][j].position,
00797                                    _grid[i][jNext].position,
00798                                    _grid[iNext][jNext].position,
00799                                    _grid[iNext][j].position);
00800 
00801 
00802             // upper left face normal (2nd quadrant)
00803             _grid[i][j].adjFaceNormals[1] = 
00804                 calcQuadFaceNormal(_grid[i][j].position,
00805                                    _grid[iNext][j].position,
00806                                    _grid[iNext][jPrev].position,
00807                                    _grid[i][jPrev].position);
00808 
00809 
00810             // lower left face normal (3nd quadrant)
00811             _grid[i][j].adjFaceNormals[2] = 
00812                 calcQuadFaceNormal(_grid[i][j].position,
00813                                    _grid[i][jPrev].position,
00814                                    _grid[iPrev][jPrev].position,
00815                                    _grid[iPrev][j].position);
00816 
00817 
00818             // lower right face normal (4th quadrant)
00819             _grid[i][j].adjFaceNormals[3] = 
00820                 calcQuadFaceNormal(_grid[i][j].position,
00821                                    _grid[iPrev][j].position,
00822                                    _grid[iPrev][jNext].position,
00823                                    _grid[i][jNext].position);
00824         }
00825     }
00826 }

void ExtrusionSurface::calcSweepSurfaceTexCoords ( void   )  [private]

Definition at line 686 of file OSGExtrusionGeometry.cpp.

References _crossSection, _grid, _spine, _texCoordMap, osg::Eps, FDEBUG, and FFATAL.

Referenced by createGeometry().

00687 {
00688     FDEBUG(("OSGExtrusion:calcSweepSurfaceTexCoords: Calculating texture coordinates\n"));
00689     if(_grid.size() < _spine.size())
00690     {
00691         FFATAL(("OSGExtrusion:calcSweepSurfaceTexCoords: Grid not initialized\n"));
00692         return;
00693     }
00694     _texCoordMap.clear();
00695     
00696     /* X3D Spec:
00697      *
00698      *  Textures are mapped so that the coordinates range in the U direction 
00699      *  from 0 to 1 along the crossSection curve (with 0 corresponding to the 
00700      *  first point in crossSection and 1 to the last) and in the V direction
00701      *  from 0 to 1 along the spine curve (with 0 corresponding to the first 
00702      *  listed spine point and 1 to the last) 
00703      */
00704 
00705     // accumulate distances along u and v directions
00706     for(UInt32 i = 0; i < _spine.size(); ++i)
00707     {
00708         for(UInt32 j = 0; j < _crossSection.size(); ++j)
00709         {
00710             Real32 u,v;
00711             UInt32 iPrev = (i == 0) ? 0 : i - 1;
00712             UInt32 jPrev = (j == 0) ? 0 : j - 1;
00713 
00714             // contains length of i-th column curve up to the (j-1)-th point
00715             u = _grid[i][jPrev].texCoord[0];
00716             // add distance to j-th point
00717             u += _grid[i][j].position.dist(_grid[i][jPrev].position);
00718 
00719             // contains length of j-th row curve up to the (i-1)-th point
00720             v = _grid[iPrev][j].texCoord[1];
00721             // add distance to i-th point
00722             v += _grid[i][j].position.dist(_grid[iPrev][j].position);
00723 
00724             _grid[i][j].texCoord[0] = u;
00725             _grid[i][j].texCoord[1] = v;
00726         }
00727     }
00728 
00729     // renormalize distances to [0,1]x[0,1]
00730     for(UInt32 i = 0; i < _spine.size(); ++i)
00731     {
00732         for(UInt32 j = 0; j < _crossSection.size(); ++j)
00733         {
00734             // length is maximal in the row/column curve end points
00735             Real32 uMax = _grid[i][_crossSection.size() - 1].texCoord[0];
00736             Real32 vMax = _grid[_spine.size() - 1][j].texCoord[1];
00737 
00738             if(uMax > Eps)
00739                 _grid[i][j].texCoord[0] /= uMax;
00740 
00741             if(vMax > Eps)
00742                 _grid[i][j].texCoord[1] /= vMax;
00743         }
00744     }
00745 }

void ExtrusionSurface::determineTopology ( void   )  [private]

Initializes the topology flags of the extrusion surface

Definition at line 238 of file OSGExtrusionGeometry.cpp.

References _crossSection, _crossSectionClosed, _spine, _spineClosed, osg::Eps, FDEBUG, and osg::VectorInterface< ValueTypeT, StorageInterfaceT >::length().

Referenced by createGeometry().

00239 {
00240     // compute vector differences between start and end points
00241     Vec3f sDiff = _spine.back() - _spine.front();
00242     Vec2f cDiff = _crossSection.back() - _crossSection.front();
00243 
00244     // determine whether the curves are closed
00245     _spineClosed = (sDiff.length() < Eps) ? true : false;
00246     _crossSectionClosed = (cDiff.length() < Eps) ? true : false;
00247     
00248     FDEBUG(("OSGExtrusion:checkInput: Topology: (Spine: %s / Cross-section: %s)\n", 
00249             (_spineClosed ? "Closed" : "Open"),
00250             (_crossSectionClosed ? "Closed" : "Open")));
00251 }

void ExtrusionSurface::initGrid ( void   )  [private]

Initializes the _grid data structure

Definition at line 600 of file OSGExtrusionGeometry.cpp.

References _crossSection, _grid, _spine, and FDEBUG.

Referenced by calcSweepSurfacePositions(), and createGeometry().

00601 {
00602     FDEBUG(("OSGExtrusion:initGrid: Initializing vertex grid\n"));
00603     
00604     _grid.clear();
00605     _grid.resize(_spine.size());
00606 
00607     VertexGrid::iterator gridRowIt = _grid.begin();
00608     for(Int32 i = 0; i < _spine.size(); i++, ++gridRowIt)
00609     {
00610         gridRowIt->resize(_crossSection.size());
00611     }
00612 }

bool ExtrusionSurface::verifyInput ( void   )  [private]

Returns true if an extrusion surface can be generated from the supplied data.

Definition at line 214 of file OSGExtrusionGeometry.cpp.

References _crossSection, _spine, and FWARNING.

Referenced by createGeometry().

00215 {
00216     if(_crossSection.size() < 2)
00217     {
00218         FWARNING(("OSGExtrusion:checkInput: Cross section is degenerate\n"));
00219         return false;
00220     }
00221 
00222     if(_spine.size() < 2)
00223     {
00224         FWARNING(("OSGExtrusion:checkInput: spine is degenerate\n"));
00225         return false;
00226     }
00227 
00228     return true;
00229 }

void ExtrusionSurface::refineCrossSection ( UInt32  nTimes  )  [private]

Definition at line 259 of file OSGExtrusionGeometry.cpp.

References _crossSection, _crossSectionClosed, FDEBUG, and subdivide().

Referenced by createGeometry().

00260 {
00261     FDEBUG(("OSGExtrusion:refineCrossSection: Refinining %d times\n",nTimes));
00262     std::vector<Vec2f> output;
00263 
00264     // cast <Pnt2f> to <Vec2f> because we need the vector interface
00265     std::vector<Vec2f> & csVec2f ((std::vector<Vec2f>&)(_crossSection));
00266     subdivide(csVec2f, &output, nTimes, _crossSectionClosed);
00267 
00268     // swap output data into _crossSection
00269     output.swap(csVec2f);
00270 }

void ExtrusionSurface::refineOrientation ( UInt32  nTimes  )  [private]

Subdivides the _orientation vector n-times

Definition at line 316 of file OSGExtrusionGeometry.cpp.

References FFATAL.

00317 {
00318     FFATAL(("OSGExtrusion:refineOrientation: Not Implemented\n"));
00319 }

void ExtrusionSurface::refineScale ( UInt32  nTimes  )  [private]

Subdivides the scale parameters vector n-times

Definition at line 297 of file OSGExtrusionGeometry.cpp.

References _scale, _spineClosed, and FDEBUG.

Referenced by createGeometry().

00298 {
00299     FDEBUG(("OSGExtrusion:refineScale: Refinining %d times\n",nTimes));
00300 
00301     std::vector<Vec2f> output;
00302     subdivide<Vec2f>(_scale, &output, nTimes, _spineClosed);
00303 
00304     // swap output data into _scale
00305     output.swap(_scale);
00306 }

void ExtrusionSurface::refineSpine ( UInt32  nTimes  )  [private]

Subdivides the spine n-times

Definition at line 277 of file OSGExtrusionGeometry.cpp.

References _spine, _spineClosed, and FDEBUG.

Referenced by createGeometry().

00278 {
00279     FDEBUG(("OSGExtrusion:refineSpine: Refinining %d times\n",nTimes));
00280 
00281     std::vector<Vec3f> output;
00282 
00283     // cast <Pnt3f> to <Vec3f> because we need the vector interface    
00284     std::vector<Vec3f> & spVec3f ((std::vector<Vec3f>&)(_spine));
00285     subdivide<Vec3f>(spVec3f, &output, nTimes, _spineClosed);
00286 
00287     // swap output data into _spine
00288     output.swap(spVec3f);
00289 }

void ExtrusionSurface::storeConvexCap ( UInt32  spineIndex,
bool  invertNormal,
GeoIndicesUI32Ptr  indicesPtr,
GeoPLengthsUI32Ptr  lensPtr,
GeoPTypesUI8Ptr  typesPtr 
) [private]

Stores a convex cap surface in the supplied field containers

Parameters:
spineIndex The spine point at which the cap is to be created
invertNormal If true the cap normal is reversed

Definition at line 1206 of file OSGExtrusionGeometry.cpp.

References _ccw, _convex, _createNormals, _crossSection, _crossSectionClosed, _grid, _transform, calcWindingNumber(), osg::Eps, FDEBUG, FFATAL, FWARNING, osg::ExtrusionSurface::Vertex::normal, osg::NullFC, osg::ExtrusionSurface::Vertex::position, storePrimitive(), storeVertex(), and osg::ExtrusionSurface::Vertex::texCoord.

Referenced by createGeometry().

01211 {
01212     assert(indicesPtr != NullFC);
01213     assert(lensPtr    != NullFC);
01214     assert(typesPtr   != NullFC);
01215 
01216     if(!_convex)
01217     {
01218         FFATAL(("OSGExtrusion:storeCap: Non-convex caps not yet implemented\n"));
01219         return;
01220     }
01221     
01222     std::vector<Pnt3f> capBorderCurveInSection;
01223     std::vector<Pnt2f> capBorderCurveInXZPlane(_crossSection);
01224     capBorderCurveInSection.reserve(_grid[spineIndex].size());
01225 
01226     std::vector<Vertex>::const_iterator gIt = _grid[spineIndex].begin();
01227     while(gIt != _grid[spineIndex].end())
01228     {
01229         capBorderCurveInSection.push_back(gIt->position);
01230         ++gIt;
01231     }
01232 
01233     if(!_crossSectionClosed)
01234     {
01235         capBorderCurveInSection.push_back(_grid[spineIndex].front().position);
01236         capBorderCurveInXZPlane.push_back(_crossSection.front());
01237     }
01238 
01239     FDEBUG(("OSGExtrusion:storeCap: Generating cap[%d], type=%s, _ccw=%s\n", 
01240             spineIndex,
01241             (isBeginCap ? "begin cap" : "end cap"),
01242             (_ccw ? "TRUE" : "FALSE")));
01243            
01244     Pnt3f baryCenterInSection;
01245     Pnt2f baryCenterInXZPlane;
01246 
01247     std::vector<Pnt3f>::iterator sIt = capBorderCurveInSection.begin();
01248     std::vector<Pnt2f>::iterator cIt = capBorderCurveInXZPlane.begin();
01249 
01250     // compute barycenters
01251     UInt32 nBorderPoints = capBorderCurveInSection.size() - 1;
01252     // calculate the mean of all points with the exception of the last
01253     // (which is equal to the first)
01254     for(UInt32 i = 0; i < nBorderPoints; ++i, ++sIt, ++cIt)
01255     {
01256         baryCenterInSection += Vec3f(*sIt);
01257         baryCenterInXZPlane += Vec2f(*cIt);
01258     }
01259     baryCenterInSection /= nBorderPoints;
01260     baryCenterInXZPlane /= nBorderPoints;
01261 
01262    /* X3D Spec:
01263     *
01264     * Normals for the caps are generated along the Y-axis of the SCP,
01265     * with the ordering determined by viewing the cross-section from
01266     * above (looking along the negative Y-axis of the SCP). By default, a
01267     * beginCap with a counterclockwise ordering shall have a normal along
01268     * the negative Y-axis. An endCap with a counterclockwise ordering
01269     * shall have a normal along the positive Y-axis.
01270     *
01271     */
01272 
01273     // compute winding number
01274     Int32 windNum = calcWindingNumber(capBorderCurveInXZPlane,
01275                                       baryCenterInXZPlane);
01276     
01277     FDEBUG(("OSGExtrusion:storeCap: Cross-section has winding number: %d\n",
01278             windNum));
01279 
01280     bool isCCWOrderedCap = true;
01281     if(windNum != 0)
01282     {
01283         isCCWOrderedCap = (windNum > 0) ? true : false;
01284     }
01285     else
01286     {
01287         FWARNING(("OSGExtrusion:storeCap: Winding number = 0. Culling might be incorrect\n"));
01288         // hope isCCWCrossSection == true ist correct
01289     }
01290 
01291     Vertex v;
01292     v.position = baryCenterInSection;
01293 
01294     // compute cap normal
01295     bool negateNormal = false;
01296     if(_createNormals)
01297     {
01298         // Take the Y-axis at the given spine index as the cap normal
01299         Vec3f capNormal = Vec3f(_transform[spineIndex][1]);
01300 
01301         if(isBeginCap) 
01302         {
01303             if(!isCCWOrderedCap)
01304             {
01305                 negateNormal = true;
01306             }
01307         }
01308         else // end cap
01309         {
01310             if(isCCWOrderedCap)
01311             {
01312                 negateNormal = true;
01313             }
01314         }
01315 
01316         if(!_ccw)
01317             negateNormal = !negateNormal;
01318 
01319         v.normal = negateNormal ? -capNormal : capNormal;
01320 
01321         FDEBUG(("OSGExtrusion:storeCap: Cap normal: (%f, %f, %f)\n",
01322                 v.normal[0], v.normal[1], v.normal[2]));
01323     }
01324      
01325     // calculate texture coordinates
01326     // compute 2D bounding box for cross section
01327     Real32 xMin,xMax,zMin,zMax;
01328     xMin = xMax = capBorderCurveInXZPlane[0][0];
01329     zMin = zMax = capBorderCurveInXZPlane[0][1];
01330     for(cIt = capBorderCurveInXZPlane.begin(); 
01331         cIt != capBorderCurveInXZPlane.end(); ++cIt)
01332     {
01333         if(xMin > (*cIt)[0]) xMin = (*cIt)[0];
01334         if(xMax < (*cIt)[0]) xMax = (*cIt)[0];
01335         if(zMin > (*cIt)[1]) zMin = (*cIt)[1];
01336         if(zMax < (*cIt)[1]) zMax = (*cIt)[1];
01337     }
01338     Real32 xWidth = xMax - xMin;
01339     Real32 zWidth = zMax - zMin;
01340     Real32 maxWidth = (xWidth > zWidth) ? xWidth : zWidth;
01341     Real32 scale = (maxWidth > Eps) ? 1.f / maxWidth : 1.f;
01342 
01343     v.texCoord[0] = (baryCenterInXZPlane[0] - xMin) * scale;
01344     v.texCoord[1] = (baryCenterInXZPlane[1] - zMin) * scale;
01345 
01346     // store barycenter vertex
01347     storeVertex(v, indicesPtr);
01348 
01349     bool reverseInsert = false;
01350     
01351     if(isCCWOrderedCap)
01352     {
01353         if(!negateNormal)
01354             reverseInsert = true;
01355     }
01356     else
01357     {
01358         if(negateNormal)
01359             reverseInsert = true;
01360     }
01361 
01362     if(reverseInsert)
01363     {
01364         FDEBUG(("OSGExtrusion:storeCap: storing cap border vertices reversed\n")); 
01365         std::vector<Pnt3f>::reverse_iterator sRevIt 
01366             = capBorderCurveInSection.rbegin();
01367         std::vector<Pnt2f>::reverse_iterator  cRevIt
01368             = capBorderCurveInXZPlane.rbegin();
01369 
01370         // store cross section image vertices
01371         for(; sRevIt != capBorderCurveInSection.rend(); ++cRevIt, ++sRevIt)
01372         {
01373             v.position = *sRevIt;
01374             v.texCoord[0] = ((*cRevIt)[0] - xMin) * scale;
01375             v.texCoord[1] = ((*cRevIt)[1] - zMin) * scale;
01376 
01377             storeVertex(v, indicesPtr);
01378         }
01379     }
01380     else // don't reverse insert
01381     {
01382         FDEBUG(("OSGExtrusion:storeCap: storing cap border vertices\n")); 
01383         sIt = capBorderCurveInSection.begin();
01384         cIt = capBorderCurveInXZPlane.begin();
01385         // store cross section image vertices
01386         for(; sIt != capBorderCurveInSection.end(); ++cIt, ++sIt)
01387         {
01388             v.position = *sIt;
01389             v.texCoord[0] = ((*cIt)[0] - xMin) * scale;
01390             v.texCoord[1] = ((*cIt)[1] - zMin) * scale;
01391 
01392             storeVertex(v, indicesPtr);
01393         }
01394     }
01395 
01396     storePrimitive(GL_TRIANGLE_FAN, lensPtr, typesPtr);
01397 }

void ExtrusionSurface::storeSweepSurfaceWithNormals ( GeoIndicesUI32Ptr  indicesPtr,
GeoPLengthsUI32Ptr  lensPtr,
GeoPTypesUI8Ptr  typesPtr 
) [private]

Stores the sweep surface obtained by extruding the cross-section along the spine into the supplied field containers. The surface normals are also generated. The _creaseAngle is respected during primitive generation.

Definition at line 862 of file OSGExtrusionGeometry.cpp.

References _ccw, _creaseAngle, _crossSection, _grid, _spine, calcSweepSurfaceFaceNormals(), calcVertexNormal(), osg::VectorInterface< ValueTypeT, StorageInterfaceT >::enclosedAngle(), osg::Eps, osg::NullFC, storePrimitive(), and storeVertex().

Referenced by createGeometry().

00865 {
00866     assert(indicesPtr != NullFC);
00867     assert(lensPtr    != NullFC);
00868     assert(typesPtr   != NullFC);
00869 
00870     // we need to calculate the face normals first
00871     calcSweepSurfaceFaceNormals();
00872  
00873     if(_ccw)
00874     {
00875         // The current face is the face in quadrant 1 of the vertex
00876         // grid[i,j]. Stripes are generated in positive j direction
00877         // along the cross-section.
00878         UInt32 spineEnd = _spine.size() - 1;
00879         UInt32 cSEnd = _crossSection.size() - 1;
00880         for(UInt32 i = 0; i < spineEnd; i++)
00881         {
00882             // upper left vertex of current quad face
00883             // current face is located in 4th quadrant of vertex
00884             calcVertexNormal(&_grid[i+1][0], 3);
00885             storeVertex(_grid[i+1][0], indicesPtr);
00886 
00887             // lower left vertex of current quad face
00888             // current face is located in 1st quadrant of vertex            
00889             calcVertexNormal(&_grid[i][0], 0);
00890             storeVertex(_grid[i][0], indicesPtr);
00891 
00892             Vec3f fN = _grid[i][0].adjFaceNormals[0];
00893             for(UInt32 j = 0; j < cSEnd; j++)
00894             {
00895                 // The next face is the face in quadrant 1 of the vertex
00896                 // grid[i,j+1]                
00897                 Vec3f fNNext = _grid[i][j+1].adjFaceNormals[0];
00898 
00899                 // if the creaseAngle is too small the strip has to be split,
00900                 // because the normals are not shared along the common edge
00901                 // of the current and the next face.
00902                 // if j + 1 == csEnd the current quad is the last one
00903                 if((fN.enclosedAngle(fNNext) + Eps > _creaseAngle - Eps)
00904                    || (j + 1 == cSEnd))
00905                 {
00906                     // upper right vertex of current quad face
00907                     // current face is located in 3rd quadrant of vertex
00908                     calcVertexNormal(&_grid[i+1][j+1], 2);
00909                     storeVertex(_grid[i+1][j+1], indicesPtr);
00910 
00911                     // upper right vertex of current quad face
00912                     // current face is located in 2nd quadrant of vertex
00913                     calcVertexNormal(&_grid[i][j+1], 1);
00914                     storeVertex(_grid[i][j+1], indicesPtr);
00915                     
00916                     // terminate strip
00917                     storePrimitive(GL_TRIANGLE_STRIP, lensPtr, typesPtr);
00918                 }
00919 
00920                 // Either the strip was split above or not. In both cases
00921                 // continue/begin new strip if there's still a quad left
00922                 if(j + 1 < cSEnd)
00923                 {
00924                     
00925                     // upper left vertex of _next_ quad face
00926                     // next face is located in 4th quadrant of vertex
00927                     calcVertexNormal(&_grid[i+1][j+1], 3); 
00928                     storeVertex(_grid[i+1][j+1], indicesPtr);
00929                     
00930                     // lower left vertex of _next_ quad face
00931                     // next face is located in 1st quadrant of vertex
00932                     calcVertexNormal(&_grid[i][j+1], 0);
00933                     storeVertex(_grid[i][j+1], indicesPtr);
00934                 }
00935 
00936                 // update face normal
00937                 fN = fNNext;                
00938             }
00939         }
00940     }
00941     else // cw case
00942     {
00943         // The current face is the face in quadrant 1 of the vertex
00944         // grid[i,j-1]. Stripes are generated in negative j direction
00945         // along the cross-section.
00946         for(UInt32 i = 0; i < _spine.size() - 1; i++)
00947         {
00948             UInt32 cSEnd = _crossSection.size() - 1;
00949 
00950             // begin new triangle strip
00951             calcVertexNormal(&_grid[i+1][cSEnd], 2);
00952             storeVertex(_grid[i+1][cSEnd], indicesPtr);
00953 
00954             calcVertexNormal(&_grid[i][cSEnd], 1);
00955             storeVertex(_grid[i][cSEnd], indicesPtr);
00956 
00957             Vec3f fN = _grid[i][cSEnd].adjFaceNormals[0];            
00958             for(UInt32 j = cSEnd; j > 0; j--)
00959             {
00960                 Vec3f fNNext = _grid[i][j - 1].adjFaceNormals[0];
00961                 if((fN.enclosedAngle(fNNext) + Eps > _creaseAngle - Eps)
00962                    || (j == 1))
00963                 {
00964                     calcVertexNormal(&_grid[i + 1][j - 1], 3);
00965                     storeVertex(_grid[i + 1][j - 1], indicesPtr);
00966                     
00967                     calcVertexNormal(&_grid[i][j - 1], 0);
00968                     storeVertex(_grid[i][j - 1], indicesPtr);
00969                     
00970                     // terminate strip
00971                     storePrimitive(GL_TRIANGLE_STRIP, lensPtr, typesPtr);
00972                 }
00973 
00974                 if(j > 1) // still one quad to go
00975                 {
00976                     calcVertexNormal(&_grid[i + 1][j - 1], 2);
00977                     storeVertex(_grid[i + 1][j - 1], indicesPtr);
00978                 
00979                     calcVertexNormal(&_grid[i][j - 1], 1);
00980                     storeVertex(_grid[i][j - 1], indicesPtr);
00981                 }
00982                 // update face normal
00983                 fN = fNNext;                
00984             }
00985         }
00986     }
00987 }

void ExtrusionSurface::storeSweepSurfaceWithoutNormals ( GeoIndicesUI32Ptr  indicesPtr,
GeoPLengthsUI32Ptr  lensPtr,
GeoPTypesUI8Ptr  typesPtr 
) [private]

Stores the sweep surface obtained by extruding the cross-section along the spine into the supplied field containers. Normals are not generated.

Definition at line 834 of file OSGExtrusionGeometry.cpp.

References _crossSection, _grid, _spine, osg::NullFC, storePrimitive(), and storeVertex().

Referenced by createGeometry().

00837 {
00838     assert(indicesPtr != NullFC);
00839     assert(lensPtr    != NullFC);
00840     assert(typesPtr   != NullFC);
00841 
00842     for(UInt32 i = 0; i < _spine.size() - 1; i++)
00843     {
00844         for(UInt32 j = 0; j < _crossSection.size(); j++)
00845         {
00846             Vertex v;
00847             // begin new triangle strip
00848             v = _grid[i+1][j];
00849 
00850             // store position (and texcoord if available)
00851             storeVertex(v, indicesPtr);
00852 
00853             v = _grid[i][j];
00854             // store position (and texcoord if available)
00855             storeVertex(v, indicesPtr);
00856         }
00857         // store row strip
00858         storePrimitive(GL_TRIANGLE_STRIP, lensPtr, typesPtr);
00859     }
00860 }

void ExtrusionSurface::storeMaps ( GeoPositions3fPtr  positionsPtr,
GeoNormals3fPtr  normalsPtr,
GeoTexCoords2fPtr  texCoordsPtr 
) [private]

Stores the accumulated property data in the supplied field containers

Definition at line 1410 of file OSGExtrusionGeometry.cpp.

References _createNormals, _createTexCoords, _normalMap, _posMap, _texCoordMap, osg::beginEditCP(), osg::endEditCP(), FDEBUG, osg::GeoProperty< GeoPropertyDesc >::GeoPropDataFieldMask, and osg::NullFC.

Referenced by createGeometry().

01413 {
01414     assert(posPtr != NullFC);
01415 
01416     FDEBUG(("OSGExtrusion:storeMaps: position map size:    %d\n", _posMap.size()));
01417     FDEBUG(("OSGExtrusion:storeMaps: normal map size:      %d\n", _normalMap.size()));
01418     FDEBUG(("OSGExtrusion:storeMaps: tex coord map size:   %d\n", _texCoordMap.size()));
01419 
01420     // write shared positions
01421     beginEditCP(posPtr, GeoPositions3f::GeoPropDataFieldMask);
01422 
01423     posPtr->resize(_posMap.size());
01424     for(PositionMap::iterator pMIt = _posMap.begin();
01425         pMIt != _posMap.end(); ++pMIt)
01426     {
01427         posPtr->setValue(pMIt->first, pMIt->second);
01428     }
01429 
01430     endEditCP(posPtr, GeoPositions3f::GeoPropDataFieldMask);
01431 
01432     // write shared vertex normals
01433     if(_createNormals)
01434     {
01435         assert(normalsPtr != NullFC);
01436         beginEditCP(normalsPtr, GeoNormals3f::GeoPropDataFieldMask);
01437 
01438         normalsPtr->resize(_normalMap.size());
01439         for(NormalMap::iterator nMIt = _normalMap.begin();
01440             nMIt != _normalMap.end(); ++nMIt)
01441         {
01442             normalsPtr->setValue(nMIt->first, nMIt->second);
01443         }
01444 
01445         endEditCP(normalsPtr, GeoNormals3f::GeoPropDataFieldMask);
01446     }
01447 
01448     // write shared texture coordinates
01449     if(_createTexCoords)
01450     {
01451         assert(texPtr != NullFC);
01452         beginEditCP(texPtr, GeoTexCoords2f::GeoPropDataFieldMask);
01453 
01454         texPtr->resize(_texCoordMap.size());
01455         for(TexCoordMap::iterator tMIt = _texCoordMap.begin();
01456             tMIt != _texCoordMap.end(); ++tMIt)
01457         {
01458             texPtr->setValue(tMIt->first, tMIt->second);
01459         }
01460 
01461         endEditCP(texPtr, GeoTexCoords2f::GeoPropDataFieldMask);
01462     }
01463 }

void osg::ExtrusionSurface::storeVertex ( const Vertex vertex,
GeoIndicesUI32Ptr  indicesPtr 
) [inline, private]

Stores a property index in the supplied field container and the property itself into an internal map

Definition at line 404 of file OSGExtrusionGeometry.inl.

References _createNormals, _createTexCoords, _normalMap, _posMap, _texCoordMap, _totalVertexCount, _vertexCount, osg::ExtrusionSurface::Vertex::normal, osg::NullFC, osg::ExtrusionSurface::Vertex::position, SLOG, store(), and osg::ExtrusionSurface::Vertex::texCoord.

Referenced by storeConvexCap(), storeFaceNormalGeo(), storeSweepSurfaceWithNormals(), storeSweepSurfaceWithoutNormals(), and storeVertexNormalGeo().

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 }

void osg::ExtrusionSurface::storePrimitive ( GLenum  type,
GeoPLengthsUI32Ptr  lensPtr,
GeoPTypesUI8Ptr  typesPtr 
) [inline, private]

Stores the _vertexCount into the lengths field container and the supplied primivite type into the types field container. The _vertexCount is reset to 0.

Definition at line 452 of file OSGExtrusionGeometry.inl.

References _primitiveCount, _totalVertexCount, _vertexCount, FFATAL, and osg::NullFC.

Referenced by storeConvexCap(), storeFaceNormalGeo(), storeSweepSurfaceWithNormals(), storeSweepSurfaceWithoutNormals(), and storeVertexNormalGeo().

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 }

template<typename PType>
UInt32 osg::ExtrusionSurface::store ( PType  property,
std::map< PType, UInt32, vecless< PType > > &  propertyIndexMap 
) [inline, private]

Returns a new index for the supplied property and stores it the given map

Definition at line 510 of file OSGExtrusionGeometry.inl.

References SLOG.

Referenced by store(), and storeVertex().

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 }

template<typename PType>
void osg::ExtrusionSurface::store ( const PType  property,
std::map< PType, UInt32, vecless< PType > > &  propertyIndexMap,
GeoIndicesUI32Ptr  indicesPtr 
) [inline, private]

Returns a new index for the supplied property, stores it as (property -> index) in the given map. The obtained index is directly stored in the supplied field container

Definition at line 546 of file OSGExtrusionGeometry.inl.

References osg::NullFC, and store().

00549 {
00550     assert(indicesPtr != NullFC);
00551     indicesPtr->push_back(store(property, propertyIndexMap));
00552 }

ExtrusionSurface::Pnt3fConstItPair osg::ExtrusionSurface::getPrevAndNextIt ( const Pnt3fConstIt pIt  )  [inline, private]

Returns a pair of iterators pointing to the previous and the next spine point. The iterators are wrapped around at the ends if the spine is closed and saturated otherwise

Definition at line 100 of file OSGExtrusionGeometry.inl.

References _spine, and _spineClosed.

Referenced by calcNonUnitYAxis(), and calcNonUnitZAxis().

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 }

Vec3f osg::ExtrusionSurface::calcNonUnitYAxis ( const Pnt3fConstIt pIt  )  [inline, private]

Returns the non-normalized Y-Axis at pIt

Definition at line 140 of file OSGExtrusionGeometry.inl.

References getPrevAndNextIt().

Referenced by calcYAxes().

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 }

Vec3f osg::ExtrusionSurface::calcNonUnitZAxis ( const Pnt3fConstIt pIt  )  [inline, private]

Returns the non-normalized Z-Axis at pIt

Definition at line 165 of file OSGExtrusionGeometry.inl.

References osg::VectorInterface< ValueTypeT, StorageInterfaceT >::cross(), and getPrevAndNextIt().

Referenced by calcZAxes().

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 }

Vec3f osg::ExtrusionSurface::calcXAxis ( const MatrixConstIt pIt  )  [inline, private]

Returns the normalized X-Axis at pIt

Definition at line 205 of file OSGExtrusionGeometry.inl.

References osg::VectorInterface< ValueTypeT, StorageInterfaceT >::cross(), and osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize().

Referenced by calcXAxes().

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 }

Vec3f osg::ExtrusionSurface::calcTriangleFaceNormal ( const Pnt3f a,
const Pnt3f b,
const Pnt3f c 
) [inline, private]

Returns the non-normalized right handed face normal of the three points a,b,c, if _ccw is true and the negated otherwise

Definition at line 292 of file OSGExtrusionGeometry.inl.

References _ccw, and osg::VectorInterface< ValueTypeT, StorageInterfaceT >::cross().

Referenced by calcQuadFaceNormal().

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 }

Vec3f osg::ExtrusionSurface::calcQuadFaceNormal ( const Pnt3f a,
const Pnt3f b,
const Pnt3f c,
const Pnt3f d 
) [inline, private]

Returns the normalized right handed face normal of the quad given by the four points a,b,c, if _ccw is true and the negated face normal otherwise

Definition at line 310 of file OSGExtrusionGeometry.inl.

References calcTriangleFaceNormal(), osg::Eps, osg::VectorInterface< ValueTypeT, StorageInterfaceT >::length(), and osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize().

Referenced by calcSweepSurfaceFaceNormals().

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 }

void osg::ExtrusionSurface::calcVertexNormal ( Vertex vertexPtr,
UInt32  faceIndex 
) [inline, private]

Returns the normalized vertex normal obtained by averaging all face normals of adjacent faces enclosing an angle less than _creaseAngle with the face normal given by vertexPtr->adjFaceNormals[faceIndex]

Definition at line 354 of file OSGExtrusionGeometry.inl.

References _creaseAngle, osg::ExtrusionSurface::Vertex::adjFaceNormals, osg::VectorInterface< ValueTypeT, StorageInterfaceT >::enclosedAngle(), osg::Eps, osg::ExtrusionSurface::Vertex::normal, and osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize().

Referenced by storeSweepSurfaceWithNormals().

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 }

bool ExtrusionSurface::isLeft ( const Pnt2f a,
const Pnt2f b 
) [inline, private]

Definition at line 996 of file OSGExtrusionGeometry.cpp.

References osg::VectorInterface< ValueTypeT, StorageInterfaceT >::dot(), and osg::VectorInterface< ValueTypeT, StorageInterfaceT >::normalize().

Referenced by calcWindingNumber().

00997 {
00998     Vec2f d = b - a;
00999     d.normalize();
01000     // compute the normal pointing into the _right_ half plane of the oriented
01001     // line
01002     Vec2f n = Vec2f(d.y(), -d.x());
01003     // the dot product is >0 when two vectors point into the same direction
01004     return n.dot(a) > 0.f;
01005 }

Real32 ExtrusionSurface::computeMinYAbs ( const std::vector< Pnt2f > &  contour,
Real32  alpha 
) [private]

Definition at line 1013 of file OSGExtrusionGeometry.cpp.

References osg::osgabs(), osg::osgcos(), and osg::osgsin().

Referenced by calcBetterRotationAngle().

01015 {
01016     const Real32 sinAlpha = osgsin(alpha);
01017     const Real32 cosAlpha = osgcos(alpha);
01018 
01019     Real32 minYAbs = 1.f;
01020     for(std::vector<Pnt2f>::const_iterator it = contour.begin();
01021         it != contour.end(); ++it)
01022     {
01023         Real32 y = sinAlpha * it->x() + cosAlpha * it->y();
01024         if(osgabs(y) < minYAbs)
01025             minYAbs = y;
01026     }
01027 
01028     return minYAbs;
01029 }

Real32 ExtrusionSurface::calcBetterRotationAngle ( const std::vector< Pnt2f > &  contour,
UInt32  nAngles 
) [private]

Definition at line 1038 of file OSGExtrusionGeometry.cpp.

References computeMinYAbs(), and osg::Pi.

Referenced by calcOptimizedContour().

01040 {
01041     Real32 maxMinY = 0.f;
01042     Real32 bestAlpha = 0.f;
01043 
01044     Real32 alphaInc = 2 * Pi / nAngles;
01045     for(Real32 alpha = 0.f; alpha < 2 * Pi; alpha += alphaInc)
01046     {
01047         Real32 minYAlpha = computeMinYAbs(contour, alpha);
01048         if(minYAlpha > maxMinY)
01049         {
01050             maxMinY = minYAlpha;
01051             bestAlpha = alpha;
01052         }
01053     }
01054 
01055     return bestAlpha;
01056 }

bool ExtrusionSurface::calcOptimizedContour ( const std::vector< Pnt2f > &  contour,
const Pnt2f point,
std::vector< Pnt2f > *  optimizedContour 
) [private]

Definition at line 1065 of file OSGExtrusionGeometry.cpp.

References calcBetterRotationAngle(), osg::Eps, FDEBUG, FWARNING, osg::osgabs(), osg::osgcos(), osg::osgsin(), and p.

Referenced by calcWindingNumber().

01068 {
01069     // copy the input
01070     std::vector<Pnt2f> coords(contour);
01071 
01072     // translate the reference point to the origin
01073     // and compute a scale factor
01074     Real32 maxLen = std::numeric_limits<Real32>::min();
01075     Real32 minLen = std::numeric_limits<Real32>::max();
01076 
01077     for(std::vector<Pnt2f>::iterator it = coords.begin();
01078             it != coords.end(); ++it)
01079     {
01080         // translate the problem to the origin
01081         *it -= Vec2f(point);
01082         Real32 len = Vec2f(*it).length();
01083 
01084         if(len > maxLen)  maxLen = len;
01085         if(len < minLen)  minLen = len;
01086     }
01087 
01088     if(maxLen < Eps)
01089     {
01090         FWARNING(("OSGExtrusion:calcOptimizedContour: Contour completely degenerate\n"));
01091         return false;
01092     }
01093 
01094     if(minLen < Eps)
01095     {
01096         FWARNING(("OSGExtrusion:calcOptimizedContour: Reference point on curve\n"));
01097         return false;
01098     }
01099 
01100     // rescale the contour to the unit disk and determine the minimal
01101     // absolute y coordinate
01102     Real32 minAbsY = 1.f;
01103     for(std::vector<Pnt2f>::iterator it = coords.begin();
01104             it != coords.end(); ++it)
01105     {
01106         *it /= maxLen;
01107         // osgabs(it->y()) <= 1.f after rescale
01108         if(osgabs(it->y()) < minAbsY)
01109             minAbsY = osgabs(it->y());
01110     }
01111 
01112     optimizedContour->clear();
01113     optimizedContour->reserve(coords.size());
01114     
01115     if(minAbsY > Eps) // we can probably determine all crossings
01116     {
01117         optimizedContour->assign(coords.begin(), coords.end());
01118     }
01119     else // try to rotate the contour
01120     {
01121         // we need to rotate the contour to get a reasonable result
01122         FDEBUG(("OSGExtrusion:calcOptimizedContour: Contour needs rotation\n"));
01123         // compute the best rotation angle for 64 equal partitions 
01124         // of the circle
01125         Real32 alpha = calcBetterRotationAngle(contour, 64);
01126         FDEBUG(("OSGExtrusion:calcOptimizedContour: Rotation angle is: %f\n",
01127                 alpha));
01128 
01129         Real32 sinAlpha = osgsin(alpha);
01130         Real32 cosAlpha = osgcos(alpha);
01131 
01132         // rotate the contour and copy it into the output vector
01133         for(std::vector<Pnt2f>::iterator it = coords.begin();
01134             it != coords.end(); ++it)
01135         {
01136             Pnt2f p;
01137             p[0] = cosAlpha * it->x() - sinAlpha * it->y();
01138             p[1] = sinAlpha * it->x() + cosAlpha * it->y();
01139 
01140             optimizedContour->push_back(p);
01141         }
01142     }
01143 
01144     // optimization successful
01145     return true;
01146 }

Int32 ExtrusionSurface::calcWindingNumber ( const std::vector< Pnt2f > &  contour,
const Pnt2f point 
) [private]

Definition at line 1156 of file OSGExtrusionGeometry.cpp.

References calcOptimizedContour(), and isLeft().

Referenced by storeConvexCap().

01158 {
01159     Int32 windingNumber = 0;
01160     std::vector<Pnt2f> coords;
01161 
01162     // translate contour to origin and rotate it to a better position
01163     calcOptimizedContour(contour, point, &coords);
01164 
01165     const Pnt2f *prevPoint = &(coords[coords.size() - 1]);
01166     for(UInt32 i = 0; i < coords.size(); ++i)
01167     {
01168         const Pnt2f *curPoint = &(coords[i]);
01169         if(prevPoint->y() < 0.f)
01170         {
01171             // upward crossing
01172             if(curPoint->y() > 0.f)
01173             {
01174                 if(isLeft(*prevPoint, *curPoint) == true)
01175                     windingNumber++;
01176             }
01177         }
01178         else // prevPoint->y() > 0.f
01179         {
01180             // downward crossing
01181             if(curPoint->y() < 0.f)
01182             {
01183                 if(isLeft(*prevPoint, *curPoint) == false)
01184                     windingNumber--;
01185             }
01186         }
01187         prevPoint = curPoint;
01188     }
01189 
01190     return windingNumber;
01191 }

void ExtrusionSurface::storeFaceNormalGeo ( GeoIndicesUI32Ptr  indicesPtr,
GeoPLengthsUI32Ptr  lensPtr,
GeoPTypesUI8Ptr  typesPtr 
) [private]

Definition at line 1936 of file OSGExtrusionGeometry.cpp.

References _createNormals, _createTexCoords, _grid, osg::ExtrusionSurface::Vertex::adjFaceNormals, osg::ExtrusionSurface::Vertex::normal, osg::ExtrusionSurface::Vertex::position, storePrimitive(), and storeVertex().

Referenced by createGeometry().

01939 {
01940     if(!_createNormals || !_createTexCoords)
01941         return;
01942 
01943     for(UInt32 i = 0; i < _grid.size(); i++)
01944     {
01945         for(UInt32 j = 0; j < _grid[i].size(); j++)
01946         {
01947             Vertex a = _grid[i][j];
01948             a.normal = Vec3f();
01949 
01950             for(UInt32 k = 0; k < 4; k++)
01951             {
01952                 Vertex b_k =_grid[i][j];
01953                 b_k.normal = Vec3f();
01954                 b_k.position += 0.3f * a.adjFaceNormals[k];
01955 
01956                 storeVertex(a, indicesPtr);
01957                 storeVertex(b_k, indicesPtr);
01958 
01959                 storePrimitive(GL_LINES, lensPtr, typesPtr);
01960             }
01961         }
01962     }
01963 }

void ExtrusionSurface::storeVertexNormalGeo ( GeoIndicesUI32Ptr  indicesPtr,
GeoPLengthsUI32Ptr  lensPtr,
GeoPTypesUI8Ptr  typesPtr 
) [private]

Definition at line 1889 of file OSGExtrusionGeometry.cpp.

References _createNormals, _createTexCoords, _normalMap, _posMap, osg::ExtrusionSurface::Vertex::normal, osg::ExtrusionSurface::Vertex::position, storePrimitive(), storeVertex(), and osg::ExtrusionSurface::Vertex::texCoord.

Referenced by createGeometry().

01892 {
01893     if(!_createNormals || !_createTexCoords)
01894         return;
01895 
01896     std::vector<Vec3f> nRevTable(_normalMap.size());
01897     std::vector<Pnt3f> pRevTable(_posMap.size());
01898 
01899     NormalMap::iterator   nIt = _normalMap.begin();
01900     PositionMap::iterator pIt = _posMap.begin();
01901 
01902     // build a lookup table of normal indices to vertex normals
01903     for(; nIt != _normalMap.end(); ++nIt)
01904         nRevTable[nIt->second] = nIt->first;
01905 
01906     // build a lookup table of position indices to vertex positions
01907     for(; pIt != _posMap.end(); ++pIt)
01908         pRevTable[pIt->second] = pIt->first;
01909 
01910     UInt32 prevN = indicesPtr->size();
01911     UInt32 i = 0;
01912 
01913     Vertex v;
01914 
01915     v.normal = Vec3f(0.f, 0.f, 0.f);
01916     v.texCoord = Vec2f(0.f, 0.f);
01917 
01918     while(i < prevN)
01919     {
01920         v.position = pRevTable[indicesPtr->getValue(i)];
01921         storeVertex(v, indicesPtr);
01922         
01923         v.position += 0.3f * nRevTable[indicesPtr->getValue(i+1)];
01924         storeVertex(v, indicesPtr);
01925         storePrimitive(GL_LINES, lensPtr, typesPtr);
01926 
01927         i+=3;
01928     }
01929 }


Member Data Documentation

The orientation values rotating the cross section plane (CP) in R^3

Definition at line 268 of file OSGExtrusionGeometry.h.

Referenced by calcTransforms(), createGeometry(), and ExtrusionSurface().

std::vector<Vec2f> osg::ExtrusionSurface::_scale [private]

The cross-section scale parameters of the extrusion surface

Definition at line 271 of file OSGExtrusionGeometry.h.

Referenced by calcTransforms(), ExtrusionSurface(), and refineScale().

std::vector<Pnt3f> osg::ExtrusionSurface::_spine [private]

The crease angle of the extrusion surface

Definition at line 277 of file OSGExtrusionGeometry.h.

Referenced by calcVertexNormal(), and storeSweepSurfaceWithNormals().

If true, a begin cap is to be generated

Definition at line 280 of file OSGExtrusionGeometry.h.

Referenced by createGeometry().

If true, an end cap is to be generated

Definition at line 283 of file OSGExtrusionGeometry.h.

Referenced by createGeometry().

If true, the ordering of the generated primitives is ccw w.r.t. the generated normals

Definition at line 288 of file OSGExtrusionGeometry.h.

Referenced by calcTriangleFaceNormal(), storeConvexCap(), and storeSweepSurfaceWithNormals().

If true, the cross section is assumed to be convex

Definition at line 291 of file OSGExtrusionGeometry.h.

Referenced by createGeometry(), and storeConvexCap().

If true, the cross section of the extrusion surface is assumend to be closed

Definition at line 297 of file OSGExtrusionGeometry.h.

Referenced by calcSweepSurfaceFaceNormals(), determineTopology(), refineCrossSection(), and storeConvexCap().

If true, the spine of the extrusion surface is assumed to be closed

Definition at line 300 of file OSGExtrusionGeometry.h.

Referenced by calcSweepSurfaceFaceNormals(), determineTopology(), getPrevAndNextIt(), refineScale(), and refineSpine().

If true, the spine contains at least one non-trivial collinear segment and all other parts consist of coinciding points

Definition at line 305 of file OSGExtrusionGeometry.h.

Referenced by calcTransforms(), calcXAxes(), and calcZAxes().

If true, all points of the spine coincide

Definition at line 308 of file OSGExtrusionGeometry.h.

Referenced by calcTransforms(), calcXAxes(), and calcYAxes().

If true, normals are generated

Definition at line 311 of file OSGExtrusionGeometry.h.

Referenced by createGeometry(), storeConvexCap(), storeFaceNormalGeo(), storeMaps(), storeVertex(), and storeVertexNormalGeo().

If true, texture coordinates are generated

Definition at line 314 of file OSGExtrusionGeometry.h.

Referenced by createGeometry(), storeFaceNormalGeo(), storeMaps(), storeVertex(), and storeVertexNormalGeo().

std::vector<Matrix> osg::ExtrusionSurface::_transform [private]

The affine transformations from the crossection plane to the spine aligned crossection planes

Definition at line 320 of file OSGExtrusionGeometry.h.

Referenced by calcSweepSurfacePositions(), calcTransforms(), calcXAxes(), calcYAxes(), calcZAxes(), and storeConvexCap().

The map containing (position, index) pairs for the extrusion surface

Definition at line 326 of file OSGExtrusionGeometry.h.

Referenced by calcSweepSurfacePositions(), createGeometry(), storeMaps(), storeVertex(), and storeVertexNormalGeo().

The map containing (vertex normal, index) pairs for the extrusion surface

Definition at line 331 of file OSGExtrusionGeometry.h.

Referenced by createGeometry(), storeMaps(), storeVertex(), and storeVertexNormalGeo().

The map containing (tex coord, index) pairs for the extrusion surface

Definition at line 336 of file OSGExtrusionGeometry.h.

Referenced by calcSweepSurfaceTexCoords(), createGeometry(), storeMaps(), and storeVertex().

The number of vertices stored in the current primitive

Definition at line 339 of file OSGExtrusionGeometry.h.

Referenced by storePrimitive(), and storeVertex().

The total number of vertices which have been stored until now

Definition at line 342 of file OSGExtrusionGeometry.h.

Referenced by createGeometry(), storePrimitive(), and storeVertex().

The total number of primitives stored in the geometry

Definition at line 345 of file OSGExtrusionGeometry.h.

Referenced by createGeometry(), and storePrimitive().


The documentation for this class was generated from the following files:

Generated on Mon Mar 17 11:13:27 2008 for OpenSG by  doxygen 1.5.5