// 2. Get most distant point of the face's point set
private static boolean step(int faceIndex) {
		Triangle t = faces.get(faceIndex);
		// 2. Get most distant point of the face's point set
		Vector3f furthestPoint = null;
		int furthestPointID = -1;
		Vector3f A = vertices.get(t.a);
		List<Vector3f> facepoints = listsOfFacePoints.get(faceIndex);
		float distance = 0;
		for (int i = 0; i < facepoints.size(); i++) {
			Vector3f P = facepoints.get(i);
			float dist = VecMath.dotproduct(VecMath.subtraction(P, A, tmpvec), t.normal);
			if (dist >= distance) {
				distance = dist;
				furthestPoint = P;
				furthestPointID = i;
			}
		}
		if (furthestPointID == -1 || vertices.contains(furthestPoint)) { // TODO: check
			return true;
		}
		facepoints.remove(furthestPointID);
		vertices.add(furthestPoint);
		furthestPointID = vertices.size() - 1;
		lastremovedTriangles.clear();
		lastremovedTriangles.add(faces.remove(faceIndex));
		listsOfFacePoints.remove(faceIndex);
		// 3. Find all faces that can be seen from this point
		HashSet<Integer> lightFaceVertices = new HashSet<Integer>(); // HAS TO BE REINITIALIZED... don't ask why.
		lightFaceVertices.add(t.a);
		lightFaceVertices.add(t.b);
		lightFaceVertices.add(t.c);
		List<Triangle> vertsA = new ArrayList<Triangle>();
		List<Triangle> vertsB = new ArrayList<Triangle>();
		List<Triangle> vertsC = new ArrayList<Triangle>();
		vertsA.add(t);
		vertsB.add(t);
		vertsC.add(t);
		lightFaceVerticesToTriangles.clear();
		lightFaceVerticesToTriangles.put(t.a, vertsA);
		lightFaceVerticesToTriangles.put(t.b, vertsB);
		lightFaceVerticesToTriangles.put(t.c, vertsC);
		for (int i = faces.size() - 1; i >= 0; i--) {
			Triangle tri = faces.get(i);
			Vector3f triA = vertices.get(tri.a);
			if (VecMath.dotproduct(tri.normal, VecMath.subtraction(furthestPoint, triA, tmpvec)) > 0) {
				lastremovedTriangles.add(faces.remove(i));
				lightFaceVertices.add(tri.a);
				lightFaceVertices.add(tri.b);
				lightFaceVertices.add(tri.c);
				if ((vertsA = lightFaceVerticesToTriangles.get(tri.a)) != null) {
					vertsA.add(tri);
				} else {
					vertsA = new ArrayList<Triangle>();
					vertsA.add(tri);
					lightFaceVerticesToTriangles.put(tri.a, vertsA);
				}
				if ((vertsB = lightFaceVerticesToTriangles.get(tri.b)) != null) {
					vertsB.add(tri);
				} else {
					vertsB = new ArrayList<Triangle>();
					vertsB.add(tri);
					lightFaceVerticesToTriangles.put(tri.b, vertsB);
				}
				if ((vertsC = lightFaceVerticesToTriangles.get(tri.c)) != null) {
					vertsC.add(tri);
				} else {
					vertsC = new ArrayList<Triangle>();
					vertsC.add(tri);
					lightFaceVerticesToTriangles.put(tri.c, vertsC);
				}
				facepoints.addAll(listsOfFacePoints.remove(i));
			}
		}
		// 4.0 Remove all vertices that are only connected to lightFaceVertices
		Iterator<Integer> iter = lightFaceVertices.iterator();
		toRemove.clear();
		for (int i = 0; i < lightFaceVertices.size(); i++) {
			int vert = iter.next(); // TODO: check
			if (lightFaceVerticesToTriangles.get(vert).size() == adjacentsMap.get(vert).size()) {
				toRemove.add(vert);
			}
		}
		for (Integer i : toRemove) {
			for (Integer adj : adjacentsMap.get(i)) {
				adjacentsMap.get(adj).remove(i);
				tmppair.set(i, adj);
				edgesToTriangles.remove(tmppair);
			}
			lightFaceVertices.remove((int) i);
			vertices.set((int) i, null);
			freeVertexPositions.add(i);
		}
		// 4.1 Get vertices on border between lit and unlit triangles
		HashSet<Integer> vertsOnEdge = new HashSet<Integer>(); // HAS TO BE REINITIALIZED
		for (Integer vert : lightFaceVertices) {
			vertsOnEdge.add(vert);
		}
		// 4.2 Get edges on border
		int currentVert = vertsOnEdge.iterator().next();
		edge.clear(); // TODO: make HashSet (no! has to be ordered list!)
		for (int i = 0; i < vertsOnEdge.size(); i++) {
			edge.add(currentVert);
			ArrayList<Integer> adjs = adjacentsMap.get(currentVert);
			List<Triangle> vertexLightTriangles = lightFaceVerticesToTriangles.get(currentVert);
			for (int j = 0; j < adjs.size(); j++) {
				Integer currAdj = adjs.get(j);
				if (vertsOnEdge.contains(currAdj) && !edge.contains(currAdj)) {
					int tricount = 0;
					for (int k = 0; k < vertexLightTriangles.size() && tricount < 2; k++) {
						Triangle kTri = vertexLightTriangles.get(k);
						if (kTri.a == currAdj || kTri.b == currAdj || kTri.c == currAdj) {
							tricount++;
						}
					}
					if (tricount == 1) {
						currentVert = currAdj;
						break;
					}
				}
			}
		}
		// 4.2.1 remove old adjacents (crossing triangle hole)
		int edgesize = edge.size();
		int edgesizeMinusOne = edgesize - 1;
		for (int i = 0; i < edgesize; i++) {
			currentVert = edge.get(i);
			removeAdj.clear();
			for (Integer adj : adjacentsMap.get(currentVert)) {
				if (edge.contains(adj)) {
					int adjIndexOnEdge = edge.indexOf(adj);
					if (Math.abs(i - adjIndexOnEdge) > 1 && !(i == 0 && adjIndexOnEdge == edgesizeMinusOne)
							&& !(i == edgesizeMinusOne && adjIndexOnEdge == 0)) {
						tmppair.set(currentVert, adj);
						Pair<Triangle, Triangle> edgeTriangles = edgesToTriangles.get(tmppair);
						// TODO: performance
						if (lastremovedTriangles.contains(edgeTriangles.getFirst())
								&& lastremovedTriangles.contains(edgeTriangles.getSecond())) {
							removeAdj.add(adj);
							edgesToTriangles.remove(edgeTriangles);
						}
					}
				}
			}
			for (Integer removAdjacent : removeAdj) { // TODO: make faster
				adjacentsMap.get(currentVert).remove(removAdjacent);
			}
		}
		// 4.3 Stitch holes using edge
		newLightFaces.clear();
		ArrayList<Integer> furthestPointNeighbours = new ArrayList<Integer>(edge.size());
		A = vertices.get(edge.get(0));
		Vector3f B = vertices.get(edge.get(1));
		Vector3f C = vertices.get(edge.get(2));
		for (int i = 3; i < edge.size() && !linearIndependent(A, B, C); i++) {
			C = vertices.get(edge.get(i));
		}
		Vector3f normal = VecMath.computeNormal(A, B, C);
		boolean correctOrientation = VecMath.dotproduct(normal, VecMath.subtraction(A, furthestPoint, tmpvec)) < 0;
		int vertIDb = edge.get(0);
		for (int i = 0; i < edge.size(); i++) {
			int vertIDa = vertIDb;
			if (i < edge.size() - 1) {
				vertIDb = edge.get(i + 1);
			} else {
				vertIDb = edge.get(0);
			}
			Vector3f vA = vertices.get(vertIDa);
			Vector3f vB = vertices.get(vertIDb);
			Vector3f norm = VecMath.computeNormal(vA, vB, furthestPoint);
			Triangle stitchTriangle;
			if (correctOrientation) {
				stitchTriangle = new Triangle(vertIDa, vertIDb, furthestPointID, norm);
			} else {
				norm.negate();
				stitchTriangle = new Triangle(vertIDa, furthestPointID, vertIDb, norm);
			}
			faces.add(0, stitchTriangle);
			newLightFaces.add(stitchTriangle);
			// Update adjacents map
			adjacentsMap.get(vertIDa).add(furthestPointID);
			tmppair.set(vertIDa, vertIDb);
			Pair<Triangle, Triangle> oldEdgeInfo = edgesToTriangles.get(tmppair);
			// find out which triangle got deleted
			if (lastremovedTriangles.contains(oldEdgeInfo.getFirst())) {
				oldEdgeInfo.setFirst(stitchTriangle);
			} else {
				oldEdgeInfo.setSecond(stitchTriangle);
			}
			tmppair.set(vertIDa, furthestPointID);
			oldEdgeInfo = edgesToTriangles.get(tmppair);
			if (oldEdgeInfo != null) {
				oldEdgeInfo.setSecond(stitchTriangle);
			} else {
				// TODO: just relevant for first iteration, move before loop
				edgesToTriangles.put(new Pair<Integer, Integer>(vertIDa, furthestPointID),
						new Pair<Triangle, Triangle>(null, stitchTriangle));
			}
			tmppair.set(vertIDb, furthestPointID);
			oldEdgeInfo = edgesToTriangles.get(tmppair);
			if (oldEdgeInfo != null) {
				// TODO: just relevant for last iteration
				oldEdgeInfo.setFirst(stitchTriangle);
			} else {
				edgesToTriangles.put(new Pair<Integer, Integer>(vertIDb, furthestPointID),
						new Pair<Triangle, Triangle>(stitchTriangle, null));
			}
			furthestPointNeighbours.add(vertIDa);
		}
		// 5. Assign all points of all light-faces to the new created faces
		adjacentsMap.put(furthestPointID, furthestPointNeighbours);
		for (Triangle tri : newLightFaces) {
			listsOfFacePoints.add(0, getLightPoints(tri, facepoints));
		}
		// 6. Push new created faces on the stack and start at (1))
		return false;
	}
