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 {
01218 FFATAL(("OSGExtrusion:storeCap: Non-convex caps not yet implemented\n"));
01219 return;
01220 }
01221
01222 std::vector<Pnt3f> capBorderCurveInSection;
01223 std::vector<Pnt2f> capBorderCurveInXZPlane(_crossSection);
01224 capBorderCurveInSection.reserve(_grid[spineIndex].size());
01225
01226 std::vector<Vertex>::const_iterator gIt = _grid[spineIndex].begin();
01227 while(gIt != _grid[spineIndex].end())
01228 {
01229 capBorderCurveInSection.push_back(gIt->position);
01230 ++gIt;
01231 }
01232
01233 if(!_crossSectionClosed)
01234 {
01235 capBorderCurveInSection.push_back(_grid[spineIndex].front().position);
01236 capBorderCurveInXZPlane.push_back(_crossSection.front());
01237 }
01238
01239 FDEBUG(("OSGExtrusion:storeCap: Generating cap[%d], type=%s, _ccw=%s\n",
01240 spineIndex,
01241 (isBeginCap ? "begin cap" : "end cap"),
01242 (_ccw ? "TRUE" : "FALSE")));
01243
01244 Pnt3f baryCenterInSection;
01245 Pnt2f baryCenterInXZPlane;
01246
01247 std::vector<Pnt3f>::iterator sIt = capBorderCurveInSection.begin();
01248 std::vector<Pnt2f>::iterator cIt = capBorderCurveInXZPlane.begin();
01249
01250
01251 UInt32 nBorderPoints = capBorderCurveInSection.size() - 1;
01252
01253
01254 for(UInt32 i = 0; i < nBorderPoints; ++i, ++sIt, ++cIt)
01255 {
01256 baryCenterInSection += Vec3f(*sIt);
01257 baryCenterInXZPlane += Vec2f(*cIt);
01258 }
01259 baryCenterInSection /= nBorderPoints;
01260 baryCenterInXZPlane /= nBorderPoints;
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 Int32 windNum = calcWindingNumber(capBorderCurveInXZPlane,
01275 baryCenterInXZPlane);
01276
01277 FDEBUG(("OSGExtrusion:storeCap: Cross-section has winding number: %d\n",
01278 windNum));
01279
01280 bool isCCWOrderedCap = true;
01281 if(windNum != 0)
01282 {
01283 isCCWOrderedCap = (windNum > 0) ? true : false;
01284 }
01285 else
01286 {
01287 FWARNING(("OSGExtrusion:storeCap: Winding number = 0. Culling might be incorrect\n"));
01288
01289 }
01290
01291 Vertex v;
01292 v.position = baryCenterInSection;
01293
01294
01295 bool negateNormal = false;
01296 if(_createNormals)
01297 {
01298
01299 Vec3f capNormal = Vec3f(_transform[spineIndex][1]);
01300
01301 if(isBeginCap)
01302 {
01303 if(!isCCWOrderedCap)
01304 {
01305 negateNormal = true;
01306 }
01307 }
01308 else
01309 {
01310 if(isCCWOrderedCap)
01311 {
01312 negateNormal = true;
01313 }
01314 }
01315
01316 if(!_ccw)
01317 negateNormal = !negateNormal;
01318
01319 v.normal = negateNormal ? -capNormal : capNormal;
01320
01321 FDEBUG(("OSGExtrusion:storeCap: Cap normal: (%f, %f, %f)\n",
01322 v.normal[0], v.normal[1], v.normal[2]));
01323 }
01324
01325
01326
01327 Real32 xMin,xMax,zMin,zMax;
01328 xMin = xMax = capBorderCurveInXZPlane[0][0];
01329 zMin = zMax = capBorderCurveInXZPlane[0][1];
01330 for(cIt = capBorderCurveInXZPlane.begin();
01331 cIt != capBorderCurveInXZPlane.end(); ++cIt)
01332 {
01333 if(xMin > (*cIt)[0]) xMin = (*cIt)[0];
01334 if(xMax < (*cIt)[0]) xMax = (*cIt)[0];
01335 if(zMin > (*cIt)[1]) zMin = (*cIt)[1];
01336 if(zMax < (*cIt)[1]) zMax = (*cIt)[1];
01337 }
01338 Real32 xWidth = xMax - xMin;
01339 Real32 zWidth = zMax - zMin;
01340 Real32 maxWidth = (xWidth > zWidth) ? xWidth : zWidth;
01341 Real32 scale = (maxWidth > Eps) ? 1.f / maxWidth : 1.f;
01342
01343 v.texCoord[0] = (baryCenterInXZPlane[0] - xMin) * scale;
01344 v.texCoord[1] = (baryCenterInXZPlane[1] - zMin) * scale;
01345
01346
01347 storeVertex(v, indicesPtr);
01348
01349 bool reverseInsert = false;
01350
01351 if(isCCWOrderedCap)
01352 {
01353 if(!negateNormal)
01354 reverseInsert = true;
01355 }
01356 else
01357 {
01358 if(negateNormal)
01359 reverseInsert = true;
01360 }
01361
01362 if(reverseInsert)
01363 {
01364 FDEBUG(("OSGExtrusion:storeCap: storing cap border vertices reversed\n"));
01365 std::vector<Pnt3f>::reverse_iterator sRevIt
01366 = capBorderCurveInSection.rbegin();
01367 std::vector<Pnt2f>::reverse_iterator cRevIt
01368 = capBorderCurveInXZPlane.rbegin();
01369
01370
01371 for(; sRevIt != capBorderCurveInSection.rend(); ++cRevIt, ++sRevIt)
01372 {
01373 v.position = *sRevIt;
01374 v.texCoord[0] = ((*cRevIt)[0] - xMin) * scale;
01375 v.texCoord[1] = ((*cRevIt)[1] - zMin) * scale;
01376
01377 storeVertex(v, indicesPtr);
01378 }
01379 }
01380 else
01381 {
01382 FDEBUG(("OSGExtrusion:storeCap: storing cap border vertices\n"));
01383 sIt = capBorderCurveInSection.begin();
01384 cIt = capBorderCurveInXZPlane.begin();
01385
01386 for(; sIt != capBorderCurveInSection.end(); ++cIt, ++sIt)
01387 {
01388 v.position = *sIt;
01389 v.texCoord[0] = ((*cIt)[0] - xMin) * scale;
01390 v.texCoord[1] = ((*cIt)[1] - zMin) * scale;
01391
01392 storeVertex(v, indicesPtr);
01393 }
01394 }
01395
01396 storePrimitive(GL_TRIANGLE_FAN, lensPtr, typesPtr);
01397 }
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410 void ExtrusionSurface::storeMaps(GeoPositions3fPtr posPtr,
01411 GeoNormals3fPtr normalsPtr,
01412 GeoTexCoords2fPtr texPtr)
01413 {
01414 assert(posPtr != NullFC);
01415
01416 FDEBUG(("OSGExtrusion:storeMaps: position map size: %d\n", _posMap.size()));
01417 FDEBUG(("OSGExtrusion:storeMaps: normal map size: %d\n", _normalMap.size()));
01418 FDEBUG(("OSGExtrusion:storeMaps: tex coord map size: %d\n", _texCoordMap.size()));
01419
01420
01421 beginEditCP(posPtr, GeoPositions3f::GeoPropDataFieldMask);
01422
01423 posPtr->resize(_posMap.size());
01424 for(PositionMap::iterator pMIt = _posMap.begin();
01425 pMIt != _posMap.end(); ++pMIt)
01426 {
01427 posPtr->setValue(pMIt->first, pMIt->second);
01428 }
01429
01430 endEditCP(posPtr, GeoPositions3f::GeoPropDataFieldMask);
01431
01432
01433 if(_createNormals)
01434 {
01435 assert(normalsPtr != NullFC);
01436 beginEditCP(normalsPtr, GeoNormals3f::GeoPropDataFieldMask);
01437
01438 normalsPtr->resize(_normalMap.size());
01439 for(NormalMap::iterator nMIt = _normalMap.begin();
01440 nMIt != _normalMap.end(); ++nMIt)
01441 {
01442 normalsPtr->setValue(nMIt->first, nMIt->second);
01443 }
01444
01445 endEditCP(normalsPtr, GeoNormals3f::GeoPropDataFieldMask);
01446 }
01447
01448
01449 if(_createTexCoords)
01450 {
01451 assert(texPtr != NullFC);
01452 beginEditCP(texPtr, GeoTexCoords2f::GeoPropDataFieldMask);
01453
01454 texPtr->resize(_texCoordMap.size());
01455 for(TexCoordMap::iterator tMIt = _texCoordMap.begin();
01456 tMIt != _texCoordMap.end(); ++tMIt)
01457 {
01458 texPtr->setValue(tMIt->first, tMIt->second);
01459 }
01460
01461 endEditCP(texPtr, GeoTexCoords2f::GeoPropDataFieldMask);
01462 }
01463 }
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 GeometryPtr ExtrusionSurface::createGeometry(UInt32 nSubdivs)
01478 {
01479
01480
01481 if(!verifyInput())
01482 {
01483 FWARNING(("OSGExtrusion:createGeometry: Invalid input. Returning NullFC\n"));
01484 return NullFC;
01485 }
01486
01487
01488 determineTopology();
01489
01490
01491 if(nSubdivs > 0)
01492 {
01493 refineCrossSection(nSubdivs);
01494
01495 if(_orientation.size() == 1)
01496 {
01497 refineSpine(nSubdivs);
01498 refineScale(nSubdivs);
01499 }
01500 else
01501 {
01502
01503
01504 FINFO(("OSGExtrusion:createGeometry: Too many orientations. Not refining along spine\n"));
01505 }
01506 }
01507
01508
01509 initGrid();
01510 calcSweepSurfacePositions();
01511
01512 if(_createTexCoords)
01513 {
01514 calcSweepSurfaceTexCoords();
01515 }
01516
01517
01518 GeoPositions3fPtr posPtr = GeoPositions3f::create();
01519 GeoPLengthsUI32Ptr lensPtr = GeoPLengthsUI32::create();
01520 GeoIndicesUI32Ptr indicesPtr = GeoIndicesUI32::create();
01521 GeoPTypesUI8Ptr typesPtr = GeoPTypesUI8::create();
01522 GeoNormals3fPtr normalsPtr = NullFC;
01523 GeoTexCoords2fPtr texPtr = NullFC;
01524
01525 if(_createNormals)
01526 normalsPtr = GeoNormals3f::create();
01527
01528 if(_createTexCoords)
01529 texPtr = GeoTexCoords2f::create();
01530
01531 beginEditCP(indicesPtr, GeoIndicesUI32::GeoPropDataFieldMask);
01532 beginEditCP(lensPtr, GeoPLengthsUI32::GeoPropDataFieldMask);
01533 beginEditCP(typesPtr, GeoPTypesUI8::GeoPropDataFieldMask);
01534
01535 if(_createNormals)
01536 {
01537
01538 storeSweepSurfaceWithNormals(indicesPtr, lensPtr, typesPtr);
01539 }
01540 else
01541 {
01542
01543 storeSweepSurfaceWithoutNormals(indicesPtr, lensPtr, typesPtr);
01544 }
01545
01546 if(_convex)
01547 {
01548
01549 if(_beginCap)
01550 {
01551 FDEBUG(("OSGExtrusion:createGeometry: Creating begin cap\n"));
01552 storeConvexCap(0,
01553 true,
01554 indicesPtr,
01555 lensPtr,
01556 typesPtr);
01557 }
01558
01559 if(_endCap)
01560 {
01561 FDEBUG(("OSGExtrusion:createGeometry: Creating end cap\n"));
01562 storeConvexCap(_spine.size() - 1,
01563 false,
01564 indicesPtr,
01565 lensPtr,
01566 typesPtr);
01567 }
01568 }
01569 else
01570 {
01571 FFATAL(("OSGExtrusion:createGeometry: Support for non-convex caps not implemented\n"));
01572 }
01573
01574 #ifdef DEBUG_VERTEX_NORMALS
01575
01576 storeVertexNormalGeo(indicesPtr, lensPtr, typesPtr);
01577 #endif
01578
01579 #ifdef DEBUG_FACE_NORMALS
01580
01581 storeFaceNormalGeo(indicesPtr, lensPtr, typesPtr);
01582 #endif
01583
01584 endEditCP(indicesPtr, GeoIndicesUI32::GeoPropDataFieldMask);
01585 endEditCP(lensPtr, GeoPLengthsUI32::GeoPropDataFieldMask);
01586 endEditCP(typesPtr, GeoPTypesUI8::GeoPropDataFieldMask);
01587
01588
01589 storeMaps(posPtr, normalsPtr, texPtr);
01590
01591
01592 GeometryPtr geoPtr = Geometry::create();
01593
01594 beginEditCP(geoPtr, Geometry::TypesFieldMask |
01595 Geometry::LengthsFieldMask |
01596 Geometry::IndicesFieldMask |
01597 Geometry::IndexMappingFieldMask |
01598 Geometry::PositionsFieldMask |
01599 Geometry::NormalsFieldMask |
01600 Geometry::TexCoordsFieldMask );
01601
01602
01603
01604
01605
01606
01607
01608
01609 geoPtr->getIndexMapping().push_back(Geometry::MapPosition);
01610 if(_createNormals)
01611 geoPtr->getIndexMapping().push_back(Geometry::MapNormal);
01612 if(_createTexCoords)
01613 geoPtr->getIndexMapping().push_back(Geometry::MapTexCoords);
01614
01615
01616 geoPtr->setLengths(lensPtr);
01617 geoPtr->setIndices(indicesPtr);
01618 geoPtr->setTypes(typesPtr);
01619
01620
01621 geoPtr->setPositions(posPtr);
01622 geoPtr->setNormals(normalsPtr);
01623 geoPtr->setTexCoords(texPtr);
01624
01625 endEditCP(geoPtr, Geometry::TypesFieldMask |
01626 Geometry::LengthsFieldMask |
01627 Geometry::IndicesFieldMask |
01628 Geometry::IndexMappingFieldMask |
01629 Geometry::PositionsFieldMask |
01630 Geometry::NormalsFieldMask |
01631 Geometry::TexCoordsFieldMask );
01632
01633
01634 SINFO << "OSGExtrusion:createGeometry: Stats: ("
01635 << _primitiveCount << '/'
01636 << _totalVertexCount << '/'
01637 << _posMap.size() << '/'
01638 << _normalMap.size() << '/'
01639 << _texCoordMap.size() << ')'
01640 << "(Prims/Verts/Pos/Norms/TexCoords)"
01641 << std::endl;
01642
01643 return geoPtr;
01644 }
01645
01646
01647 NodePtr OSG::makeExtrusion(const std::vector<Pnt2f> &crossSection,
01648 const std::vector<Quaternion> &orientation,
01649 const std::vector<Vec2f> &scale,
01650 const std::vector<Pnt3f> &spine,
01651 Real32 creaseAngle,
01652 bool beginCap,
01653 bool endCap,
01654 bool ccw,
01655 bool convex,
01656 bool buildNormal,
01657 bool buildTexCoord,
01658 UInt32 numOfSubdivision)
01659 {
01660 GeometryPtr pGeo = makeExtrusionGeo(crossSection,
01661 orientation,
01662 scale,
01663 spine,
01664 creaseAngle,
01665 beginCap,
01666 endCap,
01667 ccw,
01668 convex,
01669 buildNormal,
01670 buildTexCoord,
01671 numOfSubdivision);
01672 if(pGeo == NullFC)
01673 {
01674 return NullFC;
01675 }
01676
01677 NodePtr node = Node::create();
01678 beginEditCP(node);
01679 node->setCore(pGeo);
01680 endEditCP(node);
01681 return node;
01682 }
01683
01684
01685 GeometryPtr OSG::makeExtrusionGeo(const std::vector<Pnt2f> &crossSection,
01686 const std::vector<Quaternion> &orientation,
01687 const std::vector<Vec2f> &scale,
01688 const std::vector<Pnt3f> &spine,
01689 Real32 creaseAngle,
01690 bool beginCap,
01691 bool endCap,
01692 bool ccw,
01693 bool convex,
01694 bool buildNormal,
01695 bool buildTexCoord,
01696 UInt32 numSubdivs)
01697 {
01698
01699 const char* prefix = "OSGExtrusion:makeExtrusionGeo";
01700 FDEBUG(("%s: crossSection.size() == %d\n", prefix, crossSection.size()));
01701 FDEBUG(("%s: orientation.size() == %d\n", prefix, orientation.size()));
01702 FDEBUG(("%s: scale.size() == %d\n", prefix, scale.size()));
01703 FDEBUG(("%s: spine.size() == %d\n", prefix, spine.size()));
01704 FDEBUG(("%s: creaseAngle == %f\n", prefix, creaseAngle));
01705 FDEBUG(("%s: beginCap == %s\n",
01706 prefix, (beginCap ? "TRUE" : "FALSE")));
01707 FDEBUG(("%s: endCap == %s\n",
01708 prefix, (endCap ? "TRUE" : "FALSE")));
01709 FDEBUG(("%s: ccw == %s\n",
01710 prefix, (ccw ? "TRUE" : "FALSE")));
01711 FDEBUG(("%s: convex == %s\n",
01712 prefix, (convex ? "TRUE" : "FALSE")));
01713 FDEBUG(("%s: buildNormal == %s\n",
01714 prefix, (buildNormal ? "TRUE" : "FALSE")));
01715 FDEBUG(("%s: buildTexCoord == %s\n",
01716 prefix, (buildTexCoord ? "TRUE" : "FALSE")));
01717 FDEBUG(("%s: nSubdivs == %d\n", prefix, numSubdivs));
01718
01719 if(crossSection.size() == 1)
01720 {
01721 FWARNING(("OSGExtrusion: Encountered 1 point cross section\n"));
01722 return NullFC;
01723 }
01724
01725
01726 ExtrusionSurface surf(crossSection,
01727 orientation,
01728 scale,
01729 spine,
01730 creaseAngle,
01731 beginCap,
01732 endCap,
01733 ccw,
01734 convex,
01735 buildNormal,
01736 buildTexCoord);
01737
01738
01739 GeometryPtr geoPtr = surf.createGeometry(numSubdivs);
01740
01741 return geoPtr;
01742 }
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761 template <class VectorTypeT>
01762 static void subdivide(const typename std::vector<VectorTypeT>& dataIn,
01763 typename std::vector<VectorTypeT>* dataOut,
01764 bool closed)
01765 {
01766 typename std::vector<VectorTypeT>::const_iterator inputIt;
01767
01768
01769 if(dataIn.size() <= 2)
01770 {
01771
01772 dataOut->assign(dataIn.begin(), dataIn.end());
01773 return;
01774 }
01775
01776
01777 dataOut->clear();
01778 dataOut->reserve((2 * dataIn.size()) + 1);
01779
01780 inputIt = dataIn.begin();
01781 dataOut->push_back(*inputIt);
01782
01783
01784
01785 if(closed)
01786 {
01787
01788 dataOut->push_back(apply4PtScheme<VectorTypeT>(dataIn.end() - 2,
01789 inputIt,
01790 inputIt + 1,
01791 inputIt + 2));
01792 }
01793
01794 else
01795 {
01796 dataOut->push_back(apply3PtScheme<VectorTypeT>(inputIt,
01797 inputIt + 1,
01798 inputIt + 2));
01799 }
01800 inputIt++;
01801
01802
01803
01804
01805
01806 if(dataIn.size() > 3)
01807 {
01808
01809 for(; (inputIt + 2) != dataIn.end(); ++inputIt)
01810 {
01811 dataOut->push_back(*inputIt);
01812 dataOut->push_back(apply4PtScheme<VectorTypeT>(inputIt - 1,
01813 inputIt,
01814 inputIt + 1,
01815 inputIt + 2));
01816 }
01817 }
01818
01819 dataOut->push_back(*inputIt);
01820
01821
01822
01823 if(closed)
01824 {
01825 dataOut->push_back(apply4PtScheme<VectorTypeT>(dataIn.end() - 3,
01826 dataIn.end() - 2,
01827 dataIn.begin(),
01828 dataIn.begin() + 1));
01829 }
01830 else
01831 {
01832
01833
01834 dataOut->push_back(apply3PtScheme<VectorTypeT>(dataIn.end() - 1,
01835 dataIn.end() - 2,
01836 dataIn.end() - 3));
01837 }
01838
01839
01840 dataOut->push_back(dataIn.back());
01841 }
01842
01843
01844
01845
01846
01847
01848
01849
01850 template <class VectorTypeT>
01851 static void subdivide(const typename std::vector<VectorTypeT>& dataIn,
01852 typename std::vector<VectorTypeT>* dataOut,
01853 UInt32 nTimes,
01854 bool closed)
01855 {
01856 std::vector<VectorTypeT> in(dataIn), out;
01857 for(UInt32 i = 0; i < nTimes; i++)
01858 {
01859 if(i + 1 < nTimes)
01860 {
01861 out.clear();
01862 out.reserve(2 * (in.size() + 1));
01863 subdivide<VectorTypeT>(in, &out, closed);
01864
01865
01866 in.swap(out);
01867 }
01868 else
01869 {
01870 dataOut->clear();
01871 dataOut->reserve(2 * (in.size() + 1));
01872
01873
01874 subdivide<VectorTypeT>(in, dataOut, closed);
01875 }
01876 }
01877 }
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889 void ExtrusionSurface::storeVertexNormalGeo(GeoIndicesUI32Ptr indicesPtr,
01890 GeoPLengthsUI32Ptr lensPtr,
01891 GeoPTypesUI8Ptr typesPtr)
01892 {
01893 if(!_createNormals || !_createTexCoords)
01894 return;
01895
01896 std::vector<Vec3f> nRevTable(_normalMap.size());
01897 std::vector<Pnt3f> pRevTable(_posMap.size());
01898
01899 NormalMap::iterator nIt = _normalMap.begin();
01900 PositionMap::iterator pIt = _posMap.begin();
01901
01902
01903 for(; nIt != _normalMap.end(); ++nIt)
01904 nRevTable[nIt->second] = nIt->first;
01905
01906
01907 for(; pIt != _posMap.end(); ++pIt)
01908 pRevTable[pIt->second] = pIt->first;
01909
01910 UInt32 prevN = indicesPtr->size();
01911 UInt32 i = 0;
01912
01913 Vertex v;
01914
01915 v.normal = Vec3f(0.f, 0.f, 0.f);
01916 v.texCoord = Vec2f(0.f, 0.f);
01917
01918 while(i < prevN)
01919 {
01920 v.position = pRevTable[indicesPtr->getValue(i)];
01921 storeVertex(v, indicesPtr);
01922
01923 v.position += 0.3f * nRevTable[indicesPtr->getValue(i+1)];
01924 storeVertex(v, indicesPtr);
01925 storePrimitive(GL_LINES, lensPtr, typesPtr);
01926
01927 i+=3;
01928 }
01929 }
01930
01931
01932
01933
01934
01935
01936 void ExtrusionSurface::storeFaceNormalGeo(GeoIndicesUI32Ptr indicesPtr,
01937 GeoPLengthsUI32Ptr lensPtr,
01938 GeoPTypesUI8Ptr typesPtr)
01939 {
01940 if(!_createNormals || !_createTexCoords)
01941 return;
01942
01943 for(UInt32 i = 0; i < _grid.size(); i++)
01944 {
01945 for(UInt32 j = 0; j < _grid[i].size(); j++)
01946 {
01947 Vertex a = _grid[i][j];
01948 a.normal = Vec3f();
01949
01950 for(UInt32 k = 0; k < 4; k++)
01951 {
01952 Vertex b_k =_grid[i][j];
01953 b_k.normal = Vec3f();
01954 b_k.position += 0.3f * a.adjFaceNormals[k];
01955
01956 storeVertex(a, indicesPtr);
01957 storeVertex(b_k, indicesPtr);
01958
01959 storePrimitive(GL_LINES, lensPtr, typesPtr);
01960 }
01961 }
01962 }
01963 }
01964
01965
01966 #ifdef DEBUG_VERTEX_NORMALS
01967 #undef DEBUG_VERTEX_NORMALS
01968 #endif
01969
01970 #ifdef DEBUG_FACE_NORMALS
01971 #undef DEBUG_FACE_NORMALS
01972 #endif
01973
01974
01975
01976
01977 #ifdef __sgi
01978 #pragma set woff 1174
01979 #endif
01980
01981 #ifdef OSG_LINUX_ICC
01982 #pragma warning( disable : 177 )
01983 #endif
01984
01985 namespace
01986 {
01987 static OSG::Char8 cvsid_cpp [] = "@(#)$Id: $";
01988 static OSG::Char8 cvsid_hpp [] = OSGEXTRUSIONGEOMETRY_HEADER_CVSID;
01989 static OSG::Char8 cvsid_inl [] = OSGEXTRUSIONGEOMETRY_INLINE_CVSID;
01990 }
01991
01992 #ifdef __sgi
01993 #pragma reset woff 1174
01994 #endif