private final void computeArray(
      final double[] vd, final int[] vertices, final double[] nd, final int[] normals) {
    if (2 * vertices.length + 6 >= (vertexData.length - vertexCount) / Polygon.VERTEX_LENGTH)
      increaseVertexCapacity(vertices.length / 3);

    int vc = vertexCount;
    for (int i = 0; i < vertices.length; i++) {
      int vi = vertices[i];
      VecMat.transform(matrix, vd[vi++], vd[vi++], vd[vi], vertexData, vc + Polygon.SX);
      vertexData[vc + Polygon.SW] = 1;
      int ni = normals[i];
      VecMat.transformNormal(
          inverseTransposeMatrix, nd[ni++], nd[ni++], nd[ni], vertexData, vc + Polygon.NX);
      vc += Polygon.VERTEX_LENGTH;
      if (vertexColors) {
        DoubleArray color = vertexColor.item(vi / 3).toDoubleArray();
        vertexData[vc + Polygon.R] = color.getValueAt(0);
        vertexData[vc + Polygon.G] = color.getValueAt(1);
        vertexData[vc + Polygon.B] = color.getValueAt(2);
        vertexData[vc + Polygon.A] =
            (vertexColorLength == 4 || (vertexColorLength == -1 && color.getLength() > 3))
                ? color.getValueAt(3)
                : 1.;
      }
    }
    compute(vertices.length);
  }
  public ToolEvent process(VirtualDeviceContext context) throws MissingSlotException {
    if (context.getEvent().getInputSlot() == cameraToWorld) return null;
    DoubleArray pointer = context.getTransformationMatrix(pointerNDC);
    if (pointer == null) throw new MissingSlotException(pointerNDC);
    if (oldX == Integer.MAX_VALUE) {
      oldX = pointer.getValueAt(3);
      oldY = pointer.getValueAt(7);
      return null;
    }
    double x = pointer.getValueAt(3);
    double y = pointer.getValueAt(7);
    double dist = x * x + y * y;
    double z = 2 > dist ? Math.sqrt(2 - dist) : 0;
    Rn.setToValue(mouseCoords, x, y, z);

    mouseCoords = Rn.normalize(mouseCoords, mouseCoords);
    double[] cross = Rn.crossProduct(null, mouseCoordsOld, mouseCoords);
    double angle = gain * Math.asin(Rn.euclideanNorm(cross));
    double[] cross4 = {cross[0], cross[1], cross[2], 0};
    cross = new Matrix(context.getTransformationMatrix(cameraToWorld)).multiplyVector(cross4);
    result.assignFrom(P3.makeRotationMatrix(null, cross, angle));
    Rn.setToValue(mouseCoordsOld, x, y, z);
    return new ToolEvent(this, context.getEvent().getTimeStamp(), out, da);
  }
  public final void processPseudoTube(DoubleArray from, DoubleArray to) {
    if (lineShader == null) return;
    shader = lineShader.getPolygonShader();
    double w = 1;
    if (from.size() == 4) w = from.getValueAt(3);
    VecMat.transform(
        matrix, from.getValueAt(0), from.getValueAt(1), from.getValueAt(2), w, point0, 0);

    VecMat.transformUnNormalized(matrix, 0, 0, lineWidth, normal0, 0);
    w = 1;
    if (to.size() == 4) w = to.getValueAt(3);
    VecMat.transform(matrix, to.getValueAt(0), to.getValueAt(1), to.getValueAt(2), w, point1, 0);

    double[] mat = matrix;
    double[] tmat = inverseTransposeMatrix;
    matrix = identity;
    inverseTransposeMatrix = identity;

    direction[0] = point1[0] - point0[0];
    direction[1] = point1[1] - point0[1];
    direction[2] = point1[2] - point0[2];

    // TODO: decide: better but slower:
    zzNormal[0] = point1[0] + point0[0];
    zzNormal[1] = point1[1] + point0[1];
    zzNormal[2] = point1[2] + point0[2];
    VecMat.normalize(zzNormal);

    // TODO make only one call to norm...
    if (VecMat.norm(direction) == 0) {
      matrix = mat;
      inverseTransposeMatrix = tmat;

      return;
    }
    VecMat.normalize(direction);
    double length = VecMat.norm(normal0);
    VecMat.cross(direction, zzNormal, normal0);
    VecMat.normalize(normal0);
    VecMat.cross(normal0, direction, normal1);

    normal0[0] *= length;
    normal0[1] *= length;
    // allways zero:
    normal0[2] *= length;

    VecMat.normalize(normal1);

    if (VecMat.dot(normal1, zzNormal) < 0) {
      normal1[0] *= -1;
      normal1[1] *= -1;
      normal1[2] *= -1;
      System.out.println("flip");
    }

    line[0] = point0[0] - normal0[0];
    line[1] = point0[1] - normal0[1];
    line[2] = point0[2];

    line[3] = point0[0];
    line[4] = point0[1];
    line[5] = point0[2] + length;

    line[6] = point1[0];
    line[7] = point1[1];
    line[8] = point1[2] + length;

    line[9] = point1[0] - normal0[0];
    line[10] = point1[1] - normal0[1];
    line[11] = point1[2];

    normal2[0] = +cs / length * normal0[0] + ss * normal1[0];
    normal2[1] = +cs / length * normal0[1] + ss * normal1[1];
    normal2[2] = ss * normal1[2];

    normal2[3] = normal1[0];
    normal2[4] = normal1[1];
    normal2[5] = normal1[2];

    computeArrayNoTransform(line, lineIndices, normal2, nIndices);

    /////

    line[0] = point0[0];
    line[1] = point0[1];
    line[2] = point0[2] + length;

    line[3] = point0[0] + normal0[0];
    line[4] = point0[1] + normal0[1];
    line[5] = point0[2];

    line[6] = point1[0] + normal0[0];
    line[7] = point1[1] + normal0[1];
    line[8] = point1[2];

    line[9] = point1[0];
    line[10] = point1[1];
    line[11] = point1[2] + length;

    normal2[0] = normal1[0];
    normal2[1] = normal1[1];
    normal2[2] = normal1[2];

    normal2[3] = -cs / length * normal0[0] + ss * normal1[0];
    normal2[4] = -cs / length * normal0[1] + ss * normal1[1];
    normal2[5] = ss * normal1[2];

    computeArrayNoTransform(line, lineIndices, normal2, nIndices);

    /*
    test1[0] = point1[0];
    test1[1] = point1[1];
    test1[2] = point1[2];
    test2[0] = point1[0]+normal1[0];
    test2[1] = point1[1]+normal1[1];
    test2[2] = point1[2]+normal1[2];




    test3[0] = point0[0];
    test3[1] = point0[1];
    test3[2] = point0[2];
    test4[0] = point0[0]+normal1[0];
    test4[1] = point0[1]+normal1[1];
    test4[2] = point0[2]+normal1[2];

    processLine(tda1,tda2);
    processLine(tda3,tda4);

    */

    matrix = mat;
    inverseTransposeMatrix = tmat;
  }
  /* (non-Javadoc)
   * @see de.jreality.soft.LineProcessor#processLine(double[], int, int)
   */
  public final void processLine(DoubleArray from, DoubleArray to) {
    if (lineShader == null) return;
    shader = lineShader.getPolygonShader();
    double w = 1;
    if (from.size() == 4) w = from.getValueAt(3);
    VecMat.transform(
        matrix, from.getValueAt(0), from.getValueAt(1), from.getValueAt(2), 1, point0, 0);

    VecMat.transformUnNormalized(matrix, 0, 0, lineWidth, normal0, 0);

    w = 1;
    if (to.size() == 4) w = from.getValueAt(3);
    VecMat.transform(matrix, to.getValueAt(0), to.getValueAt(1), to.getValueAt(2), 1, point1, 0);
    // VecMat.transformUnNormalized(matrix,0,0,.2,normal0,0);

    double[] mat = matrix;
    double[] tmat = inverseTransposeMatrix;
    matrix = identity;
    inverseTransposeMatrix = identity;
    // VecMat.assignIdentity(matrix);

    direction[0] = point1[0] - point0[0];
    direction[1] = point1[1] - point0[1];
    direction[2] = point1[2] - point0[2];
    // TODO make only one call to norm...
    if (VecMat.norm(direction) == 0) {
      matrix = mat;
      inverseTransposeMatrix = tmat;
      return;
    }
    VecMat.normalize(direction);
    double length = VecMat.norm(normal0);
    VecMat.cross(direction, zNormal, normal0);
    VecMat.normalize(normal0);
    normal0[0] *= length;
    normal0[1] *= length;
    normal0[2] *= length;

    VecMat.cross(normal0, direction, normal1);
    VecMat.normalize(normal1);

    line[0] = point0[0] - normal0[0];
    line[1] = point0[1] - normal0[1];
    line[2] = point0[2] + length; // - normal0[2];	

    line[3] = point0[0] + normal0[0];
    line[4] = point0[1] + normal0[1];
    line[5] = point0[2] + length; // + normal0[2];

    line[6] = point1[0] + normal0[0];
    line[7] = point1[1] + normal0[1];
    line[8] = point1[2] + length; // + normal0[2];

    line[9] = point1[0] - normal0[0];
    line[10] = point1[1] - normal0[1];
    line[11] = point1[2] + length; // + normal0[2];

    computeArray(line, lineIndices, normal1, pointNormals);
    matrix = mat;
    inverseTransposeMatrix = tmat;
  }
 public final void processPoint(final DoubleArrayArray data, int index) {
   DoubleArray da = data.item(index).toDoubleArray();
   double w = 1;
   if (da.size() == 4) w = da.getValueAt(3);
   if (vertexColors) {
     DoubleArray color = vertexColor.item(index).toDoubleArray();
     for (int i = 0; i < 16; i++) {
       pointColors[i][0] = color.getValueAt(0);
       pointColors[i][1] = color.getValueAt(1);
       pointColors[i][2] = color.getValueAt(2);
       pointColors[i][3] =
           (vertexColorLength == 4 || (vertexColorLength == -1 && color.getLength() > 3))
               ? color.getValueAt(3)
               : 1.;
     }
     vertexColor = pointColorDataList;
   }
   processPoint(da.getValueAt(0), da.getValueAt(1), da.getValueAt(2), w);
 }
  private final void computeArray(
      final DoubleArrayArray vd,
      final IntArray vertices,
      final DoubleArrayArray nd,
      final IntArray normals,
      DataList texCoords) {
    if (2 * vertices.getLength() + 6 >= (vertexData.length - vertexCount) / Polygon.VERTEX_LENGTH)
      increaseVertexCapacity(vertices.getLength() / 3);

    int vc = vertexCount;
    if (vd.getLengthAt(0) == 3)
      for (int i = 0; i < vertices.getLength(); i++) {
        int vi = vertices.getValueAt(i);
        DoubleArray vertex = vd.item(vi).toDoubleArray();
        VecMat.transform(
            matrix,
            vertex.getValueAt(0),
            vertex.getValueAt(1),
            vertex.getValueAt(2),
            vertexData,
            vc + Polygon.SX);
        vertexData[vc + Polygon.SW] = 1;
        int ni = normals.getValueAt(i);
        DoubleArray normal = nd.item(ni).toDoubleArray();
        VecMat.transformNormal(
            inverseTransposeMatrix,
            normal.getValueAt(0),
            normal.getValueAt(1),
            normal.getValueAt(2),
            vertexData,
            vc + Polygon.NX);
        if (vertexColors) {
          DoubleArray color = vertexColor.item(vi).toDoubleArray();
          vertexData[vc + Polygon.R] = color.getValueAt(0);
          vertexData[vc + Polygon.G] = color.getValueAt(1);
          vertexData[vc + Polygon.B] = color.getValueAt(2);
          vertexData[vc + Polygon.A] =
              (vertexColorLength == 4 || (vertexColorLength == -1 && color.getLength() > 3))
                  ? color.getValueAt(3)
                  : 1.;
        }
        if (useTexCoords && texCoords != null) {
          DoubleArray tc = texCoords.item(vi).toDoubleArray();
          vertexData[vc + Polygon.U] = tc.getValueAt(0);
          vertexData[vc + Polygon.V] = tc.getValueAt(1);
        }
        vc += Polygon.VERTEX_LENGTH;
      }
    else // vertices are 4 tupel
    for (int i = 0; i < vertices.getLength(); i++) {
        int vi = vertices.getValueAt(i);
        DoubleArray vertex = vd.item(vi).toDoubleArray();
        VecMat.transform(
            matrix,
            vertex.getValueAt(0),
            vertex.getValueAt(1),
            vertex.getValueAt(2),
            vertex.getValueAt(3),
            vertexData,
            vc + Polygon.SX);
        if (vertexData[vc + Polygon.SW] != 0) {
          final double d = vertexData[vc + Polygon.SW];
          vertexData[vc + Polygon.SX] /= d;
          vertexData[vc + Polygon.SY] /= d;
          vertexData[vc + Polygon.SZ] /= d;
          vertexData[vc + Polygon.SW] = 1;
        }
        int ni = normals.getValueAt(i);
        DoubleArray normal = nd.item(ni).toDoubleArray();
        VecMat.transformNormal(
            inverseTransposeMatrix,
            normal.getValueAt(0),
            normal.getValueAt(1),
            normal.getValueAt(2),
            // normal.getValueAt(3),
            vertexData,
            vc + Polygon.NX);
        if (vertexColors) {
          DoubleArray color = vertexColor.item(vi).toDoubleArray();
          vertexData[vc + Polygon.R] = color.getValueAt(0);
          vertexData[vc + Polygon.G] = color.getValueAt(1);
          vertexData[vc + Polygon.B] = color.getValueAt(2);
          vertexData[vc + Polygon.A] =
              (vertexColorLength == 4 || (vertexColorLength == -1 && color.getLength() > 3))
                  ? color.getValueAt(3)
                  : 1.;
        }
        if (useTexCoords && texCoords != null) {
          DoubleArray tc = texCoords.item(vi).toDoubleArray();
          vertexData[vc + Polygon.U] = tc.getValueAt(0);
          vertexData[vc + Polygon.V] = tc.getValueAt(1);
        }
        vc += Polygon.VERTEX_LENGTH;
      }
    compute(vertices.getLength());
  }