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 #ifndef PLIB_NURBS_NURBSSUB_SOURCE
00027 #define PLIB_NURBS_NURBSSUB_SOURCE
00028
00029 #include "nurbsSub.h"
00030 #include <iostream>
00031 #include <cstdio>
00032 #include <stdio.h>
00033
00036 namespace PLib {
00037
00038
00039 const int FALSE_ = 0 ;
00040 const int TRUE_ = 1 ;
00041
00042 struct BOOL{
00043 int value ;
00044 BOOL(): value(FALSE_) {;}
00045 BOOL(int a) { if(a>0) value=TRUE_; else value=FALSE_;}
00046 BOOL(const BOOL& b) { value = b.value ; }
00047 int operator!() { if(value>0) return FALSE_; return TRUE_ ;}
00048 operator int() const {return value;}
00049 int& operator=(int a) { value = a ; return value ; }
00050 };
00051
00062 template <class T>
00063 NurbsSubSurface<T>::NurbsSubSurface(const NurbsSurface<T,3>& s): rsurf(s) {
00064 surf = 0 ;
00065 render = 0 ;
00066
00067
00068 }
00069
00070 #define MAXORDER 20
00071
00072 template <class T>
00073 struct NurbSurface {
00074
00075 int numU, numV;
00076
00077 int orderU, orderV;
00078
00079 T * kvU, * kvV;
00080
00081
00082 Matrix<HPoint_nD<T,3> >& points;
00083
00084
00085 BOOL strV0, strVn,
00086 strU0, strUn;
00087 BOOL flatV, flatU;
00088 SurfSample<T> c00, c0n,
00089 cn0, cnn;
00090 RenderMesh<T> *render;
00091
00092 static T epsilon ;
00093
00094 NurbSurface(): points(tmpPoints) { render = 0 ; }
00095 NurbSurface(Matrix<HPoint_nD<T,3> >& s, int du, int dv);
00096
00097 protected:
00098 Matrix<HPoint_nD<T,3> > tmpPoints ;
00099
00100 };
00101
00102 #define CHECK( n ) \
00103 { if (!(n)) { fprintf( stderr, "Ran out of memory\n" ); exit(-1); } }
00104
00105 #define DIVW( rpt, pt ) \
00106 { (pt)->x() = (rpt)->x() / (rpt)->w(); \
00107 (pt)->y() = (rpt)->y() / (rpt)->w(); \
00108 (pt)->z() = (rpt)->z() / (rpt)->w(); }
00109
00110
00111
00112
00113 template <class T> void DrawSubdivision( NurbSurface<T> *, T tolerance );
00114 template <class T> void DrawEvaluation( NurbSurface<T> * );
00115
00116 template <class T> int FindBreakPoint( T u, T * kv, int m, int k );
00117 template <class T> void AllocNurb( NurbSurface<T> *, T *, T * );
00118 template <class T> void CloneNurb( NurbSurface<T> *, NurbSurface<T> * );
00119 template <class T> void FreeNurb( NurbSurface<T> * );
00120 template <class T> void RefineSurface( NurbSurface<T> *, NurbSurface<T> *, BOOL );
00121
00122 template <class T> void CalcPoint( T, T, NurbSurface<T> *, Point_nD<T,3> *, Point_nD<T,3> *, Point_nD<T,3> * );
00123
00124
00135 template <class T>
00136 void NurbsSubSurface<T>::drawSubdivision(T tolerance)
00137 {
00138 initSurf();
00139 surf->render = render ;
00140 DrawSubdivision(surf,tolerance);
00141 }
00142
00152 template <class T>
00153 void NurbsSubSurface<T>::drawSubdivisionPS(const char* f, T tolerance)
00154 {
00155 ofstream fout ;
00156 fout.open(f) ;
00157 if(fout)
00158 drawSubdivisionPS(fout,tolerance) ;
00159 fout.close();
00160 }
00161
00172 template <class T>
00173 void NurbsSubSurface<T>::drawSubdivisionVRML(const char* f, T tolerance, const Color& col)
00174 {
00175 ofstream fout ;
00176 fout.open(f) ;
00177 if(fout)
00178 drawSubdivisionVRML(fout,tolerance,col) ;
00179 fout.close();
00180 }
00181
00192 template <class T>
00193 void NurbsSubSurface<T>::drawSubdivisionVRML97(const char* f, T tolerance, const Color& col)
00194 {
00195 ofstream fout ;
00196 fout.open(f) ;
00197 if(fout)
00198 drawSubdivisionVRML97(fout,tolerance,col) ;
00199 fout.close();
00200 }
00201
00212 template <class T>
00213 void NurbsSubSurface<T>::drawSubdivisionPS(ostream &os, T tolerance)
00214 {
00215 if(render)
00216 delete render ;
00217 render = new RenderMeshPS<T>(os) ;
00218 drawSubdivision(tolerance) ;
00219 }
00220
00231 template <class T>
00232 void NurbsSubSurface<T>::drawSubdivisionVRML(ostream &os, T tolerance, const Color& col)
00233 {
00234 if(render)
00235 delete render ;
00236 render = new RenderMeshVRML<T>(os,col) ;
00237 drawSubdivision(tolerance) ;
00238 }
00239
00250 template <class T>
00251 void NurbsSubSurface<T>::drawSubdivisionVRML97(ostream &os, T tolerance, const Color& col)
00252 {
00253 if(render)
00254 delete render ;
00255 render = new RenderMeshVRML97<T>(os,col) ;
00256 drawSubdivision(tolerance) ;
00257 }
00258
00269 template <class T>
00270
00271 void NurbsSubSurface<T>::drawSubdivisionPoints(BasicArray<Point_nD<T,3> >&pnts, T tolerance)
00272 {
00273 if(render)
00274 delete render ;
00275 render = new RenderMeshPoints<T>(pnts) ;
00276 drawSubdivision(tolerance) ;
00277 }
00278
00288 template <class T>
00289 void NurbsSubSurface<T>::initSurf()
00290 {
00291 if(surf)
00292 delete surf ;
00293 surf = new NurbSurface<T> ;
00294 surf->numU = rsurf.ctrlPnts().rows() ;
00295 surf->numV = rsurf.ctrlPnts().cols() ;
00296 surf->orderU = rsurf.degreeU()+1 ;
00297 surf->orderV = rsurf.degreeV()+1 ;
00298 surf->kvU = new T[surf->numU + surf->orderU];
00299 surf->kvV = new T[surf->numV + surf->orderV];
00300 surf->points.resize(surf->numV,surf->numU);
00301
00302 surf->flatV = FALSE_;
00303 surf->flatU = FALSE_;
00304 surf->strU0 = FALSE_;
00305 surf->strUn = FALSE_;
00306 surf->strV0 = FALSE_;
00307 surf->strVn = FALSE_;
00308
00309 surf->render = render ;
00310
00311 int i;
00312 for(i=rsurf.knotU().n()-1;i>=0;--i){
00313 surf->kvU[i] = rsurf.knotU()[i] ;
00314 }
00315 for(i=rsurf.knotV().n()-1;i>=0;--i){
00316 surf->kvV[i] = rsurf.knotV()[i] ;
00317 }
00318 for(i=rsurf.ctrlPnts().rows()-1;i>=0;--i)
00319 for(int j=rsurf.ctrlPnts().cols()-1;j>=0;--j)
00320 surf->points(j,i) = rsurf.ctrlPnts()(i,j) ;
00321 }
00322
00323 template <class T>
00324 NurbSurface<T>::NurbSurface(Matrix<HPoint_nD<T,3> >& s, int du, int dv): points(s), orderU(du+1), orderV(dv+1){
00325 numU = points.rows() ;
00326 numV = points.cols() ;
00327 kvU = new T[numU + orderU] ;
00328 kvV = new T[numV + orderV] ;
00329 render = 0 ;
00330 }
00331
00338 template <class T>
00339 NurbsSubSurface<T>::~NurbsSubSurface()
00340 {
00341 if(surf){
00342 delete []surf->kvU ;
00343 delete []surf->kvV ;
00344 }
00345 }
00346
00361 template <class T>
00362 void RenderMeshPS<T>::screenProject(const HPoint_nD<T,3> &worldPt, Point_nD<T,3> &screenPt )
00363 {
00364 screenPt.x() = worldPt.x() / worldPt.w() * 100 + 200;
00365 screenPt.y() = worldPt.y() / worldPt.w() * 100 + 200;
00366 screenPt.z() = worldPt.z() / worldPt.w() * 100 + 200;
00367 }
00368
00381 template <class T>
00382 void RenderMeshVRML<T>::screenProject(const HPoint_nD<T,3> &worldPt, Point_nD<T,3> &screenPt )
00383 {
00384 screenPt = project(worldPt) ;
00385 }
00386
00387
00400 template <class T>
00401 void RenderMeshVRML97<T>::screenProject(const HPoint_nD<T,3> &worldPt, Point_nD<T,3> &screenPt )
00402 {
00403 screenPt = project(worldPt) ;
00404 if(init){
00405 p_min = p_max = screenPt ;
00406 init = 0 ;
00407 }
00408 if(screenPt.x()<p_min.x()) p_min.x() = screenPt.x();
00409 if(screenPt.y()<p_min.y()) p_min.y() = screenPt.y();
00410 if(screenPt.z()<p_min.z()) p_min.z() = screenPt.z();
00411 if(screenPt.x()>p_max.x()) p_max.x() = screenPt.x();
00412 if(screenPt.y()>p_max.y()) p_max.y() = screenPt.y();
00413 if(screenPt.z()>p_max.z()) p_max.z() = screenPt.z();
00414 }
00415
00416
00429 template <class T>
00430 void RenderMeshPoints<T>::screenProject(const HPoint_nD<T,3> &worldPt, Point_nD<T,3> &screenPt )
00431 {
00432 screenPt = project(worldPt) ;
00433 }
00434
00435
00436 inline void LineTo( ostream& out, short x, short y )
00437 {
00438 out << (int)x << " " << (int)y << " lineto\n" ;
00439 }
00440
00441 inline void MoveTo( ostream& out, short x, short y )
00442 {
00443 out << (int)x << " " << (int)y << " moveto\n" ;
00444 }
00445
00452 template <class T>
00453 void RenderMeshPS<T>::drawHeader(){
00454 out << "%!PS-Adobe-2.1\n";
00455 out << "%%Title: code5_0.ps (20)\n" ;
00456 out << "%%Creator: color_grid_generator\n" ;
00457 out << "%%BoundingBox: 0 0 500 500\n" ;
00458 out << "%%Pages: 0\n" ;
00459 out << "%%EndComments\n" ;
00460 out << "0 setlinewidth\n" ;
00461 out << "0 0 0 setrgbcolor\n" ;
00462 }
00463
00470 template <class T>
00471 void RenderMeshPS<T>::drawFooter(){
00472 out << "showpage\n%%EOF\n" ;
00473 }
00474
00475
00486 template <class T>
00487 void RenderMeshPS<T>::drawTriangle( const SurfSample<T> &v0, const SurfSample<T> &v1, const SurfSample<T> & v2 )
00488 {
00489 out << "newpath\n" ;
00490 MoveTo( out, (short) (v0.point.x() * 100 + 200), (short) (v0.point.y() * 100 + 200) );
00491 LineTo( out, (short) (v1.point.x() * 100 + 200), (short) (v1.point.y() * 100 + 200) );
00492 LineTo( out, (short) (v2.point.x() * 100 + 200), (short) (v2.point.y() * 100 + 200) );
00493 LineTo( out, (short) (v0.point.x() * 100 + 200), (short) (v0.point.y() * 100 + 200) );
00494 out << "stroke\n" ;
00495 }
00496
00506 template <class T>
00507 void RenderMeshPS<T>::drawLine( const SurfSample<T> &v0, const SurfSample<T> &v1)
00508 {
00509 out << "newpath\n" ;
00510 MoveTo(out , (short) (v0.point.x() * 100 + 200), (short) (v0.point.y() * 100 + 200) );
00511 LineTo( out, (short) (v1.point.x() * 100 + 200), (short) (v1.point.y() * 100 + 200) );
00512 out << "stroke\n" ;
00513 }
00514
00515
00522 template <class T>
00523 void RenderMeshVRML97<T>::drawHeader()
00524 {
00525 size = 0 ;
00526 out << "#VRML V2.0 utf8\n" ;
00527 out << "# Generated by Phil's NURBS library\n" ;
00528 out << "\nGroup {\n" ;
00529 out << "\n children [\n" ;
00530 out << "\tDEF T Transform {\n";
00531 out << "\t children [\n" ;
00532 out << "\t\tShape {\n" ;
00533 out << "\t\t appearance Appearance {\n" ;
00534 out << "\t\t\tmaterial Material{ diffuseColor " << float(color.r/255.0) << ' ' << float(color.g/255.0) << ' ' << float(color.b/255.0) << " }\n" ;
00535 out << "\t\t }\n" ;
00536 out << "\t\t geometry IndexedFaceSet {\n" ;
00537 out << "\t\t\tsolid FALSE\n" ;
00538 out << "\t\t\tcoord Coordinate {\n" ;
00539 out << "\t\t\t point [\n" ;
00540 }
00541
00550 template <class T>
00551 void RenderMeshVRML97<T>::drawFooter(){
00552
00553 out << "\t\t\t ]\n" ;
00554 out << "\t\t\t}\n" ;
00555
00556 out << "\t\t\t coordIndex [\n" ;
00557
00558 for(int i=0;i<size;++i){
00559 out << "\t\t\t\t" << 3*i << ", " << 3*i+1 << ", " << 3*i+2 << ", -1,\n" ;
00560 }
00561 out << "\t\t\t ]\n" ;
00562 out << "\t\t\t}\n" ;
00563 out << "\t\t}\n" ;
00564 out << "\t ]\n" ;
00565 out << "\t}\n" ;
00566 out << " ]\n" ;
00567 out << "}\n" ;
00568
00569 Point_nD<T,3> p_mid((p_max.x()+p_min.x())/T(2),
00570 (p_max.y()+p_min.y())/T(2),
00571 (p_max.z()+p_min.z())/T(2));
00572
00573 T x_axis = p_max.x() - p_min.x() ;
00574 T y_axis = p_max.y() - p_min.y() ;
00575
00576 T axis = (x_axis< y_axis) ? y_axis : x_axis ;
00577 axis *= T(2) ;
00578
00579 out << "Viewpoint {\n\t position " << p_mid.x() << ' ' << p_mid.y() << ' ' << p_max.z()+axis << "\n\t description \"top\"\n}\n" ;
00580
00581
00582 out << "NavigationInfo { type \"EXAMINE\" }\n" ;
00583
00584 }
00585
00592 template <class T>
00593 void RenderMeshVRML<T>::drawHeader()
00594 {
00595 size = 0 ;
00596 out << "#VRML V1.0 ascii\n" ;
00597 out << "# Generated by Phil's NURBS library\n" ;
00598 out << "\nSeparator {\n" << "\tMaterialBinding { value PER_VERTEX_INDEXED }\n" ;
00599 out << "\tMaterial{ ambientColor 0.25 0.25 0.25\n\t\tdiffuseColor " << float(color.r/255.0) << ' ' << float(color.g/255.0) << ' ' << float(color.b/255.0) << " }\n" ;
00600 out << "\tCoordinate3 {\n" ;
00601 out << "\t\tpoint [\n" ;
00602 }
00603
00612 template <class T>
00613 void RenderMeshVRML<T>::drawFooter(){
00614
00615 out << "\t\t]\n" ;
00616 out << "\t}\n" ;
00617
00618 out << "\tIndexedFaceSet{\n" ;
00619 out << "\t\tcoordIndex[\n" ;
00620
00621 for(int i=0;i<size;++i){
00622 out << "\t\t\t" << 3*i << ", " << 3*i+1 << ", " << 3*i+2 << ", -1,\n" ;
00623 }
00624 out << "\t\t]\n" ;
00625 out << "\t}\n" ;
00626
00627 out << "}\n" ;
00628 }
00629
00630
00643 template <class T>
00644 void RenderMeshVRML<T>::drawTriangle(const SurfSample<T> &v0, const SurfSample<T> &v1, const SurfSample<T> & v2 )
00645 {
00646 ++size ;
00647 out << "\t\t\t" << v0.point.x() << " " << v0.point.y() << " " << v0.point.z() << ",\n" ;
00648 out << "\t\t\t" << v1.point.x() << " " << v1.point.y() << " " << v1.point.z() << ",\n" ;
00649 out << "\t\t\t" << v2.point.x() << " " << v2.point.y() << " " << v2.point.z() << ",\n" ;
00650
00651 }
00652
00665 template <class T>
00666 void RenderMeshVRML97<T>::drawTriangle(const SurfSample<T> &v0, const SurfSample<T> &v1, const SurfSample<T> & v2 )
00667 {
00668 ++size ;
00669 out << "\t\t\t\t" << v0.point.x() << " " << v0.point.y() << " " << v0.point.z() << ",\n" ;
00670 out << "\t\t\t\t" << v1.point.x() << " " << v1.point.y() << " " << v1.point.z() << ",\n" ;
00671 out << "\t\t\t\t" << v2.point.x() << " " << v2.point.y() << " " << v2.point.z() << ",\n" ;
00672
00673 }
00674
00681 template <class T>
00682 void RenderMeshPoints<T>::drawHeader()
00683 {
00684 points.clear();
00685 }
00686
00694 template <class T>
00695 void RenderMeshPoints<T>::drawFooter(){
00696 }
00697
00698
00711 template <class T>
00712 void RenderMeshPoints<T>::drawTriangle(const SurfSample<T> &v0, const SurfSample<T> &v1, const SurfSample<T> & v2 )
00713 {
00714
00715 points.push_back(v0.point);
00716 points.push_back(v1.point);
00717 points.push_back(v2.point);
00718 }
00719
00720 template <class T>
00721 int
00722 FindBreakPoint( T u, T * kv, int m, int k )
00723 {
00724 int i;
00725
00726 if (u == kv[m+1])
00727 return m;
00728
00729 i = m + k;
00730 while ((u < kv[i]) && (i > 0))
00731 i--;
00732 return( i );
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 template <class T> void
00747 BasisFunctions( T u, int brkPoint, T * kv, int k, T * bvals )
00748 {
00749 int r, s, i;
00750 T omega;
00751
00752 bvals[0] = 1.0;
00753 for (r = 2; r <= k; r++)
00754 {
00755 i = brkPoint - r + 1;
00756 bvals[r - 1] = 0.0;
00757 for (s = r-2; s >= 0; s--)
00758 {
00759 i++;
00760 if (i < 0)
00761 omega = 0;
00762 else
00763 omega = (u - kv[i]) / (kv[i + r - 1] - kv[i]);
00764 bvals[s + 1] = bvals[s + 1] + (1 - omega) * bvals[s];
00765 bvals[s] = omega * bvals[s];
00766 }
00767 }
00768 }
00769
00770
00771
00772
00773 template <class T> void
00774 BasisDerivatives( T u, int brkPoint, T * kv, int k, T * dvals )
00775 {
00776 register int s, i;
00777 T omega, knotScale;
00778
00779 BasisFunctions( u, brkPoint, kv, k - 1, dvals );
00780
00781 dvals[k-1] = 0.0;
00782
00783 knotScale = kv[brkPoint + 1] - kv[brkPoint];
00784
00785 i = brkPoint - k + 1;
00786 for (s = k - 2; s >= 0; s--)
00787 {
00788 i++;
00789 omega = knotScale * ((T)(k-1)) / (kv[i+k-1] - kv[i]);
00790 dvals[s + 1] += -omega * dvals[s];
00791 dvals[s] *= omega;
00792 }
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 template <class T>
00804 void
00805 CalcPoint(T u, T v, NurbSurface<T> * n,
00806 Point_nD<T,3> * p, Point_nD<T,3> * utan, Point_nD<T,3> * vtan)
00807 {
00808 int i, j, ri, rj;
00809 HPoint_nD<T,3> * cp;
00810 T tmp;
00811 T wsqrdiv;
00812 int ubrkPoint, ufirst;
00813 T bu[MAXORDER], buprime[MAXORDER];
00814 int vbrkPoint, vfirst;
00815 T bv[MAXORDER], bvprime[MAXORDER];
00816 HPoint_nD<T,3> r, rutan, rvtan;
00817
00818 r.x() = 0.0;
00819 r.y() = 0.0;
00820 r.z() = 0.0;
00821 r.w() = 0.0;
00822
00823 rutan = r;
00824 rvtan = r;
00825
00826
00827
00828 ubrkPoint = FindBreakPoint( u, n->kvU, n->numU-1, n->orderU );
00829 ufirst = ubrkPoint - n->orderU + 1;
00830 BasisFunctions( u, ubrkPoint, n->kvU, n->orderU, bu );
00831 if (utan)
00832 BasisDerivatives( u, ubrkPoint, n->kvU, n->orderU, buprime );
00833
00834 vbrkPoint = FindBreakPoint( v, n->kvV, n->numV-1, n->orderV );
00835 vfirst = vbrkPoint - n->orderV + 1;
00836 BasisFunctions( v, vbrkPoint, n->kvV, n->orderV, bv );
00837 if (vtan)
00838 BasisDerivatives( v, vbrkPoint, n->kvV, n->orderV, bvprime );
00839
00840
00841
00842 for (i = 0; i < n->orderV; i++)
00843 for (j = 0; j < n->orderU; j++)
00844 {
00845 ri = n->orderV - 1 - i;
00846 rj = n->orderU - 1 - j;
00847
00848 tmp = bu[rj] * bv[ri];
00849 cp = &( n->points(i+vfirst,j+ufirst) );
00850 r.x() += cp->x() * tmp;
00851 r.y() += cp->y() * tmp;
00852 r.z() += cp->z() * tmp;
00853 r.w() += cp->w() * tmp;
00854
00855 if (utan)
00856 {
00857 tmp = buprime[rj] * bv[ri];
00858 rutan.x() += cp->x() * tmp;
00859 rutan.y() += cp->y() * tmp;
00860 rutan.z() += cp->z() * tmp;
00861 rutan.w() += cp->w() * tmp;
00862 }
00863 if (vtan)
00864 {
00865 tmp = bu[rj] * bvprime[ri];
00866 rvtan.x() += cp->x() * tmp;
00867 rvtan.y() += cp->y() * tmp;
00868 rvtan.z() += cp->z() * tmp;
00869 rvtan.w() += cp->w() * tmp;
00870 }
00871 }
00872
00873
00874
00875 wsqrdiv = 1.0 / (r.w() * r.w());
00876 if (utan)
00877 {
00878 utan->x() = (r.w() * rutan.x() - rutan.w() * r.x()) * wsqrdiv;
00879 utan->y() = (r.w() * rutan.y() - rutan.w() * r.y()) * wsqrdiv;
00880 utan->z() = (r.w() * rutan.z() - rutan.w() * r.z()) * wsqrdiv;
00881 }
00882 if (vtan)
00883 {
00884 vtan->x() = (r.w() * rvtan.x() - rvtan.w() * r.x()) * wsqrdiv;
00885 vtan->y() = (r.w() * rvtan.y() - rvtan.w() * r.y()) * wsqrdiv;
00886 vtan->z() = (r.w() * rvtan.z() - rvtan.w() * r.z()) * wsqrdiv;
00887 }
00888
00889 p->x() = r.x() / r.w();
00890 p->y() = r.y() / r.w();
00891 p->z() = r.z() / r.w();
00892 }
00893
00894
00895
00896
00897
00898 template <class T>
00899 void
00900 DrawEvaluation( NurbSurface<T> * n )
00901 {
00902 Point_nD<T,3> p, utan, vtan;
00903 register int i, j;
00904 register T u, v, d;
00905 SurfSample<T> ** pts ;
00906
00907 int Granularity = 10;
00908
00909
00910
00911 CHECK( pts = new (SurfSample<T>*)[Granularity+1]);
00912 CHECK( pts[0] = new SurfSample<T>[(Granularity+1)*(Granularity+1)]);
00913
00914 for (i = 1; i <= Granularity; i++)
00915 pts[i] = &(pts[0][(Granularity+1) * i]);
00916
00917
00918
00919 for (i = 0; i <= Granularity; i++)
00920 {
00921 v = ((T) i / (T) Granularity)
00922 * (n->kvV[n->numV] - n->kvV[n->orderV-1])
00923 + n->kvV[n->orderV-1];
00924
00925 for (j = 0; j <= Granularity; j++)
00926 {
00927 u = ((T) j / (T) Granularity)
00928 * (n->kvU[n->numU] - n->kvU[n->orderU-1])
00929 + n->kvU[n->orderU-1];
00930
00931 CalcPoint( u, v, n, &(pts[i][j].point), &utan, &vtan );
00932 p = crossProduct(utan,vtan) ;
00933 d = norm(p) ;
00934 if (d != 0.0)
00935 {
00936 p.x() /= d;
00937 p.y() /= d;
00938 p.z() /= d;
00939 }
00940 else
00941 {
00942 p.x() = 0;
00943 p.y() = 0;
00944 p.z() = 0;
00945 }
00946 pts[i][j].normLen = d;
00947 pts[i][j].normal = p;
00948 pts[i][j].u = u;
00949 pts[i][j].v = v;
00950 }
00951 }
00952
00953
00954
00955 for (i = 0; i < Granularity; i++)
00956 for (j = 0; j < Granularity; j++)
00957 {
00958 n->render->drawTriangle( pts[i][j], pts[i+1][j+1], pts[i+1][j] );
00959 n->render->drawTriangle( pts[i][j], pts[i][j+1], pts[i+1][j+1] );
00960 }
00961
00962 delete [] pts[0];
00963 delete [] pts ;
00964 }
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980 template <class T> void
00981 CalcAlpha( T * ukv, T * wkv, int m, int n, int k, T *** alpha )
00982 {
00983 int i, j;
00984 int brkPoint, r, rm1, last, s;
00985 T omega;
00986 T aval[MAXORDER];
00987
00988 if (! *alpha)
00989 {
00990 CHECK( *alpha = new (T*)[k+1]);
00991 for (i = 0; i <= k; i++)
00992 CHECK( (*alpha)[i] = new T[(m + n + 1)]);
00993 }
00994
00995 for (j = 0; j <= m + n; j++)
00996 {
00997 brkPoint = FindBreakPoint( wkv[j], ukv, m, k );
00998 aval[0] = 1.0;
00999 for (r = 2; r <= k; r++)
01000 {
01001 rm1 = r - 1;
01002 last = minimum( rm1, brkPoint );
01003 i = brkPoint - last;
01004 if (last < rm1)
01005 aval[last] = aval[last] * (wkv[j + r - 1] - ukv[i])
01006 / (ukv[i + r - 1] - ukv[i]);
01007 else
01008 aval[last] = 0.0;
01009
01010 for (s = last - 1; s >= 0; s-- )
01011 {
01012 i++;
01013 omega = (wkv[j + r - 1] - ukv[i]) / (ukv[i + r - 1] - ukv[i]);
01014 aval[s + 1] = aval[s+1] + (1 - omega) * aval[s];
01015 aval[s] = omega * aval[s];
01016 }
01017 }
01018 last = minimum( k - 1, brkPoint );
01019 for (i = 0; i <= k; i++)
01020 (*alpha)[i][j] = 0.0;
01021 for (s = 0; s <= last; s++)
01022 (*alpha)[last - s][j] = aval[s];
01023 }
01024 }
01025
01026
01027
01028
01029
01030 template <class T>
01031 void
01032 RefineSurface( NurbSurface<T> * src, NurbSurface<T> * dest, BOOL dirflag )
01033 {
01034 int i, j, out;
01035 HPoint_nD<T,3> * dp, * sp;
01036 int i1, brkPoint, maxj, maxout;
01037 register T tmp;
01038 T ** alpha = 0;
01039
01040
01041
01042 if (dirflag)
01043 {
01044 CalcAlpha( src->kvU, dest->kvU, src->numU - 1, dest->numU - src->numU,
01045 src->orderU, &alpha );
01046 maxj = dest->numU;
01047 maxout = src->numV;
01048 }
01049 else
01050 {
01051 CalcAlpha( src->kvV, dest->kvV, src->numV - 1, dest->numV - src->numV,
01052 src->orderV, &alpha );
01053 maxj = dest->numV;
01054 maxout = dest->numU;
01055 }
01056
01057
01058
01059 for (out = 0; out < maxout; out++)
01060 for (j = 0; j < maxj; j++)
01061 {
01062 if (dirflag)
01063 {
01064 dp = &(dest->points(out,j));
01065 brkPoint = FindBreakPoint( dest->kvU[j], src->kvU,
01066 src->numU-1, src->orderU );
01067 i1 = maximum( brkPoint - src->orderU + 1, 0 );
01068 sp = &(src->points(out,i1));
01069 } else {
01070 dp = &(dest->points(j,out));
01071 brkPoint = FindBreakPoint( dest->kvV[j], src->kvV,
01072 src->numV-1, src->orderV );
01073 i1 = maximum( brkPoint - src->orderV + 1, 0 );
01074 sp = &(src->points(i1,out));
01075 }
01076 dp->x() = 0.0;
01077 dp->y() = 0.0;
01078 dp->z() = 0.0;
01079 dp->w() = 0.0;
01080 for (i = i1; i <= brkPoint; i++)
01081 {
01082 tmp = alpha[i - i1][j];
01083 sp = (dirflag ? &(src->points(out,i)) : &(src->points(i,out)) );
01084 dp->x() += tmp * sp->x();
01085 dp->y() += tmp * sp->y();
01086 dp->z() += tmp * sp->z();
01087 dp->w() += tmp * sp->w();
01088 }
01089 }
01090
01091
01092 for (i = 0; i <= (dirflag ? src->orderU : src->orderV); i++)
01093 delete [] alpha[i] ;
01094 delete [] alpha ;
01095 }
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110 template <class T>
01111 void
01112 AllocNurb( NurbSurface<T> * n, T * ukv, T * vkv )
01113 {
01114 int i;
01115
01116 if (! ukv)
01117 n->kvU = new T[n->numU + n->orderU] ;
01118 else
01119 n->kvU = ukv;
01120 if (! vkv)
01121 n->kvV = new T[n->numV + n->orderV];
01122 else
01123 n->kvV = vkv;
01124
01125 n->points.resize(n->numV,n->numU) ;
01126 }
01127
01128
01129
01130
01131
01132 template <class T>
01133 void
01134 FreeNurb( NurbSurface<T> * n )
01135 {
01136 int i;
01137
01138 if (n->kvU) delete [] n->kvU ;
01139 n->kvU = 0;
01140 if (n->kvV) delete [] n->kvV ;
01141 n->kvV = 0;
01142 delete n ;
01143 n = 0 ;
01144
01145 }
01146
01147
01148
01149
01150
01151 template <class T>
01152 void
01153 CloneNurb( NurbSurface<T> * src, NurbSurface<T> * dst )
01154 {
01155 int i, j;
01156 T * srcp, *dstp;
01157
01158
01159 dst->numU = src->numU ;
01160 dst->numV = src->numV ;
01161 dst->orderU = src->orderU ;
01162 dst->orderV = src->orderV ;
01163
01164 dst->strU0 = src->strU0 ;
01165 dst->strUn = src->strUn ;
01166 dst->strV0 = src->strV0 ;
01167 dst->strVn = src->strVn ;
01168
01169 dst->kvU = 0;
01170 dst->kvV = 0;
01171 dst->points = 0;
01172
01173 AllocNurb( dst, (T*)0, (T*)0 );
01174
01175
01176 srcp = src->kvU;
01177 dstp = dst->kvU;
01178 for (i = 0; i < src->numU + src->orderU; i++)
01179 *dstp++ = *srcp++;
01180
01181 srcp = src->kvV;
01182 dstp = dst->kvV;
01183 for (i = 0; i < src->numV + src->orderV; i++)
01184 *dstp++ = *srcp++;
01185
01186
01187 for (i = 0; i < src->numV; i++)
01188 for (j = 0; j < src->numU; j++)
01189 dst->points(i,j) = src->points(i,j);
01190 }
01191
01192
01193
01194
01195
01196
01197
01198
01199 #define DIVPT( p, dn ) { ((p).x()) /= (dn); ((p).y()) /= (dn); ((p).z()) /= (dn); }
01200
01201 #define maxV(surf) ((surf)->numV-1)
01202 #define maxU(surf) ((surf)->numU-1)
01203
01204
01205
01206
01207
01208
01209
01210 template <class T> int
01211 SplitKV( T * srckv,
01212 T ** destkv,
01213 int * splitPt,
01214 int m, int k )
01215 {
01216 int i, last;
01217 int middex, extra, same;
01218 T midVal;
01219
01220 extra = 0;
01221 last = (m + k);
01222
01223 middex = last / 2;
01224 midVal = srckv[middex];
01225
01226
01227
01228 i = middex+1;
01229 same = 1;
01230 while ((i < last) && (srckv[i] == midVal)) {
01231 i++;
01232 same++;
01233 }
01234
01235 i = middex-1;
01236 while ((i > 0) && (srckv[i] == midVal)) {
01237 i--;
01238 middex--;
01239 same++;
01240 }
01241
01242 if (i <= 0)
01243 {
01244 midVal = (srckv[0] + srckv[last]) / 2.0;
01245 middex = last / 2;
01246 while (srckv[middex + 1] < midVal)
01247 middex++;
01248 same = 0;
01249 }
01250
01251 extra = k - same;
01252 *destkv = new T[m+k+extra+1];
01253
01254 if (same < k)
01255 {
01256 for (i = 0; i <= middex; i++)
01257 (*destkv)[i] = srckv[i];
01258
01259 for (i = middex+1; i <= middex+extra; i++)
01260 (*destkv)[i] = midVal;
01261
01262 for (i = middex + k - same + 1; i <= m + k + extra; i++)
01263 (*destkv)[i] = srckv[i - extra];
01264 }
01265 else
01266 {
01267 for (i = 0; i <= m + k; i++)
01268 (*destkv)[i] = srckv[i];
01269 }
01270
01271 *splitPt = (extra < k) ? middex - 1 : middex;
01272 return( extra );
01273 }
01274
01275
01276
01277
01278
01279 template <class T> void
01280 ProjectToLine( Point_nD<T,3> * firstPt, Point_nD<T,3> * lastPt, Point_nD<T,3> * midPt )
01281 {
01282 Point_nD<T,3> base, v0, vm;
01283 T fraction, denom;
01284
01285 base = *firstPt;
01286
01287 v0 = *lastPt - base ;
01288 vm = *midPt - base ;
01289
01290 denom = norm2(v0) ;
01291
01292 fraction = (denom == 0.0) ? 0.0 : (v0*vm ) / denom;
01293
01294 midPt->x() = base.x() + fraction * v0.x();
01295 midPt->y() = base.y() + fraction * v0.y();
01296 midPt->z() = base.z() + fraction * v0.z();
01297 }
01298
01299
01300
01301
01302
01303
01304
01305 template <class T> void
01306 FixNormals( SurfSample<T> * s0, SurfSample<T> * s1, SurfSample<T> * s2 )
01307 {
01308 BOOL goodnorm;
01309 int i, j, ok;
01310 T dist;
01311 SurfSample<T> * V[3];
01312 Point_nD<T,3> normal;
01313
01314 V[0] = s0; V[1] = s1; V[2] = s2;
01315
01316
01317 for (ok = 0, goodnorm = FALSE_;
01318 (ok < 3L) && !(goodnorm = (V[ok]->normLen > 0.0)); ok++);
01319
01320 if (! goodnorm)
01321 {
01322 normal.x() = 0.0; normal.y() = 0.0; normal.z() = 0.0;
01323
01324 for (i = 0; i < 3L; i++)
01325 {
01326 j = (i + 1) % 3L;
01327 normal.x() += (V[i]->point.y() - V[j]->point.y()) * (V[i]->point.z() + V[j]->point.z());
01328 normal.y() += (V[i]->point.z() - V[j]->point.z()) * (V[i]->point.x() + V[j]->point.x());
01329 normal.z() += (V[i]->point.x() - V[j]->point.x()) * (V[i]->point.y() + V[j]->point.y());
01330 }
01331
01332 dist = norm(normal) ;
01333 if (dist == 0.0)
01334 return;
01335
01336 DIVPT( normal, dist );
01337
01338 for (i = 0; i < 3; i++)
01339 {
01340 V[i]->normal = normal;
01341 V[i]->normLen = dist;
01342 }
01343 }
01344 else
01345 {
01346 for (i = 0; i < 3; i++)
01347 if ((i != ok) && (V[i]->normLen == 0.0))
01348 V[i]->normal = V[ok]->normal;
01349 }
01350 return;
01351 }
01352
01353
01354
01355
01356
01357 template <class T> void
01358 AdjustNormal( SurfSample<T> * samp )
01359 {
01360
01361 samp->normLen = norm(samp->normal) ;
01362
01363 if (samp->normLen < samp->epsilon )
01364 samp->normLen = 0.0;
01365 else
01366 DIVPT( (samp->normal), samp->normLen );
01367 }
01368
01369
01370
01371
01372
01373
01374 template <class T> void
01375 GetNormal( NurbSurface<T> * n, int indV, int indU )
01376 {
01377 Point_nD<T,3> tmpL, tmpR;
01378 SurfSample<T> * crnr;
01379
01380 if ( (indU && indV) || ((! indU) && (!indV)) )
01381 {
01382 if (indU)
01383 crnr = &(n->cnn);
01384 else
01385 crnr = &(n->c00);
01386 DIVW( &(n->points(indV,(indU ? (indU-1) : 1))), &tmpL );
01387 DIVW( &(n->points((indV ? (indV-1) : 1),indU)), &tmpR );
01388 }
01389 else
01390 {
01391 if (indU)
01392 crnr = &(n->c0n);
01393 else
01394 crnr = &(n->cn0);
01395 DIVW( &(n->points(indV,(indU ? (indU-1) : 1))), &tmpR );
01396 DIVW( &(n->points((indV ? (indV-1) : 1),indU)), &tmpL );
01397 }
01398
01399 tmpL -= crnr->point ;
01400 tmpR -= crnr->point ;
01401 crnr->normal = crossProduct(tmpL,tmpR);
01402 AdjustNormal( crnr );
01403 }
01404
01405
01406
01407
01408
01409 template <class T> void
01410 MakeNewCorners( NurbSurface<T> * parent,
01411 NurbSurface<T> * kid0,
01412 NurbSurface<T> * kid1,
01413 BOOL dirflag )
01414 {
01415 DIVW( &(kid0->points(maxV(kid0),maxU(kid0))), &(kid0->cnn.point) );
01416 GetNormal( kid0, maxV(kid0), maxU(kid0) );
01417
01418 if (dirflag)
01419 {
01420 kid0->strUn = FALSE_;
01421
01422 DIVW( &(kid0->points(0,maxU(kid0))), &(kid0->c0n.point) );
01423 GetNormal( kid0, 0, maxU(kid0) );
01424
01425
01426
01427
01428 kid1->c00.point = kid0->c0n.point;
01429 GetNormal( kid1, 0, 0 );
01430 kid1->cn0.point = kid0->cnn.point;
01431 GetNormal( kid1, maxV(kid1), 0 );
01432
01433
01434
01435
01436
01437 if (parent->strV0)
01438 ProjectToLine( &(parent->c00.point),
01439 &(parent->c0n.point),
01440 &(kid0->c0n.point) );
01441 if (parent->strVn)
01442 ProjectToLine( &(parent->cn0.point),
01443 &(parent->cnn.point),
01444 &(kid0->cnn.point) );
01445
01446 kid1->c00.point = kid0->c0n.point;
01447 kid1->cn0.point = kid0->cnn.point;
01448 kid1->strU0 = FALSE_;
01449 }
01450 else
01451 {
01452 kid0->strVn = FALSE_;
01453
01454 DIVW( &(kid0->points(maxV(kid0),0)), &(kid0->cn0.point) );
01455 GetNormal( kid0, maxV(kid0), 0 );
01456 kid1->c00.point = kid0->cn0.point;
01457 GetNormal( kid1, 0, 0 );
01458 kid1->c0n.point = kid0->cnn.point;
01459 GetNormal( kid1, 0, maxU(kid1) );
01460
01461 if (parent->strU0)
01462 ProjectToLine( &(parent->c00.point),
01463 &(parent->cn0.point),
01464 &(kid0->cn0.point) );
01465 if (parent->strUn)
01466 ProjectToLine( &(parent->c0n.point),
01467 &(parent->cnn.point),
01468 &(kid0->cnn.point) );
01469
01470 kid1->c00.point = kid0->cn0.point;
01471 kid1->c0n.point = kid0->cnn.point;
01472 kid1->strV0 = FALSE_;
01473 }
01474 }
01475
01476
01477
01478
01479
01480
01481
01482
01483 template <class T> void
01484 SplitSurface( NurbSurface<T> * parent,
01485 NurbSurface<T> * kid0, NurbSurface<T> * kid1,
01486 BOOL dirflag )
01487 {
01488 NurbSurface<T> *tmp;
01489 T * newkv;
01490 int i, j, splitPt;
01491
01492 tmp = new NurbSurface<T> ;
01493
01494
01495
01496
01497
01498
01499
01500
01501 tmp->numU = parent->numU ;
01502 tmp->numV = parent->numV ;
01503 tmp->orderU = parent->orderU ;
01504 tmp->orderV = parent->orderV ;
01505
01506 tmp->strU0 = parent->strU0 ;
01507 tmp->strUn = parent->strUn ;
01508 tmp->strV0 = parent->strV0 ;
01509 tmp->strVn = parent->strVn ;
01510
01511 tmp->render = parent->render ;
01512
01513 if (dirflag)
01514 {
01515 tmp->numU = parent->numU + SplitKV( parent->kvU,
01516 &newkv,
01517 &splitPt,
01518 maxU(parent),
01519 parent->orderU );
01520 AllocNurb( tmp, newkv, (T*)0 );
01521 for (i = 0; i < tmp->numV + tmp->orderV; i++)
01522 tmp->kvV[i] = parent->kvV[i];
01523 }
01524 else
01525 {
01526 tmp->numV = parent->numV + SplitKV( parent->kvV,
01527 &newkv,
01528 &splitPt,
01529 maxV(parent),
01530 parent->orderV );
01531 AllocNurb( tmp, (T*)0, newkv );
01532 for (i = 0; i < tmp->numU + tmp->orderU; i++)
01533 tmp->kvU[i] = parent->kvU[i];
01534 }
01535 RefineSurface( parent, tmp, dirflag );
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545 kid0->orderU = parent->orderU ;
01546 kid0->orderV = parent->orderV ;
01547
01548 kid0->strU0 = parent->strU0 ;
01549 kid0->strUn = parent->strUn ;
01550 kid0->strV0 = parent->strV0 ;
01551 kid0->strVn = parent->strVn ;
01552
01553 kid0->c00 = parent->c00 ;
01554 kid0->c0n = parent->c0n ;
01555 kid0->cn0 = parent->cn0 ;
01556 kid0->cnn = parent->cnn ;
01557
01558 kid0->render = parent->render ;
01559
01560 kid0->numU = dirflag ? splitPt+1 : parent->numU;
01561 kid0->numV = dirflag ? parent->numV : splitPt+1;
01562 kid0->kvU = kid0->kvV = 0;
01563 AllocNurb( kid0, (T*)0, (T*)0 );
01564
01565 for (i = 0; i < kid0->numV; i++)
01566 for (j = 0; j < kid0->numU; j++)
01567 kid0->points(i,j) = tmp->points(i,j) ;
01568 for (i = 0; i < kid0->orderU + kid0->numU; i++)
01569 kid0->kvU[i] = tmp->kvU[i];
01570 for (i = 0; i < kid0->orderV + kid0->numV; i++)
01571 kid0->kvV[i] = tmp->kvV[i];
01572
01573
01574
01575 splitPt++;
01576
01577 kid1->orderU = parent->orderU ;
01578 kid1->orderV = parent->orderV ;
01579
01580 kid1->strU0 = parent->strU0 ;
01581 kid1->strUn = parent->strUn ;
01582 kid1->strV0 = parent->strV0 ;
01583 kid1->strVn = parent->strVn ;
01584
01585 kid1->c00 = parent->c00 ;
01586 kid1->c0n = parent->c0n ;
01587 kid1->cn0 = parent->cn0 ;
01588 kid1->cnn = parent->cnn ;
01589
01590 kid1->render = parent->render ;
01591
01592 kid1->numU = dirflag ? tmp->numU - splitPt : parent->numU;
01593 kid1->numV = dirflag ? parent->numV : tmp->numV - splitPt;
01594 kid1->kvU = kid1->kvV = 0;
01595 AllocNurb( kid1, (T*)0, (T*)0 );
01596
01597 for (i = 0; i < kid1->numV; i++)
01598 for (j = 0; j < kid1->numU; j++)
01599 kid1->points(i,j)
01600 = tmp->points(dirflag ? i: (i + splitPt) ,dirflag ? (j + splitPt) : j);
01601 for (i = 0; i < kid1->orderU + kid1->numU; i++)
01602 kid1->kvU[i] = tmp->kvU[dirflag ? (i + splitPt) : i];
01603 for (i = 0; i < kid1->orderV + kid1->numV; i++)
01604 kid1->kvV[i] = tmp->kvV[dirflag ? i : (i + splitPt)];
01605
01606
01607 MakeNewCorners( parent, kid0, kid1, dirflag );
01608
01609 FreeNurb( tmp );
01610
01611 }
01612
01613
01614
01615
01616
01617
01618
01619 #define GETPT( i ) (( dirflag ? (n->points(crvInd,i)) : (n->points(i,crvInd)) ))
01620
01621 #define EPSILON n->epsilon
01622
01623 template <class T> BOOL
01624 IsCurveStraight( NurbSurface<T> * n,
01625 T tolerance,
01626 int crvInd,
01627 BOOL dirflag )
01628 {
01629 Point_nD<T,3> p, vec, prod;
01630 Point_nD<T,3> cp, e0;
01631 int i, last;
01632 T linelen, dist;
01633
01634
01635 if ((dirflag ? n->numU : n->numV) == 2)
01636 return( TRUE_ );
01637
01638 last = (dirflag ? n->numU : n->numV) - 1;
01639 n->render->screenProject( GETPT( 0 ), e0 );
01640
01641
01642
01643 linelen = 0.0;
01644 for (i = last; (i > 0) && (linelen < EPSILON); i--)
01645 {
01646 n->render->screenProject( GETPT( i ), cp );
01647 vec = cp - e0 ;
01648 linelen = norm(vec) ;
01649 }
01650
01651 DIVPT( vec, linelen );
01652
01653 if (linelen > EPSILON)
01654 for (i = 1; i <= last; i++)
01655 {
01656
01657
01658
01659 n->render->screenProject( GETPT( i ), cp );
01660 p = cp - e0 ;
01661
01662 prod = crossProduct(p,vec) ;
01663 dist = norm(prod) ;
01664
01665 if (dist > tolerance)
01666 return( FALSE_ );
01667 }
01668
01669 return( TRUE_ );
01670 }
01671
01672
01673
01674
01675
01676
01677 template <class T> BOOL
01678 TestFlat( NurbSurface<T> * n, T tolerance )
01679 {
01680 int i;
01681 BOOL straight;
01682 Point_nD<T,3> cp00, cp0n, cpn0, cpnn, planeEqn;
01683 T dist,d ;
01684
01685
01686
01687 if (! n->strU0)
01688 n->strU0 = IsCurveStraight( n, tolerance, 0, FALSE_ );
01689 if (! n->strUn)
01690 n->strUn = IsCurveStraight( n, tolerance, maxU(n), FALSE_ );
01691 if (! n->strV0)
01692 n->strV0 = IsCurveStraight( n, tolerance, 0, TRUE_ );
01693 if (! n->strVn)
01694 n->strVn = IsCurveStraight( n, tolerance, maxV(n), TRUE_ );
01695
01696
01697
01698 straight = TRUE_;
01699 if ( (! n->flatU) && (n->strV0) && (n->strVn) )
01700 for (i = 1;
01701 (i < maxV(n)) && (straight = IsCurveStraight( n, tolerance, i, TRUE_ ));
01702 i++);
01703
01704 if (straight && n->strV0 && n->strVn)
01705 n->flatU = TRUE_;
01706
01707 straight = TRUE_;
01708 if ( (! n->flatV) && (n->strU0) && (n->strUn) )
01709 for (i = 1;
01710 (i < maxU(n)) && (straight = IsCurveStraight( n, tolerance, i, FALSE_ ));
01711 i++);
01712
01713 if (straight && n->strU0 && n->strUn)
01714 n->flatV = TRUE_;
01715
01716 if ( (! n->flatV) || (! n->flatU) )
01717 return( FALSE_ );
01718
01719
01720
01721 n->render->screenProject( (n->points(0,0)), cp00 );
01722 n->render->screenProject( (n->points(0,maxU(n))), cp0n );
01723 n->render->screenProject( (n->points(maxV(n),0)), cpn0 );
01724 n->render->screenProject( (n->points(maxV(n),maxU(n))), cpnn );
01725
01726 cp0n -= cp00 ;
01727 cpn0 -= cp00 ;
01728
01729
01730
01731
01732
01733
01734 planeEqn = crossProduct(cpn0,cp0n) ;
01735 planeEqn = planeEqn.unitLength() ;
01736
01737 d = planeEqn * cp00 ;
01738 dist = fabs( ( planeEqn * cpnn ) - d );
01739
01740 if ( dist > tolerance )
01741 return( FALSE_ );
01742 else
01743 return( TRUE_ );
01744 }
01745
01746
01747
01748
01749 template <class T>
01750 void EmitTriangles( NurbSurface<T> * n )
01751 {
01752 Point_nD<T,3> vecnn, vec0n;
01753 T len2nn, len20n;
01754 T u0, un, v0, vn;
01755
01756
01757
01758
01759
01760
01761 vecnn = n->c00.point - n->cnn.point ;
01762 vec0n = n->c0n.point - n->cn0.point ;
01763
01764 len2nn = norm2(vecnn) ;
01765 len20n = norm2(vec0n) ;
01766
01767 if (maximum(len2nn, len20n) < n->epsilon)
01768 return;
01769
01770
01771
01772
01773 u0 = n->kvU[n->orderU-1];
01774 un = n->kvU[n->numU];
01775 v0 = n->kvV[n->orderV-1];
01776 vn = n->kvV[n->numV];
01777 n->c00.u = u0; n->c00.v = v0;
01778 n->c0n.u = un; n->c0n.v = v0;
01779 n->cn0.u = u0; n->cn0.v = vn;
01780 n->cnn.u = un; n->cnn.v = vn;
01781
01782
01783
01784
01785 if ((n->c00.normLen == 0.0) || (n->cnn.normLen == 0.0) || (n->cn0.normLen == 0.0))
01786 FixNormals( &(n->c00), &(n->cnn), &(n->cn0) );
01787 if (n->c0n.normLen == 0.0)
01788 FixNormals( &(n->c00), &(n->c0n), &(n->cnn) );
01789
01790 if ( len2nn < len20n )
01791 {
01792 n->render->drawTriangle( n->c00, n->cnn, n->cn0 );
01793 n->render->drawTriangle( n->c00, n->c0n, n->cnn );
01794 }
01795 else
01796 {
01797 n->render->drawTriangle( n->c0n, n->cnn, n->cn0 );
01798 n->render->drawTriangle( n->c0n, n->cn0, n->c00 );
01799 }
01800 }
01801
01802
01803
01804
01805
01806
01807 template <class T> void
01808 DoSubdivision( NurbSurface<T> * n, T tolerance, BOOL dirflag, int level )
01809 {
01810 NurbSurface<T> *left, *right;
01811
01812 left = new NurbSurface<T>;
01813 right = new NurbSurface<T>;
01814
01815 if (TestFlat( n, tolerance ))
01816 {
01817 EmitTriangles( n );
01818 }
01819 else
01820 {
01821 if ( ((! n->flatV) && (! n->flatU)) || ((n->flatV) && (n->flatU)) )
01822 dirflag = !dirflag;
01823 else
01824 {
01825 if (n->flatU)
01826 dirflag = FALSE_;
01827 else
01828 dirflag = TRUE_;
01829 }
01830 SplitSurface( n, left, right, dirflag );
01831 DoSubdivision( left, tolerance, dirflag, level + 1 );
01832 DoSubdivision( right, tolerance, dirflag, level + 1 );
01833 FreeNurb( left );
01834 FreeNurb( right );
01835 }
01836 }
01837
01838
01839
01840 template <class T> void
01841 DrawSubdivision( NurbSurface<T> * surf, T tolerance )
01842 {
01843 surf->flatV = FALSE_;
01844 surf->flatU = FALSE_;
01845 surf->strU0 = FALSE_;
01846 surf->strUn = FALSE_;
01847 surf->strV0 = FALSE_;
01848 surf->strVn = FALSE_;
01849
01850
01851
01852
01853
01854 DIVW( &(surf->points(0,0)), &surf->c00.point );
01855 DIVW( &(surf->points(0,surf->numU-1)), &surf->c0n.point );
01856 DIVW( &(surf->points(surf->numV-1,0)), &surf->cn0.point );
01857 DIVW( &(surf->points(surf->numV-1,surf->numU-1)), &surf->cnn.point );
01858
01859 GetNormal( surf, 0, 0 );
01860 GetNormal( surf, 0, maxU(surf) );
01861 GetNormal( surf, maxV(surf), 0 );
01862 GetNormal( surf, maxV(surf), maxU(surf) );
01863
01864 RenderMesh<T> *render ;
01865
01866 render = surf->render ;
01867 render->drawHeader();
01868 DoSubdivision( surf, tolerance, TRUE_, 0 );
01869
01870 render->drawFooter();
01871 }
01872
01881 template <class T>
01882 SurfSample<T>& SurfSample<T>::operator=(const SurfSample<T>& s) {
01883 point = s.point ;
01884 normal = s.normal ;
01885 normLen = s.normLen ;
01886 u = s.u ;
01887 v = s.v ;
01888 return *this ;
01889 }
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920 }
01921
01922 #endif // #define PLIB_NURBS_NURBSSUB_SOURCE