PageRenderTime 80ms CodeModel.GetById 18ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 1ms

/src/org/mt4j/util/TriangleNormalGenerator.java

http://mt4j.googlecode.com/
Java | 1776 lines | 793 code | 310 blank | 673 comment | 200 complexity | a9266dd4431d01cecb8493c4d9824e1c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/***********************************************************************
   2 * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
   3 *  
   4 *   This program is free software: you can redistribute it and/or modify
   5 *   it under the terms of the GNU General Public License as published by
   6 *   the Free Software Foundation, either version 3 of the License, or
   7 *   (at your option) any later version.
   8 *
   9 *   This program is distributed in the hope that it will be useful,
  10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 *   GNU General Public License for more details.
  13 *
  14 *   You should have received a copy of the GNU General Public License
  15 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16 *
  17 ***********************************************************************/
  18package org.mt4j.util;
  19
  20import java.util.ArrayList;
  21
  22import org.mt4j.components.visibleComponents.shapes.GeometryInfo;
  23import org.mt4j.util.logging.ILogger;
  24import org.mt4j.util.logging.MTLoggerFactory;
  25import org.mt4j.util.math.ToolsGeometry;
  26import org.mt4j.util.math.ToolsMath;
  27import org.mt4j.util.math.Vector3D;
  28import org.mt4j.util.math.Vertex;
  29
  30import processing.core.PApplet;
  31
  32/**
  33 * This class can be used to generate normals for indexed triangles geometry.
  34 * <br><li>It duplicates a vertex that has more than 1 texture coordinate.
  35 * So texture with indexed geometry can still be used.
  36 * <br><li>It also duplicates equal vertices that get assigned different normals in the calculation process according
  37 * to the face they belong to.
  38 * <p>
  39 * 
  40 * @author C.Ruff
  41 */
  42public class TriangleNormalGenerator {
  43	
  44	/** The Constant logger. */
  45	private static final ILogger logger = MTLoggerFactory.getLogger(TriangleNormalGenerator.class.getName());
  46	static{
  47		logger.setLevel(ILogger.ERROR);
  48	}
  49	
  50	/** The null vect. */
  51	private Vertex nullVect;
  52	
  53	/** Use these for console debug info. */
  54//	private boolean debug;
  55
  56	/** The use normals equal to face. */
  57	private boolean useNormalsEqualToFace;
  58
  59	/** The use equal neighbor normals again. */
  60	private boolean useEqualNeighborNormalsAgain;
  61	
  62 
  63	/**
  64	 * Constructor.
  65	 */
  66	public TriangleNormalGenerator(){
  67		nullVect = new Vertex(0,0,0, -1, -1);
  68		useNormalsEqualToFace 			= true;
  69		useEqualNeighborNormalsAgain 	= true;
  70	}
  71	
  72	
  73	/**
  74	 * Generates smooth normals for a triangle geometry array.
  75	 * 
  76	 * @param pa the pa
  77	 * @param geometryInfo the geometry info
  78	 * 
  79	 * @return the geometry info
  80	 * 
  81	 * the geometry array with normals
  82	 */
  83	public GeometryInfo generateTriangleNormals(PApplet pa, GeometryInfo geometryInfo){
  84		return this.generateTriangleNormals(pa, geometryInfo, 180);
  85	}
  86	
  87	
  88	/**
  89	 * Generates normals for the provided geometry info according to the crease angle.
  90	 * <br>A crease angle of 180 will result in a all smoothed model, smoothing each vertex normal
  91	 * across all its neighbor faces' face normals.
  92	 * <br>A crease angle of zero (0) will result in a flat shaded geometry. Only face normals will
  93	 * be used then.
  94	 * <br>A crease angle of 89 will create hard edges at 90 degree angle faces and smooth faces with
  95	 * less then 90 degree normals. This would be ideal to generate normals for a cube.
  96	 * <br>The best crease angle for a model has to be found by testing different angles.
  97	 * 
  98	 * <br><strong>Note:</strong>The geometry has to represent a TRIANGLES array!
  99	 * <br><strong>Note:</strong>The stroke color information gets lost during the process and is reset
 100	 * to the default color. Set it again if needed with <code>setStrokeColorAll</code>.
 101	 * 
 102	 * @param pa the pa
 103	 * @param geometryInfo the geometry info
 104	 * @param creaseAngle the crease angle
 105	 * 
 106	 * @return the geometry info
 107	 * 
 108	 * the geometry array with normals
 109	 */
 110	public GeometryInfo generateTriangleNormals(PApplet pa, GeometryInfo geometryInfo, float creaseAngle ){
 111		Vertex[] vertices = geometryInfo.getVertices();
 112		
 113		//Gen texcoord array
 114		float[][] texCoords = new float[vertices.length][2];
 115		for (int i = 0; i < vertices.length; i++) {
 116			Vertex v = vertices[i];
 117			texCoords[i][0] = v.getTexCoordU();
 118			texCoords[i][1] = v.getTexCoordV();
 119		}
 120		
 121		//Gen or get indices array
 122		int[] indices = null;
 123		if (!geometryInfo.isIndexed()){
 124			indices = new int[vertices.length];
 125			for (int i = 0; i < vertices.length; i++) {
 126				indices[i] = i;
 127			}
 128		}else{
 129			indices = geometryInfo.getIndices();
 130		}
 131		
 132		//Gen texcoord array as same as indices array
 133		int[] texIndices = new int[indices.length];
 134        System.arraycopy(indices, 0, texIndices, 0, indices.length);
 135        //		for (int i = 0; i < indices.length; i++) {
 136		//	texIndices[i] = indices[i];
 137		//}
 138
 139		//Generate normals
 140		GeometryInfo geom = null;
 141		if (creaseAngle == 180){
 142			geom = this.generateSmoothNormals(pa, vertices, indices, texCoords, texIndices, creaseAngle, false, false);
 143		}else{
 144			geom = this.generateCreaseAngleNormals(pa, vertices, indices, texCoords, texIndices, creaseAngle, false, false);
 145		}
 146		
 147		//Reset indices if they werent set before,too
 148		//Reconstruct the passed in geometryinfo
 149		if (!geometryInfo.isIndexed()){
 150			geometryInfo.reconstruct(geom.getVertices(), geom.getNormals(), null, true, false, null);
 151		}else{
 152			geometryInfo.reconstruct(geom.getVertices(), geom.getNormals(), geom.getIndices(), true, false, null);
 153		}
 154		geom = null;
 155		return geometryInfo;
 156	}
 157
 158	
 159	
 160	
 161	/**
 162	 * Generates triangle normals, smoothed acroos all neighbor faces.
 163	 * <br>Also dissolves multiple texturecoordinates belonging to the same vertex by
 164	 * duplicating them.
 165	 * 
 166	 * @param pa the pa
 167	 * @param originalVertices the original vertices
 168	 * @param originalIndices the original indices
 169	 * @param originalTexCoords the original tex coords
 170	 * @param originalTexIndices the original tex indices
 171	 * @param creaseAngle the crease angle
 172	 * @param flipTextureY the flip texture y
 173	 * @param flipTextureX the flip texture x
 174	 * 
 175	 * @return the geometry info
 176	 */
 177	public GeometryInfo generateSmoothNormals(PApplet pa, Vertex[] originalVertices, int[] originalIndices, float[][] originalTexCoords, int[] originalTexIndices, float creaseAngle, boolean flipTextureY, boolean flipTextureX){
 178			int newDuplicatesWithDiffTexCoordsCreated 	= 0;
 179			int newDuplicatesWithDiffNormalCreated 		= 0;
 180			
 181			logger.debug("-> Loading all smoothed model.");
 182			
 183			ArrayList<VertexData> 	vertexDatas = new ArrayList<VertexData>(originalVertices.length);
 184			ArrayList<MyFace> 		faces 		= new ArrayList<MyFace>(Math.round(originalIndices.length/3));
 185			
 186			//Init and fill vertexdata list with as many as vertices
 187			for (int i = 0; i < originalVertices.length; i++) {
 188				//Vertex v = vertices[i];
 189				VertexData vd = new VertexData();
 190				vd.setArrayIndex(i);
 191				vertexDatas.add(vd);
 192			}
 193			
 194			
 195			int pp0 = 0;
 196			int pp1 = 0;
 197			int pp2 = 0;
 198			
 199			int tIndexPP0 = 0;
 200			int tIndexPP1 = 0;
 201			int tIndexPP2 = 0;
 202			//GO through indices array and create a face for every three indices (must be triangle array!) 
 203			for (int i = 0; i < originalIndices.length/3; i++) {
 204				//int currentIndex = indices[i];
 205				
 206				//Next 3 vertex indices as the new faces pointers
 207				pp0 = originalIndices[i*3];
 208				pp1 = originalIndices[i*3+1];
 209				pp2 = originalIndices[i*3+2];
 210				
 211				if (originalTexCoords.length > 0){
 212					//Next 3 texture texture indices //(vertex and texture indices indexed in the same order)
 213					tIndexPP0 = originalTexIndices[i*3];
 214					tIndexPP1 = originalTexIndices[i*3+1];
 215					tIndexPP2 = originalTexIndices[i*3+2];
 216				}
 217				
 218				
 219				MyFace myFace = new MyFace();
 220				myFace.p0 = pp0;
 221				myFace.p1 = pp1;
 222				myFace.p2 = pp2;
 223				
 224				int vertexPointer = pp0;
 225				int texturePointer = tIndexPP0;
 226				for (int j = 0; j < 3; j++) {
 227					if 	   (j == 0)	{
 228						vertexPointer 	= pp0;
 229						texturePointer  = tIndexPP0;
 230					}
 231					else if(j == 1){
 232						vertexPointer 	= pp1;
 233						texturePointer  = tIndexPP1;
 234					}
 235					else if(j == 2){
 236						vertexPointer 	= pp2;
 237						texturePointer  = tIndexPP2;
 238					}
 239					
 240					//Get the vertexdata at the index, the face points to
 241					VertexData myVertexData 	= vertexDatas.get(vertexPointer);
 242					
 243					Vertex newVertex = new Vertex(
 244							originalVertices[vertexPointer].x, 
 245							originalVertices[vertexPointer].y, 
 246							originalVertices[vertexPointer].z,
 247							originalVertices[vertexPointer].getR(),
 248							originalVertices[vertexPointer].getG(),
 249							originalVertices[vertexPointer].getB(),
 250							originalVertices[vertexPointer].getA()
 251					);
 252					
 253	
 254//					Create texcoords and add to vertex
 255					float[] tex = new float[2];
 256					if (originalTexCoords.length > 0){
 257						tex[0] = originalTexCoords[texturePointer][0];
 258						tex[1] = originalTexCoords[texturePointer][1];
 259						
 260						if (flipTextureY){
 261							tex[1] = 1.0f-tex[1];
 262						}
 263						
 264						if (flipTextureX){
 265							tex[0] = 1.0f-tex[0];
 266						}
 267						
 268						newVertex.setTexCoordU(tex[0]);
 269						newVertex.setTexCoordV(tex[1]);
 270					}
 271
 272					//Check if the vertex data at the pointer is empty thats the case before first time a vertex is added to it here
 273					if (myVertexData.getVertex() == null){
 274						myVertexData.setVertex(newVertex);
 275						myVertexData.addNeighborFace(myFace);
 276						logger.debug("vdP" + j + " vertex in vertexData not initialzied -> set it");
 277//						logger.debug("vdP0 is empty -> adding first vertex, texture tuple");
 278					}else{//Vertex data at index already contains one or more vertices 
 279						
 280						//Check if the vertex data at the index contains a vertex that is equal to the new vertex and its texture information 
 281						//-> if true, just add the vertex to that vertexdata and the face it also is in
 282						//-> if false, check if a duplicate vertexdata is registered in the vertexdata the face points to
 283						//		-> if true, add the vertex to the duplicate, change face index to the duplicates index
 284						//		-> if false, create new vertexdata at end of list, add the vertex and texcoords of the vertex, and register 
 285						//			it as a duplicate in the original vertexdata, change the face index to the new duplicates index
 286						if (myVertexData.equalsVertex(newVertex)){
 287							//Register das face mit dem vertex data
 288							myVertexData.addNeighborFace(myFace);
 289							logger.debug("vdP" + j + "already CONTAINS a vertex with same coords and texture information -> do nothing, just a the current face to its neighborlist");
 290						}else{
 291							
 292							//Check if already duplicates were created, maybe with the same vertex and texture information,
 293							//then we have to add the vertex to that vertexdata rather than creating a new one
 294							int duplicateIndex = myVertexData.getVertDuplicateSameVertDiffTextureCoordListIndex(newVertex);
 295							
 296							if (duplicateIndex != -1){ //Es gibt schon ein duplicate mit gleichen tex coords wie dieses hier, adde bei duplicateIndex
 297								//Change face pointer of p0 to the duplicates index
 298								if 	   (j == 0)	myFace.p0 = duplicateIndex;
 299								else if(j == 1) myFace.p1 = duplicateIndex;
 300								else if(j == 2)	myFace.p2 = duplicateIndex;
 301								
 302								//wenn wir orginal hinzuf?gen wird auch allen duplicates neighbor face zugef?gt.
 303								myVertexData.addNeighborFace(myFace);
 304								
 305								logger.debug("vdP" + j + "has different texture coordiantes but a already created duplicate has the same -> change this face pointer to the duplicate one");
 306							}else{//there was no duplicate created with the same texture coords yet -> create one!
 307								
 308								//Neuen Vertex machen, an original vertices list anh?ngen, neuen index in face auf diesen setzen, face adden
 309								VertexData newVertexData = new VertexData();
 310								
 311								//Add the vertex information to the newly created vertexdata
 312								newVertexData.setVertex(newVertex);
 313								
 314								//Get new index at end of vertex list
 315								int newIndexOfNewVertexData = vertexDatas.size();
 316								
 317								//Change the index of the face to the index the new Vdata is created at
 318								if 	   (j == 0)	myFace.p0 = newIndexOfNewVertexData;
 319								else if(j == 1) myFace.p1 = newIndexOfNewVertexData;
 320								else if(j == 2)	myFace.p2 = newIndexOfNewVertexData;
 321								
 322								//Tell the vertexdata the index it is in the overall data
 323								newVertexData.setArrayIndex(newIndexOfNewVertexData);
 324								
 325								//Add new vertex data at the end of the list of all vertexdatas
 326								vertexDatas.add(newVertexData);
 327								
 328								//Inform the original vertexdata, that a duplicate with diff tex coords was created and register it
 329								myVertexData.registerCreatedDuplicateDiffTexCoords(newVertexData);
 330								
 331								//Adde face zu orginal face -> damit wird auch duplicates und dem neuen hinzugef?gt,
 332								//wenn wir es vorher mit registerDuplicate am orginal registiert haben!
 333								myVertexData.addNeighborFace(myFace);
 334								
 335								//copy the face list the vertex is contained in of the original 
 336								//to the duplicate (for normal generation later, so they are still neighbors)! 
 337								newVertexData.addNeighborFaces(myVertexData.getFacesContainedIn());
 338								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);
 339								newDuplicatesWithDiffTexCoordsCreated++;
 340							}//end if duplicate exists
 341						}//end if vertexdata already contains Vnew
 342					}//end if vertexdata is empty
 343				}//end for p0,p1,p2
 344				
 345				//Calculate the face's normal vector
 346				myFace.calcFaceNormal(vertexDatas);
 347				
 348				myFace.index = faces.size(); 
 349				
 350				//Add face to facelist
 351				faces.add(myFace);
 352			}
 353			
 354			logger.debug("-> Processed duplicate vertex/texture points.");
 355			
 356			
 357			//Create arrays
 358			Vertex[] newVertices 	= new Vertex[vertexDatas.size()];
 359			Vector3D[] normals  	= new Vector3D[vertexDatas.size()];
 360			int[] newIndices		= new int[faces.size()*3];
 361			
 362			
 363			/*
 364			 * Go through the final faces list and fill vertex/newIndices/normal arrays
 365			 */
 366			for (int j = 0; j < faces.size(); j++) {
 367				MyFace myFace = faces.get(j);
 368				//Get vertex pointers of face to newVertices in newVertices list
 369				int indexP0 = myFace.p0;
 370				int indexP1 = myFace.p1;
 371				int indexP2 = myFace.p2;
 372				
 373				//Use pointers as newIndices and fill newIndices array
 374				newIndices[j*3]		= indexP0;
 375				newIndices[j*3+1]	= indexP1;
 376				newIndices[j*3+2]	= indexP2;
 377				
 378				//Get the vertexdatas out of the list with the pointers
 379				VertexData vdP0 = vertexDatas.get(indexP0);
 380				VertexData vdP1 = vertexDatas.get(indexP1);
 381				VertexData vdP2 = vertexDatas.get(indexP2);
 382				
 383				//Get the vertex out of the vdata
 384				Vertex v0 = vdP0.getVertex();
 385				Vertex v1 = vdP1.getVertex();
 386				Vertex v2 = vdP2.getVertex();
 387				
 388				//Put newVertices from vertexdata list in vertex array for the geometry array
 389				newVertices[indexP0] = v0;
 390				newVertices[indexP1] = v1;
 391				newVertices[indexP2] = v2;
 392				
 393				//Get the faces normal
 394//				Vector3D faceNormal = Tools3D.getNormal(v0, v1, v2, true); //myFace.normal;//
 395//				Vector3D faceNormal = myFace.normal.getCopy();
 396//				faceNormal.normalizeLocal();
 397				
 398				Vector3D faceNormal = myFace.normalNormalized;
 399				
 400				Vector3D normalP0;
 401				if (vdP0.getNeighborFaces().size() > 1){
 402//					logger.debug("Calcing v normal of face: " + myFace.index + " P0");
 403					normalP0 = vdP0.calcVertexNormalAllNeighbors();
 404				}else{
 405					normalP0 = faceNormal;
 406				}
 407				
 408				Vector3D normalP1;
 409				if (vdP1.getNeighborFaces().size() > 1){
 410//					logger.debug("Calcing v normal of face: " + myFace.index + " P1");
 411					normalP1 = vdP1.calcVertexNormalAllNeighbors();
 412				}else{
 413					normalP1 = faceNormal;
 414				}
 415				
 416				Vector3D normalP2;
 417				if (vdP2.getNeighborFaces().size() > 1){
 418//					logger.debug("Calcing v normal of face: " + myFace.index + " P2");
 419					normalP2 = vdP2.calcVertexNormalAllNeighbors();
 420				}else{
 421					normalP2 = faceNormal;
 422				}
 423				
 424				normals[indexP0] = normalP0;
 425				normals[indexP1] = normalP1;
 426				normals[indexP2] = normalP2;
 427				
 428				////Normalen debug linien sehen mit normals invertiert richtig
 429				//aus, aber model wird falsch geshaded!
 430				/*
 431				normals[indexP0].scale(-1);
 432				normals[indexP1].scale(-1);
 433				normals[indexP2].scale(-1);
 434				*/
 435			} 
 436			
 437			//Leider n?tig? da manche models newVertices enthalten, die in den faces garnicht referenziert werden, quasi tote verts
 438			for (int j = 0; j < newVertices.length; j++) {
 439				if (newVertices[j] == null){
 440					newVertices[j] = nullVect;
 441				}
 442				//Normals array should be same length as verts, check for nulls here
 443				if (normals[j] == null){
 444					normals[j] = nullVect;
 445				}
 446				//System.out.print(normals[j] + " - ");
 447			}
 448			
 449			logger.debug("----------------------------------------------------------------------------------");
 450			logger.debug("New duplicates of same vertices with different texture coordinates created: " + newDuplicatesWithDiffTexCoordsCreated);
 451			logger.debug("New duplicates of same vertices with different normal created: " + newDuplicatesWithDiffNormalCreated);
 452			logger.debug("Original number of vertices: " + originalVertices.length);
 453			logger.debug("Final number of vertices: " + vertexDatas.size());
 454			logger.debug("Original number of faces: " + originalIndices.length/3);
 455			logger.debug("Final number of faces: " + faces.size());
 456			logger.debug("Original number of indices: " + originalIndices.length);
 457			logger.debug("Final number of indices: " + newIndices.length);
 458			logger.debug("Final number of normals: " + normals.length);
 459			logger.debug("----------------------------------------------------------------------------------");
 460			
 461			if (newVertices.length > 2 && faces.size() > 0){
 462				// Create a geometryInfo with all vertices of the mesh
 463				GeometryInfo geometryInfo = new GeometryInfo(pa, newVertices, newIndices);
 464	
 465				//Set the normals for the geometry
 466				geometryInfo.setNormals(normals, true, false);
 467	
 468				//Clean up a bit
 469				vertexDatas = null;
 470				faces		= null;
 471				
 472				return geometryInfo;
 473			}
 474			return null;
 475		}
 476
 477
 478
 479	
 480	
 481	/**
 482	 * Generates normals for the provided geometry data according to the crease angle.
 483	 * <br>A crease angle of 180 will result in a all smoothed model, smoothing each vertex normal
 484	 * across all its neighbor faces' face normals.
 485	 * <br>A crease angle of zero (0) will result in a flat shaded geometry. Only face normals will
 486	 * be used then.
 487	 * <br>A crease angle of 89 will create hard edges at 90 degree angle faces and smooth faces with
 488	 * less then 90 degree normals. This would be ideal to generate normals for a cube.
 489	 * <br>The best crease angle for a model has to be found by testing.
 490	 * 
 491	 * @param pa the pa
 492	 * @param originalVertices the original vertices
 493	 * @param originalIndices the original indices
 494	 * @param originalTexCoords the original tex coords
 495	 * @param originalTexIndices the original tex indices
 496	 * @param creaseAngle the crease angle
 497	 * @param flipTextureY the flip texture y
 498	 * @param flipTextureX the flip texture x
 499	 * 
 500	 * @return the geometry info
 501	 * 
 502	 * indexed, geometry info with normals
 503	 */
 504	public GeometryInfo generateCreaseAngleNormals(PApplet pa, Vertex[] originalVertices, int[] originalIndices, float[][] originalTexCoords, int[] originalTexIndices, float creaseAngle, boolean flipTextureY, boolean flipTextureX){
 505			int newDuplicatesWithDiffTexCoordsCreated 	= 0;
 506			int newDuplicatesWithDiffNormalCreated 		= 0;
 507			
 508			boolean useNormailizedNormalsForAdding = true;
 509
 510			logger.debug("-> Loading  model with a crease angle: " + creaseAngle);
 511			
 512			float creaseAngleRad = (float)Math.toRadians(creaseAngle);
 513//			float creaseAngleRad = 
 514			float creaseCosinus = (float)Math.cos(creaseAngle); 
 515			
 516			nullVect 	= new Vertex(0,0,0, -1, -1);
 517			ArrayList<VertexData> 	vertexDatas = new ArrayList<VertexData>();
 518			ArrayList<MyFace> 		faces 		= new ArrayList<MyFace>();
 519			
 520			//Init and fill vertexdata list with as many as vertices
 521			for (int i = 0; i < originalVertices.length; i++) {
 522				//Vertex v = vertices[i];
 523				VertexData vd = new VertexData();
 524				vd.setArrayIndex(i);
 525				vertexDatas.add(vd);
 526			}
 527			
 528	/////////////////////////////////////
 529			
 530			//GO through indices array and create a face for every three indices (must be triangle array!) 
 531			int pp0 = 0;
 532			int pp1 = 0;
 533			int pp2 = 0;
 534			
 535			int tIndexPP0 = 0;
 536			int tIndexPP1 = 0;
 537			int tIndexPP2 = 0;
 538			
 539			for (int i = 0; i < originalIndices.length/3; i++) {
 540				//int currentIndex = indices[i];
 541				
 542				//Next 3 vertex indices as the new faces pointers for our face
 543				pp0 = originalIndices[i*3];
 544				pp1 = originalIndices[i*3+1];
 545				pp2 = originalIndices[i*3+2];
 546				
 547				if (originalTexCoords.length > 0){
 548					//Next 3 texture texture indices //(vertex and texture indices indexed in the same order)
 549					tIndexPP0 = originalTexIndices[i*3];
 550					tIndexPP1 = originalTexIndices[i*3+1];
 551					tIndexPP2 = originalTexIndices[i*3+2];
 552				}
 553				
 554				
 555				MyFace myFace = new MyFace();
 556				myFace.p0 = pp0;
 557				myFace.p1 = pp1;
 558				myFace.p2 = pp2;
 559				
 560				int vertexPointer = pp0;
 561				int texturePointer = tIndexPP0;
 562				for (int j = 0; j < 3; j++) {
 563					if 	   (j == 0)	{
 564						vertexPointer 	= pp0;
 565						texturePointer  = tIndexPP0;
 566					}
 567					else if(j == 1){
 568						vertexPointer 	= pp1;
 569						texturePointer  = tIndexPP1;
 570					}
 571					else if(j == 2){
 572						vertexPointer 	= pp2;
 573						texturePointer  = tIndexPP2;
 574					}
 575					
 576					//Get the vertexdata at the index, the face points to
 577					VertexData myVertexData 	= vertexDatas.get(vertexPointer);
 578					
 579					Vertex newVertex = new Vertex(
 580							originalVertices[vertexPointer].x, 
 581							originalVertices[vertexPointer].y, 
 582							originalVertices[vertexPointer].z,
 583							originalVertices[vertexPointer].getR(),
 584							originalVertices[vertexPointer].getG(),
 585							originalVertices[vertexPointer].getB(),
 586							originalVertices[vertexPointer].getA()
 587					);
 588	
 589					//Create texcoords and add to vertex
 590					float[] tex = new float[2];
 591					if (originalTexCoords.length > 0){
 592						tex[0] = originalTexCoords[texturePointer][0];
 593						tex[1] = originalTexCoords[texturePointer][1];
 594						
 595						if (flipTextureY){
 596							tex[1] = 1.0f-tex[1];
 597						}
 598						
 599						if (flipTextureX){
 600							tex[0] = 1.0f-tex[0];
 601						}
 602						
 603						newVertex.setTexCoordU(tex[0]);
 604						newVertex.setTexCoordV(tex[1]);
 605					}
 606
 607					//Check if the vertex data at the pointer is empty thats the case before first time a vertex is added to it here
 608					if (myVertexData.getVertex() == null){
 609						myVertexData.setVertex(newVertex);
 610						myVertexData.addNeighborFace(myFace);
 611						logger.debug("vdP" + j + " vertex in vertexData not initialized -> set it: " + newVertex);
 612					}else{//Vertex data at index already contains one or more vertices 
 613						
 614						//Check if the vertex data at the index contains a vertex that is equal to the new vertex and its texture information 
 615						//-> if true, just add the vertex to that vertexdata and the face it also is in
 616						//-> if false, check if a duplicate vertexdata is registered in the vertexdata the face points to
 617						//		-> if true, add the vertex to the duplicate, change face index to the duplicates index
 618						//		-> if false, create new vertexdata at end of list, add the vertex and texcoords of the vertex, and register 
 619						//			it as a duplicate in the original vertexdata, change the face index to the new duplicates index
 620						if (myVertexData.equalsVertex(newVertex)){
 621							//Register das face mit dem vertex data
 622							myVertexData.addNeighborFace(myFace);
 623							logger.debug("vdP" + j + "already CONTAINS a vertex with same coords and texture information -> do nothing, just add the current face to its neighborlist");
 624						}else{
 625							
 626							//Check if already duplicates were created, maybe with the same vertex and texture information,
 627							//then we have to add the vertex to that vertexdata rather than creating a new one
 628							int duplicateIndex = myVertexData.getVertDuplicateSameVertDiffTextureCoordListIndex(newVertex);
 629							
 630							if (duplicateIndex != -1){ //Es gibt schon ein duplicate mit gleichen tex coords wie dieses hier, adde bei duplicateIndex
 631								//Change face pointer of p0 to the duplicates index
 632								if 	   (j == 0)	myFace.p0 = duplicateIndex;
 633								else if(j == 1) myFace.p1 = duplicateIndex;
 634								else if(j == 2)	myFace.p2 = duplicateIndex;
 635								
 636								//wenn wir orginal hinzuf?gen wird auch allen duplicates neighbor face zugef?gt.
 637								myVertexData.addNeighborFace(myFace);
 638								
 639								logger.debug("vdP" + j + "has different texture coordiantes but a already created duplicate has the same -> change this face pointer to the duplicate one");
 640							}else{//there was no duplicate created with the same texture coords yet -> create one!
 641								
 642								//Neuen Vertex machen, an original vertices list anh?ngen, neuen index in face auf diesen setzen, face adden
 643								VertexData newVertexData = new VertexData();
 644								
 645								//Add the vertex information to the newly created vertexdata
 646								newVertexData.setVertex(newVertex);
 647								
 648								//Get new index at end of vertex list
 649								int newIndexOfNewVertexData = vertexDatas.size();
 650								
 651								//Change the index of the face to the index the new Vdata is created at
 652								if 	   (j == 0)	myFace.p0 = newIndexOfNewVertexData;
 653								else if(j == 1) myFace.p1 = newIndexOfNewVertexData;
 654								else if(j == 2)	myFace.p2 = newIndexOfNewVertexData;
 655								
 656								//Tell the vertexdata the index it is in the overall data
 657								newVertexData.setArrayIndex(newIndexOfNewVertexData);
 658								
 659								//Add new vertex data at the end of the list of all vertexdatas
 660								vertexDatas.add(newVertexData);
 661								
 662								//Inform the original vertexdata, that a duplicate with diff tex coords was created and register it
 663								myVertexData.registerCreatedDuplicateDiffTexCoords(newVertexData);
 664								
 665								//Adde face zu orginal face -> damit wird auch duplicates und dem neuen hinzugef?gt,
 666								//wenn wir es vorher mit registerDuplicate am orginal registiert haben!
 667								myVertexData.addNeighborFace(myFace);
 668								
 669								//copy the face list the vertex is contained in of the original 
 670								//to the duplicate (for normal generation later, so they are still neighbors)! 
 671								newVertexData.addNeighborFaces(myVertexData.getFacesContainedIn());
 672								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);
 673								newDuplicatesWithDiffTexCoordsCreated++;
 674							}//end if duplicate exists
 675						}//end if vertexdata already contains Vnew
 676					}//end if vertexdata is empty
 677				}//end for p0,p1,p2
 678				
 679				//Calculate the face's normal vector
 680				myFace.calcFaceNormal(vertexDatas);
 681				
 682				myFace.index = faces.size(); 
 683				
 684				//Add face to facelist
 685				faces.add(myFace);
 686			}
 687			
 688			logger.debug("-> Processed duplicate vertex/texture points.");
 689	/////////////////////////////////////////
 690			
 691			
 692	//////////////////////////////////////		
 693	
 694			if (creaseAngleRad != 0.0) {
 695				//Durch alle selbst kreierten faces gehen, und schauen ob ein vertex des faces mit einem seiner
 696				//nachbar faces einen "sharp edge" hat oder smooth ist.
 697				//wenn smooth -> als smooth neighbor des face pointers hinzuf?gen
 698                for (MyFace currentFace : faces) {
 699                    //Get vertex pointers of face to vertices in vertices list
 700                    int indexP0 = currentFace.p0;
 701                    int indexP1 = currentFace.p1;
 702                    int indexP2 = currentFace.p2;
 703
 704                    //Get the vertexdatas out of the list with the pointers
 705                    VertexData vdP0 = vertexDatas.get(indexP0);
 706                    VertexData vdP1 = vertexDatas.get(indexP1);
 707                    VertexData vdP2 = vertexDatas.get(indexP2);
 708
 709
 710                    int[] currentFaceVertIndices = currentFace.getVertexIndices();
 711                    //Go through all 3 vertexdata entries in the current face and check for its smooth neighbors
 712                    for (int faceVD = 0; faceVD < currentFaceVertIndices.length /*currentFace.getVertexIndices().length*/; faceVD++) {
 713
 714                        VertexData currentFaceVertexData = null;
 715                        if (faceVD == 0) {
 716                            currentFaceVertexData = vdP0; /*logger.debug("Face: " + j + " - P0");*/
 717                        } else if (faceVD == 1) {
 718                            currentFaceVertexData = vdP1; /*logger.debug("Face: " + j + " - P1");*/
 719                        } else if (faceVD == 2) {
 720                            currentFaceVertexData = vdP2; /*logger.debug("Face: " + j + " - P2");*/
 721                        }
 722
 723                        ArrayList<MyFace> facesVDIsIn = currentFaceVertexData.getFacesContainedIn();
 724
 725                        //Go through all neighbor faces that the vertex(data) is a part of
 726                        for (MyFace anotherFaceVDisIn : facesVDIsIn) {
 727                            //Check that we are not considering the same face as the currentFace
 728                            if (!anotherFaceVDisIn.equals(currentFace)) {
 729
 730                                boolean onSameSurface = isOnSameSurfaceRadians(currentFace, anotherFaceVDisIn, creaseAngleRad);
 731//								boolean onSameSurface = isOnSameSurfaceCosAngle(currentFace, anotherFaceVDisIn, creaseCosinus);
 732
 733                                //Check if the current face and the other face VD are connected
 734                                //by an angle < cos_angle degrees,
 735                                //if so, add the faces to the vds smooth neighbor list (for later normal generation)
 736                                //if NOT so, create new VertexData, as a copy of the current one at the end of
 737                                //the vertexdata list, adjust the face pointers of the current face to the new one
 738                                //(we need another vertex so we have two different normals for them if the two faces arent smoothly connected)
 739                                if (onSameSurface) {
 740                                    if (faceVD == 0) {
 741                                        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() + " )");
 742                                    } else if (faceVD == 1) {
 743                                        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() + " )");
 744                                    } else if (faceVD == 2) {
 745                                        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() + " )");
 746                                    }
 747
 748                                    if (faceVD == 0) {
 749                                        currentFace.addSmoothNeighborP0(anotherFaceVDisIn);
 750                                    } else if (faceVD == 1) {
 751                                        currentFace.addSmoothNeighborP1(anotherFaceVDisIn);
 752                                    } else if (faceVD == 2) {
 753                                        currentFace.addSmoothNeighborP2(anotherFaceVDisIn);
 754                                    }
 755                                }//if smooth
 756                            }//if not checking against this same face
 757                        }
 758                    }//for loop through all 3 vertexdatas of the current face
 759                }
 760	
 761			}//end if creaseAngle != 0.0
 762	///////////////////////////////////////////////////////////////////////////		
 763
 764			
 765			
 766	/////////////////	//moved to the next loop
 767//			//Vertex normalen berechnen
 768//			for (int j = 0; j < faces.size(); j++) {
 769//				MyFace currentFace = faces.get(j);
 770//				currentFace.calcVertexNormals(useNormailizedNormalsForAdding);
 771//			}
 772	//////////////////
 773			
 774			// /|\
 775			// combine?
 776			// \|/
 777			
 778	//////////////////////////////////////////////////////////////////////		
 779			
 780	
 781			//Die vertex normalen wurden pro face und pro pointer auf ein vertex in den faces berechnet
 782			//Jetzt f?gen wir den VertexDatas, die die vertices representieren diese vertex normalen hinzu.
 783			//Wenn in mehreren faces auf den gleichen vertex gezeigt wird, aber in dem face f?r diesen vertex eine
 784			//andere normale berechnet wurde (weil face mit anderen smooth ist) m?ssen wir evtl das Vertex(data) duplizieren
 785			//und diesem die andere normale hinzuf?gen
 786			for (int j = 0; j < faces.size(); j++) {
 787				MyFace currentFace = faces.get(j);
 788				
 789				//GENERATE THE FACES VERTEX NORMAL BASED ON ITS SMOOTH NEIGHBORS
 790				currentFace.calcVertexNormals(useNormailizedNormalsForAdding);
 791				
 792				int[] faceVertexPointer = currentFace.getVertexIndices();
 793				
 794				//Go trough all (3) vertexpointer p0..2 of the current face
 795				for (int i = 0; i < faceVertexPointer.length; i++) {
 796					int currentVertexPointer = faceVertexPointer[i];
 797					
 798					logger.debug("-> Processing face[" + j + "].P" + i + " Vertex: " + vertexDatas.get(currentVertexPointer).getVertex());
 799					
 800					//Hole vertexdata auf das das currentFace an dem aktuellen zeiger (p0,p1,p2) zeigt
 801					VertexData currentVertexDataP0OrP1OrP2 = vertexDatas.get(currentVertexPointer);
 802					
 803					//Get normal saved in the vertexdata at position Face.Px
 804					Vector3D currentFacesCurrentVDNormal = currentVertexDataP0OrP1OrP2.getUniqueVertexNormal();
 805					
 806					//Get vertex normal array calculated and saved in the face for each point Px
 807					Vector3D[] vertexNormalsCurrentFace = currentFace.getVertexNormals();
 808					
 809					//Check if the vertexnormal data at the pointer is null -> thats the case before first time a vertexnormal is set here
 810					if (currentFacesCurrentVDNormal == null){
 811						currentVertexDataP0OrP1OrP2.setUniqueVertexNormal(vertexNormalsCurrentFace[i]);
 812						logger.debug("Face " + j + ", vdP" + i + " (Vertex: " + vertexDatas.get(currentVertexPointer).getVertex() + ")" + " normal not yet set -> set it: " + vertexNormalsCurrentFace[i]);
 813					}else{//Vertexdata at index already contains a vertexnormal -> check if its the equal to this faces currentVD's
 814						
 815						if (currentFacesCurrentVDNormal.equalsVectorWithTolerance(vertexNormalsCurrentFace[i], ToolsMath.ZERO_TOLERANCE)){
 816							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]);
 817						}else{
 818							int duplicateIndexOfSameVertDiffNormal = currentVertexDataP0OrP1OrP2.getVertDuplicateSameVertDiffNormalListIndex(vertexNormalsCurrentFace[i]); 
 819							
 820							if (duplicateIndexOfSameVertDiffNormal != -1){ //Es gibt schon ein duplicate mit gleichen tex coords wie dieses hier, adde bei duplicateIndex
 821								//Change face pointer of p0 to the duplicates index
 822								if 	   (i == 0)	currentFace.p0 = duplicateIndexOfSameVertDiffNormal;
 823								else if(i == 1) currentFace.p1 = duplicateIndexOfSameVertDiffNormal;
 824								else if(i == 2)	currentFace.p2 = duplicateIndexOfSameVertDiffNormal;
 825								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]);
 826							}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
 827								
 828								//Neuen Vertex machen, an original vertices list anh?ngen, neuen index in face auf diesen setzen
 829								VertexData newVertexData = new VertexData();
 830								
 831								//Add the vertex information to the newly created vertexdata
 832								newVertexData.setVertex(currentVertexDataP0OrP1OrP2.getVertex());
 833								
 834								//Set the vertex normal for the new vertexdata  as the vertex normal of the current face' calced normal for that vertex
 835								newVertexData.setUniqueVertexNormal(vertexNormalsCurrentFace[i]);
 836								
 837								//Get new index at end of vertex list
 838								int newIndexOfNewVertexData = vertexDatas.size();
 839								
 840								//Change the index of the face to the index the new Vdata is created at
 841								if 	   (i == 0)	currentFace.p0 = newIndexOfNewVertexData;
 842								else if(i == 1) currentFace.p1 = newIndexOfNewVertexData;
 843								else if(i == 2)	currentFace.p2 = newIndexOfNewVertexData;
 844								
 845								//Tell the vertexdata the index it is in the overall data
 846								newVertexData.setArrayIndex(newIndexOfNewVertexData);
 847								
 848								//Add new vertex data at the end of the list of all vertexdatas
 849								vertexDatas.add(newVertexData);
 850								
 851								//Inform the original vertexdata, that a duplicate with diff tex coords was created and register it
 852								currentVertexDataP0OrP1OrP2.registerCreatedDuplicateDiffNormal(newVertexData);
 853								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]);
 854								newDuplicatesWithDiffNormalCreated++;
 855							}//end if duplicate exists
 856						}//end if vertexdata already contains Vnew
 857					}//end if vertexdata is empty
 858				}	
 859			}
 860	////////////////////////////////////		
 861			
 862			
 863			
 864			
 865	//////////////////////////////////////////		
 866			//Create arrays
 867			Vertex[] newVertices 	= new Vertex[vertexDatas.size()];
 868			Vector3D[] normals  	= new Vector3D[vertexDatas.size()];
 869			int[] newIndices		= new int[faces.size()*3];
 870			
 871			/*
 872			 * Go through the final faces list and fill vertex/newIndices/normal arrays
 873			 */
 874			for (int j = 0; j < faces.size(); j++) {
 875				MyFace myFace = faces.get(j);
 876				//Get vertex pointers of face to newVertices in newVertices list
 877				int indexP0 = myFace.p0;
 878				int indexP1 = myFace.p1;
 879				int indexP2 = myFace.p2;
 880				
 881				//Use pointers as newIndices and fill newIndices array
 882				newIndices[j*3]		= indexP0;
 883				newIndices[j*3+1]	= indexP1;
 884				newIndices[j*3+2]	= indexP2;
 885				
 886				//Get the vertexdatas out of the list with the pointers
 887				VertexData vdP0 = vertexDatas.get(indexP0);
 888				VertexData vdP1 = vertexDatas.get(indexP1);
 889				VertexData vdP2 = vertexDatas.get(indexP2);
 890				
 891				//Get the vertex out of the vdata
 892				Vertex v0 = vdP0.getVertex();
 893				Vertex v1 = vdP1.getVertex();
 894				Vertex v2 = vdP2.getVertex();
 895				
 896				//Put newVertices from vertexdata list in vertex array for the geometry array
 897				newVertices[indexP0] = v0;
 898				newVertices[indexP1] = v1;
 899				newVertices[indexP2] = v2;
 900				
 901				//Get the faces normal
 902				normals[indexP0] = vdP0.uniqueVertexNormal;
 903				normals[indexP1] = vdP1.uniqueVertexNormal;
 904				normals[indexP2] = vdP2.uniqueVertexNormal;
 905				
 906				////Normalen debug linien sehen mit normals invertiert richtig
 907				//aus, aber model wird falsch geshaded!
 908				/*
 909				normals[indexP0].scale(-1);
 910				normals[indexP1].scale(-1);
 911				normals[indexP2].scale(-1);
 912				*/
 913			} 
 914			
 915			//Leider n?tig? da manche models newVertices enthalten, die in den faces garnicht referenziert werden, quasi tote verts
 916			for (int j = 0; j < newVertices.length; j++) {
 917				if (newVertices[j] == null){
 918					newVertices[j] = nullVect;
 919				}
 920				//Normals array should be same length as verts, check for nulls here
 921				if (normals[j] == null){
 922					normals[j] = nullVect;
 923				}
 924	//			System.out.print(normals[j] + " - ");
 925			}
 926	//		logger.debug();
 927	///////////////////////////////////////////////////////		
 928			
 929			logger.debug("----------------------------------------------------------------------------------");
 930			logger.debug("New duplicates of vertices with same vertex but different texture coordinates created: " + newDuplicatesWithDiffTexCoordsCreated);
 931			logger.debug("New duplicates of vertices with same vertex but different normal created: " + newDuplicatesWithDiffNormalCreated);
 932			logger.debug("Original number of vertices: " + originalVertices.length);
 933			logger.debug("Final number of vertices: " + vertexDatas.size());
 934			logger.debug("Final number of indices: " + newIndices.length);
 935			logger.debug("Final number of faces: " + faces.size());
 936			logger.debug("Final number of normals: " + normals.length);
 937			logger.debug("----------------------------------------------------------------------------------");
 938			
 939			if (newVertices.length > 2 && faces.size() > 0){
 940				// Create a geometryInfo with all vertices of the mesh
 941				GeometryInfo geometryInfo = new GeometryInfo(pa, newVertices, newIndices);
 942	
 943				//Set the normals for the geometry
 944				geometryInfo.setNormals(normals, true, false);
 945	
 946				//Clean up a bit
 947				vertexDatas = null;
 948				faces		= null;
 949				
 950				return geometryInfo;
 951			}
 952			return null;
 953		}
 954
 955
 956	
 957	/**
 958	 * Sets the debug mode.
 959	 * 
 960	 * @param debug the debug
 961	 */
 962	public void setDebug(boolean debug) {
 963		if (debug)
 964			logger.setLevel(ILogger.DEBUG);
 965		else
 966			logger.setLevel(ILogger.ERROR);
 967	}
 968	
 969	/**
 970	 * This influences the normal generation with crease angles.
 971	 * If <code>useNormalsEqualToFace</code> is set to true, normals
 972	 * of neighbor faces, that have the same normal as the face and vertex were checking
 973	 * against will be used in the calculation.
 974	 * </br>If <code>useNormalsEqualToFace</code> is set to false, these normals equal to
 975	 * the test face normal will be discarded to avoid adding up redundant normals.
 976	 * </br>The default is FALSE.
 977	 * 
 978	 * @param useNormalsEqualToFace use other normals equal to face or
 979	 */
 980	public void setUseNormalsEqualToFace(boolean useNormalsEqualToFace) {
 981		this.useNormalsEqualToFace = useNormalsEqualToFace;
 982	}
 983
 984	/**
 985	 * This influences the normal generation with crease angles.
 986	 * <br<>If <code>useEqualNeighborNormalsAgain</code> is set to true, normals
 987	 * of neighbor faces, that have the same normal as a neighbor face previously used in
 988	 * the calculation for one same vertex normal will again be used and added in.
 989	 * <br>If <code>useEqualNeighborNormalsAgain</code> is set to false, these normals will
 990	 * not be added in the calculation again.
 991	 * <br>The default is FALSE.
 992	 * 
 993	 * @param useEqualNeighborNormalsAgain use equal neighbor normals again
 994	 */
 995	public void setUseEqualNeighborNormalsAgain(boolean useEqualNeighborNormalsAgain) {
 996		this.useEqualNeighborNormalsAgain = useEqualNeighborNormalsAgain;
 997	}
 998	
 999	
