1 /*---------------------------------------------------------------------------*\
2 * OpenSG NURBS Library *
5 * Copyright (C) 2001-2006 by the University of Bonn, Computer Graphics Group*
7 * http://cg.cs.uni-bonn.de/ *
9 * contact: edhellon@cs.uni-bonn.de, guthe@cs.uni-bonn.de, rk@cs.uni-bonn.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
40 #include "OSGQuadTreeCreator.h"
41 #include "OSGParSpaceTrimmer.h"
42 #include "OSGNurbsPatchSurface.h"
43 //#include <DCTPBoundary.h>
44 #include "OSGpredicates.h" // for exactinit
45 //#include "rounding.h" // for FPU_ROUND_DOUBLE
46 #include "OSGSurface.h"
50 //#include "BoundarySimplifier/BoundaryObject.h"
54 //put miniball inside OSG namespace
55 //#include "miniball/miniball.H"
58 #pragma warning (disable : 985)
62 #define OSG_VEC_COMPUTE
64 //static unsigned int g_uiColor = 0;
67 static double g_dTrimmingConversionTime
= 0.0;
68 static double g_dTrimmingApproximationTime
= 0.0;
69 static OSG::Time g_clTrimmingApproximationStart
;
70 static double g_dTotalTime
= 0.0;
71 static OSG::Time g_clTotalStart
;
72 static OSG::Time g_clActTime
;
77 CNurbsPatchSurface::CNurbsPatchSurface():
78 m_vclBSplineSurfaces ( ),
79 m_vvvclBezierSurfaces ( ),
84 m_vclParameterVertices ( ),
85 m_vclGlobalVertices ( ),
89 m_pclQuadTree (NULL
),
90 m_bErrorTreeValid (false),
91 m_bUseTextures (false),
92 m_vvTextureControlPoints( )
94 #ifdef OSG_TIMING_FUNCS
95 , m_uiTotalTriangleCnt (0 )
96 , m_uiNewTriangleCnt (0 )
99 #ifdef OSG_KEEP_2D_POINTS
106 CNurbsPatchSurface::~CNurbsPatchSurface()
108 // unsigned int ui_idx;
115 for(unsigned int ui_number
= 0; ui_number
< m_vtSurfaces
.size(); ++ui_number
)
117 delete m_vtSurfaces
[ui_number
].pclErrorTree
;
120 m_vclBSplineSurfaces
.clear();
121 m_vvvclBezierSurfaces
.clear();
122 m_vvdUParams
.clear();
123 m_vvdVParams
.clear();
124 m_vtSurfaces
.clear();
125 // m_vpclNodes.clear( );
126 if(m_pclQuadTree
!= NULL
)
128 delete m_pclQuadTree
;
129 m_pclQuadTree
= NULL
;
135 void CNurbsPatchSurface::AddSurface(BSplineTrimmedSurface
*clSurface
)
138 g_clTotalStart
= OSG::getSystemTime();
141 unsigned int ui_number
= UInt32(m_vclBSplineSurfaces
.size());
143 // std::cerr << "\rreading surface " << ui_number + 1;
146 m_vclBSplineSurfaces
.resize(ui_number
+ 1);
147 m_vvvclBezierSurfaces
.resize(ui_number
+ 1);
148 m_vvdUParams
.resize(ui_number
+ 1);
149 m_vvdVParams
.resize(ui_number
+ 1);
150 // m_vclSeperateMeshes.resize( ui_number + 1 );
151 // m_vclSewedMeshes.resize( ui_number + 1 );
152 m_vtSurfaces
.resize(ui_number
+ 1);
153 // m_vtTrimmingCurves.resize( ui_number + 1 );
154 // m_vpclNodes.resize( ui_number + 1 );
157 // copy and init values
158 m_vclBSplineSurfaces
[ui_number
] = *clSurface
;
159 m_vtSurfaces
[ui_number
].dError
= 10.0;
160 m_vtSurfaces
[ui_number
].ucStatus
= 0;
161 m_vtSurfaces
[ui_number
].pclErrorTree
= new CErrorQuadTree();
162 m_bErrorTreeValid
= true;
163 m_vtSurfaces
[ui_number
].uiTriangleCnt
= 0;
165 // calculate initial values
166 ConvertToBezier(ui_number
);
169 g_clActTime
= OSG::getSystemTime();
170 g_dTotalTime
+= g_clActTime
- g_clTotalStart
;
171 g_dTrimmingConversionTime
+= g_clActTime
- g_clTotalStart
;
176 void CNurbsPatchSurface::setSurface(BSplineTrimmedSurface
*clSurface
,
177 std::vector
<Pnt2f
> & texturecps
,
180 //FIXME: I'm not sure how much of these reinits is actually needed
187 for(unsigned int ui_number
= 0; ui_number
< m_vtSurfaces
.size(); ++ui_number
)
189 delete m_vtSurfaces
[ui_number
].pclErrorTree
;
190 m_vtSurfaces
[ui_number
].pclErrorTree
= NULL
;
193 m_vclBSplineSurfaces
.clear();
194 m_vvvclBezierSurfaces
.clear();
195 m_vvdUParams
.clear();
196 m_vvdVParams
.clear();
197 m_vtSurfaces
.clear();
200 // std::cerr<<"setSurface: m_vtSurfaces.size(): " << m_vtSurfaces.size() <<
202 AddSurface(clSurface
);
204 m_bUseTextures
= bUseTextures
;
209 BSplineTensorSurface
&tensor_surface
= clSurface
->getSurface();
210 DCTPVec4dmatrix
& surf_cps
= tensor_surface
.getControlPointMatrix();
211 UInt32 u_size
= UInt32(surf_cps
.size());
212 UInt32 v_size
= UInt32(surf_cps
[0].size());
214 if( (u_size
* v_size
) != texturecps
.size() )
216 std::cerr
<< "setSurface: wrong number of texture control points, texturing disabled" << std::endl
;
217 m_bUseTextures
= false;
220 m_vvTextureControlPoints
.resize(u_size
);
222 for(i
= 0; i
< u_size
; ++i
)
224 m_vvTextureControlPoints
[i
].resize(v_size
);
227 for(i
= 0; i
< u_size
; ++i
)
229 for(j
= 0; j
< v_size
; ++j
)
231 tempv2d
[0] = texturecps
[k
][0];
232 tempv2d
[1] = texturecps
[k
][1];
233 m_vvTextureControlPoints
[i
][j
] = tempv2d
;
241 void CNurbsPatchSurface::setupErrorTree(double dError
)
243 double d_old_err
= m_vtSurfaces
[0].dError
;
245 m_vtSurfaces
[0].dError
= dError
;
246 CalculateQuadTree(0, false);
248 m_vtSurfaces
[0].dError
= d_old_err
;
251 void CNurbsPatchSurface::setError(double dError
)
258 m_vtSurfaces
[0].vvclEdgeLoops
.clear();
259 m_vtSurfaces
[0].vvclEdgeLoops3D
.clear();
260 m_vtSurfaces
[0].vvclEdgeLoopsNorm
.clear();
261 m_vtSurfaces
[0].vvclEdgeLoopsTex
.clear();
266 //normal tessellation, no texture
267 void CNurbsPatchSurface::getTessellation(std::vector
<Pnt3f
> & gverts
,
268 std::vector
<Vec3f
> & norms
,
269 std::vector
<SimplePolygon
> &tris
,
273 g_clTotalStart
= OSG::getSystemTime();
276 if( (m_vtSurfaces
[0].ucStatus
& BEZIER_SURFACES_VALID
) &&
277 ( (m_vtSurfaces
[0].ucStatus
& TRIM_SEGS_VALID
) == 0) )
280 g_clTrimmingApproximationStart
= OSG::getSystemTime();
282 CalculateQuadTree(0, true);
283 CalculateTrimmingLoops(0);
285 g_clActTime
= OSG::getSystemTime();
286 g_dTrimmingApproximationTime
+= g_clActTime
- g_clTrimmingApproximationStart
;
288 CalculateQuadTree(0, false);
289 // std::cerr << "\rtesselating surface " << ui_surface + 1;
290 CalculateActualTrimming(0);
291 CalculateGraph(0, usedelaunay
);
292 // ConvertPoints( 0 );
293 //// convertPoints( gverts, tris );
299 // BuildNode( ui_surface );
300 //// calculateNormals( norms );
301 calculatePointsAndNormals(gverts
, tris
, norms
);
302 ComputeNormalCone(0, norms
);
303 m_vclParameterVertices
.clear();
304 m_vclGlobalVertices
.clear();
305 m_vclTriangles
.clear();
309 std::cerr
<< "shouldn't be here..." << std::endl
;
311 // std::cerr << std::endl;
313 g_clActTime
= OSG::getSystemTime();
314 g_dTotalTime
+= g_clActTime
- g_clTotalStart
;
315 // std::cerr << "conversion " << g_dTrimmingConversionTime << " sec" << std::endl;
316 // std::cerr << "trimming " << g_dTrimmingApproximationTime << " sec " << std::endl;
317 // std::cerr << "total " << g_dTotalTime << " sec" << std::endl;
321 //normal tessellation, texturemapping: both normals and texturecoords
322 void CNurbsPatchSurface::getTessellation(std::vector
<Pnt3f
> & gverts
,
323 std::vector
<Vec3f
> & norms
,
324 std::vector
<Pnt2f
> & texturecoords
,
325 std::vector
<SimplePolygon
> &tris
,
329 if( (m_vtSurfaces
[0].ucStatus
& BEZIER_SURFACES_VALID
) &&
330 ( (m_vtSurfaces
[0].ucStatus
& TRIM_SEGS_VALID
) == 0) )
332 CalculateQuadTree(0, true);
333 CalculateTrimmingLoops(0);
334 CalculateQuadTree(0, false);
335 // std::cerr << "\rtesselating surface " << ui_surface + 1;
336 CalculateActualTrimming(0);
337 CalculateGraph(0, usedelaunay
);
343 // BuildNode( ui_surface );
344 //// calculateNormals( norms );
345 calculatePointsNormalsAndTextureCoords(gverts
,
349 ComputeNormalCone(0, norms
);
350 m_vclParameterVertices
.clear();
351 m_vclGlobalVertices
.clear();
352 m_vclTriangles
.clear();
356 std::cerr
<< "shouldn't be here..." << std::endl
;
358 // std::cerr << std::endl;
362 // get tessellation, using normalmaps (texcoords, but not normals!)
363 void CNurbsPatchSurface::getTessellation(std::vector
<Pnt3f
> & gverts
,
364 std::vector
<Pnt2f
> & texturecoords
,
365 std::vector
<SimplePolygon
> &tris
,
368 // Real64 d_time, d_last_time;
369 // d_last_time = getSystemTime();
371 if( (m_vtSurfaces
[0].ucStatus
& BEZIER_SURFACES_VALID
) &&
372 ( (m_vtSurfaces
[0].ucStatus
& TRIM_SEGS_VALID
) == 0) )
374 // std::cerr << "CalculateQuadTree";// << std::endl;
375 CalculateQuadTree(0, true);
376 /* d_time = getSystemTime();
377 std::cerr << " " << d_time - d_last_time << std::endl;
378 d_last_time = d_time;
379 std::cerr << "CalculateTrimmingLoops";// << std::endl;*/
380 CalculateTrimmingLoops(0);
381 /* d_time = getSystemTime();
382 std::cerr << " " << d_time - d_last_time << std::endl;
383 d_last_time = d_time;
384 std::cerr << "CalculateQuadTree";// << std::endl;*/
385 CalculateQuadTree(0, false);
386 /* d_time = getSystemTime();
387 std::cerr << " " << d_time - d_last_time << std::endl;
388 d_last_time = d_time;
389 // std::cerr << "\rtesselating surface " << ui_surface + 1;
390 std::cerr << "CalculateActualTrimming";// << std::endl;*/
391 CalculateActualTrimming(0);
392 /* d_time = getSystemTime();
393 std::cerr << " " << d_time - d_last_time << std::endl;
394 d_last_time = d_time;
395 std::cerr << "CalculateGraph";// << std::endl;*/
396 CalculateGraph(0, usedelaunay
);
397 /* d_time = getSystemTime();
398 std::cerr << " " << d_time - d_last_time << std::endl;
399 d_last_time = d_time;*/
400 // ConvertPoints( 0 );
401 //// convertPoints( gverts, tris );
407 // BuildNode( ui_surface );
408 //// calculateNormals( norms );
409 // calculatePointsAndNormals( gverts, tris, norms );
410 // std::cerr << "calculatePointsAndTextureCoords";// << std::endl;
411 calculatePointsAndTextureCoords(gverts
, tris
, texturecoords
);
412 /* d_time = getSystemTime();
413 std::cerr << " " << d_time - d_last_time << std::endl;
414 d_last_time = d_time;
415 // ComputeNormalCone( 0, norms );
416 std::cerr << "clearing" << std::endl;*/
417 m_vclParameterVertices
.clear();
418 m_vclGlobalVertices
.clear();
419 m_vclTriangles
.clear();
423 std::cerr
<< "shouldn't be here..." << std::endl
;
425 // std::cerr << std::endl;
432 void CNurbsPatchSurface::calculatePointsAndNormals(
433 std::vector
<Pnt3f
> & gverts
,
434 std::vector
<SimplePolygon
> &tris
,
435 std::vector
<Vec3f
> & norms
)
437 BSplineTensorSurface cl_surf
;
439 // std::cerr << "c" << std::endl;
441 cl_surf
= m_vclBSplineSurfaces
[0].getSurface();
442 // NOTE: also computes 3D vertex info in the gverts array
443 #ifdef OSG_VEC_COMPUTE
444 cl_surf
.computeNormal(m_vclParameterVertices
,
448 gverts
.resize(m_vclParameterVertices
.size() );
449 norms
.resize(m_vclParameterVertices
.size() );
451 for(unsigned int i
= 0; i
< m_vclParameterVertices
.size(); ++i
)
454 norms
[i
] = cl_surf
.computeNormal(m_vclParameterVertices
[i
], i_err
, gverts
[i
]);
459 std::cerr<<"haho"<< m_vclParameterVertices.size() << " " << gverts.size() << " " << norms.size() << std::endl;
460 for ( UInt32 i = 0; i < gverts.size(); ++i )
462 std::cerr << gverts[i] << " " << norms[i] << std::endl;
466 std::cerr<<"m_vclParameterVertices.size(): " << m_vclParameterVertices.size() << std::endl;
467 for ( UInt32 i = 0; i < m_vclParameterVertices.size(); ++i )
469 std::cerr<< m_vclParameterVertices[i] << std::endl;
470 if (osgabs(m_vclParameterVertices[i][1] - 8271.61) < 1.0f)
472 std::cerr<<"zeroing norm: " << i << std::endl;
473 norms[i][0] = norms[i][1] = norms[i][2] = 0.f;
478 tris
= m_vclTriangles
;
480 //copy the normals into the vvclEdgeLoopsNorm structure
481 unsigned int numloops
= UInt32(m_vtSurfaces
[0].vvclEdgeLoops
.size());
482 unsigned int actlooplength
;
483 #ifdef OSG_KEEP_2D_POINTS
484 unsigned int ui_actvertidx
= 0;
489 m_vtSurfaces
[0].vvclEdgeLoopsNorm
.resize(numloops
);
490 #ifndef OSG_FORCE_NO_T_VERTICES
491 m_vtSurfaces
[0].vvclEdgeLoops3D
.resize(numloops
);
494 for(unsigned int ui_actloop
= 0; ui_actloop
< numloops
; ++ui_actloop
)
496 actlooplength
= UInt32(m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
].size());
497 m_vtSurfaces
[0].vvclEdgeLoopsNorm
[ui_actloop
].resize(actlooplength
);
498 #ifdef OSG_KEEP_2D_POINTS
500 for(unsigned int ui_act
= 0; ui_act
< actlooplength
; ++ui_act
)
502 m_vtSurfaces
[0].vvclEdgeLoopsNorm
[ui_actloop
][ui_act
] =
503 Vec3d(norms
[ui_actvertidx
][0],
504 norms
[ui_actvertidx
][1],
505 norms
[ui_actvertidx
][2]);
507 /* std::cerr << norms[ ui_actvertidx ][0] << " ";
508 std::cerr << norms[ ui_actvertidx ][1] << " ";
509 std::cerr << norms[ ui_actvertidx ][2] << std::endl;*/
515 #ifdef OSG_FORCE_NO_T_VERTICES
516 cl_surf
.computeNormalforTrimming(
517 m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
],
518 m_vtSurfaces
[0].vvclEdgeLoopsNorm
[ui_actloop
]);
520 cl_surf
.computeNormalforTrimming(
521 m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
],
522 m_vtSurfaces
[0].vvclEdgeLoopsNorm
[ui_actloop
],
523 &m_vtSurfaces
[0].vvclEdgeLoops3D
[ui_actloop
]);
533 void CNurbsPatchSurface::calculatePointsNormalsAndTextureCoords(
534 std::vector
<Pnt3f
> & gverts
,
535 std::vector
<SimplePolygon
> &tris
,
536 std::vector
<Vec3f
> & norms
,
537 std::vector
<Pnt2f
> & texturecoords
)
539 BSplineTensorSurface cl_surf
;
542 cl_surf
= m_vclBSplineSurfaces
[0].getSurface();
543 // NOTE: also computes 3D vertex info in the gverts array
544 cl_surf
.computeNormal(m_vclParameterVertices
,
547 // FIXME: this is a hack just to try out if it works.
548 // FIXME: will need to modify OSGBSplineTensorSurface.cpp to have
549 // FIXME: a fucnction that combines these two.
550 std::vector
<Pnt3f
> dummyverts
;
551 cl_surf
.computeTex(m_vclParameterVertices
,
554 &m_vvTextureControlPoints
);
559 std::cerr<<"haho"<< m_vclParameterVertices.size() << " " << gverts.size() << " " << norms.size() << std::endl;
560 for ( UInt32 i = 0; i < gverts.size(); ++i )
562 std::cerr << gverts[i] << " " << norms[i] << std::endl;
566 tris
= m_vclTriangles
;
568 //copy the normals into the vvclEdgeLoopsNorm structure
569 unsigned int numloops
= UInt32(m_vtSurfaces
[0].vvclEdgeLoops
.size());
570 unsigned int actlooplength
;
571 unsigned int ui_actloop
;
572 #ifdef OSG_KEEP_2D_POINTS
573 unsigned int ui_actvertidx
= 0;
578 m_vtSurfaces
[0].vvclEdgeLoopsNorm
.resize(numloops
);
579 #ifndef OSG_FORCE_NO_T_VERTICES
580 m_vtSurfaces
[0].vvclEdgeLoops3D
.resize(numloops
);
583 for(ui_actloop
= 0; ui_actloop
< numloops
; ++ui_actloop
)
585 actlooplength
= UInt32(m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
].size());
586 m_vtSurfaces
[0].vvclEdgeLoopsNorm
[ui_actloop
].resize(actlooplength
);
587 #ifdef OSG_KEEP_2D_POINTS
589 for(unsigned int ui_act
= 0; ui_act
< actlooplength
; ++ui_act
)
591 m_vtSurfaces
[0].vvclEdgeLoopsNorm
[ui_actloop
][ui_act
] =
592 Vec3d(norms
[ui_actvertidx
][0],
593 norms
[ui_actvertidx
][1],
594 norms
[ui_actvertidx
][2]);
599 #ifdef OSG_FORCE_NO_T_VERTICES
600 cl_surf
.computeNormalforTrimming(
601 m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
],
602 m_vtSurfaces
[0].vvclEdgeLoopsNorm
[ui_actloop
]);
604 cl_surf
.computeNormalforTrimming(
605 m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
],
606 m_vtSurfaces
[0].vvclEdgeLoopsNorm
[ui_actloop
],
607 &m_vtSurfaces
[0].vvclEdgeLoops3D
[ui_actloop
]);
613 //copy the texturecoords into the vvclEdgeLoopsTex structure
614 numloops
= UInt32(m_vtSurfaces
[0].vvclEdgeLoops
.size());
615 #ifdef OSG_KEEP_2D_POINTS
619 m_vtSurfaces
[0].vvclEdgeLoopsTex
.resize(numloops
);
621 for(ui_actloop
= 0; ui_actloop
< numloops
; ++ui_actloop
)
623 actlooplength
= UInt32(m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
].size());
624 m_vtSurfaces
[0].vvclEdgeLoopsTex
[ui_actloop
].resize(actlooplength
);
625 #ifdef OSG_KEEP_2D_POINTS
627 for(unsigned int ui_act
= 0; ui_act
< actlooplength
; ++ui_act
)
629 m_vtSurfaces
[0].vvclEdgeLoopsTex
[ui_actloop
][ui_act
] =
630 Vec3d(texturecoords
[ui_actvertidx
][0],
631 texturecoords
[ui_actvertidx
][1],
632 texturecoords
[ui_actvertidx
][2]);
637 cl_surf
.computeTexforTrimming(
638 m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
],
639 m_vtSurfaces
[0].vvclEdgeLoopsTex
[ui_actloop
],
640 &m_vvTextureControlPoints
);
651 void CNurbsPatchSurface::calculatePointsAndTextureCoords(
652 std::vector
<Pnt3f
> & gverts
,
653 std::vector
<SimplePolygon
> &tris
,
654 std::vector
<Pnt2f
> & texturecoords
)
656 BSplineTensorSurface cl_surf
;
659 cl_surf
= m_vclBSplineSurfaces
[0].getSurface();
660 cl_surf
.computeTex(m_vclParameterVertices
,
663 &m_vvTextureControlPoints
);
665 std::cerr<<"haho"<< m_vclParameterVertices.size() << " " << gverts.size() << " " << norms.size() << std::endl;
666 for ( UInt32 i = 0; i < gverts.size(); ++i )
668 std::cerr << gverts[i] << " " << norms[i] << std::endl;
672 tris
= m_vclTriangles
;
674 //copy the normals into the vvclEdgeLoopsNorm structure
675 unsigned int numloops
= UInt32(m_vtSurfaces
[0].vvclEdgeLoops
.size());
676 unsigned int actlooplength
;
677 #ifdef OSG_KEEP_2D_POINTS
678 unsigned int ui_actvertidx
= 0;
683 m_vtSurfaces
[0].vvclEdgeLoopsTex
.resize(numloops
);
685 for(unsigned int ui_actloop
= 0; ui_actloop
< numloops
; ++ui_actloop
)
687 actlooplength
= UInt32(m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
].size());
688 m_vtSurfaces
[0].vvclEdgeLoopsTex
[ui_actloop
].resize(actlooplength
);
689 #ifdef OSG_KEEP_2D_POINTS
691 for(unsigned int ui_act
= 0; ui_act
< actlooplength
; ++ui_act
)
693 m_vtSurfaces
[0].vvclEdgeLoopsTex
[ui_actloop
][ui_act
] =
694 Vec3d(texturecoords
[ui_actvertidx
][0],
695 texturecoords
[ui_actvertidx
][1],
696 texturecoords
[ui_actvertidx
][2]);
701 cl_surf
.computeTexforTrimming(
702 m_vtSurfaces
[0].vvclEdgeLoops
[ui_actloop
],
703 m_vtSurfaces
[0].vvclEdgeLoopsTex
[ui_actloop
],
704 &m_vvTextureControlPoints
);
714 // set error for given surface patch
715 void CNurbsPatchSurface::SetError(const unsigned int cuiSurface
, double dError
)
717 if(cuiSurface
>= m_vtSurfaces
.size() )
722 // std::cerr << "Setting error = " << dError << " for surface " << cuiSurface + 1 << "." << std::endl << std::endl;
724 m_vtSurfaces
[cuiSurface
].dError
= dError
;
725 // m_vtSurfaces[ cuiSurface ].ucStatus &= QUAD_TREE_INVALID_MASK;
726 m_vtSurfaces
[cuiSurface
].ucStatus
&= BEZIER_SURFACES_VALID
;
730 // convert surface to piecewise bezier form
731 void CNurbsPatchSurface::ConvertToBezier(unsigned int uiSurface
)
733 BSplineTensorSurface
& rcl_bspline_surface
= m_vclBSplineSurfaces
[uiSurface
].getSurface();
734 trimmingloop
& rvvcl_trimming_loops
= m_vclBSplineSurfaces
[uiSurface
].getTrimmingLoops();
735 bezier2dvector vcl_beziertrimmingcurves
;
736 std::vector
<unsigned int> vui_curves_per_loop(0);
737 unsigned int ui_tloops
= UInt32(rvvcl_trimming_loops
.size());
738 unsigned int ui_curve
;
740 // std::cerr << "Converting surface " << uiSurface + 1 << " to bezier form." << std::endl;
742 vui_curves_per_loop
.resize(ui_tloops
);
743 m_vtSurfaces
[uiSurface
].vvclBezierCurves
.resize(ui_tloops
);
745 // std::cerr << "ConvertToBezier: numofloops: " << ui_tloops << std::endl;
746 for(unsigned int ui_loop
= 0; ui_loop
< ui_tloops
; ++ui_loop
)
748 unsigned int ui_curves
= UInt32(rvvcl_trimming_loops
[ui_loop
].size());
749 unsigned int ui_prev
= ui_curves
- 1;
751 vui_curves_per_loop
[ui_loop
] = 0;
752 vcl_beziertrimmingcurves
.clear();
754 for(ui_curve
= 0; ui_curve
< ui_curves
; ++ui_curve
)
756 // std::cerr << "processing curve " << ui_curve + 1 << std::endl;
757 bezier2dvector vcl_converted_tmp
;
760 DCTPVec3dvector vcl_cp
=
761 rvvcl_trimming_loops
[ui_loop
][ui_prev
].getControlPointVector();
762 Vec3d cl_prev
= vcl_cp
[vcl_cp
.size() - 1];
763 vcl_cp
= rvvcl_trimming_loops
[ui_loop
][ui_curve
].getControlPointVector();
764 if(DCTPVecIsNotEqual(cl_prev
, vcl_cp
[0]) )
766 BezierCurve2D cl_temp
;
767 DCTPVec3dvector
vcl_temp(2);
769 vcl_temp
[0] = cl_prev
;
770 vcl_temp
[1] = vcl_cp
[0];
771 cl_temp
.setControlPointVector(vcl_temp
);
772 cl_temp
.optimizeDegree();
773 // std::cerr << "inserting linear trimming curve to close gap." << std::endl;
774 // std::cerr << vcl_temp[ 0 ] << " -> " << vcl_temp[ 1 ] << std::endl;
775 vcl_beziertrimmingcurves
.insert(vcl_beziertrimmingcurves
.end(), cl_temp
);
776 ++vui_curves_per_loop
[ui_loop
];
780 if(rvvcl_trimming_loops
[ui_loop
][ui_curve
].makeBezier(vcl_converted_tmp
, vd_pars
) )
782 // SWARNING << "Conversion of trimming loop " << ui_loop + 1;
783 // SWARNING << " curve " << ui_curve + 1;
784 // SWARNING << " surface " << uiSurface + 1 << " to bezier form failed!" << endLog;
788 vcl_beziertrimmingcurves
.insert(
789 vcl_beziertrimmingcurves
.end(), vcl_converted_tmp
.begin(), vcl_converted_tmp
.end() );
790 vui_curves_per_loop
[ui_loop
] += UInt32(vcl_converted_tmp
.size());
794 // check for colinear trimming
795 for(ui_curve
= 0; ui_curve
< vcl_beziertrimmingcurves
.size(); ++ui_curve
)
797 unsigned int ui_next
= (ui_curve
+ 1) % vcl_beziertrimmingcurves
.size();
799 // check if both linear
800 if( (vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector().size() == 2) &&
801 (vcl_beziertrimmingcurves
[ui_next
].getControlPointVector().size() == 2) &&
802 (DCTPVecIsEqual(vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[1],
803 vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[0]) ) )
806 Vec2d cl_s0
, cl_e0
, cl_s1
, cl_e1
;
809 cl_s0
[0] = vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[0][0]
810 / vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[0][2];
811 cl_s0
[1] = vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[0][1]
812 / vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[0][2];
814 cl_e0
[0] = vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[1][0]
815 / vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[1][2];
816 cl_e0
[1] = vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[1][1]
817 / vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[1][2];
819 cl_s1
[0] = vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[0][0]
820 / vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[0][2];
821 cl_s1
[1] = vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[0][1]
822 / vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[0][2];
824 cl_e1
[0] = vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[1][0]
825 / vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[1][2];
826 cl_e1
[1] = vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[1][1]
827 / vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[1][2];
829 cl_tmp
= cl_e1
- cl_s0
;
831 cl_tmp
*= 1.0 / sqrt(cl_tmp
.squareLength() );
832 cl_tmp
*= cl_tmp
.dot(cl_e0
- cl_s0
);
833 cl_tmp
-= cl_e0
- cl_s0
;
835 if(cl_tmp
.squareLength() < DCTP_EPS
* DCTP_EPS
)
839 vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[0] =
840 vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[0];
844 vcl_beziertrimmingcurves
[ui_curve
].getControlPointVector()[1] =
845 vcl_beziertrimmingcurves
[ui_next
].getControlPointVector()[1];
847 for( ; ui_next
< vcl_beziertrimmingcurves
.size() - 1; ++ui_next
)
849 vcl_beziertrimmingcurves
[ui_next
] = vcl_beziertrimmingcurves
[ui_next
+ 1];
852 vcl_beziertrimmingcurves
.pop_back();
858 vui_curves_per_loop
[ui_loop
] = UInt32(vcl_beziertrimmingcurves
.size());
860 // std::cerr << "loop " << ui_loop + 1 << " contains " << vui_curves_per_loop[ ui_loop ] << " curves." << std::endl;
861 for(ui_curve
= 0; ui_curve
< vui_curves_per_loop
[ui_loop
]; ++ui_curve
)
863 /* Vec2dvector vcl_cp = vcl_beziertrimmingcurves[ ui_curve ].getControlPointVector( );
865 std::cerr << vcl_cp[ 0 ] << " -> " << vcl_cp[ vcl_cp.size( ) - 1 ] << std::endl;*/
866 m_vtSurfaces
[uiSurface
].vvclBezierCurves
[ui_loop
].push_back(vcl_beziertrimmingcurves
[ui_curve
]);
870 if(rcl_bspline_surface
.makeBezier(m_vvvclBezierSurfaces
[uiSurface
],
871 m_vvdUParams
[uiSurface
],
872 m_vvdVParams
[uiSurface
]) )
874 // SWARNING << "Conversion of surface " << uiSurface + 1 << " to bezier form failed!" << endLog;
878 Gen3DLoops(uiSurface
);
879 m_vvvclBezierSurfaces
[uiSurface
].clear();
882 // std::cerr <<"numofbeziers: " << m_vvvclBezierSurfaces[ uiSurface ].size() << " " <<
883 // m_vvvclBezierSurfaces[ uiSurface ][0].size() << std::endl;
884 m_vtSurfaces
[uiSurface
].ucStatus
|= BEZIER_SURFACES_VALID
;
888 //this is a new one, that has to be called twice because of the direct
891 // set up quad tree with saved error
892 void CNurbsPatchSurface::CalculateQuadTree(unsigned int uiSurface
, bool bForEdges
)
894 if(!(m_vtSurfaces
[uiSurface
].ucStatus
& BEZIER_SURFACES_VALID
) )
896 std::cerr
<< "Bezier surfaces invalid for surface " << uiSurface
+ 1 << std::endl
;
900 // std::cerr << "Building QuadTree for surface " << uiSurface + 1 << "." << std::endl;
902 // m_vclSeperateMeshes[ uiSurface ].reinit( );
905 if(m_vtSurfaces
[uiSurface
].vvcl3DCurves
.size() != 0)
907 // no quadtree required when 3d loops are present
908 m_vtSurfaces
[uiSurface
].ucStatus
|= QUAD_TREE_VALID
;
914 m_pclQuadTree
= new QuadTreeCreator(&m_clMesh
/*, bForEdges*/);
915 // m_pclQuadTree = new QuadTreeCreator( &m_vclSeperateMeshes[ uiSurface ] );
916 m_pclQuadTree
->setErrorTolerance(m_vtSurfaces
[uiSurface
].dError
/ 3.0);
917 if(m_pclQuadTree
->setInitialLeaves(m_vvvclBezierSurfaces
[uiSurface
],
918 m_vvdUParams
[uiSurface
],
919 m_vvdVParams
[uiSurface
]) )
921 std::cerr
<< "QuadTree setup of surface " << uiSurface
+ 1 << " failed." << std::endl
;
922 m_vtSurfaces
[uiSurface
].ucStatus
|= QUAD_TREE_ERROR
;
923 delete m_pclQuadTree
;
926 #ifndef OSG_ADAPTIVE_QUAD_TREE
927 if(m_pclQuadTree
->createQuadTree() )
929 std::cerr
<< "QuadTree creation of surface " << uiSurface
+ 1 << " failed." << std::endl
;
930 m_vtSurfaces
[uiSurface
].ucStatus
|= QUAD_TREE_ERROR
;
931 delete m_pclQuadTree
;
934 delete m_pclQuadTree
;
942 #ifdef OSG_USE_NURBS_PATCH
943 m_vtSurfaces
[uiSurface
].pclErrorTree
->BuildMesh(&m_clMesh
,
944 &(m_vclBSplineSurfaces
[uiSurface
].getSurface() ),
945 #ifdef OSG_ARBITRARY_SPLIT
946 m_vtSurfaces
[uiSurface
].clMinParam
,
947 m_vtSurfaces
[uiSurface
].clMaxParam
,
949 m_vtSurfaces
[uiSurface
].dError
,
950 m_vtSurfaces
[uiSurface
].fMinError
,
951 m_vtSurfaces
[uiSurface
].fMaxError
);
953 m_vtSurfaces
[uiSurface
].pclErrorTree
->BuildMesh(&m_clMesh
,
954 &m_vvvclBezierSurfaces
[uiSurface
],
955 &m_vvdUParams
[uiSurface
],
956 &m_vvdVParams
[uiSurface
],
957 m_vtSurfaces
[uiSurface
].dError
,
958 m_vtSurfaces
[uiSurface
].fMinError
,
959 m_vtSurfaces
[uiSurface
].fMaxError
);
961 // std::cerr << "min error = " << m_vtSurfaces[ uiSurface ].fMinError << std::endl;
962 // std::cerr << "max error = " << m_vtSurfaces[ uiSurface ].fMaxError << std::endl;
965 m_vtSurfaces
[uiSurface
].ucStatus
|= QUAD_TREE_VALID
;
973 // calculate finest trimming curve
974 void CNurbsPatchSurface::CalculateTrimmingLoops(unsigned int uiSurface
)
976 bezier2ddequevector vvcl_curves
= m_vtSurfaces
[uiSurface
].vvclBezierCurves
;
978 if(!(m_vtSurfaces
[uiSurface
].ucStatus
& QUAD_TREE_VALID
) )
980 std::cerr
<< "Quad tree invalid for surface " << uiSurface
+ 1 << std::endl
;
981 m_vtSurfaces
[uiSurface
].clMin
= Vec3d(m_vtSurfaces
[uiSurface
].dError
* 100, m_vtSurfaces
[uiSurface
].dError
* 100, m_vtSurfaces
[uiSurface
].dError
* 100);
982 m_vtSurfaces
[uiSurface
].clMax
= Vec3d(0, 0, 0); // this is invalid and will always fail BB test
988 ParSpaceTrimmer cl_trimmer
;
990 if(m_vtSurfaces
[uiSurface
].vvcl3DCurves
.size() != 0)
992 #ifdef OSG_USE_SIMPLIFIER
993 cl_trimmer
.Initialize(m_clMesh
, vvcl_curves
,
994 m_vtSurfaces
[uiSurface
].vvcl3DCurves
,
995 m_vtSurfaces
[uiSurface
].vvclEdgeLoops
,
996 m_vtSurfaces
[uiSurface
].dError
,
997 &m_vclBSplineSurfaces
[uiSurface
].getSurface() );
999 cl_trimmer
.Initialize(m_clMesh
, vvcl_curves
,
1000 m_vtSurfaces
[uiSurface
].vvcl3DCurves
,
1001 m_vtSurfaces
[uiSurface
].vvclEdgeLoops
,
1002 m_vtSurfaces
[uiSurface
].dError
);
1007 #ifdef OSG_ADAPTIVE_QUAD_TREE
1008 #ifdef OSG_USE_SIMPLIFIER
1009 cl_trimmer
.Initialize(m_clMesh
, vvcl_curves
,
1010 m_vtSurfaces
[uiSurface
].vvclEdgeLoops
, m_pclQuadTree
,
1011 &m_vclBSplineSurfaces
[uiSurface
].getSurface() );
1013 cl_trimmer
.Initialize(m_clMesh
, vvcl_curves
, m_vtSurfaces
[uiSurface
].vvclEdgeLoops
, m_pclQuadTree
);
1016 cl_trimmer
.Initialize(m_clMesh
, vvcl_curves
, m_vtSurfaces
[uiSurface
].vvclEdgeLoops
);
1021 if(cl_trimmer
.PerformTrimming() )
1023 std::cerr
<< "Par space trimmer failed (surface " << uiSurface
+ 1 << ")." << std::endl
;
1024 m_vtSurfaces
[uiSurface
].clMin
= Vec3d(m_vtSurfaces
[uiSurface
].dError
* 100, m_vtSurfaces
[uiSurface
].dError
* 100, m_vtSurfaces
[uiSurface
].dError
* 100);
1025 m_vtSurfaces
[uiSurface
].clMax
= Vec3d(0, 0, 0); // this is invalid and will always fail BB test
1026 #ifndef OSG_ADAPTIVE_QUAD_TREE
1027 if(m_pclQuadTree
!= NULL
)
1029 delete m_pclQuadTree
;
1030 m_pclQuadTree
= NULL
;
1036 catch(ParSpaceTrimmerError cl_err
)
1038 std::cerr
<< "Par space trimmer exception caught: " << cl_err
.errtype
<< " (surface " << uiSurface
+ 1 << ")" << std::endl
;
1039 m_vtSurfaces
[uiSurface
].clMin
= Vec3d(m_vtSurfaces
[uiSurface
].dError
* 100, m_vtSurfaces
[uiSurface
].dError
* 100, m_vtSurfaces
[uiSurface
].dError
* 100);
1040 m_vtSurfaces
[uiSurface
].clMax
= Vec3d(0, 0, 0); // this is invalid and will always fail BB test
1041 #ifndef OSG_ADAPTIVE_QUAD_TREE
1042 if(m_pclQuadTree
!= NULL
)
1044 delete m_pclQuadTree
;
1045 m_pclQuadTree
= NULL
;
1053 const unsigned int cui_size
=
1054 UInt32(m_vtSurfaces
[uiSurface
].vvclEdgeLoops
.size());
1056 m_vtSurfaces
[uiSurface
].vvclEdgeLoops3D
.resize(cui_size
);
1057 m_vtSurfaces
[uiSurface
].vbReversed
.resize(cui_size
);
1058 m_vtSurfaces
[uiSurface
].vbUsed
.resize(cui_size
);
1060 // std::cerr <<"edgeloops.size(): " << cui_size << std::endl;
1061 unsigned int ui_vertex
;
1063 for(unsigned int ui_loop
= 0; ui_loop
< cui_size
; ++ui_loop
)
1065 // std::cerr << "edge loop " << ui_loop + 1 << " of " << cui_size << std::endl;
1066 const unsigned int cui_size2
= UInt32(m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
].size());
1067 std::vector
<Pnt3f
> vcl_temp3d
;
1069 m_vtSurfaces
[uiSurface
].vvclEdgeLoops3D
[ui_loop
].resize(cui_size2
);
1070 vcl_temp3d
.resize(cui_size2
);
1071 m_vclBSplineSurfaces
[uiSurface
].getSurface().compute(
1072 m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
],
1075 for(ui_vertex
= 0; ui_vertex
< cui_size2
; ++ui_vertex
)
1077 // std::cerr << "vertex " << ui_vertex + 1 << " of " << cui_size2 << std::endl;
1078 /* const Vec3d ccl_vec = m_vclBSplineSurfaces[ uiSurface ].getSurface( ).compute(
1079 m_vtSurfaces[ uiSurface ].vvclEdgeLoops[ ui_loop ][ ui_vertex ],
1082 ccl_vec
[0] = vcl_temp3d
[ui_vertex
][0];
1083 ccl_vec
[1] = vcl_temp3d
[ui_vertex
][1];
1084 ccl_vec
[2] = vcl_temp3d
[ui_vertex
][2];
1085 // std::cerr << "pos: " << ccl_vec << std::endl;
1087 m_vtSurfaces
[uiSurface
].vvclEdgeLoops3D
[ui_loop
][ui_vertex
] = ccl_vec
;
1089 if( (ui_loop
== 0) && (ui_vertex
== 0) )
1091 m_vtSurfaces
[uiSurface
].clMin
=
1092 m_vtSurfaces
[uiSurface
].clMax
= ccl_vec
;
1093 #ifdef OSG_ARBITRARY_SPLIT
1094 m_vtSurfaces
[uiSurface
].clMinParam
= m_vtSurfaces
[uiSurface
].clMaxParam
=
1095 m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
][ui_vertex
];
1100 if(ccl_vec
[0] < m_vtSurfaces
[uiSurface
].clMin
[0])
1101 m_vtSurfaces
[uiSurface
].clMin
[0] = ccl_vec
[0];
1102 else if(ccl_vec
[0] > m_vtSurfaces
[uiSurface
].clMax
[0])
1103 m_vtSurfaces
[uiSurface
].clMax
[0] = ccl_vec
[0];
1104 if(ccl_vec
[1] < m_vtSurfaces
[uiSurface
].clMin
[1])
1105 m_vtSurfaces
[uiSurface
].clMin
[1] = ccl_vec
[1];
1106 else if(ccl_vec
[1] > m_vtSurfaces
[uiSurface
].clMax
[1])
1107 m_vtSurfaces
[uiSurface
].clMax
[1] = ccl_vec
[1];
1108 if(ccl_vec
[2] < m_vtSurfaces
[uiSurface
].clMin
[2])
1109 m_vtSurfaces
[uiSurface
].clMin
[2] = ccl_vec
[2];
1110 else if(ccl_vec
[2] > m_vtSurfaces
[uiSurface
].clMax
[2])
1111 m_vtSurfaces
[uiSurface
].clMax
[2] = ccl_vec
[2];
1112 #ifdef OSG_ARBITRARY_SPLIT
1113 if(m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
][ui_vertex
][0] < m_vtSurfaces
[uiSurface
].clMinParam
[0])
1114 m_vtSurfaces
[uiSurface
].clMinParam
[0] = m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
][ui_vertex
][0];
1115 else if(m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
][ui_vertex
][0] > m_vtSurfaces
[uiSurface
].clMaxParam
[0])
1116 m_vtSurfaces
[uiSurface
].clMaxParam
[0] = m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
][ui_vertex
][0];
1117 if(m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
][ui_vertex
][1] < m_vtSurfaces
[uiSurface
].clMinParam
[1])
1118 m_vtSurfaces
[uiSurface
].clMinParam
[1] = m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
][ui_vertex
][1];
1119 else if(m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
][ui_vertex
][1] > m_vtSurfaces
[uiSurface
].clMaxParam
[1])
1120 m_vtSurfaces
[uiSurface
].clMaxParam
[1] = m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
][ui_vertex
][1];
1126 SimplePolygon cl_check
;
1127 // std::cerr <<"baszom1: " << cui_size2 << std::endl;
1128 cl_check
.vertices
.resize(cui_size2
- 1);
1130 for(ui_vertex
= 0; ui_vertex
< cui_size2
- 1; ++ui_vertex
)
1132 cl_check
.vertices
[ui_vertex
] = ui_vertex
;
1135 // std::cerr <<"baszom2" << std::endl;
1136 // std::cerr <<"checked vector: " << std::endl;
1137 // unsigned int kk = m_vtSurfaces[ uiSurface ].vvclEdgeLoops[ ui_loop ].size();
1138 // for (unsigned int iii = 0; iii < kk; ++iii)
1139 // std::cerr << m_vtSurfaces[ uiSurface ].vvclEdgeLoops[ ui_loop
1140 // ][iii] << std::endl;
1144 if(cl_check
.isReversed(m_vtSurfaces
[uiSurface
].vvclEdgeLoops
[ui_loop
]) )
1146 // std::cerr << "loop is reversed" << std::endl;
1147 m_vtSurfaces
[uiSurface
].vbReversed
[ui_loop
] = true;
1148 // std::cerr <<"baszom2.5" << std::endl;
1153 // std::cerr << "loop is normal" << std::endl;
1154 m_vtSurfaces
[uiSurface
].vbReversed
[ui_loop
] = false;
1155 // std::cerr <<"baszom2.6"<<std::endl;
1157 // std::cerr <<"baszom3"<<std::endl;
1158 m_vtSurfaces
[uiSurface
].vbUsed
[ui_loop
] = true;
1162 m_vtSurfaces
[uiSurface
].clMin
-= Vec3d(m_vtSurfaces
[uiSurface
].dError
, m_vtSurfaces
[uiSurface
].dError
, m_vtSurfaces
[uiSurface
].dError
);
1163 m_vtSurfaces
[uiSurface
].clMax
+= Vec3d(m_vtSurfaces
[uiSurface
].dError
, m_vtSurfaces
[uiSurface
].dError
, m_vtSurfaces
[uiSurface
].dError
);
1164 #ifdef OSG_ADAPTIVE_QUAD_TREE
1165 if(m_pclQuadTree
!= NULL
)
1167 delete m_pclQuadTree
;
1168 m_pclQuadTree
= NULL
;
1171 m_vtSurfaces
[uiSurface
].ucStatus
|= TRIMMING_VALID
;
1178 // calculate actual trimming curve
1179 void CNurbsPatchSurface::CalculateActualTrimming(unsigned int uiSurface
)
1181 ParSpaceTrimmer cl_trimmer
;
1183 // std::cerr << "g";
1185 //// cl_trimmer.Initialize2( m_clMesh, m_vtSurfaces[ uiSurface ].vvclEdgeLoops, m_vtSurfaces[ uiSurface ].vvclEdgeLoops3D );
1187 #ifdef OSG_FORCE_NO_T_VERTICES
1188 cl_trimmer
.Initialize2(m_clMesh
,
1189 m_vtSurfaces
[uiSurface
].vvclEdgeLoops
,
1190 m_vtSurfaces
[uiSurface
].vvclEdgeLoops3D
,
1191 // m_vtSurfaces[ uiSurface ].vvclEdgeLoopsNorm,
1192 m_vtSurfaces
[uiSurface
].vbReversed
,
1193 m_vtSurfaces
[uiSurface
].vbUsed
);
1196 cl_trimmer
.Initialize2(m_clMesh
, m_vtSurfaces
[uiSurface
].vvclEdgeLoops
, m_vtSurfaces
[uiSurface
].vvclEdgeLoops3D
, m_vtSurfaces
[uiSurface
].vbReversed
, m_vtSurfaces
[uiSurface
].vbUsed
);
1197 #endif /* OSG_FORCE_NO_T_VERTICES */
1198 // cl_trimmer.Initialize2( m_vclSeperateMeshes[ uiSurface ], m_vtSurfaces[ uiSurface ].vvclEdgeLoops );
1201 if(cl_trimmer
.PerformTrimming2() )
1203 std::cerr
<< "Par space trimmer2 failed (surface " << uiSurface
+ 1 << ")." << std::endl
;
1207 catch(ParSpaceTrimmerError cl_err
)
1209 std::cerr
<< "Par space trimmer2 exception caught: " << cl_err
.errtype
<< " (surface " << uiSurface
+ 1 << ")" << std::endl
;
1213 #ifndef OSG_FORCE_NO_T_VERTICES
1214 // get new trimming loops
1215 cl_trimmer
.getTrimmingLoops(m_vtSurfaces
[uiSurface
].vvclEdgeLoops
);
1224 m_pclGraph
= new DirectedGraph
<Vec2d
, unsigned char>;
1225 #ifdef OSG_KEEP_2D_POINTS
1226 if(cl_trimmer
.buildSurfaceGraph(m_pclGraph
, &m_vclGlobalVertices
, NULL
, &m_vuiIndex
) )
1228 if(cl_trimmer
.buildSurfaceGraph(m_pclGraph
, &m_vclGlobalVertices
) )
1231 std::cerr
<< "Build surface graph failed (surface " << uiSurface
+ 1 << ")." << std::endl
;
1235 catch(ParSpaceTrimmerError cl_err
)
1237 std::cerr
<< "Par space trimmer exception caught: " << cl_err
.errtype
<< " (surface " << uiSurface
+ 1 << ")" << std::endl
;
1238 // m_vtSurfaces[ uiSurface ].ucStatus |= TRIMMING_ERROR;
1242 m_vtSurfaces
[uiSurface
].ucStatus
|= TRIMMING_VALID
;
1246 // perform graph traversal
1247 void CNurbsPatchSurface::CalculateGraph(unsigned int uiSurface
, bool usedelaunay
)
1249 GraphTraverser cl_traverser
;
1251 if(!(m_vtSurfaces
[uiSurface
].ucStatus
& TRIMMING_VALID
) )
1253 std::cerr
<< "Trimming invalid for surface " << uiSurface
+ 1 << std::endl
;
1257 // std::cerr << "t";
1258 // std::cerr << "Traversing graph of surface " << uiSurface + 1 << "." << std::endl;
1260 cl_traverser
.Initialize(*m_pclGraph
, usedelaunay
);
1263 if(cl_traverser
.Traverse() )
1265 std::cerr
<< "Graph traverser failed (surface " << uiSurface
+ 1 << ")." << std::endl
;
1266 // m_vtSurfaces[ uiSurface ].ucStatus |= TRIANGULATION_ERROR;
1270 catch(GraphTraverserError cl_err
)
1272 std::cerr
<< "Graph traverser exception caught: " << cl_err
.errtype
<< " (surface " << uiSurface
+ 1 << ")" << std::endl
;
1273 // m_vtSurfaces[ uiSurface ].ucStatus |= TRIANGULATION_ERROR;
1277 m_vclTriangles
= *(cl_traverser
.getPolys() );
1278 m_vclParameterVertices
= *(cl_traverser
.getVertices() );
1279 m_vtSurfaces
[uiSurface
].ucStatus
|= TRIANGULATION_VALID
;
1281 #ifdef OSG_KEEP_2D_POINTS
1282 // change triangle vertices to indices of trimming loop vertex
1283 const unsigned int cui_size
= m_vclTriangles
.size();
1284 unsigned int ui_idx
;
1286 for(ui_idx
= 0; ui_idx
< cui_size
; ++ui_idx
)
1288 std::vector
<int> & rvi_verts
= m_vclTriangles
[ui_idx
].vertices
;
1289 const unsigned int cui_vert_cnt
= rvi_verts
.size();
1290 unsigned int ui_vert
;
1292 for(ui_vert
= 0; ui_vert
< cui_vert_cnt
; ++ui_vert
)
1294 // change triangle indices
1295 if(rvi_verts
[ui_vert
] < ( int ) m_vuiIndex
.size() )
1296 rvi_verts
[ui_vert
] = ( int ) m_vuiIndex
[rvi_verts
[ui_vert
]];
1300 // copy trimming loops to global vertices
1301 const unsigned int cui_loop_cnt
= m_vtSurfaces
[0].vvclEdgeLoops3D
.size();
1302 unsigned int ui_loop
;
1306 for(ui_loop
= 0; ui_loop
< cui_loop_cnt
; ++ui_loop
)
1308 if(m_vtSurfaces
[0].vbUsed
[ui_loop
])
1310 const unsigned int cui_vert_cnt
= m_vtSurfaces
[0].vvclEdgeLoops
[ui_loop
].size();
1311 unsigned int ui_vert
;
1313 for(ui_vert
= 0; ui_vert
< cui_vert_cnt
; ++ui_vert
)
1315 m_vclParameterVertices
[ui_idx
] = m_vtSurfaces
[0].vvclEdgeLoops
[ui_loop
][ui_vert
];
1321 /* if( m_vclGlobalVertices.size( ) > ui_idx )
1323 m_vclGlobalVertices.resize( ui_idx );
1331 void CNurbsPatchSurface::ComputeNormalCone(const unsigned int cuiSurface
,
1332 std::vector
<Vec3f
>& normals
)
1334 /* unsigned int ui_cnt = 0;
1336 Miniball<3> cl_miniball;
1337 for ( unsigned int ui_normal= 0; ui_normal < normals.size(); ++ui_normal )
1339 double d_len = normals[ ui_normal ].length( );
1340 if( d_len > DCTP_EPS )
1342 normals[ ui_normal ] *= 1.0 / d_len;
1343 // std::cerr << normals[ ui_normal ] << std::endl;
1344 Miniball<3>::Point cl_point;
1345 cl_point[ 0 ]= normals[ ui_normal ].x();
1346 cl_point[ 1 ]= normals[ ui_normal ].y();
1347 cl_point[ 2 ]= normals[ ui_normal ].z();
1348 cl_miniball.check_in( cl_point );
1352 // std::cerr << "-----" << std::endl;
1354 cl_miniball.build();
1357 cl_center[0]= cl_miniball.center()[0];
1358 cl_center[1]= cl_miniball.center()[1];
1359 cl_center[2]= cl_miniball.center()[2];
1361 // compute intersection of sphere bounding the normals with unit sphere
1362 // => formula from http://astronomy.swin.edu.au/~pbourke/geometry/spheresphere/
1363 double d_distance_squared= cl_center.squareLength();
1365 if ( (d_distance_squared < 0.001) || ( ui_cnt < 3 ) )
1367 // arbitrary direction
1368 m_vtSurfaces[ cuiSurface ].tNormalCone.clDirection= Vec3d(1.0, 0.0, 0.0);
1370 // angle > 180 degrees
1371 m_vtSurfaces[ cuiSurface ].tNormalCone.dThreshold = 1.0;
1375 double d_nominator_root= ( d_distance_squared - cl_miniball.squared_radius( ) + 1.0 ) * 0.5;
1376 double d_height= sqrt( 1.0 - ( d_nominator_root * d_nominator_root ) / d_distance_squared );
1377 cl_center *= 1.0 / sqrt( d_distance_squared );//.normalize();
1379 m_vtSurfaces[ cuiSurface ].tNormalCone.clDirection= cl_center;
1380 m_vtSurfaces[ cuiSurface ].tNormalCone.dThreshold = d_height;
1382 // std::cerr << cl_center << std::endl;
1383 // std::cerr << d_height << std::endl;*/
1386 void CNurbsPatchSurface::Gen3DLoops(const unsigned int cuiSurface
)
1388 const unsigned int cui_loop_cnt
= UInt32(m_vtSurfaces
[cuiSurface
].vvclBezierCurves
.size());
1389 unsigned int ui_loop
;
1390 unsigned int ui_curve_cnt
;
1391 unsigned int ui_curve
;
1392 bezier2ddeque vcl_new_curves
;
1393 std::vector
<unsigned int> vui_u_seg
;
1394 std::vector
<unsigned int> vui_v_seg
;
1395 unsigned int ui_dim
;
1396 unsigned int ui_pos
;
1398 std::vector
<Vec4d
> vcl_points
;
1401 m_vtSurfaces
[cuiSurface
].vvcl3DCurves
.resize(cui_loop_cnt
);
1403 for(ui_loop
= 0; ui_loop
< cui_loop_cnt
; ++ui_loop
)
1405 // first cut the curves with the bezier patches
1406 vcl_new_curves
.clear();
1409 ui_curve_cnt
= UInt32(m_vtSurfaces
[cuiSurface
].vvclBezierCurves
[ui_loop
].size());
1411 for(ui_curve
= 0; ui_curve
< ui_curve_cnt
; ++ui_curve
)
1413 CutCurve(cuiSurface
, m_vtSurfaces
[cuiSurface
].vvclBezierCurves
[ui_loop
][ui_curve
],
1414 vcl_new_curves
, vui_u_seg
, vui_v_seg
);
1417 m_vtSurfaces
[cuiSurface
].vvclBezierCurves
[ui_loop
] = vcl_new_curves
;
1419 // then elevate the trimming curves into 3d space
1420 ui_curve_cnt
= UInt32(m_vtSurfaces
[cuiSurface
].vvclBezierCurves
[ui_loop
].size());
1421 m_vtSurfaces
[cuiSurface
].vvcl3DCurves
[ui_loop
].resize(ui_curve_cnt
);
1423 for(ui_curve
= 0; ui_curve
< ui_curve_cnt
; ++ui_curve
)
1425 const unsigned int cui_u_seg
= vui_u_seg
[ui_curve
];
1426 const unsigned int cui_v_seg
= vui_v_seg
[ui_curve
];
1427 BezierTensorSurface
&rcl_surf
= m_vvvclBezierSurfaces
[cuiSurface
][cui_u_seg
][cui_v_seg
];
1428 BezierCurve2D
& rcl_curve2d
= m_vtSurfaces
[cuiSurface
].vvclBezierCurves
[ui_loop
][ui_curve
];
1430 rcl_curve2d
.optimizeDegree();
1433 // Even though there exists a closed formula which
1434 // gives the degree of a rational Bezier curve elevated by
1435 // a rational Bezier patch, here we don't take into account
1436 // the weights of the elevating Bezier patch and therefore
1437 // this degree approximation is necessary for rational
1438 // trimming curves. The closed formula is also quite
1439 // expensive to calculate, our method is a bit cheaper.
1440 // Although it usually overestimates the degree, it doesn't
1441 // really matter in practice since the approximated 3D
1442 // Bezier curve will be degree reduced as much as possible.
1443 // And this method was easier to implement anyway. :-)
1444 unsigned int approxdegree
= rcl_curve2d
.computeNonratApproximationDegree(1e-4);
1445 ui_dim
= ( (UInt32(rcl_surf
.getControlPointMatrix().size()) - 1)
1446 + (UInt32(rcl_surf
.getControlPointMatrix()[0].size()) - 1) )
1448 #ifdef OSG_NURBS_DEBUG
1449 if(approxdegree
!= rcl_curve2d
.getControlPointVector().size() - 1)
1451 std::cerr
<< "approxdegree: " << approxdegree
<< " dim: " << ui_dim
<< std::endl
;
1453 #endif /* OSG_NURBS_DEBUG */
1460 for(ui_pos
= 0; ui_pos
<= ui_dim
; ++ui_pos
)
1463 cl_param
= rcl_curve2d
.computewdeCasteljau( (double(ui_pos
) ) / ui_dim
, i_err
);
1464 // vcl_points.push_back( rcl_surf.computewdeCasteljau( cl_param, i_err ) );
1465 vcl_points
.push_back(m_vclBSplineSurfaces
[cuiSurface
].getSurface().compute4D(cl_param
, i_err
) );
1468 if(m_vtSurfaces
[cuiSurface
].vvcl3DCurves
[ui_loop
][ui_curve
].createCurve(vcl_points
) == 0)
1470 m_vtSurfaces
[cuiSurface
].vvcl3DCurves
[ui_loop
][ui_curve
].optimizeDegree();
1472 #ifdef OSG_NURBS_DEBUG
1473 if(approxdegree
!= rcl_curve2d
.getControlPointVector().size() - 1)
1475 std::cerr
<< "optimdegree: " << m_vtSurfaces
[cuiSurface
].vvcl3DCurves
[ui_loop
][ui_curve
].getControlPointVector().size() - 1 << std::endl
;
1477 #endif /* OSG_NURBS_DEBUG */
1478 // rcl_curve2d.write( );
1479 // m_vtSurfaces[ cuiSurface ].vvcl3DCurves[ ui_loop ][ ui_curve ].write( );
1484 void CNurbsPatchSurface::CutCurve(const unsigned int cuiSurface
,
1485 BezierCurve2D
& rclCurve
,
1486 bezier2ddeque
& rclCut
,
1487 std::vector
<unsigned int>& rvuiUSeg
,
1488 std::vector
<unsigned int>& rvuiVSeg
)
1490 typedef std::multimap
<double, unsigned int> CurveMap
;
1491 typedef CurveMap::iterator CurveMapIt
;
1493 const int ci_u_seg_cnt
= UInt32(m_vvdUParams
[cuiSurface
].size());
1494 const int ci_v_seg_cnt
= UInt32(m_vvdVParams
[cuiSurface
].size());
1497 unsigned int ui_curve
;
1498 unsigned int ui_curve_cnt
= 1;
1499 std::vector
<BezierCurve2D
> vcl_curves
;
1500 std::vector
<double> vd_curvestart
;
1501 std::vector
<double> vd_curveend
;
1502 std::vector
<double> vd_int
;
1503 unsigned int ui_int
;
1504 BezierCurve2D cl_new_curve
;
1505 CurveMap mm_curve_sort
;
1506 CurveMapIt itmm_curve_it
;
1510 vcl_curves
.push_back(rclCurve
);
1511 vd_curvestart
.push_back(0.0);
1512 vd_curveend
.push_back(1.0);
1513 mm_curve_sort
.insert(CurveMap::value_type(0.0, 0u));
1515 for(ui_curve
= 0; ui_curve
< ui_curve_cnt
; ++ui_curve
)
1519 // cut in u-direction
1520 for(i_u_seg
= 0; i_u_seg
< ci_u_seg_cnt
; ++i_u_seg
)
1523 vcl_curves
[ui_curve
].intersection(vd_int
, m_vvdUParams
[cuiSurface
][i_u_seg
], false);
1525 for(ui_int
= 0; ui_int
< vd_int
.size(); ++ui_int
)
1527 if( (vd_int
[ui_int
] > 1e-7) &&
1528 (1.0 - vd_int
[ui_int
] > 1e-7) )
1530 vcl_curves
[ui_curve
].subDivision(vd_int
[ui_int
], cl_new_curve
);
1531 vcl_curves
.push_back(cl_new_curve
);
1532 vd_curvestart
.push_back( (vd_curvestart
[ui_curve
] + vd_curveend
[ui_curve
]) * 0.5);
1533 vd_curveend
.push_back(vd_curveend
[ui_curve
]);
1534 vd_curveend
[ui_curve
] = vd_curvestart
[ui_curve_cnt
];
1535 mm_curve_sort
.insert(CurveMap::value_type(vd_curvestart
[ui_curve_cnt
], ui_curve_cnt
));
1545 // cut in v-direction
1546 for(i_v_seg
= 0; i_v_seg
< ci_v_seg_cnt
; ++i_v_seg
)
1549 vcl_curves
[ui_curve
].intersection(vd_int
, m_vvdVParams
[cuiSurface
][i_v_seg
], true);
1551 for(ui_int
= 0; ui_int
< vd_int
.size(); ++ui_int
)
1553 if( (vd_int
[ui_int
] > 1e-7) &&
1554 (1.0 - vd_int
[ui_int
] > 1e-7) )
1556 vcl_curves
[ui_curve
].subDivision(vd_int
[ui_int
], cl_new_curve
);
1557 vcl_curves
.push_back(cl_new_curve
);
1558 vd_curvestart
.push_back( (vd_curvestart
[ui_curve
] + vd_curveend
[ui_curve
]) * 0.5);
1559 vd_curveend
.push_back(vd_curveend
[ui_curve
]);
1560 vd_curveend
[ui_curve
] = vd_curvestart
[ui_curve_cnt
];
1561 mm_curve_sort
.insert(CurveMap::value_type(vd_curvestart
[ui_curve_cnt
], ui_curve_cnt
) );
1575 // sort and append new curves
1576 const unsigned int cui_offset
= UInt32(rclCut
.size());
1578 rclCut
.resize(ui_curve_cnt
+ cui_offset
);
1581 for(itmm_curve_it
= mm_curve_sort
.begin(); itmm_curve_it
!= mm_curve_sort
.end(); ++itmm_curve_it
)
1583 // std::cerr << itmm_curve_it->second << " ";
1584 rclCut
[ui_curve
+ cui_offset
] = vcl_curves
[itmm_curve_it
->second
];
1588 // std::cerr << std::endl;
1590 // ok, now we know that all curve midpoints are INSIDE a cell (or the whole curve is on the edge)
1591 for(ui_curve
= 0; ui_curve
< ui_curve_cnt
; ++ui_curve
)
1593 const Vec2d ccl_mid
= rclCut
[ui_curve
+ cui_offset
].computewdeCasteljau(0.5, i_err
);
1595 // check if curve lies outside the surface
1596 if(ccl_mid
[0] <= m_vvdUParams
[cuiSurface
][0])
1598 std::vector
<Vec3d
> &rcl_cp
= rclCut
[ui_curve
+ cui_offset
].getControlPointVector();
1600 rcl_cp
[1] = rcl_cp
[rcl_cp
.size() - 1];
1601 rcl_cp
[0][0] = m_vvdUParams
[cuiSurface
][0] * rcl_cp
[0][2];
1602 rcl_cp
[1][0] = m_vvdUParams
[cuiSurface
][0] * rcl_cp
[1][2];
1604 rvuiUSeg
.push_back(0);
1606 else if(ccl_mid
[0] >= m_vvdUParams
[cuiSurface
][ci_u_seg_cnt
- 1])
1608 std::vector
<Vec3d
> &rcl_cp
= rclCut
[ui_curve
+ cui_offset
].getControlPointVector();
1610 rcl_cp
[1] = rcl_cp
[rcl_cp
.size() - 1];
1611 rcl_cp
[0][0] = m_vvdUParams
[cuiSurface
][ci_u_seg_cnt
- 1] * rcl_cp
[0][2];
1612 rcl_cp
[1][0] = m_vvdUParams
[cuiSurface
][ci_u_seg_cnt
- 1] * rcl_cp
[1][2];
1614 rvuiUSeg
.push_back(ci_u_seg_cnt
- 2);
1618 for(i_u_seg
= 1; i_u_seg
< ci_u_seg_cnt
; ++i_u_seg
)
1620 if(ccl_mid
[0] <= m_vvdUParams
[cuiSurface
][i_u_seg
])
1622 rvuiUSeg
.push_back(i_u_seg
- 1);
1628 // check if curve lies outside the surface
1629 if(ccl_mid
[1] <= m_vvdVParams
[cuiSurface
][0])
1631 std::vector
<Vec3d
> &rcl_cp
= rclCut
[ui_curve
+ cui_offset
].getControlPointVector();
1633 rcl_cp
[1] = rcl_cp
[rcl_cp
.size() - 1];
1634 rcl_cp
[0][1] = m_vvdVParams
[cuiSurface
][0] * rcl_cp
[0][2];
1635 rcl_cp
[1][1] = m_vvdVParams
[cuiSurface
][0] * rcl_cp
[1][2];
1637 rvuiVSeg
.push_back(0);
1639 else if(ccl_mid
[1] >= m_vvdVParams
[cuiSurface
][ci_v_seg_cnt
- 1])
1641 std::vector
<Vec3d
> &rcl_cp
= rclCut
[ui_curve
+ cui_offset
].getControlPointVector();
1643 rcl_cp
[1] = rcl_cp
[rcl_cp
.size() - 1];
1644 rcl_cp
[0][1] = m_vvdVParams
[cuiSurface
][ci_v_seg_cnt
- 1] * rcl_cp
[0][2];
1645 rcl_cp
[1][1] = m_vvdVParams
[cuiSurface
][ci_v_seg_cnt
- 1] * rcl_cp
[1][2];
1647 rvuiVSeg
.push_back(ci_v_seg_cnt
- 2);
1651 for(i_v_seg
= 1; i_v_seg
< ci_v_seg_cnt
; ++i_v_seg
)
1653 if(ccl_mid
[1] <= m_vvdVParams
[cuiSurface
][i_v_seg
])
1655 rvuiVSeg
.push_back(i_v_seg
- 1);