float creaseAngleRad = (float)Math.toRadians(creaseAngle);
// float creaseAngleRad =
float creaseCosinus = (float)Math.cos(creaseAngle);
nullVect = new Vertex(0,0,0, -1, -1);
ArrayList<VertexData> vertexDatas = new ArrayList<VertexData>();
ArrayList<MyFace> faces = new ArrayList<MyFace>();
//Init and fill vertexdata list with as many as vertices
for (int i = 0; i < originalVertices.length; i++) {
//Vertex v = vertices[i];
VertexData vd = new VertexData();
vd.setArrayIndex(i);
vertexDatas.add(vd);
}
/////////////////////////////////////
//GO through indices array and create a face for every three indices (must be triangle array!)
int pp0 = 0;
int pp1 = 0;
int pp2 = 0;
int tIndexPP0 = 0;
int tIndexPP1 = 0;
int tIndexPP2 = 0;
for (int i = 0; i < originalIndices.length/3; i++) {
//int currentIndex = indices[i];
//Next 3 vertex indices as the new faces pointers for our face
pp0 = originalIndices[i*3];
pp1 = originalIndices[i*3+1];
pp2 = originalIndices[i*3+2];
if (originalTexCoords.length > 0){
//Next 3 texture texture indices //(vertex and texture indices indexed in the same order)
tIndexPP0 = originalTexIndices[i*3];
tIndexPP1 = originalTexIndices[i*3+1];
tIndexPP2 = originalTexIndices[i*3+2];
}
MyFace myFace = new MyFace();
myFace.p0 = pp0;
myFace.p1 = pp1;
myFace.p2 = pp2;
int vertexPointer = pp0;
int texturePointer = tIndexPP0;
for (int j = 0; j < 3; j++) {
if (j == 0) {
vertexPointer = pp0;
texturePointer = tIndexPP0;
}
else if(j == 1){
vertexPointer = pp1;
texturePointer = tIndexPP1;
}
else if(j == 2){
vertexPointer = pp2;
texturePointer = tIndexPP2;
}
//Get the vertexdata at the index, the face points to
VertexData myVertexData = vertexDatas.get(vertexPointer);
Vertex newVertex = new Vertex(
originalVertices[vertexPointer].x,
originalVertices[vertexPointer].y,
originalVertices[vertexPointer].z,
originalVertices[vertexPointer].getR(),
originalVertices[vertexPointer].getG(),
originalVertices[vertexPointer].getB(),
originalVertices[vertexPointer].getA()
);
//Create texcoords and add to vertex
float[] tex = new float[2];
if (originalTexCoords.length > 0){
tex[0] = originalTexCoords[texturePointer][0];
tex[1] = originalTexCoords[texturePointer][1];
if (flipTextureY){
tex[1] = 1.0f-tex[1];
}
if (flipTextureX){
tex[0] = 1.0f-tex[0];
}
newVertex.setTexCoordU(tex[0]);
newVertex.setTexCoordV(tex[1]);
}
//Check if the vertex data at the pointer is empty thats the case before first time a vertex is added to it here
if (myVertexData.getVertex() == null){
myVertexData.setVertex(newVertex);
myVertexData.addNeighborFace(myFace);
logger.debug("vdP" + j + " vertex in vertexData not initialized -> set it: " + newVertex);
}else{//Vertex data at index already contains one or more vertices
//Check if the vertex data at the index contains a vertex that is equal to the new vertex and its texture information
//-> if true, just add the vertex to that vertexdata and the face it also is in
//-> if false, check if a duplicate vertexdata is registered in the vertexdata the face points to
// -> if true, add the vertex to the duplicate, change face index to the duplicates index
// -> if false, create new vertexdata at end of list, add the vertex and texcoords of the vertex, and register
// it as a duplicate in the original vertexdata, change the face index to the new duplicates index
if (myVertexData.equalsVertex(newVertex)){
//Register das face mit dem vertex data
myVertexData.addNeighborFace(myFace);
logger.debug("vdP" + j + "already CONTAINS a vertex with same coords and texture information -> do nothing, just add the current face to its neighborlist");
}else{
//Check if already duplicates were created, maybe with the same vertex and texture information,
//then we have to add the vertex to that vertexdata rather than creating a new one
int duplicateIndex = myVertexData.getVertDuplicateSameVertDiffTextureCoordListIndex(newVertex);
if (duplicateIndex != -1){ //Es gibt schon ein duplicate mit gleichen tex coords wie dieses hier, adde bei duplicateIndex
//Change face pointer of p0 to the duplicates index
if (j == 0) myFace.p0 = duplicateIndex;
else if(j == 1) myFace.p1 = duplicateIndex;
else if(j == 2) myFace.p2 = duplicateIndex;
//wenn wir orginal hinzuf�gen wird auch allen duplicates neighbor face zugef�gt.
myVertexData.addNeighborFace(myFace);
logger.debug("vdP" + j + "has different texture coordiantes but a already created duplicate has the same -> change this face pointer to the duplicate one");
}else{//there was no duplicate created with the same texture coords yet -> create one!
//Neuen Vertex machen, an original vertices list anh�ngen, neuen index in face auf diesen setzen, face adden
VertexData newVertexData = new VertexData();
//Add the vertex information to the newly created vertexdata
newVertexData.setVertex(newVertex);
//Get new index at end of vertex list
int newIndexOfNewVertexData = vertexDatas.size();
//Change the index of the face to the index the new Vdata is created at
if (j == 0) myFace.p0 = newIndexOfNewVertexData;
else if(j == 1) myFace.p1 = newIndexOfNewVertexData;
else if(j == 2) myFace.p2 = newIndexOfNewVertexData;
//Tell the vertexdata the index it is in the overall data
newVertexData.setArrayIndex(newIndexOfNewVertexData);
//Add new vertex data at the end of the list of all vertexdatas
vertexDatas.add(newVertexData);
//Inform the original vertexdata, that a duplicate with diff tex coords was created and register it
myVertexData.registerCreatedDuplicateDiffTexCoords(newVertexData);
//Adde face zu orginal face -> damit wird auch duplicates und dem neuen hinzugef�gt,
//wenn wir es vorher mit registerDuplicate am orginal registiert haben!
myVertexData.addNeighborFace(myFace);
//copy the face list the vertex is contained in of the original
//to the duplicate (for normal generation later, so they are still neighbors)!
newVertexData.addNeighborFaces(myVertexData.getFacesContainedIn());
logger.debug("vdP" + j + "isnt empty but DOESENT CONTAIN (also no duplicate contains) a vertex with same coords and texture information -> creating new V.D. at: " + newIndexOfNewVertexData);
newDuplicatesWithDiffTexCoordsCreated++;
}//end if duplicate exists
}//end if vertexdata already contains Vnew
}//end if vertexdata is empty
}//end for p0,p1,p2
//Calculate the face's normal vector
myFace.calcFaceNormal(vertexDatas);
myFace.index = faces.size();
//Add face to facelist
faces.add(myFace);
}
logger.debug("-> Processed duplicate vertex/texture points.");
/////////////////////////////////////////
//////////////////////////////////////
if (creaseAngleRad != 0.0) {
//Durch alle selbst kreierten faces gehen, und schauen ob ein vertex des faces mit einem seiner
//nachbar faces einen "sharp edge" hat oder smooth ist.
//wenn smooth -> als smooth neighbor des face pointers hinzuf�gen
for (int j = 0; j < faces.size(); j++) {
MyFace currentFace = faces.get(j);
//Get vertex pointers of face to vertices in vertices list
int indexP0 = currentFace.p0;
int indexP1 = currentFace.p1;
int indexP2 = currentFace.p2;
//Get the vertexdatas out of the list with the pointers
VertexData vdP0 = vertexDatas.get(indexP0);
VertexData vdP1 = vertexDatas.get(indexP1);
VertexData vdP2 = vertexDatas.get(indexP2);
int[] currentFaceVertIndices = currentFace.getVertexIndices();
//Go through all 3 vertexdata entries in the current face and check for its smooth neighbors
for (int faceVD = 0; faceVD < currentFaceVertIndices.length /*currentFace.getVertexIndices().length*/; faceVD++) {
VertexData currentFaceVertexData = null;
if (faceVD == 0) {currentFaceVertexData = vdP0; /*logger.debug("Face: " + j + " - P0");*/}
else if(faceVD == 1) {currentFaceVertexData = vdP1; /*logger.debug("Face: " + j + " - P1");*/}
else if(faceVD == 2) {currentFaceVertexData = vdP2; /*logger.debug("Face: " + j + " - P2");*/}
ArrayList<MyFace> facesVDIsIn = currentFaceVertexData.getFacesContainedIn();
//Go through all neighbor faces that the vertex(data) is a part of
for (int k = 0; k < facesVDIsIn.size(); k++) {
MyFace anotherFaceVDisIn = facesVDIsIn.get(k);
//Check that we are not considering the same face as the currentFace
if (!anotherFaceVDisIn.equals(currentFace)){
boolean onSameSurface = isOnSameSurfaceRadians(currentFace, anotherFaceVDisIn, creaseAngleRad);
// boolean onSameSurface = isOnSameSurfaceCosAngle(currentFace, anotherFaceVDisIn, creaseCosinus);
//Check if the current face and the other face VD are connected
//by an angle < cos_angle degrees,
//if so, add the faces to the vds smooth neighbor list (for later normal generation)
//if NOT so, create new VertexData, as a copy of the current one at the end of
//the vertexdata list, adjust the face pointers of the current face to the new one
//(we need another vertex so we have two different normals for them if the two faces arent smoothly connected)
if (onSameSurface){
if (faceVD == 0) {
logger.debug("Face: " + (currentFace.index) + " (P0:" + currentFace.p0 + " P1:" + currentFace.p1 + " P2:" + currentFace.p2 + ")" + " is smooth with face: " + (anotherFaceVDisIn.index) + " (P0:" + anotherFaceVDisIn.p0 + " P1:" + anotherFaceVDisIn.p1 + " P2:" + anotherFaceVDisIn.p2 + ") at currentFaces' pointer: " + currentFace.p0 + " (" + vdP0.getVertex()+ " )");
}
else if(faceVD == 1) {
logger.debug("Face: " + (currentFace.index) + " (P0:" + currentFace.p0 + " P1:" + currentFace.p1 + " P2:" + currentFace.p2 + ")" + " is smooth with face: " + (anotherFaceVDisIn.index) + " (P0:" + anotherFaceVDisIn.p0 + " P1:" + anotherFaceVDisIn.p1 + " P2:" + anotherFaceVDisIn.p2 + ") at currentFaces' pointer: " + currentFace.p1+ " (" + vdP1.getVertex()+ " )");
}
else if(faceVD == 2) {
logger.debug("Face: " + (currentFace.index) + " (P0:" + currentFace.p0 + " P1:" + currentFace.p1 + " P2:" + currentFace.p2 + ")" + " is smooth with face: " + (anotherFaceVDisIn.index) + " (P0:" + anotherFaceVDisIn.p0 + " P1:" + anotherFaceVDisIn.p1 + " P2:" + anotherFaceVDisIn.p2 + ") at currentFaces' pointer: " + currentFace.p2+ " (" + vdP2.getVertex()+ " )");
}
if (faceVD == 0) {
currentFace.addSmoothNeighborP0(anotherFaceVDisIn);
}
else if(faceVD == 1) {
currentFace.addSmoothNeighborP1(anotherFaceVDisIn);
}
else if(faceVD == 2) {
currentFace.addSmoothNeighborP2(anotherFaceVDisIn);
}
}//if smooth
}//if not checking against this same face
}//for loop through all faces the current vertex is in
}//for loop through all 3 vertexdatas of the current face
}//for loop through all previously created faces
}//end if creaseAngle != 0.0
///////////////////////////////////////////////////////////////////////////
///////////////// //moved to the next loop
// //Vertex normalen berechnen
// for (int j = 0; j < faces.size(); j++) {
// MyFace currentFace = faces.get(j);
// currentFace.calcVertexNormals(useNormailizedNormalsForAdding);
// }
//////////////////
// /|\
// combine?
// \|/
//////////////////////////////////////////////////////////////////////
//Die vertex normalen wurden pro face und pro pointer auf ein vertex in den faces berechnet
//Jetzt f�gen wir den VertexDatas, die die vertices representieren diese vertex normalen hinzu.
//Wenn in mehreren faces auf den gleichen vertex gezeigt wird, aber in dem face f�r diesen vertex eine
//andere normale berechnet wurde (weil face mit anderen smooth ist) m�ssen wir evtl das Vertex(data) duplizieren
//und diesem die andere normale hinzuf�gen
for (int j = 0; j < faces.size(); j++) {
MyFace currentFace = faces.get(j);
//GENERATE THE FACES VERTEX NORMAL BASED ON ITS SMOOTH NEIGHBORS
currentFace.calcVertexNormals(useNormailizedNormalsForAdding);
int[] faceVertexPointer = currentFace.getVertexIndices();
//Go trough all (3) vertexpointer p0..2 of the current face
for (int i = 0; i < faceVertexPointer.length; i++) {
int currentVertexPointer = faceVertexPointer[i];
logger.debug("-> Processing face[" + j + "].P" + i + " Vertex: " + vertexDatas.get(currentVertexPointer).getVertex());
//Hole vertexdata auf das das currentFace an dem aktuellen zeiger (p0,p1,p2) zeigt
VertexData currentVertexDataP0OrP1OrP2 = vertexDatas.get(currentVertexPointer);
//Get normal saved in the vertexdata at position Face.Px
Vector3D currentFacesCurrentVDNormal = currentVertexDataP0OrP1OrP2.getUniqueVertexNormal();
//Get vertex normal array calculated and saved in the face for each point Px
Vector3D[] vertexNormalsCurrentFace = currentFace.getVertexNormals();
//Check if the vertexnormal data at the pointer is null -> thats the case before first time a vertexnormal is set here
if (currentFacesCurrentVDNormal == null){
currentVertexDataP0OrP1OrP2.setUniqueVertexNormal(vertexNormalsCurrentFace[i]);
logger.debug("Face " + j + ", vdP" + i + " (Vertex: " + vertexDatas.get(currentVertexPointer).getVertex() + ")" + " normal not yet set -> set it: " + vertexNormalsCurrentFace[i]);
}else{//Vertexdata at index already contains a vertexnormal -> check if its the equal to this faces currentVD's
if (currentFacesCurrentVDNormal.equalsVectorWithTolerance(vertexNormalsCurrentFace[i], ToolsMath.ZERO_TOLERANCE)){
logger.debug("Face " + j + ", vdP" + i + " (Vertex: " + vertexDatas.get(currentVertexPointer).getVertex() + ")" + " already CONTAINS a normal with the same values as the normal of this faces point -> we can leave the index and normal at the same place: N:" + vertexNormalsCurrentFace[i]);
}else{
int duplicateIndexOfSameVertDiffNormal = currentVertexDataP0OrP1OrP2.getVertDuplicateSameVertDiffNormalListIndex(vertexNormalsCurrentFace[i]);
if (duplicateIndexOfSameVertDiffNormal != -1){ //Es gibt schon ein duplicate mit gleichen tex coords wie dieses hier, adde bei duplicateIndex
//Change face pointer of p0 to the duplicates index
if (i == 0) currentFace.p0 = duplicateIndexOfSameVertDiffNormal;
else if(i == 1) currentFace.p1 = duplicateIndexOfSameVertDiffNormal;
else if(i == 2) currentFace.p2 = duplicateIndexOfSameVertDiffNormal;
logger.debug("Face " + j + " vdP" + i + " (Vertex: " + vertexDatas.get(currentVertexPointer).getVertex() + ")" + " vertexnormal is conform with a duplicate of the original vertex -> point to that duplicate: N:" + vertexNormalsCurrentFace[i]);
}else{//duplicate index == -1 -> neither the orignal faces point has the same vertexnormal nor a duplicate with different normal has that normal -> create new VD with the different normal and same vertex
//Neuen Vertex machen, an original vertices list anh�ngen, neuen index in face auf diesen setzen
VertexData newVertexData = new VertexData();
//Add the vertex information to the newly created vertexdata
newVertexData.setVertex(currentVertexDataP0OrP1OrP2.getVertex());
//Set the vertex normal for the new vertexdata as the vertex normal of the current face' calced normal for that vertex
newVertexData.setUniqueVertexNormal(vertexNormalsCurrentFace[i]);
//Get new index at end of vertex list
int newIndexOfNewVertexData = vertexDatas.size();
//Change the index of the face to the index the new Vdata is created at
if (i == 0) currentFace.p0 = newIndexOfNewVertexData;
else if(i == 1) currentFace.p1 = newIndexOfNewVertexData;
else if(i == 2) currentFace.p2 = newIndexOfNewVertexData;
//Tell the vertexdata the index it is in the overall data
newVertexData.setArrayIndex(newIndexOfNewVertexData);
//Add new vertex data at the end of the list of all vertexdatas
vertexDatas.add(newVertexData);
//Inform the original vertexdata, that a duplicate with diff tex coords was created and register it
currentVertexDataP0OrP1OrP2.registerCreatedDuplicateDiffNormal(newVertexData);
logger.debug("Face " + j + ", vdP" + i + " (Vertex: " + vertexDatas.get(currentVertexPointer).getVertex() + ")" + " has a different vertexnormal and DOESENT CONTAIN a link to a duplicate vertex with same normal information -> creating new VD at: " + newIndexOfNewVertexData + " N:" + vertexNormalsCurrentFace[i]);
newDuplicatesWithDiffNormalCreated++;
}//end if duplicate exists
}//end if vertexdata already contains Vnew
}//end if vertexdata is empty
}
}
////////////////////////////////////
//////////////////////////////////////////
//Create arrays
Vertex[] newVertices = new Vertex[vertexDatas.size()];
Vector3D[] normals = new Vector3D[vertexDatas.size()];
int[] newIndices = new int[faces.size()*3];
/*
* Go through the final faces list and fill vertex/newIndices/normal arrays
*/
for (int j = 0; j < faces.size(); j++) {
MyFace myFace = faces.get(j);
//Get vertex pointers of face to newVertices in newVertices list
int indexP0 = myFace.p0;
int indexP1 = myFace.p1;
int indexP2 = myFace.p2;
//Use pointers as newIndices and fill newIndices array
newIndices[j*3] = indexP0;
newIndices[j*3+1] = indexP1;
newIndices[j*3+2] = indexP2;
//Get the vertexdatas out of the list with the pointers
VertexData vdP0 = vertexDatas.get(indexP0);
VertexData vdP1 = vertexDatas.get(indexP1);
VertexData vdP2 = vertexDatas.get(indexP2);
//Get the vertex out of the vdata
Vertex v0 = vdP0.getVertex();
Vertex v1 = vdP1.getVertex();
Vertex v2 = vdP2.getVertex();
//Put newVertices from vertexdata list in vertex array for the geometry array
newVertices[indexP0] = v0;
newVertices[indexP1] = v1;
newVertices[indexP2] = v2;