0001: /*
0002: * $RCSfile: GeometryInfo.java,v $
0003: *
0004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: *
0010: * - Redistribution of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * - Redistribution in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in
0015: * the documentation and/or other materials provided with the
0016: * distribution.
0017: *
0018: * Neither the name of Sun Microsystems, Inc. or the names of
0019: * contributors may be used to endorse or promote products derived
0020: * from this software without specific prior written permission.
0021: *
0022: * This software is provided "AS IS," without a warranty of any
0023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
0024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
0025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
0026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
0027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
0028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
0029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
0030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
0031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
0032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
0033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
0034: * POSSIBILITY OF SUCH DAMAGES.
0035: *
0036: * You acknowledge that this software is not designed, licensed or
0037: * intended for use in the design, construction, operation or
0038: * maintenance of any nuclear facility.
0039: *
0040: * $Revision: 1.4 $
0041: * $Date: 2007/02/09 17:20:19 $
0042: * $State: Exp $
0043: */
0044:
0045: package com.sun.j3d.utils.geometry;
0046:
0047: import com.sun.j3d.utils.geometry.Triangulator;
0048: import java.io.*;
0049: import javax.media.j3d.*;
0050: import javax.vecmath.*;
0051: import com.sun.j3d.internal.J3dUtilsI18N;
0052: import java.util.HashMap;
0053: import com.sun.j3d.utils.geometry.GeometryInfoGenerator;
0054: import com.sun.j3d.internal.BufferWrapper;
0055: import com.sun.j3d.internal.ByteBufferWrapper;
0056: import com.sun.j3d.internal.FloatBufferWrapper;
0057: import com.sun.j3d.internal.DoubleBufferWrapper;
0058: import com.sun.j3d.internal.ByteOrderWrapper;
0059: import javax.media.j3d.J3DBuffer;
0060:
0061: /**
0062: * The GeometryInfo object holds data for processing by the Java3D geometry
0063: * utility tools.<p><blockquote>
0064: *
0065: * The NormalGenerator adds normals to geometry without normals.<p>
0066: *
0067: * The Stripifier combines adjacent triangles into triangle strips for
0068: * more efficent rendering.<p></blockquote>
0069: *
0070: * Also, the GeometryCompressor can take a set of GeometryInfo objects in a
0071: * CompressionSteam and generate a CompressedGeometry object from the
0072: * geometry.<p>
0073: * Geometry is loaded into a GeometryInfo in a manner similar to the
0074: * <a href="../../../../../javax/media/j3d/GeometryArray.html">
0075: * GeometryArray</a> methods. The constructor for the GeometryInfo takes a flag
0076: * that specifies the kind of data being loaded. The vertex data is
0077: * specified using methods that are similar to the GeometryArray methods, but
0078: * with fewer variations.<p>
0079: * The major difference between GeometryInfo and GeometryArray is
0080: * that the number of vertices, vertex format, and other data are specified
0081: * implictly, rather than as part of the constructor. The number of verticies
0082: * comes from the number of coordinates passed to the setCoordinates()
0083: * method. The format comes from the set of data components that are
0084: * specified. For example, calling the setCoordinates(), setColors3() and
0085: * setTextureCoordinatesParames(1, 2) methods implies a
0086: * format of COORDINATES | COLOR_3
0087: * | TEXTURE_COORDINATE_2. Indexed representation is specified by calling
0088: * the methods that specify the indices, for example
0089: * setCoordinateIndices().<p>
0090: * Stripped primitives are loaded using the TRIANGLE_FAN_ARRAY or
0091: * TRIANGLE_STRIP_ARRAY flags to the constructor. The setStripCounts()
0092: * method specifies the length of each strip.<p>
0093: * A set of complex polygons is loaded using the POLYGON_ARRAY
0094: * flag to the constructor. The setStripCounts() method specifies the length
0095: * of each contour of the polygons. The setContourCounts() method specifies
0096: * the number of countours in each polygon. For example, a triangle with a
0097: * triangular hole would have strip counts [3, 3] (indicating two contours of
0098: * three points) and contour counts [2] (indicating a single polygon with two
0099: * contours).<p>
0100: * GeometryInfo itelf contains some simple utilities, such as
0101: * calculating indices for non-indexed data ("indexifying") and getting rid
0102: * of unused data in your indexed geometry ("compacting").<p>
0103: * The geometry utility tools modify the contents of the
0104: * GeometryInfo. After processing, the resulting geometry can be extracted
0105: * from the GeometryInfo by calling getGeometryArray(). If multiple tools
0106: * are used, the order of processing should be: generate normals, then
0107: * stripify. For example, to convert a general mesh of polygons without
0108: * normals into an optimized mesh call:
0109: * <pre><blockquote>
0110: * GeometryInfo gi = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
0111: * // initialize the geometry info here
0112: * // generate normals
0113: * NormalGenerator ng = new NormalGenerator();
0114: * ng.generateNormals(gi);
0115: * // stripify
0116: * Stripifier st = new Stripifier();
0117: * st.stripify(gi);
0118: * GeometryArray result = gi.getGeometryArray();
0119: * </blockquote></pre>
0120: *
0121: * @see NormalGenerator
0122: * @see Stripifier
0123: * @see com.sun.j3d.utils.compression.CompressionStream
0124: * @see com.sun.j3d.utils.compression.GeometryCompressor
0125: * @see javax.media.j3d.GeometryArray
0126: */
0127:
0128: public class GeometryInfo {
0129:
0130: /**
0131: * Send to the constructor to inform that the data will be arranged so
0132: * that each set of three vertices form an independent triangle
0133: */
0134: public static final int TRIANGLE_ARRAY = 1;
0135:
0136: /**
0137: * Send to the constructor to inform that the data will be arranged so
0138: * that each set of four vertices form an independent quad
0139: */
0140: public static final int QUAD_ARRAY = 2;
0141:
0142: /**
0143: * Send to the constructor to inform that the data will be arranged so
0144: * that the stripCounts array indicates how many vertices to use
0145: * for each triangle fan.
0146: */
0147: public static final int TRIANGLE_FAN_ARRAY = 3;
0148:
0149: /**
0150: * Send to the constructor to inform that the data will be arranged so
0151: * that the stripCounts array indicates how many vertices to use
0152: * for each triangle strip.
0153: */
0154: public static final int TRIANGLE_STRIP_ARRAY = 4;
0155:
0156: /**
0157: * Send to the constructor to inform that the data is arranged as
0158: * possibly multi-contour, possible non-planar polygons.
0159: * The stripCounts array indicates how many vertices to use
0160: * for each contour, and the contourCounts array indicates how many
0161: * stripCounts entries to use for each polygon. The first
0162: * contour is the bounding polygon, and subsequent contours are
0163: * "holes." If contourCounts is left null, the default is
0164: * one contour per polygon.
0165: */
0166: public static final int POLYGON_ARRAY = 5;
0167:
0168: private int prim;
0169:
0170: // 1 Show indexification details
0171: private static final int DEBUG = 0;
0172:
0173: private Point3f coordinates[] = null;
0174: private Color3f colors3[] = null;
0175: private Color4f colors4[] = null;
0176: private Vector3f normals[] = null;
0177: private Object texCoordSets[][] = null;
0178:
0179: private int coordinateIndices[] = null;
0180: private int colorIndices[] = null;
0181: private int normalIndices[] = null;
0182: private int texCoordIndexSets[][] = null;
0183:
0184: private int[] texCoordSetMap = null;
0185: private int texCoordSetCount = 0;
0186: private int texCoordDim = 0;
0187:
0188: private int stripCounts[] = null;
0189: private int contourCounts[] = null;
0190:
0191: private Triangulator tr = null;
0192: private NormalGenerator ng = null;
0193:
0194: private int oldPrim = 0;
0195: private int oldStripCounts[] = null;
0196:
0197: private boolean coordOnly = false;
0198:
0199: /**
0200: * Constructor.
0201: * Creates an empty GeometryInfo object.
0202: * @param primitive Tells the GeometryInfo object the type of
0203: * primitive data to be stored
0204: * in it, so it will know the format of the data. It can be one of
0205: * TRIANGLE_ARRAY,
0206: * QUAD_ARRAY, TRIANGLE_FAN_ARRAY, TRIANGLE_STRIP_ARRAY, or POLYGON_ARRAY.
0207: */
0208: public GeometryInfo(int primitive) {
0209: if ((primitive >= TRIANGLE_ARRAY)
0210: && (primitive <= POLYGON_ARRAY)) {
0211: prim = primitive;
0212: } else {
0213: throw new IllegalArgumentException(J3dUtilsI18N
0214: .getString("GeometryInfo0"));
0215: }
0216: } // End of GeometryInfo(int)
0217:
0218: /**
0219: * Contructor. Populates the GeometryInfo with the geometry from
0220: * the GeometryArray.<p>
0221: * If the GeometryArray uses the <code>Initial</code> and
0222: * <code>Valid</code> GeometryArray methods (<code>
0223: * setInitialVertexIndex()</code> and <code>setValidVertexCount()
0224: * </code> and their cousins) then only the needed geometry
0225: * is copied into the GeometryInfo.
0226: */
0227: public GeometryInfo(GeometryArray ga) {
0228: GeometryInfoGenerator.create(this , ga);
0229: } // End of GeometryInfo(GeometryArray)
0230:
0231: /**
0232: * Removes all data from the GeometryInfo and resets the primitive.
0233: * After a call to reset(), the GeometryInfo object will be just like
0234: * it was when it was newly constructed.
0235: * @param primitive Either TRIANGLE_ARRAY, QUAD_ARRAY,
0236: * TRIANGLE_FAN_ARRAY, TRIANGLE_STRIP_ARRAY, or POLYGON_ARRAY.
0237: * Tells the GeometryInfo object the type of primitive data to be stored
0238: * in it, so it will know the format of the data.
0239: */
0240: public void reset(int primitive) {
0241: if ((primitive >= TRIANGLE_ARRAY)
0242: && (primitive <= POLYGON_ARRAY)) {
0243: prim = primitive;
0244: } else {
0245: throw new IllegalArgumentException(J3dUtilsI18N
0246: .getString("GeometryInfo0"));
0247: }
0248:
0249: coordinates = null;
0250: colors3 = null;
0251: colors4 = null;
0252: normals = null;
0253:
0254: coordinateIndices = null;
0255: colorIndices = null;
0256: normalIndices = null;
0257:
0258: stripCounts = null;
0259: contourCounts = null;
0260:
0261: oldPrim = 0;
0262: oldStripCounts = null;
0263:
0264: texCoordDim = 0;
0265: texCoordSetCount = 0;
0266: texCoordSets = null;
0267: texCoordIndexSets = null;
0268: texCoordSetMap = null;
0269:
0270: coordOnly = false;
0271:
0272: } // End of reset(int)
0273:
0274: /**
0275: * Removes all data from this GeometryInfo and populates it with
0276: * the geometry from the GeometryArray.
0277: */
0278: public void reset(GeometryArray ga) {
0279: GeometryInfoGenerator.create(this , ga);
0280: } // End of reset(GeometryArray)
0281:
0282: // This method takes an indexed quad array and expands it to
0283: // a list of indexed triangles. It is used for the Coordinate
0284: // indices as well as the color and texture indices.
0285: private int[] expandQuad(int indices[]) {
0286: int triangles[] = new int[indices.length / 4 * 6];
0287:
0288: for (int i = 0; i < indices.length / 4; i++) {
0289: triangles[i * 6 + 0] = indices[i * 4];
0290: triangles[i * 6 + 1] = indices[i * 4 + 1];
0291: triangles[i * 6 + 2] = indices[i * 4 + 2];
0292: triangles[i * 6 + 3] = indices[i * 4];
0293: triangles[i * 6 + 4] = indices[i * 4 + 2];
0294: triangles[i * 6 + 5] = indices[i * 4 + 3];
0295: }
0296:
0297: return triangles;
0298: } // End of expandQuad
0299:
0300: // This method takes an indexed triangle fan and expands it to
0301: // a list of indexed triangles. It is used for the Coordinate
0302: // indices as well as the color and texture indices.
0303: private int[] expandTriFan(int numTris, int indices[]) {
0304: int triangles[] = new int[numTris * 3];
0305: int p = 0;
0306: int base = 0;
0307: for (int f = 0; f < stripCounts.length; f++) {
0308: for (int t = 0; t < stripCounts[f] - 2; t++) {
0309: triangles[p++] = indices[base];
0310: triangles[p++] = indices[base + t + 1];
0311: triangles[p++] = indices[base + t + 2];
0312: }
0313: base += stripCounts[f];
0314: }
0315: return triangles;
0316: } // End of expandTriFan
0317:
0318: // This method takes an indexed triangle strip and expands it to
0319: // a list of indexed triangles. It is used for the Coordinate
0320: // indices as well as the color and texture indices.
0321: private int[] expandTriStrip(int numTris, int indices[]) {
0322: int triangles[] = new int[numTris * 3];
0323:
0324: int p = 0;
0325: int base = 0;
0326: for (int s = 0; s < stripCounts.length; s++) {
0327: for (int t = 0; t < stripCounts[s] - 2; t++) {
0328:
0329: // Use a ping-ponging algorithm to reverse order on every other
0330: // triangle to preserve winding
0331: if (t % 2 == 0) {
0332: triangles[p++] = indices[base + t + 0];
0333: triangles[p++] = indices[base + t + 1];
0334: triangles[p++] = indices[base + t + 2];
0335: } else {
0336: triangles[p++] = indices[base + t + 0];
0337: triangles[p++] = indices[base + t + 2];
0338: triangles[p++] = indices[base + t + 1];
0339: }
0340: }
0341: base += stripCounts[s];
0342: }
0343:
0344: return triangles;
0345: } // End of expandTriStrip
0346:
0347: // Used by the NormalGenerator utility. Informs the GeometryInfo object
0348: // to remember its current primitive and stripCounts arrays so that
0349: // they can be used to convert the object back to its original
0350: // primitive
0351: void rememberOldPrim() {
0352: oldPrim = prim;
0353: oldStripCounts = stripCounts;
0354: } // End of rememberOldPrim
0355:
0356: // The NormalGenerator needs to know the original primitive for
0357: // facet normal generation for quads
0358: int getOldPrim() {
0359: return oldPrim;
0360: } // End of getOldPrim
0361:
0362: // Used by the Utility libraries other than the NormalGenerator.
0363: // Informs the GeometryInfo object that the geometry need not
0364: // be converted back to the original primitive before returning.
0365: // For example, if a list of Fans is sent, converted to Triangles
0366: // for normal generation, and then stripified by the Stripifyer,
0367: // we want to make sure that GeometryInfo doesn't convert the
0368: // geometry *back* to fans before creating the output GeometryArray.
0369: void forgetOldPrim() {
0370: oldPrim = 0;
0371: oldStripCounts = null;
0372: } // End of forgetOldPrim
0373:
0374: // We have changed the user's data from their original primitive
0375: // type to TRIANGLE_ARRAY. If this method is being called, it
0376: // means we need to change it back (to try and hide from the user
0377: // the fact that we've converted). This usually happens when
0378: // the user has used GeometryInfo for generating normals, but
0379: // they are not Stripifying or Triangulating. The function is
0380: // called from getGeometryArray before creating the output data.
0381: private void changeBackToOldPrim() {
0382: if (oldPrim != 0) {
0383: convertToIndexedTriangles();
0384: if (ng == null)
0385: ng = new NormalGenerator();
0386: ng.convertBackToOldPrim(this , oldPrim, oldStripCounts);
0387: oldPrim = 0;
0388: oldStripCounts = null;
0389: }
0390: } // End of changeBackToOldPrim
0391:
0392: /**
0393: * Convert the GeometryInfo object to have primitive type TRIANGLE_ARRAY
0394: * and be indexed.
0395: * @throws IllegalArgumentException if coordinate data is missing,
0396: * if the index lists aren't all the
0397: * same length, if an index list is set and the corresponding data
0398: * list isn't set, if a data list is set and the corresponding
0399: * index list is unset (unless all index lists are unset or in
0400: * USE_COORD_INDEX_ONLY format),
0401: * if StripCounts or ContourCounts is inconsistent with the current
0402: * primitive, if the sum of the contourCounts array doesn't equal
0403: * the length of the StripCounts array, or if the number of vertices
0404: * isn't a multiple of three (for triangles) or four (for quads).
0405: */
0406: public void convertToIndexedTriangles() {
0407: int triangles = 0;
0408:
0409: // This calls checkForBadData
0410: indexify();
0411:
0412: if (prim == TRIANGLE_ARRAY)
0413: return;
0414:
0415: switch (prim) {
0416:
0417: case QUAD_ARRAY:
0418:
0419: coordinateIndices = expandQuad(coordinateIndices);
0420: if (colorIndices != null)
0421: colorIndices = expandQuad(colorIndices);
0422: if (normalIndices != null)
0423: normalIndices = expandQuad(normalIndices);
0424: for (int i = 0; i < texCoordSetCount; i++)
0425: texCoordIndexSets[i] = expandQuad(texCoordIndexSets[i]);
0426: break;
0427:
0428: case TRIANGLE_FAN_ARRAY:
0429: // Count how many triangles are in the object
0430: for (int i = 0; i < stripCounts.length; i++) {
0431: triangles += stripCounts[i] - 2;
0432: }
0433:
0434: coordinateIndices = expandTriFan(triangles,
0435: coordinateIndices);
0436: if (colorIndices != null)
0437: colorIndices = expandTriFan(triangles, colorIndices);
0438: if (normalIndices != null)
0439: normalIndices = expandTriFan(triangles, normalIndices);
0440: for (int i = 0; i < texCoordSetCount; i++)
0441: texCoordIndexSets[i] = expandTriFan(triangles,
0442: texCoordIndexSets[i]);
0443: break;
0444:
0445: case TRIANGLE_STRIP_ARRAY:
0446: // Count how many triangles are in the object
0447: for (int i = 0; i < stripCounts.length; i++) {
0448: triangles += stripCounts[i] - 2;
0449: }
0450:
0451: coordinateIndices = expandTriStrip(triangles,
0452: coordinateIndices);
0453: if (colorIndices != null)
0454: colorIndices = expandTriStrip(triangles, colorIndices);
0455: if (normalIndices != null)
0456: normalIndices = expandTriStrip(triangles, normalIndices);
0457: for (int i = 0; i < texCoordSetCount; i++)
0458: texCoordIndexSets[i] = expandTriStrip(triangles,
0459: texCoordIndexSets[i]);
0460: break;
0461:
0462: case POLYGON_ARRAY:
0463: if (tr == null)
0464: tr = new Triangulator();
0465: tr.triangulate(this );
0466: break;
0467: }
0468:
0469: prim = TRIANGLE_ARRAY;
0470: stripCounts = null;
0471: } // End of convertToIndexedTriangles
0472:
0473: /**
0474: * Get the current primitive. Some of the utilities may change the
0475: * primitive type of the data stored in the GeometryInfo object
0476: * (for example, the stripifyer will change it to TRIANGLE_STRIP_ARRAY).
0477: */
0478: public int getPrimitive() {
0479: return prim;
0480: } // End of getPrimitive()
0481:
0482: /**
0483: * Set the current primitive. Some of the utilities may change the
0484: * primitive type of the data stored in the GeometryInfo object
0485: * (for example, the stripifyer will change it to TRIANGLE_STRIP_ARRAY).
0486: * But the user can't change the primitive type - it is set in the
0487: * constructor. Therefore, this method has package scope.
0488: */
0489: void setPrimitive(int primitive) {
0490: if ((prim >= TRIANGLE_ARRAY) && (prim <= POLYGON_ARRAY)) {
0491: prim = primitive;
0492: } else {
0493: throw new IllegalArgumentException(J3dUtilsI18N
0494: .getString("GeometryInfo0"));
0495: }
0496: } // End of setPrimitive()
0497:
0498: /**
0499: * Sets the coordinates array.
0500: * No data copying is done because a reference to user data is used.
0501: */
0502: public void setCoordinates(Point3f coordinates[]) {
0503: this .coordinates = coordinates;
0504: } // End of setCoordinates
0505:
0506: /**
0507: * Sets the coordinates array.
0508: * The points are copied into the GeometryInfo object.
0509: */
0510: public void setCoordinates(Point3d coordinates[]) {
0511: if (coordinates == null)
0512: this .coordinates = null;
0513: else {
0514: this .coordinates = new Point3f[coordinates.length];
0515: for (int i = 0; i < coordinates.length; i++) {
0516: this .coordinates[i] = new Point3f(
0517: (float) (coordinates[i].x),
0518: (float) (coordinates[i].y),
0519: (float) (coordinates[i].z));
0520: }
0521: }
0522: } // End of setCoordinates
0523:
0524: /**
0525: * Sets the coordinates array.
0526: * The points are copied into the GeometryInfo object.
0527: */
0528: public void setCoordinates(float coordinates[]) {
0529: if (coordinates == null)
0530: this .coordinates = null;
0531: else {
0532: this .coordinates = new Point3f[coordinates.length / 3];
0533: for (int i = 0; i < this .coordinates.length; i++) {
0534: this .coordinates[i] = new Point3f(coordinates[i * 3],
0535: coordinates[i * 3 + 1], coordinates[i * 3 + 2]);
0536: }
0537: }
0538: } // End of setCoordinates
0539:
0540: /**
0541: * Sets the coordinates array.
0542: * The points are copied into the GeometryInfo object.
0543: */
0544: public void setCoordinates(double coordinates[]) {
0545: if (coordinates == null)
0546: this .coordinates = null;
0547: else {
0548: this .coordinates = new Point3f[coordinates.length / 3];
0549: for (int i = 0; i < coordinates.length / 3; i++) {
0550: this .coordinates[i] = new Point3f(
0551: (float) coordinates[i * 3],
0552: (float) coordinates[i * 3 + 1],
0553: (float) coordinates[i * 3 + 2]);
0554: }
0555: }
0556: } // End of setCoordinates
0557:
0558: /**
0559: * Retrieves a reference to the coordinate array.
0560: */
0561: public Point3f[] getCoordinates() {
0562: return coordinates;
0563: } // End of getCoordinates
0564:
0565: /**
0566: * Sets the colors array.
0567: * No data copying is done because a reference to
0568: * user data is used.
0569: */
0570: public void setColors(Color3f colors[]) {
0571: colors3 = colors;
0572: colors4 = null;
0573: } // End of setColors
0574:
0575: /**
0576: * Sets the colors array.
0577: * No data copying is done because a reference to
0578: * user data is used.
0579: */
0580: public void setColors(Color4f colors[]) {
0581: colors3 = null;
0582: colors4 = colors;
0583: } // End of setColors
0584:
0585: /**
0586: * Sets the colors array.
0587: * The points are copied into the GeometryInfo object.
0588: */
0589: public void setColors(Color3b colors[]) {
0590: if (colors == null) {
0591: colors3 = null;
0592: colors4 = null;
0593: } else {
0594: colors3 = new Color3f[colors.length];
0595: colors4 = null;
0596: for (int i = 0; i < colors.length; i++) {
0597: colors3[i] = new Color3f(
0598: (float) (colors[i].x & 0xff) / 255.0f,
0599: (float) (colors[i].y & 0xff) / 255.0f,
0600: (float) (colors[i].z & 0xff) / 255.0f);
0601: }
0602: }
0603: } // End of setColors
0604:
0605: /**
0606: * Sets the colors array.
0607: * The points are copied into the GeometryInfo object.
0608: */
0609: public void setColors(Color4b colors[]) {
0610: if (colors == null) {
0611: colors3 = null;
0612: colors4 = null;
0613: } else {
0614: colors3 = null;
0615: colors4 = new Color4f[colors.length];
0616: for (int i = 0; i < colors.length; i++) {
0617: colors4[i] = new Color4f(
0618: (float) (colors[i].x & 0xff) / 255.0f,
0619: (float) (colors[i].y & 0xff) / 255.0f,
0620: (float) (colors[i].z & 0xff) / 255.0f,
0621: (float) (colors[i].w & 0xff) / 255.0f);
0622: }
0623: }
0624: } // End of setColors
0625:
0626: /**
0627: * Sets the colors array.
0628: * The points are copied into the GeometryInfo object, assuming
0629: * 3 components (R, G, and B) per vertex.
0630: */
0631: public void setColors3(float colors[]) {
0632: if (colors == null) {
0633: colors3 = null;
0634: colors4 = null;
0635: } else {
0636: colors3 = new Color3f[colors.length / 3];
0637: colors4 = null;
0638: for (int i = 0; i < colors.length / 3; i++) {
0639: colors3[i] = new Color3f(colors[i * 3],
0640: colors[i * 3 + 1], colors[i * 3 + 2]);
0641: }
0642: }
0643: } // End of setColors3
0644:
0645: /**
0646: * Sets the colors array.
0647: * The points are copied into the GeometryInfo object, assuming
0648: * 4 components (R, G, B, and A) per vertex.
0649: */
0650: public void setColors4(float colors[]) {
0651: if (colors == null) {
0652: colors3 = null;
0653: colors4 = null;
0654: } else {
0655: colors3 = null;
0656: colors4 = new Color4f[colors.length / 4];
0657: for (int i = 0; i < colors.length / 4; i++) {
0658: colors4[i] = new Color4f(colors[i * 4],
0659: colors[i * 4 + 1], colors[i * 4 + 2],
0660: colors[i * 4 + 3]);
0661: }
0662: }
0663: } // End of setColors4
0664:
0665: /**
0666: * Sets the colors array.
0667: * The points are copied into the GeometryInfo object, assuming
0668: * 3 components (R, G, and B) per vertex.
0669: */
0670: public void setColors3(byte colors[]) {
0671: if (colors == null) {
0672: colors3 = null;
0673: colors4 = null;
0674: } else {
0675: colors3 = new Color3f[colors.length / 3];
0676: colors4 = null;
0677: for (int i = 0; i < colors.length / 3; i++) {
0678: colors3[i] = new Color3f(
0679: (float) (colors[i * 3] & 0xff) / 255.0f,
0680: (float) (colors[i * 3 + 1] & 0xff) / 255.0f,
0681: (float) (colors[i * 3 + 2] & 0xff) / 255.0f);
0682: }
0683: }
0684: } // End of setColors3
0685:
0686: /**
0687: * Sets the colors array.
0688: * The points are copied into the GeometryInfo object, assuming
0689: * 4 components (R, G, B, and A) per vertex.
0690: */
0691: public void setColors4(byte colors[]) {
0692: if (colors == null) {
0693: colors3 = null;
0694: colors4 = null;
0695: } else {
0696: colors3 = null;
0697: colors4 = new Color4f[colors.length / 4];
0698: for (int i = 0; i < colors.length / 4; i++) {
0699: colors4[i] = new Color4f(
0700: (float) (colors[i * 4] & 0xff) / 255.0f,
0701: (float) (colors[i * 4 + 1] & 0xff) / 255.0f,
0702: (float) (colors[i * 4 + 2] & 0xff) / 255.0f,
0703: (float) (colors[i * 4 + 3] & 0xff) / 255.0f);
0704: }
0705: }
0706: } // End of setColors4
0707:
0708: /**
0709: * Retrieves a reference to the colors array. Will be either
0710: * <code>Color3f[]</code> or <code>Color4f[]</code> depending on
0711: * the type of the input data. Call
0712: * getNumColorComponents() to find out which version is returned.
0713: */
0714: public Object[] getColors() {
0715: if (colors3 != null)
0716: return colors3;
0717: else
0718: return colors4;
0719: } // End of getColors
0720:
0721: /**
0722: * Returns the number of color data components stored per vertex
0723: * in the current GeometryInfo object (3 for RGB or 4 for RGBA).
0724: * If no colors are currently defined, 0 is returned.
0725: */
0726: public int getNumColorComponents() {
0727: if (colors3 != null)
0728: return 3;
0729: else if (colors4 != null)
0730: return 4;
0731: else
0732: return 0;
0733: } // End of getNumColorComponents
0734:
0735: /**
0736: * Sets the normals array.
0737: * No data copying is done because a reference to
0738: * user data is used.
0739: */
0740: public void setNormals(Vector3f normals[]) {
0741: this .normals = normals;
0742: } // End of setNormals
0743:
0744: /**
0745: * Sets the normals array.
0746: * The points are copied into the GeometryInfo object.
0747: */
0748: public void setNormals(float normals[]) {
0749: if (normals == null)
0750: this .normals = null;
0751: else {
0752: this .normals = new Vector3f[normals.length / 3];
0753: for (int i = 0; i < this .normals.length; i++) {
0754: this .normals[i] = new Vector3f(normals[i * 3],
0755: normals[i * 3 + 1], normals[i * 3 + 2]);
0756: }
0757: }
0758: } // End of setNormals(float[])
0759:
0760: /**
0761: * Retrieves a reference to the normal array.
0762: */
0763: public Vector3f[] getNormals() {
0764: return normals;
0765: } // End of getNormals
0766:
0767: /**
0768: * This method is used to specify the number of texture coordinate sets
0769: * and the dimensionality of the texture coordinates.
0770: * The number of texture coordinate sets must be specified to the GeometryInfo
0771: * class before any of the sets are specified. The dimensionality of the
0772: * texture coordinates may be 2, 3, or 4, corresponding to 2D, 3D, or 4D
0773: * texture coordinates respectively.(All sets must have the same
0774: * dimensionality.) The default is zero, 2D texture coordinate sets.
0775: * This method should be called before any texture coordinate sets are
0776: * specified because <b>calling this method will delete all previously
0777: * specified texture coordinate and texture coordinate index arrays</b>
0778: * associated with this GeometryInfo. For example:
0779: * <blockquote><pre>
0780: * geomInfo.setTextureCoordinateParams(2, 3);
0781: * geomInfo.setTextureCoordinates(0, tex0);
0782: * geomInfo.setTextureCoordinates(1, tex1);
0783: * geomInfo.setTextureCoordinateParams(1, 2);
0784: * geomInfo.getTexCoordSetCount();
0785: * </blockquote></pre>
0786: * The second call to <code>setTextureCoordinateParams</code> will erase all
0787: * the texture coordinate arrays, so the subsequent call to <code>
0788: * getTexCoordSetCount</code> will return 1.
0789: * @param numSets The number of texture coordinate sets that will be
0790: * specified for this GeometryInfo object.
0791: * @param dim The dimensionality of the texture coordinates. Has to be 2, 3
0792: * or 4.
0793: * @throws IllegalArgumentException if the dimensionality of the texture
0794: * coordinates is not one of 2, 3 or 4.
0795: */
0796: public void setTextureCoordinateParams(int numSets, int dim) {
0797: if (dim == 2) {
0798: texCoordSets = new TexCoord2f[numSets][];
0799: } else if (dim == 3) {
0800: texCoordSets = new TexCoord3f[numSets][];
0801: } else if (dim == 4) {
0802: texCoordSets = new TexCoord4f[numSets][];
0803: } else {
0804: throw new IllegalArgumentException(J3dUtilsI18N
0805: .getString("GeometryInfo9"));
0806: }
0807: texCoordIndexSets = new int[numSets][];
0808: texCoordDim = dim;
0809: texCoordSetCount = numSets;
0810: } // End of setTextureCoordinateParams
0811:
0812: /**
0813: * Returns the number of texture coordinate sets in this GeometryInfo.
0814: * This value is set with setTextureCoordinateParams().
0815: * If setTextureCoordinateParams()
0816: * has not been called, 0 is returned unless one of the deprecated
0817: * texture coordinate methods has been called. Calling one of the
0818: * deprecated texture coordinate methods sets the count to 1.
0819: * The deprecated texture coordinate methods are those that don't
0820: * take texCoordSet as the first parameter.
0821: * @return the number of texture coordinate sets in this
0822: * GeometryInfo.
0823: */
0824: public int getTexCoordSetCount() {
0825: return texCoordSetCount;
0826: }
0827:
0828: /**
0829: * Returns the number of texture coordinate components that are stored
0830: * per vertex. Returns 2 for ST (2D), 3 for STR (3D),
0831: * or 4 for STRQ (4D), aslo known as the "dimensionality" of the
0832: * coordinates. This value is set with
0833: * setTextureCoordinateParams(). If setTextureCoordinateParams()
0834: * has not been called, 0 is returned unless one of the deprecated
0835: * texture coordinate methods has been called. Calling one of the
0836: * deprecated texture coordinate methods sets the dimensionality
0837: * explicitly (if you called setTextureCoordinates(Point2f[]) then
0838: * 2 is returned).
0839: * The deprecated texture coordinate methods are those that don't
0840: * take texCoordSet as the first parameter.
0841: */
0842: public int getNumTexCoordComponents() {
0843: return texCoordDim;
0844: } // End of getNumTexCoordComponents
0845:
0846: /**
0847: * Sets the mapping between texture coordinate sets and texture units.
0848: * See the
0849: * <a href="../../../../../javax/media/j3d/GeometryArray.html#texCoordSetMap">
0850: * GeometryArray constructor </a> for further details.
0851: * <p> <b>Note:</b> If the texCoordSetMap is not set, multi-texturing is
0852: * turned off. Only the texture coordinate set at index 0 (if set) will be
0853: * used. Any other sets specified by the GeometryInfo.setTextureCoordinate*
0854: * methods will be ignored.
0855: */
0856: public void setTexCoordSetMap(int map[]) {
0857: texCoordSetMap = map;
0858: }
0859:
0860: /**
0861: * Returns a reference to the texture coordinate set map.
0862: * See the
0863: * <a href="../../../../../javax/media/j3d/GeometryArray.html#texCoordSetMap">
0864: * GeometryArray constructor </a> for further details.
0865: */
0866: public int[] getTexCoordSetMap() {
0867: return texCoordSetMap;
0868: }
0869:
0870: /**
0871: * Sets the 2D texture coordinates for the specified set.
0872: * No data copying is done - a reference to user data is used.
0873: * @param texCoordSet The texture coordinate set for which these
0874: * coordinates are being specified.
0875: * @param texCoords Array of 2D texture coordinates.
0876: * @throws IllegalArgumentException if <code>texCoordSet </code> < 0 or
0877: * <code>texCoordSet >= texCoordSetCount</code>,
0878: * or the texture coordinate parameters were not previously set by
0879: * calling <code>setTextureCoordinateParams(texCoordSetCount, 2)</code>.
0880: */
0881: public void setTextureCoordinates(int texCoordSet,
0882: TexCoord2f texCoords[]) {
0883: if (texCoordDim != 2)
0884: throw new IllegalArgumentException(J3dUtilsI18N
0885: .getString("GeometryInfo15"));
0886: if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
0887: throw new IllegalArgumentException(J3dUtilsI18N
0888: .getString("GeometryInfo18"));
0889:
0890: texCoordSets[texCoordSet] = texCoords;
0891: } // End of setTextureCoordinates(int, TexCoord3f[])
0892:
0893: /**
0894: * Sets the TextureCoordinates array by copying the data
0895: * into the GeometryInfo object.
0896: * This method sets the number of texture coordinate sets to 1,
0897: * sets the dimensionality of the texture coordinates to 2,
0898: * and sets the coordinates for texture coordinate set 0.
0899: * @deprecated As of Java 3D 1.3 replaced by
0900: * <code>setTextureCoordinates(int texCoordSet, TexCoord2f coords[])</code>
0901: */
0902: public void setTextureCoordinates(Point2f texCoords[]) {
0903: texCoordSetCount = 1;
0904: texCoordDim = 2;
0905: texCoordSets = new TexCoord2f[1][];
0906: if (texCoords != null) {
0907: TexCoord2f[] tex = new TexCoord2f[texCoords.length];
0908: for (int i = 0; i < texCoords.length; i++)
0909: tex[i] = new TexCoord2f(texCoords[i]);
0910: texCoordSets[0] = tex;
0911: }
0912: } // End of setTextureCoordinates(Point2f[])
0913:
0914: /**
0915: * Sets the texture coordinates array for the specified set.
0916: * No data copying is done - a reference to user data is used.
0917: * @param texCoordSet The texture coordinate set for which these coordinates
0918: * are being specified.
0919: * @param texCoords Array of 3D texture coordinates.
0920: * @throws IllegalArgumentException if <code> texCoordSet </code> < 0 or
0921: * <code>texCoordSet >= texCoordSetCount</code>,
0922: * or the texture coordinate parameters were not previously set by
0923: * calling <code>setTextureCoordinateParams(texCoordSetCount, 3)</code>.
0924: */
0925: public void setTextureCoordinates(int texCoordSet,
0926: TexCoord3f texCoords[]) {
0927: if (texCoordDim != 3)
0928: throw new IllegalArgumentException(J3dUtilsI18N
0929: .getString("GeometryInfo16"));
0930: if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
0931: throw new IllegalArgumentException(J3dUtilsI18N
0932: .getString("GeometryInfo18"));
0933:
0934: texCoordSets[texCoordSet] = texCoords;
0935: } // End of setTextureCoordinates(int, TexCoord3f[])
0936:
0937: /**
0938: * Sets the TextureCoordinates array by copying the data
0939: * into the GeometryInfo object.
0940: * This method sets the number of texture coordinate sets to 1,
0941: * sets the dimensionality of the texture coordinates to 3,
0942: * and sets the coordinates for texture coordinate set 0.
0943: * @deprecated As of Java 3D 1.3 replaced by
0944: * <code>setTextureCoordinates(int texCoordSet, TexCoord3f coords[])</code>
0945: */
0946: public void setTextureCoordinates(Point3f texCoords[]) {
0947: texCoordSetCount = 1;
0948: texCoordDim = 3;
0949: texCoordSets = new TexCoord3f[1][];
0950: if (texCoords != null) {
0951: TexCoord3f[] tex = new TexCoord3f[texCoords.length];
0952: for (int i = 0; i < texCoords.length; i++)
0953: tex[i] = new TexCoord3f(texCoords[i]);
0954: texCoordSets[0] = tex;
0955: }
0956: } // End of setTextureCoordinates(Point3f[])
0957:
0958: /**
0959: * Sets the texture coordinates array for the specified set.
0960: * No data copying is done - a reference to user data is used.
0961: * @param texCoordSet The texture coordinate set for which these coordinates
0962: * are being specified.
0963: * @param texCoords Array of 4D texture coordinates.
0964: * @throws IllegalArgumentException if <code> texCoordSet </code> < 0 or
0965: * <code>texCoordSet >= texCoordSetCount</code>,
0966: * or the texture coordinate parameters were not previously set by
0967: * calling <code>setTextureCoordinateParams(texCoordSetCount, 4)</code>.
0968: */
0969: public void setTextureCoordinates(int texCoordSet,
0970: TexCoord4f texCoords[]) {
0971: if (texCoordDim != 4)
0972: throw new IllegalArgumentException(J3dUtilsI18N
0973: .getString("GeometryInfo17"));
0974: if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
0975: throw new IllegalArgumentException(J3dUtilsI18N
0976: .getString("GeometryInfo18"));
0977:
0978: texCoordSets[texCoordSet] = texCoords;
0979: } // End of setTextureCoordinates(int, TexCoord4f[])
0980:
0981: /**
0982: * Sets the texture coordinates array by copying the data into the
0983: * GeometryInfo object. The number of sets and dimensionality of
0984: * the sets must have been set previously with
0985: * setTextureCoordinateParams(texCoordSetCount, dim).
0986: * @param texCoordSet The texture coordinate set for which these coordinates
0987: * are being specified.
0988: * @param texCoords The float array of texture coordinates. For n texture
0989: * coordinates with dimensionality d, there must be d*n floats in the array.
0990: * @throws IllegalArgumentException if <code>texCoordSet </code> < 0 or
0991: * <code>texCoordSet >= texCoordSetCount</code>,
0992: * or the texture coordinate parameters were not previously set by
0993: * calling <code>setTextureCoordinateParams</code>.
0994: */
0995: public void setTextureCoordinates(int texCoordSet,
0996: float texCoords[]) {
0997: if ((texCoords.length % texCoordDim) != 0)
0998: throw new IllegalArgumentException(J3dUtilsI18N
0999: .getString("GeometryInfo2"));
1000:
1001: // Copy the texCoords into this GeometryInfo object
1002: if (texCoordDim == 2) {
1003: TexCoord2f tcoords[] = new TexCoord2f[texCoords.length / 2];
1004: for (int i = 0; i < tcoords.length; i++)
1005: tcoords[i] = new TexCoord2f(texCoords[i * 2],
1006: texCoords[i * 2 + 1]);
1007: setTextureCoordinates(texCoordSet, tcoords);
1008: } else if (texCoordDim == 3) {
1009: TexCoord3f tcoords[] = new TexCoord3f[texCoords.length / 3];
1010: for (int i = 0; i < tcoords.length; i++)
1011: tcoords[i] = new TexCoord3f(texCoords[i * 3],
1012: texCoords[i * 3 + 1], texCoords[i * 3 + 2]);
1013: setTextureCoordinates(texCoordSet, tcoords);
1014: } else if (texCoordDim == 4) {
1015: TexCoord4f tcoords[] = new TexCoord4f[texCoords.length / 4];
1016: for (int i = 0; i < tcoords.length; i++)
1017: tcoords[i] = new TexCoord4f(texCoords[i * 4],
1018: texCoords[i * 4 + 1], texCoords[i * 4 + 2],
1019: texCoords[i * 4 + 3]);
1020: setTextureCoordinates(texCoordSet, tcoords);
1021: } else {
1022: throw new IllegalArgumentException(J3dUtilsI18N
1023: .getString("GeometryInfo21"));
1024: }
1025: } // End of setTextureCoordinates(int, float[])
1026:
1027: /**
1028: * Sets the texture coordinates array by copying the data
1029: * into the GeometryInfo object, assuming two numbers
1030: * (S and T) per vertex.
1031: * This method sets the number of texture coordinate sets to 1,
1032: * sets the dimensionality of the texture coordinates to 2,
1033: * and sets the coordinates for texture coordinate set 0.
1034: * @deprecated As of Java 3D 1.3 replaced by
1035: * <code>setTextureCoordinates(int texCoordSet, float texCoords[])</code>
1036: */
1037: public void setTextureCoordinates2(float texCoords[]) {
1038: texCoordSetCount = 1;
1039: texCoordDim = 2;
1040: texCoordSets = new TexCoord2f[1][];
1041: setTextureCoordinates(0, texCoords);
1042: } // End of setTextureCoordinates2(float[])
1043:
1044: /**
1045: * Sets the TextureCoordinates array by copying the data
1046: * into the GeometryInfo object, assuming three numbers
1047: * (S, T, & R) per vertex.
1048: * This method sets the number of texture coordinate sets to 1,
1049: * sets the dimensionality of the texture coordinates to 3,
1050: * and sets the coordinates for texture coordinate set 0.
1051: * @deprecated As of Java 3D 1.3 replaced by
1052: * <code>setTextureCoordinates(int texCoordSet, float texCoords[])</code>
1053: */
1054: public void setTextureCoordinates3(float texCoords[]) {
1055: texCoordSetCount = 1;
1056: texCoordDim = 3;
1057: texCoordSets = new TexCoord3f[1][];
1058: setTextureCoordinates(0, texCoords);
1059: } // End of setTextureCoordinates3(float[])
1060:
1061: /**
1062: * Returns a reference to the indicated texture coordinate array.
1063: * The return type will be <code>TexCoord2f[]</code>, <code>TexCoord3f[]
1064: * </code>, or <code>TexCoord4f[]</code> depending on the
1065: * current dimensionality of the texture coordinates in the GeometryInfo
1066: * object. Use <code>getNumTexCoordComponents()</code> to find out which
1067: * version is returned.
1068: * @param texCoordSet The index of the texture coordinate set to
1069: * retrieve.
1070: * @return An array of texture coordinates at the specified index
1071: * @throws IllegalArgumentException If <code> texCoordSet</code> < 0
1072: * or <code>texCoordSet >= texCoordSetCount</code>
1073: */
1074: public Object[] getTextureCoordinates(int texCoordSet) {
1075: if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
1076: throw new IllegalArgumentException(J3dUtilsI18N
1077: .getString("GeometryInfo18"));
1078: return texCoordSets[texCoordSet];
1079: } // End of getTextureCoordinates(int)
1080:
1081: /**
1082: * Retrieves a reference to texture coordinate set 0.
1083: * The return type will be <code>TexCoord2f[]</code>, <code>TexCoord3f[]
1084: * </code>, or <code>TexCoord4f[]</code> depending on the
1085: * current dimensionality of the texture coordinates in the GeometryInfo
1086: * object. Use <code>getNumTexCoordComponents()</code> to find out which
1087: * version is returned. Equivalent to <code>getTextureCoordinates(0)</code>.
1088: * @return An array of texture coordinates for set 0.
1089: * @deprecated As of Java 3D 1.3 replaced by
1090: * <code>getTextureCoordinates(int texCoordSet)</code>
1091: */
1092: public Object[] getTextureCoordinates() {
1093: return texCoordSets[0];
1094: } // End of getTextureCoordinates()
1095:
1096: /**
1097: * Sets the array of indices into the Coordinate array.
1098: * No data copying is done - a reference to user data is used.
1099: */
1100: public void setCoordinateIndices(int coordinateIndices[]) {
1101: this .coordinateIndices = coordinateIndices;
1102: } // End of setCoordinateIndices
1103:
1104: /**
1105: * Retrieves a reference to the array of indices into the
1106: * coordinate array.</p>
1107: *
1108: * This method should be considered for advanced users only.
1109: * Novice users should just use getGeometryArray() to retrieve
1110: * their data so that the internal format of GeometryInfo is
1111: * of no concern.</p>
1112: *
1113: * Depending on which of the utility routines you've called
1114: * on your GeometryInfo object, the results may not be what you
1115: * expect. If you've called the Stripifier, your GeometryInfo
1116: * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1117: * and your data will be formatted accordingly. Similarly, if
1118: * you've called the Triangulator, your data is in indexed
1119: * TRIANGLE_ARRAY format. Generating normals with the NormalGenerator
1120: * utility will convert your data to indexed TRIANGLE_ARRAY also,
1121: * but if you call getGeometryArray without calling the Stripifier or
1122: * Triangulator, your data will be converted back to the original
1123: * primitive type when creating the GeometryArray object to pass
1124: * back. However, if your creaseAngle was not Math.PI (no creases -
1125: * smooth shading), then the introduction of
1126: * creases into your model may have split primitives, lengthening
1127: * the StripCounts and index arrays from your original data.
1128: */
1129: public int[] getCoordinateIndices() {
1130: return coordinateIndices;
1131: } // End of getCoordinateIndices
1132:
1133: /**
1134: * Sets the array of indices into the Color array.
1135: * No data copying is done - a reference to user data is used.
1136: */
1137: public void setColorIndices(int colorIndices[]) {
1138: this .colorIndices = colorIndices;
1139: } // End of setColorIndices
1140:
1141: /**
1142: * Retrieves a reference to the array of indices into the
1143: * color array.</p>
1144: *
1145: * This method should be considered for advanced users only.
1146: * Novice users should just use getGeometryArray() to retrieve
1147: * their data so that the internal format of GeometryInfo is
1148: * of no concern.</p>
1149: *
1150: * Depending on which of the utility routines you've called
1151: * on your GeometryInfo object, the results may not be what you
1152: * expect. If you've called the Stripifier, your GeometryInfo
1153: * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1154: * and your data will be formatted accordingly. Similarly, if
1155: * you've called the Triangulator, your data is in indexed
1156: * TRIANGLE_ARRAY format. Generating normals with the NormalGenerator
1157: * utility will convert your data to indexed TRIANGLE_ARRAY also,
1158: * but if you call getGeometryArray without calling the Stripifier or
1159: * Triangulator, your data will be converted back to the original
1160: * primitive type when creating the GeometryArray object to pass
1161: * back. However, if your creaseAngle was not Math.PI (no creases -
1162: * smooth shading), then the introduction of
1163: * creases into your model may have split primitives, lengthening
1164: * the StripCounts and index arrays from your original data.
1165: */
1166: public int[] getColorIndices() {
1167: return colorIndices;
1168: } // End of getColorIndices
1169:
1170: /**
1171: * Sets the array of indices into the Normal array.
1172: * No data copying is done - a reference to user data is used.
1173: */
1174: public void setNormalIndices(int normalIndices[]) {
1175: this .normalIndices = normalIndices;
1176:
1177: } // End of setNormalIndices
1178:
1179: /**
1180: * Retrieves a reference to the array of indices into the
1181: * Normal array.</p>
1182: *
1183: * This method should be considered for advanced users only.
1184: * Novice users should just use getGeometryArray() to retrieve
1185: * their data so that the internal format of GeometryInfo is
1186: * of no concern.</p>
1187: *
1188: * Depending on which of the utility routines you've called
1189: * on your GeometryInfo object, the results may not be what you
1190: * expect. If you've called the Stripifier, your GeometryInfo
1191: * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1192: * and your data will be formatted accordingly. Similarly, if
1193: * you've called the Triangulator, your data is in indexed
1194: * TRIANGLE_ARRAY format. Generating normals with the NormalGenerator
1195: * utility will convert your data to indexed TRIANGLE_ARRAY also,
1196: * but if you call getGeometryArray without calling the Stripifier or
1197: * Triangulator, your data will be converted back to the original
1198: * primitive type when creating the GeometryArray object to pass
1199: * back. However, if your creaseAngle was not Math.PI (no creases -
1200: * smooth shading), then the introduction of
1201: * creases into your model may have split primitives, lengthening
1202: * the StripCounts and index arrays from your original data.
1203: */
1204: public int[] getNormalIndices() {
1205: return normalIndices;
1206: } // End of getNormalIndices
1207:
1208: /**
1209: * Sets one of the texture coordinate index arrays.
1210: * No data copying is done - a reference to user data is used.
1211: * @param texCoordSet The texture coordinate set for which these coordinate
1212: * indices are being specified.
1213: * @param texIndices The integer array of indices into the specified texture
1214: * coordinate set
1215: * @throws IllegalArgumentException If <code> texCoordSet</code> < 0 or
1216: * <code>texCoordSet >= texCoordSetCount</code>.
1217: */
1218: public void setTextureCoordinateIndices(int texCoordSet,
1219: int texIndices[]) {
1220: if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
1221: throw new IllegalArgumentException(J3dUtilsI18N
1222: .getString("GeometryInfo18"));
1223:
1224: // Texture coordinates are indexed
1225: texCoordIndexSets[texCoordSet] = texIndices;
1226: } // End of setTextureCoordinateIndices(int, int[])
1227:
1228: /**
1229: * Sets the array of indices into texture coordinate set 0. Do not
1230: * call this method if you are using more than one set of texture
1231: * coordinates.
1232: * No data is copied - a reference to the user data is used.
1233: * @deprecated As of Java 3D 1.3 replaced by
1234: * <code>setTextureCoordinateIndices(int texCoordSet, int indices[])</code>
1235: * @throws IllegalArgumentException If <code>texCoordSetCount > 1</code>.
1236: */
1237: public void setTextureCoordinateIndices(int texIndices[]) {
1238: if (texCoordSetCount > 1)
1239: throw new IllegalArgumentException(J3dUtilsI18N
1240: .getString("GeometryInfo1"));
1241: texCoordIndexSets = new int[1][];
1242: texCoordIndexSets[0] = texIndices;
1243: } // End of setTextureCoordinateIndices(int[])
1244:
1245: /**
1246: * Retrieves a reference to the specified array of texture
1247: * coordinate indices.<p>
1248: *
1249: * This method should be considered for advanced users only.
1250: * Novice users should just use getGeometryArray() to retrieve
1251: * their data so that the internal format of GeometryInfo is
1252: * of no concern.</p>
1253: *
1254: * Depending on which of the utility routines you've called
1255: * on your GeometryInfo object, the results may not be what you
1256: * expect. If you've called the Stripifier, your GeometryInfo
1257: * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1258: * and your data will be formatted accordingly. Similarly, if
1259: * you've called the Triangulator, your data is in indexed
1260: * TRIANGLE_ARRAY format. Generating normals with the NormalGenerator
1261: * utility will convert your data to indexed TRIANGLE_ARRAY also,
1262: * but if you call getGeometryArray without calling the Stripifier or
1263: * Triangulator, your data will be converted back to the original
1264: * primitive type when creating the GeometryArray object to pass
1265: * back. However, if your creaseAngle was not Math.PI (no creases -
1266: * smooth shading), then the introduction of
1267: * creases into your model may have split primitives, lengthening
1268: * the StripCounts and index arrays from your original data.
1269: * @param texCoordSet The texture coordinate index set to be
1270: * retrieved.
1271: * @return Integer array of the texture coordinate indices for the specified
1272: * set.
1273: */
1274: public int[] getTextureCoordinateIndices(int texCoordSet) {
1275: return texCoordIndexSets[texCoordSet];
1276: }
1277:
1278: /**
1279: * Returns a reference to texture coordinate index set 0.
1280: * Equivalent to
1281: * <code>getTextureCoordinateIndices(0)</code>.
1282: * @deprecated As of Java 3D 1.3 replaced by
1283: * <code>int[] getTextureCoordinateIndices(int texCoordSet) </code>
1284: * @return Integer array of the texture coordinate indices for set 0
1285: */
1286: public int[] getTextureCoordinateIndices() {
1287: if (texCoordIndexSets == null)
1288: return null;
1289: return texCoordIndexSets[0];
1290: } // End of getTextureCoordinateIndices()
1291:
1292: /**
1293: * Sets the array of strip counts. If index lists have been set for
1294: * this GeomteryInfo object then the data is indexed and the stripCounts
1295: * are like stripIndexCounts. If no index lists have been set then
1296: * the data is non-indexed and the stripCounts are like
1297: * stripVertexCounts.
1298: * @see GeometryStripArray#GeometryStripArray(int, int,
1299: * int[] stripVertexCounts)
1300: * @see IndexedGeometryStripArray#IndexedGeometryStripArray(int, int, int,
1301: * int[] stripIndexCounts)
1302: */
1303: public void setStripCounts(int stripCounts[]) {
1304: this .stripCounts = stripCounts;
1305: } // End of setStripCounts
1306:
1307: /**
1308: * Retrieves a reference to the array of stripCounts.</p>
1309: *
1310: * This method should be considered for advanced users only.
1311: * Novice users should just use getGeometryArray() to retrieve
1312: * their data so that the internal format of GeometryInfo is
1313: * of no concern.</p>
1314: *
1315: * Depending on which of the utility routines you've called
1316: * on your GeometryInfo object, the results may not be what you
1317: * expect. If you've called the Stripifier, your GeometryInfo
1318: * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1319: * and your data will be formatted accordingly. Similarly, if
1320: * you've called the Triangulator, your data is in indexed
1321: * TRIANGLE_ARRAY format. Generating normals with the NormalGenerator
1322: * utility will convert your data to indexed TRIANGLE_ARRAY also,
1323: * but if you call getGeometryArray without calling the Stripifier or
1324: * Triangulator, your data will be converted back to the original
1325: * primitive type when creating the GeometryArray object to pass
1326: * back. However, if your creaseAngle was not Math.PI (no creases -
1327: * smooth shading), then the introduction of
1328: * creases into your model may have split primitives, lengthening
1329: * the StripCounts and index arrays from your original data.
1330: */
1331: public int[] getStripCounts() {
1332: return stripCounts;
1333: } // End of getStripCounts
1334:
1335: /**
1336: * Sets the list of contour counts. Only used with the POLYGON_ARRAY
1337: * primitive. Polygons can be made of several vertex lists
1338: * called contours. The first list is the polygon, and
1339: * subsequent lists are "holes" that are removed from the
1340: * polygon. All of the holes must be contained entirely
1341: * within the polygon.
1342: */
1343: public void setContourCounts(int contourCounts[]) {
1344: this .contourCounts = contourCounts;
1345: } // End of setContourCounts
1346:
1347: /**
1348: * Retrieves a reference to the array of contourCounts.
1349: */
1350: public int[] getContourCounts() {
1351: return contourCounts;
1352: } // End of getContourCounts
1353:
1354: /*
1355: * This routine will return an index list for any array of objects.
1356: */
1357: int[] getListIndices(Object list[]) {
1358: // Create list of indices to return
1359: int indices[] = new int[list.length];
1360:
1361: // Create hash table with initial capacity equal to the number
1362: // of components (assuming about half will be duplicates)
1363: HashMap table = new HashMap(list.length);
1364:
1365: Integer idx;
1366: for (int i = 0; i < list.length; i++) {
1367:
1368: // Find index associated with this object
1369: idx = (Integer) table.get(list[i]);
1370:
1371: if (idx == null) {
1372: // We haven't seen this object before
1373: indices[i] = i;
1374:
1375: // Put into hash table and remember the index
1376: table.put(list[i], new Integer(i));
1377:
1378: } else {
1379: // We've seen this object
1380: indices[i] = idx.intValue();
1381: }
1382: }
1383:
1384: return indices;
1385: } // End of getListIndices
1386:
1387: // Class to hash 'size' integers
1388: private class IndexRow {
1389: int[] val;
1390: int size;
1391: private static final int HASHCONST = 0xBABEFACE;
1392:
1393: public int hashCode() {
1394: int bits = 0;
1395: for (int i = 0; i < size; i++) {
1396: bits ^= (bits * HASHCONST) << 2;
1397: }
1398: return bits;
1399: } // End of IndexRow.hashCode
1400:
1401: public boolean equals(Object obj) {
1402: for (int i = 0; i < size; i++) {
1403: if (((IndexRow) obj).get(i) != val[i])
1404: return false;
1405: }
1406: return true;
1407: } // End of IndexRow.equals()
1408:
1409: public int get(int index) {
1410: return val[index];
1411: } // End of IndexRow.get
1412:
1413: public void set(int index, int value) {
1414: val[index] = value;
1415: } // End of IndexRow.set
1416:
1417: IndexRow(int numColumns) {
1418: size = numColumns;
1419: val = new int[size];
1420: } // End of IndexRow constructor
1421: } // End of class IndexRow
1422:
1423: /**
1424: * Create index lists for all data lists.
1425: * Identical data entries are guaranteed to
1426: * use the same index value. Does not remove unused data values
1427: * from the object - call compact() to do this.
1428: * @param useCoordIndexOnly Reformat the data into the
1429: * GeometryArray.USE_COORD_INDEX_ONLY format where there is only
1430: * one index list. If the data is already in the USE_COORD_INDEX_ONLY
1431: * format, sending false (or calling indexify()) will change
1432: * it to the normal indexed format.
1433: * @throws IllegalArgumentException if coordinate data is missing,
1434: * if the index lists aren't all the
1435: * same length, if an index list is set and the corresponding data
1436: * list isn't set, if a data list is set and the corresponding
1437: * index list is unset (unless all index lists are unset or in
1438: * USE_COORD_INDEX_ONLY format),
1439: * if StripCounts or ContourCounts is inconsistent with the current
1440: * primitive, if the sum of the contourCounts array doesn't equal
1441: * the length of the StripCounts array, or if the number of vertices
1442: * isn't a multiple of three (for triangles) or four (for quads).
1443: */
1444: public void indexify(boolean useCoordIndexOnly) {
1445: checkForBadData();
1446:
1447: if (useCoordIndexOnly) {
1448: // Return if already in this format
1449: if (coordOnly)
1450: return;
1451:
1452: // Start from normal indexed format
1453: indexify(false);
1454:
1455: // Reformat data to USE_COORD_INDEX_ONLY format
1456: // Need to make an index into the index lists using each
1457: // row of indexes as one value
1458:
1459: // First, find out how many index lists there are;
1460: int numLists = 1; // Always have coordinates
1461: if (colorIndices != null)
1462: numLists++;
1463: if (normalIndices != null)
1464: numLists++;
1465: numLists += texCoordSetCount;
1466:
1467: // Make single array containing all indices
1468: int n = coordinateIndices.length;
1469: IndexRow[] ir = new IndexRow[n];
1470: int j;
1471: for (int i = 0; i < n; i++) {
1472: ir[i] = new IndexRow(numLists);
1473: j = 0;
1474: ir[i].set(j++, coordinateIndices[i]);
1475: if (colorIndices != null)
1476: ir[i].set(j++, colorIndices[i]);
1477: if (normalIndices != null)
1478: ir[i].set(j++, normalIndices[i]);
1479: for (int k = 0; k < texCoordSetCount; k++) {
1480: ir[i].set(j++, texCoordIndexSets[k][i]);
1481: }
1482: }
1483:
1484: // Get index into that array
1485: int[] coordOnlyIndices = getListIndices(ir);
1486:
1487: // Get rid of duplicate rows
1488: int newInd[] = new int[coordOnlyIndices.length];
1489: ir = (IndexRow[]) compactData(coordOnlyIndices, ir, newInd);
1490: coordOnlyIndices = newInd;
1491:
1492: // Reformat data lists to correspond to new index
1493:
1494: // Allocate arrays to hold reformatted data
1495: Point3f[] newCoords = new Point3f[ir.length];
1496: Color3f[] newColors3 = null;
1497: Color4f[] newColors4 = null;
1498: Vector3f[] newNormals = null;
1499: Object newTexCoordSets[][] = null;
1500: if (colors3 != null)
1501: newColors3 = new Color3f[ir.length];
1502: else if (colors4 != null)
1503: newColors4 = new Color4f[ir.length];
1504: if (normals != null)
1505: newNormals = new Vector3f[ir.length];
1506: for (int i = 0; i < texCoordSetCount; i++) {
1507: if (texCoordDim == 2) {
1508: if (i == 0)
1509: newTexCoordSets = new TexCoord2f[texCoordSetCount][];
1510: newTexCoordSets[i] = new TexCoord2f[ir.length];
1511: } else if (texCoordDim == 3) {
1512: if (i == 0)
1513: newTexCoordSets = new TexCoord3f[texCoordSetCount][];
1514: newTexCoordSets[i] = new TexCoord3f[ir.length];
1515: } else if (texCoordDim == 4) {
1516: if (i == 0)
1517: newTexCoordSets = new TexCoord4f[texCoordSetCount][];
1518: newTexCoordSets[i] = new TexCoord4f[ir.length];
1519: }
1520: }
1521:
1522: // Copy data into new arrays
1523: n = ir.length;
1524: for (int i = 0; i < n; i++) {
1525: j = 0;
1526: newCoords[i] = coordinates[(ir[i]).get(j++)];
1527: if (colors3 != null) {
1528: newColors3[i] = colors3[(ir[i]).get(j++)];
1529: } else if (colors4 != null) {
1530: newColors4[i] = colors4[(ir[i]).get(j++)];
1531: }
1532: if (normals != null)
1533: newNormals[i] = normals[(ir[i]).get(j++)];
1534: for (int k = 0; k < texCoordSetCount; k++) {
1535: newTexCoordSets[k][i] = texCoordSets[k][(ir[i])
1536: .get(j++)];
1537: }
1538: }
1539:
1540: // Replace old arrays with new arrays
1541: coordinates = newCoords;
1542: colors3 = newColors3;
1543: colors4 = newColors4;
1544: normals = newNormals;
1545: texCoordSets = newTexCoordSets;
1546: coordinateIndices = coordOnlyIndices;
1547: colorIndices = null;
1548: normalIndices = null;
1549: texCoordIndexSets = new int[texCoordSetCount][];
1550:
1551: coordOnly = true;
1552: } else if (coordOnly) {
1553: // Need to change from useCoordIndexOnly format to normal
1554: // indexed format. Should make a more efficient implementation
1555: // later.
1556:
1557: int n = coordinateIndices.length;
1558: if ((colors3 != null) || (colors4 != null)) {
1559: colorIndices = new int[n];
1560: for (int i = 0; i < n; i++)
1561: colorIndices[i] = coordinateIndices[i];
1562: }
1563: if (normals != null) {
1564: normalIndices = new int[n];
1565: for (int i = 0; i < n; i++)
1566: normalIndices[i] = coordinateIndices[i];
1567: }
1568: texCoordIndexSets = new int[texCoordSetCount][];
1569: for (int i = 0; i < texCoordSetCount; i++) {
1570: texCoordIndexSets[i] = new int[n];
1571: for (int j = 0; j < n; j++) {
1572: texCoordIndexSets[i][j] = coordinateIndices[j];
1573: }
1574: }
1575: coordOnly = false;
1576: } else {
1577:
1578: // No need to indexify if already indexed
1579: if (coordinateIndices != null)
1580: return;
1581:
1582: coordinateIndices = getListIndices(coordinates);
1583:
1584: if (colors3 != null)
1585: colorIndices = getListIndices(colors3);
1586: else if (colors4 != null)
1587: colorIndices = getListIndices(colors4);
1588:
1589: if (normals != null)
1590: normalIndices = getListIndices(normals);
1591:
1592: texCoordIndexSets = new int[texCoordSetCount][];
1593: for (int i = 0; i < texCoordSetCount; i++) {
1594: texCoordIndexSets[i] = getListIndices(texCoordSets[i]);
1595: }
1596:
1597: coordOnly = false;
1598: }
1599:
1600: if ((DEBUG & 1) == 1) {
1601: System.out.println("Coordinate Array:");
1602: for (int i = 0; i < coordinates.length; i++) {
1603: System.out.println(" " + i + " " + coordinates[i]
1604: + " " + coordinates[i].hashCode());
1605: }
1606: System.out.println("Index array:");
1607: for (int i = 0; i < coordinateIndices.length; i++) {
1608: System.out.println(" " + i + " "
1609: + coordinateIndices[i]);
1610: }
1611: }
1612:
1613: } // End of indexify
1614:
1615: public void indexify() {
1616: indexify(false);
1617: } // End of indexify()
1618:
1619: /**
1620: * Allocates an array of the same type as the input type. This allows us to
1621: * use a generic compactData method.
1622: *
1623: * @param data Array of coordinate, color, normal or texture coordinate data
1624: * The data can be in one of the following formats - Point3f, Color3f,
1625: * Color4f, TexCoord2f, TexCoord3f, TexCoord4f.
1626: *
1627: * @param num The size of the array to be allocated
1628: *
1629: * @return An array of size num of the same type as the input type
1630: *
1631: * @exception IllegalArgumentException if the input array is not one of the
1632: * types listed above.
1633: */
1634: Object[] allocateArray(Object data[], int num) {
1635: Object newData[] = null;
1636: if (data instanceof javax.vecmath.Point3f[]) {
1637: newData = new Point3f[num];
1638: } else if (data instanceof javax.vecmath.Vector3f[]) {
1639: newData = new Vector3f[num];
1640: } else if (data instanceof javax.vecmath.Color3f[]) {
1641: newData = new Color3f[num];
1642: } else if (data instanceof javax.vecmath.Color4f[]) {
1643: newData = new Color4f[num];
1644: } else if (data instanceof javax.vecmath.TexCoord2f[]) {
1645: newData = new TexCoord2f[num];
1646: } else if (data instanceof javax.vecmath.TexCoord3f[]) {
1647: newData = new TexCoord3f[num];
1648: } else if (data instanceof javax.vecmath.TexCoord4f[]) {
1649: newData = new TexCoord4f[num];
1650: } else if (data instanceof IndexRow[]) {
1651: // Hack so we can use compactData for coordIndexOnly
1652: newData = new IndexRow[num];
1653: } else
1654: throw new IllegalArgumentException(J3dUtilsI18N
1655: .getString("GeometryInfo9"));
1656: return newData;
1657: } // End of allocateArray
1658:
1659: /**
1660: * Generic method that compacts (ie removes unreferenced/duplicate data)
1661: * any type of indexed data.
1662: * Used to compact coordinate, color, normal and texture coordinate data.
1663: * @param indices Array of indices
1664: * @param data Array of coordinate, color, normal or texture coordinate data
1665: * The data can be in one of the following formats - Point3f, Color3f,
1666: * Color4f, TexCoord2f, TexCoord3f, TexCoord4f.
1667: * @param newInd The new array of indexes after the data has been compacted.
1668: * This must be allocated by the calling method. On return, this array will
1669: * contain the new index data. The size of this array must be equal to
1670: * indices.length
1671: * @return Array of the data with unreferenced and duplicate entries removed.
1672: * The return type will be the same as the type that was passed in data.
1673: */
1674: // TODO: Remove duplicate entries in data lists.
1675: private Object[] compactData(int indices[], Object data[],
1676: int newInd[]) {
1677: Object newData[] = null;
1678: /*
1679: * This is a three step process.
1680: * First, find out how many unique indexes are used. This
1681: * will be the size of the new data array.
1682: */
1683: int numUnique = 0;
1684: int translationTable[] = new int[data.length];
1685: for (int i = 0; i < indices.length; i++) {
1686: if (translationTable[indices[i]] == 0) {
1687:
1688: numUnique++;
1689: translationTable[indices[i]] = 1;
1690: }
1691: }
1692: /*
1693: * Second, build the new data list. Remember the new indexes so
1694: * we can use the table to translate the old indexes to the new
1695: */
1696: newData = allocateArray(data, numUnique);
1697: int newIdx = 0;
1698: for (int i = 0; i < translationTable.length; i++) {
1699: if (translationTable[i] != 0) {
1700: newData[newIdx] = data[i];
1701: translationTable[i] = newIdx++;
1702: }
1703: }
1704: /*
1705: * Third, make the new index list
1706: */
1707: for (int i = 0; i < indices.length; i++) {
1708: newInd[i] = translationTable[indices[i]];
1709: }
1710: return newData;
1711: } // End of compactData
1712:
1713: /**
1714: * Remove unused data from an indexed dataset.
1715: * Indexed data may contain data entries that are never referenced by
1716: * the dataset. This routine will remove those entries where
1717: * appropriate and renumber the indices to match the new values.
1718: * @throws IllegalArgumentException if coordinate data is missing,
1719: * if the index lists aren't all the
1720: * same length, if an index list is set and the corresponding data
1721: * list isn't set, if a data list is set and the corresponding
1722: * index list is unset (unless all index lists are unset or in
1723: * USE_COORD_INDEX_ONLY format),
1724: * if StripCounts or ContourCounts is inconsistent with the current
1725: * primitive, if the sum of the contourCounts array doesn't equal
1726: * the length of the StripCounts array, or if the number of vertices
1727: * isn't a multiple of three (for triangles) or four (for quads).
1728: */
1729: public void compact() {
1730: checkForBadData();
1731:
1732: // Only usable on indexed data
1733: if (coordinateIndices == null)
1734: return;
1735:
1736: // USE_COORD_INDEX_ONLY never has unused data
1737: if (coordOnly)
1738: return;
1739:
1740: int newInd[] = new int[coordinateIndices.length];
1741: coordinates = (Point3f[]) compactData(coordinateIndices,
1742: coordinates, newInd);
1743: coordinateIndices = newInd;
1744:
1745: if (colorIndices != null) {
1746: newInd = new int[colorIndices.length];
1747: if (colors3 != null)
1748: colors3 = (Color3f[]) compactData(colorIndices,
1749: colors3, newInd);
1750: else if (colors4 != null)
1751: colors4 = (Color4f[]) compactData(colorIndices,
1752: colors4, newInd);
1753: colorIndices = newInd;
1754: }
1755:
1756: if (normalIndices != null) {
1757: newInd = new int[normalIndices.length];
1758: normals = (Vector3f[]) compactData(normalIndices, normals,
1759: newInd);
1760: normalIndices = newInd;
1761: }
1762:
1763: for (int i = 0; i < texCoordSetCount; i++) {
1764: newInd = new int[texCoordIndexSets[i].length];
1765: texCoordSets[i] = compactData(texCoordIndexSets[i],
1766: texCoordSets[i], newInd);
1767: texCoordIndexSets[i] = newInd;
1768: }
1769: } // End of compact
1770:
1771: /**
1772: * Check the data to make sure everything's consistent.
1773: */
1774: private void checkForBadData() {
1775: boolean badData = false;
1776:
1777: //
1778: // Coordinates are required
1779: //
1780: if (coordinates == null) {
1781: throw new IllegalArgumentException(J3dUtilsI18N
1782: .getString("GeometryInfo3"));
1783: }
1784:
1785: //
1786: // Check for indices with no data
1787: //
1788: if ((colors3 == null) && (colors4 == null)
1789: && (colorIndices != null))
1790: throw new IllegalArgumentException(J3dUtilsI18N
1791: .getString("GeometryInfo4"));
1792: if ((normals == null) && (normalIndices != null))
1793: throw new IllegalArgumentException(J3dUtilsI18N
1794: .getString("GeometryInfo11"));
1795:
1796: //
1797: // Make sure all TextureCoordinate data is set (indices or not)
1798: //
1799: for (int i = 0; i < texCoordSetCount; i++) {
1800: if (texCoordSets[i] == null)
1801: throw new IllegalArgumentException(J3dUtilsI18N
1802: .getString("GeometryInfo10"));
1803: }
1804:
1805: //
1806: // Check for Missing Index lists
1807: //
1808: boolean texInds = false; // Indicates whether we have texcoord indices
1809: if (texCoordIndexSets != null) {
1810: for (int i = 0; i < texCoordSetCount; i++) {
1811: if (texCoordIndexSets[i] != null)
1812: texInds = true;
1813: }
1814: }
1815: if ((coordinateIndices != null) || (colorIndices != null)
1816: || (normalIndices != null) || texInds) {
1817: // At least one index list is present, so they all must be
1818: // present (unless coordOnly)
1819: if (coordinateIndices == null)
1820: badData = true;
1821: else if (coordOnly) {
1822: if ((colorIndices != null) || (normalIndices != null)
1823: || (texInds == true)) {
1824: throw new IllegalArgumentException(J3dUtilsI18N
1825: .getString("GeometryInfo20"));
1826: }
1827: } else if (((colors3 != null) || (colors4 != null))
1828: && (colorIndices == null))
1829: badData = true;
1830: else if ((normals != null) && (normalIndices == null))
1831: badData = true;
1832: else if ((texCoordSetCount > 0) && !texInds)
1833: badData = true;
1834: if (badData)
1835: throw new IllegalArgumentException(J3dUtilsI18N
1836: .getString("GeometryInfo19"));
1837: }
1838:
1839: //
1840: // Make sure index lists are all the same length
1841: //
1842: if ((coordinateIndices != null) && (!coordOnly)) {
1843: if (((colors3 != null) || (colors4 != null))
1844: && (colorIndices.length != coordinateIndices.length))
1845: badData = true;
1846: else if ((normals != null)
1847: && (normalIndices.length != coordinateIndices.length))
1848: badData = true;
1849: else {
1850: //Check all texCoord indices have the same length
1851: for (int i = 0; i < texCoordSetCount; i++) {
1852: if (texCoordIndexSets[i].length != coordinateIndices.length) {
1853: badData = true;
1854: break;
1855: }
1856: }
1857: }
1858: if (badData) {
1859: throw new IllegalArgumentException(J3dUtilsI18N
1860: .getString("GeometryInfo5"));
1861: }
1862: }
1863:
1864: //
1865: // For stripped primitives, make sure we have strip counts
1866: //
1867: if ((prim == TRIANGLE_STRIP_ARRAY)
1868: || (prim == TRIANGLE_FAN_ARRAY)
1869: || (prim == POLYGON_ARRAY)) {
1870: if (stripCounts == null)
1871: badData = true;
1872: } else if (stripCounts != null)
1873: badData = true;
1874: if (badData) {
1875: throw new IllegalArgumentException(J3dUtilsI18N
1876: .getString("GeometryInfo6"));
1877: }
1878:
1879: // Find out how much data we have
1880: int count;
1881: if (coordinateIndices == null)
1882: count = coordinates.length;
1883: else
1884: count = coordinateIndices.length;
1885:
1886: //
1887: // Make sure sum of strip counts equals indexCount (or vertexCount)
1888: // and check to make sure triangles and quads have the right number
1889: // of vertices
1890: //
1891: if ((prim == TRIANGLE_STRIP_ARRAY)
1892: || (prim == TRIANGLE_FAN_ARRAY)
1893: || (prim == POLYGON_ARRAY)) {
1894: int sum = 0;
1895: for (int i = 0; i < stripCounts.length; i++) {
1896: sum += stripCounts[i];
1897: }
1898: if (sum != count) {
1899: throw new IllegalArgumentException(J3dUtilsI18N
1900: .getString("GeometryInfo7"));
1901: }
1902: } else if (prim == TRIANGLE_ARRAY) {
1903: if (count % 3 != 0) {
1904: throw new IllegalArgumentException(J3dUtilsI18N
1905: .getString("GeometryInfo12"));
1906: }
1907: } else if (prim == QUAD_ARRAY) {
1908: if (count % 4 != 0) {
1909: throw new IllegalArgumentException(J3dUtilsI18N
1910: .getString("GeometryInfo13"));
1911: }
1912: }
1913:
1914: //
1915: // For polygons, make sure the contours add up.
1916: //
1917: if (prim == POLYGON_ARRAY) {
1918: if (contourCounts != null) {
1919: int c = 0;
1920: for (int i = 0; i < contourCounts.length; i++)
1921: c += contourCounts[i];
1922: if (c != stripCounts.length) {
1923: throw new IllegalArgumentException(J3dUtilsI18N
1924: .getString("GeometryInfo8"));
1925: }
1926: }
1927: } else {
1928: if (contourCounts != null) {
1929: throw new IllegalArgumentException(J3dUtilsI18N
1930: .getString("GeometryInfo14"));
1931: }
1932: }
1933: } // End of checkForBadData
1934:
1935: /**
1936: * Get rid of index lists by reorganizing data into an un-indexed
1937: * format. Does nothing if no index lists are set.
1938: * @throws IllegalArgumentException if coordinate data is missing,
1939: * if the index lists aren't all the
1940: * same length, if an index list is set and the corresponding data
1941: * list isn't set, if a data list is set and the corresponding
1942: * index list is unset (unless all index lists are unset or in
1943: * USE_COORD_INDEX_ONLY format),
1944: * if StripCounts or ContourCounts is inconsistent with the current
1945: * primitive, if the sum of the contourCounts array doesn't equal
1946: * the length of the StripCounts array, or if the number of vertices
1947: * isn't a multiple of three (for triangles) or four (for quads).
1948: */
1949: public void unindexify() {
1950: checkForBadData();
1951: if (coordinateIndices != null) {
1952: // Switch from USE_COORD_INDEX_ONLY format
1953: if (coordOnly)
1954: indexify(false);
1955:
1956: coordinates = (Point3f[]) unindexifyData(coordinates,
1957: coordinateIndices);
1958: coordinateIndices = null;
1959:
1960: if (colors3 != null) {
1961: colors3 = (Color3f[]) unindexifyData(colors3,
1962: colorIndices);
1963: } else if (colors4 != null) {
1964: colors4 = (Color4f[]) unindexifyData(colors4,
1965: colorIndices);
1966: }
1967: colorIndices = null;
1968:
1969: if (normals != null) {
1970: normals = (Vector3f[]) unindexifyData(normals,
1971: normalIndices);
1972: normalIndices = null;
1973: }
1974:
1975: for (int i = 0; i < texCoordSetCount; i++)
1976: texCoordSets[i] = unindexifyData(texCoordSets[i],
1977: texCoordIndexSets[i]);
1978: texCoordIndexSets = new int[texCoordSetCount][];
1979: }
1980: } // End of unindexify
1981:
1982: /**
1983: * Generic unindexify method. Can unindex data in any of the following
1984: * formats Point3f, Color3f, Color4f, Vector3f, TexCoord2f, TexCoord3f,
1985: * TexCoord4f.
1986: */
1987: private Object[] unindexifyData(Object data[], int index[]) {
1988: Object newData[] = allocateArray(data, index.length);
1989: for (int i = 0; i < index.length; i++) {
1990: newData[i] = data[index[i]];
1991: }
1992: return newData;
1993: } // End of unindexifyData
1994:
1995: /**
1996: * Calculate vertexFormat based on data.
1997: */
1998: private int getVertexFormat() {
1999: int vertexFormat = GeometryArray.COORDINATES;
2000:
2001: if (colors3 != null)
2002: vertexFormat |= GeometryArray.COLOR_3;
2003: else if (colors4 != null)
2004: vertexFormat |= GeometryArray.COLOR_4;
2005:
2006: if (normals != null)
2007: vertexFormat |= GeometryArray.NORMALS;
2008:
2009: if (texCoordDim == 2)
2010: vertexFormat |= GeometryArray.TEXTURE_COORDINATE_2;
2011: else if (texCoordDim == 3)
2012: vertexFormat |= GeometryArray.TEXTURE_COORDINATE_3;
2013: else if (texCoordDim == 4)
2014: vertexFormat |= GeometryArray.TEXTURE_COORDINATE_4;
2015:
2016: return vertexFormat;
2017: } // End of getVertexFormat
2018:
2019: /**
2020: * Calculate vertexCount based on data
2021: */
2022: private int getVertexCount() {
2023: int vertexCount = coordinates.length;
2024:
2025: if (colors3 != null) {
2026: if (colors3.length > vertexCount)
2027: vertexCount = colors3.length;
2028: } else if (colors4 != null) {
2029: if (colors4.length > vertexCount)
2030: vertexCount = colors4.length;
2031: }
2032:
2033: if (normals != null) {
2034: if (normals.length > vertexCount)
2035: vertexCount = normals.length;
2036: }
2037:
2038: // Find max length tex coord set
2039: for (int i = 0; i < texCoordSetCount; i++) {
2040: if (texCoordSets[i].length > vertexCount)
2041: vertexCount = texCoordSets[i].length;
2042: }
2043:
2044: return vertexCount;
2045: } // End of getVertexCount
2046:
2047: /**
2048: * Converts an array of Tuple2f, Tuple3f, or Tuple4f values into
2049: * an array of floats. Assumes array is not null. Returns null
2050: * if array is not Tuple2f, Tuple3f, or Tuple4f. Used by fillIn()
2051: * for BY_REFERENCE not INTERLEAVED geometry.
2052: */
2053: private float[] vecmathToFloat(Object[] ar) {
2054: if (ar[0] instanceof Tuple2f) {
2055: float[] p = new float[ar.length * 2];
2056: Tuple2f[] a = (Tuple2f[]) ar;
2057: for (int i = 0; i < ar.length; i++) {
2058: p[i * 2] = a[i].x;
2059: p[i * 2 + 1] = a[i].y;
2060: }
2061: return p;
2062: } else if (ar[0] instanceof Tuple3f) {
2063: float[] p = new float[ar.length * 3];
2064: Tuple3f[] a = (Tuple3f[]) ar;
2065: for (int i = 0; i < ar.length; i++) {
2066: p[i * 3] = a[i].x;
2067: p[i * 3 + 1] = a[i].y;
2068: p[i * 3 + 2] = a[i].z;
2069: }
2070: return p;
2071: } else if (ar[0] instanceof Tuple4f) {
2072: float[] p = new float[ar.length * 4];
2073: Tuple4f[] a = (Tuple4f[]) ar;
2074: for (int i = 0; i < ar.length; i++) {
2075: p[i * 4] = a[i].x;
2076: p[i * 4 + 1] = a[i].y;
2077: p[i * 4 + 2] = a[i].z;
2078: p[i * 4 + 3] = a[i].w;
2079: }
2080: return p;
2081: }
2082: return null;
2083: } // End of vecmathToFloat
2084:
2085: /**
2086: * Fill in the GeometryArray object. Used by getGeometryArray and
2087: * getIndexedGeometryArray. checkForBadData has already been called.
2088: */
2089: private void fillIn(GeometryArray ga, boolean byRef,
2090: boolean interleaved, boolean nio) {
2091: if (interleaved) {
2092: // Calculate number of words per vertex
2093: int wpv = 3; // Always have coordinate data
2094: if (normals != null)
2095: wpv += 3;
2096: if (colors3 != null)
2097: wpv += 3;
2098: else if (colors4 != null)
2099: wpv += 4;
2100: wpv += (texCoordSetCount * texCoordDim);
2101:
2102: // Build array of interleaved data
2103: float[] d = new float[wpv * coordinates.length];
2104:
2105: // Fill in the array
2106: int offset = 0;
2107: for (int i = 0; i < coordinates.length; i++) {
2108: if (texCoordDim == 2) {
2109: for (int j = 0; j < texCoordSetCount; j++) {
2110: d[offset++] = ((TexCoord2f) texCoordSets[j][i]).x;
2111: d[offset++] = ((TexCoord2f) texCoordSets[j][i]).y;
2112: }
2113: } else if (texCoordDim == 3) {
2114: for (int j = 0; j < texCoordSetCount; j++) {
2115: d[offset++] = ((TexCoord3f) texCoordSets[j][i]).x;
2116: d[offset++] = ((TexCoord3f) texCoordSets[j][i]).y;
2117: d[offset++] = ((TexCoord3f) texCoordSets[j][i]).z;
2118: }
2119: } else if (texCoordDim == 4) {
2120: for (int j = 0; j < texCoordSetCount; j++) {
2121: d[offset++] = ((TexCoord4f) texCoordSets[j][i]).x;
2122: d[offset++] = ((TexCoord4f) texCoordSets[j][i]).y;
2123: d[offset++] = ((TexCoord4f) texCoordSets[j][i]).z;
2124: d[offset++] = ((TexCoord4f) texCoordSets[j][i]).w;
2125: }
2126: }
2127:
2128: if (colors3 != null) {
2129: d[offset++] = colors3[i].x;
2130: d[offset++] = colors3[i].y;
2131: d[offset++] = colors3[i].z;
2132: } else if (colors4 != null) {
2133: d[offset++] = colors4[i].x;
2134: d[offset++] = colors4[i].y;
2135: d[offset++] = colors4[i].z;
2136: d[offset++] = colors4[i].w;
2137: }
2138:
2139: if (normals != null) {
2140: d[offset++] = normals[i].x;
2141: d[offset++] = normals[i].y;
2142: d[offset++] = normals[i].z;
2143: }
2144:
2145: d[offset++] = coordinates[i].x;
2146: d[offset++] = coordinates[i].y;
2147: d[offset++] = coordinates[i].z;
2148: }
2149: // Register reference to array of interleaved data
2150: if (nio) {
2151: ByteBufferWrapper b = ByteBufferWrapper
2152: .allocateDirect(d.length * 4);
2153: FloatBufferWrapper f = b.order(
2154: ByteOrderWrapper.nativeOrder()).asFloatBuffer();
2155: f.put(d);
2156: ga.setInterleavedVertexBuffer(f.getJ3DBuffer());
2157: } else
2158: ga.setInterleavedVertices(d);
2159: } else if (nio) {
2160:
2161: ByteBufferWrapper b = ByteBufferWrapper
2162: .allocateDirect(coordinates.length * 4 * 3);
2163: FloatBufferWrapper f = b.order(
2164: ByteOrderWrapper.nativeOrder()).asFloatBuffer();
2165: f.put(vecmathToFloat(coordinates));
2166: ga.setCoordRefBuffer(f.getJ3DBuffer());
2167:
2168: if (colors3 != null) {
2169: b = ByteBufferWrapper
2170: .allocateDirect(colors3.length * 4 * 3);
2171: f = b.order(ByteOrderWrapper.nativeOrder())
2172: .asFloatBuffer();
2173: f.put(vecmathToFloat(colors3));
2174: ga.setColorRefBuffer(f.getJ3DBuffer());
2175: } else if (colors4 != null) {
2176: b = ByteBufferWrapper
2177: .allocateDirect(colors4.length * 4 * 4);
2178: f = b.order(ByteOrderWrapper.nativeOrder())
2179: .asFloatBuffer();
2180: f.put(vecmathToFloat(colors4));
2181: ga.setColorRefBuffer(f.getJ3DBuffer());
2182: }
2183:
2184: if (normals != null) {
2185: b = ByteBufferWrapper
2186: .allocateDirect(normals.length * 4 * 3);
2187: f = b.order(ByteOrderWrapper.nativeOrder())
2188: .asFloatBuffer();
2189: f.put(vecmathToFloat(normals));
2190: ga.setNormalRefBuffer(f.getJ3DBuffer());
2191: }
2192:
2193: for (int i = 0; i < texCoordSetCount; i++) {
2194: b = ByteBufferWrapper
2195: .allocateDirect(texCoordSets[i].length * 4
2196: * texCoordDim);
2197: f = b.order(ByteOrderWrapper.nativeOrder())
2198: .asFloatBuffer();
2199: f.put(vecmathToFloat(texCoordSets[i]));
2200: ga.setTexCoordRefBuffer(i, f.getJ3DBuffer());
2201: }
2202: } else if (byRef) {
2203: // Need to copy the data into float arrays - GeometryArray
2204: // prefers them over the vecmath types
2205: ga.setCoordRefFloat(vecmathToFloat(coordinates));
2206: if (colors3 != null)
2207: ga.setColorRefFloat(vecmathToFloat(colors3));
2208: else if (colors4 != null)
2209: ga.setColorRefFloat(vecmathToFloat(colors4));
2210: if (normals != null)
2211: ga.setNormalRefFloat(vecmathToFloat(normals));
2212: for (int i = 0; i < texCoordSetCount; i++) {
2213: ga.setTexCoordRefFloat(i,
2214: vecmathToFloat(texCoordSets[i]));
2215: }
2216: } else {
2217: ga.setCoordinates(0, coordinates);
2218: if (colors3 != null)
2219: ga.setColors(0, colors3);
2220: else if (colors4 != null)
2221: ga.setColors(0, colors4);
2222: if (normals != null)
2223: ga.setNormals(0, normals);
2224: for (int i = 0; i < texCoordSetCount; i++) {
2225: if (texCoordDim == 2) {
2226: ga.setTextureCoordinates(i, 0,
2227: (TexCoord2f[]) texCoordSets[i]);
2228: } else if (texCoordDim == 3) {
2229: ga.setTextureCoordinates(i, 0,
2230: (TexCoord3f[]) texCoordSets[i]);
2231: } else if (texCoordDim == 4) {
2232: ga.setTextureCoordinates(i, 0,
2233: (TexCoord4f[]) texCoordSets[i]);
2234: }
2235: }
2236: }
2237:
2238: if (coordinateIndices != null) {
2239: IndexedGeometryArray iga = null;
2240: iga = (IndexedGeometryArray) ga;
2241: iga.setCoordinateIndices(0, coordinateIndices);
2242: if (!coordOnly) {
2243: if (colorIndices != null)
2244: iga.setColorIndices(0, colorIndices);
2245: if (normalIndices != null)
2246: iga.setNormalIndices(0, normalIndices);
2247: for (int i = 0; i < texCoordSetCount; i++)
2248: iga.setTextureCoordinateIndices(i, 0,
2249: texCoordIndexSets[i]);
2250: }
2251: }
2252: } // End of fillIn
2253:
2254: /**
2255: * Redo indexes to guarantee connection information.
2256: * Use this routine if your original data is in indexed format, but
2257: * you don't trust that the indexing is correct. After this
2258: * routine it is guaranteed that two points with the same
2259: * position will have the same coordinate index (for example).
2260: * Try this if you see
2261: * glitches in your normals or stripification, to rule out
2262: * bad indexing as the source of the problem. Works with normal
2263: * indexed format or USE_COORD_INDEX_ONLY format.
2264: * @throws IllegalArgumentException if coordinate data is missing,
2265: * if the index lists aren't all the
2266: * same length, if an index list is set and the corresponding data
2267: * list isn't set, if a data list is set and the corresponding
2268: * index list is unset (unless all index lists are unset or in
2269: * USE_COORD_INDEX_ONLY format),
2270: * if StripCounts or ContourCounts is inconsistent with the current
2271: * primitive, if the sum of the contourCounts array doesn't equal
2272: * the length of the StripCounts array, or if the number of vertices
2273: * isn't a multiple of three (for triangles) or four (for quads).
2274: */
2275: public void recomputeIndices() {
2276: boolean remember = coordOnly;
2277:
2278: // Can make more efficient implementation later
2279: unindexify();
2280: indexify(remember);
2281: } // End of recomputeIndices
2282:
2283: /**
2284: * Reverse the order of an array of ints (computer class homework
2285: * problem).
2286: */
2287: private void reverseList(int list[]) {
2288: int t;
2289:
2290: if (list == null)
2291: return;
2292:
2293: for (int i = 0; i < list.length / 2; i++) {
2294: t = list[i];
2295: list[i] = list[list.length - i - 1];
2296: list[list.length - i - 1] = t;
2297: }
2298: } // End of reverseList
2299:
2300: /**
2301: * Reverse the order of all lists. If your polygons are formatted with
2302: * clockwise winding, you will always see the back and never the front.
2303: * (Java 3D always wants vertices specified with a counter-clockwise
2304: * winding.)
2305: * This method will (in effect) reverse the winding of your data by
2306: * inverting all of the index lists and the stripCounts
2307: * and contourCounts lists.
2308: * @throws IllegalArgumentException if coordinate data is missing,
2309: * if the index lists aren't all the
2310: * same length, if an index list is set and the corresponding data
2311: * list isn't set, if a data list is set and the corresponding
2312: * index list is unset (unless all index lists are unset or in
2313: * USE_COORD_INDEX_ONLY format),
2314: * if StripCounts or ContourCounts is inconsistent with the current
2315: * primitive, if the sum of the contourCounts array doesn't equal
2316: * the length of the StripCounts array, or if the number of vertices
2317: * isn't a multiple of three (for triangles) or four (for quads).
2318: */
2319: public void reverse() {
2320: indexify();
2321: reverseList(stripCounts);
2322: reverseList(oldStripCounts);
2323: reverseList(contourCounts);
2324: reverseList(coordinateIndices);
2325: reverseList(colorIndices);
2326: reverseList(normalIndices);
2327: for (int i = 0; i < texCoordSetCount; i++)
2328: reverseList(texCoordIndexSets[i]);
2329: } // End of reverse
2330:
2331: /**
2332: * Returns true if the data in this GeometryInfo is currently
2333: * formatted in the USE_COORD_INDEX_ONLY format where a single
2334: * index list is used to index into all data lists.
2335: * @see GeometryInfo#indexify(boolean)
2336: * @see GeometryInfo#getIndexedGeometryArray(boolean, boolean, boolean,
2337: * boolean, boolean)
2338: */
2339: public boolean getUseCoordIndexOnly() {
2340: return coordOnly;
2341: } // End of getUseCoordIndexOnly
2342:
2343: /**
2344: * Tells the GeometryInfo that its data is formatted in the
2345: * USE_COORD_INDEX_ONLY format with a single index list
2346: * (the coordinate index list) that indexes into all data
2347: * lists (coordinates, normals, colors, and texture
2348: * coordinates). NOTE: this will not convert the data
2349: * for you. This method is for when you are sending in
2350: * data useng the setCoordinates, setNormals, setColors,
2351: * and/or setTextureCoordinates methods, and you are only
2352: * setting one index using setCoordinateIndices(). If
2353: * you want GeometryInfo to convert your data to the
2354: * USE_COORD_INDEX_ONLY format, use indexify(true) or
2355: * getIndexedGeometryArray with the useCoordIndexOnly
2356: * parameter set to true.
2357: * @see GeometryInfo#indexify(boolean)
2358: * @see GeometryInfo#getIndexedGeometryArray(boolean, boolean, boolean,
2359: * boolean, boolean)
2360: */
2361: public void setUseCoordIndexOnly(boolean useCoordIndexOnly) {
2362: coordOnly = useCoordIndexOnly;
2363: } // End of setUseCoordIndexOnly
2364:
2365: /**
2366: * Creates and returns a non-indexed Java 3D GeometryArray object
2367: * based on the data in the GeometryInfo object. This object is
2368: * suitable to be attached to a Shape3D node for rendering.
2369: * @param byRef Use geometry BY_REFERENCE
2370: * @param interleaved Use INTERLEAVED geometry. Implies byRef is
2371: * true as well.
2372: * @param nio Create GeometryArray using java.nio.Buffer for
2373: * geometry arrays. Only usable on JDK 1.4 or higher. Implies
2374: * byRef is true as well.
2375: * @throws IllegalArgumentException if coordinate data is missing,
2376: * if the index lists aren't all the
2377: * same length, if an index list is set and the corresponding data
2378: * list isn't set, if a data list is set and the corresponding
2379: * index list is unset (unless all index lists are unset or in
2380: * USE_COORD_INDEX_ONLY format),
2381: * if StripCounts or ContourCounts is inconsistent with the current
2382: * primitive, if the sum of the contourCounts array doesn't equal
2383: * the length of the StripCounts array, or if the number of vertices
2384: * isn't a multiple of three (for triangles) or four (for quads).
2385: */
2386: public GeometryArray getGeometryArray(boolean byRef,
2387: boolean interleaved, boolean nio) {
2388: checkForBadData();
2389:
2390: if (prim == POLYGON_ARRAY) {
2391: if (tr == null)
2392: tr = new Triangulator();
2393: tr.triangulate(this );
2394: } else
2395: changeBackToOldPrim();
2396:
2397: unindexify();
2398:
2399: int vertexFormat = getVertexFormat();
2400: if (nio)
2401: vertexFormat |= (GeometryArray.BY_REFERENCE | GeometryArray.USE_NIO_BUFFER);
2402: if (interleaved)
2403: vertexFormat |= (GeometryArray.BY_REFERENCE | GeometryArray.INTERLEAVED);
2404: if (byRef)
2405: vertexFormat |= GeometryArray.BY_REFERENCE;
2406:
2407: int vertexCount = coordinates.length;
2408:
2409: // If the texCoordSetMap hasn't been set, assume one set of
2410: // texture coordinates only and one texture state unit
2411: if ((texCoordSetCount > 0) && (texCoordSetMap == null)) {
2412: texCoordSetCount = 1;
2413: texCoordSetMap = new int[1];
2414: texCoordSetMap[0] = 0;
2415: }
2416:
2417: // Create the GeometryArray object
2418: GeometryArray ga = null;
2419: switch (prim) {
2420: case TRIANGLE_ARRAY:
2421: TriangleArray ta = new TriangleArray(vertexCount,
2422: vertexFormat, texCoordSetCount, texCoordSetMap);
2423: ga = (GeometryArray) ta;
2424: break;
2425:
2426: case QUAD_ARRAY:
2427: QuadArray qa = new QuadArray(vertexCount, vertexFormat,
2428: texCoordSetCount, texCoordSetMap);
2429: ga = (GeometryArray) qa;
2430: break;
2431:
2432: case TRIANGLE_STRIP_ARRAY:
2433: TriangleStripArray tsa = new TriangleStripArray(
2434: vertexCount, vertexFormat, texCoordSetCount,
2435: texCoordSetMap, stripCounts);
2436: ga = (GeometryArray) tsa;
2437: break;
2438:
2439: case TRIANGLE_FAN_ARRAY:
2440: TriangleFanArray tfa = new TriangleFanArray(vertexCount,
2441: vertexFormat, texCoordSetCount, texCoordSetMap,
2442: stripCounts);
2443: ga = (GeometryArray) tfa;
2444: break;
2445: }
2446:
2447: fillIn(ga, byRef, interleaved, nio);
2448:
2449: return ga;
2450: } // End of getGeometryArray(int, int)
2451:
2452: /**
2453: * Creates and returns a non-indexed Java 3D GeometryArray object
2454: * based on the data in the GeometryInfo object. This object is
2455: * suitable to be attached to a Shape3D node for rendering.
2456: * The geometry is <b>not</b> created using data BY_REFERENCE,
2457: * INTERLEAVED, or USE_NIO_BUFFER.
2458: * @throws IllegalArgumentException if coordinate data is missing,
2459: * if the index lists aren't all the
2460: * same length, if an index list is set and the corresponding data
2461: * list isn't set, if a data list is set and the corresponding
2462: * index list is unset (unless all index lists are unset or in
2463: * USE_COORD_INDEX_ONLY format),
2464: * if StripCounts or ContourCounts is inconsistent with the current
2465: * primitive, if the sum of the contourCounts array doesn't equal
2466: * the length of the StripCounts array, or if the number of vertices
2467: * isn't a multiple of three (for triangles) or four (for quads).
2468: */
2469: public GeometryArray getGeometryArray() {
2470: return getGeometryArray(false, false, false);
2471: } // End of getGeometryArray()
2472:
2473: /**
2474: * Creates and returns a IndexedGeometryArray
2475: * based on the data in the GeometryInfo object. This object is
2476: * suitable to be attached to a Shape3D node for rendering.
2477: * @param compact Remove Coordinates, Colors, Normals, and
2478: * TextureCoordinates that aren't referenced by any indices.
2479: * @param byRef Create the IndexedGeometryArray using geometry
2480: * BY_REFERENCE.
2481: * @param interleaved Use INTERLEAVED geometry. Implies byRef is
2482: * true as well.
2483: * @param nio Create GeometryArray using java.nio.Buffer for
2484: * geometry arrays. Only usable on JDK 1.4 or higher. Implies
2485: * byRef is true as well.
2486: * @param useCoordIndexOnly Create the IndexedGeometryArray using
2487: * USE_COORD_INDEX_ONLY. Values from the coordinate index array
2488: * are used as a single set of indices into all vertex
2489: * component arrays (coord, color, normal, and texCoord).
2490: * @throws IllegalArgumentException if coordinate data is missing,
2491: * if the index lists aren't all the
2492: * same length, if an index list is set and the corresponding data
2493: * list isn't set, if a data list is set and the corresponding
2494: * index list is unset (unless all index lists are unset or in
2495: * USE_COORD_INDEX_ONLY format),
2496: * if StripCounts or ContourCounts is inconsistent with the current
2497: * primitive, if the sum of the contourCounts array doesn't equal
2498: * the length of the StripCounts array, or if the number of vertices
2499: * isn't a multiple of three (for triangles) or four (for quads).
2500: */
2501: public IndexedGeometryArray getIndexedGeometryArray(
2502: boolean compact, boolean byRef, boolean interleaved,
2503: boolean useCoordIndexOnly, boolean nio) {
2504: indexify(useCoordIndexOnly);
2505:
2506: if (compact)
2507: compact();
2508:
2509: if (prim == POLYGON_ARRAY) {
2510: if (tr == null)
2511: tr = new Triangulator();
2512: tr.triangulate(this );
2513: } else
2514: changeBackToOldPrim();
2515:
2516: if (useCoordIndexOnly && coordOnly == false) {
2517: // Check to see if we can optimize for USE_COORD_INDEX_ONLY
2518: int i, j;
2519: boolean canUseCoordIndexOnly = true;
2520:
2521: if (coordinateIndices != null) {
2522: // See if all the array lengths are the same
2523: if (colorIndices != null
2524: && colorIndices.length != coordinateIndices.length) {
2525: canUseCoordIndexOnly = false;
2526: }
2527: if (normalIndices != null
2528: && normalIndices.length != coordinateIndices.length) {
2529: canUseCoordIndexOnly = false;
2530: }
2531: for (i = 0; i < texCoordSetCount; i++) {
2532: if (texCoordIndexSets[i] != null
2533: && texCoordIndexSets[i].length != coordinateIndices.length) {
2534: canUseCoordIndexOnly = false;
2535: break;
2536: }
2537: }
2538: if (canUseCoordIndexOnly
2539: && ((colorIndices != null)
2540: || (normalIndices != null) || (texCoordSetCount > 0))) {
2541: // All array lengths are the same. Check their contents
2542:
2543: for (i = 0; i < coordinateIndices.length; i++) {
2544: int indexValue = coordinateIndices[i];
2545:
2546: if (colorIndices != null
2547: && colorIndices[i] != indexValue) {
2548: canUseCoordIndexOnly = false;
2549: break;
2550: }
2551: if (normalIndices != null
2552: && normalIndices[i] != indexValue) {
2553: canUseCoordIndexOnly = false;
2554: break;
2555: }
2556: for (j = 0; j < texCoordSetCount; j++) {
2557: if (texCoordIndexSets[j] != null
2558: && texCoordIndexSets[j][i] != indexValue) {
2559: canUseCoordIndexOnly = false;
2560: break;
2561: }
2562: }
2563: }
2564: }
2565: }
2566: coordOnly = canUseCoordIndexOnly;
2567: }
2568:
2569: int vertexFormat = getVertexFormat();
2570: if (nio)
2571: vertexFormat |= (GeometryArray.BY_REFERENCE | GeometryArray.USE_NIO_BUFFER);
2572: if (interleaved)
2573: vertexFormat |= (GeometryArray.BY_REFERENCE | GeometryArray.INTERLEAVED);
2574: if (byRef)
2575: vertexFormat |= GeometryArray.BY_REFERENCE;
2576: if (coordOnly)
2577: vertexFormat |= GeometryArray.USE_COORD_INDEX_ONLY;
2578:
2579: int vertexCount = getVertexCount();
2580:
2581: if ((texCoordSetCount > 0) && (texCoordSetMap == null)) {
2582: texCoordSetCount = 1;
2583: texCoordSetMap = new int[1];
2584: texCoordSetMap[0] = 0;
2585: }
2586:
2587: //
2588: // Create the IndexedGeometryArray object
2589: //
2590:
2591: IndexedGeometryArray ga = null;
2592:
2593: switch (prim) {
2594: case TRIANGLE_ARRAY:
2595: IndexedTriangleArray ta = new IndexedTriangleArray(
2596: vertexCount, vertexFormat, texCoordSetCount,
2597: texCoordSetMap, coordinateIndices.length);
2598: ga = (IndexedGeometryArray) ta;
2599: break;
2600:
2601: case QUAD_ARRAY:
2602: IndexedQuadArray qa = new IndexedQuadArray(vertexCount,
2603: vertexFormat, texCoordSetCount, texCoordSetMap,
2604: coordinateIndices.length);
2605: ga = (IndexedGeometryArray) qa;
2606: break;
2607: case TRIANGLE_STRIP_ARRAY:
2608: IndexedTriangleStripArray tsa = new IndexedTriangleStripArray(
2609: vertexCount, vertexFormat, texCoordSetCount,
2610: texCoordSetMap, coordinateIndices.length,
2611: stripCounts);
2612: ga = (IndexedGeometryArray) tsa;
2613: break;
2614:
2615: case TRIANGLE_FAN_ARRAY:
2616: IndexedTriangleFanArray tfa = new IndexedTriangleFanArray(
2617: vertexCount, vertexFormat, texCoordSetCount,
2618: texCoordSetMap, coordinateIndices.length,
2619: stripCounts);
2620: ga = (IndexedGeometryArray) tfa;
2621: break;
2622: }
2623:
2624: // Fill in the GeometryArray object
2625: fillIn(ga, byRef, interleaved, nio);
2626:
2627: return ga;
2628: } // End of getIndexedGeometryArray(bool, bool, bool, bool, bool)
2629:
2630: /**
2631: * Creates and returns an IndexedGeometryArray
2632: * based on the data in the GeometryInfo object. This object is
2633: * suitable to be attached to a Shape3D node for rendering.
2634: * Equivalent to <code>getIndexedGeometryArray(compact, false,
2635: * false, false, false)</code>.
2636: * @param compact Remove Coordinates, Colors, Normals, and
2637: * TextureCoordinates that aren't referenced by any indices.
2638: * @throws IllegalArgumentException if coordinate data is missing,
2639: * if the index lists aren't all the
2640: * same length, if an index list is set and the corresponding data
2641: * list isn't set, if a data list is set and the corresponding
2642: * index list is unset (unless all index lists are unset or in
2643: * USE_COORD_INDEX_ONLY format),
2644: * if StripCounts or ContourCounts is inconsistent with the current
2645: * primitive, if the sum of the contourCounts array doesn't equal
2646: * the length of the StripCounts array, or if the number of vertices
2647: * isn't a multiple of three (for triangles) or four (for quads).
2648: */
2649: public IndexedGeometryArray getIndexedGeometryArray(boolean compact) {
2650: return getIndexedGeometryArray(compact, false, false, false,
2651: false);
2652: } // End of getIndexedGeometryArray(boolean)
2653:
2654: /**
2655: * Creates and returns an IndexedGeometryArray
2656: * based on the data in the GeometryInfo object. This object is
2657: * suitable to be attached to a Shape3D node for rendering.
2658: * Equivalent to <code>getIndexedGeometryArray(false, false,
2659: * false, false, false)</code>.
2660: * @throws IllegalArgumentException if coordinate data is missing,
2661: * if the index lists aren't all the
2662: * same length, if an index list is set and the corresponding data
2663: * list isn't set, if a data list is set and the corresponding
2664: * index list is unset (unless all index lists are unset or in
2665: * USE_COORD_INDEX_ONLY format),
2666: * if StripCounts or ContourCounts is inconsistent with the current
2667: * primitive, if the sum of the contourCounts array doesn't equal
2668: * the length of the StripCounts array, or if the number of vertices
2669: * isn't a multiple of three (for triangles) or four (for quads).
2670: */
2671: public IndexedGeometryArray getIndexedGeometryArray() {
2672: return getIndexedGeometryArray(false, false, false, false,
2673: false);
2674: } // End of getIndexedGeometryArray()
2675:
2676: } // End of class GeometryInfo
2677:
2678: // End of file GeometryInfo.java
|