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
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
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
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
00055
00056
00057 _pSurface = new Surface(ss,
00058 new AutoArray<Vertex3>(vertices),
00059 sSize*tSize,
00060 new AutoArray<Vertex3>(normals),
00061 sSize*tSize,
00062 NULL,
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
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
00084
00085
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
00105
00106
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 }