1 /* 2 * Copyright (c) 2002-2008 LWJGL Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. 35 * All rights reserved. 36 */ 37 38 /* 39 ** License Applicability. Except to the extent portions of this file are 40 ** made subject to an alternative license as permitted in the SGI Free 41 ** Software License B, Version 1.1 (the "License"), the contents of this 42 ** file are subject only to the provisions of the License. You may not use 43 ** this file except in compliance with the License. You may obtain a copy 44 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 45 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: 46 ** 47 ** http://oss.sgi.com/projects/FreeB 48 ** 49 ** Note that, as provided in the License, the Software is distributed on an 50 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS 51 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND 52 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A 53 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 54 ** 55 ** NOTE: The Original Code (as defined below) has been licensed to Sun 56 ** Microsystems, Inc. ("Sun") under the SGI Free Software License B 57 ** (Version 1.1), shown above ("SGI License"). Pursuant to Section 58 ** 3.2(3) of the SGI License, Sun is distributing the Covered Code to 59 ** you under an alternative license ("Alternative License"). This 60 ** Alternative License includes all of the provisions of the SGI License 61 ** except that Section 2.2 and 11 are omitted. Any differences between 62 ** the Alternative License and the SGI License are offered solely by Sun 63 ** and not by SGI. 64 ** 65 ** Original Code. The Original Code is: OpenGL Sample Implementation, 66 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 67 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 68 ** Copyright in any portions created by third parties is as indicated 69 ** elsewhere herein. All Rights Reserved. 70 ** 71 ** Additional Notice Provisions: The application programming interfaces 72 ** established by SGI in conjunction with the Original Code are The 73 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released 74 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version 75 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X 76 ** Window System(R) (Version 1.3), released October 19, 1998. This software 77 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation 78 ** published by SGI, but has not been independently verified as being 79 ** compliant with the OpenGL(R) version 1.2.1 Specification. 80 ** 81 ** Author: Eric Veach, July 1994 82 ** Java Port: Pepijn Van Eeckhoudt, July 2003 83 ** Java Port: Nathan Parker Burg, August 2003 84 */ 85 package org.lwjgl.util.glu.tessellation; 86 87 import org.lwjgl.util.glu.GLUtessellator; 88 import org.lwjgl.util.glu.GLUtessellatorCallback; 89 import org.lwjgl.util.glu.GLUtessellatorCallbackAdapter; 90 91 import static org.lwjgl.util.glu.GLU.*; 92 93 public class GLUtessellatorImpl implements GLUtessellator { 94 public static final int TESS_MAX_CACHE = 100; 95 96 private int state; /* what begin/end calls have we seen? */ 97 98 private GLUhalfEdge lastEdge; /* lastEdge->Org is the most recent vertex */ 99 GLUmesh mesh; /* stores the input contours, and eventually 100 the tessellation itself */ 101 102 /*** state needed for projecting onto the sweep plane ***/ 103 104 double[] normal = new double[3]; /* user-specified normal (if provided) */ 105 double[] sUnit = new double[3]; /* unit vector in s-direction (debugging) */ 106 double[] tUnit = new double[3]; /* unit vector in t-direction (debugging) */ 107 108 /*** state needed for the line sweep ***/ 109 110 private double relTolerance; /* tolerance for merging features */ 111 int windingRule; /* rule for determining polygon interior */ 112 boolean fatalError; /* fatal error: needed combine callback */ 113 114 Dict dict; /* edge dictionary for sweep line */ 115 PriorityQ pq; /* priority queue of vertex events */ 116 GLUvertex event; /* current sweep event being processed */ 117 118 /*** state needed for rendering callbacks (see render.c) ***/ 119 120 boolean flagBoundary; /* mark boundary edges (use EdgeFlag) */ 121 boolean boundaryOnly; /* Extract contours, not triangles */ 122 GLUface lonelyTriList; 123 /* list of triangles which could not be rendered as strips or fans */ 124 125 126 127 /*** state needed to cache single-contour polygons for renderCache() */ 128 129 private boolean flushCacheOnNextVertex; /* empty cache on next vertex() call */ 130 int cacheCount; /* number of cached vertices */ 131 CachedVertex[] cache = new CachedVertex[TESS_MAX_CACHE]; /* the vertex data */ 132 133 /*** rendering callbacks that also pass polygon data ***/ 134 private Object polygonData; /* client data for current polygon */ 135 136 private GLUtessellatorCallback callBegin; 137 private GLUtessellatorCallback callEdgeFlag; 138 private GLUtessellatorCallback callVertex; 139 private GLUtessellatorCallback callEnd; 140 // private GLUtessellatorCallback callMesh; 141 private GLUtessellatorCallback callError; 142 private GLUtessellatorCallback callCombine; 143 144 private GLUtessellatorCallback callBeginData; 145 private GLUtessellatorCallback callEdgeFlagData; 146 private GLUtessellatorCallback callVertexData; 147 private GLUtessellatorCallback callEndData; 148 // private GLUtessellatorCallback callMeshData; 149 private GLUtessellatorCallback callErrorData; 150 private GLUtessellatorCallback callCombineData; 151 152 private static final double GLU_TESS_DEFAULT_TOLERANCE = 0.0; 153 // private static final int GLU_TESS_MESH = 100112; /* void (*)(GLUmesh *mesh) */ 154 private static GLUtessellatorCallback NULL_CB = new GLUtessellatorCallbackAdapter(); 155 156 // #define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \ 157 // MAX(sizeof(GLUvertex),sizeof(GLUface)))) 158 GLUtessellatorImpl()159 public GLUtessellatorImpl() { 160 state = TessState.T_DORMANT; 161 162 normal[0] = 0; 163 normal[1] = 0; 164 normal[2] = 0; 165 166 relTolerance = GLU_TESS_DEFAULT_TOLERANCE; 167 windingRule = GLU_TESS_WINDING_ODD; 168 flagBoundary = false; 169 boundaryOnly = false; 170 171 callBegin = NULL_CB; 172 callEdgeFlag = NULL_CB; 173 callVertex = NULL_CB; 174 callEnd = NULL_CB; 175 callError = NULL_CB; 176 callCombine = NULL_CB; 177 // callMesh = NULL_CB; 178 179 callBeginData = NULL_CB; 180 callEdgeFlagData = NULL_CB; 181 callVertexData = NULL_CB; 182 callEndData = NULL_CB; 183 callErrorData = NULL_CB; 184 callCombineData = NULL_CB; 185 186 polygonData = null; 187 188 for (int i = 0; i < cache.length; i++) { 189 cache[i] = new CachedVertex(); 190 } 191 } 192 gluNewTess()193 public static GLUtessellator gluNewTess() 194 { 195 return new GLUtessellatorImpl(); 196 } 197 198 makeDormant()199 private void makeDormant() { 200 /* Return the tessellator to its original dormant state. */ 201 202 if (mesh != null) { 203 Mesh.__gl_meshDeleteMesh(mesh); 204 } 205 state = TessState.T_DORMANT; 206 lastEdge = null; 207 mesh = null; 208 } 209 requireState(int newState)210 private void requireState(int newState) { 211 if (state != newState) gotoState(newState); 212 } 213 gotoState(int newState)214 private void gotoState(int newState) { 215 while (state != newState) { 216 /* We change the current state one level at a time, to get to 217 * the desired state. 218 */ 219 if (state < newState) { 220 if (state == TessState.T_DORMANT) { 221 callErrorOrErrorData(GLU_TESS_MISSING_BEGIN_POLYGON); 222 gluTessBeginPolygon(null); 223 } else if (state == TessState.T_IN_POLYGON) { 224 callErrorOrErrorData(GLU_TESS_MISSING_BEGIN_CONTOUR); 225 gluTessBeginContour(); 226 } 227 } else { 228 if (state == TessState.T_IN_CONTOUR) { 229 callErrorOrErrorData(GLU_TESS_MISSING_END_CONTOUR); 230 gluTessEndContour(); 231 } else if (state == TessState.T_IN_POLYGON) { 232 callErrorOrErrorData(GLU_TESS_MISSING_END_POLYGON); 233 /* gluTessEndPolygon( tess ) is too much work! */ 234 makeDormant(); 235 } 236 } 237 } 238 } 239 gluDeleteTess()240 public void gluDeleteTess() { 241 requireState(TessState.T_DORMANT); 242 } 243 gluTessProperty(int which, double value)244 public void gluTessProperty(int which, double value) { 245 switch (which) { 246 case GLU_TESS_TOLERANCE: 247 if (value < 0.0 || value > 1.0) break; 248 relTolerance = value; 249 return; 250 251 case GLU_TESS_WINDING_RULE: 252 int windingRule = (int) value; 253 if (windingRule != value) break; /* not an integer */ 254 255 switch (windingRule) { 256 case GLU_TESS_WINDING_ODD: 257 case GLU_TESS_WINDING_NONZERO: 258 case GLU_TESS_WINDING_POSITIVE: 259 case GLU_TESS_WINDING_NEGATIVE: 260 case GLU_TESS_WINDING_ABS_GEQ_TWO: 261 this.windingRule = windingRule; 262 return; 263 default: 264 break; 265 } 266 267 case GLU_TESS_BOUNDARY_ONLY: 268 boundaryOnly = (value != 0); 269 return; 270 271 default: 272 callErrorOrErrorData(GLU_INVALID_ENUM); 273 return; 274 } 275 callErrorOrErrorData(GLU_INVALID_VALUE); 276 } 277 278 /* Returns tessellator property */ gluGetTessProperty(int which, double[] value, int value_offset)279 public void gluGetTessProperty(int which, double[] value, int value_offset) { 280 switch (which) { 281 case GLU_TESS_TOLERANCE: 282 /* tolerance should be in range [0..1] */ 283 assert (0.0 <= relTolerance && relTolerance <= 1.0); 284 value[value_offset] = relTolerance; 285 break; 286 case GLU_TESS_WINDING_RULE: 287 assert (windingRule == GLU_TESS_WINDING_ODD || 288 windingRule == GLU_TESS_WINDING_NONZERO || 289 windingRule == GLU_TESS_WINDING_POSITIVE || 290 windingRule == GLU_TESS_WINDING_NEGATIVE || 291 windingRule == GLU_TESS_WINDING_ABS_GEQ_TWO); 292 value[value_offset] = windingRule; 293 break; 294 case GLU_TESS_BOUNDARY_ONLY: 295 assert (boundaryOnly == true || boundaryOnly == false); 296 value[value_offset] = boundaryOnly ? 1 : 0; 297 break; 298 default: 299 value[value_offset] = 0.0; 300 callErrorOrErrorData(GLU_INVALID_ENUM); 301 break; 302 } 303 } /* gluGetTessProperty() */ 304 gluTessNormal(double x, double y, double z)305 public void gluTessNormal(double x, double y, double z) { 306 normal[0] = x; 307 normal[1] = y; 308 normal[2] = z; 309 } 310 gluTessCallback(int which, GLUtessellatorCallback aCallback)311 public void gluTessCallback(int which, GLUtessellatorCallback aCallback) { 312 switch (which) { 313 case GLU_TESS_BEGIN: 314 callBegin = aCallback == null ? NULL_CB : aCallback; 315 return; 316 case GLU_TESS_BEGIN_DATA: 317 callBeginData = aCallback == null ? NULL_CB : aCallback; 318 return; 319 case GLU_TESS_EDGE_FLAG: 320 callEdgeFlag = aCallback == null ? NULL_CB : aCallback; 321 /* If the client wants boundary edges to be flagged, 322 * we render everything as separate triangles (no strips or fans). 323 */ 324 flagBoundary = aCallback != null; 325 return; 326 case GLU_TESS_EDGE_FLAG_DATA: 327 callEdgeFlagData = callBegin = aCallback == null ? NULL_CB : aCallback; 328 /* If the client wants boundary edges to be flagged, 329 * we render everything as separate triangles (no strips or fans). 330 */ 331 flagBoundary = (aCallback != null); 332 return; 333 case GLU_TESS_VERTEX: 334 callVertex = aCallback == null ? NULL_CB : aCallback; 335 return; 336 case GLU_TESS_VERTEX_DATA: 337 callVertexData = aCallback == null ? NULL_CB : aCallback; 338 return; 339 case GLU_TESS_END: 340 callEnd = aCallback == null ? NULL_CB : aCallback; 341 return; 342 case GLU_TESS_END_DATA: 343 callEndData = aCallback == null ? NULL_CB : aCallback; 344 return; 345 case GLU_TESS_ERROR: 346 callError = aCallback == null ? NULL_CB : aCallback; 347 return; 348 case GLU_TESS_ERROR_DATA: 349 callErrorData = aCallback == null ? NULL_CB : aCallback; 350 return; 351 case GLU_TESS_COMBINE: 352 callCombine = aCallback == null ? NULL_CB : aCallback; 353 return; 354 case GLU_TESS_COMBINE_DATA: 355 callCombineData = aCallback == null ? NULL_CB : aCallback; 356 return; 357 // case GLU_TESS_MESH: 358 // callMesh = aCallback == null ? NULL_CB : aCallback; 359 // return; 360 default: 361 callErrorOrErrorData(GLU_INVALID_ENUM); 362 return; 363 } 364 } 365 addVertex(double[] coords, Object vertexData)366 private boolean addVertex(double[] coords, Object vertexData) { 367 GLUhalfEdge e; 368 369 e = lastEdge; 370 if (e == null) { 371 /* Make a self-loop (one vertex, one edge). */ 372 373 e = Mesh.__gl_meshMakeEdge(mesh); 374 if (e == null) return false; 375 if (!Mesh.__gl_meshSplice(e, e.Sym)) return false; 376 } else { 377 /* Create a new vertex and edge which immediately follow e 378 * in the ordering around the left face. 379 */ 380 if (Mesh.__gl_meshSplitEdge(e) == null) return false; 381 e = e.Lnext; 382 } 383 384 /* The new vertex is now e.Org. */ 385 e.Org.data = vertexData; 386 e.Org.coords[0] = coords[0]; 387 e.Org.coords[1] = coords[1]; 388 e.Org.coords[2] = coords[2]; 389 390 /* The winding of an edge says how the winding number changes as we 391 * cross from the edge''s right face to its left face. We add the 392 * vertices in such an order that a CCW contour will add +1 to 393 * the winding number of the region inside the contour. 394 */ 395 e.winding = 1; 396 e.Sym.winding = -1; 397 398 lastEdge = e; 399 400 return true; 401 } 402 cacheVertex(double[] coords, Object vertexData)403 private void cacheVertex(double[] coords, Object vertexData) { 404 if (cache[cacheCount] == null) { 405 cache[cacheCount] = new CachedVertex(); 406 } 407 408 CachedVertex v = cache[cacheCount]; 409 410 v.data = vertexData; 411 v.coords[0] = coords[0]; 412 v.coords[1] = coords[1]; 413 v.coords[2] = coords[2]; 414 ++cacheCount; 415 } 416 417 flushCache()418 private boolean flushCache() { 419 CachedVertex[] v = cache; 420 421 mesh = Mesh.__gl_meshNewMesh(); 422 if (mesh == null) return false; 423 424 for (int i = 0; i < cacheCount; i++) { 425 CachedVertex vertex = v[i]; 426 if (!addVertex(vertex.coords, vertex.data)) return false; 427 } 428 cacheCount = 0; 429 flushCacheOnNextVertex = false; 430 431 return true; 432 } 433 gluTessVertex(double[] coords, int coords_offset, Object vertexData)434 public void gluTessVertex(double[] coords, int coords_offset, Object vertexData) { 435 int i; 436 boolean tooLarge = false; 437 double x; 438 double[] clamped = new double[3]; 439 440 requireState(TessState.T_IN_CONTOUR); 441 442 if (flushCacheOnNextVertex) { 443 if (!flushCache()) { 444 callErrorOrErrorData(GLU_OUT_OF_MEMORY); 445 return; 446 } 447 lastEdge = null; 448 } 449 for (i = 0; i < 3; ++i) { 450 x = coords[i+coords_offset]; 451 if (x < -GLU_TESS_MAX_COORD) { 452 x = -GLU_TESS_MAX_COORD; 453 tooLarge = true; 454 } 455 if (x > GLU_TESS_MAX_COORD) { 456 x = GLU_TESS_MAX_COORD; 457 tooLarge = true; 458 } 459 clamped[i] = x; 460 } 461 if (tooLarge) { 462 callErrorOrErrorData(GLU_TESS_COORD_TOO_LARGE); 463 } 464 465 if (mesh == null) { 466 if (cacheCount < TESS_MAX_CACHE) { 467 cacheVertex(clamped, vertexData); 468 return; 469 } 470 if (!flushCache()) { 471 callErrorOrErrorData(GLU_OUT_OF_MEMORY); 472 return; 473 } 474 } 475 476 if (!addVertex(clamped, vertexData)) { 477 callErrorOrErrorData(GLU_OUT_OF_MEMORY); 478 } 479 } 480 481 gluTessBeginPolygon(Object data)482 public void gluTessBeginPolygon(Object data) { 483 requireState(TessState.T_DORMANT); 484 485 state = TessState.T_IN_POLYGON; 486 cacheCount = 0; 487 flushCacheOnNextVertex = false; 488 mesh = null; 489 490 polygonData = data; 491 } 492 493 gluTessBeginContour()494 public void gluTessBeginContour() { 495 requireState(TessState.T_IN_POLYGON); 496 497 state = TessState.T_IN_CONTOUR; 498 lastEdge = null; 499 if (cacheCount > 0) { 500 /* Just set a flag so we don't get confused by empty contours 501 * -- these can be generated accidentally with the obsolete 502 * NextContour() interface. 503 */ 504 flushCacheOnNextVertex = true; 505 } 506 } 507 508 gluTessEndContour()509 public void gluTessEndContour() { 510 requireState(TessState.T_IN_CONTOUR); 511 state = TessState.T_IN_POLYGON; 512 } 513 gluTessEndPolygon()514 public void gluTessEndPolygon() { 515 GLUmesh mesh; 516 517 try { 518 requireState(TessState.T_IN_POLYGON); 519 state = TessState.T_DORMANT; 520 521 if (this.mesh == null) { 522 if (!flagBoundary /*&& callMesh == NULL_CB*/) { 523 524 /* Try some special code to make the easy cases go quickly 525 * (eg. convex polygons). This code does NOT handle multiple contours, 526 * intersections, edge flags, and of course it does not generate 527 * an explicit mesh either. 528 */ 529 if (Render.__gl_renderCache(this)) { 530 polygonData = null; 531 return; 532 } 533 } 534 if (!flushCache()) throw new RuntimeException(); /* could've used a label*/ 535 } 536 537 /* Determine the polygon normal and project vertices onto the plane 538 * of the polygon. 539 */ 540 Normal.__gl_projectPolygon(this); 541 542 /* __gl_computeInterior( tess ) computes the planar arrangement specified 543 * by the given contours, and further subdivides this arrangement 544 * into regions. Each region is marked "inside" if it belongs 545 * to the polygon, according to the rule given by windingRule. 546 * Each interior region is guaranteed be monotone. 547 */ 548 if (!Sweep.__gl_computeInterior(this)) { 549 throw new RuntimeException(); /* could've used a label */ 550 } 551 552 mesh = this.mesh; 553 if (!fatalError) { 554 boolean rc = true; 555 556 /* If the user wants only the boundary contours, we throw away all edges 557 * except those which separate the interior from the exterior. 558 * Otherwise we tessellate all the regions marked "inside". 559 */ 560 if (boundaryOnly) { 561 rc = TessMono.__gl_meshSetWindingNumber(mesh, 1, true); 562 } else { 563 rc = TessMono.__gl_meshTessellateInterior(mesh); 564 } 565 if (!rc) throw new RuntimeException(); /* could've used a label */ 566 567 Mesh.__gl_meshCheckMesh(mesh); 568 569 if (callBegin != NULL_CB || callEnd != NULL_CB 570 || callVertex != NULL_CB || callEdgeFlag != NULL_CB 571 || callBeginData != NULL_CB 572 || callEndData != NULL_CB 573 || callVertexData != NULL_CB 574 || callEdgeFlagData != NULL_CB) { 575 if (boundaryOnly) { 576 Render.__gl_renderBoundary(this, mesh); /* output boundary contours */ 577 } else { 578 Render.__gl_renderMesh(this, mesh); /* output strips and fans */ 579 } 580 } 581 // if (callMesh != NULL_CB) { 582 // 583 ///* Throw away the exterior faces, so that all faces are interior. 584 // * This way the user doesn't have to check the "inside" flag, 585 // * and we don't need to even reveal its existence. It also leaves 586 // * the freedom for an implementation to not generate the exterior 587 // * faces in the first place. 588 // */ 589 // TessMono.__gl_meshDiscardExterior(mesh); 590 // callMesh.mesh(mesh); /* user wants the mesh itself */ 591 // mesh = null; 592 // polygonData = null; 593 // return; 594 // } 595 } 596 Mesh.__gl_meshDeleteMesh(mesh); 597 polygonData = null; 598 mesh = null; 599 } catch (Exception e) { 600 e.printStackTrace(); 601 callErrorOrErrorData(GLU_OUT_OF_MEMORY); 602 } 603 } 604 605 /*******************************************************/ 606 607 /* Obsolete calls -- for backward compatibility */ 608 gluBeginPolygon()609 public void gluBeginPolygon() { 610 gluTessBeginPolygon(null); 611 gluTessBeginContour(); 612 } 613 614 615 /*ARGSUSED*/ gluNextContour(int type)616 public void gluNextContour(int type) { 617 gluTessEndContour(); 618 gluTessBeginContour(); 619 } 620 621 gluEndPolygon()622 public void gluEndPolygon() { 623 gluTessEndContour(); 624 gluTessEndPolygon(); 625 } 626 callBeginOrBeginData(int a)627 void callBeginOrBeginData(int a) { 628 if (callBeginData != NULL_CB) 629 callBeginData.beginData(a, polygonData); 630 else 631 callBegin.begin(a); 632 } 633 callVertexOrVertexData(Object a)634 void callVertexOrVertexData(Object a) { 635 if (callVertexData != NULL_CB) 636 callVertexData.vertexData(a, polygonData); 637 else 638 callVertex.vertex(a); 639 } 640 callEdgeFlagOrEdgeFlagData(boolean a)641 void callEdgeFlagOrEdgeFlagData(boolean a) { 642 if (callEdgeFlagData != NULL_CB) 643 callEdgeFlagData.edgeFlagData(a, polygonData); 644 else 645 callEdgeFlag.edgeFlag(a); 646 } 647 callEndOrEndData()648 void callEndOrEndData() { 649 if (callEndData != NULL_CB) 650 callEndData.endData(polygonData); 651 else 652 callEnd.end(); 653 } 654 callCombineOrCombineData(double[] coords, Object[] vertexData, float[] weights, Object[] outData)655 void callCombineOrCombineData(double[] coords, Object[] vertexData, float[] weights, Object[] outData) { 656 if (callCombineData != NULL_CB) 657 callCombineData.combineData(coords, vertexData, weights, outData, polygonData); 658 else 659 callCombine.combine(coords, vertexData, weights, outData); 660 } 661 callErrorOrErrorData(int a)662 void callErrorOrErrorData(int a) { 663 if (callErrorData != NULL_CB) 664 callErrorData.errorData(a, polygonData); 665 else 666 callError.error(a); 667 } 668 669 } 670