gt:             field = node.getFieldValue(index);
context: /*****************************************************************************
   *                        Web3d.org Copyright (c) 2001
   *                               Java Source
   *
   * This source is licensed under the GNU LGPL v2.1
   * Please read http://www.gnu.org/copyleft/lgpl.html for more information
   *
   * This software comes with the standard NO WARRANTY disclaimer for any
   * purpose. Use it at your own risk. If there's a problem you get to fix it.
   *
   ****************************************************************************/
  
  package org.web3d.vrml.renderer.common.nodes.rigidphysics;
  
  // External imports
  import java.util.HashMap;
  
  import org.odejava.Body;
  import org.odejava.JointGroup;
  import org.odejava.JointUniversal;
  import org.odejava.World;
  import org.odejava.ode.OdeConstants;
  
  // Local imports
  import org.web3d.vrml.lang.*;
  import org.web3d.vrml.nodes.*;
  
  import org.web3d.vrml.renderer.common.nodes.AbstractNode;
  
  /**
   * Implementation of the UniversalJoint node.
   * <p>
   *
   * @author Justin Couch
   * @version $Revision: 1.6 $
   */
  public abstract class BaseUniversalJoint extends BaseJointNode {
  
      // Field index constants
  
      /** The field index for anchorPoint */
      protected static final int FIELD_ANCHOR_POINT = LAST_JOINT_INDEX + 1;
  
      /** The field index for axis1 */
      protected static final int FIELD_AXIS1 = LAST_JOINT_INDEX + 2;
  
      /** The field index for axis2 */
      protected static final int FIELD_AXIS2 = LAST_JOINT_INDEX + 3;
  
      /** The field index for body1AnchorPoint */
      protected static final int FIELD_BODY1_ANCHOR_POINT = LAST_JOINT_INDEX + 4;
  
      /** The field index for body2AnchorPoint */
      protected static final int FIELD_BODY2_ANCHOR_POINT = LAST_JOINT_INDEX + 5;
  
      /** The field index for body1Axis */
      protected static final int FIELD_BODY1_AXIS = LAST_JOINT_INDEX + 6;
  
      /** The field index for body2Axis */
      protected static final int FIELD_BODY2_AXIS = LAST_JOINT_INDEX + 7;
  
      /** The field index for stop1Bounce */
      protected static final int FIELD_STOP1_BOUNCE = LAST_JOINT_INDEX + 8;
  
      /** The field index for stop2Bounce */
      protected static final int FIELD_STOP2_BOUNCE = LAST_JOINT_INDEX + 9;
  
      /** The field index for stop1ErrorCorrection */
      protected static final int FIELD_STOP1_ERROR_CORRECTION = LAST_JOINT_INDEX + 10;
  
      /** The field index for stop2ErrorCorrection */
      protected static final int FIELD_STOP2_ERROR_CORRECTION = LAST_JOINT_INDEX + 11;
  
      /** Last index used by this base node */
      protected static final int LAST_INDEX = FIELD_STOP2_ERROR_CORRECTION;
  
      /** Number of fields in this node */
      private static final int NUM_FIELDS = LAST_INDEX + 1;
  
      /** Message when the stopBounce value is out of range */
      protected static final String BOUNCE1_RANGE_MSG =
          "The stop1Bounce value is out of the required range [0,1]: ";
  
      /** Message when the stop2Bounce value is out of range */
      protected static final String BOUNCE2_RANGE_MSG =
          "The stop2Bounce value is out of the required range [0,1]: ";
  
      /** Message when the stop1ErrorCorrection value is out of range */
      protected static final String STOP_ERROR1_RANGE_MSG =
          "The stop1ErrorCorrection value is out of the required range [0,1]: ";
  
      /** Message when the stop2ErrorCorrection value is out of range */
      protected static final String STOP_ERROR2_RANGE_MSG =
          "The stop2ErrorCorrection value is out of the required range [0,1]: ";
  
      /** Message when the user attempt to write to the body1AnchorPoint field */
      private static final String AP1_WRITE_MSG =
          "body1AnchorPoint is outputOnly and cannot be set";
  
      /** Message when the user attempt to write to the body2AnchorPoint field */
      private static final String AP2_WRITE_MSG =
          "body2AnchorPoint is outputOnly and cannot be set";
  
      /** Message when the user attempt to write to the body1Axis field */
      private static final String AX1_WRITE_MSG =
          "body1Axis is outputOnly and cannot be set";
  
      /** Message when the user attempt to write to the body2Axis field */
      private static final String AX2_WRITE_MSG =
          "body2Axis is outputOnly and cannot be set";
  
      /** Index list if the output capable fields */
      private static final int[] outputFields;
  
      /** Listing of field indexes that have nodes */
      private static final int[] nodeFields;
  
      /** Array of VRMLFieldDeclarations */
      private static VRMLFieldDeclaration[] fieldDecl;
  
      /** Hashmap between a field name and its index */
      private static HashMap fieldMap;
  
      // The VRML field values
  
      /** The value of the anchorPoint field */
      protected float[] vfAnchorPoint;
  
      /** The value of the axis1 field */
      protected float[] vfAxis1;
  
      /** The value of the axis2 field */
      protected float[] vfAxis2;
  
      /** The value of the body1AnchorPoint field */
      protected float[] vfBody1AnchorPoint;
  
      /** The value of the body1AnchorPoint field */
      protected float[] vfBody2AnchorPoint;
  
      /** The value of the body1Axis field */
      protected float[] vfBody1Axis;
  
      /** The value of the body1Axis field */
      protected float[] vfBody2Axis;
  
      /** The value of the stop1Bounce field */
      protected float vfStop1Bounce;
  
      /** The value of the stop2Bounce field */
      protected float vfStop2Bounce;
  
      /** The value of the stop1ErrorCorrection field */
      protected float vfStop1ErrorCorrection;
  
      /** The value of the stop2ErrorCorrection field */
      protected float vfStop2ErrorCorrection;
  
      // Other vars
  
      /** The ODE representation of the joint */
      protected JointUniversal odeJoint;
  
      /**
       * Static constructor to initialise all the field values.
       */
      static {
          nodeFields = new int[] {
              FIELD_METADATA,
              FIELD_BODY1,
              FIELD_BODY2
          };
  
          outputFields = new int[] {
              FIELD_BODY1_ANCHOR_POINT,
              FIELD_BODY2_ANCHOR_POINT,
              FIELD_BODY1_AXIS,
              FIELD_BODY2_AXIS,
          };
  
          fieldDecl = new VRMLFieldDeclaration[NUM_FIELDS];
          fieldMap = new HashMap(NUM_FIELDS * 3);
  
          fieldDecl[FIELD_METADATA] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFNode",
                                       "metadata");
          fieldDecl[FIELD_ANCHOR_POINT] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFVec3f",
                                       "anchorPoint");
          fieldDecl[FIELD_AXIS1] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFVec3f",
                                       "axis1");
          fieldDecl[FIELD_AXIS2] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFVec3f",
                                       "axis2");
          fieldDecl[FIELD_BODY1] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFNode",
                                       "body1");
          fieldDecl[FIELD_BODY2] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFNode",
                                       "body2");
          fieldDecl[FIELD_BODY1_ANCHOR_POINT] =
              new VRMLFieldDeclaration(FieldConstants.EVENTOUT,
                                       "SFVec3f",
                                       "body1AnchorPoint");
          fieldDecl[FIELD_BODY2_ANCHOR_POINT] =
              new VRMLFieldDeclaration(FieldConstants.EVENTOUT,
                                       "SFVec3f",
                                       "body2AnchorPoint");
          fieldDecl[FIELD_BODY1_AXIS] =
              new VRMLFieldDeclaration(FieldConstants.EVENTOUT,
                                       "SFVec3f",
                                       "body1Axis");
          fieldDecl[FIELD_BODY2_AXIS] =
              new VRMLFieldDeclaration(FieldConstants.EVENTOUT,
                                       "SFVec3f",
                                       "body2Axis");
          fieldDecl[FIELD_STOP1_BOUNCE] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFFloat",
                                       "stop1Bounce");
          fieldDecl[FIELD_STOP2_BOUNCE] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFFloat",
                                       "stop2Bounce");
          fieldDecl[FIELD_STOP1_ERROR_CORRECTION] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFFloat",
                                       "stop1ErrorCorrection");
          fieldDecl[FIELD_STOP2_ERROR_CORRECTION] =
              new VRMLFieldDeclaration(FieldConstants.EXPOSEDFIELD,
                                       "SFFloat",
                                       "stop2ErrorCorrection");
  
          Integer idx = new Integer(FIELD_METADATA);
          fieldMap.put("metadata", idx);
          fieldMap.put("set_metadata", idx);
          fieldMap.put("metadata_changed", idx);
  
          idx = new Integer(FIELD_ANCHOR_POINT);
          fieldMap.put("anchorPoint", idx);
          fieldMap.put("set_anchorPoint", idx);
          fieldMap.put("anchorPoint_changed", idx);
  
          idx = new Integer(FIELD_BODY1);
          fieldMap.put("body1", idx);
          fieldMap.put("set_body1", idx);
          fieldMap.put("body1_changed", idx);
  
          idx = new Integer(FIELD_BODY2);
          fieldMap.put("body2", idx);
          fieldMap.put("set_body2", idx);
          fieldMap.put("body2_changed", idx);
  
          idx = new Integer(FIELD_AXIS1);
          fieldMap.put("axis1", idx);
          fieldMap.put("set_axis1", idx);
          fieldMap.put("axis1_changed", idx);
  
          idx = new Integer(FIELD_AXIS2);
          fieldMap.put("axis2", idx);
          fieldMap.put("set_axis2", idx);
          fieldMap.put("axis2_changed", idx);
  
          idx = new Integer(FIELD_STOP1_BOUNCE);
          fieldMap.put("stop1Bounce", idx);
          fieldMap.put("set_stop1Bounce", idx);
          fieldMap.put("stop1Bounce_changed", idx);
  
          idx = new Integer(FIELD_STOP2_BOUNCE);
          fieldMap.put("stop2Bounce", idx);
          fieldMap.put("set_stop2Bounce", idx);
          fieldMap.put("stop2Bounce_changed", idx);
  
          idx = new Integer(FIELD_STOP1_ERROR_CORRECTION);
          fieldMap.put("stop1ErrorCorrection", idx);
          fieldMap.put("set_stop1ErrorCorrection", idx);
          fieldMap.put("stop1ErrorCorrection_changed", idx);
  
          idx = new Integer(FIELD_STOP2_ERROR_CORRECTION);
          fieldMap.put("stop2ErrorCorrection", idx);
          fieldMap.put("set_stop2ErrorCorrection", idx);
          fieldMap.put("stop2ErrorCorrection_changed", idx);
  
          fieldMap.put("body1AnchorPoint", new Integer(FIELD_BODY1_ANCHOR_POINT));
          fieldMap.put("body2AnchorPoint", new Integer(FIELD_BODY2_ANCHOR_POINT));
          fieldMap.put("body1Axis", new Integer(FIELD_BODY1_AXIS));
          fieldMap.put("body2Axis", new Integer(FIELD_BODY2_AXIS));
      }
  
      /**
       * Construct a new default universal joint node object.
       */
      public BaseUniversalJoint() {
          super("UniversalJoint");
  
          vfAnchorPoint = new float[3];
          vfAxis1 = new float[3];
          vfAxis2 = new float[3];
          vfStop1Bounce = 0;
          vfStop2Bounce = 0;
          vfStop1ErrorCorrection = 0.8f;
          vfStop2ErrorCorrection = 0.8f;
  
          vfBody1AnchorPoint = new float[3];
          vfBody2AnchorPoint = new float[3];
          vfBody1Axis = new float[3];
          vfBody2Axis = new float[3];
  
          hasChanged = new boolean[NUM_FIELDS];
      }
  
      /**
       * Construct a new instance of this node based on the details from the
       * given node. If the node is not the same type, an exception will be
       * thrown.
       *
       * @param node The node to copy
       * @throws IllegalArgumentException The node is not the same type
       */
      public BaseUniversalJoint(VRMLNodeType node) {
          this();
  
          checkNodeType(node);
  
          try {
              int index = node.getFieldIndex("anchorPoint");
              VRMLFieldData field = node.getFieldValue(index);
              vfAnchorPoint[0] = field.floatArrayValue[0];
              vfAnchorPoint[1] = field.floatArrayValue[1];
              vfAnchorPoint[2] = field.floatArrayValue[2];
  
              index = node.getFieldIndex("axis1");
              field = node.getFieldValue(index);
              vfAxis1[0] = field.floatArrayValue[0];
              vfAxis1[1] = field.floatArrayValue[1];
              vfAxis1[2] = field.floatArrayValue[2];
  
              index = node.getFieldIndex("axis2");
              field = node.getFieldValue(index);
              vfAxis2[0] = field.floatArrayValue[0];
              vfAxis2[1] = field.floatArrayValue[1];
              vfAxis2[2] = field.floatArrayValue[2];
  
              index = node.getFieldIndex("stop1Bounce");
              field = node.getFieldValue(index);
              vfStop1Bounce = field.floatValue;
  
              index = node.getFieldIndex("stop2Bounce");
  