/**
   * Calculates an intersection with the face of a block defined by 3 points.
   *
   * @param blockPos The position of the block to intersect with
   * @param v0 Point 1
   * @param v1 Point 2
   * @param v2 Point 3
   * @param origin Origin of the intersection ray
   * @param ray Direction of the intersection ray
   * @return Ray-face-intersection
   */
  private static RayBoxIntersection rayFaceIntersection(
      Vector3f blockPos, Vector3f v0, Vector3f v1, Vector3f v2, Vector3f origin, Vector3f ray) {

    // Calculate the plane to intersect with
    Vector3f a = Vector3f.sub(v1, v0, null);
    Vector3f b = Vector3f.sub(v2, v0, null);
    Vector3f norm = Vector3f.cross(a, b, null);

    float d = -(norm.x * v0.x + norm.y * v0.y + norm.z * v0.z);

    /** Calculate the distance on the ray, where the intersection occurs. */
    float t =
        -(norm.x * origin.x + norm.y * origin.y + norm.z * origin.z + d)
            / (Vector3f.dot(ray, norm));

    if (t < 0) {
      return null;
    }

    /** Calc. the point of intersection. */
    Vector3f intersectPoint = VectorPool.getVector(ray.x * t, ray.y * t, ray.z * t);
    Vector3f.add(intersectPoint, origin, intersectPoint);

    if (intersectPoint.x >= v0.x
        && intersectPoint.x <= v2.x
        && intersectPoint.y >= v0.y
        && intersectPoint.y <= v2.y
        && intersectPoint.z >= v0.z
        && intersectPoint.z <= v2.z) {
      return new RayBoxIntersection(blockPos, v0, v1, v2, d, t, origin, ray, intersectPoint);
    }

    return null;
  }
  private static Vector3f calculateSpherePoint(float x, float y) {
    Vector3f result = new Vector3f(x, y, 0);

    float sqrZ = 1 - Vector3f.dot(result, result);

    if (sqrZ > 0) result.z = (float) Math.sqrt(sqrZ);
    else result.normalise();

    return result;
  }
  private void billboardRotation(Camera camera) {
    Matrix4f matrix =
        Maths.createTransformationMatrix(
            new Vector3f(
                camera.getPosition().x,
                camera.getPosition().y + DayNightCycle.getSunY(),
                camera.getPosition().z + DayNightCycle.getSunZ()),
            0,
            0,
            0,
            DayNightCycle.getSunScale());

    Vector3f objToCamProj, objToCam;
    float angleCosine;

    objToCamProj = new Vector3f(0, 0, DayNightCycle.getSunZ());
    /*lookAt = new Vector3f(0,0,1);

    try{
    	objToCamProj.normalise();
    	lookAt.normalise();
    	angleCosine = Vector3f.dot(lookAt, objToCamProj);
    	if((angleCosine < 1f) && (angleCosine > -1f)){
    		if(objToCamProj.x > 0)
    			matrix.rotate((float)(Math.acos(angleCosine)), new Vector3f(0,1,0));
    		else
    			matrix.rotate((float)(Math.acos(angleCosine)), new Vector3f(0,-1,0));
    	}
    }catch(Exception e){

    }*/

    objToCam = new Vector3f(0, -DayNightCycle.getSunY(), -DayNightCycle.getSunZ());

    try {
      objToCamProj.normalise();
      objToCam.normalise();

      angleCosine = Vector3f.dot(objToCamProj, objToCam);
      if ((angleCosine < 1) && (angleCosine > -1)) {
        if (objToCam.y < 0) matrix.rotate((float) (Math.acos(angleCosine)), new Vector3f(1, 0, 0));
        else matrix.rotate((float) (Math.acos(angleCosine)), new Vector3f(-1, 0, 0));
      }
    } catch (Exception e) {

    }

    shader.loadTransformationMatrix(matrix);
  }
  private Matrix4f getTransform(float mouseX, float mouseY) {
    Preconditions.checkNotNull(dragStart, "Draging not started");
    Vector3f current = calculateSpherePoint(mouseX, mouseY);

    float dot = Vector3f.dot(dragStart, current);
    if (Math.abs(dot - 1) < 0.0001) return lastTransform;

    Vector3f axis = Vector3f.cross(dragStart, current, null);

    try {
      axis.normalise();
    } catch (IllegalStateException e) { // Zero length vector
      return lastTransform;
    }

    float angle = 2 * (float) (Math.acos(dot));

    Matrix4f rotation = new Matrix4f();
    rotation.rotate(angle, axis);
    return Matrix4f.mul(rotation, lastTransform, null);
  }