1 /* 2 ** License Applicability. Except to the extent portions of this file are 3 ** made subject to an alternative license as permitted in the SGI Free 4 ** Software License B, Version 1.1 (the "License"), the contents of this 5 ** file are subject only to the provisions of the License. You may not use 6 ** this file except in compliance with the License. You may obtain a copy 7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: 9 ** 10 ** http://oss.sgi.com/projects/FreeB 11 ** 12 ** Note that, as provided in the License, the Software is distributed on an 13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS 14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND 15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A 16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 17 ** 18 ** Original Code. The Original Code is: OpenGL Sample Implementation, 19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 21 ** Copyright in any portions created by third parties is as indicated 22 ** elsewhere herein. All Rights Reserved. 23 ** 24 ** Additional Notice Provisions: The application programming interfaces 25 ** established by SGI in conjunction with the Original Code are The 26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released 27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version 28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X 29 ** Window System(R) (Version 1.3), released October 19, 1998. This software 30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation 31 ** published by SGI, but has not been independently verified as being 32 ** compliant with the OpenGL(R) version 1.2.1 Specification. 33 */ 34 35 /* 36 * mesher.c++ 37 * 38 */ 39 40 //#include "glimports.h" 41 //#include "myassert.h" 42 //#include "mystdio.h" 43 //#include "gridvertex.h" 44 //#include "gridtrimvertex.h" 45 //#include "jarcloc.h" 46 //#include "gridline.h" 47 //#include "trimline.h" 48 //#include "uarray.h" 49 #include "backend.h" 50 #include "mesher.h" 51 52 53 const float Mesher::ZERO = 0.0; 54 55 Mesher::Mesher( Backend& b ) 56 : backend( b ), 57 p( sizeof( GridTrimVertex ), 100, "GridTrimVertexPool" ) 58 { 59 stacksize = 0; 60 vdata = 0; 61 last[0] = 0; 62 last[1] = 0; 63 itop = 0; 64 lastedge = 0; //needed to prevent purify UMR 65 } 66 67 Mesher::~Mesher( void ) 68 { 69 if( vdata ) delete[] vdata; 70 } 71 72 void 73 Mesher::init( unsigned int npts ) 74 { 75 p.clear(); 76 if( stacksize < npts ) { 77 stacksize = 2 * npts; 78 if( vdata ) delete[] vdata; 79 vdata = new GridTrimVertex_p[stacksize]; 80 } 81 } 82 83 inline void 84 Mesher::push( GridTrimVertex *gt ) 85 { 86 assert( itop+1 != (int)stacksize ); 87 vdata[++itop] = gt; 88 } 89 90 inline void 91 Mesher::pop( long ) 92 { 93 } 94 95 inline void 96 Mesher::openMesh() 97 { 98 backend.bgntmesh( "addedge" ); 99 } 100 101 inline void 102 Mesher::closeMesh() 103 { 104 backend.endtmesh(); 105 } 106 107 inline void 108 Mesher::swapMesh() 109 { 110 backend.swaptmesh(); 111 } 112 113 inline void 114 Mesher::clearStack() 115 { 116 itop = -1; 117 last[0] = 0; 118 } 119 120 void 121 Mesher::finishLower( GridTrimVertex *gtlower ) 122 { 123 for( push(gtlower); 124 nextlower( gtlower=new(p) GridTrimVertex ); 125 push(gtlower) ) 126 addLower(); 127 addLast(); 128 } 129 130 void 131 Mesher::finishUpper( GridTrimVertex *gtupper ) 132 { 133 for( push(gtupper); 134 nextupper( gtupper=new(p) GridTrimVertex ); 135 push(gtupper) ) 136 addUpper(); 137 addLast(); 138 } 139 140 void 141 Mesher::mesh( void ) 142 { 143 GridTrimVertex *gtlower, *gtupper; 144 145 Hull::init( ); 146 nextupper( gtupper = new(p) GridTrimVertex ); 147 nextlower( gtlower = new(p) GridTrimVertex ); 148 149 clearStack(); 150 openMesh(); 151 push(gtupper); 152 153 nextupper( gtupper = new(p) GridTrimVertex ); 154 nextlower( gtlower ); 155 156 assert( gtupper->t && gtlower->t ); 157 158 if( gtupper->t->param[0] < gtlower->t->param[0] ) { 159 push(gtupper); 160 lastedge = 1; 161 if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) { 162 finishLower(gtlower); 163 return; 164 } 165 } else if( gtupper->t->param[0] > gtlower->t->param[0] ) { 166 push(gtlower); 167 lastedge = 0; 168 if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) { 169 finishUpper(gtupper); 170 return; 171 } 172 } else { 173 if( lastedge == 0 ) { 174 push(gtupper); 175 lastedge = 1; 176 if( nextupper(gtupper=new(p) GridTrimVertex) == 0 ) { 177 finishLower(gtlower); 178 return; 179 } 180 } else { 181 push(gtlower); 182 lastedge = 0; 183 if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) { 184 finishUpper(gtupper); 185 return; 186 } 187 } 188 } 189 190 while ( 1 ) { 191 if( gtupper->t->param[0] < gtlower->t->param[0] ) { 192 push(gtupper); 193 addUpper(); 194 if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) { 195 finishLower(gtlower); 196 return; 197 } 198 } else if( gtupper->t->param[0] > gtlower->t->param[0] ) { 199 push(gtlower); 200 addLower(); 201 if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) { 202 finishUpper(gtupper); 203 return; 204 } 205 } else { 206 if( lastedge == 0 ) { 207 push(gtupper); 208 addUpper(); 209 if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) { 210 finishLower(gtlower); 211 return; 212 } 213 } else { 214 push(gtlower); 215 addLower(); 216 if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) { 217 finishUpper(gtupper); 218 return; 219 } 220 } 221 } 222 } 223 } 224 225 inline int 226 Mesher::isCcw( int ilast ) 227 { 228 REAL area = det3( vdata[ilast]->t, vdata[itop-1]->t, vdata[itop-2]->t ); 229 return (area < ZERO) ? 0 : 1; 230 } 231 232 inline int 233 Mesher::isCw( int ilast ) 234 { 235 REAL area = det3( vdata[ilast]->t, vdata[itop-1]->t, vdata[itop-2]->t ); 236 return (area > -ZERO) ? 0 : 1; 237 } 238 239 inline int 240 Mesher::equal( int x, int y ) 241 { 242 return( last[0] == vdata[x] && last[1] == vdata[y] ); 243 } 244 245 inline void 246 Mesher::copy( int x, int y ) 247 { 248 last[0] = vdata[x]; last[1] = vdata[y]; 249 } 250 251 inline void 252 Mesher::move( int x, int y ) 253 { 254 vdata[x] = vdata[y]; 255 } 256 257 inline void 258 Mesher::output( int x ) 259 { 260 backend.tmeshvert( vdata[x] ); 261 } 262 263 /*--------------------------------------------------------------------------- 264 * addedge - addedge an edge to the triangulation 265 * 266 * This code has been re-written to generate large triangle meshes 267 * from a monotone polygon. Although smaller triangle meshes 268 * could be generated faster and with less code, larger meshes 269 * actually give better SYSTEM performance. This is because 270 * vertices are processed in the backend slower than they are 271 * generated by this code and any decrease in the number of vertices 272 * results in a decrease in the time spent in the backend. 273 *--------------------------------------------------------------------------- 274 */ 275 276 void 277 Mesher::addLast( ) 278 { 279 register int ilast = itop; 280 281 if( lastedge == 0 ) { 282 if( equal( 0, 1 ) ) { 283 output( ilast ); 284 swapMesh(); 285 for( register int i = 2; i < ilast; i++ ) { 286 swapMesh(); 287 output( i ); 288 } 289 copy( ilast, ilast-1 ); 290 } else if( equal( ilast-2, ilast-1) ) { 291 swapMesh(); 292 output( ilast ); 293 for( register int i = ilast-3; i >= 0; i-- ) { 294 output( i ); 295 swapMesh(); 296 } 297 copy( 0, ilast ); 298 } else { 299 closeMesh(); openMesh(); 300 output( ilast ); 301 output( 0 ); 302 for( register int i = 1; i < ilast; i++ ) { 303 swapMesh(); 304 output( i ); 305 } 306 copy( ilast, ilast-1 ); 307 } 308 } else { 309 if( equal( 1, 0) ) { 310 swapMesh(); 311 output( ilast ); 312 for( register int i = 2; i < ilast; i++ ) { 313 output( i ); 314 swapMesh(); 315 } 316 copy( ilast-1, ilast ); 317 } else if( equal( ilast-1, ilast-2) ) { 318 output( ilast ); 319 swapMesh(); 320 for( register int i = ilast-3; i >= 0; i-- ) { 321 swapMesh(); 322 output( i ); 323 } 324 copy( ilast, 0 ); 325 } else { 326 closeMesh(); openMesh(); 327 output( 0 ); 328 output( ilast ); 329 for( register int i = 1; i < ilast; i++ ) { 330 output( i ); 331 swapMesh(); 332 } 333 copy( ilast-1, ilast ); 334 } 335 } 336 closeMesh(); 337 //for( register long k=0; k<=ilast; k++ ) pop( k ); 338 } 339 340 void 341 Mesher::addUpper( ) 342 { 343 register int ilast = itop; 344 345 if( lastedge == 0 ) { 346 if( equal( 0, 1 ) ) { 347 output( ilast ); 348 swapMesh(); 349 for( register int i = 2; i < ilast; i++ ) { 350 swapMesh(); 351 output( i ); 352 } 353 copy( ilast, ilast-1 ); 354 } else if( equal( ilast-2, ilast-1) ) { 355 swapMesh(); 356 output( ilast ); 357 for( register int i = ilast-3; i >= 0; i-- ) { 358 output( i ); 359 swapMesh(); 360 } 361 copy( 0, ilast ); 362 } else { 363 closeMesh(); openMesh(); 364 output( ilast ); 365 output( 0 ); 366 for( register int i = 1; i < ilast; i++ ) { 367 swapMesh(); 368 output( i ); 369 } 370 copy( ilast, ilast-1 ); 371 } 372 lastedge = 1; 373 //for( register long k=0; k<ilast-1; k++ ) pop( k ); 374 move( 0, ilast-1 ); 375 move( 1, ilast ); 376 itop = 1; 377 } else { 378 if( ! isCcw( ilast ) ) return; 379 do { 380 itop--; 381 } while( (itop > 1) && isCcw( ilast ) ); 382 383 if( equal( ilast-1, ilast-2 ) ) { 384 output( ilast ); 385 swapMesh(); 386 for( register int i=ilast-3; i>=itop-1; i-- ) { 387 swapMesh(); 388 output( i ); 389 } 390 copy( ilast, itop-1 ); 391 } else if( equal( itop, itop-1 ) ) { 392 swapMesh(); 393 output( ilast ); 394 for( register int i = itop+1; i < ilast; i++ ) { 395 output( i ); 396 swapMesh(); 397 } 398 copy( ilast-1, ilast ); 399 } else { 400 closeMesh(); openMesh(); 401 output( ilast ); 402 output( ilast-1 ); 403 for( register int i=ilast-2; i>=itop-1; i-- ) { 404 swapMesh(); 405 output( i ); 406 } 407 copy( ilast, itop-1 ); 408 } 409 //for( register int k=itop; k<ilast; k++ ) pop( k ); 410 move( itop, ilast ); 411 } 412 } 413 414 void 415 Mesher::addLower() 416 { 417 register int ilast = itop; 418 419 if( lastedge == 1 ) { 420 if( equal( 1, 0) ) { 421 swapMesh(); 422 output( ilast ); 423 for( register int i = 2; i < ilast; i++ ) { 424 output( i ); 425 swapMesh(); 426 } 427 copy( ilast-1, ilast ); 428 } else if( equal( ilast-1, ilast-2) ) { 429 output( ilast ); 430 swapMesh(); 431 for( register int i = ilast-3; i >= 0; i-- ) { 432 swapMesh(); 433 output( i ); 434 } 435 copy( ilast, 0 ); 436 } else { 437 closeMesh(); openMesh(); 438 output( 0 ); 439 output( ilast ); 440 for( register int i = 1; i < ilast; i++ ) { 441 output( i ); 442 swapMesh(); 443 } 444 copy( ilast-1, ilast ); 445 } 446 447 lastedge = 0; 448 //for( register long k=0; k<ilast-1; k++ ) pop( k ); 449 move( 0, ilast-1 ); 450 move( 1, ilast ); 451 itop = 1; 452 } else { 453 if( ! isCw( ilast ) ) return; 454 do { 455 itop--; 456 } while( (itop > 1) && isCw( ilast ) ); 457 458 if( equal( ilast-2, ilast-1) ) { 459 swapMesh(); 460 output( ilast ); 461 for( register int i=ilast-3; i>=itop-1; i--) { 462 output( i ); 463 swapMesh( ); 464 } 465 copy( itop-1, ilast ); 466 } else if( equal( itop-1, itop) ) { 467 output( ilast ); 468 swapMesh(); 469 for( register int i=itop+1; i<ilast; i++ ) { 470 swapMesh( ); 471 output( i ); 472 } 473 copy( ilast, ilast-1 ); 474 } else { 475 closeMesh(); openMesh(); 476 output( ilast-1 ); 477 output( ilast ); 478 for( register int i=ilast-2; i>=itop-1; i-- ) { 479 output( i ); 480 swapMesh( ); 481 } 482 copy( itop-1, ilast ); 483 } 484 //for( register int k=itop; k<ilast; k++ ) pop( k ); 485 move( itop, ilast ); 486 } 487 } 488 489 490