NurbsSurface.cc

Go to the documentation of this file.
00001 #include <esg/geometry/NurbsSurface.h>
00002 #include <esg/AutoArray.h>
00003 
00004 using namespace esg;
00005 
00006 void NurbsSurface::_triangulate_surface(const ON_NurbsSurface& surface,
00007                                         const SDS&             ss,
00008                                         AutoPtr<Intersector>*  pAutoInt)
00009 {
00010     ON_3dPoint    ONPoint;
00011     ON_3dVector   ONNormal;
00012     const double* s_knots = surface.Knot(0);
00013     const double* t_knots = surface.Knot(1);
00014     int           sn      = surface.KnotCount(0);
00015     int           tn      = surface.KnotCount(1);
00016     int           sSize;
00017     int           tSize;
00018     int           i,j,k,l;
00019 
00020     // count points of non-empty intervals:
00021     sSize = (tSize = 0);
00022     i = 0; while (i < sn) { i += surface.KnotMultiplicity(0,i); sSize++; }
00023     i = 0; while (i < tn) { i += surface.KnotMultiplicity(1,i); tSize++; }
00024 
00025     //    fprintf(stderr,"s,t: %i %i\n",sSize, tSize);
00026 
00027     Vector3* vertices = new Vector3 [sSize * tSize];
00028     Vector3* normals  = new Vector3 [sSize * tSize];
00029 
00030     i = 0;
00031     k = 0;
00032     while (k < sSize) {
00033         i += surface.KnotMultiplicity(0,i) - 1;
00034         j = 0;
00035         l = 0;
00036         while (l < tSize) {
00037             j += surface.KnotMultiplicity(1,j) - 1;
00038             if (surface.EvNormal(s_knots[i],t_knots[j],ONPoint,ONNormal)) {
00039                 //fprintf(stderr,"p,v: %i, %f %f %f\n",k*tSize+l,ONPoint.x,ONPoint.y,ONPoint.z);
00040                 vertices[k*tSize+l].set(ONPoint.x,ONPoint.y,ONPoint.z);
00041                 normals [k*tSize+l].set(ONNormal.x,ONNormal.y,ONNormal.z);
00042             } else {
00043                 vertices[k*tSize+l].set(0,0,0);
00044                 normals [k*tSize+l].set(0,0,0);
00045             }
00046             l++;
00047             j++;
00048         }
00049         k++;
00050         i++;
00051     }
00052 
00053     /*
00054      * Now we have 1D array of vertices and their nornals.
00055      * Then let's create new trianguleted surface.
00056      */
00057     _pSurface = new Surface(ss,
00058                             new AutoArray<Vertex3>(vertices),
00059                             sSize*tSize,
00060                             new AutoArray<Vertex3>(normals),
00061                             sSize*tSize,
00062                             NULL,  // to do: UV coordinates mapping from NURBS
00063                             0,
00064                             Surface::TRIANGLES,
00065                             pAutoInt,
00066                             true);
00067     if (!_pSurface) {
00068         fprintf(stderr, "NurbsSurface Error: Failed to create triangulated surface\n");
00069         return;
00070     }
00071 
00072     /*
00073      * Append all non-degenerated triangles into the mesh object.
00074      */
00075     unsigned indices [3];
00076     Vector3  normal;
00077     for (int i = 0; i < sSize-1; i++) {
00078         for (int j = 0; j < tSize-1; j++) {
00079             indices[0] = ( i    * tSize) + j;
00080             indices[1] = ((i+1) * tSize) + j;
00081             indices[2] = ((i+1) * tSize) + j+1;
00082 
00083             //indices[0] = ( i    * tSize) + j;
00084             //indices[1] = ( i    * tSize) + j+1;
00085             //indices[2] = ((i+1) * tSize) + j+1;
00086 
00087             if (vertices[indices[0]] != vertices[indices[1]] &&
00088                 vertices[indices[0]] != vertices[indices[2]] &&
00089                 vertices[indices[1]] != vertices[indices[2]])
00090             {
00091                 normal.cross(vertices[indices[1]] - vertices[indices[0]],
00092                              vertices[indices[2]] - vertices[indices[0]]);
00093                 if (normal.dot(normals[indices[0]]) < 0) normal.negate();
00094                 _pSurface->normal(normal);
00095                 _pSurface->vertex(indices[0], indices[0]);
00096                 _pSurface->vertex(indices[1], indices[1]);
00097                 _pSurface->vertex(indices[2], indices[2]);
00098             }
00099 
00100             indices[0] = ( i    * tSize) + j;
00101             indices[1] = ((i+1) * tSize) + j+1;
00102             indices[2] = ( i    * tSize) + j+1;
00103             
00104             //indices[0] = ( i    * tSize) + j;
00105             //indices[1] = ((i+1) * tSize) + j+1;
00106             //indices[2] = ((i+1) * tSize) + j;
00107 
00108             if (vertices[indices[0]] != vertices[indices[1]] &&
00109                 vertices[indices[0]] != vertices[indices[2]] &&
00110                 vertices[indices[1]] != vertices[indices[2]])
00111             {
00112                 normal.cross(vertices[indices[1]] - vertices[indices[0]],
00113                              vertices[indices[2]] - vertices[indices[0]]);
00114                 if (normal.dot(normals[indices[0]]) < 0) normal.negate();
00115                 _pSurface->normal(normal);
00116                 _pSurface->vertex(indices[0], indices[0]);
00117                 _pSurface->vertex(indices[1], indices[1]);
00118                 _pSurface->vertex(indices[2], indices[2]);
00119             }
00120         }
00121     }
00122 
00123     _pSurface->done();
00124 }
00125 
00126 Mesh* NurbsSurface::_mesh(int density) const
00127 {
00128     if (!_pSurface) {
00129         fprintf(stderr, "NurbsSurface Error: No surface to create mesh\n");
00130         return NULL;
00131     } else 
00132         return _pSurface->mesh(density);
00133 }
00134 
00135 void NurbsSurface::_duplicate_attributes (const Geometry& src)
00136 {
00137     Geometry::_duplicate_attributes(src);
00138 
00139     if (((NurbsSurface&)src)._pSurface)
00140         _pSurface = (Surface*) ((NurbsSurface&)src)._pSurface->clone(NULL);
00141     else
00142         _pSurface = NULL;
00143 }
00144 
00145 void NurbsSurface::_rotateX(float angle)
00146 {
00147     if (_pSurface) _pSurface->_rotateX(angle);
00148 }
00149 
00150 void NurbsSurface::_rotateY(float angle)
00151 {
00152     if (_pSurface) _pSurface->_rotateY(angle);
00153 }
00154 
00155 void NurbsSurface::_rotateZ(float angle)
00156 {
00157     if (_pSurface) _pSurface->_rotateZ(angle);
00158 }
00159 
00160 void NurbsSurface::_rotate(float angle, const Vector3& axis)
00161 {
00162     if (_pSurface) _pSurface->_rotate(angle, axis);
00163 }
00164 
00165 void NurbsSurface::_rotate(const Matrix3& mat)
00166 {
00167     if (_pSurface) _pSurface->_rotate(mat);
00168 }
00169 
00170 void NurbsSurface::_translate(float x, float y, float z)
00171 {
00172     if (_pSurface) _pSurface->_translate(x,y,z);
00173 }
00174 
00175 void NurbsSurface::_transform(const Matrix4& mat)
00176 {
00177     if (_pSurface) _pSurface->_transform(mat);
00178 }
00179 
00180 void NurbsSurface::_scale(float s)
00181 {
00182     if (_pSurface) _pSurface->_scale(s);
00183 }
00184 
00185 
00186 
00187 NurbsSurface::NurbsSurface(const SDS&            ss,
00188                            AutoPtr<Intersector>* it,
00189                            int                   dimension,
00190                            bool                  rational,
00191                            int                   order0, 
00192                            int                   order1,
00193                            int                   count0,
00194                            int                   count1)
00195 {
00196 #warning "TODO: Employing NURBS instead of polygonal surface"
00197     ON_NurbsSurface nurbsS(dimension,rational,order0,order1,count0,count1);
00198     _triangulate_surface(nurbsS, ss, it);
00199 }
00200 
00201 NurbsSurface::NurbsSurface(const SDS&             ss,
00202                            AutoPtr<Intersector>*  it,
00203                            const ON_NurbsSurface& sp)
00204 {
00205     _triangulate_surface(sp, ss, it);
00206 }
00207 
00208 NurbsSurface::~NurbsSurface()
00209 {
00210     if (_pSurface)    delete _pSurface;
00211 }
00212 
00213 void NurbsSurface::rayIntersection(PointEnv      * pEnv,
00214                                    int             mask,
00215                                    const Vector3 & origin,
00216                                    const Vector3 & direction, 
00217                                    float           maxD) 
00218 {
00219     if (_pSurface)
00220         _pSurface->rayIntersection(pEnv, mask, origin, direction, maxD);
00221     else 
00222         if (pEnv) pEnv->mask = ENV_HAVE_NOTHING;
00223 }
00224 
00225 bool NurbsSurface::mapToUV(const Vector3& v, Vector2& uv)
00226 {
00227     fprintf(stderr,"NurbsSurface::mapToUV(): Not implemented\n");
00228     return false;
00229 }
00230 
00231 Interval NurbsSurface::extent(const Vector3& dir) const
00232 {
00233     if (_pSurface) return _pSurface->extent(dir);
00234     else {
00235         Interval interval;
00236         interval.min =  MAXFLOAT;
00237         interval.max = -MAXFLOAT;
00238         return interval;
00239     }
00240 }
00241 
00242 Geometry* NurbsSurface::clone(const Matrix4 * pTrMat) const
00243 {
00244   NurbsSurface* pRet = new NurbsSurface();
00245   pRet->_duplicate_attributes(*this);
00246   if (pTrMat) pRet->_transform(*pTrMat);
00247   return pRet;
00248 }
00249 
00250 Vector3 NurbsSurface::centroid() const
00251 {
00252     if (_pSurface) return _pSurface->centroid();
00253     else return Vector3(0,0,0);
00254 }
00255 
00256 double NurbsSurface::radius() const
00257 {
00258     if (_pSurface) return _pSurface->radius();
00259     else return -MAXDOUBLE;
00260 }
00261 
00262 double NurbsSurface::radius(const Vector3& centroid) const
00263 {
00264     if (_pSurface) return _pSurface->radius(centroid);
00265     else return -MAXDOUBLE;
00266 }
00267 
00268 void NurbsSurface::dump(const char* intent, const char* tab)
00269 {
00270     printf("geometry NurbsSurface {\n");
00271     if (_pSurface) _pSurface->dump(intent, tab);
00272     printf("%s }\n", intent);
00273 }

Generated on Wed Jun 28 12:24:31 2006 for esg by  doxygen 1.4.6