OSGSurface.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                           OpenSG NURBS Library                            *
00003  *                                                                           *
00004  *                                                                           *
00005  * Copyright (C) 2001-2006 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 "OSGIntersectAction.h"
00052 #include "OSGRenderAction.h"
00053 #include "OSGSimpleMaterial.h"
00054 #include "OSGFatBorderChunk.h"
00055
00056 #include "OSGGeometry.h"
00057 #include "OSGTypedGeoIntegralProperty.h"
00058 #include "OSGTypedGeoVectorProperty.h"
00059
00060 #include "OSGGeoFunctions.h"
00061
00062 #include "OSGGL.h"
00063 #include "OSGGLU.h"
00064 #include "OSGGLEXT.h"
00065
00066 #include "OSGSurface.h"
00067
00068 /*
00069 #ifdef OSG_USE_ATI
00070 #  include <GL/glx.h>
00071 #  include <GL/glext.h>
00072 #  include <GL/glATI.h>
00073 #endif
00074 */
00075
00076 #include <boost/bind.hpp>
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 /***************************************************************************\
00087  *                               Types                                     *
00088 \***************************************************************************/
00089
00090 /***************************************************************************\
00091  *                           Class variables                               *
00092 \***************************************************************************/
00093
00094 const OSG::BitVector Surface::CurveFieldMask =
00095     (Surface::NumCurvesFieldMask |
00096      Surface::KnotLengthsFieldMask |
00097      Surface::DimensionsFieldMask |
00098      Surface::CurveControlPointsFieldMask |
00099      Surface::KnotsFieldMask |
00100      Surface::CurvesPerLoopFieldMask);
00101
00102 const OSG::BitVector Surface::SurfaceFieldMask =
00103     (Surface::DimUFieldMask |
00104      Surface::DimVFieldMask |
00105      Surface::KnotsUFieldMask |
00106      Surface::KnotsVFieldMask |
00107      Surface::ControlPointsFieldMask |
00108      Surface::ErrorFieldMask |
00109      Surface::IsDelaunayFieldMask |
00110      Surface::TextureControlPointsFieldMask);
00111
00112
00113 /*----------------------- constructors & destructors ----------------------*/
00114
00116
00117 Surface::Surface(void) :
00118     Inherited()
00119 {
00120 //    std::cerr<<"constructor"<<std::endl;
00121     _trimmedSurface = NULL;
00122     _surfacePatch   = NULL;
00123 }
00124
00126
00127 Surface::Surface(const Surface &source) :
00128     Inherited(source)
00129 {
00130     // We need these for every class and every aspect, so we have to
00131     // allocate them here.
00132     _trimmedSurface = new BSplineTrimmedSurface;
00133     _surfacePatch   = new CNurbsPatchSurface;
00134 }
00135
00137
00138 Surface::~Surface(void)
00139 {
00140     delete _trimmedSurface;
00141     delete _surfacePatch;
00142 }
00143
00144
00145 /*----------------------------- class specific ----------------------------*/
00146
00148
00149 void Surface::initMethod(InitPhase ePhase)
00150 {
00151     Inherited::initMethod(ePhase);
00152
00153     if(ePhase == TypeObject::SystemPost)
00154     {
00155         RenderAction::registerEnterDefault(
00156             getClassType(),
00157             reinterpret_cast<Action::Callback>(&Geometry::renderActionEnterHandler));
00158
00159         RenderAction::registerLeaveDefault(
00160             getClassType(),
00161             reinterpret_cast<Action::Callback>(&Geometry::renderActionLeaveHandler));
00162
00163         IntersectAction::registerEnterDefault(
00164             getClassType(),
00165             reinterpret_cast<Action::Callback>(&Geometry::intersect));
00166
00167         // init robust predicates
00168         ::exactinit();
00169
00170         // turn appearance preserving tessellation on
00171         CErrorQuadTree::m_sbNormalApproximation = true;
00172     }
00173 }
00174
00176
00177 void Surface::changed(ConstFieldMaskArg whichField,
00178                       UInt32            origin,
00179                       BitVector         detail)
00180 {
00181     if( (whichField & DimUFieldMask) ||
00182         (whichField & DimVFieldMask) ||
00183         (whichField & KnotsUFieldMask) ||
00184         (whichField & KnotsVFieldMask) ||
00185         (whichField & ControlPointsFieldMask) ||
00186         (whichField & NumCurvesFieldMask) ||
00187         (whichField & KnotLengthsFieldMask) ||
00188         (whichField & DimensionsFieldMask) ||
00189         (whichField & CurveControlPointsFieldMask) ||
00190         (whichField & KnotsFieldMask) ||
00191         (whichField & CurvesPerLoopFieldMask) ||
00192         (whichField & TextureControlPointsFieldMask) )
00193     {
00194         editDirtyMask() |= TESSELLATE;
00195
00196         Window::refreshGLObject(getSurfaceGLId());
00197     }
00198     else if( (whichField & ErrorFieldMask) ||
00199              (whichField & IsDelaunayFieldMask) )
00200     {
00201         editDirtyMask() |= RETESSELLATE;
00202
00203         Window::refreshGLObject(getSurfaceGLId());
00204     }
00205
00206     // you should call the parent's changed() function in case
00207     // it needs to update inherited fields.
00208     Inherited::changed(whichField, origin, detail);
00209 //    std::cerr<<"Surface::changed:   texcoords ptr: " << getTexCoords() << std::endl;
00210 //    std::cerr<<"Surface::changed:   texcoords1 ptr: " << getTexCoords1() << std::endl;
00211
00212 }
00213
00214
00216 /*
00217  *  This should be called from the user program once per frame for every
00218  *  patch. This returns the patch's desired error level for the
00219  * dynamic LOD balancing.
00220  */
00221 Real64 Surface::getDesiredError(Pnt3f viewPos, Real64 halfPixelSize)
00222 {
00223     Vec3f  dist;
00224     Real64 distance;
00225
00226     findClosestPoint(dist, viewPos);
00227     distance = dist.squareLength();
00228
00229 /*    if( distance < _max.dist2( _min ) )
00230     {
00231         findClosestPointExact( dist, viewPos );
00232         distance = dist.squareLength( );
00233     }*/
00234
00235     distance = osgSqrt(distance);
00236     // multiply the length of a line at distance one that projects
00237     // to half a pixel with the distance of the current BB to get
00238     // the maximum geometric error that is allowed for the surface
00239     // within the BB
00240     Real64 desired_error = halfPixelSize * distance;
00241
00242 //  std::cerr << distance << " " << desired_error << std::endl;
00243
00244     if(desired_error < _max.dist(_min) * 0.001)     // 0.1% of bounding box
00245     {
00246 //          printf( "error below minimum => setting to minimal error %f\n", _max.dist( _min ) * 0.001 );
00247         desired_error = _max.dist(_min) * 0.001;
00248     }
00249
00250     return desired_error;
00251 }
00252
00254 /*
00255  *  This should becalled from the render() function in order
00256  *  to only call this for nodes that are not culled.
00257  *
00258  */
00259 bool Surface::updateError(Pnt3f viewPos, Real64 halfPixelSize)
00260 {
00261     Real64 d_max_error = getDesiredError(viewPos, halfPixelSize);
00262
00263     // FIXME: this will convert the surface data once again,
00264     // not very effective... should only be retessellated !!!
00265     // FIXME: do we have to change the error in every frame ???
00266     Real32 current_error = getError();
00267     if(d_max_error < current_error)
00268     {
00269         std::cerr << "retessellating due to too high error: " << d_max_error
00270                   << " " << current_error << std::endl;
00271 //        Real32 new_error = osgMin(d_max_error, current_error / 2.0);
00272
00273         setError(d_max_error / 2.0);
00274     }
00275     else if(d_max_error > current_error * 4.0)
00276     {
00277         std::cerr << "retessellating due to too low error: " << d_max_error
00278                   << " " << current_error << std::endl;
00279
00280         setError(d_max_error / 2.0);
00281     }
00282     return true;
00283 }
00284
00285
00286 // protected
00287
00288
00289 /* given an set of arbitrary bounding volumes
00290  * find the vector to the point on the volume that is closest to the view pos
00291 */
00292 void Surface::findClosestPoint(Vec3f& rDist, const Pnt3f viewPos) const
00293 {
00294     const UInt32 parent_cnt = getParents().size();
00295     UInt32       parent_idx;
00296     Real64       min_dist = 1e300;
00297     Vec3f        temp_dist;
00298     Real64       curr_dist;
00299
00300     for(parent_idx = 0; parent_idx < parent_cnt; ++parent_idx)
00301     {
00302         Node            *parent = dynamic_cast<Node *>(getParents()[0]);
00303         const BoxVolume &bVol   = parent->getVolume();
00304
00305         Pnt3f bb_min;
00306         Pnt3f bb_max;
00307
00308         bVol.getBounds(bb_min, bb_max);
00309
00310         if(viewPos[0] < bb_min[0])
00311         {
00312             temp_dist[0] = viewPos[0] - bb_min[0];
00313         }
00314         else if(viewPos[0] > bb_max[0])
00315         {
00316             temp_dist[0] = viewPos[0] - bb_max[0];
00317         }
00318         else
00319         {
00320             temp_dist[0] = 0.0;
00321         }
00322
00323         if(viewPos[1] < bb_min[1])
00324         {
00325             temp_dist[1] = viewPos[1] - bb_min[1];
00326         }
00327         else if(viewPos[1] > bb_max[1])
00328         {
00329             temp_dist[1] = viewPos[1] - bb_max[1];
00330         }
00331         else
00332         {
00333             temp_dist[1] = 0.0;
00334         }
00335
00336         if(viewPos[2] < bb_min[2])
00337         {
00338             temp_dist[2] = viewPos[2] - bb_min[2];
00339         }
00340         else if(viewPos[2] > bb_max[2])
00341         {
00342             temp_dist[2] = viewPos[2] - bb_max[2];
00343         }
00344         else
00345         {
00346             temp_dist[2] = 0.0;
00347         }
00348
00349         curr_dist = temp_dist.squareLength();
00350
00351         if(curr_dist < min_dist)
00352         {
00353             min_dist = curr_dist;
00354             rDist    = temp_dist;
00355         }
00356     }
00357 }
00358
00359
00360 void Surface::findClosestPointExact(Vec3f& rDist, const Pnt3f viewPos) const
00361 {
00362 //  const GeoPositions3fPtr cpcl_points = GeoPositions3fPtr::dcast( cpcl_geo->getPositions( ) );
00363     const GeoPnt3fProperty *cpcl_points =
00364         dynamic_cast<const GeoPnt3fProperty *>(getPositions());
00365     const unsigned int      cui_idx_cnt = cpcl_points->getSize();
00366     Pnt3f                   cl_pos;
00367     unsigned int            ui_idx;
00368     Vec3f                   cl_temp;
00369     double                  d_min = DBL_MAX;
00370     double                  d_temp;
00371
00372     for(ui_idx = 0; ui_idx < cui_idx_cnt; ++ui_idx)
00373     {
00374         cl_pos  = cpcl_points->getValue(ui_idx);
00375         cl_temp = cl_pos - viewPos;
00376         d_temp  = cl_temp.squareLength();
00377         if(d_temp <= d_min)
00378         {
00379             d_min = d_temp;
00380             rDist = cl_temp;
00381         }
00382     }
00383 }
00384
00385
00387 void Surface::tessellate(void)
00388 {
00389     // local variables for tessellation
00390 //    BSplineTrimmedSurface _trimmedSurface;  // internal representation of surface
00391 //    CNurbsPatchSurface cpatch;              // "tessellator" object
00392 //    simplepolygonvector tris;               // resulting indexed triangle set
00393     std::vector<SimplePolygon> tris;
00394     std::vector<Pnt3f>         gverts;      // resulting vertices
00395     std::vector<Vec3f>         norms;       // resulting surface normals
00396     std::vector<Pnt2f>         texturecoords; // resulting texture coordinates
00397
00398     Int32 err = convertSurface();
00399     if(err)
00400     {
00401 //        exit(-1);
00402         return;
00403     }
00404     if(_sfTextureControlPoints.getValue() == NULL)
00405     {
00406         err = tessellateSurface(tris, gverts, norms);
00407 #ifdef OSG_NURBS_DEBUG
00408         std::cerr << "Surface::tessellate err1: " << err << " #tris: " << tris.size() << std::endl;
00409 #endif /* OSG_NURBS_DEBUG */
00410         if(err)
00411             return;
00412         buildSurface(tris, gverts, norms, texturecoords);
00413     }
00414     else
00415     {
00416 /*
00417         // fragment program stuff (no normals)
00418         err = tessellateSurface( tris, gverts, texturecoords );
00419         if ( err ) return;
00420         (void) buildSurface( tris, gverts, texturecoords );
00421 */
00422         // classic texturemapping stuff (both normals and texcoords)
00423         err = tessellateSurface(tris, gverts, norms, texturecoords);
00424 #ifdef OSG_NURBS_DEBUG
00425         std::cerr << "Surface::tessellate err2: " << err << " #tris: " << tris.size() << std::endl;
00426 #endif /* OSG_NURBS_DEBUG */
00427         if(err)
00428             return;
00429         buildSurface(tris, gverts, norms, texturecoords);
00430     }
00431
00432     // invalidate the volume cache -- strictly speaking this is only needed
00433     // for rational surfaces
00434     _volumeCache.setEmpty();
00435
00436 //        std::cerr<<"Surface::tessellate:   texcoords ptr: " << getTexCoords() << std::endl;
00437 //        std::cerr<<"Surface::tessellate:   texcoords1 ptr: " << getTexCoords1() << std::endl;
00438
00439 //    buildPointSet();
00440 //    SLOG << "tessellate NI" << endLog;
00441 }
00442
00444 void Surface::reTessellate(void)
00445 {
00446     std::vector<SimplePolygon> tris;
00447     std::vector<Pnt3f>         gverts;      // resulting vertices
00448     std::vector<Vec3f>         norms;       // resulting surface normals
00449     std::vector<Pnt2f>         texturecoords; // resulting texture coordinates
00450
00451
00452     //FIXMEZ0RZ:
00453 //    _surfacePatch->setSurface( _trimmedSurface );
00454     if(getError() < DCTP_EPS)
00455     {
00456 //        SLOG << " Surface::tessellate: correcting negative/zero error" <<
00457 //              endLog;
00458         setError(0.2f);
00459     }
00460
00461     _surfacePatch->setError(getError() );
00462 //    SSurface *surfdata = _surfacePatch->getSurfaceData();
00463
00464     if(_sfTextureControlPoints.getValue() == NULL)
00465     {
00466         _surfacePatch->getTessellation(gverts, norms, tris, getIsDelaunay());
00467         buildSurface(tris, gverts, norms, texturecoords);
00468     }
00469     else
00470     {
00471 /*
00472         //normalmap stuff
00473         _surfacePatch->getTessellation( gverts, texturecoords, tris, getIsDelaunay() );
00474         (void) buildSurface( tris, gverts, texturecoords );
00475 */
00476
00477         //classic texturemapped stuff
00478         _surfacePatch->getTessellation(gverts, norms, texturecoords,
00479                                        tris, getIsDelaunay());
00480         buildSurface(tris, gverts, norms, texturecoords);
00481
00482     }
00483
00484     // invalidate the volume cache -- strictly speaking this is only needed
00485     // for rational surfaces
00486     _volumeCache.setEmpty();
00487
00488 //        std::cerr<<"Surface::reTessellate:   texcoords ptr: " << getTexCoords() << std::endl;
00489 //        std::cerr<<"Surface::reTessellate:   texcoords1 ptr: " << getTexCoords1() << std::endl;
00490
00491 }
00492
00493 //internal
00494 Int32 Surface::convertSurface(void)
00495 {
00496 //    BSplineTrimmedSurface *_trimmedSurface = (BSplineTrimmedSurface*)trimsurf;
00497
00498     bool                    israt;
00499     const GeoPnt3fProperty *pPos    =
00500         dynamic_cast<const GeoPnt3fProperty *>(getControlPoints());
00501     const GeoPnt4fProperty *pRatPos =
00502         dynamic_cast<const GeoPnt4fProperty *>(getControlPoints());
00503
00504 //    std::cerr<< "pPos: " << pPos << " pRatPos: " << pRatPos << std::endl;
00505     if(getControlPoints() == NULL)
00506     {
00507         SLOG << "Surface::tessellate: null surfacecontrol prop " << endLog;
00508         return -1;
00509     }
00510
00511     if(pPos != NULL)
00512     {
00513         israt = false;
00514     }
00515     else if(pRatPos != NULL)
00516     {
00517         israt = true;
00518     }
00519     else
00520     {
00521         SLOG << "Surface::tessellate: null surfacecontrol prop " << endLog;
00522         return -1;
00523     }
00524
00525     const MFPnt3f *polyControlPoints = NULL;
00526     const MFPnt4f *ratControlPoints  = NULL;
00527     UInt32         cpsize;
00528
00529     if(!israt)
00530     {
00531         polyControlPoints = &(pPos->getField());
00532         cpsize            = polyControlPoints->size();
00533     }
00534     else
00535     {
00536         ratControlPoints = &(pRatPos->getField());
00537         cpsize           = ratControlPoints->size();
00538     }
00539 //    MFPnt3f &_mfControlPoints = pPos->getField();
00540
00541     // check knots, dimensions and control points
00542     if(cpsize == 0)
00543     {
00544         SLOG << "Surface::tessellate: null surfacecontrol points " << endLog;
00545         return -1;
00546     }
00547 /*    if ( cpdim !=3 && cpdim !=4 )
00548     {
00549         SLOG << "Surface::tessellate: wrong control point dimensions " <<
00550                 endLog;
00551     }*/
00552     UInt32 dimu = _sfDimU.getValue();
00553     UInt32 dimv = _sfDimV.getValue();
00554     if(dimu == 0 || dimv == 0)
00555     {
00556         SLOG << "Surface::tessellate: 0 dimensions " << endLog;
00557         return -1;
00558     }
00559
00560     UInt32 knotusize = _mfKnotsU.size();
00561     UInt32 knotvsize = _mfKnotsV.size();
00562     if(knotusize == 0 || knotvsize == 0)
00563     {
00564         SLOG << "Surface::tessellate: empty knotvectors " << endLog;
00565         return -1;
00566     }
00567
00568     UInt32 cpusize = knotusize - dimu - 1;
00569     UInt32 cpvsize = knotvsize - dimv - 1;
00570     if(cpusize < 1 || cpvsize < 1 || cpusize * cpvsize != cpsize)
00571     {
00572         SLOG << cpusize << "x" << cpvsize << ":" << cpsize << endLog;
00573         SLOG << "Surface::tessellate: inconsistent attributes " << endLog;
00574         return -1;
00575     }
00576
00577     if(_sfNumCurves.getValue() == 0)     // no trimming specified, add dummy trimming
00578     {
00579         Real64 umin = _mfKnotsU[0];
00580         Real64 vmin = _mfKnotsV[0];
00581         Real64 umax = _mfKnotsU[knotusize - 1];
00582         Real64 vmax = _mfKnotsV[knotvsize - 1];
00583
00584         std::vector<Real64> tmpknotvec(4);
00585         std::vector<Pnt2f>  tmpcps(2);
00586         UInt32              dim = 1;
00587         tmpknotvec[0] = 0.0;
00588         tmpknotvec[1] = 0.0;
00589         tmpknotvec[2] = 1.0;
00590         tmpknotvec[3] = 1.0;
00591
00592         // (umin, vmin) -> (umax,vmin)
00593         tmpcps[0][0] = umin; tmpcps[0][1] = vmin;
00594         tmpcps[1][0] = umax; tmpcps[1][1] = vmin;
00595         addCurve(dim, tmpknotvec, tmpcps);
00596
00597         // (umax, vmin) -> (umax,vmax)
00598         tmpcps[0][0] = umax; tmpcps[0][1] = vmin;
00599         tmpcps[1][0] = umax; tmpcps[1][1] = vmax;
00600         addCurve(dim, tmpknotvec, tmpcps);
00601
00602         // (umax, vmax) -> (umin,vmax)
00603         tmpcps[0][0] = umax; tmpcps[0][1] = vmax;
00604         tmpcps[1][0] = umin; tmpcps[1][1] = vmax;
00605         addCurve(dim, tmpknotvec, tmpcps);
00606
00607         // (umin, vmax) -> (umin,vmin)
00608         tmpcps[0][0] = umin; tmpcps[0][1] = vmax;
00609         tmpcps[1][0] = umin; tmpcps[1][1] = vmin;
00610         addCurve(dim, tmpknotvec, tmpcps);
00611     }
00612
00613     // now we checked everything, let's convert the surface+trimcurves
00614     // to the internal representation
00615
00616     // first create surface
00617     BSplineTensorSurface tensor_surface;
00618     UInt32               i, j, k;
00619     DCTPVec4dmatrix      qnet;
00620     Vec4d                vec4;
00621     qnet.resize(cpusize);
00622
00623     for(i = 0; i < cpusize; ++i)
00624     {
00625         qnet[i].resize(cpvsize);
00626
00627         for(j = 0; j < cpvsize; ++j)
00628         {
00629             k = i * cpvsize + j;
00630             if(!israt)
00631             {
00632                 vec4[0] = (*polyControlPoints)[k][0];
00633                 vec4[1] = (*polyControlPoints)[k][1];
00634                 vec4[2] = (*polyControlPoints)[k][2];
00635                 vec4[3] = 1.0f;
00636 //                SLOG << "qnet["<<i<<"]["<<j<<"]: " << vec4 << endLog;
00637 //                SLOG << "k: " << k << endLog;
00638             }
00639             else
00640             {
00641                 vec4[0] = (*ratControlPoints)[k][0];
00642                 vec4[1] = (*ratControlPoints)[k][1];
00643                 vec4[2] = (*ratControlPoints)[k][2];
00644                 vec4[3] = (*ratControlPoints)[k][3];
00645 //                SLOG << "qnet["<<i<<"]["<<j<<"]: " << vec4 << endLog;
00646 //                SLOG << "k: " << k << endLog;
00647             }
00648             qnet[i][j] = vec4;
00649         }
00650     }
00651
00652     tensor_surface.setControlPointMatrix(qnet);
00653     // convert knotvectors
00654     DCTPdvector knotuvec(knotusize);
00655     DCTPdvector knotvvec(knotvsize);
00656
00657     for(i = 0; i < knotusize; ++i)
00658     {
00659         knotuvec[i] = _mfKnotsU[i];
00660     }
00661
00662     for(i = 0; i < knotvsize; ++i)
00663     {
00664         knotvvec[i] = _mfKnotsV[i];
00665     }
00666
00667     tensor_surface.setKnotsAndDimension(knotuvec, dimu, knotvvec, dimv);
00668 //    std::cerr<<"0.2"<<std::endl;
00669 //    fprintf(stderr,"%x\n", _trimmedSurface);
00670     _trimmedSurface->setSurface(tensor_surface);
00671 //    std::cerr<<"0.3"<<std::endl;
00672
00673     // now create/convert trimming loops
00674     trimmingloop trimloops;
00675     UInt32       cplsize = _mfCurvesPerLoop.size();
00676     trimloops.resize(cplsize);
00677
00678     for(i = 0; i < cplsize; ++i)
00679     {
00680         trimloops[i].resize(_mfCurvesPerLoop[i]);
00681     }
00682
00683     UInt32          actknotoffset = 0;
00684     UInt32          actcpoffset   = 0;
00685 //    UInt32          actloopoffset = 0;
00686     UInt32          actcurveno    = 0;
00687     UInt32          acttrimcpsize = 0;
00688     DCTPdvector     actknots;
00689     DCTPVec3dvector acttrimcps;
00690     BSplineCurve2D  actcurve;
00691
00692     for(i = 0; i < trimloops.size(); ++i)
00693     {
00694         for(j = 0; j < trimloops[i].size(); ++j)
00695         {
00696             actknots.resize(_mfKnotLengths[actcurveno]);
00697 //            SLOG << "Debug: _mfKnotLengths[ actcurveno ]: " <<
00698 //                    _mfKnotLengths[ actcurveno ] << " actcurveno: " <<
00699 //                    actcurveno << endLog;
00700             acttrimcpsize = actknots.size() - _mfDimensions[actcurveno] - 1;
00701             if(acttrimcpsize < 1)
00702             {
00703                 SLOG << "Surface::tessellate: wrong trimming curve attributes "
00704                      << endLog;
00705                 return -1;
00706             }
00707             acttrimcps.resize(acttrimcpsize);
00708
00709             for(k = 0; k < actknots.size(); ++k)
00710             {
00711                 actknots[k] = _mfKnots[actknotoffset + k];
00712             }
00713
00714             actknotoffset += actknots.size();
00715             actcurve.setKnotsAndDimension(actknots,
00716                                           _mfDimensions[actcurveno]);
00717
00718 //            SLOG << "Debug: actknotoffset: " << actknotoffset << endLog;
00719 //            SLOG << "Debug: actcpoffset: " << actcpoffset << endLog;
00720 //            SLOG << "Debug: _mfCurveControlPoints.size(): " <<
00721 //                    _mfCurveControlPoints.size() << endLog;
00722 //            SLOG << "Debug: _mfKnots.size(): " << _mfKnots.size() << endLog;
00723 //            SLOG << "Debug: acttrimcps.size(): " << acttrimcps.size() << endLog;
00724             for(k = 0; k < acttrimcpsize; ++k)
00725             {
00726 //                SLOG <<"Debug: k: " << k << endLog;
00727                 acttrimcps[k][0] = _mfCurveControlPoints[actcpoffset + k][0];
00728                 acttrimcps[k][1] = _mfCurveControlPoints[actcpoffset + k][1];
00729                 acttrimcps[k][2] = _mfCurveControlPoints[actcpoffset + k][2];
00730             }
00731
00732             actcpoffset += acttrimcpsize;
00733             actcurve.setControlPointVector(acttrimcps);
00734
00735             trimloops[i][j] = actcurve;
00736             actcurveno++;
00737         }
00738
00739     }
00740
00741     _trimmedSurface->setTrimmingLoops(trimloops);
00742     _trimmedSurface->normalize();
00743
00744 //    global_surf = *_trimmedSurface;
00745     return 0;
00746 }
00747
00748
00749 //internal
00750 // normal, nontexturemapped
00751 Int32 Surface::tessellateSurface(std::vector<SimplePolygon> &triangles,
00752                                  std::vector<Pnt3f> &        gverts,
00753                                  std::vector<Vec3f> &        norms)
00754 {
00755 //    BSplineTrimmedSurface *_trimmedSurface = (BSplineTrimmedSurface*)trimsurf;
00756 //    std::vector< SimplePolygon > *triangles = (std::vector< SimplePolygon > *)tris;
00757 //    CNurbsPatchSurface cpatch;              // "tessellator" object
00758     std::vector<Pnt2f> dummy;
00759     _surfacePatch->setSurface(_trimmedSurface, dummy, false);
00760
00761     if(_sfError.getValue() < DCTP_EPS)
00762     {
00763 //        SLOG << " Surface::tessellate: correcting negative/zero error" <<
00764 //                endLog;
00765         _sfError.setValue(0.2f);
00766     }
00767
00768     _surfacePatch->setError(_sfError.getValue() );
00769     _surfacePatch->getTessellation(gverts, norms, triangles, getIsDelaunay() );
00770     SSurface *surfaceData =  _surfacePatch->getSurfaceData();
00771     _min = Pnt3d(surfaceData->clMin[0], surfaceData->clMin[1],
00772                  surfaceData->clMin[2]);
00773     _max = Pnt3d(surfaceData->clMax[0], surfaceData->clMax[1],
00774                  surfaceData->clMax[2]);
00775 #ifdef OSG_ARBITRARY_SPLIT
00776     _minParam = Pnt2d(surfaceData->clMinParam[0], surfaceData->clMinParam[1]);
00777     _maxParam = Pnt2d(surfaceData->clMaxParam[0], surfaceData->clMaxParam[1]);
00778 #endif
00779 
00780
00781 //    std::cerr<< "min, max: [" << _min << "][" << _max << "]" << std::endl;
00782 //    std::cerr<< "minparam, maxparam: [" << _minParam << "][ " << _maxParam  << "]" << std::endl;
00783
00784     return 0;
00785 }
00786
00787 //internal
00788 // surface with texturemap, no normalmap!
00789 Int32 Surface::tessellateSurface(std::vector<SimplePolygon> &triangles,
00790                                  std::vector<Pnt3f> &        gverts,
00791                                  std::vector<Vec3f> &        norms,
00792                                  std::vector<Pnt2f> &        texcoords)
00793 {
00794 //    BSplineTrimmedSurface *_trimmedSurface = (BSplineTrimmedSurface*)trimsurf;
00795 //    std::vector< SimplePolygon > *triangles = (std::vector< SimplePolygon > *)tris;
00796 //    CNurbsPatchSurface cpatch;              // "tessellator" object
00797     const GeoVec2fProperty *pTexPos = dynamic_cast<const GeoVec2fProperty *>(
00798         getTextureControlPoints());
00799     std::vector<Pnt2f> tmptexcoords;
00800     UInt32             i;
00801     UInt32             s = pTexPos->getField().size();
00802
00803     for(i = 0; i < s; ++i)
00804     {
00805         tmptexcoords.push_back(Pnt2f(pTexPos->getField()[i][0],
00806                                      pTexPos->getField()[i][1]));
00807     }
00808
00809     _surfacePatch->setSurface(_trimmedSurface, tmptexcoords, true);
00810     if(_sfError.getValue() < DCTP_EPS)
00811     {
00812 //        SLOG << " Surface::tessellate: correcting negative/zero error" <<
00813 //                endLog;
00814         _sfError.setValue(0.2f);
00815     }
00816
00817     _surfacePatch->setError(_sfError.getValue() );
00818     _surfacePatch->getTessellation(gverts, norms, texcoords, triangles, getIsDelaunay() );
00819
00820 //    std::cerr<< "norms.size(): " << norms.size() << " texcoords.size(): " <<
00821 //            texcoords.size() << std::endl;
00822     SSurface *surfaceData =  _surfacePatch->getSurfaceData();
00823     _min = Pnt3d(surfaceData->clMin[0], surfaceData->clMin[1],
00824                  surfaceData->clMin[2]);
00825     _max = Pnt3d(surfaceData->clMax[0], surfaceData->clMax[1],
00826                  surfaceData->clMax[2]);
00827 #ifdef OSG_ARBITRARY_SPLIT
00828     _minParam = Pnt2d(surfaceData->clMinParam[0], surfaceData->clMinParam[1]);
00829     _maxParam = Pnt2d(surfaceData->clMaxParam[0], surfaceData->clMaxParam[1]);
00830 #endif
00831 
00832
00833 //    std::cerr<< "min, max: [" << _min << "][" << _max << "]" << std::endl;
00834 //    std::cerr<< "minparam, maxparam: [" << _minParam << "][ " << _maxParam  << "]" << std::endl;
00835
00836     return 0;
00837 }
00838
00839 //internal
00840 // surface with normalmaps
00841 Int32 Surface::tessellateSurface(std::vector<SimplePolygon> &triangles,
00842                                  std::vector<Pnt3f> &        gverts,
00843                                  std::vector<Pnt2f> &        texcoords)
00844 {
00845 //    BSplineTrimmedSurface *_trimmedSurface = (BSplineTrimmedSurface*)trimsurf;
00846 //    std::vector< SimplePolygon > *triangles = (std::vector< SimplePolygon > *)tris;
00847 //    CNurbsPatchSurface cpatch;              // "tessellator" object
00848     const GeoVec2fProperty *pTexPos = dynamic_cast<const GeoVec2fProperty *>(
00849         getTextureControlPoints());
00850     std::vector<Pnt2f> tmptexcoords;
00851     UInt32             i;
00852     UInt32             s =  pTexPos->getField().size();
00853
00854     for(i = 0; i < s; ++i)
00855     {
00856         tmptexcoords.push_back(Pnt2f(pTexPos->getField()[i][0],
00857                                      pTexPos->getField()[i][1]));
00858     }
00859
00860     _surfacePatch->setSurface(_trimmedSurface,
00861                               tmptexcoords,
00862                               true);
00863     if(_sfError.getValue() < DCTP_EPS)
00864     {
00865 //        SLOG << " Surface::tessellate: correcting negative/zero error" <<
00866 //                endLog;
00867         _sfError.setValue(0.2f);
00868     }
00869
00870     _surfacePatch->setError(_sfError.getValue());
00871     std::vector<Vec3f> norms;
00872     _surfacePatch->getTessellation(gverts, norms, triangles, false);
00873     _surfacePatch->getTessellation(gverts, texcoords, triangles, getIsDelaunay() );
00874
00875     SSurface *surfaceData =  _surfacePatch->getSurfaceData();
00876     _min = Pnt3d(surfaceData->clMin[0], surfaceData->clMin[1],
00877                  surfaceData->clMin[2]);
00878     _max = Pnt3d(surfaceData->clMax[0], surfaceData->clMax[1],
00879                  surfaceData->clMax[2]);
00880
00881 #ifdef OSG_ARBITRARY_SPLIT
00882     _minParam = Pnt2d(surfaceData->clMinParam[0], surfaceData->clMinParam[1]);
00883     _maxParam = Pnt2d(surfaceData->clMaxParam[0], surfaceData->clMaxParam[1]);
00884 #endif
00885 
00886
00887 //    std::cerr<< "min, max: [" << _min << "][" << _max << "]" << std::endl;
00888 //    std::cerr<< "minparam, maxparam: [" << _minParam << "][ " << _maxParam  << "]" << std::endl;
00889
00890     return 0;
00891 }
00892
00893 //internal
00894 // normal surface
00895 Int32 Surface::buildSurface(std::vector<SimplePolygon> &triangles,
00896                             std::vector<Pnt3f> &        gverts,
00897                             std::vector<Vec3f> &        norms,
00898                             std::vector<Pnt2f> &        texcoords)
00899
00900 {
00901     // FIXME:
00902     //
00903     // At least on Linux/ATI with the current OpenGL drivers
00904     // TextureCoordinate1 doesn't get passed to the vertex program
00905     // unless there's TextureCoordinate0 present.
00906     // Might even crash older drivers, and might also be a problem
00907     // on Windows with some driver versions.
00908     //
00909     // Therefore the Surface uses TextureCoordinate0 to pass tangent
00910     // coordinates to the FatBorderChunk, thus texturing an OSGSurface
00911     // that uses FBs should begin in TextureCoordinate1.
00912     //
00913     // Currently only 1 texture is supported (copied to the fragment
00914     // program for further processing, and built by this function)
00915     // more can be easily added if it's a problem.
00916     //
00917     // FIXME END
00918
00919     GeoIntegralPropertyUnrecPtr pcl_type      = getTypes();
00920     GeoIntegralPropertyUnrecPtr pcl_size      = getLengths();
00921     GeoVectorPropertyUnrecPtr   pcl_points    = getPositions();
00922     GeoVectorPropertyUnrecPtr   pcl_norms     = getNormals();
00923     GeoIntegralPropertyUnrecPtr pcl_indices   = getIndices();
00924     GeoVectorPropertyUnrecPtr   pcl_texcoords = getTexCoords1();
00925     //FatBorderChunk parameters are always passed in TextureCoordinate.
00926     GeoVec3fPropertyUnrecPtr    pcl_tangents  =
00927         dynamic_cast<GeoVec3fProperty *>(getTexCoords());
00928     SimpleMaterialUnrecPtr      pcl_mat       =
00929         dynamic_cast<SimpleMaterial *>(getMaterial());
00930 //  GeometryPtr         pcl_geo = Geometry::create( );
00931     SimplePolygon       *pcl_face;
00932     const UInt32         cui_faces = triangles.size();
00933     UInt32               ui_face;
00934     BSplineTensorSurface cl_surf = _trimmedSurface->getSurface();
00935 //    int                  i_err;
00936     Vec3d                cl_norm;
00937     const UInt32         cui_verts = gverts.size();
00938     UInt32               ui_vert;
00939     SSurface            *pt_surfdata  = _surfacePatch->getSurfaceData();
00940     const UInt32         cui_loop_cnt = pt_surfdata->vvclEdgeLoops.size();
00941     UInt32               ui_loop;
00942     UInt32               ui_vertex_cnt;
00943     UInt32               ui_idx;
00944     UInt32               ui_used;
00945 //    Vec3d               *pcl_actn;
00946     Vec3d               *pcl_actv;
00947     Vec3d               *pcl_nextv;
00948     Vec3d               *pcl_prevv;
00949     Vec3f                cl_v1, cl_v2, cl_tangent;
00950     std::vector<Int32>   vi_new_idx(cui_verts);
00951     bool                 b_show_trimming = false;
00952
00953     // check if material has the fat border chunk
00954     if(pcl_mat != NULL)
00955     {
00956         if(pcl_mat->find(FatBorderChunk::getClassType()) != NULL)
00957             b_show_trimming = true;
00958     }
00959
00960 //    std::cerr<<"show_trimming: " << b_show_trimming << std::endl;
00961     if(pcl_type == NULL)
00962     {
00963         pcl_type = GeoUInt8Property::create();
00964     }
00965     if(pcl_size == NULL)
00966     {
00967         pcl_size = GeoUInt32Property::create();
00968     }
00969     if(pcl_points == NULL)
00970     {
00971         pcl_points = GeoPnt3fProperty::create();
00972     }
00973     if( (norms.size() > 0) && (pcl_norms == NULL) )
00974     {
00975         pcl_norms = GeoVec3fProperty::create();
00976     }
00977     if(pcl_indices == NULL)
00978     {
00979         pcl_indices = GeoUInt32Property::create();
00980     }
00981     if( (texcoords.size() > 0) && (pcl_texcoords == NULL) )
00982     {
00983         pcl_texcoords = GeoVec2fProperty::create();
00984     }
00985     if(b_show_trimming)
00986     {
00987         if(pcl_tangents == NULL)
00988         {
00989             pcl_tangents = GeoVec3fProperty::create();
00990         }
00991     }
00992     else
00993     {
00994         if(pcl_tangents != NULL)
00995         {
00996             setTexCoords(NULL);
00997         }
00998     }
00999
01000     // check for unused points
01001     for(ui_vert = 0; ui_vert < cui_verts; ++ui_vert)
01002     {
01003         vi_new_idx[ui_vert] = -1;
01004     }
01005
01006     for(ui_face = 0; ui_face < cui_faces; ++ui_face)
01007     {
01008         pcl_face                          = &triangles[ui_face];
01009         vi_new_idx[pcl_face->vertices[0]] = 0;
01010         vi_new_idx[pcl_face->vertices[1]] = 0;
01011         vi_new_idx[pcl_face->vertices[2]] = 0;
01012     }
01013
01014     // calculate new indices
01015     ui_used = 0;
01016
01017     for(ui_vert = 0; ui_vert < cui_verts; ++ui_vert)
01018     {
01019         if(vi_new_idx[ui_vert] >= 0)
01020         {
01021             vi_new_idx[ui_vert] = ui_used;
01022             ++ui_used;
01023         }
01024     }
01025
01026 //  m_vtSurfaces[ uiSurface ].uiTriangleCnt = cui_faces;
01027 //  m_vclNormal.resize( m_vclParameterVertices.size( ) );
01028
01029 //        std::cerr<<"fuck3"<<std::endl;
01030     pcl_type->clear();
01031 //        std::cerr<<"fuck4"<<std::endl;
01032     pcl_type->push_back(GL_TRIANGLES);
01033 //        std::cerr<<"fuck5"<<std::endl;
01034     if(b_show_trimming)
01035     {
01036         for(ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop)
01037         {
01038             pcl_type->push_back(GL_TRIANGLE_STRIP);
01039         }
01040     } // b_show_trimming
01041
01042 //    std::cerr<<"types"<<std::endl;
01043     pcl_size->clear();
01044     pcl_size->push_back(3 * cui_faces);
01045     ui_idx = 3 * cui_faces;
01046     if(b_show_trimming)
01047     {
01048         for(ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop)
01049         {
01050             pcl_size->push_back(2 + 2 * pt_surfdata->vvclEdgeLoops[ui_loop].size() );
01051             ui_idx += 2 + 2 * pt_surfdata->vvclEdgeLoops[ui_loop].size();
01052         }
01053     }
01054 //      std::cerr << ui_idx << " indices" << std::endl;
01055
01056 //    std::cerr<<"size"<<std::endl;
01057     pcl_points->clear();
01058
01059     for(ui_vert = 0; ui_vert < cui_verts; ++ui_vert)
01060     {
01061         if(vi_new_idx[ui_vert] >= 0)
01062         {
01063             pcl_points->push_back(gverts[ui_vert]);
01064         }
01065     }
01066
01067     if(b_show_trimming)
01068     {
01069         for(ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop)
01070         {
01071             ui_vertex_cnt = pt_surfdata->vvclEdgeLoops[ui_loop].size();
01072
01073             for(ui_vert = 0; ui_vert < ui_vertex_cnt; ++ui_vert)
01074             {
01075                 pcl_points->push_back(
01076                     Pnt3f(pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert][0],
01077                           pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert][1],
01078                           pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert][2] ));
01079                 pcl_points->push_back(
01080                     Pnt3f(pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert][0],
01081                           pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert][1],
01082                           pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert][2] ));
01083             }
01084         }
01085     } // b_show_trimming
01086
01087 //    std::cerr<<"points"<<std::endl;
01088     if(norms.size() > 0)
01089     {
01090         pcl_norms->clear();
01091
01092         for(ui_vert = 0; ui_vert < cui_verts; ++ui_vert)
01093         {
01094             if(vi_new_idx[ui_vert] >= 0)
01095                 pcl_norms->push_back(norms[ui_vert]);
01096         }
01097
01098         if(b_show_trimming)
01099         {
01100             for(ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop)
01101             {
01102                 ui_vertex_cnt = pt_surfdata->vvclEdgeLoops[ui_loop].size();
01103
01104                 for(ui_vert = 0; ui_vert < ui_vertex_cnt; ++ui_vert)
01105                 {
01106                     pcl_norms->push_back(
01107                         Vec3f(pt_surfdata->vvclEdgeLoopsNorm[ui_loop][ui_vert][0],
01108                               pt_surfdata->vvclEdgeLoopsNorm[ui_loop][ui_vert][1],
01109                               pt_surfdata->vvclEdgeLoopsNorm[ui_loop][ui_vert][2] ));
01110                     pcl_norms->push_back(
01111                         Vec3f(pt_surfdata->vvclEdgeLoopsNorm[ui_loop][ui_vert][0],
01112                               pt_surfdata->vvclEdgeLoopsNorm[ui_loop][ui_vert][1],
01113                               pt_surfdata->vvclEdgeLoopsNorm[ui_loop][ui_vert][2] ));
01114                 }
01115             }
01116         } // b_show_trimming
01117 //      std::cerr<<"norms"<<std::endl;
01118     }
01119
01120     if(texcoords.size() > 0)
01121     {
01122         pcl_texcoords->clear();
01123
01124         for(ui_vert = 0; ui_vert < cui_verts; ++ui_vert)
01125         {
01126             if(vi_new_idx[ui_vert] >= 0)
01127             {
01128                 pcl_texcoords->push_back(Vec2f(texcoords[ui_vert][0],
01129                                                texcoords[ui_vert][1]) );
01130 //                 std::cerr<<"texcoords: " << texcoords[ ui_vert ][ 0 ] <<
01131 //                             " " << texcoords[ ui_vert ][ 1 ] << std::endl;
01132             }
01133         }
01134
01135         if(b_show_trimming)
01136         {
01137             for(ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop)
01138             {
01139                 ui_vertex_cnt = pt_surfdata->vvclEdgeLoops[ui_loop].size();
01140
01141                 for(ui_vert = 0; ui_vert < ui_vertex_cnt; ++ui_vert)
01142                 {
01143                     pcl_texcoords->push_back(
01144                         Vec2f(pt_surfdata->vvclEdgeLoopsTex[ui_loop][ui_vert][0],
01145                               pt_surfdata->vvclEdgeLoopsTex[ui_loop][ui_vert][1]) );
01146                     pcl_texcoords->push_back(
01147                         Vec2f(pt_surfdata->vvclEdgeLoopsTex[ui_loop][ui_vert][0],
01148                               pt_surfdata->vvclEdgeLoopsTex[ui_loop][ui_vert][1]) );
01149                 }
01150             }
01151         } // b_show_trimming
01152     }
01153
01154     if(b_show_trimming)
01155     {
01156         pcl_tangents->clear();
01157
01158         for(ui_vert = 0; ui_vert < cui_verts; ++ui_vert)
01159         {
01160             if(vi_new_idx[ui_vert] >= 0)
01161             {
01162                 pcl_tangents->editFieldPtr()->push_back(Vec3f(0.0, 0.0, 0.0) );
01163             }
01164         }
01165
01166         for(ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop)
01167         {
01168             ui_vertex_cnt = pt_surfdata->vvclEdgeLoops[ui_loop].size();
01169
01170             for(ui_vert = 0; ui_vert < ui_vertex_cnt; ++ui_vert)
01171             {
01172                 if(ui_vert == 0)
01173                 {
01174                     pcl_prevv = &pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vertex_cnt - 1];
01175                     pcl_nextv = &pt_surfdata->vvclEdgeLoops3D[ui_loop][1];
01176                 }
01177                 else if(ui_vert == ui_vertex_cnt - 1)
01178                 {
01179                     pcl_prevv = &pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert - 1];
01180                     pcl_nextv = &pt_surfdata->vvclEdgeLoops3D[ui_loop][0];
01181                 }
01182                 else
01183                 {
01184                     pcl_prevv = &pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert - 1];
01185                     pcl_nextv = &pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert + 1];
01186                 }
01187                 pcl_actv = &pt_surfdata->vvclEdgeLoops3D[ui_loop][ui_vert];
01188                 // calculate the tangents of the trimming polyloops:
01189                 // (nextv - actv).normalize() plus
01190                 // (actv - prevv).normalize()  -> and normalize it again
01191                 cl_v1[0] = (*pcl_nextv)[0] - (*pcl_actv)[0];
01192                 cl_v1[1] = (*pcl_nextv)[1] - (*pcl_actv)[1];
01193                 cl_v1[2] = (*pcl_nextv)[2] - (*pcl_actv)[2];
01194                 cl_v1.normalize();
01195                 cl_v2[0] = (*pcl_actv)[0] - (*pcl_prevv)[0];
01196                 cl_v2[1] = (*pcl_actv)[1] - (*pcl_prevv)[1];
01197                 cl_v2[2] = (*pcl_actv)[2] - (*pcl_prevv)[2];
01198                 cl_v2.normalize();
01199                 cl_tangent = cl_v1 + cl_v2;
01200                 cl_tangent.normalize();
01201
01202                 cl_tangent *= sqrt(getError() );
01203
01204                 pcl_tangents->editFieldPtr()->push_back(-cl_tangent);
01205                 pcl_tangents->editFieldPtr()->push_back( cl_tangent);
01206             }
01207         }
01208
01209 //      std::cerr<<"tangents"<<std::endl;
01210     } // b_show_trimming
01211
01212     pcl_indices->clear();
01213
01214     for(ui_face = 0; ui_face < cui_faces; ++ui_face)
01215     {
01216         pcl_face = &triangles[ui_face];
01217         if( (norms.size() == 0) ||
01218             (checkOrient(pcl_face->vertices[0],
01219                          pcl_face->vertices[1],
01220                          pcl_face->vertices[2], gverts, norms) ) )
01221         {
01222             pcl_indices->push_back(vi_new_idx[pcl_face->vertices[0]]);
01223             pcl_indices->push_back(vi_new_idx[pcl_face->vertices[1]]);
01224             pcl_indices->push_back(vi_new_idx[pcl_face->vertices[2]]);
01225         }
01226         else
01227         {
01228             pcl_indices->push_back(vi_new_idx[pcl_face->vertices[0]]);
01229             pcl_indices->push_back(vi_new_idx[pcl_face->vertices[2]]);
01230             pcl_indices->push_back(vi_new_idx[pcl_face->vertices[1]]);
01231         }
01232     }
01233
01234     ui_idx = ui_used;
01235     if(b_show_trimming)
01236     {
01237         for(ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop)
01238         {
01239             ui_vertex_cnt = pt_surfdata->vvclEdgeLoops[ui_loop].size();
01240
01241             for(ui_vert = 0; ui_vert < ui_vertex_cnt; ++ui_vert)
01242             {
01243                 pcl_indices->push_back(ui_idx++);
01244                 pcl_indices->push_back(ui_idx++);
01245             }
01246
01247             pcl_indices->push_back(ui_idx - 2 * ui_vertex_cnt);
01248             pcl_indices->push_back(ui_idx - 2 * ui_vertex_cnt + 1);
01249         }
01250
01251 //          std::cerr << ui_idx + 2 * cui_loop_cnt << " indices used" << std::endl;
01252     } // b_show_trimming
01253 //    std::cerr<<"indices"<<std::endl;
01254
01255     if(b_show_trimming)
01256     {
01257         if(norms.size() > 0)
01258         {
01259             if(texcoords.size() > 0)    // fatborders, normals and standard textures
01260             {
01261                 setTypes     (pcl_type     );
01262                 setLengths   (pcl_size     );
01263                 setIndices   (pcl_indices  );
01264
01265                 setPositions (pcl_points   );
01266                 setNormals   (pcl_norms    );
01267                 setTexCoords (pcl_tangents );
01268                 setTexCoords1(pcl_texcoords);
01269                 //                   std::cerr<<"setting stuph3 "<<std::endl;
01270             }
01271             else // fatborders, normals but no standard textures (most used case)
01272             {
01273                 setTypes    (pcl_type    );
01274                 setLengths  (pcl_size    );
01275                 setIndices  (pcl_indices );
01276
01277                 setPositions(pcl_points  );
01278                 setNormals  (pcl_norms   );
01279                 setTexCoords(pcl_tangents);
01280
01281 //                   std::cerr<<"setting stuph!"<<std::endl;
01282             }
01283         }
01284         else
01285         {
01286             if(texcoords.size() > 0)    //fatborders and normalmaps and no textures
01287             {
01288                 setTypes     (pcl_type     );
01289                 setLengths   (pcl_size     );
01290                 setIndices   (pcl_indices  );
01291
01292                 setPositions (pcl_points   );
01293                 setTexCoords (pcl_tangents );
01294                 setTexCoords1(pcl_texcoords);
01295             }
01296             else // fatborders, no normals, no textures -- makes no sense??? NPR?
01297                  // essentially flat-shading
01298             {
01299                 setTypes   (pcl_type     );
01300                 setLengths (pcl_size     );
01301                 setIndices (pcl_indices  );
01302
01303                 setPositions(pcl_points  );
01304                 setTexCoords(pcl_tangents);
01305 //                   std::cerr<<"setting stuph2"<<std::endl;
01306             }
01307         }
01308     }
01309     else
01310     {
01311         if(norms.size() > 0)
01312         {
01313             if(texcoords.size() > 0)     // no fatborders, normals and standard textures
01314             {
01315                 setTypes    (pcl_type     );
01316                 setLengths  (pcl_size     );
01317                 setIndices  (pcl_indices  );
01318
01319                 setPositions(pcl_points   );
01320                 setNormals  (pcl_norms    );
01321                 setTexCoords(pcl_texcoords);
01322 //                   std::cerr<<"setting stuph4"<<std::endl;
01323             }
01324             else // no fatborders, normals but no standard textures
01325             {
01326                 setTypes    (pcl_type   );
01327                 setLengths  (pcl_size   );
01328                 setIndices  (pcl_indices);
01329
01330                 setPositions(pcl_points );
01331                 setNormals  (pcl_norms  );
01332             }
01333         }
01334         else
01335         {
01336             if(texcoords.size() > 0)    // no fatborders, normalmaps
01337             {
01338                 setTypes    (pcl_type     );
01339                 setLengths  (pcl_size     );
01340                 setIndices  (pcl_indices  );
01341
01342                 setPositions(pcl_points   );
01343                 setTexCoords(pcl_texcoords);
01344             }
01345             else // no fatborders, no normals, no textures
01346             {
01347                 setTypes    (pcl_type   );
01348                 setLengths  (pcl_size   );
01349                 setIndices  (pcl_indices);
01350
01351                 setPositions(pcl_points );
01352             }
01353         }
01354     }
01355
01356 //        std::cerr<<"Surface::buildSurface:   texcoords ptr: " << getTexCoords() << std::endl;
01357 //        std::cerr<<"Surface::buildSurface:   texcoords1 ptr: " << getTexCoords1() << std::endl;
01358
01359
01360     // build new display list if used
01361 //  invalidateDlistCache( );
01362
01363     return 0;
01364 }
01365
01366
01367 //internal
01368 bool Surface::checkOrient(UInt32 ui_v1, UInt32 ui_v2, UInt32 ui_v3,
01369                           std::vector<Pnt3f> &m_vclGlobalVertices,
01370                           std::vector<Vec3f> &m_vclNormal)
01371 {
01372     const Vec3f ccl_norm_p = m_vclNormal[ui_v1] + m_vclNormal[ui_v2] + m_vclNormal[ui_v3];
01373     const Vec3f ccl_vec1   = m_vclGlobalVertices[ui_v2] - m_vclGlobalVertices[ui_v1];
01374     const Vec3f ccl_vec2   = m_vclGlobalVertices[ui_v3] - m_vclGlobalVertices[ui_v1];
01375     const Vec3f ccl_norm_t = ccl_vec1.cross(ccl_vec2);
01376
01377     // FIXME: is 0.0 really better than -DCTP_EPS ?
01378     return(ccl_norm_p.dot(ccl_norm_t) > 0.0);
01379 }
01380
01381
01383
01404 void Surface::addCurve(
01405     UInt32                     dim,
01406     const std::vector<Real64> &knots,
01407     const std::vector<Pnt2f> & controlpoints,
01408     bool                       newloop)
01409 {
01410     UInt32             cpsize = controlpoints.size();
01411     std::vector<Pnt3f> ratcontrolpoints;
01412
01413     ratcontrolpoints.reserve(cpsize);
01414
01415     for(UInt32 i = 0; i < cpsize; ++i)
01416     {
01417         ratcontrolpoints.push_back(Pnt3f(controlpoints[i][0],
01418                                          controlpoints[i][1],
01419                                          1.0f) );
01420     }
01421
01422     addCurve(dim, knots, ratcontrolpoints, newloop);
01423 }
01424
01426
01447 void Surface::addCurve(
01448     UInt32                     dim,
01449     const std::vector<Real64> &knots,
01450     const std::vector<Pnt3f> & controlpoints,
01451     bool                       newloop)
01452 {
01453     UInt32 cpsize   = controlpoints.size();
01454     UInt32 knotsize = knots.size();
01455
01456     if(dim + cpsize + 1 != knotsize)
01457     {
01458 //        SWARNING <<"Surface::addCurve: inconsistent curve attributes..." << endLog;
01459         return;
01460     }
01461 //    SLOG <<"addCurve NI " << std::endl;
01462
01463     if(_sfNumCurves.getValue() == 0)
01464     {
01465         //this is the first curve -> it starts a new loop
01466 //        SLOG <<"addcurve first curve"<<endLog;
01467         newloop = true;
01468     }
01469     _mfDimensions.push_back(dim);
01470     if(newloop)
01471     {
01472         _mfCurvesPerLoop.push_back(1);   //1 curve in a new loop
01473 //        SLOG <<"addcurve newloop"<<endLog;
01474     }
01475     else
01476     {
01477 //        SLOG <<"addcurve NOT newloop"<<endLog;
01478         UInt32 cplsize = _mfCurvesPerLoop.size();
01479 //        _mfCurvesPerLoop.setValue( _mfCurvesPerLoop.getValue( cplsize - 1 ) + 1,
01480 //                                   cplsize - 1 );
01481         _mfCurvesPerLoop[cplsize - 1] = _mfCurvesPerLoop[cplsize - 1] + 1;
01482     }
01483     _mfKnotLengths.push_back(knotsize);
01484     UInt32 i;
01485
01486     for(i = 0; i < knotsize; ++i)
01487     {
01488         _mfKnots.push_back(Real32(knots[i]) );
01489     }
01490
01491     for(i = 0; i < cpsize; ++i)
01492     {
01493         _mfCurveControlPoints.push_back(controlpoints[i]);
01494     }
01495
01496     _sfNumCurves.setValue(_sfNumCurves.getValue() + 1);
01497 }
01498
01500
01508 void Surface::removeCurves(void)
01509 {
01510     if(_sfNumCurves.getValue() == 0)    //we have no curves
01511     {
01512         return;
01513     }
01514
01515     _sfNumCurves.setValue(0);
01516     _mfKnotLengths.clear();
01517     _mfDimensions.clear();
01518     _mfCurveControlPoints.clear();
01519     _mfKnots.clear();
01520     _mfCurvesPerLoop.clear();
01521 }
01522
01523
01525 SurfaceTransitPtr Surface::clone(void)
01526 {
01527     SurfaceTransitPtr surf = Surface::create();
01528
01529     SWARNING << "Surface::clone not completely implemented!" << endLog;
01530     //  create copies of the attributes
01531     if(getMFKnotsU() != NULL)
01532         surf->editMFKnotsU()->setValues(*getMFKnotsU());
01533
01534     if(getMFKnotsV() != NULL)
01535         surf->editMFKnotsV()->setValues(*getMFKnotsV());
01536
01537     if(getMFKnotLengths() != NULL)
01538         surf->editMFKnotLengths()->setValues(*getMFKnotLengths());
01539
01540     if(getMFDimensions() != NULL)
01541         surf->editMFDimensions()->setValues(*getMFDimensions());
01542
01543     if(getMFCurveControlPoints() != NULL)
01544         surf->editMFCurveControlPoints()->setValues(*getMFCurveControlPoints());
01545
01546     if(getMFKnots() != NULL)
01547         surf->editMFKnots()->setValues(*getMFKnots());
01548
01549     if(getMFCurvesPerLoop() != NULL)
01550         surf->editMFCurvesPerLoop()->setValues(*getMFCurvesPerLoop());
01551
01552     surf->setMaterial(getMaterial());
01553     surf->setDimU(getDimU());
01554     surf->setDimV(getDimV());
01555     surf->setNumCurves(getNumCurves());
01556     surf->setError(getError());
01557     surf->setIsDelaunay(getIsDelaunay());
01558     surf->setControlPoints(getControlPoints());
01559     surf->setTextureControlPoints(getTextureControlPoints());
01560
01561     return surf;
01562 }
01563
01564
01566
01583 //#pragma optimize("",off)
01584 void Surface::readFromTSO(std::istream &infile, bool useTextures)
01585 {
01586     Int32                  err                = 0;
01587     BSplineTrimmedSurface *cl_trimmed_surface = new BSplineTrimmedSurface;
01588     BSplineTensorSurface   tensor_surface;
01589     trimmingloop           trimloop;
01590
01591     // this is actually rather inefficient: first we convert the data to the
01592     // OpenSG representation, and then we convert back
01593     // to the BSplineTrimmedSurface representation later
01594     // during the tessellation...
01595     // but it's somewhat simpler to extract the info from
01596     // the BSplineTrimmedSurface class than to read from the file
01597     // I might rewrite it later, though...
01598
01599     err = cl_trimmed_surface->read(infile);
01600     if(err)
01601     {
01602         SWARNING << "Couldn't read surface, exiting... " << err << endLog;
01603         delete cl_trimmed_surface;
01604         return;
01605     }
01606
01607     tensor_surface = cl_trimmed_surface->getSurface();
01608     trimloop       = cl_trimmed_surface->getTrimmingLoops();
01609
01610     // OK, first do surface business
01611     DCTPVec4dmatrix v4cps =  tensor_surface.getControlPointMatrix();
01612
01613     UInt32 cpusize = v4cps.size();
01614     UInt32 cpvsize = v4cps[0].size();
01615     UInt32 /*k,*/u,v;
01616     Vec4d  vec4;
01617
01618     GeoPnt4fPropertyUnrecPtr pPos;
01619
01620     if(_sfControlPoints.getValue() == NULL)
01621     {
01622         pPos = GeoPnt4fProperty::create();
01623
01624         setControlPoints(pPos);
01625     }
01626     else
01627     {
01628         pPos = dynamic_cast<GeoPnt4fProperty *>(_sfControlPoints.getValue());
01629     }
01630
01631     MFPnt4f *mfControlPoints = pPos->editFieldPtr();
01632 //    MFPnt3f &mfControlPoints = pPos->getField();
01633
01634 //    mfControlPoints.resize( cpusize * cpvsize );
01635     mfControlPoints->clear();
01636
01637     for(u = 0; u < cpusize; ++u)
01638     {
01639         for(v = 0; v < cpvsize; ++v)
01640         {
01641 //            k = u * cpvsize + v;
01642             vec4 = v4cps[u][v];
01643             mfControlPoints->push_back(Pnt4f(vec4[0], vec4[1], vec4[2], vec4[3]));
01644 //            mfControlPoints.push_back(Pnt3f(vec4[0], vec4[1], vec4[2]));
01645         }
01646     }
01647
01648     _sfDimU.setValue(tensor_surface.getDimension_U() );
01649     _sfDimV.setValue(tensor_surface.getDimension_V() );
01650
01651     DCTPdvector knots;
01652
01653     knots = tensor_surface.getKnotVector_U();
01654     _mfKnotsU.clear();
01655
01656     for(u = 0; u < knots.size(); ++u)
01657     {
01658         _mfKnotsU.push_back(Real32(knots[u]) );
01659     }
01660
01661     knots = tensor_surface.getKnotVector_V();
01662     _mfKnotsV.clear();
01663
01664     for(v = 0; v < knots.size(); ++v)
01665     {
01666         _mfKnotsV.push_back(Real32(knots[v]) );
01667     }
01668
01669     // now deal with the trimming curves
01670     removeCurves();
01671
01672     bool                isnewloop;
01673     UInt32              actdim;
01674     std::vector<Real64> actknots;
01675     std::vector<Pnt3f>  actcontrolpoints;
01676     DCTPVec3dvector     v3actcps;
01677
01678     for(UInt32 i = 0; i < trimloop.size(); ++i)
01679     {
01680         isnewloop = true;
01681
01682         for(UInt32 j = 0; j < trimloop[i].size(); ++j)
01683         {
01684             actknots = trimloop[i][j].getKnotVector();
01685             actdim   = trimloop[i][j].getDimension();
01686             v3actcps = trimloop[i][j].getControlPointVector();
01687             actcontrolpoints.clear();
01688
01689             for(UInt32 kk = 0; kk < v3actcps.size(); ++kk)
01690             {
01691                 actcontrolpoints.push_back(Pnt3f(v3actcps[kk][0],
01692                                                  v3actcps[kk][1],
01693                                                  v3actcps[kk][2]));
01694             }
01695
01696             addCurve(actdim, actknots, actcontrolpoints, isnewloop);
01697             isnewloop = false;
01698         }
01699     }
01700
01701     // trimming curves...
01702     delete cl_trimmed_surface;
01703
01704     if(useTextures)
01705     {
01706 //        std::cerr<<"read in texture coordinates..."<<std::endl;
01707         char buffer[1024];
01708         infile >> buffer >> std::ws;
01709 //        std::cerr <<"buffer: " << buffer <<std::endl;
01710         UInt32 numoftexcps = cpusize * cpvsize;
01711 //        _mfTextureControlPoints.clear();
01712
01713         GeoVec2fPropertyUnrecPtr pTexPos;
01714
01715         if(_sfTextureControlPoints.getValue() == NULL)
01716         {
01717             pTexPos = GeoVec2fProperty::create();
01718
01719             setTextureControlPoints(pTexPos);
01720         }
01721         else
01722         {
01723             pTexPos = dynamic_cast<GeoVec2fProperty *>(
01724                 _sfTextureControlPoints.getValue());
01725         }
01726
01727         MFVec2f *mfTextureControlPoints = pTexPos->editFieldPtr();
01728         mfTextureControlPoints->clear();
01729
01730         Vec2f temp;
01731
01732         for(UInt32 ti = 0; ti < numoftexcps; ++ti)
01733         {
01734             infile >> std::ws >> temp[0] >> std::ws >> temp[1] >> std::ws;
01735             mfTextureControlPoints->push_back(temp);
01736         }
01737
01738 //        std::cerr<<"read " << mfTextureControlPoints.size() << " cps."<<std::endl;
01739     }
01740 }
01741 //#pragma optimize("",on)
01742
01743
01744 void Surface::writeToTSO(std::ostream &outfile)
01745 {
01746     _trimmedSurface->write(outfile);
01747 }
01748
01749
01751
01755 UInt32 Surface::writeToOBJ(std::ostream &outfile, UInt32 offset)
01756 {
01757     unsigned int uicnt;
01758 //     std::cerr << "current offset:" << g_current_obj_offset << std::endl;
01759     outfile << "g obj " << std::endl;
01760     GeoVectorProperty   *pcl_points    = getPositions();
01761     GeoVectorProperty   *pcl_norms     = getNormals();
01762     GeoIntegralProperty *pcl_indices   = getIndices();
01763     GeoVectorProperty   *pcl_texcoords = getTexCoords();
01764     std::cerr << " indices size: " << pcl_indices->size() << std::endl;
01765     std::cerr << " points size: " << pcl_points->size() << std::endl;
01766     UInt32 ui_faces   = pcl_indices->size() / 3;
01767     UInt32 uivertsize = pcl_points->size();
01768     outfile << "# vertices " << uivertsize << std::endl;
01769
01770     //write out vertices
01771     for(uicnt = 0; uicnt < uivertsize; uicnt++)
01772     {
01773         Pnt3f ppp = pcl_points->getValue<Pnt3f>(uicnt);
01774
01775         outfile << "v " << ppp.x() << " " <<
01776         ppp.y() << " " <<
01777         ppp.z() << std::endl;
01778
01779     }
01780
01781     //write out normals
01782     for(uicnt = 0; uicnt < uivertsize; uicnt++)
01783     {
01784         Vec3f ppp = pcl_norms->getValue<Vec3f>(uicnt);
01785
01786         outfile << "vn " << ppp.x() << " " <<
01787         ppp.y() << " " <<
01788         ppp.z() << std::endl;
01789
01790     }
01791
01792     //write out texture coordinates
01793     for(uicnt = 0; uicnt < uivertsize; uicnt++)
01794     {
01795         Vec2f ppp = pcl_texcoords->getValue<Vec2f>(uicnt);
01796
01797         outfile << "vt " << ppp.x() << " " <<
01798         ppp.y() << " " << std::endl;
01799     }
01800
01801     outfile << "# faces " << ui_faces << std::endl;
01802
01803     //write out triangles
01804     for(unsigned int uitricnt = 0; uitricnt < ui_faces; uitricnt++)
01805     {
01806         UInt32 ind1 = pcl_indices->getValue(uitricnt * 3);
01807         UInt32 ind2 = pcl_indices->getValue(uitricnt * 3 + 1);
01808         UInt32 ind3 = pcl_indices->getValue(uitricnt * 3 + 2);
01809         UInt32 i1   = ind1 + offset + 1;
01810         UInt32 i2   = ind2 + offset + 1;
01811         UInt32 i3   = ind3 + offset + 1;
01812
01813         outfile << "f ";
01814         outfile << i1 << "/" << i1 << "/" << i1 << " " <<
01815         i2 << "/" << i2 << "/" << i2 << " " <<
01816         i3 << "/" << i3 << "/" << i3 << std::endl;
01817     }
01818
01819     return offset + uivertsize;
01820 }
01821
01823
01824 void Surface::dump(            UInt32,
01825                          const BitVector) const
01826 {
01827     SLOG << "Dump Surface NI" << endLog;
01828 }
01829
01830 void Surface::onCreate(const Surface *source)
01831 {
01832     // if we're in startup this is the prototype, which shouldn't have an id
01833     if(GlobalSystemState == Startup)
01834         return;
01835
01836     setSurfaceGLId(
01837         Window::registerGLObject(
01838             boost::bind(&Surface::handleGL,
01839                         SurfaceMTUncountedPtr(this), _1, _2, _3, _4),
01840             &Surface::handleDestroyGL));
01841
01842     Inherited::onCreate(source);
01843 }
01844
01845 void Surface::onDestroy(UInt32 id)
01846 {
01847     if(getSurfaceGLId() > 0)
01848         Window::destroyGLObject(getSurfaceGLId(), 1);
01849
01850     Inherited::onDestroy(id);
01851 }
01852
01853 UInt32 Surface::handleGL(DrawEnv                *pEnv,
01854                          UInt32                  id,
01855                          Window::GLObjectStatusE mode,
01856                          UInt32                  uiOptions)
01857 {
01858     if(mode == Window::initialize  ||
01859        mode == Window::needrefresh ||
01860        mode == Window::reinitialize)
01861     {
01862         if((getDirtyMask() & DONTTESSELLATE) == 0x0000)
01863         {
01864             if((getDirtyMask() & TESSELLATE) != 0x0000)
01865             {
01866                 tessellate();
01867             }
01868             else if((getDirtyMask() & RETESSELLATE) != 0x0000)
01869             {
01870                 reTessellate();
01871             }
01872
01873             editDirtyMask() &= ~(TESSELLATE | RETESSELLATE);
01874         }
01875     }
01876
01877     return 0;
01878 }
01879
01880 void Surface::handleDestroyGL(DrawEnv                *pEnv,
01881                               UInt32                  id,
01882                               Window::GLObjectStatusE mode)
01883 {
01884     UInt32  glid;
01885     Window *pWin = pEnv->getWindow();
01886
01887     if(mode == Window::destroy)
01888     {
01889         glid = pWin->getGLObjectId(id);
01890
01891         glDeleteLists(glid, 1);
01892     }
01893     else if(mode == Window::finaldestroy)
01894     {
01895         //SWARNING << "Last geometry user destroyed" << std::endl;
01896     }
01897     else
01898     {
01899         SWARNING << "Surface::handleDestroyGL: Illegal mode: "
01900                  << mode << " for id " << id << std::endl;
01901     }
01902 }
01903
01904 // Calculate the volume based on bounding box of the control points.
01905 // If any of the control points have 0 weight, also take into
01906 // account the tessellated geometry, otherwise the volume will be
01907 // too small.
01908 // FIXME: a better solution might be to do de Casteljau steps
01909 // FIXME: until there are no control points w/ 0 weights and
01910 // FIXME: redo the calculation...
01911 void Surface::adjustVolume(Volume & volume)
01912 {
01913     if(!_volumeCache.isEmpty())
01914     {
01915         // use cached volume.
01916         volume.setValid();
01917         volume.extendBy(_volumeCache);
01918
01919         return;
01920     }
01921
01922     GeoVectorProperty *pos             = getControlPoints();
01923     bool               has_zeroweights = false;
01924
01925     _volumeCache.setValid();
01926
01927     GeoPnt3fProperty *pPos    = dynamic_cast<GeoPnt3fProperty *>(pos);
01928     GeoPnt4fProperty *pRatPos = dynamic_cast<GeoPnt4fProperty *>(pos);
01929
01930     if(pos == NULL)
01931         return;                  // Node has no points, no volume
01932
01933     if(pPos != NULL)
01934     {
01935         for(UInt32 i = 0; i < pPos->size(); ++i)
01936         {
01937             _volumeCache.extendBy(pPos->getValue(i));
01938         }
01939     }
01940     else if(pRatPos != NULL)
01941     {
01942         for(UInt32 i = 0; i < pRatPos->size(); ++i)
01943         {
01944             Pnt3f pnt;
01945
01946             if(osgAbs(pRatPos->getField()[i][3]) > DCTP_EPS)
01947             {
01948                 pnt[0] = pRatPos->getField()[i][0] / pRatPos->getField()[i][3];
01949                 pnt[1] = pRatPos->getField()[i][1] / pRatPos->getField()[i][3];
01950                 pnt[2] = pRatPos->getField()[i][2] / pRatPos->getField()[i][3];
01951                 _volumeCache.extendBy(pnt);
01952             }
01953             else
01954             {
01955                 has_zeroweights = true;
01956             }
01957         }
01958     }
01959
01960     if(has_zeroweights)
01961     {
01962         GeoVectorProperty *points = getPositions();
01963         if(points != NULL)
01964         {
01965             for(UInt32 i = 0; i < points->size(); ++i)
01966             {
01967                 _volumeCache.extendBy(points->getValue<Pnt3r>(i));
01968             }
01969         }
01970         // FIXME: a warning should be printed here since the calculated
01971         // FIXME: volume will not be exact if there was no tessellated
01972         // FIXME: geometry, but in that case there's nothing to render
01973         // FIXME: anyway so we skip the warning (which would be
01974         // FIXME: unnecessarily (and annoyingly) printed at startup
01975         // FIXME: e.g. when the SSM::showall() method is called).
01976         // FIXME: Better suggestions are welcome.
01977     }
01978
01979     volume.extendBy(_volumeCache);
01980 }
01981
01982 void Surface::forceTessellate(void)
01983 {
01984     editDirtyMask() |= DONTTESSELLATE;
01985
01986     if((getDirtyMask() & TESSELLATE) != 0x0000)
01987     {
01988         tessellate();
01989     }
01990     else if((getDirtyMask() & RETESSELLATE) != 0x0000)
01991     {
01992         reTessellate();
01993     }
01994
01995     editDirtyMask() &= ~(TESSELLATE | RETESSELLATE);
01996 }
01997
01998 void Surface::flip(void)
01999 {
02000     if(_trimmedSurface != NULL)
02001         _trimmedSurface->flip();
02002 }
02003
02004 Action::ResultE Surface::drawPrimitives(DrawEnv *pEnv)
02005 {
02006     pEnv->getWindow()->validateGLObject(getSurfaceGLId(), pEnv);
02007
02008     return Inherited::drawPrimitives(pEnv);
02009 }