1000	/**
1001	 * Calculates ..
1002	 * 
1003	 * @param face1 the face1
1004	 * @param face2 the face2
1005	 * @param cosAngle the cos angle
1006	 * 
1007	 * @return true, if checks if is on same surface radians
1008	 */
1009		private boolean isOnSameSurfaceRadians(MyFace face1, MyFace face2, float cosAngle) { 
1010			
1011	//		float cosineBetweenNormals 	= face1.normal.dot(face2.normal);
1012	//		logger.debug(Math.acos(cosineBetweenNormals));
1013	//		boolean smooth 	= cosineBetweenNormals > cosAngle;
1014	//		//boolean smoothTriangles = (cosineBetweenNormals > cosAngle);
1015	//        //logger.debug("surface: compare dot=" +dot + " cos-angle=" + cos_angle + " return " + (dot > cos_angle));
1016	//		logger.debug(Vector3D.angleBetween(face1.normal, face2.normal));
1017	//		logger.debug();
1018	//		
1019	//        return smooth;
1020	        
1021			boolean debugSmoothChecking = false;
1022	        float angleBetweenNorms = Vector3D.angleBetween(face1.normal, face2.normal);
1023	        
1024	        if (debugSmoothChecking){
1025	        	 float angleBetweenNormsDegrees = (float)Math.toDegrees(angleBetweenNorms);
1026		        logger.debug("Angle between normals :" + angleBetweenNormsDegrees);
1027		        logger.debug("Crease angle: " + Math.toDegrees(cosAngle));
1028	        }
1029	        
1030	        boolean smooth = angleBetweenNorms < cosAngle; 
1031	        
1032	        if (debugSmoothChecking)
1033	        	logger.debug("-> Smooth: " + smooth);
1034	        
1035	        if (Float.isNaN(angleBetweenNorms)){
1036	        	smooth = true;
1037	        	if (debugSmoothChecking)
1038	        		logger.debug("NAN!");
1039	        }
1040	        
1041	        return smooth;
1042	//		float threshold = (float)Math.cos(creaseAngle);
1043	//		float cosine 	= face1.normal.dot(face2.normal);
1044	//		boolean smooth 	= cosine > threshold;
1045	//
1046	//		//boolean smoothTriangles = (cosine > threshold);
1047	//        //logger.debug("surface: compare dot=" +dot + " cos-angle=" + cos_angle + " return " + (dot > cos_angle));
1048	//        return smooth;
1049	//        return false;
1050	////		return true; 
1051	    }
1052
1053
1054
1055	/**
1056	 * Calculates ..
1057	 * 
1058	 * @param face1 the face1
1059	 * @param face2 the face2
1060	 * @param cosAngle the cos angle
1061	 * 
1062	 * @return true, if checks if is on same surface cos angle
1063	 */
1064	private boolean isOnSameSurfaceCosAngle(MyFace face1, MyFace face2, float cosAngle) { //FIXME really correct?
1065		float cosineBetweenNormals 	= face1.normal.dot(face2.normal);
1066		boolean smooth 	= cosineBetweenNormals > Math.abs(cosAngle);
1067		
1068		if (Float.isNaN(cosineBetweenNormals))
1069			smooth = true;
1070		
1071	    return smooth;
1072	}
1073
1074
1075
1076	/**
1077	 * Class representing a triangle face of a mesh.
1078	 * 
1079	 * @author C.Ruff
1080	 */
1081		private class MyFace{
1082			
1083			/** The p0. */
1084			int p0;
1085			
1086			/** The p1. */
1087			int p1;
1088			
1089			/** The p2. */
1090			int p2;
1091			
1092			/** The smooth neighbors p0. */
1093			private ArrayList<MyFace> smoothNeighborsP0;
1094			
1095			/** The smooth neighbors p1. */
1096			private ArrayList<MyFace> smoothNeighborsP1;
1097			
1098			/** The smooth neighbors p2. */
1099			private ArrayList<MyFace> smoothNeighborsP2;
1100			
1101			/** The normal. */
1102			Vector3D normal;
1103			
1104			/** The normal normalized. */
1105			Vector3D normalNormalized;
1106			
1107			/** The center. */
1108			private Vector3D center;
1109			
1110			/** The index. */
1111			int index;
1112			
1113			/** The vertex normal p0. */
1114			private Vector3D vertexNormalP0;
1115			
1116			/** The vertex normal p1. */
1117			private Vector3D vertexNormalP1;
1118			
1119			/** The vertex normal p2. */
1120			private Vector3D vertexNormalP2;
1121			
1122			/** The vertex normals. */
1123			private Vector3D[] vertexNormals;
1124			
1125			/**
1126			 * Instantiates a new my face.
1127			 */
1128			public MyFace(){
1129				p0 = -1;
1130				p1 = -1;
1131				p2 = -1;
1132				//normal = nullVect;
1133				
1134				smoothNeighborsP0 = new ArrayList<MyFace>();
1135				smoothNeighborsP1 = new ArrayList<MyFace>();
1136				smoothNeighborsP2 = new ArrayList<MyFace>();
1137			}
1138			
1139			/**
1140			 * Gets the vertex indices.
1141			 * 
1142			 * @return the vertex indices
1143			 * 
1144			 * the pointers (indices) into the vertex array, this face holds (length=3 here)
1145			 */
1146			public int[] getVertexIndices() {
1147				return new int[]{p0,p1,p2};
1148			}
1149			
1150			/**
1151			 * Registers the face as a smooth neighbor of this faces vertex at
1152			 * the index P0. This is only relevant if a crease angle is used.
1153			 * 
1154			 * @param neighborFace the neighbor face
1155			 */
1156			public void addSmoothNeighborP0(MyFace neighborFace){
1157				if (!smoothNeighborsP0.contains(neighborFace)){
1158					smoothNeighborsP0.add(neighborFace);
1159				}
1160			}
1161			
1162			/**
1163			 * Registers the face as a smooth neighbor of this faces vertex at
1164			 * the index P1. This is only relevant if a crease angle is used.
1165			 * 
1166			 * @param neighborFace the neighbor face
1167			 */
1168			public void addSmoothNeighborP1(MyFace neighborFace){
1169				if (!smoothNeighborsP1.contains(neighborFace)){
1170					smoothNeighborsP1.add(neighborFace);
1171				}
1172			}
1173			
1174			/**
1175			 * Registers the face as a smooth neighbor of this faces vertex at
1176			 * the index P2. This is only relevant if a crease angle is used.
1177			 * 
1178			 * @param neighborFace the neighbor face
1179			 */
1180			public void addSmoothNeighborP2(MyFace neighborFace){
1181				if (!smoothNeighborsP2.contains(neighborFace)){
1182					smoothNeighborsP2.add(neighborFace);
1183				}
1184			}
1185			
1186	
1187			/**
1188			 * Calculates this face's face normal.
1189			 * 
1190			 * @param vertexList the vertex list
1191			 */
1192			public void calcFaceNormal(ArrayList<VertexData> ve

Large files files are truncated, but you can click here to view the full file