changed: gcc8 base update
[opensg.git] / Source / System / NodeCores / Drawables / Nurbs / Internal / OSGNurbsPatchSurface.cpp
blob92fb8187fb29cc3b660233fff034c5aaf708f8c0
1 /*---------------------------------------------------------------------------*\
2 * OpenSG NURBS Library *
3 * *
4 * *
5 * Copyright (C) 2001-2006 by the University of Bonn, Computer Graphics Group*
6 * *
7 * http://cg.cs.uni-bonn.de/ *
8 * *
9 * contact: edhellon@cs.uni-bonn.de, guthe@cs.uni-bonn.de, rk@cs.uni-bonn.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
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. *
18 * *
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. *
23 * *
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. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
38 #include "OSGLog.h"
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"
48 #include <map>
50 //#include "BoundarySimplifier/BoundaryObject.h"
52 OSG_USING_NAMESPACE
54 //put miniball inside OSG namespace
55 //#include "miniball/miniball.H"
57 #ifdef WIN32
58 #pragma warning (disable : 985)
59 #endif
61 //#define DRAW_LINES
62 #define OSG_VEC_COMPUTE
64 //static unsigned int g_uiColor = 0;
66 #ifdef WRITE_STAT
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;
73 #endif
75 #define OSG_3D_LOOPS
77 CNurbsPatchSurface::CNurbsPatchSurface():
78 m_vclBSplineSurfaces ( ),
79 m_vvvclBezierSurfaces ( ),
80 m_vvdUParams ( ),
81 m_vvdVParams ( ),
82 m_clMesh ( ),
83 m_vtSurfaces ( ),
84 m_vclParameterVertices ( ),
85 m_vclGlobalVertices ( ),
86 // m_vclNormal (),
87 m_pclGraph (NULL ),
88 m_vclTriangles ( ),
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 )
97 #endif
99 #ifdef OSG_KEEP_2D_POINTS
100 , m_vuiIndex ( )
101 #endif
106 CNurbsPatchSurface::~CNurbsPatchSurface()
108 // unsigned int ui_idx;
110 if(m_pclGraph)
112 delete m_pclGraph;
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;
134 // add surface patch
135 void CNurbsPatchSurface::AddSurface(BSplineTrimmedSurface *clSurface)
137 #ifdef WRITE_STAT
138 g_clTotalStart = OSG::getSystemTime();
139 #endif
141 unsigned int ui_number = UInt32(m_vclBSplineSurfaces.size());
143 // std::cerr << "\rreading surface " << ui_number + 1;
145 // resize vectors
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);
168 #ifdef WRITE_STAT
169 g_clActTime = OSG::getSystemTime();
170 g_dTotalTime += g_clActTime - g_clTotalStart;
171 g_dTrimmingConversionTime += g_clActTime - g_clTotalStart;
172 #endif
175 //FIXME: quick hack
176 void CNurbsPatchSurface::setSurface(BSplineTrimmedSurface *clSurface,
177 std::vector<Pnt2f> & texturecps,
178 bool bUseTextures)
180 //FIXME: I'm not sure how much of these reinits is actually needed
181 if(m_pclGraph)
183 delete m_pclGraph;
184 m_pclGraph = NULL;
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();
198 //FIXME END
200 // std::cerr<<"setSurface: m_vtSurfaces.size(): " << m_vtSurfaces.size() <<
201 // std::endl;
202 AddSurface(clSurface);
204 m_bUseTextures = bUseTextures;
205 if(m_bUseTextures)
207 UInt32 k = 0;
208 UInt32 i, j;
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());
213 Vec2d tempv2d;
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;
218 return;
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;
234 k++;
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);
247 m_clMesh.reinit();
248 m_vtSurfaces[0].dError = d_old_err;
251 void CNurbsPatchSurface::setError(double dError)
253 if(m_pclGraph)
255 delete m_pclGraph;
256 m_pclGraph = NULL;
258 m_vtSurfaces[0].vvclEdgeLoops.clear();
259 m_vtSurfaces[0].vvclEdgeLoops3D.clear();
260 m_vtSurfaces[0].vvclEdgeLoopsNorm.clear();
261 m_vtSurfaces[0].vvclEdgeLoopsTex.clear();
262 SetError(0, dError);
265 //less hack...
266 //normal tessellation, no texture
267 void CNurbsPatchSurface::getTessellation(std::vector<Pnt3f> & gverts,
268 std::vector<Vec3f> & norms,
269 std::vector<SimplePolygon> &tris,
270 bool usedelaunay)
272 #ifdef WRITE_STAT
273 g_clTotalStart = OSG::getSystemTime();
274 #endif
276 if( (m_vtSurfaces[0].ucStatus & BEZIER_SURFACES_VALID) &&
277 ( (m_vtSurfaces[0].ucStatus & TRIM_SEGS_VALID) == 0) )
279 #ifdef WRITE_STAT
280 g_clTrimmingApproximationStart = OSG::getSystemTime();
281 #endif
282 CalculateQuadTree(0, true);
283 CalculateTrimmingLoops(0);
284 #ifdef WRITE_STAT
285 g_clActTime = OSG::getSystemTime();
286 g_dTrimmingApproximationTime += g_clActTime - g_clTrimmingApproximationStart;
287 #endif
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 );
294 if(m_pclGraph)
296 delete m_pclGraph;
297 m_pclGraph = NULL;
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();
307 else
309 std::cerr << "shouldn't be here..." << std::endl;
311 // std::cerr << std::endl;
312 #ifdef WRITE_STAT
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;
318 #endif
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,
326 bool usedelaunay)
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);
338 if(m_pclGraph)
340 delete m_pclGraph;
341 m_pclGraph = NULL;
343 // BuildNode( ui_surface );
344 //// calculateNormals( norms );
345 calculatePointsNormalsAndTextureCoords(gverts,
346 tris,
347 norms,
348 texturecoords);
349 ComputeNormalCone(0, norms);
350 m_vclParameterVertices.clear();
351 m_vclGlobalVertices.clear();
352 m_vclTriangles.clear();
354 else
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,
366 bool usedelaunay)
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 );
402 if(m_pclGraph)
404 delete m_pclGraph;
405 m_pclGraph = NULL;
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();
421 else
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,
445 gverts,
446 norms);
447 #else
448 gverts.resize(m_vclParameterVertices.size() );
449 norms.resize(m_vclParameterVertices.size() );
451 for(unsigned int i = 0; i < m_vclParameterVertices.size(); ++i)
453 int i_err = 0;
454 norms[i] = cl_surf.computeNormal(m_vclParameterVertices[i], i_err, gverts[i]);
457 #endif
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;
477 tris.clear();
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;
485 #endif
487 Vec3d cl_norm;
488 // Int32 i_err;
489 m_vtSurfaces[0].vvclEdgeLoopsNorm.resize(numloops);
490 #ifndef OSG_FORCE_NO_T_VERTICES
491 m_vtSurfaces[0].vvclEdgeLoops3D.resize(numloops);
492 #endif
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;*/
511 ui_actvertidx++;
514 #else
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]);
519 #else
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]);
524 #endif
525 #endif
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,
545 gverts,
546 norms);
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,
552 dummyverts,
553 texturecoords,
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;
565 tris.clear();
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;
574 #endif
576 Vec3d cl_norm;
577 // Int32 i_err;
578 m_vtSurfaces[0].vvclEdgeLoopsNorm.resize(numloops);
579 #ifndef OSG_FORCE_NO_T_VERTICES
580 m_vtSurfaces[0].vvclEdgeLoops3D.resize(numloops);
581 #endif
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]);
595 ui_actvertidx++;
598 #else
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]);
603 #else
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]);
608 #endif
609 #endif
613 //copy the texturecoords into the vvclEdgeLoopsTex structure
614 numloops = UInt32(m_vtSurfaces[0].vvclEdgeLoops.size());
615 #ifdef OSG_KEEP_2D_POINTS
616 ui_actvertidx = 0;
617 #endif
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]);
633 ui_actvertidx++;
636 #else
637 cl_surf.computeTexforTrimming(
638 m_vtSurfaces[0].vvclEdgeLoops[ui_actloop],
639 m_vtSurfaces[0].vvclEdgeLoopsTex[ui_actloop],
640 &m_vvTextureControlPoints);
641 #endif
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,
661 gverts,
662 texturecoords,
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;
671 tris.clear();
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;
679 #endif
681 Vec3d cl_norm;
682 // Int32 i_err;
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]);
697 ui_actvertidx++;
700 #else
701 cl_surf.computeTexforTrimming(
702 m_vtSurfaces[0].vvclEdgeLoops[ui_actloop],
703 m_vtSurfaces[0].vvclEdgeLoopsTex[ui_actloop],
704 &m_vvTextureControlPoints);
705 #endif
714 // set error for given surface patch
715 void CNurbsPatchSurface::SetError(const unsigned int cuiSurface, double dError)
717 if(cuiSurface >= m_vtSurfaces.size() )
719 return;
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;
758 DCTPdvector vd_pars;
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];
778 ui_prev = ui_curve;
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;
786 else
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]) ) )
805 // check if colinear
806 Vec2d cl_s0, cl_e0, cl_s1, cl_e1;
807 Vec2d cl_tmp;
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)
837 if(ui_next == 0)
839 vcl_beziertrimmingcurves[ui_next].getControlPointVector()[0] =
840 vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[0];
842 else
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();
853 --ui_curve;
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;
877 #ifdef OSG_3D_LOOPS
878 Gen3DLoops(uiSurface);
879 m_vvvclBezierSurfaces[uiSurface].clear();
880 #endif
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
889 //NURBS usage
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;
897 return;
900 // std::cerr << "Building QuadTree for surface " << uiSurface + 1 << "." << std::endl;
902 // m_vclSeperateMeshes[ uiSurface ].reinit( );
903 if(bForEdges)
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;
909 return;
911 // std::cerr << "q";
912 m_clMesh.reinit();
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;
924 return;
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;
932 return;
934 delete m_pclQuadTree;
935 #endif
937 else //2nd round...
939 // std::cerr << "b";
940 m_clMesh.reinit();
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,
948 #endif
949 m_vtSurfaces[uiSurface].dError,
950 m_vtSurfaces[uiSurface].fMinError,
951 m_vtSurfaces[uiSurface].fMaxError);
952 #else
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);
960 #endif
961 // std::cerr << "min error = " << m_vtSurfaces[ uiSurface ].fMinError << std::endl;
962 // std::cerr << "max error = " << m_vtSurfaces[ uiSurface ].fMaxError << std::endl;
963 //#endif
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
983 return;
986 // std::cerr << "t";
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() );
998 #else
999 cl_trimmer.Initialize(m_clMesh, vvcl_curves,
1000 m_vtSurfaces[uiSurface].vvcl3DCurves,
1001 m_vtSurfaces[uiSurface].vvclEdgeLoops,
1002 m_vtSurfaces[uiSurface].dError);
1003 #endif
1005 else
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() );
1012 #else
1013 cl_trimmer.Initialize(m_clMesh, vvcl_curves, m_vtSurfaces[uiSurface].vvclEdgeLoops, m_pclQuadTree);
1014 #endif
1015 #else
1016 cl_trimmer.Initialize(m_clMesh, vvcl_curves, m_vtSurfaces[uiSurface].vvclEdgeLoops);
1017 #endif
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;
1032 #endif
1033 return;
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;
1047 #endif
1048 return;
1052 // int i_err;
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],
1073 vcl_temp3d);
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 ],
1080 i_err );*/
1081 Vec3d ccl_vec;
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];
1096 #endif
1098 else
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];
1121 #endif
1125 //check direction
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;
1151 else
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;
1170 #endif
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);
1195 #else
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;
1204 return;
1207 catch(ParSpaceTrimmerError cl_err)
1209 std::cerr << "Par space trimmer2 exception caught: " << cl_err.errtype << " (surface " << uiSurface + 1 << ")" << std::endl;
1210 return;
1213 #ifndef OSG_FORCE_NO_T_VERTICES
1214 // get new trimming loops
1215 cl_trimmer.getTrimmingLoops(m_vtSurfaces[uiSurface].vvclEdgeLoops);
1216 #endif
1220 if(m_pclGraph)
1222 delete m_pclGraph;
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) )
1227 #else
1228 if(cl_trimmer.buildSurfaceGraph(m_pclGraph, &m_vclGlobalVertices) )
1229 #endif
1231 std::cerr << "Build surface graph failed (surface " << uiSurface + 1 << ")." << std::endl;
1232 return;
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;
1239 return;
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;
1254 return;
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;
1267 // return;
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;
1274 // return;
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;
1304 ui_idx = 0;
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];
1316 ++ui_idx;
1321 /* if( m_vclGlobalVertices.size( ) > ui_idx )
1323 m_vclGlobalVertices.resize( ui_idx );
1325 #endif
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 );
1349 ++ui_cnt;
1352 // std::cerr << "-----" << std::endl;
1354 cl_miniball.build();
1356 Vec3d cl_center;
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;
1372 return;
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;
1397 Vec2d cl_param;
1398 std::vector<Vec4d> vcl_points;
1399 int i_err;
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();
1407 vui_u_seg.clear();
1408 vui_v_seg.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();
1432 // REMARK:
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) )
1447 * approxdegree;
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 */
1455 if(ui_dim > 40)
1456 ui_dim = 40;
1458 vcl_points.clear();
1460 for(ui_pos = 0; ui_pos <= ui_dim; ++ui_pos)
1462 i_err = 0;
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());
1495 int i_u_seg;
1496 int i_v_seg;
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;
1507 int i_err;
1508 bool b_cut;
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)
1517 b_cut = false;
1519 // cut in u-direction
1520 for(i_u_seg = 0; i_u_seg < ci_u_seg_cnt; ++i_u_seg)
1522 vd_int.clear();
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));
1536 ++ui_curve_cnt;
1537 b_cut = true;
1538 break;
1543 if(!b_cut)
1545 // cut in v-direction
1546 for(i_v_seg = 0; i_v_seg < ci_v_seg_cnt; ++i_v_seg)
1548 vd_int.clear();
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) );
1562 ++ui_curve_cnt;
1563 b_cut = true;
1564 break;
1569 if(b_cut)
1571 --ui_curve;
1575 // sort and append new curves
1576 const unsigned int cui_offset = UInt32(rclCut.size());
1578 rclCut.resize(ui_curve_cnt + cui_offset);
1579 ui_curve = 0;
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];
1585 ++ui_curve;
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];
1603 rcl_cp.resize(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];
1613 rcl_cp.resize(2);
1614 rvuiUSeg.push_back(ci_u_seg_cnt - 2);
1616 else
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);
1623 break;
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];
1636 rcl_cp.resize(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];
1646 rcl_cp.resize(2);
1647 rvuiVSeg.push_back(ci_v_seg_cnt - 2);
1649 else
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);
1656 break;