00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
00072
00073
00074
00075
00076
00077
00078 #include "OSGBSplineTrimmedSurface.h"
00079 #include "OSGNurbsPatchSurface.h"
00080 #include "OSGSimplePolygon.h"
00081
00082 #include "OSGpredicates.h"
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
00103
00104
00105
00106
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
00144
00146
00147 Surface::Surface(void) :
00148 Inherited()
00149 {
00150
00151 _trimmedSurface = NULL;
00152 _surfacePatch = NULL;
00153 }
00154
00156
00157 Surface::Surface(const Surface &source) :
00158 Inherited(source)
00159 {
00160
00161
00162
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
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
00205 ::exactinit();
00206
00207 CErrorQuadTree::m_sbNormalApproximation = true;
00208
00209 }
00210
00212
00213 void Surface::changed(BitVector whichField, UInt32 origin)
00214 {
00215
00216
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
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
00246
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
00260
00261 Inherited::changed( whichField, origin );
00262
00263
00264
00265 }
00266
00267
00269
00270
00271
00272
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
00283
00284
00285
00286
00287
00288 distance = sqrt( distance );
00289
00290
00291
00292
00293 Real64 desired_error = halfPixelSize * distance;
00294
00295
00296
00297 if( desired_error < _max.dist( _min ) * 0.001 )
00298 {
00299
00300 desired_error = _max.dist( _min ) * 0.001;
00301 }
00302
00303 return desired_error;
00304 }
00305
00307
00308
00309
00310
00311
00312 bool Surface::updateError( Pnt3f viewPos, Real64 halfPixelSize )
00313 {
00314 Real64 d_max_error = getDesiredError( viewPos, halfPixelSize );
00315
00316
00317
00318
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
00348
00349
00350
00351
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
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
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
00472
00473
00474
00475 std::vector< SimplePolygon > tris;
00476 std::vector< Pnt3f > gverts;
00477 std::vector< Vec3f > norms;
00478 std::vector< Pnt2f > texturecoords;
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
00496
00497
00498
00499
00500
00501 err = tessellateSurface( tris, gverts, norms, texturecoords );
00502 if ( err ) return;
00503 (void) buildSurface( tris, gverts, norms, texturecoords );
00504
00505 }
00506
00507
00508
00509
00510
00511
00512
00513 }
00514
00516 void Surface::reTessellate( void )
00517 {
00518 std::vector< SimplePolygon > tris;
00519 std::vector< Pnt3f > gverts;
00520 std::vector< Vec3f > norms;
00521 std::vector< Pnt2f > texturecoords;
00522
00523
00524
00525
00526 if ( getError() < DCTP_EPS )
00527 {
00528
00529
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
00545
00546
00547
00548
00549
00550 _surfacePatch->getTessellation( gverts, norms, texturecoords,
00551 tris, getIsDelaunay() );
00552 (void) buildSurface( tris, gverts, norms, texturecoords );
00553
00554 }
00555
00556
00557
00558
00559 }
00560
00561
00562 Int32 Surface::convertSurface( void )
00563 {
00564
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
00578 UInt32 cpsize = _mfControlPoints.size();
00579 if( cpsize == 0 )
00580 {
00581 SLOG << "Surface::tessellate: null surfacecontrol points " << endLog;
00582 return -1;
00583 }
00584
00585
00586
00587
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 )
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
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
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
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
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
00648
00649
00650
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
00663 k = i * cpvsize + j;
00664 vec3.x = _mfControlPoints[k][0];
00665 vec3.y = _mfControlPoints[k][1];
00666 vec3.z = _mfControlPoints[k][2];
00667
00668
00669
00670 qnet[ i ][ j ] = vec3;
00671 }
00672 }
00673 tensor_surface.setControlPointMatrix( qnet );
00674
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
00687
00688 _trimmedSurface->setSurface( tensor_surface );
00689
00690
00691
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
00714
00715
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
00732
00733
00734
00735
00736
00737 for ( k = 0; k < acttrimcpsize; ++k )
00738 {
00739
00740 acttrimcps[ k ].x = _mfCurveControlPoints[ actcpoffset + k ][0];
00741 acttrimcps[ k ].y = _mfCurveControlPoints[ actcpoffset + k ][1];
00742
00743
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
00757 return 0;
00758 }
00759
00760
00761
00762
00763 Int32 Surface::tessellateSurface( std::vector< SimplePolygon > &triangles,
00764 std::vector< Pnt3f > &gverts,
00765 std::vector< Vec3f > &norms )
00766 {
00767
00768
00769
00770 std::vector< Pnt2f > dummy;
00771 _surfacePatch->setSurface( _trimmedSurface, dummy, false );
00772 if ( _sfError.getValue() < DCTP_EPS )
00773 {
00774
00775
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
00792
00793
00794 return 0;
00795 }
00796
00797
00798
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
00805
00806
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
00822
00823 _sfError.setValue( 0.2 );
00824 }
00825 _surfacePatch->setError ( _sfError.getValue() );
00826 _surfacePatch->getTessellation( gverts, norms, texcoords, triangles, getIsDelaunay() );
00827
00828
00829
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
00842
00843
00844 return 0;
00845 }
00846
00847
00848
00849 Int32 Surface::tessellateSurface( std::vector< SimplePolygon > &triangles,
00850 std::vector< Pnt3f > &gverts,
00851 std::vector< Pnt2f > &texcoords )
00852 {
00853
00854
00855
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
00871
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
00891
00892
00893 return 0;
00894 }
00895
00896
00897
00898
00899
00900
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
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
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
00932 GeoTexCoords3fPtr pcl_tangents = GeoTexCoords3fPtr::dcast( getTexCoords( ) );
00933 SimpleMaterialPtr pcl_mat = SimpleMaterialPtr::dcast( getMaterial( ) );
00934 SurfacePtr thisPtr = SurfacePtr( this );
00935
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
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
00968 {
00969 b_show_trimming = true;
00970 break;
00971 }
00972 }
00973 }
00974
00975
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
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
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
01044
01045
01046 beginEditCP( pcl_type, GeoPTypesUI8::GeoPropDataFieldMask );
01047 {
01048
01049 pcl_type->clear();
01050
01051 pcl_type->push_back( GL_TRIANGLES );
01052
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 }
01060 }
01061 endEditCP( pcl_type, GeoPTypesUI8::GeoPropDataFieldMask );
01062
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
01077 }
01078 endEditCP( pcl_size, GeoPLengthsUI32::GeoPropDataFieldMask );
01079
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 }
01107 }
01108 endEditCP( pcl_points, GeoPositions3f::GeoPropDataFieldMask );
01109
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 }
01139 }
01140 endEditCP( pcl_norms, GeoNormals3f::GeoPropDataFieldMask );
01141
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
01156
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 }
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
01211
01212
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
01233 }
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 ) ) )