001/***************************************************************************** 002 * J3D.org Copyright (c) 2000 003 * Java Source 004 * 005 * This source is licensed under the GNU LGPL v2.1 006 * Please read http://www.gnu.org/copyleft/lgpl.html for more information 007 * 008 ****************************************************************************/ 009 010package jahuwaldt.j3d.geom; 011 012// Standard imports 013import org.jogamp.vecmath.Vector3f; 014 015// Application specific imports 016 017/** 018 * A simple cylinder that can be configured to have end caps. 019 * <p> 020 * 021 * The generator is used to create cylinder shaped geometry for the code. 022 * Internally we use a triangle array to generate the information as a 023 * collection of single triangles. A triangle strip would be more efficient 024 * for rendering, but that's too hard for this first cut :) 025 * 026 * The height of the cone is along the Y axis with the point in the positive 027 * Y direction. The radius is around the X-Z plane. The whole object is 028 * centered on the origin. 029 * 030 * @author Justin Couch 031 * @version $Revision: 1.11-JAH1 $ 032 */ 033public class CylinderGenerator extends GeometryGenerator 034{ 035 /** The default height of the object */ 036 private static final float DEFAULT_HEIGHT = 2; 037 038 /** The default radius of the cylinder */ 039 private static final float DEFAULT_RADIUS = 1; 040 041 /** Default number of segments used in the cone */ 042 private static final int DEFAULT_FACETS = 16; 043 044 /** The height of the code */ 045 private float cylinderHeight; 046 047 /** The radius of the bottom of the cone */ 048 private float radius; 049 050 /** Flag to indicate if the geometry should create the top */ 051 private boolean useTop; 052 053 /** Flag to indicate if the geometry should create the side */ 054 private boolean useSide; 055 056 /** Flag to indicate if the geometry should create the bottom */ 057 private boolean useBottom; 058 059 /** The number of sections used around the cone */ 060 private int facetCount; 061 062 /** The points on the base of the cone for each facet in [x, z] */ 063 private float[] baseCoordinates; 064 065 /** The number of values used in the base coordinate array */ 066 private int numBaseValues; 067 068 /** 069 * The 2D texture coordinates for the sphere. These match the order of 070 * vertex declaration in the quadCoordinates field thus making life 071 * easy for dealing with half spheres 072 */ 073 private float[] texCoordinates2D; 074 075 /** The number of values used in the 2D tex coord array */ 076 private int numTexCoords2D; 077 078 /** 079 * The 3D texture coordinates for the sphere. These match the order of 080 * vertex declaration in the quadCoordinates field thus making life 081 * easy for dealing with half spheres 082 */ 083 private float[] texCoordinates3D; 084 085 /** The number of values used in the 2D tex coord array */ 086 private int numTexCoords3D; 087 088 /** Flag indicating base values have changed */ 089 private boolean baseChanged; 090 091 /** Flag to indicate the facet count or half settings have changed */ 092 private boolean facetsChanged; 093 094 /** Working values for the normal generation */ 095 private Vector3f normal; 096 097 /** 098 * Construct a default cylinder with end caps. The default height is 2 099 * and radius 1. There are 16 faces on around the radius. 100 */ 101 public CylinderGenerator() 102 { 103 this(DEFAULT_HEIGHT, DEFAULT_RADIUS, DEFAULT_FACETS, true, true, true); 104 } 105 106 /** 107 * Construct a default cylinder with the option of having end caps. 108 * The default height is 2 and radius 1. There are 16 faces on around the 109 * radius. 110 * 111 * @param ends true to use end caps 112 */ 113 public CylinderGenerator(boolean ends) 114 { 115 this(DEFAULT_HEIGHT, DEFAULT_RADIUS, DEFAULT_FACETS, ends, ends, true); 116 } 117 118 /** 119 * Construct a default cylinder with end caps and selectable number of 120 * faces around the radius. The default height is 2 and radius 1. The 121 * minimum number of facets is 3. 122 * 123 * @param facets The number of faces to use around the radius 124 * @throws IllegalArgumentException The number of facets is less than 3 125 */ 126 public CylinderGenerator(int facets) 127 { 128 this(DEFAULT_HEIGHT, DEFAULT_RADIUS, facets, true, true, true); 129 } 130 131 /** 132 * Construct a default cylinder with the option of having end caps and 133 * selectable number of faces around the radius. The default height is 2 134 * and radius 1.The minimum number of facets is 3. 135 * 136 * @param facets The number of faces to use around the radius 137 * @param ends true to use end caps 138 * @throws IllegalArgumentException The number of facets is less than 3 139 */ 140 public CylinderGenerator(int facets, boolean ends) 141 { 142 this(DEFAULT_HEIGHT, DEFAULT_RADIUS, facets, ends, ends, true); 143 } 144 145 /** 146 * Construct a cylinder of a given height and radius with ends. There are 147 * 16 faces around the radius. 148 * 149 * @param height The height of the cylinder to generate 150 * @param radius The radis of the cylinder to generate 151 */ 152 public CylinderGenerator(float height, float radius) 153 { 154 this(height, radius, DEFAULT_FACETS, true, true, true); 155 } 156 157 /** 158 * Construct a cylinder of a given height and radius with ends and 159 * selectable number of faces around the radius. The minimum 160 * number of facets is 3. 161 * 162 * @param height The height of the cylinder to generate 163 * @param radius The radis of the cylinder to generate 164 * @param facets The number of faces to use around the radius 165 * @throws IllegalArgumentException The number of facets is less than 3 166 */ 167 public CylinderGenerator(float height, float radius, int facets) 168 { 169 this(height, radius, facets, true, true, true); 170 } 171 172 /** 173 * Construct a cylinder of a given height and radius with the option of 174 * ends. There are 16 faces around the radius. 175 * 176 * @param height The height of the cylinder to generate 177 * @param radius The radis of the cylinder to generate 178 * @param ends true to use end caps 179 * @param side true to display the sides 180 */ 181 public CylinderGenerator(float height, float radius, boolean ends, boolean side) 182 { 183 this(height, radius, DEFAULT_FACETS, ends, ends, side); 184 } 185 186 /** 187 * Construct a cylinder of a given height and radius with the option of 188 * ends. There are 16 faces around the radius. 189 * 190 * @param height The height of the cylinder to generate 191 * @param radius The radis of the cylinder to generate 192 * @param top Whether to generate the top of the cylinder 193 * @param bottom Whether to generate the bottom of the cylinder 194 * @param side Whether to generate the side of the cylinder 195 */ 196 public CylinderGenerator(float height, float radius, boolean top, boolean bottom, 197 boolean side) 198 { 199 this(height, radius, DEFAULT_FACETS, top, bottom, side); 200 } 201 202 /** 203 * Construct a cylinder of a given height and radius with the option of 204 * ends and selectable number of faces around the radius. The minimum 205 * number of facets is 3. 206 * 207 * @param height The height of the cylinder to generate 208 * @param radius The radis of the cylinder to generate 209 * @param facets The number of faces to use around the radius 210 * @param ends true to use end caps 211 * @param side true to display the side 212 * @throws IllegalArgumentException The number of facets is less than 3 213 */ 214 public CylinderGenerator(float height, 215 float radius, 216 int facets, 217 boolean ends, 218 boolean side) 219 { 220 this(height, radius, facets, true, true, side); 221 } 222 223 /** 224 * Construct a cylinder of a given height and radius with the option of 225 * ends and selectable number of faces around the radius. The minimum 226 * number of facets is 3. 227 * 228 * @param height The height of the cylinder to generate 229 * @param radius The radis of the cylinder to generate 230 * @param facets The number of faces to use around the radius 231 * @param top Whether to generate the top of the cylinder 232 * @param bottom Whether to generate the bottom of the cylinder 233 * @param side Whether to generate the side of the cylinder 234 * @throws IllegalArgumentException The number of facets is less than 3 235 */ 236 public CylinderGenerator(float height, 237 float radius, 238 int facets, 239 boolean top, 240 boolean bottom, 241 boolean side) { 242 243 if(facets < 3) 244 throw new IllegalArgumentException("Number of facets is < 3"); 245 246 facetCount = facets; 247 cylinderHeight = height; 248 this.radius = radius; 249 250 useTop = top; 251 useBottom = bottom; 252 useSide = side; 253 baseChanged = true; 254 facetsChanged = true; 255 normal = new Vector3f(); 256 } 257 258 /** 259 * Check to see that this cylinder has ends in use or not 260 * 261 * @return true if there is are end caps in use 262 */ 263 public boolean hasEnds() 264 { 265 if (useTop && useBottom) 266 return true; 267 else 268 return false; 269 } 270 271 /** 272 * Get the dimensions of the cylinder. These are returned as 2 values of 273 * height and radius respectively for the array. A new array is 274 * created each time so you can do what you like with it. 275 * 276 * @return The current size of the cone 277 */ 278 public float[] getDimensions() 279 { 280 return new float[] { cylinderHeight, radius }; 281 } 282 283 /** 284 * Change the dimensions of the cone to be generated. Calling this will 285 * make the points be re-calculated next time you ask for geometry or 286 * normals. 287 * 288 * @param height The height of the cone to generate 289 * @param radius The radius of the bottom of the cone 290 * @param ends True if to generate faces for the ends 291 * @param side true if to generate faces for the sides 292 */ 293 public void setDimensions(float height, float radius, boolean ends, 294 boolean side) 295 { 296 if((cylinderHeight != height) || (this.radius != radius)) 297 { 298 baseChanged = true; 299 cylinderHeight = height; 300 this.radius = radius; 301 } 302 303 if(ends != useTop != useBottom) 304 facetsChanged = true; 305 306 if (side != useSide) 307 facetsChanged = true; 308 309 useTop = ends; 310 useBottom = ends; 311 useSide = side; 312 } 313 314 /** 315 * Change the number of facets used to create this cone. This will cause 316 * the geometry to be regenerated next time they are asked for. 317 * The minimum number of facets is 3. 318 * 319 * @param facets The number of facets on the side of the cone 320 * @throws IllegalArgumentException The number of facets is less than 3 321 */ 322 public void setFacetCount(int facets) 323 { 324 if(facets < 3) 325 throw new IllegalArgumentException("Number of facets is < 3"); 326 327 facetCount = facets; 328 baseChanged = true; 329 facetsChanged = true; 330 } 331 332 /** 333 * Get the number of vertices that this generator will create for the 334 * shape given in the definition. 335 * 336 * @param data The data to base the calculations on 337 * @return The vertex count for the object 338 * @throws UnsupportedTypeException The generator cannot handle the type 339 * of geometry you have requested. 340 */ 341 public int getVertexCount(GeometryData data) 342 throws UnsupportedTypeException 343 { 344 int ret_val = 0; 345 346 switch(data.geometryType) 347 { 348 case GeometryData.TRIANGLES: 349 if (useSide) 350 ret_val = facetCount * 6; 351 if(useTop) 352 ret_val += facetCount * 3; 353 if(useBottom) 354 ret_val += facetCount * 3; 355 break; 356 357 case GeometryData.QUADS: 358 if (useSide) 359 ret_val = facetCount * 4; 360 if(useTop) 361 ret_val += facetCount * 4; 362 if(useBottom) 363 ret_val += facetCount * 4; 364 break; 365 366 // These all have the same vertex count 367 case GeometryData.TRIANGLE_STRIPS: 368 if (useSide) 369 ret_val = (facetCount + 1) * 2; 370 if(useTop) 371 ret_val += (facetCount + 1) * 2; 372 if(useBottom) 373 ret_val += (facetCount + 1) * 2; 374 break; 375 376 case GeometryData.TRIANGLE_FANS: 377 if (useSide) 378 ret_val = facetCount * 4; 379 if(useTop) 380 ret_val += (facetCount + 2); 381 if(useBottom) 382 ret_val += (facetCount + 2); 383 384 case GeometryData.INDEXED_TRIANGLES: 385 case GeometryData.INDEXED_QUADS: 386 case GeometryData.INDEXED_TRIANGLE_STRIPS: 387 case GeometryData.INDEXED_TRIANGLE_FANS: 388 if (useSide) 389 ret_val = facetCount * 2; 390 if(useTop) 391 ret_val += 1 + facetCount; 392 if(useBottom) 393 ret_val += 1 + facetCount; 394 break; 395 396 default: 397 throw new UnsupportedTypeException("Unknown geometry type: " + 398 data.geometryType); 399 } 400 401 return ret_val; 402 } 403 404 /** 405 * Generate a new set of geometry items based on the passed data. If the 406 * data does not contain the right minimum array lengths an exception will 407 * be generated. If the array reference is null, this will create arrays 408 * of the correct length and assign them to the return value. 409 * 410 * @param data The data to base the calculations on 411 * @throws InvalidArraySizeException The array is not big enough to contain 412 * the requested geometry 413 * @throws UnsupportedTypeException The generator cannot handle the type 414 * of geometry you have requested 415 */ 416 public void generate(GeometryData data) 417 throws UnsupportedTypeException, InvalidArraySizeException 418 { 419 switch(data.geometryType) 420 { 421 case GeometryData.TRIANGLES: 422 unindexedTriangles(data); 423 break; 424 case GeometryData.QUADS: 425 unindexedQuads(data); 426 break; 427 case GeometryData.TRIANGLE_STRIPS: 428 triangleStrips(data); 429 break; 430 case GeometryData.TRIANGLE_FANS: 431 triangleFans(data); 432 break; 433 case GeometryData.INDEXED_QUADS: 434 indexedQuads(data); 435 break; 436 case GeometryData.INDEXED_TRIANGLES: 437 indexedTriangles(data); 438 break; 439 case GeometryData.INDEXED_TRIANGLE_STRIPS: 440 indexedTriangleStrips(data); 441 break; 442 case GeometryData.INDEXED_TRIANGLE_FANS: 443 indexedTriangleFans(data); 444 break; 445 446 default: 447 throw new UnsupportedTypeException("Unknown geometry type: " + 448 data.geometryType); 449 } 450 } 451 452 /** 453 * Generate a new set of points for an unindexed quad array 454 * 455 * @param data The data to base the calculations on 456 * @throws InvalidArraySizeException The array is not big enough to contain 457 * the requested geometry 458 */ 459 private void unindexedTriangles(GeometryData data) 460 throws InvalidArraySizeException 461 { 462 generateUnindexedTriCoordinates(data); 463 464 if((data.geometryComponents & GeometryData.NORMAL_DATA) != 0) 465 generateUnindexedTriNormals(data); 466 467 if((data.geometryComponents & GeometryData.TEXTURE_2D_DATA) != 0) 468 generateTriTexture2D(data); 469 else if((data.geometryComponents & GeometryData.TEXTURE_3D_DATA) != 0) 470 generateTriTexture3D(data); 471 } 472 473 /** 474 * Generate a new set of points for an unindexed quad array 475 * 476 * @param data The data to base the calculations on 477 * @throws InvalidArraySizeException The array is not big enough to contain 478 * the requested geometry 479 */ 480 private void unindexedQuads(GeometryData data) 481 throws InvalidArraySizeException 482 { 483 generateUnindexedQuadCoordinates(data); 484 485 if((data.geometryComponents & GeometryData.NORMAL_DATA) != 0) 486 generateUnindexedQuadNormals(data); 487 488 if((data.geometryComponents & GeometryData.TEXTURE_2D_DATA) != 0) 489 generateTriTexture2D(data); 490 else if((data.geometryComponents & GeometryData.TEXTURE_3D_DATA) != 0) 491 generateTriTexture3D(data); 492 } 493 494 /** 495 * Generate a new set of points for an indexed quad array. Uses the same 496 * points as an indexed triangle, but repeats the top coordinate index. 497 * 498 * @param data The data to base the calculations on 499 * @throws InvalidArraySizeException The array is not big enough to contain 500 * the requested geometry 501 */ 502 private void indexedQuads(GeometryData data) 503 throws InvalidArraySizeException 504 { 505 generateIndexedCoordinates(data); 506 507 if((data.geometryComponents & GeometryData.NORMAL_DATA) != 0) 508 generateIndexedNormals(data); 509 510 if((data.geometryComponents & GeometryData.TEXTURE_2D_DATA) != 0) 511 generateTriTexture2D(data); 512 else if((data.geometryComponents & GeometryData.TEXTURE_3D_DATA) != 0) 513 generateTriTexture3D(data); 514 515 // now let's do the index list 516 int index_size = data.vertexCount * 4; 517 518 if(data.indexes == null) 519 data.indexes = new int[index_size]; 520 else if(data.indexes.length < index_size) 521 throw new InvalidArraySizeException("Coordinates", 522 data.indexes.length, 523 index_size); 524 525 int[] indexes = data.indexes; 526 data.indexesCount = index_size; 527 int idx = 0; 528 int vtx = 0; 529 530 if (useSide) 531 { 532 // each face consists of an anti-clockwise 533 for(int i = facetCount; --i > 0; vtx += 2) 534 { 535 indexes[idx++] = vtx; 536 indexes[idx++] = vtx + 1; 537 indexes[idx++] = vtx + 3; 538 indexes[idx++] = vtx + 2; 539 } 540 541 indexes[idx++] = vtx++; 542 indexes[idx++] = vtx++; 543 indexes[idx++] = 0; 544 indexes[idx++] = 1; 545 } 546 547 int middle; 548 if(useTop) 549 { 550 middle = vtx++; 551 552 // top face. 553 for(int i = facetCount; --i > 0; ) 554 { 555 indexes[idx++] = middle; 556 indexes[idx++] = vtx++; 557 indexes[idx++] = vtx; 558 indexes[idx++] = middle; 559 } 560 561 indexes[idx++] = middle; 562 indexes[idx++] = vtx++; 563 indexes[idx++] = middle + 1; 564 indexes[idx++] = middle; 565 } 566 567 if (useBottom) 568 { 569 middle = vtx++; 570 571 // bottom face is same as top. 572 for(int i = facetCount; --i > 0; ) 573 { 574 indexes[idx++] = middle; 575 indexes[idx++] = vtx + 1; 576 indexes[idx++] = vtx++; 577 indexes[idx++] = middle; 578 } 579 580 indexes[idx++] = middle; 581 indexes[idx++] = middle + 1; 582 indexes[idx++] = vtx; 583 indexes[idx++] = middle; 584 } 585 } 586 587 /** 588 * Generate a new set of points for an indexed triangle array 589 * 590 * @param data The data to base the calculations on 591 * @throws InvalidArraySizeException The array is not big enough to contain 592 * the requested geometry 593 */ 594 private void indexedTriangles(GeometryData data) 595 throws InvalidArraySizeException 596 { 597 generateIndexedCoordinates(data); 598 599 if((data.geometryComponents & GeometryData.NORMAL_DATA) != 0) 600 generateIndexedNormals(data); 601 602 if((data.geometryComponents & GeometryData.TEXTURE_2D_DATA) != 0) 603 generateTriTexture2D(data); 604 else if((data.geometryComponents & GeometryData.TEXTURE_3D_DATA) != 0) 605 generateTriTexture3D(data); 606 607 // now let's do the index list 608 int index_size = data.vertexCount * 3; 609 610 if(data.indexes == null) 611 data.indexes = new int[index_size]; 612 else if(data.indexes.length < index_size) 613 throw new InvalidArraySizeException("Coordinates", 614 data.indexes.length, 615 index_size); 616 617 int[] indexes = data.indexes; 618 data.indexesCount = index_size; 619 int idx = 0; 620 int vtx = 0; 621 622 if (useSide) 623 { 624 // each face consists of an anti-clockwise 625 for(int i = facetCount; --i > 0; vtx += 2) 626 { 627 // triangle 1 628 indexes[idx++] = vtx; 629 indexes[idx++] = vtx + 1; 630 indexes[idx++] = vtx + 3; 631 632 // triangle 2 633 indexes[idx++] = vtx + 3; 634 indexes[idx++] = vtx + 2; 635 indexes[idx++] = vtx; 636 } 637 638 // triangle 1 639 indexes[idx++] = vtx; 640 indexes[idx++] = vtx + 1; 641 indexes[idx++] = 1; 642 643 // triangle 2 644 indexes[idx++] = 1; 645 indexes[idx++] = 0; 646 indexes[idx++] = vtx; 647 648 vtx += 2; 649 } 650 651 int middle; 652 653 if(useTop) 654 { 655 middle = vtx++; 656 657 for(int i = facetCount; --i > 0; ) 658 { 659 indexes[idx++] = middle; 660 indexes[idx++] = vtx + 1; 661 indexes[idx++] = vtx++; 662 } 663 664 indexes[idx++] = middle; 665 indexes[idx++] = middle + 1; 666 indexes[idx++] = vtx; 667 668 } 669 if (useBottom) 670 { 671 middle = vtx++; 672 673 for(int i = facetCount; --i > 0; ) 674 { 675 indexes[idx++] = middle; 676 indexes[idx++] = vtx + 1; 677 indexes[idx++] = vtx++; 678 } 679 680 indexes[idx++] = middle; 681 indexes[idx++] = middle + 1; 682 indexes[idx++] = vtx; 683 } 684 } 685 686 /** 687 * Generate a new set of points for a triangle strip array. There is one 688 * strip for the side and one strip each for the ends. 689 * 690 * @param data The data to base the calculations on 691 * @throws InvalidArraySizeException The array is not big enough to contain 692 * the requested geometry 693 */ 694 private void triangleStrips(GeometryData data) 695 throws InvalidArraySizeException 696 { 697 generateUnindexedTriStripCoordinates(data); 698 699 if((data.geometryComponents & GeometryData.NORMAL_DATA) != 0) 700 generateUnindexedTriStripNormals(data); 701 702 if((data.geometryComponents & GeometryData.TEXTURE_2D_DATA) != 0) 703 generateTriTexture2D(data); 704 else if((data.geometryComponents & GeometryData.TEXTURE_3D_DATA) != 0) 705 generateTriTexture3D(data); 706 707 int num_strips = 0; 708 709 if (useSide) 710 num_strips++; 711 712 if (useTop) 713 num_strips++; 714 715 if (useBottom) 716 num_strips++; 717 718 if(data.stripCounts == null) 719 data.stripCounts = new int[num_strips]; 720 else if(data.stripCounts.length < num_strips) 721 throw new InvalidArraySizeException("Strip counts", 722 data.stripCounts.length, 723 num_strips); 724 725 int scnt=0; 726 int basecount = (1 + facetCount) * 2; 727 728 data.numStrips = num_strips; 729 730 if (useSide) 731 data.stripCounts[scnt++] = basecount; 732 733 if (useTop) 734 data.stripCounts[scnt++] = basecount; 735 if (useBottom) 736 data.stripCounts[scnt++] = basecount; 737 } 738 739 /** 740 * Generate a new set of points for a triangle fan array. Each facet on the 741 * side of the cylinder is a single fan, but the ends are one big fan each. 742 * 743 * @param data The data to base the calculations on 744 * @throws InvalidArraySizeException The array is not big enough to contain 745 * the requested geometry 746 */ 747 private void triangleFans(GeometryData data) 748 throws InvalidArraySizeException 749 { 750 generateUnindexedTriFanCoordinates(data); 751 752 if((data.geometryComponents & GeometryData.NORMAL_DATA) != 0) 753 generateUnindexedTriFanNormals(data); 754 755 if((data.geometryComponents & GeometryData.TEXTURE_2D_DATA) != 0) 756 generateTriTexture2D(data); 757 else if((data.geometryComponents & GeometryData.TEXTURE_3D_DATA) != 0) 758 generateTriTexture3D(data); 759 760 int num_strips = facetCount + 2; 761 762 if(data.stripCounts == null) 763 data.stripCounts = new int[num_strips]; 764 else if(data.stripCounts.length < num_strips) 765 throw new InvalidArraySizeException("Strip counts", 766 data.stripCounts.length, 767 num_strips); 768 769 for(int i = facetCount; --i >= 0; ) 770 data.stripCounts[i] = 4; 771 772 data.stripCounts[num_strips - 2] = facetCount + 2; 773 data.stripCounts[num_strips - 1] = facetCount + 2; 774 data.numStrips = num_strips; 775 } 776 777 /** 778 * Generate a new set of points for an indexed triangle strip array. We 779 * build the strip from the existing points starting by working around the 780 * side and then doing the top and bottom. To create the ends we start at 781 * on radius point and then always refer to the center for each second 782 * item. This wastes every second triangle as a degenerate triangle, but 783 * the gain is less strips needing to be transmitted - ie less memory 784 * usage. 785 * 786 * @param data The data to base the calculations on 787 * @throws InvalidArraySizeException The array is not big enough to contain 788 * the requested geometry 789 */ 790 private void indexedTriangleStrips(GeometryData data) 791 throws InvalidArraySizeException 792 { 793 generateIndexedCoordinates(data); 794 795 if((data.geometryComponents & GeometryData.NORMAL_DATA) != 0) 796 generateIndexedNormals(data); 797 798 if((data.geometryComponents & GeometryData.TEXTURE_2D_DATA) != 0) 799 generateTriTexture2D(data); 800 else if((data.geometryComponents & GeometryData.TEXTURE_3D_DATA) != 0) 801 generateTriTexture3D(data); 802 803 int index_size = 0; 804 int num_strips = 0; 805 806 if (useSide) 807 { 808 // now let's do the index list 809 index_size = (facetCount + 1) * 2; 810 num_strips = 1; 811 } 812 813 if (useTop) 814 { 815 index_size += (facetCount + 1) * 2; 816 num_strips += 1; 817 } 818 if (useBottom) 819 { 820 index_size += (facetCount + 1) * 2; 821 num_strips += 1; 822 } 823 824 if(data.indexes == null) 825 data.indexes = new int[index_size]; 826 else if(data.indexes.length < index_size) 827 throw new InvalidArraySizeException("Indexes", 828 data.indexes.length, 829 index_size); 830 831 if(data.stripCounts == null) 832 data.stripCounts = new int[num_strips]; 833 else if(data.stripCounts.length < num_strips) 834 throw new InvalidArraySizeException("Strip counts", 835 data.stripCounts.length, 836 num_strips); 837 838 int[] indexes = data.indexes; 839 int[] stripCounts = data.stripCounts; 840 data.indexesCount = index_size; 841 data.numStrips = num_strips; 842 int idx = 0; 843 int vtx = 0; 844 int s_idx = 0; 845 846 if (useSide) 847 { 848 stripCounts[s_idx++] = (facetCount + 1) * 2; 849 850 // The side is one big strip 851 for(int i = facetCount; --i >= 0; ) 852 { 853 indexes[idx++] = vtx++; 854 indexes[idx++] = vtx++; 855 } 856 857 indexes[idx++] = 0; 858 indexes[idx++] = facetCount; 859 } 860 861 int middle; 862 if(useTop) 863 { 864 stripCounts[s_idx++] = (facetCount + 1) * 2; 865 866 // Do the top face as one strip 867 middle = vtx++; 868 869 for(int i = facetCount; --i >= 0; ) 870 { 871 indexes[idx++] = middle; 872 indexes[idx++] = vtx++; 873 } 874 875 indexes[idx++] = middle + 1; 876 indexes[idx++] = middle; 877 878 } 879 if(useBottom) 880 { 881 // Now the bottom face as one strip. Must wind it backwards compared 882 // to the top. 883 stripCounts[s_idx] = (facetCount + 1) * 2; 884 885 middle = vtx++; 886 887 for(int i = facetCount; --i >= 0; ) 888 { 889 indexes[idx++] = vtx++; 890 indexes[idx++] = middle; 891 } 892 893 indexes[idx++] = middle + 1; 894 indexes[idx++] = middle; 895 } 896 } 897 898 /** 899 * Generate a new set of points for an indexed triangle fan array. We 900 * build the strip from the existing points, and there's no need to 901 * re-order the points for the indexes this time. As for the simple fan, 902 * we use the first index, the lower-right corner as the apex for the fan. 903 * 904 * @param data The data to base the calculations on 905 * @throws InvalidArraySizeException The array is not big enough to contain 906 * the requested geometry 907 */ 908 private void indexedTriangleFans(GeometryData data) 909 throws InvalidArraySizeException 910 { 911 generateIndexedCoordinates(data); 912 913 if((data.geometryComponents & GeometryData.NORMAL_DATA) != 0) 914 generateIndexedNormals(data); 915 916 if((data.geometryComponents & GeometryData.TEXTURE_2D_DATA) != 0) 917 generateTriTexture2D(data); 918 else if((data.geometryComponents & GeometryData.TEXTURE_3D_DATA) != 0) 919 generateTriTexture3D(data); 920 921 int index_size = 0; 922 int num_strips = 0; 923 924 if (useSide) 925 { 926 index_size = facetCount * 4; 927 num_strips = facetCount; 928 } 929 930 if (useTop) 931 { 932 index_size += 2 * (facetCount + 2); 933 num_strips++; 934 } 935 936 if (useBottom) 937 { 938 index_size += 2 * (facetCount + 2); 939 num_strips++; 940 } 941 942 if(data.indexes == null) 943 data.indexes = new int[index_size]; 944 else if(data.indexes.length < index_size) 945 throw new InvalidArraySizeException("Indexes", 946 data.indexes.length, 947 index_size); 948 949 if(data.stripCounts == null) 950 data.stripCounts = new int[num_strips]; 951 else if(data.stripCounts.length < num_strips) 952 throw new InvalidArraySizeException("Strip counts", 953 data.stripCounts.length, 954 num_strips); 955 956 int[] indexes = data.indexes; 957 int[] stripCounts = data.stripCounts; 958 data.indexesCount = index_size; 959 data.numStrips = num_strips; 960 int idx = 0; 961 int vtx = 0; 962 int scnt = 0; 963 964 if (useSide) 965 { 966 // each face consists of an anti-clockwise 967 for(int i = facetCount; --i > 0; ) 968 { 969 indexes[idx++] = vtx; 970 indexes[idx++] = vtx + 1; 971 indexes[idx++] = vtx + 3; 972 indexes[idx++] = vtx + 2; 973 stripCounts[i] = 4; 974 975 vtx += 2; 976 } 977 978 indexes[idx++] = vtx; 979 indexes[idx++] = vtx + 1; 980 indexes[idx++] = 1; 981 indexes[idx++] = 0; 982 vtx += 2; 983 984 stripCounts[scnt++] = 4; 985 } 986 987 int middle; 988 989 if(useTop) 990 { 991 // Do the top face as one fan 992 middle = vtx++; 993 indexes[idx++] = middle; 994 stripCounts[scnt++] = facetCount + 2; 995 996 for(int i = facetCount; --i >= 0; ) 997 indexes[idx++] = vtx++; 998 999 indexes[idx++] = middle + 1; 1000 1001 } 1002 if (useBottom) 1003 { 1004 // Now the bottom face as one fan. Must wind it backwards compared 1005 // to the top. 1006 middle = vtx++; 1007 indexes[idx++] = middle; 1008 stripCounts[scnt++] = facetCount + 2; 1009 1010 vtx = data.vertexCount - 1; 1011 for(int i = facetCount; --i >= 0; ) 1012 indexes[idx++] = vtx--; 1013 1014 indexes[idx++] = data.vertexCount - 1; 1015 } 1016 } 1017 1018 //------------------------------------------------------------------------ 1019 // Coordinate generation routines 1020 //------------------------------------------------------------------------ 1021 1022 /** 1023 * Generates new set of unindexed points for triangles. The array consists 1024 * of the side coordinates, followed by the top and bottom. 1025 * 1026 * @param data The data to base the calculations on 1027 * @throws InvalidArraySizeException The array is not big enough to contain 1028 * the requested geometry 1029 */ 1030 private void generateUnindexedTriCoordinates(GeometryData data) 1031 throws InvalidArraySizeException 1032 { 1033 int vtx_cnt = 0; 1034 1035 if (useSide) 1036 vtx_cnt = facetCount * 6; 1037 if(useTop) 1038 vtx_cnt += facetCount * 3; 1039 if(useBottom) 1040 vtx_cnt += facetCount * 3; 1041 1042 if(data.coordinates == null) 1043 data.coordinates = new float[vtx_cnt * 3]; 1044 else if(data.coordinates.length < vtx_cnt * 3) 1045 throw new InvalidArraySizeException("Coordinates", 1046 data.coordinates.length, 1047 vtx_cnt * 3); 1048 1049 float[] coords = data.coordinates; 1050 data.vertexCount = vtx_cnt; 1051 1052 regenerateBase(); 1053 1054 int count = 0; 1055 int i = 0; 1056 int base_count = 0; 1057 float half_height = cylinderHeight / 2; 1058 1059 if (useSide) 1060 { 1061 for(i = facetCount; --i > 0; ) 1062 { 1063 //side coords triangle 1 1064 coords[count++] = baseCoordinates[base_count]; 1065 coords[count++] = -half_height; 1066 coords[count++] = baseCoordinates[base_count + 1]; 1067 1068 coords[count++] = baseCoordinates[base_count + 2]; 1069 coords[count++] = -half_height; 1070 coords[count++] = baseCoordinates[base_count + 3]; 1071 1072 coords[count++] = baseCoordinates[base_count + 2]; 1073 coords[count++] = half_height; 1074 coords[count++] = baseCoordinates[base_count + 3]; 1075 1076 //side coords triangle 2 1077 coords[count++] = baseCoordinates[base_count + 2]; 1078 coords[count++] = half_height; 1079 coords[count++] = baseCoordinates[base_count + 3]; 1080 1081 coords[count++] = baseCoordinates[base_count]; 1082 coords[count++] = half_height; 1083 coords[count++] = baseCoordinates[base_count + 1]; 1084 1085 coords[count++] = baseCoordinates[base_count]; 1086 coords[count++] = -half_height; 1087 coords[count++] = baseCoordinates[base_count + 1]; 1088 1089 base_count += 2; 1090 } 1091 1092 //side coords triangle 1 1093 coords[count++] = baseCoordinates[base_count]; 1094 coords[count++] = -half_height; 1095 coords[count++] = baseCoordinates[base_count + 1]; 1096 1097 coords[count++] = baseCoordinates[0]; 1098 coords[count++] = -half_height; 1099 coords[count++] = baseCoordinates[1]; 1100 1101 coords[count++] = baseCoordinates[0]; 1102 coords[count++] = half_height; 1103 coords[count++] = baseCoordinates[1]; 1104 1105 //side coords triangle 2 1106 coords[count++] = baseCoordinates[0]; 1107 coords[count++] = half_height; 1108 coords[count++] = baseCoordinates[1]; 1109 1110 coords[count++] = baseCoordinates[base_count]; 1111 coords[count++] = half_height; 1112 coords[count++] = baseCoordinates[base_count + 1]; 1113 1114 coords[count++] = baseCoordinates[base_count]; 1115 coords[count++] = -half_height; 1116 coords[count++] = baseCoordinates[base_count + 1]; 1117 } 1118 1119 if(useTop) 1120 { 1121 base_count = 0; 1122 1123 // Top coordinates 1124 for(i = facetCount; --i > 0; ) 1125 { 1126 coords[count++] = baseCoordinates[base_count + 2]; 1127 coords[count++] = half_height; 1128 coords[count++] = baseCoordinates[base_count + 3]; 1129 1130 coords[count++] = 0; 1131 coords[count++] = half_height; 1132 coords[count++] = 0; 1133 1134 coords[count++] = baseCoordinates[base_count]; 1135 coords[count++] = half_height; 1136 coords[count++] = baseCoordinates[base_count + 1]; 1137 1138 base_count += 2; 1139 } 1140 1141 coords[count++] = baseCoordinates[0]; 1142 coords[count++] = half_height; 1143 coords[count++] = baseCoordinates[1]; 1144 1145 coords[count++] = 0; 1146 coords[count++] = half_height; 1147 coords[count++] = 0; 1148 1149 coords[count++] = baseCoordinates[base_count]; 1150 coords[count++] = half_height; 1151 coords[count++] = baseCoordinates[base_count + 1]; 1152 1153 } 1154 1155 if (useBottom) { 1156 // Bottom coordinates 1157 1158 base_count = 0; 1159 1160 for(i = facetCount; --i > 0; ) 1161 { 1162 coords[count++] = baseCoordinates[base_count]; 1163 coords[count++] = -half_height; 1164 coords[count++] = baseCoordinates[base_count + 1]; 1165 1166 coords[count++] = 0; 1167 coords[count++] = -half_height; 1168 coords[count++] = 0; 1169 1170 coords[count++] = baseCoordinates[base_count + 2]; 1171 coords[count++] = -half_height; 1172 coords[count++] = baseCoordinates[base_count + 3]; 1173 1174 base_count += 2; 1175 } 1176 1177 // bottom coords 1178 coords[count++] = baseCoordinates[base_count]; 1179 coords[count++] = -half_height; 1180 coords[count++] = baseCoordinates[base_count + 1]; 1181 1182 coords[count++] = 0; 1183 coords[count++] = -half_height; 1184 coords[count++] = 0; 1185 1186 coords[count++] = baseCoordinates[0]; 1187 coords[count++] = -half_height; 1188 coords[count++] = baseCoordinates[1]; 1189 } 1190 } 1191 1192 /** 1193 * Generates new set of unindexed points for triangles strips. The array 1194 * consists of the side coordinates as one strip with the top and bottom 1195 * as separate strips. 1196 * 1197 * @param data The data to base the calculations on 1198 * @throws InvalidArraySizeException The array is not big enough to contain 1199 * the requested geometry 1200 */ 1201 private void generateUnindexedTriStripCoordinates(GeometryData data) 1202 throws InvalidArraySizeException 1203 { 1204 int vtx_cnt = 0; 1205 1206 if (useSide) 1207 vtx_cnt = (facetCount + 1) * 2; 1208 1209 if(useTop) 1210 vtx_cnt += (facetCount + 1) * 2; 1211 1212 if(useBottom) 1213 vtx_cnt += (facetCount + 1) * 2; 1214 1215 if(data.coordinates == null) 1216 data.coordinates = new float[vtx_cnt * 3]; 1217 else if(data.coordinates.length < vtx_cnt * 3) 1218 throw new InvalidArraySizeException("Coordinates", 1219 data.coordinates.length, 1220 vtx_cnt * 3); 1221 1222 float[] coords = data.coordinates; 1223 data.vertexCount = vtx_cnt; 1224 float half_height = cylinderHeight / 2; 1225 1226 regenerateBase(); 1227 1228 int i; 1229 int count = 0; 1230 int base_count = 0; 1231 1232 if (useSide) 1233 { 1234 // The side is one big strip 1235 for(i = facetCount; --i >= 0; ) 1236 { 1237 coords[count++] = baseCoordinates[base_count]; 1238 coords[count++] = half_height; 1239 coords[count++] = baseCoordinates[base_count + 1]; 1240 1241 coords[count++] = baseCoordinates[base_count]; 1242 coords[count++] = -half_height; 1243 coords[count++] = baseCoordinates[base_count + 1]; 1244 1245 base_count += 2; 1246 } 1247 1248 coords[count++] = baseCoordinates[0]; 1249 coords[count++] = half_height; 1250 coords[count++] = baseCoordinates[1]; 1251 1252 coords[count++] = baseCoordinates[0]; 1253 coords[count++] = -half_height; 1254 coords[count++] = baseCoordinates[1]; 1255 } 1256 1257 if(useTop) 1258 { 1259 // Do the top face as one strip 1260 base_count = 0; 1261 for(i = facetCount; --i >= 0; ) 1262 { 1263 coords[count++] = 0; 1264 coords[count++] = half_height; 1265 coords[count++] = 0; 1266 1267 coords[count++] = baseCoordinates[base_count++]; 1268 coords[count++] = half_height; 1269 coords[count++] = baseCoordinates[base_count++]; 1270 } 1271 1272 coords[count++] = 0; 1273 coords[count++] = half_height; 1274 coords[count++] = 0; 1275 1276 coords[count++] = baseCoordinates[0]; 1277 coords[count++] = half_height; 1278 coords[count++] = baseCoordinates[1]; 1279 } 1280 1281 if (useBottom) 1282 { 1283 // Now the bottom face as one fan. Must wind it backwards compared 1284 // to the top. 1285 base_count = 0; 1286 for(i = facetCount; --i >= 0; ) 1287 { 1288 coords[count++] = baseCoordinates[base_count++]; 1289 coords[count++] = -half_height; 1290 coords[count++] = baseCoordinates[base_count++]; 1291 1292 coords[count++] = 0; 1293 coords[count++] = -half_height; 1294 coords[count++] = 0; 1295 } 1296 1297 coords[count++] = baseCoordinates[0]; 1298 coords[count++] = -half_height; 1299 coords[count++] = baseCoordinates[1]; 1300 1301 coords[count++] = 0; 1302 coords[count++] = -half_height; 1303 coords[count++] = 0; 1304 } 1305 } 1306 1307 /** 1308 * Generates new set of unindexed points for triangle fans. For each 1309 * facet on the side we have one fan. For each end there is a single 1310 * fan. 1311 * 1312 * @param data The data to base the calculations on 1313 * @throws InvalidArraySizeException The array is not big enough to contain 1314 * the requested geometry 1315 */ 1316 private void generateUnindexedTriFanCoordinates(GeometryData data) 1317 throws InvalidArraySizeException 1318 { 1319 int vtx_cnt = 0; 1320 1321 if (useSide) 1322 vtx_cnt = facetCount * 4; 1323 1324 if(useTop) 1325 vtx_cnt += (facetCount + 2); 1326 1327 if(useBottom) 1328 vtx_cnt += (facetCount + 2); 1329 1330 if(data.coordinates == null) 1331 data.coordinates = new float[vtx_cnt * 3]; 1332 else if(data.coordinates.length < vtx_cnt * 3) 1333 throw new InvalidArraySizeException("Coordinates", 1334 data.coordinates.length, 1335 vtx_cnt * 3); 1336 1337 float[] coords = data.coordinates; 1338 data.vertexCount = vtx_cnt; 1339 1340 regenerateBase(); 1341 1342 int count = 0; 1343 int i = 0; 1344 int base_count = 0; 1345 float half_height = cylinderHeight / 2; 1346 1347 if (useSide) 1348 { 1349 for(i = facetCount; --i > 0; ) 1350 { 1351 //side coords triangle 1 1352 coords[count++] = baseCoordinates[base_count]; 1353 coords[count++] = half_height; 1354 coords[count++] = baseCoordinates[base_count + 1]; 1355 1356 coords[count++] = baseCoordinates[base_count]; 1357 coords[count++] = -half_height; 1358 coords[count++] = baseCoordinates[base_count + 1]; 1359 1360 coords[count++] = baseCoordinates[base_count + 2]; 1361 coords[count++] = -half_height; 1362 coords[count++] = baseCoordinates[base_count + 3]; 1363 1364 coords[count++] = baseCoordinates[base_count + 2]; 1365 coords[count++] = half_height; 1366 coords[count++] = baseCoordinates[base_count + 3]; 1367 1368 base_count += 2; 1369 } 1370 1371 coords[count++] = baseCoordinates[base_count]; 1372 coords[count++] = half_height; 1373 coords[count++] = baseCoordinates[base_count + 1]; 1374 1375 coords[count++] = baseCoordinates[base_count]; 1376 coords[count++] = -half_height; 1377 coords[count++] = baseCoordinates[base_count + 1]; 1378 1379 coords[count++] = baseCoordinates[0]; 1380 coords[count++] = -half_height; 1381 coords[count++] = baseCoordinates[1]; 1382 1383 coords[count++] = baseCoordinates[0]; 1384 coords[count++] = half_height; 1385 coords[count++] = baseCoordinates[1]; 1386 } 1387 1388 if(useTop) 1389 { 1390 base_count = 0; 1391 1392 coords[count++] = 0; 1393 coords[count++] = half_height; 1394 coords[count++] = 0; 1395 1396 // Top coordinates 1397 for(i = facetCount; --i >= 0; ) 1398 { 1399 coords[count++] = baseCoordinates[base_count++]; 1400 coords[count++] = half_height; 1401 coords[count++] = baseCoordinates[base_count++]; 1402 } 1403 1404 coords[count++] = baseCoordinates[0]; 1405 coords[count++] = half_height; 1406 coords[count++] = baseCoordinates[1]; 1407 1408 } 1409 if (useBottom) 1410 { 1411 // Bottom coordinates wound in reverse order 1412 base_count = numBaseValues - 1; 1413 1414 coords[count++] = 0; 1415 coords[count++] = -half_height; 1416 coords[count++] = 0; 1417 1418 for(i = facetCount; --i >= 0; ) 1419 { 1420 coords[count++] = baseCoordinates[base_count - 1]; 1421 coords[count++] = -half_height; 1422 coords[count++] = baseCoordinates[base_count]; 1423 1424 base_count -= 2; 1425 } 1426 1427 // bottom coords 1428 coords[count++] = baseCoordinates[numBaseValues - 2]; 1429 coords[count++] = -half_height; 1430 coords[count++] = baseCoordinates[numBaseValues - 1]; 1431 } 1432 } 1433 1434 /** 1435 * Generates new set of unindexed points for quads. The array consists 1436 * of the side coordinates, followed by the top and bottom. 1437 * 1438 * @param data The data to base the calculations on 1439 * @throws InvalidArraySizeException The array is not big enough to contain 1440 * the requested geometry 1441 */ 1442 private void generateUnindexedQuadCoordinates(GeometryData data) 1443 throws InvalidArraySizeException 1444 { 1445 int vtx_cnt = 0; 1446 1447 if (useSide) 1448 vtx_cnt = facetCount * 4; 1449 1450 if(useTop) 1451 vtx_cnt += facetCount * 4; 1452 1453 if(useBottom) 1454 vtx_cnt += facetCount * 4; 1455 1456 if(data.coordinates == null) 1457 data.coordinates = new float[vtx_cnt * 3]; 1458 else if(data.coordinates.length < vtx_cnt * 3) 1459 throw new InvalidArraySizeException("Coordinates", 1460 data.coordinates.length, 1461 vtx_cnt * 3); 1462 1463 float[] coords = data.coordinates; 1464 data.vertexCount = vtx_cnt; 1465 1466 regenerateBase(); 1467 1468 int count = 0; 1469 int i = 0; 1470 int base_count = 0; 1471 float half_height = cylinderHeight / 2; 1472 1473 if (useSide) 1474 { 1475 for(i = facetCount; --i > 0; ) 1476 { 1477 //side coords triangle 1 1478 coords[count++] = baseCoordinates[base_count]; 1479 coords[count++] = -half_height; 1480 coords[count++] = baseCoordinates[base_count + 1]; 1481 1482 coords[count++] = baseCoordinates[base_count + 2]; 1483 coords[count++] = -half_height; 1484 coords[count++] = baseCoordinates[base_count + 3]; 1485 1486 coords[count++] = baseCoordinates[base_count + 2]; 1487 coords[count++] = half_height; 1488 coords[count++] = baseCoordinates[base_count + 3]; 1489 1490 coords[count++] = baseCoordinates[base_count]; 1491 coords[count++] = half_height; 1492 coords[count++] = baseCoordinates[base_count + 1]; 1493 1494 base_count += 2; 1495 } 1496 1497 coords[count++] = baseCoordinates[base_count]; 1498 coords[count++] = -half_height; 1499 coords[count++] = baseCoordinates[base_count + 1]; 1500 1501 coords[count++] = baseCoordinates[0]; 1502 coords[count++] = -half_height; 1503 coords[count++] = baseCoordinates[1]; 1504 1505 coords[count++] = baseCoordinates[0]; 1506 coords[count++] = half_height; 1507 coords[count++] = baseCoordinates[1]; 1508 1509 coords[count++] = baseCoordinates[base_count]; 1510 coords[count++] = half_height; 1511 coords[count++] = baseCoordinates[base_count + 1]; 1512 } 1513 1514 if(useTop) 1515 { 1516 base_count = 0; 1517 1518 // Top coordinates 1519 for(i = facetCount; --i > 0; ) 1520 { 1521 coords[count++] = baseCoordinates[base_count + 2]; 1522 coords[count++] = half_height; 1523 coords[count++] = baseCoordinates[base_count + 3]; 1524 1525 coords[count++] = 0; 1526 coords[count++] = half_height; 1527 coords[count++] = 0; 1528 1529 coords[count++] = 0; 1530 coords[count++] = half_height; 1531 coords[count++] = 0; 1532 1533 coords[count++] = baseCoordinates[base_count]; 1534 coords[count++] = half_height; 1535 coords[count++] = baseCoordinates[base_count + 1]; 1536 1537 base_count += 2; 1538 } 1539 1540 coords[count++] = baseCoordinates[0]; 1541 coords[count++] = half_height; 1542 coords[count++] = baseCoordinates[1]; 1543 1544 coords[count++] = 0; 1545 coords[count++] = half_height; 1546 coords[count++] = 0; 1547 1548 coords[count++] = 0; 1549 coords[count++] = half_height; 1550 coords[count++] = 0; 1551 1552 coords[count++] = baseCoordinates[base_count]; 1553 coords[count++] = half_height; 1554 coords[count++] = baseCoordinates[base_count + 1]; 1555 1556 } 1557 if (useBottom) 1558 { 1559 // Bottom coordinates 1560 1561 base_count = 0; 1562 1563 for(i = facetCount; --i > 0; ) 1564 { 1565 coords[count++] = baseCoordinates[base_count]; 1566 coords[count++] = -half_height; 1567 coords[count++] = baseCoordinates[base_count + 1]; 1568 1569 coords[count++] = 0; 1570 coords[count++] = -half_height; 1571 coords[count++] = 0; 1572 1573 coords[count++] = 0; 1574 coords[count++] = -half_height; 1575 coords[count++] = 0; 1576 1577 coords[count++] = baseCoordinates[base_count + 2]; 1578 coords[count++] = -half_height; 1579 coords[count++] = baseCoordinates[base_count + 3]; 1580 1581 base_count += 2; 1582 } 1583 1584 // bottom coords 1585 coords[count++] = baseCoordinates[base_count]; 1586 coords[count++] = -half_height; 1587 coords[count++] = baseCoordinates[base_count + 1]; 1588 1589 coords[count++] = 0; 1590 coords[count++] = -half_height; 1591 coords[count++] = 0; 1592 1593 coords[count++] = 0; 1594 coords[count++] = -half_height; 1595 coords[count++] = 0; 1596 1597 coords[count++] = baseCoordinates[0]; 1598 coords[count++] = -half_height; 1599 coords[count++] = baseCoordinates[1]; 1600 } 1601 } 1602 1603 /** 1604 * Generates new set of indexed points for triangles or quads. The array 1605 * consists of the side coordinates, followed by the center for top, then 1606 * its points then the bottom center and its points. We do this as they 1607 * use a completely different set of normals. The side 1608 * coordinates are interleved as top and then bottom values. 1609 * 1610 * @param data The data to base the calculations on 1611 * @throws InvalidArraySizeException The array is not big enough to contain 1612 * the requested geometry 1613 */ 1614 private void generateIndexedCoordinates(GeometryData data) 1615 throws InvalidArraySizeException 1616 { 1617 int vtx_cnt = 0; 1618 1619 if (useSide) 1620 vtx_cnt = facetCount * 2; 1621 1622 if(useTop) 1623 vtx_cnt += 1 + facetCount; 1624 1625 if(useBottom) 1626 vtx_cnt += 1 + facetCount; 1627 1628 if(data.coordinates == null) 1629 data.coordinates = new float[vtx_cnt * 3]; 1630 else if(data.coordinates.length < vtx_cnt * 3) 1631 throw new InvalidArraySizeException("Coordinates", 1632 data.coordinates.length, 1633 vtx_cnt * 3); 1634 1635 float[] coords = data.coordinates; 1636 data.vertexCount = vtx_cnt; 1637 1638 regenerateBase(); 1639 1640 int count = 0; 1641 int i = 0; 1642 int base_count = 0; 1643 float half_height = cylinderHeight / 2; 1644 1645 if (useSide) 1646 { 1647 for(i = facetCount; --i >=0; ) 1648 { 1649 coords[count++] = baseCoordinates[base_count]; 1650 coords[count++] = half_height; 1651 coords[count++] = baseCoordinates[base_count + 1]; 1652 1653 coords[count++] = baseCoordinates[base_count]; 1654 coords[count++] = -half_height; 1655 coords[count++] = baseCoordinates[base_count + 1]; 1656 1657 base_count += 2; 1658 } 1659 } 1660 1661 if(useTop) 1662 { 1663 coords[count++] = 0; 1664 coords[count++] = half_height; 1665 coords[count++] = 0; 1666 1667 base_count = 0; 1668 1669 for(i = facetCount; --i >= 0; ) 1670 { 1671 coords[count++] = baseCoordinates[base_count++]; 1672 coords[count++] = half_height; 1673 coords[count++] = baseCoordinates[base_count++]; 1674 } 1675 1676 } 1677 1678 if (useBottom) 1679 { 1680 base_count = 0; 1681 1682 coords[count++] = 0; 1683 coords[count++] = -half_height; 1684 coords[count++] = 0; 1685 1686 for(i = facetCount; --i >= 0; ) 1687 { 1688 coords[count++] = baseCoordinates[base_count++]; 1689 coords[count++] = -half_height; 1690 coords[count++] = baseCoordinates[base_count++]; 1691 } 1692 } 1693 } 1694 1695 //------------------------------------------------------------------------ 1696 // Normal generation routines 1697 //------------------------------------------------------------------------ 1698 1699 /** 1700 * Generate a new set of normals for a normal set of unindexed points. 1701 * Smooth normals are used for the sides at the average between the faces. 1702 * Bottom normals always point down. 1703 * <p> 1704 * This must always be called after the coordinate generation. 1705 * 1706 * @param data The data to base the calculations on 1707 * @throws InvalidArraySizeException The array is not big enough to contain 1708 * the requested geometry 1709 */ 1710 private void generateUnindexedTriNormals(GeometryData data) 1711 throws InvalidArraySizeException 1712 { 1713 int vtx_cnt = data.vertexCount * 3; 1714 1715 if(data.normals == null) 1716 data.normals = new float[vtx_cnt]; 1717 else if(data.normals.length < vtx_cnt) 1718 throw new InvalidArraySizeException("Normals", 1719 data.normals.length, 1720 vtx_cnt); 1721 1722 int i; 1723 float[] normals = data.normals; 1724 int count = 0; 1725 int vtx = 0; 1726 1727 if (useSide) 1728 { 1729 createRadialFlatNormal(vtx++); 1730 1731 for(i = facetCount; --i > 0; ) 1732 { 1733 normals[count++] = normal.x; 1734 normals[count++] = normal.y; 1735 normals[count++] = normal.z; 1736 1737 normals[count + 9] = normal.x; 1738 normals[count + 10] = normal.y; 1739 normals[count + 11] = normal.z; 1740 1741 normals[count + 12] = normal.x; 1742 normals[count + 13] = normal.y; 1743 normals[count + 14] = normal.z; 1744 1745 createRadialFlatNormal(vtx++); 1746 1747 normals[count++] = normal.x; 1748 normals[count++] = normal.y; 1749 normals[count++] = normal.z; 1750 1751 normals[count++] = normal.x; 1752 normals[count++] = normal.y; 1753 normals[count++] = normal.z; 1754 1755 normals[count++] = normal.x; 1756 normals[count++] = normal.y; 1757 normals[count++] = normal.z; 1758 1759 count += 6; 1760 } 1761 1762 normals[count++] = normal.x; 1763 normals[count++] = normal.y; 1764 normals[count++] = normal.z; 1765 1766 normals[count + 9] = normal.x; 1767 normals[count + 10] = normal.y; 1768 normals[count + 11] = normal.z; 1769 1770 normals[count + 12] = normal.x; 1771 normals[count + 13] = normal.y; 1772 normals[count + 14] = normal.z; 1773 1774 createRadialFlatNormal(0); 1775 1776 normals[count++] = normal.x; 1777 normals[count++] = normal.y; 1778 normals[count++] = normal.z; 1779 1780 normals[count++] = normal.x; 1781 normals[count++] = normal.y; 1782 normals[count++] = normal.z; 1783 1784 normals[count++] = normal.x; 1785 normals[count++] = normal.y; 1786 normals[count++] = normal.z; 1787 1788 count += 6; 1789 } 1790 1791 // Now generate the top if we need it. 1792 if(useTop) 1793 { 1794 // The three vertices of the top in an unrolled loop 1795 for(i = facetCount; --i >= 0; ) 1796 { 1797 normals[count++] = 0; 1798 normals[count++] = 1; 1799 normals[count++] = 0; 1800 1801 normals[count++] = 0; 1802 normals[count++] = 1; 1803 normals[count++] = 0; 1804 1805 normals[count++] = 0; 1806 normals[count++] = 1; 1807 normals[count++] = 0; 1808 } 1809 1810 } 1811 1812 if (useBottom) 1813 { 1814 // The three vertices of the bottom in an unrolled loop 1815 for(i = facetCount; --i >= 0; ) 1816 { 1817 normals[count++] = 0; 1818 normals[count++] = -1; 1819 normals[count++] = 0; 1820 1821 normals[count++] = 0; 1822 normals[count++] = -1; 1823 normals[count++] = 0; 1824 1825 normals[count++] = 0; 1826 normals[count++] = -1; 1827 normals[count++] = 0; 1828 } 1829 } 1830 } 1831 1832 /** 1833 * Generate a new set of normals for a normal set of unindexed points. 1834 * Smooth normals are used for the sides at the average between the faces. 1835 * Bottom normals always point down. 1836 * <p> 1837 * This must always be called after the coordinate generation. 1838 * 1839 * @param data The data to base the calculations on 1840 * @throws InvalidArraySizeException The array is not big enough to contain 1841 * the requested geometry 1842 */ 1843 private void generateUnindexedTriStripNormals(GeometryData data) 1844 throws InvalidArraySizeException 1845 { 1846 int vtx_cnt = data.vertexCount * 3; 1847 1848 if(data.normals == null) 1849 data.normals = new float[vtx_cnt]; 1850 else if(data.normals.length < vtx_cnt) 1851 throw new InvalidArraySizeException("Normals", 1852 data.normals.length, 1853 vtx_cnt); 1854 1855 int i; 1856 float[] normals = data.normals; 1857 int count = 0; 1858 int vtx = 0; 1859 1860 if (useSide) 1861 { 1862 for(i = facetCount; --i >= 0; ) 1863 { 1864 createRadialFlatNormal(vtx++); 1865 1866 normals[count++] = normal.x; 1867 normals[count++] = normal.y; 1868 normals[count++] = normal.z; 1869 1870 normals[count++] = normal.x; 1871 normals[count++] = normal.y; 1872 normals[count++] = normal.z; 1873 } 1874 1875 // Last row of the facets is the same as the first items 1876 normals[count++] = normals[0]; 1877 normals[count++] = normals[1]; 1878 normals[count++] = normals[2]; 1879 1880 normals[count++] = normals[3]; 1881 normals[count++] = normals[4]; 1882 normals[count++] = normals[5]; 1883 } 1884 1885 // Now generate the top if we need it. 1886 if(useTop) 1887 { 1888 // The vertices of the top 1889 for(i = facetCount + 1; --i >= 0; ) 1890 { 1891 normals[count++] = 0; 1892 normals[count++] = 1; 1893 normals[count++] = 0; 1894 1895 normals[count++] = 0; 1896 normals[count++] = 1; 1897 normals[count++] = 0; 1898 } 1899 1900 } 1901 1902 if (useBottom) 1903 { 1904 // The vertices of the bottom 1905 for(i = facetCount + 1; --i >= 0; ) 1906 { 1907 normals[count++] = 0; 1908 normals[count++] = -1; 1909 normals[count++] = 0; 1910 1911 normals[count++] = 0; 1912 normals[count++] = -1; 1913 normals[count++] = 0; 1914 } 1915 } 1916 } 1917 1918 /** 1919 * Generate a new set of normals for a normal set of unindexed triangle 1920 * fan points. Smooth normals are used for the sides at the average 1921 * between the faces. Bottom normals always point down. 1922 * <p> 1923 * This must always be called after the coordinate generation. 1924 * 1925 * @param data The data to base the calculations on 1926 * @throws InvalidArraySizeException The array is not big enough to contain 1927 * the requested geometry 1928 */ 1929 private void generateUnindexedTriFanNormals(GeometryData data) 1930 throws InvalidArraySizeException 1931 { 1932 int vtx_cnt = data.vertexCount * 3; 1933 1934 if(data.normals == null) 1935 data.normals = new float[vtx_cnt]; 1936 else if(data.normals.length < vtx_cnt) 1937 throw new InvalidArraySizeException("Normals", 1938 data.normals.length, 1939 vtx_cnt); 1940 1941 int i; 1942 float[] normals = data.normals; 1943 int count = 0; 1944 int vtx = 0; 1945 1946 if (useSide) { 1947 createRadialFlatNormal(vtx++); 1948 1949 for(i = facetCount; --i > 0; ) 1950 { 1951 normals[count++] = normal.x; 1952 normals[count++] = normal.y; 1953 normals[count++] = normal.z; 1954 1955 normals[count++] = normal.x; 1956 normals[count++] = normal.y; 1957 normals[count++] = normal.z; 1958 1959 createRadialFlatNormal(vtx++); 1960 1961 normals[count++] = normal.x; 1962 normals[count++] = normal.y; 1963 normals[count++] = normal.z; 1964 1965 normals[count++] = normal.x; 1966 normals[count++] = normal.y; 1967 normals[count++] = normal.z; 1968 } 1969 1970 normals[count++] = normal.x; 1971 normals[count++] = normal.y; 1972 normals[count++] = normal.z; 1973 1974 normals[count++] = normal.x; 1975 normals[count++] = normal.y; 1976 normals[count++] = normal.z; 1977 1978 normals[count++] = normals[0]; 1979 normals[count++] = normals[1]; 1980 normals[count++] = normals[2]; 1981 1982 normals[count++] = normals[3]; 1983 normals[count++] = normals[4]; 1984 normals[count++] = normals[5]; 1985 } 1986 1987 // Now generate the bottom if we need it. 1988 if(useTop) 1989 { 1990 // The three vertices of the top in an unrolled loop 1991 for(i = facetCount + 2; --i >= 0; ) 1992 { 1993 normals[count++] = 0; 1994 normals[count++] = 1; 1995 normals[count++] = 0; 1996 } 1997 1998 } 1999 if (useBottom) 2000 { 2001 // The three vertices of the bottom in an unrolled loop 2002 for(i = facetCount + 2; --i >= 0; ) 2003 { 2004 normals[count++] = 0; 2005 normals[count++] = -1; 2006 normals[count++] = 0; 2007 } 2008 } 2009 } 2010 2011 /** 2012 * Generate a new set of normals for a normal set of unindexed points. 2013 * Smooth normals are used for the sides at the average between the faces. 2014 * Bottom normals always point down. 2015 * <p> 2016 * This must always be called after the coordinate generation. 2017 * 2018 * @param data The data to base the calculations on 2019 * @throws InvalidArraySizeException The array is not big enough to contain 2020 * the requested geometry 2021 */ 2022 private void generateUnindexedQuadNormals(GeometryData data) 2023 throws InvalidArraySizeException 2024 { 2025 int vtx_cnt = data.vertexCount * 3; 2026 2027 if(data.normals == null) 2028 data.normals = new float[vtx_cnt]; 2029 else if(data.normals.length < vtx_cnt) 2030 throw new InvalidArraySizeException("Normals", 2031 data.normals.length, 2032 vtx_cnt); 2033 2034 int i; 2035 float[] normals = data.normals; 2036 int count = 0; 2037 int vtx = 0; 2038 2039 if (useSide) 2040 { 2041 createRadialFlatNormal(vtx++); 2042 2043 for(i = facetCount; --i > 0; ) 2044 { 2045 normals[count++] = normal.x; 2046 normals[count++] = normal.y; 2047 normals[count++] = normal.z; 2048 2049 normals[count + 6] = normal.x; 2050 normals[count + 7] = normal.y; 2051 normals[count + 8] = normal.z; 2052 2053 createRadialFlatNormal(vtx++); 2054 2055 normals[count++] = normal.x; 2056 normals[count++] = normal.y; 2057 normals[count++] = normal.z; 2058 2059 normals[count++] = normal.x; 2060 normals[count++] = normal.y; 2061 normals[count++] = normal.z; 2062 2063 count += 3; 2064 } 2065 2066 normals[count++] = normal.x; 2067 normals[count++] = normal.y; 2068 normals[count++] = normal.z; 2069 2070 normals[count + 6] = normal.x; 2071 normals[count + 7] = normal.y; 2072 normals[count + 8] = normal.z; 2073 2074 createRadialFlatNormal(0); 2075 2076 normals[count++] = normal.x; 2077 normals[count++] = normal.y; 2078 normals[count++] = normal.z; 2079 2080 normals[count++] = normal.x; 2081 normals[count++] = normal.y; 2082 normals[count++] = normal.z; 2083 2084 count += 3; 2085 } 2086 2087 // Now generate the top if we need it. 2088 if(useTop) 2089 { 2090 // The three vertices of the top in an unrolled loop 2091 for(i = facetCount; --i >= 0; ) 2092 { 2093 normals[count++] = 0; 2094 normals[count++] = 1; 2095 normals[count++] = 0; 2096 2097 normals[count++] = 0; 2098 normals[count++] = 1; 2099 normals[count++] = 0; 2100 2101 normals[count++] = 0; 2102 normals[count++] = 1; 2103 normals[count++] = 0; 2104 2105 normals[count++] = 0; 2106 normals[count++] = 1; 2107 normals[count++] = 0; 2108 } 2109 2110 } 2111 if (useBottom) 2112 { 2113 // The three vertices of the bottom in an unrolled loop 2114 for(i = facetCount; --i >= 0; ) 2115 { 2116 normals[count++] = 0; 2117 normals[count++] = -1; 2118 normals[count++] = 0; 2119 2120 normals[count++] = 0; 2121 normals[count++] = -1; 2122 normals[count++] = 0; 2123 2124 normals[count++] = 0; 2125 normals[count++] = -1; 2126 normals[count++] = 0; 2127 2128 normals[count++] = 0; 2129 normals[count++] = -1; 2130 normals[count++] = 0; 2131 } 2132 } 2133 } 2134 2135 /** 2136 * Generate a new set of normals for a normal set of indexed points. 2137 * Smooth normals are used for the sides at the average between the faces. 2138 * Bottom normals always point down. 2139 * <p> 2140 * This must always be called after the coordinate generation. 2141 * 2142 * @param data The data to base the calculations on 2143 * @throws InvalidArraySizeException The array is not big enough to contain 2144 * the requested geometry 2145 */ 2146 private void generateIndexedNormals(GeometryData data) 2147 throws InvalidArraySizeException 2148 { 2149 int vtx_cnt = data.vertexCount * 3; 2150 2151 if(data.normals == null) 2152 data.normals = new float[vtx_cnt]; 2153 else if(data.normals.length < vtx_cnt) 2154 throw new InvalidArraySizeException("Normals", 2155 data.normals.length, 2156 vtx_cnt); 2157 2158 int i; 2159 float[] normals = data.normals; 2160 int count = 0; 2161 int vtx = 0; 2162 2163 if (useSide) 2164 { 2165 for(i = facetCount; --i >= 0; ) 2166 { 2167 createRadialFlatNormal(vtx++); 2168 2169 normals[count++] = normal.x; 2170 normals[count++] = normal.y; 2171 normals[count++] = normal.z; 2172 2173 normals[count++] = normal.x; 2174 normals[count++] = normal.y; 2175 normals[count++] = normal.z; 2176 } 2177 } 2178 2179 // Now generate the top if we need it. 2180 if(useTop) 2181 { 2182 // top 2183 for(i = facetCount + 1; --i >= 0; ) 2184 { 2185 normals[count++] = 0; 2186 normals[count++] = 1; 2187 normals[count++] = 0; 2188 } 2189 2190 } 2191 if (useBottom) 2192 { 2193 // bottom 2194 for(i = facetCount + 1; --i >= 0; ) 2195 { 2196 normals[count++] = 0; 2197 normals[count++] = -1; 2198 normals[count++] = 0; 2199 } 2200 } 2201 } 2202 2203 //------------------------------------------------------------------------ 2204 // Texture coordinate generation routines 2205 //------------------------------------------------------------------------ 2206 2207 /** 2208 * Generate a new set of texCoords for a normal set of unindexed points. Each 2209 * normal faces directly perpendicular for each point. This makes each face 2210 * seem flat. 2211 * <p> 2212 * This must always be called after the coordinate generation. 2213 * 2214 * @param data The data to base the calculations on 2215 * @throws InvalidArraySizeException The array is not big enough to contain 2216 * the requested geometry 2217 */ 2218 private void generateTriTexture2D(GeometryData data) 2219 throws InvalidArraySizeException 2220 { 2221 int vtx_cnt = data.vertexCount * 2; 2222 2223 if(data.textureCoordinates == null) 2224 data.textureCoordinates = new float[vtx_cnt]; 2225 else if(data.textureCoordinates.length < vtx_cnt) 2226 throw new InvalidArraySizeException("2D Texture coordinates", 2227 data.textureCoordinates.length, 2228 vtx_cnt); 2229 2230 recalc2DTexture(); 2231 2232 System.arraycopy(texCoordinates2D, 0, data.textureCoordinates, 0, vtx_cnt); 2233 float[] texCoords = data.textureCoordinates; 2234 } 2235 2236 /** 2237 * Generate a new set of texCoords for a normal set of unindexed points. Each 2238 * normal faces directly perpendicular for each point. This makes each face 2239 * seem flat. 2240 * <p> 2241 * This must always be called after the coordinate generation. 2242 * 2243 * @param data The data to base the calculations on 2244 * @throws InvalidArraySizeException The array is not big enough to contain 2245 * the requested geometry 2246 */ 2247 private void generateTriTexture3D(GeometryData data) 2248 throws InvalidArraySizeException 2249 { 2250 int vtx_cnt = data.vertexCount * 2; 2251 2252 if(data.textureCoordinates == null) 2253 data.textureCoordinates = new float[vtx_cnt]; 2254 else if(data.textureCoordinates.length < vtx_cnt) 2255 throw new InvalidArraySizeException("3D Texture coordinates", 2256 data.textureCoordinates.length, 2257 vtx_cnt); 2258 2259 float[] texCoords = data.textureCoordinates; 2260 } 2261 2262 /** 2263 * Regenerate the base coordinate points. These are the flat circle that 2264 * makes up the base of the code. The coordinates are generated based on 2265 * the 2 PI divided by the number of facets to generate. 2266 */ 2267 private final void regenerateBase() 2268 { 2269 if(!baseChanged) 2270 return; 2271 2272 baseChanged = false; 2273 2274 if((baseCoordinates == null) || 2275 (facetCount * 2 > baseCoordinates.length)) 2276 { 2277 baseCoordinates = new float[facetCount * 2]; 2278 } 2279 2280 numBaseValues = facetCount * 2; 2281 2282 // local constant to make math calcs faster 2283 double segment_angle = 2.0 * Math.PI / facetCount; 2284 int count = 0; 2285 float x, z; 2286 double angle; 2287 int i; 2288 double halfCount = (Math.PI / 2 - Math.PI / (facetCount / 2)); 2289 2290 // Reverse loop count because it is *much* faster than the forward 2291 // version. 2292 for(i = facetCount; --i >= 0; ) 2293 { 2294 angle = segment_angle * i; 2295 2296 x = (float)(radius * Math.cos(angle - halfCount)); 2297 z = (float)(radius * Math.sin(angle - halfCount)); 2298 2299 baseCoordinates[count++] = x; 2300 baseCoordinates[count++] = z; 2301 } 2302 } 2303 2304 /** 2305 * Recalculate the 2D texture coordinates IAW the coordinate values. This 2306 * starts by using the circumference as a T value of 0.5 to indicate it is 2307 * halfway through the texture (we are starting at the middle of the 2308 * sphere!). Then, if we have a bottom, we calculate the T from 0 to 0.5. 2309 * thus the coordinates are for the top half of the sphere, followed by 2310 * the bottom half. 2311 */ 2312 private void recalc2DTexture() 2313 { 2314 if(!facetsChanged) 2315 return; 2316 2317 // not a good idea because we should also leave this set to recalc 2318 // the 3D coordinates. 2319 facetsChanged = false; 2320 int vtx_count = 0; 2321 2322 if (useSide) 2323 vtx_count = (facetCount + 1) * 2; 2324 2325 if (useTop) 2326 vtx_count += (facetCount + 1) * 2; 2327 2328 if (useBottom) 2329 vtx_count += (facetCount + 1) * 2; 2330 2331 if((texCoordinates2D == null) || 2332 (vtx_count * 2 > texCoordinates2D.length)) 2333 { 2334 texCoordinates2D = new float[vtx_count * 2]; 2335 } 2336 2337 // local constant to make math calcs faster 2338 float segment_angle = 1 / (float)facetCount; 2339 float angle = (float)(2.0 * Math.PI / facetCount); 2340 2341 int count = 0; 2342 int i, k; 2343 float s, a; 2344 float[] bottom_s = new float[facetCount + 1]; 2345 float[] bottom_t = new float[facetCount + 1]; 2346 2347 if (useSide) 2348 { 2349 for(i = 0; i < facetCount; i++) 2350 { 2351 s = i * segment_angle; 2352 2353 texCoordinates2D[count++] = s; 2354 texCoordinates2D[count++] = 1; 2355 2356 texCoordinates2D[count++] = s; 2357 texCoordinates2D[count++] = 0; 2358 2359 a = i * angle; 2360 bottom_s[i] = (float)(0.5f - radius * Math.cos(a) / 2); 2361 bottom_t[i] = (float)(0.5f - radius * Math.sin(a) / 2); 2362 } 2363 2364 texCoordinates2D[count++] = 1; 2365 texCoordinates2D[count++] = 1; 2366 2367 texCoordinates2D[count++] = 1; 2368 texCoordinates2D[count++] = 0; 2369 } 2370 2371 if (useTop) 2372 { 2373 bottom_s[facetCount] = bottom_s[0]; 2374 bottom_t[facetCount] = bottom_t[0]; 2375 2376 // top is a flat square that is based with the centre at 2377 // the centre of the cone. Start with the centre point first 2378 2379 for(i = facetCount; --i >= 0; ) { 2380 texCoordinates2D[count++] = 0.5f; 2381 texCoordinates2D[count++] = 0.5f; 2382 2383 texCoordinates2D[count++] = bottom_s[i]; 2384 texCoordinates2D[count++] = bottom_t[i]; 2385 } 2386 2387 texCoordinates2D[count++] = 0.5f; 2388 texCoordinates2D[count++] = 0.5f; 2389 texCoordinates2D[count++] = bottom_s[0]; 2390 texCoordinates2D[count++] = bottom_t[1]; 2391 } 2392 2393 if (useBottom) 2394 { 2395 // Bottom is a flat square that is based with the centre at 2396 // the centre of the cone. Start with the centre point first 2397 2398 for(i = facetCount; --i >= 0; ) { 2399 texCoordinates2D[count++] = bottom_s[i]; 2400 texCoordinates2D[count++] = bottom_t[i]; 2401 2402 texCoordinates2D[count++] = 0.5f; 2403 texCoordinates2D[count++] = 0.5f; 2404 } 2405 2406 texCoordinates2D[count++] = bottom_s[0]; 2407 texCoordinates2D[count++] = bottom_t[1]; 2408 texCoordinates2D[count++] = 0.5f; 2409 texCoordinates2D[count++] = 0.5f; 2410 } 2411 2412 numTexCoords2D = count; 2413 } 2414 2415 /** 2416 * Create a normal based on the given vertex position, assuming that it is 2417 * a point in space, relative to the origin but also ignores the Y 2418 * component. This will create a normal that points directly along the 2419 * vector from the origin to the point along the X-Z plane. Useful for 2420 * doing cones and cylinders. 2421 * 2422 * @param p The facet index of the point to calculate 2423 * @param A temporary value containing the normal value 2424 */ 2425 private void createRadialFlatNormal(int p) 2426 { 2427 float x = baseCoordinates[p * 2]; 2428 float z = baseCoordinates[p * 2 + 1]; 2429 2430 float mag = x * x + z * z; 2431 2432 if(mag != 0.0) 2433 { 2434 mag = 1.0f / ((float) Math.sqrt(mag)); 2435 normal.x = x * mag; 2436 normal.y = 0; 2437 normal.z = z * mag; 2438 } 2439 else 2440 { 2441 normal.x = 0; 2442 normal.y = 0; 2443 normal.z = 0; 2444 } 2445 } 2446}