When a BY_REFERENCE GeometryArray object is created, the user creates geometry arrays and populates those arrays with geometry data. There are no geometry arrays internal to the Geometry object no copy of the geometry data made. Instead the BY_REFERENCE GeometryArray object simply stores a reference to the user array(s) of geometry data.

There are two good reasons for using BY_REFERENCE GeometryArray:

  1. if the geometry data is dynamic
  2. if the geometry data requires too much memory

This program shows how to implement the dynamic geometry data by a BY_REFERENCE GeometryArray.

 public class DynamicCylinder extends JFrame {
  private float height = 0.5f;
  private float radius = 0.02f;
  private int verticesNum = 40;
  private float[] vertices = new float[verticesNum * 3];
  private Shape3D cylinder=new Shape3D(createGeometry());
  
  private JTextField heightTxt=new JTextField("0.5",5);
  private JTextField radiusTxt=new JTextField("0.02",5);
  
  public DynamicCylinder() {
    ...
    
    // Prepare the control panel for changing the height and radius of 
    // the cylinder
    JPanel panel=new JPanel();
    panel.add(new JLabel("Height:"));
    panel.add(heightTxt);
    panel.add(new JLabel("Radius:"));
    panel.add(radiusTxt);
    JButton okBtn=new JButton("Ok");
    okBtn.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        setHeight(Float.parseFloat(heightTxt.getText()));
        setRadius(Float.parseFloat(radiusTxt.getText()));
      }
      
    });
    panel.add(okBtn);
    getContentPane().add(panel,BorderLayout.SOUTH);
  }

  public BranchGroup createSceneGraph() {
    BranchGroup objRoot = new BranchGroup();

    // Set the proper capabilities
    cylinder.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
    
    objRoot.addChild(cylinder);

    return objRoot;
  }

  private Geometry createGeometry() {
    updateVertices();

    // Create the geometry by reference
    TriangleStripArray quadArray = new TriangleStripArray(verticesNum,
        GeometryArray.COORDINATES | GeometryArray.BY_REFERENCE,
        new int[] { verticesNum });
    quadArray.setCoordRefFloat(vertices);
    // Set the capabilities
    quadArray.setCapability(GeometryArray.ALLOW_REF_DATA_READ);
    quadArray.setCapability(GeometryArray.ALLOW_REF_DATA_WRITE);

    return quadArray;
  }
  
  private void updateVertices() {
      float perR = (float) (2 * Math.PI / (verticesNum / 2 - 1));      
      for (int i = 0; i < verticesNum; i += 2) {
        vertices[ (i + 1) * 3] = vertices[i *
            3] = (float) (radius * Math.cos(i / 2 * perR));
        vertices[ (i + 1) * 3 + 2] = vertices[i * 3 +
            2] = (float) (radius * Math.sin(i / 2 * perR));
        vertices[i * 3 + 1] = height;
        vertices[ (i + 1) * 3 + 1] = 0;
      }
    }
  
  public void setHeight(float height) {
      float oldHeight = this.height;
      this.height = height;

      // Update the geometry
      this.updateGeometry();
    }
  
  public void setRadius(float radius) {
      float oldRadius = this.radius;
      this.radius = radius;

      // Update the geometry
      this.updateGeometry();
    }
  
  private void updateGeometry() {
      GeometryArray geometryArray = (GeometryArray)cylinder.getGeometry();
      geometryArray.updateData(new GeometryUpdater(){
        public void updateData(Geometry geometry){
          updateVertices();
        }
      });
    }

  public static void main(String[] args) {
    ...
  }
}