00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <memory>
00045 #include <assert.h>
00046
00047 #include "OSGConfig.h"
00048 #include <OSGLog.h>
00049
00050 #include "OSGExtrusionGeometry.h"
00051
00052
00053
00054
00055
00056 OSG_USING_NAMESPACE
00057
00058
00059
00105
00106
00107
00108 template <class VectorTypeT>
00109 void subdivide(const typename std::vector<VectorTypeT> &dataIn,
00110 typename std::vector<VectorTypeT> *dataOut,
00111 bool closed);
00112
00113 template <class VectorTypeT>
00114 void subdivide(const typename std::vector<VectorTypeT> &dataIn,
00115 typename std::vector<VectorTypeT> *dataOut,
00116 UInt32 nTimes,
00117 bool close);
00118
00119
00120
00121
00122
00123
00124
00125 ExtrusionSurface::ExtrusionSurface(const std::vector<Pnt2f> &crossSection,
00126 const std::vector<Quaternion> &orientation,
00127 const std::vector<Vec2f> &scale,
00128 const std::vector<Pnt3f> &spine,
00129 Real32 creaseAngle,
00130 bool beginCap,
00131 bool endCap,
00132 bool ccw,
00133 bool convex,
00134 bool buildNormal,
00135 bool buildTexCoord) :
00136
00137 _creaseAngle(creaseAngle),
00138 _beginCap(beginCap),
00139 _endCap(endCap),
00140 _ccw(ccw),
00141 _convex(convex),
00142 _createNormals(buildNormal),
00143 _createTexCoords(buildTexCoord),
00144 _primitiveCount(0),
00145 _vertexCount(0),
00146 _totalVertexCount(0)
00147 {
00148
00149 if(!crossSection.empty())
00150 {
00151
00152 _crossSection.assign(crossSection.begin(), crossSection.end());
00153 }
00154 else
00155 {
00156
00157 FDEBUG(("OSGExtrusion: Empty cross section. Using default.\n"));
00158 for(UInt32 i = 0; i < DEF_N_CROSS_SECTION_POINTS; i++)
00159 _crossSection.push_back(Pnt2f(DEF_CROSS_SECTION[i]));
00160 }
00161
00162
00163 if(!orientation.empty())
00164 {
00165
00166 _orientation.assign(orientation.begin(), orientation.end());
00167 }
00168 else
00169 {
00170
00171 FDEBUG(("OSGExtrusion: Empty orientation. Using default.\n"));
00172 for(UInt32 i = 0; i < DEF_N_ORIENTATION_PARAMS; i++)
00173 _orientation.push_back(Quaternion(Vec3f(DEF_ORIENTATION[i]),
00174 DEF_ORIENTATION[i][3]));
00175 }
00176
00177
00178 if(!scale.empty())
00179 {
00180
00181 _scale.assign(scale.begin(), scale.end());
00182 }
00183 else
00184 {
00185
00186 FDEBUG(("OSGExtrusion: Empty scale parameter. Using default.\n"));
00187 for(UInt32 i = 0; i < DEF_N_SCALE_PARAMS; i++)
00188 _scale.push_back(Vec2f(DEF_SCALE[i]));
00189 }
00190
00191
00192
00193 if(!spine.empty())
00194 {
00195
00196 _spine.assign(spine.begin(), spine.end());
00197 }
00198 else
00199 {
00200
00201 FDEBUG(("OSGExtrusion: Empty spine. Using default.\n"));
00202 for(UInt32 i = 0; i < DEF_N_SPINE_POINTS; i++)
00203 _spine.push_back(Pnt3f(DEF_SPINE[i]));
00204 }
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214 bool ExtrusionSurface::verifyInput(void)
00215 {
00216 if(_crossSection.size() < 2)
00217 {
00218 FWARNING(("OSGExtrusion:checkInput: Cross section is degenerate\n"));
00219 return false;
00220 }
00221
00222 if(_spine.size() < 2)
00223 {
00224 FWARNING(("OSGExtrusion:checkInput: spine is degenerate\n"));
00225 return false;
00226 }
00227
00228 return true;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238 void ExtrusionSurface::determineTopology(void)
00239 {
00240
00241 Vec3f sDiff = _spine.back() - _spine.front();
00242 Vec2f cDiff = _crossSection.back() - _crossSection.front();
00243
00244
00245 _spineClosed = (sDiff.length() < Eps) ? true : false;
00246 _crossSectionClosed = (cDiff.length() < Eps) ? true : false;
00247
00248 FDEBUG(("OSGExtrusion:checkInput: Topology: (Spine: %s / Cross-section: %s)\n",
00249 (_spineClosed ? "Closed" : "Open"),
00250 (_crossSectionClosed ? "Closed" : "Open")));
00251 }
00252
00253
00254
00255
00256
00257
00258
00259 void ExtrusionSurface::refineCrossSection(UInt32 nTimes)
00260 {
00261 FDEBUG(("OSGExtrusion:refineCrossSection: Refinining %d times\n",nTimes));
00262 std::vector<Vec2f> output;
00263
00264
00265 std::vector<Vec2f> & csVec2f ((std::vector<Vec2f>&)(_crossSection));
00266 subdivide(csVec2f, &output, nTimes, _crossSectionClosed);
00267
00268
00269 output.swap(csVec2f);
00270 }
00271
00272
00273
00274
00275
00276
00277 void ExtrusionSurface::refineSpine(UInt32 nTimes)
00278 {
00279 FDEBUG(("OSGExtrusion:refineSpine: Refinining %d times\n",nTimes));
00280
00281 std::vector<Vec3f> output;
00282
00283
00284 std::vector<Vec3f> & spVec3f ((std::vector<Vec3f>&)(_spine));
00285 subdivide<Vec3f>(spVec3f, &output, nTimes, _spineClosed);
00286
00287
00288 output.swap(spVec3f);
00289 }
00290
00291
00292
00293
00294
00295
00296
00297 void ExtrusionSurface::refineScale(UInt32 nTimes)
00298 {
00299 FDEBUG(("OSGExtrusion:refineScale: Refinining %d times\n",nTimes));
00300
00301 std::vector<Vec2f> output;
00302 subdivide<Vec2f>(_scale, &output, nTimes, _spineClosed);
00303
00304
00305 output.swap(_scale);
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 void ExtrusionSurface::refineOrientation(UInt32 nTimes)
00317 {
00318 FFATAL(("OSGExtrusion:refineOrientation: Not Implemented\n"));
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 void ExtrusionSurface::calcXAxes(void)
00332 {
00333 std::vector<Matrix>::iterator tIt = _transform.begin();
00334
00335
00336
00337 if(!_spineCollinear && !_revolutionSurface)
00338 {
00339 for(; tIt != _transform.end(); ++tIt)
00340 {
00341 Vec3f xAxis = calcXAxis(tIt);
00342 (*tIt)[0].setValue(xAxis);
00343 }
00344 }
00345 else
00346 {
00347 (*tIt)[0].setValue(Vec3f(0.f, 0.f, 0.f));
00348 }
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 void ExtrusionSurface::calcYAxes(void)
00362 {
00363 bool yAxisDefined = false;
00364
00365 std::vector<Pnt3f>::const_iterator spineIt = _spine.begin();
00366 std::vector<Matrix>::iterator tIt = _transform.begin();
00367 for(; spineIt != _spine.end(); ++spineIt, ++tIt)
00368 {
00369 Vec3f yAxis = calcNonUnitYAxis(spineIt);
00370 if(yAxis.length() > Eps)
00371 {
00372 yAxis.normalize();
00373 if(!yAxisDefined)
00374 {
00375 FDEBUG(("OSGExtrusion:calcYAxes: yAxis is defined\n"));
00376 yAxisDefined = true;
00377
00378
00379
00380 std::vector<Matrix>::iterator yIt;
00381 for(yIt = _transform.begin(); yIt != (tIt + 1); ++yIt)
00382 (*yIt)[1].setValue(yAxis);
00383 }
00384 else
00385 {
00386
00387 (*tIt)[1].setValue(yAxis);
00388 }
00389 }
00390 else if(yAxisDefined)
00391 {
00392
00393 (*tIt)[1] = (*(tIt - 1))[1];
00394 }
00395 }
00396
00397
00398 _revolutionSurface = !yAxisDefined;
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 void ExtrusionSurface::calcZAxes(void)
00411 {
00412 bool zAxisDefined = false;
00413
00414 std::vector<Pnt3f>::const_iterator spineIt = _spine.begin();
00415 std::vector<Matrix>::iterator tIt = _transform.begin();
00416 for(; spineIt != _spine.end(); ++spineIt, ++tIt)
00417 {
00418 Vec3f zAxis = calcNonUnitZAxis(spineIt);
00419 if(zAxis.length() > Eps)
00420 {
00421 zAxis.normalize();
00422 if(!zAxisDefined)
00423 {
00424 FDEBUG(("OSGExtrusion:calcZAxes: zAxis is defined\n"));
00425 zAxisDefined = true;
00426
00427
00428 (*tIt)[2].setValue(zAxis);
00429
00430
00431 std::vector<Matrix>::iterator zIt;
00432 for(zIt = _transform.begin(); zIt != tIt; ++zIt)
00433 {
00434 (*zIt)[2].setValue(zAxis);
00435 }
00436 }
00437 else
00438 {
00439 (*tIt)[2].setValue(zAxis);
00440
00441
00442 Vec3f prevZAxis((*(tIt - 1))[2][0],
00443 (*(tIt - 1))[2][1],
00444 (*(tIt - 1))[2][2]);
00445
00446
00447 if(prevZAxis.dot(zAxis) + Eps < 0.f)
00448 {
00449 FDEBUG(("OSGExtrusion:calcZAxes: Flipping z-axis\n"));
00450 zAxis.negate();
00451 }
00452
00453
00454 (*tIt)[2].setValue(zAxis);
00455 }
00456 }
00457 else if(zAxisDefined)
00458 {
00459
00460 (*tIt)[2] = (*(tIt - 1))[2];
00461 }
00462 }
00463
00464
00465
00466 _spineCollinear = !zAxisDefined;
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 void ExtrusionSurface::calcTransforms(void)
00481 {
00482 _transform.clear();
00483
00484
00485 _transform.resize(_spine.size());
00486
00487
00488
00489
00490
00491
00492
00493
00494 calcZAxes();
00495 calcYAxes();
00496
00497
00498
00499
00500 if(_revolutionSurface)
00501 {
00502 _spineCollinear = false;
00503 }
00504 calcXAxes();
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 Matrix rotation;
00518 if(_spineCollinear && !_revolutionSurface)
00519 {
00520
00521
00522 Vec3f v1(0.f, 1.f, 0.f);
00523 Vec3f v2(_transform[0][1]);
00524
00525 Quaternion q;
00526 q.setValue(v1, v2);
00527 q.getValue(rotation);
00528 }
00529
00530 std::vector<Matrix>::iterator tIt = _transform.begin();
00531 std::vector<Pnt3f>::const_iterator spineIt = _spine.begin();
00532 std::vector<Vec2f>::const_iterator scaleIt = _scale.begin();
00533 std::vector<Quaternion>::const_iterator rotIt = _orientation.begin();
00534
00535
00536
00537 for(; spineIt != _spine.end(); ++spineIt, ++tIt)
00538 {
00539
00540 if(_spineCollinear || _revolutionSurface)
00541 {
00542
00543 *tIt = rotation;
00544 }
00545
00546
00547 Matrix cSPlaneTransform;
00548
00549
00550 cSPlaneTransform[0] *= (*scaleIt)[0];
00551 cSPlaneTransform[2] *= (*scaleIt)[1];
00552
00553
00554 Matrix orientationMatrix;
00555 rotIt->getValue(orientationMatrix);
00556 cSPlaneTransform.multLeft(orientationMatrix);
00557
00558 tIt->mult(cSPlaneTransform);
00559
00560
00561 tIt->setTranslate(*spineIt);
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 if(rotIt + 1 != _orientation.end()) { ++rotIt; }
00583 if(scaleIt + 1 != _scale.end()) { ++scaleIt; }
00584 }
00585
00586 FDEBUG(("OSGExtrusion:calcTransforms: spine collinear: %s\n",
00587 (_spineCollinear ? "true" : "false")));
00588
00589 FDEBUG(("OSGExtrusion:calcTransforms: revolution surface: %s\n",
00590 (_revolutionSurface ? "true" : "false")));
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600 void ExtrusionSurface::initGrid(void)
00601 {
00602 FDEBUG(("OSGExtrusion:initGrid: Initializing vertex grid\n"));
00603
00604 _grid.clear();
00605 _grid.resize(_spine.size());
00606
00607 VertexGrid::iterator gridRowIt = _grid.begin();
00608 for(Int32 i = 0; i < _spine.size(); i++, ++gridRowIt)
00609 {
00610 gridRowIt->resize(_crossSection.size());
00611 }
00612 }
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624 void ExtrusionSurface::calcSweepSurfacePositions(void)
00625 {
00626 FDEBUG(("OSGExtrusion:calcSweepSurfacePositions: Calculation vertex positions\n"));
00627
00628 if(_grid.size() < _spine.size())
00629 {
00630 FFATAL(("OSGExtrusion:calcSweepSurfacePositions: Grid not initialized\n"));
00631 return;
00632 }
00633
00634 _posMap.clear();
00635
00636
00637 calcTransforms();
00638
00639 if(_grid.size() < _spine.size())
00640 {
00641 initGrid();
00642 }
00643
00644 std::vector<Matrix>::iterator transIt = _transform.begin();
00645 VertexGrid::iterator gridRowIt = _grid.begin();
00646
00647
00648 for(Int32 i = 0; i < _spine.size(); i++, ++gridRowIt)
00649 {
00650 if(transIt->det3() < Eps)
00651 {
00652 FWARNING(("OSGExtrusion:calcSurfacePositions: Degenerate transformation matrix\n"));
00653 SWARNING << "Degenerate transform[" << i << "]:\n "
00654 << *transIt << std::endl;
00655 }
00656
00657 std::vector<Vertex>::iterator gridColIt = gridRowIt->begin();
00658 std::vector<Pnt2f>::iterator crossIt;
00659
00660
00661 for(crossIt = _crossSection.begin(); crossIt != _crossSection.end();
00662 ++crossIt, ++gridColIt)
00663 {
00664 Pnt3f p = Pnt3f((*crossIt)[0], 0.f, (*crossIt)[1]);
00665
00666
00667 transIt->multMatrixPnt(p, gridColIt->position);
00668 }
00669
00670
00671 if(transIt + 1 != _transform.end()) { ++transIt; }
00672 }
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 void ExtrusionSurface::calcSweepSurfaceTexCoords(void)
00687 {
00688 FDEBUG(("OSGExtrusion:calcSweepSurfaceTexCoords: Calculating texture coordinates\n"));
00689 if(_grid.size() < _spine.size())
00690 {
00691 FFATAL(("OSGExtrusion:calcSweepSurfaceTexCoords: Grid not initialized\n"));
00692 return;
00693 }
00694 _texCoordMap.clear();
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 for(UInt32 i = 0; i < _spine.size(); ++i)
00707 {
00708 for(UInt32 j = 0; j < _crossSection.size(); ++j)
00709 {
00710 Real32 u,v;
00711 UInt32 iPrev = (i == 0) ? 0 : i - 1;
00712 UInt32 jPrev = (j == 0) ? 0 : j - 1;
00713
00714
00715 u = _grid[i][jPrev].texCoord[0];
00716
00717 u += _grid[i][j].position.dist(_grid[i][jPrev].position);
00718
00719
00720 v = _grid[iPrev][j].texCoord[1];
00721
00722 v += _grid[i][j].position.dist(_grid[iPrev][j].position);
00723
00724 _grid[i][j].texCoord[0] = u;
00725 _grid[i][j].texCoord[1] = v;
00726 }
00727 }
00728
00729
00730 for(UInt32 i = 0; i < _spine.size(); ++i)
00731 {
00732 for(UInt32 j = 0; j < _crossSection.size(); ++j)
00733 {
00734
00735 Real32 uMax = _grid[i][_crossSection.size() - 1].texCoord[0];
00736 Real32 vMax = _grid[_spine.size() - 1][j].texCoord[1];
00737
00738 if(uMax > Eps)
00739 _grid[i][j].texCoord[0] /= uMax;
00740
00741 if(vMax > Eps)
00742 _grid[i][j].texCoord[1] /= vMax;
00743 }
00744 }
00745 }
00746
00747
00748 void ExtrusionSurface::calcSweepSurfaceFaceNormals(void)
00749 {
00750 FDEBUG(("OSGExtrusion:calcSweepSurfaceFaceNormals: Calculating sweep surface face normals\n"));
00751
00752 if(_grid.size() < _spine.size())
00753 {
00754 FFATAL(("OSGExtrusion:calcSweepSurfaceFaceNormals: Grid not initialized\n"));
00755 return;
00756 }
00757
00758
00759 for(UInt32 i = 0; i < _spine.size(); ++i)
00760 {
00761 UInt32 iPrev, iNext;
00762
00763
00764 if(_spineClosed)
00765 {
00766
00767 iPrev = (i != 0) ? i - 1 : _spine.size() - 2;
00768 iNext = (i != _spine.size() - 1) ? i + 1 : 1;
00769 }
00770 else
00771 {
00772 iPrev = (i != 0) ? i - 1 : 0;
00773 iNext = (i != _spine.size() - 1) ? i + 1 : i;
00774 }
00775
00776 for(UInt32 j = 0; j < _crossSection.size(); ++j)
00777 {
00778 Vec3f n;
00779 UInt32 jPrev, jNext;
00780
00781
00782 if(_crossSectionClosed)
00783 {
00784
00785 jPrev = (j != 0) ? j - 1 : _crossSection.size() - 2;
00786 jNext = (j != _crossSection.size() - 1) ? j + 1 : 1;
00787 }
00788 else
00789 {
00790 jPrev = (j != 0) ? j - 1 : 0;
00791 jNext = (j != _crossSection.size() - 1) ? j + 1 : j;
00792 }
00793
00794
00795 _grid[i][j].adjFaceNormals[0] =
00796 calcQuadFaceNormal(_grid[i][j].position,
00797 _grid[i][jNext].position,
00798 _grid[iNext][jNext].position,
00799 _grid[iNext][j].position);
00800
00801
00802
00803 _grid[i][j].adjFaceNormals[1] =
00804 calcQuadFaceNormal(_grid[i][j].position,
00805 _grid[iNext][j].position,
00806 _grid[iNext][jPrev].position,
00807 _grid[i][jPrev].position);
00808
00809
00810
00811 _grid[i][j].adjFaceNormals[2] =
00812 calcQuadFaceNormal(_grid[i][j].position,
00813 _grid[i][jPrev].position,
00814 _grid[iPrev][jPrev].position,
00815 _grid[iPrev][j].position);
00816
00817
00818
00819 _grid[i][j].adjFaceNormals[3] =
00820 calcQuadFaceNormal(_grid[i][j].position,
00821 _grid[iPrev][j].position,
00822 _grid[iPrev][jNext].position,
00823 _grid[i][jNext].position);
00824 }
00825 }
00826 }
00827
00828
00829
00830
00831
00832
00833
00834 void ExtrusionSurface::storeSweepSurfaceWithoutNormals(GeoIndicesUI32Ptr indicesPtr,
00835 GeoPLengthsUI32Ptr lensPtr,
00836 GeoPTypesUI8Ptr typesPtr)
00837 {
00838 assert(indicesPtr != NullFC);
00839 assert(lensPtr != NullFC);
00840 assert(typesPtr != NullFC);
00841
00842 for(UInt32 i = 0; i < _spine.size() - 1; i++)
00843 {
00844 for(UInt32 j = 0; j < _crossSection.size(); j++)
00845 {
00846 Vertex v;
00847
00848 v = _grid[i+1][j];
00849
00850
00851 storeVertex(v, indicesPtr);
00852
00853 v = _grid[i][j];
00854
00855 storeVertex(v, indicesPtr);
00856 }
00857
00858 storePrimitive(GL_TRIANGLE_STRIP, lensPtr, typesPtr);
00859 }
00860 }
00861
00862 void ExtrusionSurface::storeSweepSurfaceWithNormals(GeoIndicesUI32Ptr indicesPtr,
00863 GeoPLengthsUI32Ptr lensPtr,
00864 GeoPTypesUI8Ptr typesPtr)
00865 {
00866 assert(indicesPtr != NullFC);
00867 assert(lensPtr != NullFC);
00868 assert(typesPtr != NullFC);
00869
00870
00871 calcSweepSurfaceFaceNormals();
00872
00873 if(_ccw)
00874 {
00875
00876
00877
00878 UInt32 spineEnd = _spine.size() - 1;
00879 UInt32 cSEnd = _crossSection.size() - 1;
00880 for(UInt32 i = 0; i < spineEnd; i++)
00881 {
00882
00883
00884 calcVertexNormal(&_grid[i+1][0], 3);
00885 storeVertex(_grid[i+1][0], indicesPtr);
00886
00887
00888
00889 calcVertexNormal(&_grid[i][0], 0);
00890 storeVertex(_grid[i][0], indicesPtr);
00891
00892 Vec3f fN = _grid[i][0].adjFaceNormals[0];
00893 for(UInt32 j = 0; j < cSEnd; j++)
00894 {
00895
00896
00897 Vec3f fNNext = _grid[i][j+1].adjFaceNormals[0];
00898
00899
00900
00901
00902
00903 if((fN.enclosedAngle(fNNext) + Eps > _creaseAngle - Eps)
00904 || (j + 1 == cSEnd))
00905 {
00906
00907
00908 calcVertexNormal(&_grid[i+1][j+1], 2);
00909 storeVertex(_grid[i+1][j+1], indicesPtr);
00910
00911
00912
00913 calcVertexNormal(&_grid[i][j+1], 1);
00914 storeVertex(_grid[i][j+1], indicesPtr);
00915
00916
00917 storePrimitive(GL_TRIANGLE_STRIP, lensPtr, typesPtr);
00918 }
00919
00920
00921
00922 if(j + 1 < cSEnd)
00923 {
00924
00925
00926
00927 calcVertexNormal(&_grid[i+1][j+1], 3);
00928 storeVertex(_grid[i+1][j+1], indicesPtr);
00929
00930
00931
00932 calcVertexNormal(&_grid[i][j+1], 0);
00933 storeVertex(_grid[i][j+1], indicesPtr);
00934 }
00935
00936
00937 fN = fNNext;
00938 }
00939 }
00940 }
00941 else
00942 {
00943
00944
00945
00946 for(UInt32 i = 0; i < _spine.size() - 1; i++)
00947 {
00948 UInt32 cSEnd = _crossSection.size() - 1;
00949
00950
00951 calcVertexNormal(&_grid[i+1][cSEnd], 2);
00952 storeVertex(_grid[i+1][cSEnd], indicesPtr);
00953
00954 calcVertexNormal(&_grid[i][cSEnd], 1);
00955 storeVertex(_grid[i][cSEnd], indicesPtr);
00956
00957 Vec3f fN = _grid[i][cSEnd].adjFaceNormals[0];
00958 for(UInt32 j = cSEnd; j > 0; j--)
00959 {
00960 Vec3f fNNext = _grid[i][j - 1].adjFaceNormals[0];
00961 if((fN.enclosedAngle(fNNext) + Eps > _creaseAngle - Eps)
00962 || (j == 1))
00963 {
00964 calcVertexNormal(&_grid[i + 1][j - 1], 3);
00965 storeVertex(_grid[i + 1][j - 1], indicesPtr);
00966
00967 calcVertexNormal(&_grid[i][j - 1], 0);
00968 storeVertex(_grid[i][j - 1], indicesPtr);
00969
00970
00971 storePrimitive(GL_TRIANGLE_STRIP, lensPtr, typesPtr);
00972 }
00973
00974 if(j > 1)
00975 {
00976 calcVertexNormal(&_grid[i + 1][j - 1], 2);
00977 storeVertex(_grid[i + 1][j - 1], indicesPtr);
00978
00979 calcVertexNormal(&_grid[i][j - 1], 1);
00980 storeVertex(_grid[i][j - 1], indicesPtr);
00981 }
00982
00983 fN = fNNext;
00984 }
00985 }
00986 }
00987 }
00988
00989
00990
00991
00992
00993
00994
00995
00996 inline bool ExtrusionSurface::isLeft(const Pnt2f &a, const Pnt2f &b)
00997 {
00998 Vec2f d = b - a;
00999 d.normalize();
01000
01001
01002 Vec2f n = Vec2f(d.y(), -d.x());
01003
01004 return n.dot(a) > 0.f;
01005 }
01006
01007
01008
01009
01010
01011
01012
01013 Real32 ExtrusionSurface::computeMinYAbs(const std::vector<Pnt2f> &contour,
01014 Real32 alpha)
01015 {
01016 const Real32 sinAlpha = osgsin(alpha);
01017 const Real32 cosAlpha = osgcos(alpha);
01018
01019 Real32 minYAbs = 1.f;
01020 for(std::vector<Pnt2f>::const_iterator it = contour.begin();
01021 it != contour.end(); ++it)
01022 {
01023 Real32 y = sinAlpha * it->x() + cosAlpha * it->y();
01024 if(osgabs(y) < minYAbs)
01025 minYAbs = y;
01026 }
01027
01028 return minYAbs;
01029 }
01030
01031
01032
01033
01034
01035
01036
01037
01038 Real32 ExtrusionSurface::calcBetterRotationAngle(const std::vector<Pnt2f> &contour,
01039 UInt32 nAngles)
01040 {
01041 Real32 maxMinY = 0.f;
01042 Real32 bestAlpha = 0.f;
01043
01044 Real32 alphaInc = 2 * Pi / nAngles;
01045 for(Real32 alpha = 0.f; alpha < 2 * Pi; alpha += alphaInc)
01046 {
01047 Real32 minYAlpha = computeMinYAbs(contour, alpha);
01048 if(minYAlpha > maxMinY)
01049 {
01050 maxMinY = minYAlpha;
01051 bestAlpha = alpha;
01052 }
01053 }
01054
01055 return bestAlpha;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065 bool ExtrusionSurface::calcOptimizedContour(const std::vector<Pnt2f> &contour,
01066 const Pnt2f &point,
01067 std::vector<Pnt2f> *optimizedContour)
01068 {
01069
01070 std::vector<Pnt2f> coords(contour);
01071
01072
01073
01074 Real32 maxLen = std::numeric_limits<Real32>::min();
01075 Real32 minLen = std::numeric_limits<Real32>::max();
01076
01077 for(std::vector<Pnt2f>::iterator it = coords.begin();
01078 it != coords.end(); ++it)
01079 {
01080
01081 *it -= Vec2f(point);
01082 Real32 len = Vec2f(*it).length();
01083
01084 if(len > maxLen) maxLen = len;
01085 if(len < minLen) minLen = len;
01086 }
01087
01088 if(maxLen < Eps)
01089 {
01090 FWARNING(("OSGExtrusion:calcOptimizedContour: Contour completely degenerate\n"));
01091 return false;
01092 }
01093
01094 if(minLen < Eps)
01095 {
01096 FWARNING(("OSGExtrusion:calcOptimizedContour: Reference point on curve\n"));
01097 return false;
01098 }
01099
01100
01101
01102 Real32 minAbsY = 1.f;
01103 for(std::vector<Pnt2f>::iterator it = coords.begin();
01104 it != coords.end(); ++it)
01105 {
01106 *it /= maxLen;
01107
01108 if(osgabs(it->y()) < minAbsY)
01109 minAbsY = osgabs(it->y());
01110 }
01111
01112 optimizedContour->clear();
01113 optimizedContour->reserve(coords.size());
01114
01115 if(minAbsY > Eps)
01116 {
01117 optimizedContour->assign(coords.begin(), coords.end());
01118 }
01119 else
01120 {
01121
01122 FDEBUG(("OSGExtrusion:calcOptimizedContour: Contour needs rotation\n"));
01123
01124
01125 Real32 alpha = calcBetterRotationAngle(contour, 64);
01126 FDEBUG(("OSGExtrusion:calcOptimizedContour: Rotation angle is: %f\n",
01127 alpha));
01128
01129 Real32 sinAlpha = osgsin(alpha);
01130 Real32 cosAlpha = osgcos(alpha);
01131
01132
01133 for(std::vector<Pnt2f>::iterator it = coords.begin();
01134 it != coords.end(); ++it)
01135 {
01136 Pnt2f p;
01137 p[0] = cosAlpha * it->x() - sinAlpha * it->y();
01138 p[1] = sinAlpha * it->x() + cosAlpha * it->y();
01139
01140 optimizedContour->push_back(p);
01141 }
01142 }
01143
01144
01145 return true;
01146 }
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 Int32 ExtrusionSurface::calcWindingNumber(const std::vector<Pnt2f> &contour,
01157 const Pnt2f &point)
01158 {
01159 Int32 windingNumber = 0;
01160 std::vector<Pnt2f> coords;
01161
01162
01163 calcOptimizedContour(contour, point, &coords);
01164
01165 const Pnt2f *prevPoint = &(coords[coords.size() - 1]);
01166 for(UInt32 i = 0; i < coords.size(); ++i)
01167 {
01168 const Pnt2f *curPoint = &(coords[i]);
01169 if(prevPoint->y() < 0.f)
01170 {
01171
01172 if(curPoint->y() > 0.f)
01173 {
01174 if(isLeft(*prevPoint, *curPoint) == true)
01175 windingNumber++;
01176 }
01177 }
01178 else
01179 {
01180
01181 if(curPoint->y() < 0.f)
01182 {
01183 if(isLeft(*prevPoint, *curPoint) == false)
01184 windingNumber--;
01185 }
01186 }
01187 prevPoint = curPoint;
01188 }
01189
01190 return windingNumber;
01191 }
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206 void ExtrusionSurface::storeConvexCap(UInt32 spineIndex,
01207 bool isBeginCap,
01208 GeoIndicesUI32Ptr indicesPtr,
01209 GeoPLengthsUI32Ptr lensPtr,
01210 GeoPTypesUI8Ptr typesPtr)
01211 {
01212 assert(indicesPtr != NullFC);
01213 assert(lensPtr != NullFC);
01214 assert(typesPtr != NullFC);
01215
01216 if(!_convex)
01217 {