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

OSGSurface.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                           OpenSG NURBS Library                            *
00003  *                                                                           *
00004  *                                                                           *
00005  * Copyright (C) 2001-2004 by the University of Bonn, Computer Graphics Group*
00006  *                                                                           *
00007  *                         http://cg.cs.uni-bonn.de/                         *
00008  *                                                                           *
00009  * contact: edhellon@cs.uni-bonn.de, guthe@cs.uni-bonn.de, rk@cs.uni-bonn.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 <stdlib.h>
00045 #include <stdio.h>
00046 
00047 
00048 #include <OSGConfig.h>
00049 
00050 #include <OSGAction.h>
00051 #include <OSGDrawAction.h>     
00052 #include <OSGRenderAction.h>   
00053 #include <OSGIntersectAction.h>
00054 #include <OSGRenderAction.h>
00055 #include <OSGSimpleMaterial.h>
00056 #include "OSGFatBorderChunk.h"
00057 
00058 #include <OSGGeometry.h>   
00059 #include <OSGGeoProperty.h>
00060 
00061 #include <OSGGeoFunctions.h>
00062 #include <OSGGeoPumpFactory.h>
00063 
00064 #include <OSGGL.h>
00065 #include <OSGGLU.h>
00066 #include <OSGGLEXT.h>
00067 
00068 #include "OSGSurface.h"
00069 
00070 /*
00071 #ifdef OSG_USE_ATI
00072 #  include <GL/glx.h>
00073 #  include <GL/glext.h>
00074 #  include <GL/glATI.h>
00075 #endif
00076 */
00077 
00078 #include "OSGBSplineTrimmedSurface.h"
00079 #include "OSGNurbsPatchSurface.h"
00080 #include "OSGSimplePolygon.h"
00081 
00082 #include "OSGpredicates.h" //for exactinit()
00083 
00084 OSG_USING_NAMESPACE
00085 
00086 #ifdef __sgi
00087 #pragma set woff 1174
00088 #endif
00089 
00090 namespace
00091 {
00092     static char cvsid_cpp[] = "@(#)$Id: FCTemplate_cpp.h,v 1.11 2002/01/14 18:38:54 dirk Exp $";
00093     static char cvsid_hpp[] = OSGSURFACE_HEADER_CVSID;
00094     static char cvsid_inl[] = OSGSURFACE_INLINE_CVSID;
00095 }
00096 
00097 #ifdef __sgi
00098 #pragma reset woff 1174
00099 #endif
00100 
00101 /***************************************************************************\
00102  *                               Types                                     *
00103 \***************************************************************************/
00104 
00105 /***************************************************************************\
00106  *                           Class variables                               *
00107 \***************************************************************************/
00108 
00109 const OSG::BitVector  Surface::CurveFieldMask = 
00110     (Surface::NumCurvesFieldMask |
00111      Surface::KnotLengthsFieldMask |
00112      Surface::DimensionsFieldMask |
00113      Surface::CurveControlPointsFieldMask |
00114      Surface::KnotsFieldMask |
00115      Surface::CurvesPerLoopFieldMask );
00116 
00117 const OSG::BitVector  Surface::SurfaceFieldMask = 
00118     (Surface::DimUFieldMask |
00119      Surface::DimVFieldMask |
00120      Surface::KnotsUFieldMask |
00121      Surface::KnotsVFieldMask |
00122      Surface::ControlPointsFieldMask |
00123      Surface::ErrorFieldMask |
00124      Surface::IsDelaunayFieldMask |
00125      Surface::TextureControlPointsFieldMask );
00126 
00127 
00128 
00143 /*----------------------- constructors & destructors ----------------------*/
00144 
00146 
00147 Surface::Surface(void) :
00148     Inherited()
00149 {
00150 //    std::cerr<<"constructor"<<std::endl;
00151     _trimmedSurface = NULL;
00152     _surfacePatch = NULL;
00153 }
00154 
00156 
00157 Surface::Surface(const Surface &source) :
00158     Inherited(source)
00159 {
00160 
00161     // We need these for every class and every aspect, so we have to 
00162     // allocate them here.
00163     _trimmedSurface = new BSplineTrimmedSurface;
00164     _surfacePatch = new CNurbsPatchSurface;
00165 }
00166 
00168 
00169 Surface::~Surface(void)
00170 {
00171     if ( _trimmedSurface != NULL )
00172         delete _trimmedSurface;
00173     if ( _surfacePatch != NULL )
00174         delete _surfacePatch;
00175 }
00176 
00177 
00178 /*----------------------------- class specific ----------------------------*/
00179 
00181 
00182 void Surface::initMethod (void)
00183 {
00184     DrawAction::registerEnterDefault( getClassType(),
00185         osgTypedMethodFunctor2BaseCPtrRef<Action::ResultE,
00186                                           MaterialDrawablePtr,
00187                                           CNodePtr,
00188                                           Action *>
00189                                           (&MaterialDrawable::drawActionHandler));
00190   
00191     RenderAction::registerEnterDefault( getClassType(),
00192         osgTypedMethodFunctor2BaseCPtrRef<Action::ResultE,
00193                                           SurfacePtr,
00194                                           CNodePtr,
00195                                           Action *>
00196                                           (&Geometry::renderActionHandler));
00197    
00198     IntersectAction::registerEnterDefault( getClassType(),
00199         osgTypedMethodFunctor2BaseCPtrRef<Action::ResultE,
00200                                          SurfacePtr,
00201                                          CNodePtr,
00202                                          Action *>(&Geometry::intersect));
00203 
00204     // init robust predicates
00205     ::exactinit();
00206     // turn appearance preserving tessellation on
00207     CErrorQuadTree::m_sbNormalApproximation = true;
00208 
00209 }
00210 
00212 
00213 void Surface::changed(BitVector whichField, UInt32 origin)
00214 {
00215     // only Client needs to tessellate / retessellate...
00216 //  if( ( origin & ChangedOrigin::Sync ) == 0 )
00217     {
00218         if( ( whichField & DimUFieldMask ) ||
00219             ( whichField & DimVFieldMask ) ||
00220             ( whichField & KnotsUFieldMask ) ||
00221             ( whichField & KnotsVFieldMask ) ||
00222             ( whichField & ControlPointsFieldMask ) ||
00223             ( whichField & NumCurvesFieldMask ) ||
00224             ( whichField & KnotLengthsFieldMask ) ||
00225             ( whichField & DimensionsFieldMask ) ||
00226             ( whichField & CurveControlPointsFieldMask ) ||
00227             ( whichField & KnotsFieldMask ) ||
00228             ( whichField & CurvesPerLoopFieldMask ) ||
00229             ( whichField & TextureControlPointsFieldMask ) )
00230         {
00231 //          SLOG <<"OSGSurface::changed: have to re-tessellate..." << endLog;
00232             SurfacePtr tmpPtr(*this);
00233             
00234             beginEditCP(tmpPtr, DirtyMaskFieldMask);
00235             {
00236                 getDirtyMask() |= TESSELLATE;
00237             }
00238             endEditCP  (tmpPtr, DirtyMaskFieldMask);
00239 
00240             Window::refreshGLObject(getSurfaceGLId());
00241         }
00242         else if( ( whichField & ErrorFieldMask ) ||
00243                  ( whichField & IsDelaunayFieldMask ) )
00244         {
00245 //          SLOG <<"OSGSurface: only error or delaunay mask" << endLog;
00246 //          std::cerr << origin << std::endl;
00247             SurfacePtr tmpPtr(*this);
00248             
00249             beginEditCP(tmpPtr, DirtyMaskFieldMask);
00250             {
00251                 getDirtyMask() |= RETESSELLATE;
00252             }
00253             endEditCP  (tmpPtr, DirtyMaskFieldMask);
00254 
00255             Window::refreshGLObject(getSurfaceGLId());
00256         }
00257     }
00258         
00259     // you should call the parent's changed() function in case
00260     // it needs to update inherited fields.
00261     Inherited::changed( whichField, origin );       
00262 //    std::cerr<<"Surface::changed:   texcoords ptr: " << getTexCoords() << std::endl;
00263 //    std::cerr<<"Surface::changed:   texcoords1 ptr: " << getTexCoords1() << std::endl;
00264     
00265 }
00266 
00267 
00269 /*
00270  *  This should be called from the user program once per frame for every
00271  *  patch. This returns the patch's desired error level for the
00272  * dynamic LOD balancing.
00273  */
00274 Real64 Surface::getDesiredError( Pnt3f viewPos, Real64 halfPixelSize )
00275 {
00276     Vec3f   dist;
00277     Real64  distance;
00278 
00279     FindClosestPoint( dist, viewPos );
00280     distance = dist.squareLength( );
00281 
00282 /*    if( distance < _max.dist2( _min ) )
00283     {
00284         FindClosestPointExact( dist, viewPos );
00285         distance = dist.squareLength( );
00286     }*/
00287 
00288     distance = sqrt( distance );
00289     // multiply the length of a line at distance one that projects 
00290     // to half a pixel with the distance of the current BB to get 
00291     // the maximum geometric error that is allowed for the surface 
00292     // within the BB
00293     Real64 desired_error = halfPixelSize * distance;
00294 
00295 //  std::cerr << distance << " " << desired_error << std::endl;
00296 
00297     if( desired_error < _max.dist( _min ) * 0.001 ) // 0.1% of bounding box
00298     {
00299 //          printf( "error below minimum => setting to minimal error %f\n", _max.dist( _min ) * 0.001 );
00300             desired_error = _max.dist( _min ) * 0.001;
00301     }
00302 
00303     return desired_error;
00304 }
00305 
00307 /*
00308  *  This should becalled from the render() function in order
00309  *  to only call this for nodes that are not culled.
00310  *
00311  */
00312 bool Surface::updateError( Pnt3f viewPos, Real64 halfPixelSize )        
00313 {
00314     Real64  d_max_error = getDesiredError( viewPos, halfPixelSize );
00315 
00316     // FIXME: this will convert the surface data once again,
00317     // not very effective... should only be retessellated !!!
00318     // FIXME: do we have to change the error in every frame ???
00319     Real32  current_error = getError();
00320     if ( d_max_error < current_error )
00321     {
00322         std::cerr << "retessellating due to too high error: " << d_max_error
00323                 << " " << current_error << std::endl;
00324         Real32 new_error = osgMin( d_max_error, current_error / 2.0 );
00325         SurfacePtr thisPtr =  SurfacePtr( this );    
00326         beginEditCP( thisPtr, Surface::ErrorFieldMask );
00327         {
00328             setError( d_max_error / 2.0 );
00329         }
00330         endEditCP( thisPtr, Surface::ErrorFieldMask );
00331     }
00332     else if ( d_max_error > current_error * 4.0 )
00333     {
00334         std::cerr << "retessellating due to too low error: " << d_max_error
00335                 << " " << current_error << std::endl;
00336         SurfacePtr thisPtr =  SurfacePtr( this );    
00337         beginEditCP( thisPtr, Surface::ErrorFieldMask );
00338         {
00339             setError( d_max_error / 2.0 );
00340         }
00341         endEditCP( thisPtr, Surface::ErrorFieldMask );
00342     }
00343     return true;  
00344 }
00345 
00346 
00347 // protected
00348 
00349 
00350 /* given an set of arbitrary bounding volumes
00351  * find the vector to the point on the volume that is closest to the view pos
00352 */
00353 void Surface::FindClosestPoint( Vec3f& rDist, const Pnt3f viewPos ) const
00354 {
00355     const UInt32    parent_cnt = getParents( ).size( );
00356     UInt32          parent_idx;
00357     Real64          min_dist = 1e300;
00358     Vec3f           temp_dist;
00359     Real64          curr_dist;
00360 
00361     for( parent_idx = 0; parent_idx < parent_cnt; ++parent_idx )
00362     {
00363         switch( getParents( )[ 0 ]->getVolume( ).getType( ) )
00364         {
00365         case DynamicVolume::BOX_VOLUME:
00366             {
00367                 Pnt3f   bb_min, bb_max;
00368 
00369                 getParents( )[ 0 ]->getVolume( ).getBounds( bb_min, bb_max );
00370 
00371 //              std::cerr << bb_min << " " << bb_max << " " << viewPos << std::endl;
00372 
00373                 if( viewPos[0] < bb_min[0] )
00374                 {
00375                     temp_dist[0] = viewPos[0] - bb_min[0];
00376                 }
00377                 else if( viewPos[0] > bb_max[0] )
00378                 {
00379                     temp_dist[0] = viewPos[0] - bb_max[0];
00380                 }
00381                 else
00382                 {
00383                     temp_dist[0] = 0.0;
00384                 }
00385 
00386                 if( viewPos[1] < bb_min[1] )
00387                 {
00388                     temp_dist[1] = viewPos[1] - bb_min[1];
00389                 }
00390                 else if( viewPos[1] > bb_max[1] )
00391                 {
00392                     temp_dist[1] = viewPos[1] - bb_max[1];
00393                 }
00394                 else
00395                 {
00396                     temp_dist[1] = 0.0;
00397                 }
00398 
00399                 if( viewPos[2] < bb_min[2] )
00400                 {
00401                     temp_dist[2] = viewPos[2] - bb_min[2];
00402                 }
00403                 else if( viewPos[2] > bb_max[2] )
00404                 {
00405                     temp_dist[2] = viewPos[2] - bb_max[2];
00406                 }
00407                 else
00408                 {
00409                     temp_dist[2] = 0.0;
00410                 }
00411             }
00412             break;
00413         case DynamicVolume::SPHERE_VOLUME:
00414             {
00415                 Real64  length;
00416                 Pnt3f   center;
00417 
00418                 getParents( )[ 0 ]->getVolume( ).getCenter( center );
00419                 temp_dist = center - viewPos;
00420                 length = temp_dist.length( ) - getParents( )[ 0 ]->getVolume( ).getScalarVolume( );
00421                 if( length > 0.0 )
00422                 {
00423                     temp_dist.normalize( );
00424                     temp_dist *= length;
00425                 }
00426                 else
00427                 {
00428                     temp_dist[0] = temp_dist[1] = temp_dist[2] = 0.0;
00429                 }
00430             }
00431             break;
00432         }
00433         curr_dist = temp_dist.squareLength( );
00434         if( curr_dist < min_dist )
00435         {
00436             min_dist = curr_dist;
00437             rDist = temp_dist;
00438         }
00439     }
00440 }
00441 
00442 
00443 void Surface::FindClosestPointExact( Vec3f& rDist, const Pnt3f viewPos ) const
00444 {
00445 //  const GeoPositions3fPtr cpcl_points = GeoPositions3fPtr::dcast( cpcl_geo->getPositions( ) );
00446     const GeoPositions3fPtr cpcl_points = GeoPositions3fPtr::dcast( getPositions() );
00447     const unsigned int      cui_idx_cnt = cpcl_points->getSize( );
00448     Pnt3f                   cl_pos;
00449     unsigned int            ui_idx;
00450     Vec3f                   cl_temp;
00451     double                  d_min = DBL_MAX;
00452     double                  d_temp;
00453 
00454     for( ui_idx = 0; ui_idx < cui_idx_cnt; ++ui_idx )
00455     {
00456         cl_pos = cpcl_points->getValue( ui_idx );
00457         cl_temp = cl_pos - viewPos;
00458         d_temp = cl_temp.squareLength( );
00459         if( d_temp <= d_min )
00460         {
00461             d_min = d_temp;
00462             rDist = cl_temp;
00463         }
00464     }
00465 }
00466 
00467 
00469 void Surface::tessellate( void )
00470 {
00471     // local variables for tessellation
00472 //    BSplineTrimmedSurface _trimmedSurface;  // internal representation of surface
00473 //    CNurbsPatchSurface cpatch;              // "tessellator" object
00474 //    simplepolygonvector tris;               // resulting indexed triangle set
00475     std::vector< SimplePolygon > tris;
00476     std::vector< Pnt3f > gverts;            // resulting vertices
00477     std::vector< Vec3f > norms;             // resulting surface normals
00478     std::vector< Pnt2f > texturecoords;     // resulting texture coordinates
00479     
00480     Int32 err = convertSurface();
00481     if ( err ) 
00482     {
00483         exit(-1);
00484         return;
00485     }
00486     if ( _sfTextureControlPoints.getValue() == NullFC )
00487     {
00488         err = tessellateSurface( tris, gverts, norms);
00489         if ( err ) return;    
00490         (void) buildSurface( tris, gverts, norms, texturecoords );
00491     }
00492     else
00493     {
00494 /*        
00495         // fragment program stuff (no normals)
00496         err = tessellateSurface( tris, gverts, texturecoords );
00497         if ( err ) return;
00498         (void) buildSurface( tris, gverts, texturecoords );
00499 */        
00500         // classic texturemapping stuff (both normals and texcoords)
00501         err = tessellateSurface( tris, gverts, norms, texturecoords );
00502         if ( err ) return;
00503         (void) buildSurface( tris, gverts, norms, texturecoords );
00504        
00505     }
00506     
00507     
00508 //        std::cerr<<"Surface::tessellate:   texcoords ptr: " << getTexCoords() << std::endl;
00509 //        std::cerr<<"Surface::tessellate:   texcoords1 ptr: " << getTexCoords1() << std::endl;
00510     
00511 //    buildPointSet();
00512 //    SLOG << "tessellate NI" << endLog;   
00513 }
00514 
00516 void Surface::reTessellate( void )
00517 {
00518     std::vector< SimplePolygon > tris;
00519     std::vector< Pnt3f > gverts;            // resulting vertices
00520     std::vector< Vec3f > norms;             // resulting surface normals
00521     std::vector< Pnt2f > texturecoords;     // resulting texture coordinates
00522 
00523     
00524     //FIXMEZ0RZ:
00525 //    _surfacePatch->setSurface( _trimmedSurface );
00526     if ( getError() < DCTP_EPS )
00527     {
00528 //        SLOG << " Surface::tessellate: correcting negative/zero error" <<
00529   //              endLog;
00530         setError( 0.2 );
00531     }
00532     
00533     _surfacePatch->setError ( getError() );
00534     SSurface *surfdata = _surfacePatch->getSurfaceData();
00535 
00536     if ( _sfTextureControlPoints.getValue() == NullFC )
00537     {
00538         _surfacePatch->getTessellation( gverts, norms, tris, getIsDelaunay() );
00539         (void) buildSurface( tris, gverts, norms, texturecoords );
00540     }
00541     else
00542     {
00543 /*        
00544         //normalmap stuff
00545         _surfacePatch->getTessellation( gverts, texturecoords, tris, getIsDelaunay() );
00546         (void) buildSurface( tris, gverts, texturecoords );
00547 */
00548    
00549        //classic texturemapped stuff
00550        _surfacePatch->getTessellation( gverts, norms, texturecoords, 
00551                                        tris, getIsDelaunay() );
00552        (void) buildSurface( tris, gverts, norms, texturecoords );
00553       
00554     }
00555     
00556 //        std::cerr<<"Surface::reTessellate:   texcoords ptr: " << getTexCoords() << std::endl;
00557 //        std::cerr<<"Surface::reTessellate:   texcoords1 ptr: " << getTexCoords1() << std::endl;
00558         
00559 }
00560 
00561 //internal
00562 Int32 Surface::convertSurface( void )
00563 {
00564 //    BSplineTrimmedSurface *_trimmedSurface = (BSplineTrimmedSurface*)trimsurf;
00565 
00566     GeoPositions3fPtr pPos = GeoPositions3fPtr::dcast(
00567         _sfControlPoints.getValue());
00568 
00569     if(_sfControlPoints.getValue() == NullFC)
00570     {
00571         SLOG << "Surface::tessellate: null surfacecontrol prop " << endLog;
00572         return -1;
00573     }
00574 
00575     MFPnt3f &_mfControlPoints = pPos->getField();
00576     
00577     // check knots, dimensions and control points
00578     UInt32 cpsize = _mfControlPoints.size();
00579     if( cpsize == 0 ) 
00580     {
00581         SLOG << "Surface::tessellate: null surfacecontrol points " << endLog;
00582         return -1;
00583     }
00584 /*    if ( cpdim !=3 && cpdim !=4 )
00585     {
00586         SLOG << "Surface::tessellate: wrong control point dimensions " <<
00587                 endLog;
00588     }*/
00589     UInt32 dimu = _sfDimU.getValue();
00590     UInt32 dimv = _sfDimV.getValue();
00591     if ( dimu == 0 || dimv == 0 )
00592     {
00593         SLOG << "Surface::tessellate: 0 dimensions " << endLog;
00594         return -1;
00595     }
00596     UInt32 knotusize = _mfKnotsU.size();
00597     UInt32 knotvsize = _mfKnotsV.size();
00598     if ( knotusize == 0 || knotvsize == 0 )
00599     {
00600         SLOG << "Surface::tessellate: empty knotvectors " << endLog;
00601         return -1;
00602     }
00603     UInt32 cpusize = knotusize - dimu - 1;
00604     UInt32 cpvsize = knotvsize - dimv - 1;
00605     if ( cpusize < 1 || cpvsize < 1 || cpusize * cpvsize != cpsize )
00606     {
00607         SLOG << cpusize << "x" << cpvsize << ":" << cpsize << endLog;
00608         SLOG << "Surface::tessellate: inconsistent attributes " << endLog;
00609         return -1;
00610     }
00611     if ( _sfNumCurves.getValue() == 0  ) // no trimming specified, add dummy trimming
00612     {
00613         Real64 umin = _mfKnotsU[ 0 ];
00614         Real64 vmin = _mfKnotsV[ 0 ];
00615         Real64 umax = _mfKnotsU[ knotusize - 1 ];
00616         Real64 vmax = _mfKnotsV[ knotvsize - 1 ];
00617         
00618         std::vector< Real64 > tmpknotvec(4);
00619         std::vector< Pnt2f > tmpcps(2);
00620         UInt32 dim = 1;
00621         tmpknotvec[ 0 ] = 0.0;
00622         tmpknotvec[ 1 ] = 0.0;
00623         tmpknotvec[ 2 ] = 1.0;
00624         tmpknotvec[ 3 ] = 1.0;
00625 
00626         // (umin, vmin) -> (umax,vmin)
00627         tmpcps[0][0] = umin; tmpcps[0][1] = vmin;
00628         tmpcps[1][0] = umax; tmpcps[1][1] = vmin;
00629         addCurve( dim, tmpknotvec, tmpcps );
00630 
00631         // (umax, vmin) -> (umax,vmax)
00632         tmpcps[0][0] = umax; tmpcps[0][1] = vmin;
00633         tmpcps[1][0] = umax; tmpcps[1][1] = vmax;
00634         addCurve( dim, tmpknotvec, tmpcps );
00635 
00636         // (umax, vmax) -> (umin,vmax)
00637         tmpcps[0][0] = umax; tmpcps[0][1] = vmax;
00638         tmpcps[1][0] = umin; tmpcps[1][1] = vmax;
00639         addCurve( dim, tmpknotvec, tmpcps );
00640 
00641         // (umin, vmax) -> (umin,vmin)
00642         tmpcps[0][0] = umin; tmpcps[0][1] = vmax;
00643         tmpcps[1][0] = umin; tmpcps[1][1] = vmin;
00644         addCurve( dim, tmpknotvec, tmpcps );
00645     }
00646 
00647     // now we checked everything, let's convert the surface+trimcurves
00648     // to the internal representation
00649     
00650     // first create surface
00651     BSplineTensorSurface tensor_surface;
00652     UInt32 i, j, k;
00653     vec3dmatrix qnet;
00654     vec3d vec3;
00655     qnet.resize( cpusize );
00656     
00657     for ( i = 0; i < cpusize; ++i )
00658     {
00659         qnet[ i ].resize( cpvsize );
00660         for ( j = 0; j < cpvsize; ++j )
00661         {
00662             //FIXME: rational support missing
00663             k = i * cpvsize + j;
00664             vec3.x = _mfControlPoints[k][0];
00665             vec3.y = _mfControlPoints[k][1];
00666             vec3.z = _mfControlPoints[k][2];
00667 //            SLOG << "qnet["<<i<<"]["<<j<<"]: " << vec3 << endLog;
00668 //            SLOG << "k: " << k << endLog;
00669 //            SLOG << "cps->getValue(k): " << cps->getValue(k) << endLog;
00670             qnet[ i ][ j ] = vec3;
00671         }
00672     }
00673     tensor_surface.setControlPointMatrix( qnet );
00674     // convert knotvectors
00675     dvector knotuvec(knotusize);
00676     dvector knotvvec(knotvsize);
00677     for ( i = 0; i < knotusize; ++i )
00678     {
00679         knotuvec[ i ] = _mfKnotsU[ i ];
00680     }
00681     for ( i = 0; i < knotvsize; ++i )
00682     {
00683         knotvvec[ i ] = _mfKnotsV[ i ];
00684     }
00685     tensor_surface.setKnotsAndDimension( knotuvec, dimu, knotvvec, dimv );
00686 //    std::cerr<<"0.2"<<std::endl;
00687 //    fprintf(stderr,"%x\n", _trimmedSurface);
00688     _trimmedSurface->setSurface( tensor_surface );
00689 //    std::cerr<<"0.3"<<std::endl;
00690 
00691     // now create/convert trimming loops
00692     trimmingloop trimloops;
00693     UInt32 cplsize = _mfCurvesPerLoop.size();
00694     trimloops.resize( cplsize );
00695     for ( i = 0; i < cplsize; ++i )
00696     {
00697         trimloops[ i ].resize( _mfCurvesPerLoop[ i ] );
00698     }
00699     UInt32 actknotoffset = 0;
00700     UInt32 actcpoffset = 0;
00701     UInt32 actloopoffset = 0;
00702     UInt32 actcurveno = 0;
00703     UInt32 acttrimcpsize = 0;
00704     dvector actknots;
00705     vec2dvector acttrimcps;
00706     
00707     BSplineCurve2D actcurve;
00708     for ( i = 0; i < trimloops.size(); ++i )
00709     {
00710         for ( j = 0; j < trimloops[i].size(); ++j )
00711         {
00712             actknots.resize( _mfKnotLengths[ actcurveno ] );
00713 //            SLOG << "Debug: _mfKnotLengths[ actcurveno ]: " <<
00714 //                    _mfKnotLengths[ actcurveno ] << " actcurveno: " <<
00715 //                    actcurveno << endLog;
00716             acttrimcpsize = actknots.size() - _mfDimensions[ actcurveno ] - 1;
00717             if ( acttrimcpsize < 1 ) 
00718             {
00719                 SLOG << "Surface::tessellate: wrong trimming curve attributes "
00720                         << endLog;
00721                 return -1;
00722             }
00723             acttrimcps.resize( acttrimcpsize );
00724             for ( k = 0; k < actknots.size(); ++k )
00725             {
00726                 actknots[ k ] = _mfKnots[ actknotoffset + k ];
00727             }
00728             actknotoffset += actknots.size();
00729             actcurve.setKnotsAndDimension( actknots, 
00730                                            _mfDimensions[ actcurveno ] );
00731 //            SLOG << "Debug: actknotoffset: " << actknotoffset << endLog;
00732 //            SLOG << "Debug: actcpoffset: " << actcpoffset << endLog;
00733 //            SLOG << "Debug: _mfCurveControlPoints.size(): " <<
00734 //                    _mfCurveControlPoints.size() << endLog;
00735 //            SLOG << "Debug: _mfKnots.size(): " << _mfKnots.size() << endLog;
00736 //            SLOG << "Debug: acttrimcps.size(): " << acttrimcps.size() << endLog;
00737             for ( k = 0; k < acttrimcpsize; ++k )
00738             {
00739 //                SLOG <<"Debug: k: " << k << endLog;
00740                 acttrimcps[ k ].x = _mfCurveControlPoints[ actcpoffset + k ][0];
00741                 acttrimcps[ k ].y = _mfCurveControlPoints[ actcpoffset + k ][1];
00742                 // FIXME: rational support missing
00743                 //acttrimcps[ k ].z = _mfCurveControlPoints[ actcpoffset + k ][2];
00744             }
00745             actcpoffset += acttrimcpsize;
00746             actcurve.setControlPointVector( acttrimcps );
00747 
00748             trimloops[i][j] = actcurve;
00749             actcurveno++;
00750         }
00751         
00752     }
00753     _trimmedSurface->setTrimmingLoops( trimloops );
00754     _trimmedSurface->normalize();
00755     
00756 //    global_surf = *_trimmedSurface;    
00757     return 0;   
00758 }
00759 
00760 
00761 //internal
00762 // normal, nontexturemapped
00763 Int32 Surface::tessellateSurface( std::vector< SimplePolygon > &triangles,
00764                                   std::vector< Pnt3f > &gverts, 
00765                                   std::vector< Vec3f > &norms )
00766 {
00767 //    BSplineTrimmedSurface *_trimmedSurface = (BSplineTrimmedSurface*)trimsurf;
00768 //    std::vector< SimplePolygon > *triangles = (std::vector< SimplePolygon > *)tris;
00769 //    CNurbsPatchSurface cpatch;              // "tessellator" object
00770     std::vector< Pnt2f > dummy;
00771     _surfacePatch->setSurface( _trimmedSurface, dummy, false );
00772     if ( _sfError.getValue() < DCTP_EPS )
00773     {
00774 //        SLOG << " Surface::tessellate: correcting negative/zero error" <<
00775 //                endLog;
00776         _sfError.setValue( 0.2 );
00777     }
00778     _surfacePatch->setError ( _sfError.getValue() );
00779     _surfacePatch->getTessellation( gverts, norms, triangles, getIsDelaunay() );
00780     SSurface *surfaceData =  _surfacePatch->getSurfaceData();
00781     _min = Pnt3d( surfaceData->clMin.x, surfaceData->clMin.y,
00782                   surfaceData->clMin.z );
00783     _max = Pnt3d( surfaceData->clMax.x, surfaceData->clMax.y,
00784                   surfaceData->clMax.z );
00785 #ifdef OSG_ARBITRARY_SPLIT
00786     _minParam = Pnt2d( surfaceData->clMinParam.x , surfaceData->clMinParam.y );
00787     _maxParam = Pnt2d( surfaceData->clMaxParam.x , surfaceData->clMaxParam.y );
00788 #endif
00789 
00790     
00791 //    std::cerr<< "min, max: [" << _min << "][" << _max << "]" << std::endl;
00792 //    std::cerr<< "minparam, maxparam: [" << _minParam << "][ " << _maxParam  << "]" << std::endl;
00793         
00794     return 0;
00795 }
00796 
00797 //internal
00798 // surface with texturemap, no normalmap!
00799 Int32 Surface::tessellateSurface( std::vector< SimplePolygon > &triangles,
00800                                   std::vector< Pnt3f > &gverts,
00801                                   std::vector< Vec3f > &norms,
00802                                   std::vector< Pnt2f > &texcoords )
00803 {
00804 //    BSplineTrimmedSurface *_trimmedSurface = (BSplineTrimmedSurface*)trimsurf;
00805 //    std::vector< SimplePolygon > *triangles = (std::vector< SimplePolygon > *)tris;
00806 //    CNurbsPatchSurface cpatch;              // "tessellator" object
00807     GeoTexCoords2fPtr pTexPos = GeoTexCoords2fPtr::dcast(_sfTextureControlPoints.getValue());
00808     std::vector<Pnt2f > tmptexcoords;
00809     UInt32 i;
00810     UInt32 s =  pTexPos->getField().size();
00811     for ( i = 0; i < s; ++i )
00812     {
00813         tmptexcoords.push_back( Pnt2f( pTexPos->getField()[i][0],
00814                                        pTexPos->getField()[i][1]));
00815     }
00816     _surfacePatch->setSurface( _trimmedSurface,
00817                                tmptexcoords,
00818                                true);
00819     if ( _sfError.getValue() < DCTP_EPS )
00820     {
00821 //        SLOG << " Surface::tessellate: correcting negative/zero error" <<
00822 //                endLog;
00823         _sfError.setValue( 0.2 );
00824     }
00825     _surfacePatch->setError ( _sfError.getValue() );
00826     _surfacePatch->getTessellation( gverts, norms, texcoords, triangles, getIsDelaunay() );
00827         
00828 //    std::cerr<< "norms.size(): " << norms.size() << " texcoords.size(): " <<
00829 //            texcoords.size() << std::endl;
00830     SSurface *surfaceData =  _surfacePatch->getSurfaceData();
00831     _min = Pnt3d( surfaceData->clMin.x, surfaceData->clMin.y,
00832                   surfaceData->clMin.z );
00833     _max = Pnt3d( surfaceData->clMax.x, surfaceData->clMax.y,
00834                   surfaceData->clMax.z );
00835 #ifdef OSG_ARBITRARY_SPLIT
00836     _minParam = Pnt2d( surfaceData->clMinParam.x , surfaceData->clMinParam.y );
00837     _maxParam = Pnt2d( surfaceData->clMaxParam.x , surfaceData->clMaxParam.y );
00838 #endif
00839 
00840     
00841 //    std::cerr<< "min, max: [" << _min << "][" << _max << "]" << std::endl;
00842 //    std::cerr<< "minparam, maxparam: [" << _minParam << "][ " << _maxParam  << "]" << std::endl;
00843         
00844     return 0;
00845 }
00846 
00847 //internal
00848 // surface with normalmaps
00849 Int32 Surface::tessellateSurface( std::vector< SimplePolygon > &triangles,
00850                                   std::vector< Pnt3f > &gverts, 
00851                                   std::vector< Pnt2f > &texcoords )
00852 {
00853 //    BSplineTrimmedSurface *_trimmedSurface = (BSplineTrimmedSurface*)trimsurf;
00854 //    std::vector< SimplePolygon > *triangles = (std::vector< SimplePolygon > *)tris;
00855 //    CNurbsPatchSurface cpatch;              // "tessellator" object
00856     GeoTexCoords2fPtr pTexPos = GeoTexCoords2fPtr::dcast(_sfTextureControlPoints.getValue());
00857     std::vector<Pnt2f > tmptexcoords;
00858     UInt32 i;
00859     UInt32 s =  pTexPos->getField().size();
00860     for ( i = 0; i < s; ++i )
00861     {
00862         tmptexcoords.push_back( Pnt2f( pTexPos->getField()[i][0],
00863                                        pTexPos->getField()[i][1]));
00864     }
00865     _surfacePatch->setSurface( _trimmedSurface,
00866                                tmptexcoords,
00867                                true);
00868     if ( _sfError.getValue() < DCTP_EPS )
00869     {
00870 //        SLOG << " Surface::tessellate: correcting negative/zero error" <<
00871 //                endLog;
00872         _sfError.setValue( 0.2 );
00873     }
00874     _surfacePatch->setError ( _sfError.getValue() );
00875     std::vector< Vec3f > norms;
00876     _surfacePatch->getTessellation( gverts, norms, triangles, false );
00877     _surfacePatch->getTessellation( gverts, texcoords, triangles, getIsDelaunay() );
00878     
00879     SSurface *surfaceData =  _surfacePatch->getSurfaceData();
00880     _min = Pnt3d( surfaceData->clMin.x, surfaceData->clMin.y,
00881                   surfaceData->clMin.z );
00882     _max = Pnt3d( surfaceData->clMax.x, surfaceData->clMax.y,
00883                   surfaceData->clMax.z );
00884 #ifdef OSG_ARBITRARY_SPLIT
00885     _minParam = Pnt2d( surfaceData->clMinParam.x , surfaceData->clMinParam.y );
00886     _maxParam = Pnt2d( surfaceData->clMaxParam.x , surfaceData->clMaxParam.y );
00887 #endif
00888 
00889     
00890 //    std::cerr<< "min, max: [" << _min << "][" << _max << "]" << std::endl;
00891 //    std::cerr<< "minparam, maxparam: [" << _minParam << "][ " << _maxParam  << "]" << std::endl;
00892         
00893     return 0;
00894 }
00895 
00896 
00897 
00898 
00899 //internal
00900 // normal surface
00901 Int32 Surface::buildSurface( std::vector< SimplePolygon > &triangles,
00902                              std::vector< Pnt3f > &gverts,
00903                              std::vector< Vec3f > &norms,
00904                              std::vector< Pnt2f > &texcoords )
00905 
00906 {
00907     // FIXME:
00908     //
00909     // At least on Linux/ATI with the current OpenGL drivers
00910     // TextureCoordinate1 doesn't get passed to the vertex program
00911     // unless there's TextureCoordinate0 present.
00912     // Might even crash older drivers, and might also be a problem
00913     // on Windows with some driver versions.
00914     //
00915     // Therefore the Surface uses TextureCoordinate0 to pass tangent
00916     // coordinates to the FatBorderChunk, thus texturing an OSGSurface
00917     // that uses FBs should begin in TextureCoordinate1. 
00918     // 
00919     // Currently only 1 texture is supported (copied to the fragment
00920     // program for further processing, and built by this function)
00921     // more can be easily added if it's a problem.
00922     //
00923     // FIXME END
00924     
00925     GeoPTypesPtr            pcl_type = getTypes();
00926     GeoPLengthsPtr          pcl_size = getLengths();
00927     GeoPositionsPtr         pcl_points = getPositions();
00928     GeoNormalsPtr           pcl_norms = getNormals();
00929     GeoIndicesPtr           pcl_indices = getIndices( );
00930     GeoTexCoordsPtr         pcl_texcoords = getTexCoords1();
00931     //FatBorderChunk parameters are always passed in TextureCoordinate.
00932     GeoTexCoords3fPtr       pcl_tangents = GeoTexCoords3fPtr::dcast( getTexCoords( ) );
00933     SimpleMaterialPtr       pcl_mat = SimpleMaterialPtr::dcast( getMaterial( ) );
00934     SurfacePtr              thisPtr = SurfacePtr( this );
00935 //  GeometryPtr         pcl_geo = Geometry::create( );
00936     SimplePolygon           *pcl_face;
00937     const UInt32            cui_faces = triangles.size();
00938     UInt32                  ui_face;
00939     BSplineTensorSurface    cl_surf = _trimmedSurface->getSurface();
00940     int                     i_err;
00941     vec3d                   cl_norm;
00942     const UInt32            cui_verts = gverts.size( );
00943     UInt32                  ui_vert;
00944     SSurface                *pt_surfdata = _surfacePatch->getSurfaceData( );
00945     const UInt32            cui_loop_cnt = pt_surfdata->vvclEdgeLoops.size( );
00946     UInt32                  ui_loop;
00947     UInt32                  ui_vertex_cnt;
00948     UInt32                  ui_idx;
00949     UInt32                  ui_used;
00950     vec3d                   *pcl_actn;
00951     vec3d                   *pcl_actv;
00952     vec3d                   *pcl_nextv;
00953     vec3d                   *pcl_prevv;
00954     Vec3f                   cl_v1, cl_v2, cl_tangent;
00955     std::vector< Int32 >    vi_new_idx( cui_verts );
00956     bool                    b_show_trimming = false;
00957    
00958     // check if material has the fat border chunk
00959     if( pcl_mat != NullFC )
00960     {
00961         const UInt32    cui_chunk_cnt = pcl_mat->getChunks( ).size( );
00962         UInt32          ui_chunk;
00963 
00964         for( ui_chunk = 0; ui_chunk < cui_chunk_cnt; ++ui_chunk )
00965         {
00966             if( FatBorderChunkPtr::dcast( pcl_mat->getChunks( ui_chunk ) ) != NullFC )
00967 //            if( VertexProgramChunkPtr::dcast( pcl_mat->getChunks( ui_chunk ) ) != NullFC )
00968             {
00969                 b_show_trimming = true;
00970                 break;
00971             }
00972         }
00973     }
00974 
00975 //    std::cerr<<"show_trimming: " << b_show_trimming << std::endl;
00976     if ( pcl_type == NullFC )
00977     {
00978         pcl_type = GeoPTypesUI8::create();
00979     }
00980     if ( pcl_size == NullFC )
00981     {
00982         pcl_size = GeoPLengthsUI32::create();
00983     }
00984     if ( pcl_points == NullFC )
00985     {
00986         pcl_points = GeoPositions3f::create();
00987     }
00988     if ( ( norms.size( ) > 0 ) && ( pcl_norms == NullFC ) )
00989     {
00990         pcl_norms = GeoNormals3f::create();
00991     }
00992     if ( pcl_indices == NullFC )
00993     {
00994         pcl_indices = GeoIndicesUI32::create();
00995     }
00996     if ( ( texcoords.size( ) > 0 ) && ( pcl_texcoords == NullFC ) )
00997     {
00998         pcl_texcoords = GeoTexCoords2f::create();
00999     }
01000     if( b_show_trimming )
01001     {
01002         if( pcl_tangents == NullFC )
01003         {
01004             pcl_tangents = GeoTexCoords3f::create( );
01005         }
01006     }
01007     else
01008     {
01009         if( pcl_tangents != NullFC )
01010         {
01011             beginEditCP( thisPtr, Geometry::TexCoordsFieldMask );
01012             {
01013                 setTexCoords( NullFC );
01014             }
01015             endEditCP( thisPtr, Geometry::TexCoordsFieldMask );
01016         }
01017     }
01018     
01019     // check for unused points
01020     for( ui_vert = 0; ui_vert < cui_verts; ++ui_vert )
01021     {
01022         vi_new_idx[ ui_vert ] = -1;
01023     }
01024     for( ui_face = 0; ui_face < cui_faces; ++ui_face )
01025     {
01026         pcl_face = &triangles[ ui_face ];
01027         vi_new_idx[ pcl_face->vertices[ 0 ] ] = 0;
01028         vi_new_idx[ pcl_face->vertices[ 1 ] ] = 0;
01029         vi_new_idx[ pcl_face->vertices[ 2 ] ] = 0;
01030     }
01031 
01032     // calculate new indices
01033     ui_used = 0;
01034     for( ui_vert = 0; ui_vert < cui_verts; ++ui_vert )
01035     {
01036         if( vi_new_idx[ ui_vert ] >= 0 )
01037         {
01038             vi_new_idx[ ui_vert ] = ui_used;
01039             ++ui_used;
01040         }
01041     }
01042 
01043 //  m_vtSurfaces[ uiSurface ].uiTriangleCnt = cui_faces;
01044 //  m_vclNormal.resize( m_vclParameterVertices.size( ) );
01045 
01046     beginEditCP( pcl_type, GeoPTypesUI8::GeoPropDataFieldMask );
01047     {
01048 //        std::cerr<<"fuck3"<<std::endl; 
01049         pcl_type->clear();
01050 //        std::cerr<<"fuck4"<<std::endl; 
01051         pcl_type->push_back( GL_TRIANGLES );
01052 //        std::cerr<<"fuck5"<<std::endl;
01053         if( b_show_trimming )
01054         {
01055             for( ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop )
01056             {
01057                 pcl_type->push_back( GL_TRIANGLE_STRIP );
01058             }
01059         } // b_show_trimming
01060     }
01061     endEditCP( pcl_type, GeoPTypesUI8::GeoPropDataFieldMask );
01062 //    std::cerr<<"types"<<std::endl;
01063     beginEditCP( pcl_size, GeoPLengthsUI32::GeoPropDataFieldMask );
01064     {
01065         pcl_size->clear();
01066         pcl_size->push_back( 3 * cui_faces );
01067         ui_idx = 3 * cui_faces;
01068         if ( b_show_trimming )
01069         {
01070             for( ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop )
01071             {
01072                 pcl_size->push_back( 2 + 2 * pt_surfdata->vvclEdgeLoops[ ui_loop ].size( ) );
01073                 ui_idx += 2 + 2 * pt_surfdata->vvclEdgeLoops[ ui_loop ].size( );
01074             }
01075         }
01076 //      std::cerr << ui_idx << " indices" << std::endl;
01077     }
01078     endEditCP( pcl_size, GeoPLengthsUI32::GeoPropDataFieldMask );
01079 //    std::cerr<<"size"<<std::endl;
01080 
01081     beginEditCP( pcl_points, GeoPositions3f::GeoPropDataFieldMask );
01082     {
01083         pcl_points->clear();
01084         for( ui_vert = 0; ui_vert < cui_verts; ++ui_vert )
01085         {
01086             if( vi_new_idx[ ui_vert ] >= 0 )
01087             {
01088                 pcl_points->push_back( gverts[ ui_vert ] );
01089             }
01090         }
01091         if( b_show_trimming )
01092         {
01093             for( ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop )
01094             {
01095                 ui_vertex_cnt = pt_surfdata->vvclEdgeLoops[ ui_loop ].size( );
01096                 for( ui_vert = 0; ui_vert < ui_vertex_cnt; ++ui_vert )
01097                 {
01098                     pcl_points->push_back( Pnt3f( pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert ].x,
01099                                                   pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert ].y,
01100                                                   pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert ].z ) );
01101                     pcl_points->push_back( Pnt3f( pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert ].x,
01102                                                   pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert ].y,
01103                                                   pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert ].z ) );
01104                 }
01105             }
01106         } // b_show_trimming
01107     }
01108     endEditCP( pcl_points, GeoPositions3f::GeoPropDataFieldMask );
01109 //    std::cerr<<"points"<<std::endl;
01110     
01111     if( norms.size( ) > 0 )
01112     {
01113         beginEditCP( pcl_norms, GeoNormals3f::GeoPropDataFieldMask );
01114         {
01115             pcl_norms->clear();
01116             for( ui_vert = 0; ui_vert < cui_verts; ++ui_vert )
01117             {
01118                 if( vi_new_idx[ ui_vert ] >= 0 )
01119                 {
01120                     pcl_norms->push_back( norms[ ui_vert ] );
01121                 }
01122             }
01123             if( b_show_trimming )
01124             {
01125                 for( ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop )
01126                 {
01127                     ui_vertex_cnt = pt_surfdata->vvclEdgeLoops[ ui_loop ].size( );
01128                     for( ui_vert = 0; ui_vert < ui_vertex_cnt; ++ui_vert )
01129                     {
01130                         pcl_norms->push_back( Vec3f( pt_surfdata->vvclEdgeLoopsNorm[ ui_loop ][ ui_vert ].x,
01131                                                      pt_surfdata->vvclEdgeLoopsNorm[ ui_loop ][ ui_vert ].y,
01132                                                      pt_surfdata->vvclEdgeLoopsNorm[ ui_loop ][ ui_vert ].z ) );
01133                         pcl_norms->push_back( Vec3f( pt_surfdata->vvclEdgeLoopsNorm[ ui_loop ][ ui_vert ].x,
01134                                                      pt_surfdata->vvclEdgeLoopsNorm[ ui_loop ][ ui_vert ].y,
01135                                                      pt_surfdata->vvclEdgeLoopsNorm[ ui_loop ][ ui_vert ].z ) );
01136                     }
01137                 }
01138             } // b_show_trimming
01139         }
01140         endEditCP( pcl_norms, GeoNormals3f::GeoPropDataFieldMask );
01141 //      std::cerr<<"norms"<<std::endl;
01142     }
01143     
01144     if( texcoords.size( ) > 0 )
01145     {
01146         beginEditCP( pcl_texcoords, GeoTexCoords2f::GeoPropDataFieldMask );
01147         {
01148             pcl_texcoords->clear();
01149             for( ui_vert = 0; ui_vert < cui_verts; ++ui_vert )
01150             {
01151                 if( vi_new_idx[ ui_vert ] >= 0 )
01152                 {
01153                     pcl_texcoords->push_back( Vec2f( texcoords[ ui_vert ][ 0 ], 
01154                                                      texcoords[ ui_vert ][ 1 ] ) );
01155 //                    std::cerr<<"texcoords: " << texcoords[ ui_vert ][ 0 ] << 
01156 //                               " " << texcoords[ ui_vert ][ 1 ] << std::endl;
01157                 }
01158             }
01159             if ( b_show_trimming )
01160             {
01161                 for( ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop )
01162                 {
01163                     ui_vertex_cnt = pt_surfdata->vvclEdgeLoops[ ui_loop ].size( );
01164                     for( ui_vert = 0; ui_vert < ui_vertex_cnt; ++ui_vert )
01165                     {
01166                         pcl_texcoords->push_back( Vec2f( pt_surfdata->vvclEdgeLoopsTex[ ui_loop ][ ui_vert ].x,
01167                                                          pt_surfdata->vvclEdgeLoopsTex[ ui_loop ][ ui_vert ].y ) );
01168                         pcl_texcoords->push_back( Vec2f( pt_surfdata->vvclEdgeLoopsTex[ ui_loop ][ ui_vert ].x,
01169                                                          pt_surfdata->vvclEdgeLoopsTex[ ui_loop ][ ui_vert ].y ) );
01170                     }
01171                 }
01172             } // b_show_trimming
01173         }
01174         endEditCP( pcl_texcoords, GeoTexCoords2f::GeoPropDataFieldMask );
01175     }
01176 
01177     if( b_show_trimming )
01178     {
01179         beginEditCP( pcl_tangents, GeoTexCoords3f::GeoPropDataFieldMask );
01180         {
01181             pcl_tangents->clear();
01182             for( ui_vert = 0; ui_vert < cui_verts; ++ui_vert )
01183             {
01184                 if( vi_new_idx[ ui_vert ] >= 0 )
01185                 {
01186                     pcl_tangents->getFieldPtr( )->push_back( Vec3f( 0.0, 0.0, 0.0 ) );
01187                 }
01188             }
01189             for( ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop )
01190             {
01191                 ui_vertex_cnt = pt_surfdata->vvclEdgeLoops[ ui_loop ].size( );
01192                 for( ui_vert = 0; ui_vert < ui_vertex_cnt; ++ui_vert )
01193                 {
01194                     if( ui_vert == 0 ) 
01195                     {
01196                         pcl_prevv = &pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vertex_cnt - 1 ];
01197                         pcl_nextv = &pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ 1 ];
01198                     }
01199                     else if ( ui_vert == ui_vertex_cnt - 1 )
01200                     {
01201                         pcl_prevv = &pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert - 1 ];
01202                         pcl_nextv = &pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ 0 ];
01203                     }
01204                     else
01205                     {
01206                         pcl_prevv = &pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert - 1 ];
01207                         pcl_nextv = &pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert + 1 ];
01208                     }
01209                     pcl_actv = &pt_surfdata->vvclEdgeLoops3D[ ui_loop ][ ui_vert ];
01210                     // calculate the tangents of the trimming polyloops:
01211                     // (nextv - actv).normalize() plus
01212                     // (actv - prevv).normalize()  -> and normalize it again
01213                     cl_v1[0] = pcl_nextv->x - pcl_actv->x;
01214                     cl_v1[1] = pcl_nextv->y - pcl_actv->y;
01215                     cl_v1[2] = pcl_nextv->z - pcl_actv->z;
01216                     cl_v1.normalize();
01217                     cl_v2[0] = pcl_actv->x - pcl_prevv->x;
01218                     cl_v2[1] = pcl_actv->y - pcl_prevv->y;
01219                     cl_v2[2] = pcl_actv->z - pcl_prevv->z;
01220                     cl_v2.normalize();
01221                     cl_tangent = cl_v1 + cl_v2;
01222                     cl_tangent.normalize( );
01223 
01224                     cl_tangent *= sqrt( getError( ) );
01225 
01226                     pcl_tangents->getFieldPtr( )->push_back( -cl_tangent );
01227                     pcl_tangents->getFieldPtr( )->push_back( cl_tangent );
01228                 }
01229             }
01230         }
01231         endEditCP( pcl_tangents, GeoTexCoords3f::GeoPropDataFieldMask );
01232 //      std::cerr<<"tangents"<<std::endl;
01233     } // b_show_trimming
01234     
01235     beginEditCP( pcl_indices, GeoIndicesUI32::GeoPropDataFieldMask );
01236     {
01237         pcl_indices->clear();
01238         for( ui_face = 0; ui_face < cui_faces; ++ui_face )
01239         {
01240             pcl_face = &triangles[ ui_face ];
01241             if( ( norms.size( ) == 0 ) ||
01242                 ( checkOrient( pcl_face->vertices[ 0 ], 
01243                                pcl_face->vertices[ 1 ],
01244                                pcl_face->vertices[ 2 ], gverts, norms ) ) )
</