gt: 		shapes.add(new Shape3D(lsa, a)) ;
context: /*
   * $RCSfile$
   *
   * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Sun designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Sun in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   *
   * $Revision: 892 $
   * $Date: 2008-02-28 20:18:01 +0000 (Thu, 28 Feb 2008) $
   * $State$
   */
  
  package javax.media.j3d;
  import javax.vecmath.* ;
  import java.util.* ;
  
  /**
   * This class implements a Shape3D backend for the abstract
   * GeometryDecompressor.
   */
  class GeometryDecompressorShape3D extends GeometryDecompressor {
      private static final boolean debug = false ;
      private static final boolean benchmark = false ;
      private static final boolean statistics = false ;
      private static final boolean printInfo = debug || benchmark || statistics ;
  
      // Type of connections in the compressed data:
      // TYPE_POINT (1), TYPE_LINE (2), or TYPE_TRIANGLE (4).
      private int bufferDataType ;
  
      // Data bundled with each vertex: bitwise combination of
      // NORMAL_IN_BUFFER (1), COLOR_IN_BUFFER (2), ALPHA_IN_BUFFER (4).
      private int dataPresent ;
  
      // List for accumulating the output of the decompressor and converting to
      // GeometryArray representations.
      private GeneralizedVertexList vlist ;
  
      // Accumulates Shape3D objects constructed from decompressor output.
      private ArrayList shapes ;
  
      // Decompressor output state variables.
      private Color4f curColor ;
      private Vector3f curNormal ;
  
      // Variables for gathering statistics.
      private int origVertexCount ;
      private int stripCount ;
      private int vertexCount ;
      private int triangleCount ;
      private long startTime ;
      private long endTime ;
  
      // Triangle array type to construct.
      private int triOutputType ;
  
      // Types of triangle output available.
      private static final int TRI_SET = 0 ;
      private static final int TRI_STRIP_SET = 1 ;
      private static final int TRI_STRIP_AND_FAN_SET = 2 ;
      private static final int TRI_STRIP_AND_TRI_SET = 3 ;
  
      // Private convenience copies of various constants.
      private static final int TYPE_POINT = 
  	CompressedGeometryRetained.TYPE_POINT ;
      private static final int TYPE_LINE = 
  	CompressedGeometryRetained.TYPE_LINE ;
      private static final int TYPE_TRIANGLE = 
  	CompressedGeometryRetained.TYPE_TRIANGLE ;
      private static final int FRONTFACE_CCW = 
  	GeneralizedStripFlags.FRONTFACE_CCW ;
  
      /**
       * Decompress the given compressed geometry. 
       * @param cgr CompressedGeometryRetained object with compressed geometry
       * @return an array of Shape3D with TriangleArray geometry if compressed
       * data contains triangles; otherwise, Shape3D array containing PointArray
       * or LineStripArray geometry
       * @see CompressedGeometry
       * @see GeometryDecompressor
       */
      Shape3D[] toTriangleArrays(CompressedGeometryRetained cgr) {
  	return decompress(cgr, TRI_SET) ;
      }
  
  
      /**
       * Decompress the given compressed geometry. 
       * @param cgr CompressedGeometryRetained object with compressed geometry
       * @return an array of Shape3D with TriangleStripArray geometry if
       * compressed data contains triangles; otherwise, Shape3D array containing
       * PointArray or LineStripArray geometry
       * @see CompressedGeometry
       * @see GeometryDecompressor
       */
      Shape3D[] toTriangleStripArrays(CompressedGeometryRetained cgr) {
  	return decompress(cgr, TRI_STRIP_SET) ;
      }
  
  
      /**
       * Decompress the given compressed geometry. 
       * @param cgr CompressedGeometryRetained object with compressed geometry
       * @return an array of Shape3D with TriangleStripArray and
       * TriangleFanArray geometry if compressed data contains triangles;
       * otherwise, Shape3D array containing PointArray or LineStripArray
       * geometry
       * @see CompressedGeometry
       * @see GeometryDecompressor
       */
      Shape3D[] toStripAndFanArrays(CompressedGeometryRetained cgr) {
  	return decompress(cgr, TRI_STRIP_AND_FAN_SET) ;
      }
  
  
      /**
       * Decompress the given compressed geometry. 
       * @param cgr CompressedGeometryRetained object with compressed geometry
       * @return an array of Shape3D with TriangleStripArray and
       * TriangleArray geometry if compressed data contains triangles;
       * otherwise, Shape3D array containing PointArray or LineStripArray
       * geometry
       * @see CompressedGeometry
       * @see GeometryDecompressor
       */
      Shape3D[] toStripAndTriangleArrays(CompressedGeometryRetained cgr) {
  	return decompress(cgr, TRI_STRIP_AND_TRI_SET) ;
      }
  
      /**
       * Decompress the data contained in a CompressedGeometryRetained and
       * return an array of Shape3D objects using the specified triangle output
       * type.  The triangle output type is ignored if the compressed data
       * contains points or lines.
       */ 
      private Shape3D[] decompress(CompressedGeometryRetained cgr,
  				 int triOutputType) {
  
  	if (! checkVersion(cgr.majorVersionNumber, cgr.minorVersionNumber)) {
  	    return null ;
  	}
  
  	vlist = null ;
  	curColor = null ;
  	curNormal = null ;
  
  	// Get descriptors for compressed data.
  	bufferDataType = cgr.bufferType ;
  	dataPresent = cgr.bufferContents ;
  	if (printInfo) beginPrint() ;
  
  	// Initialize the decompressor backend.
  	this.triOutputType = triOutputType ;
  	shapes = new ArrayList() ;
  
  	// Call the superclass decompress() method which calls the output
  	// methods of this subclass.  The results are stored in vlist.
  	super.decompress(cgr.offset, cgr.size, cgr.compressedGeometry) ;
  
  	// Convert the decompressor output to Shape3D objects.
  	addShape3D() ;
  	if (printInfo) endPrint() ;
  
  	// Return the fixed-length output array.
  	Shape3D shapeArray[] = new Shape3D[shapes.size()] ;
  	return (Shape3D[])shapes.toArray(shapeArray) ;
      }
  
      /**
       * Initialize the vertex output list based on the vertex format provided
       * by the SetState decompression command.
       */
      void outputVertexFormat(boolean bundlingNorm, boolean bundlingColor,
  			    boolean doingAlpha) {
  
  	if (vlist != null)
  	    // Construct shapes using the current vertex format.
  	    addShape3D() ;
  		
  	int vertexFormat = GeometryArray.COORDINATES ;
  
  	if (bundlingNorm)  vertexFormat |= GeometryArray.NORMALS ;
  	if (bundlingColor) vertexFormat |= GeometryArray.COLOR ;
  	if (doingAlpha)    vertexFormat |= GeometryArray.WITH_ALPHA ;
  
  	vlist = new GeneralizedVertexList(vertexFormat, FRONTFACE_CCW) ;
      }
  
      /**
       * Add a new decompressed vertex to the current list.
       */
      void outputVertex(Point3f position, Vector3f normal,
  		      Color4f color, int vertexReplaceCode) {
  
  	if (curNormal != null) normal = curNormal ;
  	vlist.addVertex(position, normal, color, vertexReplaceCode) ;
  
  	if (debug) {
  	    System.err.println(" outputVertex: flag " + vertexReplaceCode) ;
  	    System.err.println("  position " + position.toString()) ;
  	    if (normal != null)
  		System.err.println("  normal " + normal.toString()) ;
  	    if (color != null)
  		System.err.println("  color " + color.toString()) ;
  	}
      }
  
      /**
       * Create a Shape3D using the current color for both the ambient and
       * diffuse material colors, then start a new vertex list for the new
       * color.  The outputColor() method is never called if colors are bundled
       * with each vertex in the compressed buffer.
       */
      void outputColor(Color4f color) {
  	if (debug) System.err.println(" outputColor: " + color.toString()) ;
  
  	if (vlist.size() > 0) {
  	    // Construct Shape3D using the current color.
  	    addShape3D() ;
  
  	    // Start a new vertex list for the new color.
  	    vlist = new GeneralizedVertexList(vlist.vertexFormat,
  					      FRONTFACE_CCW) ;
  	}
  	if (curColor == null) curColor = new Color4f() ;
  	curColor.set(color) ;
      }
  
      /**
       * Set the current normal that will be copied to each succeeding vertex
       * output by the decompressor.  The per-vertex copy is needed since in
       * Java 3D a normal is always associated with a vertex.  This method is
       * never called if normals are bundled with each vertex in the compressed
       * buffer.
       */
      void outputNormal(Vector3f normal) {
  	if (debug) System.err.println(" outputNormal: " + normal.toString()) ;
  
  	if ((vlist.vertexFormat & GeometryArray.NORMALS) == 0) {
  	    if (vlist.size() > 0)
  		// Construct Shape3D using the current vertex format.
  		addShape3D() ;
  		
  	    // Start a new vertex list with the new format.
  	    vlist = new GeneralizedVertexList
  		(vlist.vertexFormat|GeometryArray.NORMALS, FRONTFACE_CCW) ;
  	}
  	if (curNormal == null) curNormal = new Vector3f() ;
  	curNormal.set(normal) ;
      }
  
      /**
       * Create a Shape3D object of the desired type from the current vertex
       * list.  Apply the current color, if non-null, as a Material attribute.
       */
      private void addShape3D() {
  	Material m = new Material() ;
  
  	if (curColor != null) {
  	    if ((vlist.vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
  		m.setAmbientColor(curColor.x, curColor.y, curColor.z) ;
  		m.setDiffuseColor(curColor.x, curColor.y, curColor.z) ;
  	    }
  	    else {
  		m.setAmbientColor(curColor.x, curColor.y, curColor.z) ;
  		m.setDiffuseColor(curColor.x, curColor.y, curColor.z,
  				  curColor.w) ;
  	    }
  	}
  
  	if ((vlist.vertexFormat & GeometryArray.NORMALS) == 0)
  	    m.setLightingEnable(false) ;
  	else
  	    m.setLightingEnable(true) ;
  
  	Appearance a = new Appearance() ;
  	a.setMaterial(m) ;
  
  	switch(bufferDataType) {
  	  case TYPE_TRIANGLE:
  	    switch(triOutputType) {
  	      case TRI_SET:
  		TriangleArray ta = vlist.toTriangleArray() ;
  		if (ta != null)
  		    shapes.add(new Shape3D(ta, a)) ;
  		break ;
  	      case TRI_STRIP_SET:
  		TriangleStripArray tsa = vlist.toTriangleStripArray() ;
  		if (tsa != null)
  		    shapes.add(new Shape3D(tsa, a)) ;
  		break ;
  	      case TRI_STRIP_AND_FAN_SET:
  		GeometryStripArray gsa[] = vlist.toStripAndFanArrays() ;
  		if (gsa[0] != null)
  		    shapes.add(new Shape3D(gsa[0], a)) ;
  		if (gsa[1] != null)
  		    shapes.add(new Shape3D(gsa[1], a)) ;
  		break ;
  	      case TRI_STRIP_AND_TRI_SET:
  		GeometryArray ga[] = vlist.toStripAndTriangleArrays() ;
  		if (ga[0] != null)
  		    shapes.add(new Shape3D(ga[0], a)) ;
  		if (ga[1] != null)
  		    shapes.add(new Shape3D(ga[1], a)) ;
  		break ;
  	      default:
  		throw new IllegalArgumentException
  		    (J3dI18N.getString("GeometryDecompressorShape3D0")) ;
  	    }
   	    break ;
  
  	  case TYPE_LINE:
  	    LineStripArray lsa = vlist.toLineStripArray() ;
  	    if (lsa != null)
  