private static boolean step(int faceIndex) {
Triangle t = faces.get(faceIndex);
// 2. Get most distant point of the face's point set
Vector3f furthestPoint = null;
int furthestPointID = -1;
private static boolean step(int faceIndex) {
Triangle t = faces.get(faceIndex);
// 2. Get most distant point of the face's point set
Vector3f furthestPoint = null;
int furthestPointID = -1;
Vector3f A = vertices.get(t.a);
List<Vector3f> facepoints = listsOfFacePoints.get(faceIndex);
float distance = 0;
for (int i = 0; i < facepoints.size(); i++) {
Vector3f P = facepoints.get(i);
float dist = VecMath.dotproduct(VecMath.subtraction(P, A, tmpvec), t.normal);
if (dist >= distance) {
distance = dist;
private static boolean step(int faceIndex) {
Triangle t = faces.get(faceIndex);
// 2. Get most distant point of the face's point set
Vector3f furthestPoint = null;
int furthestPointID = -1;
Vector3f A = vertices.get(t.a);
List<Vector3f> facepoints = listsOfFacePoints.get(faceIndex);
float distance = 0;
for (int i = 0; i < facepoints.size(); i++) {
Vector3f P = facepoints.get(i);
float dist = VecMath.dotproduct(VecMath.subtraction(P, A, tmpvec), t.normal);
if (dist >= distance) {
distance = dist;
furthestPoint = P;
furthestPointID = i;
}
}
if (furthestPointID == -1 || vertices.contains(furthestPoint)) { // TODO: check
return true;
}
facepoints.remove(furthestPointID);
vertices.add(furthestPoint);
furthestPointID = vertices.size() - 1;