/** @param p */
  private final boolean clipPolygon() {
    int polPos = polygonCount - 1;
    Polygon p1 = polygons[polPos];
    ClippingBox box = perspective.getFrustum();
    int x0out = 0;
    int x1out = 0;
    int y0out = 0;
    int y1out = 0;
    int z0out = 0;
    int z1out = 0;

    int n = p1.length;
    // TODO check maximal polygon vertex num here:...if applicable...

    // after clipping at the clipping plane vertices need not be in order anymore!
    // for (int v = p1.vertices[0], i = n;
    // i > 0;
    // i--, v += Polygon.VERTEX_LENGTH) {
    for (int v = p1.vertices[0], i = 0; i < n; i++) {
      v = p1.vertices[i];
      double vsw = vertexData[v + Polygon.SW];
      if (vertexData[v + Polygon.SX] < box.x0 * vsw) x0out++;
      if (vertexData[v + Polygon.SX] > box.x1 * vsw) x1out++;

      if (vertexData[v + Polygon.SY] < box.y0 * vsw) y0out++;
      if (vertexData[v + Polygon.SY] > box.y1 * vsw) y1out++;

      if (vertexData[v + Polygon.SZ] < box.z0 * vsw) z0out++;
      if (vertexData[v + Polygon.SZ] > box.z1 * vsw) z1out++;
    }
    if (x0out + x1out + y0out + y1out + z0out + z1out == 0) {
      // shader.shadePolygon(p1, vertexData, environment);
      return false; /*POLY_CLIP_IN*/
    }
    if (x0out == n || x1out == n || y0out == n || y1out == n || z0out == n || z1out == n) {
      // p1->n = 0;
      // System.out.println("OUT "+(n*Polygon.VERTEX_LENGTH));
      return true; /*POLY_CLIP_OUT*/
    }
    // shader.shadePolygon(p1, vertexData, environment);
    // now clip:
    // if (x0out) CLIP_AND_SWAP(sx, -1., box->x0, p, q, r);
    if (x0out != 0) clipToHalfspace(polPos, polygons, Polygon.SX, -1, -box.x0);
    if (x1out != 0) clipToHalfspace(polPos, polygons, Polygon.SX, 1, box.x1);

    if (y0out != 0) clipToHalfspace(polPos, polygons, Polygon.SY, -1, -box.y0);
    if (y1out != 0) clipToHalfspace(polPos, polygons, Polygon.SY, 1, box.y1);

    if (z0out != 0) clipToHalfspace(polPos, polygons, Polygon.SZ, -1, -box.z0);
    if (z1out != 0) clipToHalfspace(polPos, polygons, Polygon.SZ, 1, box.z1);
    if (p1.length == 0) return true;
    else return false;
  }
  private final void compute(int verticesLength) {

    //        boolean isTransparent = shader.getVertexShader().getTransparency() != 0.;

    if (polygonCount + 1 >= this.polygons.length) increasePolygonCapacity();

    Polygon p = polygons[polygonCount++];
    p.length = verticesLength;

    // We store the current shader for later shading
    p.setShader(shader);

    for (int i = 0; i < verticesLength; i++) {
      p.vertices[i] = vertexCount;
      vertexCount += Polygon.VERTEX_LENGTH;
    }

    // sky box shaders need the matrix...
    environment.setMatrix(matrix);
    // ****
    shader.shadePolygon(p, vertexData, environment);

    int numClip = environment.getNumClippingPlanes();
    if (numClip > 0) {
      ClippingPlaneSoft[] cp = environment.getClippingPlanes();
      // Intersector.dehomogenize(p,vertexData);
      for (int k = 0; k < numClip; k++) {
        double d = VecMat.dot(cp[k].getNormal(), cp[k].getPoint());
        // System.out.println("d "+d);
        int res = Intersector.clipToHalfspace(p, cp[k].getNormal(), -1, d, this);
        if (res == -1) { // clipped out
          p.setShader(null);
          vertexCount -= p.length * Polygon.VERTEX_LENGTH;
          polygonCount--;
          return;
        }
      }
    }
    for (int i = 0; i < p.length; i++) {
      perspective.perspective(vertexData, p.vertices[i]);
    }

    boolean clippedAway = clipPolygon();

    if (!clippedAway) {
      // if (p.length == 0)
      //    System.out.println("ZEROLENGTH!");
      // TODO: check wether we sort before computing this.
      // boolean isTransparent = (shader.getVertexShader().getTransparency() !=
      // 0.)||shader.hasTexture()||shader.interpolateAlpha();
      // shader might have changed after lighting:
      boolean isTransparent = p.getShader().needsSorting();
      ////            isTransparent = false;
      if (triangulate) {
        PolygonShader ps = p.getShader();
        if (polygonCount + 1 >= this.polygons.length) increasePolygonCapacity();
        polygonCount--;
        for (int i = 0, pl = p.length - 2; i < pl; i++) {
          Polygon pi = polygons[polygonCount++];
          pi.length = 3;
          pi.vertices[0] = p.vertices[0];
          pi.vertices[1] = p.vertices[i + 1];
          pi.vertices[2] = p.vertices[i + 2];
          pi.setShader(ps);
          if (queueOpaque || isTransparent) {
            if (sortOpaque || isTransparent) pi.computeCenterZ(vertexData);
            // pi.computeMaxZ(vertexData);
            // return;
          } else {
            renderer.renderPolygon(pi, vertexData, ps.isOutline());
            pi.setShader(null);
            // TODO:check wether this is save
            // vertexCount -= p.length * Polygon.VERTEX_LENGTH;
            polygonCount--;
          }
        }
        return;
      } else {

        if (queueOpaque || isTransparent) {
          if (sortOpaque || isTransparent) p.computeCenterZ(vertexData);
          // p.computeMaxZ(vertexData);
          return;
        } else {
          renderer.renderPolygon(p, vertexData, p.getShader().isOutline());
        }
      }
    }
    // if the polygon was clipped completely or if the polygon was opaque and therefore
    // rendered already, we can free its resources:
    p.setShader(null);
    vertexCount -= p.length * Polygon.VERTEX_LENGTH;
    polygonCount--;
  }