/**
   * Computes the new transform for this interpolator for a given alpha value.
   *
   * @param alphaValue alpha value between 0.0 and 1.0
   * @param transform object that receives the computed transform for the specified alpha value
   * @since Java 3D 1.3
   */
  public void computeTransform(float alphaValue, Matrix4f transform) {
    transform.loadIdentity();

    // compute the current value of u from alpha and the
    // determine lower and upper knot points
    computePathInterpolation(alphaValue);

    // Determine the segment within which we will be interpolating
    currentSegmentIndex = this.lowerKnot - 1;

    // if we are at the start of the curve
    if (currentSegmentIndex == 0 && currentU == 0f) {

      iQuat.set(keyFrames[1].quat);
      iPos.set(keyFrames[1].position);
      iScale.set(keyFrames[1].scale);

      // if we are at the end of the curve
    } else if (currentSegmentIndex == (numSegments - 1) && currentU == 1.0) {

      iQuat.set(keyFrames[upperKnot].quat);
      iPos.set(keyFrames[upperKnot].position);
      iScale.set(keyFrames[upperKnot].scale);

      // if we are somewhere in between the curve
    } else {

      // Get a reference to the current spline segment i.e. the
      // one bounded by lowerKnot and upperKnot
      currentSegment = cubicSplineCurve.getSegment(currentSegmentIndex);

      // interpolate quaternions
      currentSegment.getInterpolatedQuaternion(currentU, iQuat);

      // interpolate position
      currentSegment.getInterpolatedPositionVector(currentU, iPos);

      // interpolate position
      currentSegment.getInterpolatedScale(currentU, iScale);
    }

    // Alway normalize the quaternion
    iQuat.normalize();
    iQuat.toRotationMatrix(tMat);

    // Set the translation components.
    tMat.m03 = iPos.x;
    tMat.m13 = iPos.y;
    tMat.m23 = iPos.z;
    rotation.set(tMat);

    // construct a Transform3D from:  axis * rotation * axisInverse
    //	transform.multLocal(axis);
    transform.multLocal(rotation);
    transform.scale(new Vector3f(iScale));
    //	transform.multLocal(axisInverse);

  }
  protected void regenInfluenceOffsets(int index) {
    FloatBuffer verts, norms;
    Vector3f vertex = new Vector3f();
    Vector3f normal = new Vector3f();

    Geometry geom = getSkin(index);
    verts = geom.getVertexBuffer();
    if (verts == null) {
      logger.log(Level.FINE, "Skipping skin ''{0}'' because verts uninitialized", geom.getName());
      return;
    }
    norms = geom.getNormalBuffer();
    verts.clear();
    norms.clear();
    for (ArrayList<BoneInfluence> infs : cache[index]) {
      vertex.set(verts.get(), verts.get(), verts.get());
      normal.set(norms.get(), norms.get(), norms.get());

      if (infs == null) continue;

      if (bindMatrix != null) {
        bindMatrix.mult(vertex, vertex);
        bindMatrix.rotateVect(normal);
      }

      for (int x = infs.size() - 1; x >= 0; --x) {
        BoneInfluence infl = infs.get(x);
        if (infl.bone == null) continue;
        infl.vOffset = new Vector3f(vertex);
        infl.bone.bindMatrix.inverseTranslateVect(infl.vOffset);
        infl.bone.bindMatrix.inverseRotateVect(infl.vOffset);

        infl.nOffset = new Vector3f(normal);
        infl.bone.bindMatrix.inverseRotateVect(infl.nOffset);
      }
    }
  }
 public void setBindMatrix(Matrix4f mat) {
   bindMatrix = (mat != null && mat.isIdentity()) ? null : mat;
 }