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 #include "Teddy/Models/Face.h"
00026 #include "Teddy/Models/Vertex.h"
00027 #include "Teddy/PhysicalComponents/Projection.h"
00028 #include "Teddy/SysSupport/Messages.h"
00029 #include "Teddy/SysSupport/StdIO.h"
00030 #ifndef SWIG
00031 #include <algorithm>
00032 using namespace std;
00033 #endif
00034
00035
00036 namespace Teddy {
00037 namespace Models {
00038
00039
00040 #define FACE_NORMAL_EPSILON (double)(0.0002)
00041
00042
00044 Face::Face()
00045 :
00046 Element(0)
00047 {
00048 }
00049
00051 Face::~Face(){
00052 }
00053
00054
00056 void Face::add( Vertex *v ){
00057 vertices.push_front( v );
00058 v->addFace( this );
00059 }
00060
00061
00063 void Face::add( const float x, const float y, const float z ){
00064 Vertex *v = new Vertex(x,y,z);
00065 vertices.push_front( v );
00066 v->addFace( this );
00067 }
00068
00069
00071 void Face::append( Vertex *v ){
00072 vertices.push_back( v );
00073 v->addFace( this );
00074 }
00075
00076
00078 void Face::append( const float x, const float y, const float z ){
00079 Vertex *v = new Vertex(x,y,z);
00080 vertices.push_back( v );
00081 v->addFace( this );
00082 }
00083
00084
00086 void Face::draw( Projection *p ){
00087 p->beginPolygon();
00088
00089 if( isEnabled(EL_USE_ELEMENT_NORMAL|EL_HAS_ELEMENT_NORMAL) ){
00090 dmsg( M_MAT, "Drawing flat face" );
00091 p->normal( normal );
00092 }else{
00093 dmsg( M_MAT, "Drawing smoothed face" );
00094 }
00095
00096 list<Vertex*>::const_iterator v_it = vertices.begin();
00097 while( v_it != vertices.end() ){
00098 (*v_it)->draw( p );
00099 v_it++;
00100 }
00101
00102 p->end();
00103 }
00104
00105
00136 void Face::smooth( float max_smoothing_angle ){
00137
00138
00139 if( isDisabled(EL_HAS_ELEMENT_NORMAL) ){
00140 makeNormal();
00141 }
00142
00143
00144
00145 if( max_smoothing_angle <= 0 ){
00146 enable ( EL_USE_ELEMENT_NORMAL );
00147 disable( EL_USE_VERTEX_NORMALS );
00148 return;
00149 }
00150
00151 int flat_count = 0;
00152 int share_count = 0;
00153 int smooth_count = 0;
00154 bool flat = true;
00155
00156
00157 list<Vertex*>::iterator v_it = vertices.begin();
00158 while( v_it != vertices.end() ){
00159 Vertex *old_vertex = *v_it;
00160
00161
00162
00163
00164 Vertex *new_vertex = new Vertex( old_vertex );
00165
00166
00167 new_vertex->setNormal( this->getNormal() );
00168
00169
00170
00171
00172
00173 share_count = 1;
00174 smooth_count = 0;
00175 flat_count = 0;
00176 list<Face*>::iterator f_it = old_vertex->getFaces().begin();
00177 while( f_it != old_vertex->getFaces().end() ){
00178 Face *other = *f_it;
00179
00180
00181 if( other == this ){
00182 f_it++;
00183 continue;
00184 }
00185
00186
00187 if( other == NULL ){
00188 emsg( M_MAT, "NULL face in vertex cross-reference" );
00189 f_it++;
00190 continue;
00191 }
00192
00193
00194 if( other->isDisabled(EL_HAS_ELEMENT_NORMAL) ){
00195 other->makeNormal();
00196 }
00197
00198
00199
00200 share_count++;
00201 Vector n1 = this ->getNormal();
00202 Vector n2 = other->getNormal();
00203 float fn_ang = (float)( fabs( n1.angle(n2) ) );
00204 float fn_diff = max_smoothing_angle - fn_ang;
00205
00206
00207 if( fn_ang > FACE_NORMAL_EPSILON && fn_diff > FLT_MIN ){
00208 new_vertex->addNormal( n2 );
00209 smooth_count++;
00210
00211
00212
00213 if( flat == true ){
00214 flat = false;
00215
00216 Vector normal = this->getNormal();
00217 list<Vertex*>::iterator v_it_fix = vertices.begin();
00218 if( v_it_fix != v_it ){
00219 Vertex *v = *v_it_fix;
00220 v->setNormal( normal );
00221 v_it_fix++;
00222 }
00223 }
00224 }else{
00225 flat_count++;
00226 }
00227 f_it++;
00228 }
00229
00230
00231 new_vertex->normNormal();
00232
00233
00234
00235 dmsg( M_VERT,
00236 "Face %ld smoothed vertices %ld flat vertices %ld faces share",
00237 smooth_count,
00238 flat_count,
00239 share_count
00240 );
00241
00242 if( old_vertex->isDisabled(VX_HAS_NORMAL) ){
00243 old_vertex->setNormal( new_vertex->getNormal() );
00244 dmsg( M_VERT,
00245 "Old vertex %ld had no normal, setting it to (%.5f, %.5f, %.5f)",
00246 (unsigned long)(old_vertex),
00247 new_vertex->getNormal().v[0],
00248 new_vertex->getNormal().v[1],
00249 new_vertex->getNormal().v[2]
00250 );
00251 delete new_vertex;
00252 }else{
00253
00254
00255
00256
00257 Vector old_normal = old_vertex->getNormal();
00258 Vector new_normal = new_vertex->getNormal();
00259 float vn_ang = (float)( fabs( old_normal.angle(new_normal) ) );
00260 if( vn_ang > FACE_NORMAL_EPSILON ){
00261 dmsg( M_VERT,
00262 "Old vertex %ld had different %.5f normal, replacing with copy (%.5f, %.5f, %.5f)",
00263 old_vertex,
00264 vn_ang,
00265 new_vertex->getNormal().v[0],
00266 new_vertex->getNormal().v[1],
00267 new_vertex->getNormal().v[2]
00268 );
00269
00270 *v_it = new_vertex;
00271 }else{
00272 dmsg( M_VERT,
00273 "Old vertex %ld had the same normal %.5f",
00274 vn_ang,
00275 old_vertex
00276 );
00277 delete new_vertex;
00278
00279 }
00280
00281
00282 }
00283
00284
00285
00286
00287 v_it++;
00288 }
00289
00290
00291 if( flat == false ){
00292 disable( EL_USE_ELEMENT_NORMAL );
00293 enable ( EL_USE_VERTEX_NORMALS );
00294
00295 list<Vertex*>::iterator v_it_check = vertices.begin();
00296 while( v_it_check != vertices.end() ){
00297 Vertex *check_vertex = *v_it_check;
00298 if( check_vertex->isDisabled(VX_HAS_NORMAL) ){
00299 check_vertex->debug();
00300 dmsg( M_VERT, "This smooth Face has Vertex with no normal!" );
00301 }
00302 v_it_check++;
00303 }
00304 }else{
00305 list<Vertex*>::iterator v_it_check = vertices.begin();
00306 while( v_it_check != vertices.end() ){
00307 Vertex *check_vertex = *v_it_check;
00308 check_vertex->setNormal( this->getNormal() );
00309
00310
00311
00312
00313 v_it_check++;
00314 }
00315
00316
00317 enable( EL_HAS_ELEMENT_NORMAL | EL_USE_ELEMENT_NORMAL );
00318
00319
00320 }
00321 }
00322
00323
00324 #if 0
00325 bool Face::stepCSGFace( GeometryIterator *gi ){
00326 return false;
00327 }
00328
00329
00330 void Face::fillCSGFace( GeometryIterator *gi, CSG_IFace *face ){
00331
00332
00333
00334 }
00335 #endif
00336
00337
00338 };
00339 };
00340
00341
00342
00343 #if 0
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 #ifndef TRIANGULATE_H
00363
00364 #define TRIANGULATE_H
00365
00366
00379
00380
00381
00382 #include <vector>
00383
00384 class Vector2d
00385 {
00386 public:
00387 Vector2d(float x,float y)
00388 {
00389 Set(x,y);
00390 };
00391
00392 float GetX(void) const { return mX; };
00393
00394 float GetY(void) const { return mY; };
00395
00396 void Set(float x,float y)
00397 {
00398 mX = x;
00399 mY = y;
00400 };
00401 private:
00402 float mX;
00403 float mY;
00404 };
00405
00406
00407
00408 typedef std::vector< Vector2d > Vector2dVector;
00409
00410
00411 class Triangulate
00412 {
00413 public:
00414
00415
00416
00417 static bool Process(const Vector2dVector &contour,
00418 Vector2dVector &result);
00419
00420
00421 static float Area(const Vector2dVector &contour);
00422
00423
00424
00425 static bool InsideTriangle(float Ax, float Ay,
00426 float Bx, float By,
00427 float Cx, float Cy,
00428 float Px, float Py);
00429
00430
00431 private:
00432 static bool Snip(const Vector2dVector &contour,int u,int v,int w,int n,int *V);
00433
00434 };
00435
00436
00437 #endif
00438
00439
00440
00441
00442
00443
00444 #include <stdio.h>
00445 #include <stdlib.h>
00446 #include <string.h>
00447 #include <assert.h>
00448
00449 #include "triangulate.h"
00450
00451 static const float EPSILON=0.0000000001f;
00452
00453 float Triangulate::Area(const Vector2dVector &contour)
00454 {
00455
00456 int n = contour.size();
00457
00458 float A=0.0f;
00459
00460 for(int p=n-1,q=0; q<n; p=q++)
00461 {
00462 A+= contour[p].GetX()*contour[q].GetY() - contour[q].GetX()*contour[p].GetY();
00463 }
00464 return A*0.5f;
00465 }
00466
00467
00468
00469
00470
00471 bool Triangulate::InsideTriangle(float Ax, float Ay,
00472 float Bx, float By,
00473 float Cx, float Cy,
00474 float Px, float Py)
00475
00476 {
00477 float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
00478 float cCROSSap, bCROSScp, aCROSSbp;
00479
00480 ax = Cx - Bx; ay = Cy - By;
00481 bx = Ax - Cx; by = Ay - Cy;
00482 cx = Bx - Ax; cy = By - Ay;
00483 apx= Px - Ax; apy= Py - Ay;
00484 bpx= Px - Bx; bpy= Py - By;
00485 cpx= Px - Cx; cpy= Py - Cy;
00486
00487 aCROSSbp = ax*bpy - ay*bpx;
00488 cCROSSap = cx*apy - cy*apx;
00489 bCROSScp = bx*cpy - by*cpx;
00490
00491 return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
00492 };
00493
00494 bool Triangulate::Snip(const Vector2dVector &contour,int u,int v,int w,int n,int *V)
00495 {
00496 int p;
00497 float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
00498
00499 Ax = contour[V[u]].GetX();
00500 Ay = contour[V[u]].GetY();
00501
00502 Bx = contour[V[v]].GetX();
00503 By = contour[V[v]].GetY();
00504
00505 Cx = contour[V[w]].GetX();
00506 Cy = contour[V[w]].GetY();
00507
00508 if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false;
00509
00510 for (p=0;p<n;p++)
00511 {
00512 if( (p == u) || (p == v) || (p == w) ) continue;
00513 Px = contour[V[p]].GetX();
00514 Py = contour[V[p]].GetY();
00515 if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false;
00516 }
00517
00518 return true;
00519 }
00520
00521 bool Triangulate::Process(const Vector2dVector &contour,Vector2dVector &result)
00522 {
00523
00524
00525 int n = contour.size();
00526 if ( n < 3 ) return false;
00527
00528 int *V = new int[n];
00529
00530
00531
00532 if ( 0.0f < Area(contour) )
00533 for (int v=0; v<n; v++) V[v] = v;
00534 else
00535 for(int v=0; v<n; v++) V[v] = (n-1)-v;
00536
00537 int nv = n;
00538
00539
00540 int count = 2*nv;
00541
00542 for(int m=0, v=nv-1; nv>2; )
00543 {
00544
00545 if (0 >= (count--))
00546 {
00547
00548 return false;
00549 }
00550
00551
00552 int u = v ; if (nv <= u) u = 0;
00553 v = u+1; if (nv <= v) v = 0;
00554 int w = v+1; if (nv <= w) w = 0;
00555
00556 if ( Snip(contour,u,v,w,nv,V) )
00557 {
00558 int a,b,c,s,t;
00559
00560
00561 a = V[u]; b = V[v]; c = V[w];
00562
00563
00564 result.push_back( contour[a] );
00565 result.push_back( contour[b] );
00566 result.push_back( contour[c] );
00567
00568 m++;
00569
00570
00571 for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--;
00572
00573
00574 count = 2*nv;
00575 }
00576 }
00577
00578
00579
00580 delete V;
00581
00582 return true;
00583 }
00584
00585
00586
00587
00588
00589
00590
00591 #include <stdio.h>
00592 #include <stdlib.h>
00593 #include <string.h>
00594 #include <assert.h>
00595
00596
00597 #include "triangulate.h"
00598
00599 void main(int argc,char **argv)
00600 {
00601
00602
00603
00604
00605
00606
00607
00608
00609 Vector2dVector a;
00610
00611 a.push_back( Vector2d(0,6));
00612 a.push_back( Vector2d(0,0));
00613 a.push_back( Vector2d(3,0));
00614 a.push_back( Vector2d(4,1));
00615 a.push_back( Vector2d(6,1));
00616 a.push_back( Vector2d(8,0));
00617 a.push_back( Vector2d(12,0));
00618 a.push_back( Vector2d(13,2));
00619 a.push_back( Vector2d(8,2));
00620 a.push_back( Vector2d(8,4));
00621 a.push_back( Vector2d(11,4));
00622 a.push_back( Vector2d(11,6));
00623 a.push_back( Vector2d(6,6));
00624 a.push_back( Vector2d(4,3));
00625 a.push_back( Vector2d(2,6));
00626
00627
00628
00629 Vector2dVector result;
00630
00631
00632 Triangulate::Process(a,result);
00633
00634
00635 int tcount = result.size()/3;
00636
00637 for (int i=0; i<tcount; i++)
00638 {
00639 const Vector2d &p1 = result[i*3+0];
00640 const Vector2d &p2 = result[i*3+1];
00641 const Vector2d &p3 = result[i*3+2];
00642 printf("Triangle %d => (%0.0f,%0.0f) (%0.0f,%0.0f) (%0.0f,%0.0f)\n",i+1,
00643 p1.GetX(),p1.GetY(),p2.GetX(),p2.GetY(),p3.GetX(),p3.GetY());
00644 }
00645
00646 }
00647
00648
00649 #endif
00650