00001 #include <esg/Definitions.h>
00002 #include <esg/geometry/Polygon.h>
00003 #include <esg/mesh/PolygonMesh.h>
00004
00005 using namespace esg;
00006
00007 Mesh* esg::Polygon::_mesh(int) const
00008 {
00009 Mesh *tmp_polyg;
00010 #if defined(_MSC_VER)
00011 unsigned *indices = new unsigned [_nVert];
00012 #else
00013 unsigned indices [_nVert];
00014 #endif
00015
00016 for (unsigned i = 0; i < _nVert; i++) indices[i] = i;
00017
00018 if (haveVertNormals()) {
00019 tmp_polyg = (Mesh*) new PolygonMesh(_vertices,
00020 indices,
00021 _nVert,
00022 _normals,
00023 indices,
00024 _normal,
00025 _fxyz);
00026 #if defined(_MSC_VER)
00027 delete [] indices;
00028 #endif
00029 return tmp_polyg;
00030 } else {
00031 tmp_polyg = (Mesh*) new PolygonMesh(_vertices,
00032 indices,
00033 _nVert,
00034 NULL,
00035 NULL,
00036 _normal,
00037 _fxyz);
00038 #if defined(_MSC_VER)
00039 delete [] indices;
00040 #endif
00041 return tmp_polyg;
00042 }
00043 }
00044
00045 void esg::Polygon::_duplicate_attributes(const Geometry& src)
00046 {
00047 Geometry::_duplicate_attributes(src);
00048
00049 _nVert = ((Polygon&)src)._nVert;
00050
00051 _vertices = new Vector3 [_nVert];
00052 for (unsigned i = 0; i < _nVert; i++)
00053 _vertices[i].set(((Polygon&)src)._vertices[i]);
00054
00055 if (((Polygon&)src)._normals) {
00056 _normals = new Vector3 [_nVert];
00057 for (unsigned i = 0; i < _nVert; i++)
00058 _normals[i].set(((Polygon&)src)._normals[i]);
00059 } else
00060 _normals = NULL;
00061
00062 if (((Polygon&)src)._uvCoords) {
00063 _uvCoords = new Vector2 [_nVert];
00064 for (unsigned i = 0; i < _nVert; i++)
00065 _uvCoords[i].set(((Polygon&)src)._uvCoords[i]);
00066 } else
00067 _uvCoords = NULL;
00068
00069 _normal.set(((Polygon&)src)._normal);
00070 _normalFixed = ((Polygon&)src)._normalFixed;
00071
00072 _fxyz = ((Polygon&)src)._fxyz;
00073
00074 _edgeProjection = ((Polygon&)src)._edgeProjection;
00075
00076 _proj = NULL;
00077 _area = ((Polygon&)src)._area;
00078 }
00079
00080 Vector3 esg::Polygon::_get_facet_normal() const
00081 {
00082 Vector3 result;
00083 result.cross(_get_vertex(1) - _get_vertex(0),
00084 _get_vertex(_nVert-1) - _get_vertex(0));
00085 result.normalize();
00086 return result;
00087 }
00088
00089 Vertex3 esg::Polygon::_get_vertex(unsigned index) const
00090 {
00091 return _vertices[index];
00092 }
00093
00094 Vertex3 esg::Polygon::_get_vert_normal(unsigned index) const
00095 {
00096 return _normals[index];
00097 }
00098
00099 Vertex2 esg::Polygon::_get_vert_uv_coord(unsigned index) const
00100 {
00101 return _uvCoords[index];
00102 }
00103
00104 void esg::Polygon::_set_edge_projection(void)
00105 {
00106
00107 Vector3 absNorm(_normal);
00108 absNorm.absolute();
00109 if (absNorm.x >= absNorm.y && absNorm.x >= absNorm.z)
00110 _edgeProjection = YZ;
00111 else if (absNorm.y >= absNorm.x && absNorm.y >= absNorm.z)
00112 _edgeProjection = XZ;
00113 else
00114 _edgeProjection = XY;
00115 }
00116
00117 double (*esg::Polygon::_precompute_proj(void)) [6]
00118 {
00119 double (*proj)[6] = new double [_nVert-2][6];
00120 double aux;
00121 Vector3 v0(_get_vertex(0));
00122 for (register unsigned i = 2; i < _nVert; i++) {
00123 switch (_edgeProjection) {
00124 case XY:
00125 proj[i-2][0] = _get_vertex(i-1).x - v0.x;
00126 proj[i-2][1] = _get_vertex(i-1).y - v0.y;
00127 proj[i-2][2] = _get_vertex(i).x - v0.x;
00128 proj[i-2][3] = _get_vertex(i).y - v0.y;
00129 break;
00130 case YZ:
00131 proj[i-2][0] = _get_vertex(i-1).y - v0.y;
00132 proj[i-2][1] = _get_vertex(i-1).z - v0.z;
00133 proj[i-2][2] = _get_vertex(i).y - v0.y;
00134 proj[i-2][3] = _get_vertex(i).z - v0.z;
00135 break;
00136 case XZ:
00137 proj[i-2][0] = _get_vertex(i-1).x - v0.x;
00138 proj[i-2][1] = _get_vertex(i-1).z - v0.z;
00139 proj[i-2][2] = _get_vertex(i).x - v0.x;
00140 proj[i-2][3] = _get_vertex(i).z - v0.z;
00141 break;
00142 case NONE_PROJ:
00143 delete [] proj;
00144 return NULL;
00145 }
00146 aux = proj[i-2][3] * proj[i-2][0] - proj[i-2][2] * proj[i-2][1];
00147 proj[i-2][4] = proj[i-2][0] / aux;
00148 proj[i-2][5] = proj[i-2][1] / aux;
00149 }
00150
00151 return proj;
00152 }
00153
00154 bool esg::Polygon::_separation_by_plane(const Geometry& geom) const
00155 {
00156 Interval ext = geom.extent(_normal);
00157 if (ext.min <= _fxyz && _fxyz <= ext.max) return true;
00158 else return false;
00159 }
00160
00161 bool esg::Polygon::_separation_by_edges(Geometry& geom) const
00162 {
00163 PointEnv pointEnv1, pointEnv2;
00164 Vector3 ray1;
00165 Vector3 ray2;
00166
00167 for (register unsigned i = 0; i < _nVert; i++) {
00168 Vector3 edge(_get_vertex((i+1)%_nVert) - _get_vertex(i));
00169
00170 ray1.set(edge);
00171 ray1.normalize();
00172 ray2.set(ray1);
00173 ray2.negate();
00174
00175 geom.rayIntersection(&pointEnv1,
00176 ENV_WANT_INTERSECTION,
00177 _get_vertex(i),
00178 ray1);
00179 geom.rayIntersection(&pointEnv2,
00180 ENV_WANT_INTERSECTION,
00181 _get_vertex(i),
00182 ray2);
00183
00184 if ((pointEnv1.mask & ENV_HAVE_INTERSECTION) &&
00185 (pointEnv2.mask& ENV_HAVE_INTERSECTION)) return false;
00186
00187 if ((pointEnv1.mask & ENV_HAVE_INTERSECTION) &&
00188 (ray1.dot(pointEnv1.intersection) <= edge.length())) return false;
00189
00190 if ((pointEnv2.mask & ENV_HAVE_INTERSECTION) &&
00191 (ray2.dot(pointEnv2.intersection) <= edge.length())) return false;
00192 }
00193
00194 return true;
00195 }
00196
00197 bool esg::Polygon::_point_inside_polygon(const Vector3& v, Vector3* n, Vector2* uv)
00198 {
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 float alpha = 0.0, beta = 0.0;
00210 float ux = 0.0, vx = 0.0;
00211 Vector3 v0(_get_vertex(0));
00212
00213 switch (_edgeProjection) {
00214 case XY: ux = v.x - v0.x; vx = v.y - v0.y; break;
00215 case YZ: ux = v.y - v0.y; vx = v.z - v0.z; break;
00216 case XZ: ux = v.x - v0.x; vx = v.z - v0.z; break;
00217 case NONE_PROJ: return false;
00218 }
00219
00220 if (!_proj) _proj = _precompute_proj();
00221
00222 register unsigned i = 0;
00223 register double* p = &_proj[0][0];
00224 do {
00225 if (*p != 0.) {
00226 beta = vx * *(p+4) - ux * *(p+5);
00227 if ((beta >= 0.) && (beta <= 1.)) {
00228 alpha = (ux - beta * *(p+2)) / *p;
00229 if ((alpha >= 0.) && ((alpha+beta) <= 1.)) break;
00230 }
00231 } else {
00232 beta = ux / *(p+2);
00233 if ((beta >= 0.) && (beta <= 1.)) {
00234 alpha = (vx - beta * *(p+3)) / *(p+1);
00235 if ((alpha >= 0.) && ((alpha+beta) <= 1.)) break;
00236 }
00237 }
00238 if (++i >= _nVert-2) return false;
00239 p += 6;
00240 } while (true);
00241
00242
00243
00244
00245 if (n) {
00246 n->set(_get_vert_normal(0) * (1.0 - alpha - beta));
00247 n->add(_get_vert_normal(i+1) * alpha);
00248 n->add(_get_vert_normal(i+2) * beta);
00249 }
00250
00251 if (uv) {
00252 uv->set(_get_vert_uv_coord(0) * (1.0 - alpha - beta));
00253 uv->add(_get_vert_uv_coord(i+1) * alpha);
00254 uv->add(_get_vert_uv_coord(i+2) * beta);
00255 }
00256
00257 return true;
00258 }
00259
00260
00261
00262
00263 #define ESG_EDGE_EDGE_TEST(V0,U0,U1) \
00264 switch (_edgeProjection) { \
00265 case Polygon::XY: Bx=U0.x-U1.x;By=U0.y-U1.y;Cx=V0.x-U0.x;Cy=V0.y-U0.y;break;\
00266 case Polygon::YZ: Bx=U0.y-U1.y;By=U0.z-U1.z;Cx=V0.y-U0.y;Cy=V0.z-U0.z;break;\
00267 case Polygon::XZ: Bx=U0.x-U1.x;By=U0.z-U1.z;Cx=V0.x-U0.x;Cy=V0.z-U0.z;break;\
00268 case Polygon::NONE_PROJ: return false; \
00269 } \
00270 f = Ay*Bx-Ax*By; \
00271 d = By*Cx-Bx*Cy; \
00272 if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) \
00273 { \
00274 e=Ax*Cy-Ay*Cx; \
00275 if(f>0) \
00276 { \
00277 if(e>=0 && e<=f) return true; \
00278 } \
00279 else \
00280 { \
00281 if(e<=0 && e>=f) return true; \
00282 } \
00283 }
00284
00285 #define ESG_EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
00286 { \
00287 double Ax=0.0,Ay=0.0,Bx=0.0,By=0.0,Cx=0.0,Cy=0.0,e,d,f; \
00288 switch (p._edgeProjection) { \
00289 case Polygon::XY: Ax = V1.x - V0.x; Ay = V1.y - V0.y; break; \
00290 case Polygon::YZ: Ax = V1.y - V0.y; Ay = V1.z - V0.z; break; \
00291 case Polygon::XZ: Ax = V1.x - V0.x; Ay = V1.z - V0.z; break; \
00292 case Polygon::NONE_PROJ: return false; \
00293 } \
00294 \
00295 ESG_EDGE_EDGE_TEST(V0,U0,U1); \
00296 \
00297 ESG_EDGE_EDGE_TEST(V0,U1,U2); \
00298 \
00299 ESG_EDGE_EDGE_TEST(V0,U2,U0); \
00300 }
00301
00302 bool esg::Polygon::_coplanar_tri_collision(Polygon& p,
00303 const Vector3& v0,
00304 const Vector3& v1,
00305 const Vector3& v2,
00306 const Vector3& u0,
00307 const Vector3& u1,
00308 const Vector3& u2)
00309 {
00310 ESG_EDGE_AGAINST_TRI_EDGES(v0,v1,u0,u1,u2);
00311 ESG_EDGE_AGAINST_TRI_EDGES(v1,v2,u0,u1,u2);
00312 ESG_EDGE_AGAINST_TRI_EDGES(v2,v0,u0,u1,u2);
00313
00314
00315 if (_point_inside_polygon(v0, NULL, NULL)) return true;
00316 if (p._point_inside_polygon(u0, NULL, NULL)) return true;
00317 return false;
00318 }
00319
00320 #undef ESG_EDGE_EDGE_TEST
00321 #undef ESG_AGAINST_TRI_EDGES
00322
00323
00324 #define ESG_COMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \
00325 { \
00326 if(D0D1 > 0.0f) { \
00327 \
00328 \
00329 \
00330 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
00331 } else if(D0D2>0.0f) { \
00332 \
00333 A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
00334 } else if(D1*D2>0.0f || D0!=0.0f) { \
00335 \
00336 A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \
00337 } else if(D1!=0.0f) { \
00338 A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
00339 } else if(D2!=0.0f) { \
00340 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
00341 } else { \
00342 \
00343 return _coplanar_tri_collision(p, \
00344 p2Vertex0,p2Vertex1,p2Vertex2, \
00345 p2Vertex0,p2Vertex1,p2Vertex2);\
00346 } \
00347 }
00348
00349 #define ESG_SORT(a,b) if (a>b) { double c; c=a; a=b; b=c; }
00350
00351 int esg::Polygon::_triTriCollision(Polygon& p)
00352 {
00353 if (_nVert < 3 || p.numVertices() < 3) return -1;
00354
00355 double du0,du1,du2,dv0,dv1,dv2;
00356 Vector3 D;
00357 Vertex3 p1Vertex0(_get_vertex(0));
00358 Vertex3 p1Vertex1(_get_vertex(1));
00359 Vertex3 p1Vertex2(_get_vertex(2));
00360 Vertex3 p2Vertex0(p._get_vertex(0));
00361 Vertex3 p2Vertex1(p._get_vertex(1));
00362 Vertex3 p2Vertex2(p._get_vertex(2));
00363 double isect1[2], isect2[2];
00364 double du0du1,du0du2,dv0dv1,dv0dv2;
00365 double vp0,vp1,vp2;
00366 double up0,up1,up2;
00367
00368
00369
00370 du0 = p._normal.dot(p1Vertex0) + p._fxyz;
00371 du1 = p._normal.dot(p1Vertex1) + p._fxyz;
00372 du2 = p._normal.dot(p1Vertex2) + p._fxyz;
00373
00374
00375 if (fabs(du0) < Geometry::EPS) du0 = 0.0;
00376 if (fabs(du1) < Geometry::EPS) du1 = 0.0;
00377 if (fabs(du2) < Geometry::EPS) du2 = 0.0;
00378
00379 du0du1 = du0 * du1;
00380 du0du2 = du0 * du2;
00381
00382
00383 if (du0du1 > 0.0 && du0du2 > 0.0) return false;
00384
00385
00386 dv0 = _normal.dot(p2Vertex0) + _fxyz;
00387 dv1 = _normal.dot(p2Vertex1) + _fxyz;
00388 dv2 = _normal.dot(p2Vertex2) + _fxyz;
00389
00390 if (fabs(dv0) < Geometry::EPS) dv0 = 0.0;
00391 if (fabs(dv1) < Geometry::EPS) dv1 = 0.0;
00392 if (fabs(dv2) < Geometry::EPS) dv2 = 0.0;
00393
00394 dv0dv1 = dv0 * dv1;
00395 dv0dv2 = dv0 * dv2;
00396
00397
00398 if (dv0dv1 > 0.0 && dv0dv2 > 0.0) return false;
00399
00400
00401 D.cross(p._normal, _normal);
00402
00403
00404 D.absolute();
00405 if (D.x > D.y) {
00406 if (D.x > D.z) {
00407 vp0 = p2Vertex0.x;
00408 vp1 = p2Vertex1.x;
00409 vp2 = p2Vertex2.x;
00410 up0 = p1Vertex0.x;
00411 up1 = p1Vertex1.x;
00412 up2 = p1Vertex2.x;
00413 } else {
00414 vp0 = p2Vertex0.z;
00415 vp1 = p2Vertex1.z;
00416 vp2 = p2Vertex2.z;
00417 up0 = p1Vertex0.z;
00418 up1 = p1Vertex1.z;
00419 up2 = p1Vertex2.z;
00420 }
00421 } else
00422 if (D.y > D.z) {
00423 vp0 = p2Vertex0.y;
00424 vp1 = p2Vertex1.y;
00425 vp2 = p2Vertex2.y;
00426 up0 = p1Vertex0.y;
00427 up1 = p1Vertex1.y;
00428 up2 = p1Vertex2.y;
00429 } else {
00430 vp0 = p2Vertex0.z;
00431 vp1 = p2Vertex1.z;
00432 vp2 = p2Vertex2.z;
00433 up0 = p1Vertex0.z;
00434 up1 = p1Vertex1.z;
00435 up2 = p1Vertex2.z;
00436 }
00437
00438
00439 double a,b,c,x0,x1;
00440 ESG_COMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1);
00441
00442
00443 double d,e,f,y0,y1;
00444 ESG_COMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1);
00445
00446 double xx,yy,xxyy,tmp;
00447 xx = x0 * x1;
00448 yy = y0 * y1;
00449 xxyy = xx * yy;
00450
00451 tmp = a * xxyy;
00452 isect1[0] = tmp + b * x1 * yy;
00453 isect1[1] = tmp + c * x0 * yy;
00454
00455 tmp = d * xxyy;
00456 isect2[0] = tmp + e * xx * y1;
00457 isect2[1] = tmp + f * xx * y0;
00458
00459 ESG_SORT(isect1[0],isect1[1]);
00460 ESG_SORT(isect2[0],isect2[1]);
00461
00462 return ((isect1[1] < isect2[0] || isect2[1] < isect1[0]) ? false : true);
00463 }
00464
00465 #undef ESG_COMPUTE_INTERVALS
00466 #undef ESG_SORT
00467
00468
00469 void esg::Polygon::_rotateX(float a)
00470 {
00471 Matrix3d trMat;
00472 trMat.rotX(a);
00473 for (unsigned i = 0; i < _nVert; i++) {
00474 trMat.transform(_vertices[i]);
00475 if (haveVertNormals()) trMat.transform(_normals[i]);
00476 }
00477 trMat.transform(_normal);
00478 _set_edge_projection();
00479 if (_proj) { delete [] _proj; _proj = NULL; }
00480 _proj = _precompute_proj();
00481 _fxyz = - _normal.dot(_get_vertex(0));
00482 }
00483
00484 void esg::Polygon::_rotateY(float a)
00485 {
00486 Matrix3d trMat;
00487 trMat.rotY(a);
00488 for (unsigned i = 0; i < _nVert; i++) {
00489 trMat.transform(_vertices[i]);
00490 if (haveVertNormals()) trMat.transform(_normals[i]);
00491 }
00492 trMat.transform(_normal);
00493 _set_edge_projection();
00494 if (_proj) { delete [] _proj; _proj = NULL; }
00495 _fxyz = - _normal.dot(_get_vertex(0));
00496 }
00497
00498 void esg::Polygon::_rotateZ(float a)
00499 {
00500 Matrix3d trMat;
00501 trMat.rotZ(a);
00502 for (unsigned i = 0; i < _nVert; i++) {
00503 trMat.transform(_vertices[i]);
00504 if (haveVertNormals()) trMat.transform(_normals[i]);
00505 }
00506 trMat.transform(_normal);
00507 _set_edge_projection();
00508 if (_proj) { delete [] _proj; _proj = NULL; }
00509 _fxyz = - _normal.dot(_get_vertex(0));
00510 }
00511
00512 void esg::Polygon::_rotate(float a, const Vector3& axis)
00513 {
00514 Matrix4d trMat;
00515 Matrix3d rotMat;
00516 trMat.rotationGL(a, axis);
00517 trMat.get(rotMat);
00518 for (unsigned i = 0; i < _nVert; i++) {
00519 trMat.transform(_vertices[i]);
00520 if (haveVertNormals()) rotMat.transform(_normals[i]);
00521 }
00522 rotMat.transform(_normal);
00523 _set_edge_projection();
00524 if (_proj) { delete [] _proj; _proj = NULL; }
00525 _fxyz = - _normal.dot(_get_vertex(0));
00526 }
00527
00528 void esg::Polygon::_rotate(const Matrix3& rotMat)
00529 {
00530 for (unsigned i = 0; i < _nVert; i++) {
00531 rotMat.transform(_vertices[i]);
00532 if (haveVertNormals()) rotMat.transform(_normals[i]);
00533 }
00534 rotMat.transform(_normal);
00535 _set_edge_projection();
00536 if (_proj) { delete [] _proj; _proj = NULL; }
00537 _fxyz = - _normal.dot(_get_vertex(0));
00538 }
00539
00540 void esg::Polygon::_translate(float x, float y, float z)
00541 {
00542 for (unsigned i = 0; i < _nVert; i++) {
00543 _vertices[i].add(Vector3d(x,y,z));
00544 }
00545 _fxyz = - _normal.dot(_get_vertex(0));
00546 }
00547
00548 void esg::Polygon::_transform(const Matrix4& trMat)
00549 {
00550 Matrix3d rotMat;
00551 trMat.get(rotMat);
00552 for (unsigned i = 0; i < _nVert; i++) {
00553 trMat.transform(_vertices[i]);
00554 if (haveVertNormals()) rotMat.transform(_normals[i]);
00555 }
00556 rotMat.transform(_normal);
00557 _set_edge_projection();
00558 if (_proj) { delete [] _proj; _proj = NULL; }
00559 _fxyz = - _normal.dot(_get_vertex(0));
00560 }
00561
00562 void esg::Polygon::_scale(float s)
00563 {
00564 for (unsigned i = 0; i < _nVert; i++) _vertices[i].scale(s);
00565 if (_proj) { delete [] _proj; _proj = NULL; }
00566
00567 _fxyz *= s;
00568 }
00569
00570
00571
00572
00573
00574 esg::Polygon::Polygon()
00575 {
00576 _vertices = NULL;
00577 _normals = NULL;
00578 _uvCoords = NULL;
00579 _nVert = 0;
00580 _fxyz = 0;
00581 _area = 0;
00582 _proj = NULL;
00583 }
00584
00585 esg::Polygon::Polygon(const Vector3* va,
00586 const Vector3* na,
00587 const Vector2* uva,
00588 unsigned n)
00589 {
00590 _vertices = NULL;
00591 _normals = NULL;
00592 _uvCoords = NULL;
00593 _nVert = n;
00594 _proj = NULL;
00595
00596 (setVertices(va, n) && setNormals(na) && setUVCoords(uva));
00597 }
00598
00599 esg::Polygon::Polygon(const Vector3* va,
00600 const Vector3* na,
00601 const Vector2* uva,
00602 unsigned n,
00603 const Vector3& norm,
00604 bool fixedn)
00605 {
00606 _vertices = NULL;
00607 _normals = NULL;
00608 _uvCoords = NULL;
00609 _nVert = n;
00610 _proj = NULL;
00611
00612 if (setVertices(va, n) && setNormals(na) && setUVCoords(uva))
00613 setFacetNormal(norm, fixedn);
00614 }
00615
00616 esg::Polygon::~Polygon()
00617 {
00618 if (_vertices) delete [] _vertices;
00619 if (_normals) delete [] _normals;
00620 if (_uvCoords) delete [] _uvCoords;
00621 if (_proj) delete [] _proj;
00622 }
00623
00624 void esg::Polygon::rayIntersection(PointEnv* pPE,
00625 int mask,
00626 const Vector3& origin,
00627 const Vector3& direction,
00628 float maxDist)
00629 {
00630 if (!pPE) return;
00631
00632 pPE->mask = ENV_HAVE_NOTHING;
00633
00634 if (_nVert < 3) return;
00635
00636
00637
00638
00639
00640 double& np1 = pPE->nd;
00641 double& no = pPE->no;
00642 double& t = pPE->distance;
00643 Vector3& v = pPE->intersection;
00644
00645 np1 = _normal.dot(direction);
00646 if (fabs(np1) < Geometry::EPS) return;
00647 no = _normal.dot(origin);
00648 t = (no + _fxyz) / -np1;
00649 if (t < Geometry::EPS || t > maxDist) return;
00650
00651 v.set(direction);
00652 v.scaleAdd(t, origin);
00653
00654
00655
00656
00657
00658
00659 Vector3* n = (((mask&ENV_WANT_NORMAL) && haveVertNormals())
00660 ? &(pPE->normal): NULL);
00661 Vector2* uv = (((mask&ENV_WANT_UV_COORD) && haveVertUVCoords())
00662 ? &(pPE->uvCoord) : NULL);
00663
00664 if (!_point_inside_polygon(v, n, uv)) return;
00665
00666 if (n) {
00667 pPE->normalOrientation = PointEnv::OUTWARDS_NORMAL;
00668 pPE->mask |= ENV_HAVE_NORMAL;
00669 } else {
00670 if (mask & ENV_WANT_NORMAL) {
00671
00672
00673 pPE->normal.set(_normal);
00674 if (_normalFixed) pPE->normalOrientation = PointEnv::OUTWARDS_NORMAL;
00675 else pPE->normalOrientation = PointEnv::RANDOM_NORMAL;
00676 pPE->mask |= ENV_HAVE_NORMAL|ENV_HAVE_N_DOT_O|ENV_HAVE_N_DOT_D;
00677 }
00678 }
00679
00680 pPE->mask |= ((uv) ?
00681 ENV_HAVE_INTERFERENCE|ENV_HAVE_N_DOT_O|
00682 ENV_HAVE_INTERSECTION|ENV_HAVE_DISTANCE|ENV_HAVE_UV_COORD :
00683 ENV_HAVE_INTERFERENCE|ENV_HAVE_N_DOT_O|
00684 ENV_HAVE_INTERSECTION|ENV_HAVE_DISTANCE);
00685 }
00686
00687 bool esg::Polygon::mapToUV(const Vector3& v, Vector2& uv)
00688 {
00689 return _point_inside_polygon(v, NULL, &uv);
00690 }
00691
00692 void esg::Polygon::randomSample(int mask, PointEnv& pe, double* pdf)
00693 {
00694 pe.mask = ENV_HAVE_NOTHING;
00695 if (!(mask & ENV_WANT_SURFACE_POINT|ENV_WANT_UV_COORD|ENV_WANT_NORMAL))
00696 return;
00697
00698
00699 Vector3 u(_get_vertex(1)); u.sub(_get_vertex(0)); u.normalize();
00700 Vector3 v; v.cross(u, _normal); v.normalize();
00701 Interval uExt, vExt;
00702 double ud, vd, p0u = 0, p0v = 0;
00703 for (register unsigned i = 0; i < _nVert; i++) {
00704 ud = u.dot(_get_vertex(i));
00705 vd = v.dot(_get_vertex(i));
00706 if (i == 0) { p0u = ud; p0v = vd; }
00707 if (ud > uExt.max) uExt.max = ud;
00708 if (ud < uExt.min) uExt.min = ud;
00709 if (vd > vExt.max) vExt.max = vd;
00710 if (vd < vExt.min) vExt.min = vd;
00711 }
00712
00713 Vector3* n = ((((mask&ENV_WANT_NORMAL) && haveVertNormals())
00714 ? &(pe.normal) : NULL));
00715 Vector2* uv = ((((mask&ENV_WANT_UV_COORD) && haveVertUVCoords())
00716 ? &(pe.uvCoord) : NULL));
00717 Vector3 auxU, auxV;
00718
00719
00720 auxU.set(u);
00721 auxV.set(v);
00722 auxU.scale(uExt.min - p0u);
00723 auxV.scale(vExt.min - p0v);
00724 Vector3 p0(_get_vertex(0));
00725 p0.add(auxU);
00726 p0.add(auxV);
00727
00728 ud = uExt.max - uExt.min;
00729 vd = vExt.max - vExt.min;
00730
00731 do {
00732 auxU.set(u);
00733 auxU.scale(ESG_DBL_RAND * ud);
00734 auxV.set(v);
00735 auxV.scale(ESG_DBL_RAND * vd);
00736 pe.intersection.set(p0);
00737 pe.intersection.add(auxU);
00738 pe.intersection.add(auxV);
00739 } while(!_point_inside_polygon(pe.intersection, n, uv));
00740
00741 if (n) {
00742 pe.normalOrientation = PointEnv::OUTWARDS_NORMAL;
00743 pe.mask |= ENV_HAVE_NORMAL;
00744 } else {
00745 if (mask & ENV_WANT_NORMAL) {
00746
00747
00748 pe.normal.set(_normal);
00749 if (_normalFixed) pe.normalOrientation = PointEnv::OUTWARDS_NORMAL;
00750 else pe.normalOrientation = PointEnv::RANDOM_NORMAL;
00751 pe.mask |= ENV_HAVE_NORMAL;
00752 }
00753 }
00754
00755 pe.mask |= ((uv) ?
00756 ENV_HAVE_INTERFERENCE|ENV_HAVE_INTERSECTION|ENV_HAVE_UV_COORD :
00757 ENV_HAVE_INTERFERENCE|ENV_HAVE_INTERSECTION);
00758
00759 if (pdf) *pdf = 1./_area;
00760 }
00761
00762 bool esg::Polygon::randomDirection(const Vector3& pov, Vector3&, double* pdf)
00763 {
00764 if (_normalFixed && _normal.dot(pov) < _fxyz) return false;
00765 fprintf(stderr,"Polygon::randomDirection(): Not implemented\n");
00766 return false;
00767 }
00768
00769 Interval esg::Polygon::extent(const Vector3& direction) const
00770 {
00771 float vertExt;
00772 Interval retInt;
00773
00774 retInt.min = MAXFLOAT;
00775
00776 retInt.max = - MAXFLOAT;
00777
00778 for (register unsigned i = 0; i < _nVert; i++) {
00779 vertExt = direction.dot(_get_vertex(i));
00780 if (retInt.min > vertExt) retInt.min = vertExt;
00781 if (retInt.max < vertExt) retInt.max = vertExt;
00782 }
00783 return retInt;
00784 }
00785
00786
00787 Geometry* esg::Polygon::clone(const Matrix4* pTrMat) const
00788 {
00789 Polygon* pRet = new Polygon;
00790 pRet->_duplicate_attributes(*this);
00791 if (pTrMat) pRet->_transform(*pTrMat);
00792 return pRet;
00793 }
00794
00795 Vertex3 esg::Polygon::centroid() const
00796 {
00797 Vertex3 pog(0.0, 0.0, 0.0);
00798 for (register unsigned i = 0; i < _nVert; i++) {
00799 Vertex3 aux(_get_vertex(i));
00800 aux.scale(1.0/_nVert);
00801 pog.add(aux);
00802 }
00803 return pog;
00804 }
00805
00806 double esg::Polygon::radius(const Vector3& centroid) const
00807 {
00808 double r = -MAXDOUBLE;
00809 double auxR;
00810 Vector3 auxV;
00811 for (register unsigned i = 0; i < _nVert; i++) {
00812 auxV.set(_get_vertex(i));
00813 auxV.sub(centroid);
00814 auxR = auxV.length();
00815 if (auxR > r) r = auxR;
00816 }
00817 return r;
00818 }
00819
00820 bool esg::Polygon::separation(Geometry& geom, Vector3* pDir)
00821 {
00822 try {
00823 int c = _triTriCollision(dynamic_cast<Polygon&>(geom));
00824 if (c >= 0) return (!c);
00825 } catch (bad_cast) {
00826
00827 }
00828
00829
00830
00831 if (_separation_by_plane(geom)) {
00832 if (pDir) pDir->set(_normal);
00833 return true;
00834 }
00835
00836 if (!_separation_by_edges(geom)) return false;
00837
00838 return false;
00839 }
00840
00841 double esg::Polygon::distance(const Geometry& geom, Vector3* pDir)
00842 {
00843 return MINDOUBLE;
00844 }
00845
00846 void esg::Polygon::dump(const char* intent, const char* tab)
00847 {
00848 printf("%s geometry Polygon {\n", intent);
00849 printf("%s %s numVertices %d\n", intent, tab, _nVert);
00850 if (_normalFixed)
00851 printf("%s %s normal %f %f %f\n", intent, tab, _normal.x, _normal.y, _normal.z);
00852 if (_vertices) {
00853 printf("%s %s vertex [\n", intent, tab);
00854 for (register unsigned i = 0; i < _nVert; i++)
00855 printf("%s %s %s %f %f %f\n", intent, tab, tab, _vertices[i].x, _vertices[i].y, _vertices[i].z);
00856 printf("%s %s ]\n", intent, tab);
00857 }
00858 if (haveVertNormals()) {
00859 printf("%s %s vertexNormal [\n", intent, tab);
00860 for (register unsigned i = 0; i < _nVert; i++)
00861 printf("%s %s %s %f %f %f\n", intent, tab, tab, _normals[i].x, _normals[i].y, _normals[i].z);
00862 printf("%s %s ]\n", intent, tab);
00863 }
00864 if (_uvCoords) {
00865 printf("%s %s uvCoord [\n", intent, tab);
00866 for (register unsigned i = 0; i < _nVert; i++)
00867 printf("%s %s %s %f %f\n", intent, tab, tab, _uvCoords[i].x, _uvCoords[i].y);
00868 printf("%s %s ]\n", intent, tab);
00869 }
00870 printf("%s }\n", intent);
00871 }
00872
00873 Vector3 esg::Polygon::getFacetNormal() const
00874 {
00875 return _normal;
00876 }
00877
00878 bool esg::Polygon::haveFixedNormal() const
00879 {
00880 return _normalFixed;
00881 }
00882
00883 Vertex3 esg::Polygon::getVertex(unsigned index) const
00884 {
00885 return ((index < _nVert) ? _get_vertex(index) : Vertex3(0,0,0));
00886 }
00887
00888 Vertex3 esg::Polygon::getVertNormal(unsigned index) const
00889 {
00890 return ((haveVertNormals() && index < _nVert) ?
00891 _get_vert_normal(index) :
00892 Vertex3(0,0,0));
00893 }
00894
00895 bool esg::Polygon::haveVertNormals() const
00896 {
00897 return (_normals != NULL);
00898 }
00899
00900 Vertex2 esg::Polygon::getVertUVCoord(unsigned index) const
00901 {
00902 return ((haveVertUVCoords() && index < _nVert)
00903 ? _get_vert_uv_coord(index)
00904 : Vertex2(0,0));
00905 }
00906
00907 bool esg::Polygon::haveVertUVCoords() const
00908 {
00909 return (_uvCoords != NULL);
00910 }
00911
00912 unsigned esg::Polygon::numVertices() const
00913 {
00914 return _nVert;
00915 }
00916
00917 double esg::Polygon::getFXYZ() const
00918 {
00919 return _fxyz;
00920 }
00921
00922 esg::Polygon::edgeProjection esg::Polygon::getEdgeProjection() const
00923 {
00924 return _edgeProjection;
00925 }
00926
00927 bool esg::Polygon::setVertices(const Vector3* va, unsigned n)
00928 {
00929 if (_vertices) delete [] _vertices;
00930 if (_normals) delete [] _normals;
00931 if (_uvCoords) delete [] _uvCoords;
00932 if (_proj) delete [] _proj;
00933
00934 _vertices = NULL;
00935 _normals = NULL;
00936 _uvCoords = NULL;
00937 _nVert = n;
00938 _proj = NULL;
00939
00940 if (_nVert > 2) {
00941 _vertices = new Vector3d [_nVert];
00942 for (unsigned i = 0; i < _nVert; i++) _vertices[i].set(va[i]);
00943 _normal.set(_get_facet_normal());
00944 _normalFixed = false;
00945 _fxyz = - _normal.dot(_get_vertex(0));
00946 _set_edge_projection();
00947 } else {
00948 cerr << "setVerices() error: Number of vertices is less then 3" << endl;
00949 return false;
00950 }
00951
00952 #ifndef WIN32
00953 #warning "FIXME: Area of polygon"
00954 #endif
00955 _area = 1;
00956
00957 return true;
00958 }
00959
00960 bool esg::Polygon::setNormals(const Vector3* na)
00961 {
00962 if (_nVert < 3) {
00963 cerr << "setNormals() error: Number of vertices is less then 3" << endl;
00964 return false;
00965 }
00966
00967 if (_normals) {
00968 delete [] _normals;
00969 _normals = NULL;
00970 }
00971
00972 if (na) {
00973 _normals = new Vector3 [_nVert];
00974 for (unsigned i = 0; i < _nVert; i++) _normals[i].set(na[i]);
00975 }
00976
00977 return true;
00978 }
00979
00980 bool esg::Polygon::setUVCoords(const Vector2* uva)
00981 {
00982 if (_nVert < 3) {
00983 cerr << "setUVCoords() error: Number of vertices is less then 3" << endl;
00984 return false;
00985 }
00986
00987 if (_uvCoords) {
00988 delete [] _uvCoords;
00989 _uvCoords = NULL;
00990 }
00991
00992 if (uva) {
00993 _uvCoords = new Vector2 [_nVert];
00994 for (unsigned i = 0; i < _nVert; i++) _uvCoords[i].set(uva[i]);
00995 }
00996
00997 return true;
00998 }
00999
01000 void esg::Polygon::setFacetNormal(const Vector3& norm, bool fixedn)
01001 {
01002 _normal.set(norm);
01003 _normalFixed = fixedn;
01004 _fxyz = - _normal.dot(_get_vertex(0));
01005 _set_edge_projection();
01006 }
01007
01008
01009 void esg::Polygon::__debug()
01010 {
01011
01012
01013 fprintf(stderr,"Polygon vertices:\n");
01014 for (unsigned i = 0; i < _nVert; i++)
01015 fprintf(stderr,"%f %f %f\n",
01016 getVertex(i).x,getVertex(i).y,getVertex(i).z);
01017 fprintf(stderr,"Polygon's normal: %f %f %f\n",_normal.x,_normal.y,_normal.z);
01018 }