PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms 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
Possible License(s): GPL-2.0, IPL-1.0, BSD-3-Clause, LGPL-2.1, Apache-2.0
  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. ***********************************************************************/
  18. package org.mt4j.util;
  19. import java.util.ArrayList;
  20. import org.mt4j.components.visibleComponents.shapes.GeometryInfo;
  21. import org.mt4j.util.logging.ILogger;
  22. import org.mt4j.util.logging.MTLoggerFactory;
  23. import org.mt4j.util.math.ToolsGeometry;
  24. import org.mt4j.util.math.ToolsMath;
  25. import org.mt4j.util.math.Vector3D;
  26. import org.mt4j.util.math.Vertex;
  27. import processing.core.PApplet;
  28. /**
  29. * This class can be used to generate normals for indexed triangles geometry.
  30. * <br><li>It duplicates a vertex that has more than 1 texture coordinate.
  31. * So texture with indexed geometry can still be used.
  32. * <br><li>It also duplicates equal vertices that get assigned different normals in the calculation process according
  33. * to the face they belong to.
  34. * <p>
  35. *
  36. * @author C.Ruff
  37. */
  38. public class TriangleNormalGenerator {
  39. /** The Constant logger. */
  40. private static final ILogger logger = MTLoggerFactory.getLogger(TriangleNormalGenerator.class.getName());
  41. static{
  42. logger.setLevel(ILogger.ERROR);
  43. }
  44. /** The null vect. */
  45. private Vertex nullVect;
  46. /** Use these for console debug info. */
  47. // private boolean debug;
  48. /** The use normals equal to face. */
  49. private boolean useNormalsEqualToFace;
  50. /** The use equal neighbor normals again. */
  51. private boolean useEqualNeighborNormalsAgain;
  52. /**
  53. * Constructor.
  54. */
  55. public TriangleNormalGenerator(){
  56. nullVect = new Vertex(0,0,0, -1, -1);
  57. useNormalsEqualToFace = true;
  58. useEqualNeighborNormalsAgain = true;
  59. }
  60. /**
  61. * Generates smooth normals for a triangle geometry array.
  62. *
  63. * @param pa the pa
  64. * @param geometryInfo the geometry info
  65. *
  66. * @return the geometry info
  67. *
  68. * the geometry array with normals
  69. */
  70. public GeometryInfo generateTriangleNormals(PApplet pa, GeometryInfo geometryInfo){
  71. return this.generateTriangleNormals(pa, geometryInfo, 180);
  72. }
  73. /**
  74. * Generates normals for the provided geometry info according to the crease angle.
  75. * <br>A crease angle of 180 will result in a all smoothed model, smoothing each vertex normal
  76. * across all its neighbor faces' face normals.
  77. * <br>A crease angle of zero (0) will result in a flat shaded geometry. Only face normals will
  78. * be used then.
  79. * <br>A crease angle of 89 will create hard edges at 90 degree angle faces and smooth faces with
  80. * less then 90 degree normals. This would be ideal to generate normals for a cube.
  81. * <br>The best crease angle for a model has to be found by testing different angles.
  82. *
  83. * <br><strong>Note:</strong>The geometry has to represent a TRIANGLES array!
  84. * <br><strong>Note:</strong>The stroke color information gets lost during the process and is reset
  85. * to the default color. Set it again if needed with <code>setStrokeColorAll</code>.
  86. *
  87. * @param pa the pa
  88. * @param geometryInfo the geometry info
  89. * @param creaseAngle the crease angle
  90. *
  91. * @return the geometry info
  92. *
  93. * the geometry array with normals
  94. */
  95. public GeometryInfo generateTriangleNormals(PApplet pa, GeometryInfo geometryInfo, float creaseAngle ){
  96. Vertex[] vertices = geometryInfo.getVertices();
  97. //Gen texcoord array
  98. float[][] texCoords = new float[vertices.length][2];
  99. for (int i = 0; i < vertices.length; i++) {
  100. Vertex v = vertices[i];
  101. texCoords[i][0] = v.getTexCoordU();
  102. texCoords[i][1] = v.getTexCoordV();
  103. }
  104. //Gen or get indices array
  105. int[] indices = null;
  106. if (!geometryInfo.isIndexed()){
  107. indices = new int[vertices.length];
  108. for (int i = 0; i < vertices.length; i++) {
  109. indices[i] = i;
  110. }
  111. }else{
  112. indices = geometryInfo.getIndices();
  113. }
  114. //Gen texcoord array as same as indices array
  115. int[] texIndices = new int[indices.length];
  116. System.arraycopy(indices, 0, texIndices, 0, indices.length);
  117. // for (int i = 0; i < indices.length; i++) {
  118. // texIndices[i] = indices[i];
  119. //}
  120. //Generate normals
  121. GeometryInfo geom = null;
  122. if (creaseAngle == 180){
  123. geom = this.generateSmoothNormals(pa, vertices, indices, texCoords, texIndices, creaseAngle, false, false);
  124. }else{
  125. geom = this.generateCreaseAngleNormals(pa, vertices, indices, texCoords, texIndices, creaseAngle, false, false);
  126. }
  127. //Reset indices if they werent set before,too
  128. //Reconstruct the passed in geometryinfo
  129. if (!geometryInfo.isIndexed()){
  130. geometryInfo.reconstruct(geom.getVertices(), geom.getNormals(), null, true, false, null);
  131. }else{
  132. geometryInfo.reconstruct(geom.getVertices(), geom.getNormals(), geom.getIndices(), true, false, null);
  133. }
  134. geom = null;
  135. return geometryInfo;
  136. }
  137. /**
  138. * Generates triangle normals, smoothed acroos all neighbor faces.
  139. * <br>Also dissolves multiple texturecoordinates belonging to the same vertex by
  140. * duplicating them.
  141. *
  142. * @param pa the pa
  143. * @param originalVertices the original vertices
  144. * @param originalIndices the original indices
  145. * @param originalTexCoords the original tex coords
  146. * @param originalTexIndices the original tex indices
  147. * @param creaseAngle the crease angle
  148. * @param flipTextureY the flip texture y
  149. * @param flipTextureX the flip texture x
  150. *
  151. * @return the geometry info
  152. */
  153. public GeometryInfo generateSmoothNormals(PApplet pa, Vertex[] originalVertices, int[] originalIndices, float[][] originalTexCoords, int[] originalTexIndices, float creaseAngle, boolean flipTextureY, boolean flipTextureX){
  154. int newDuplicatesWithDiffTexCoordsCreated = 0;
  155. int newDuplicatesWithDiffNormalCreated = 0;
  156. logger.debug("-> Loading all smoothed model.");
  157. ArrayList<VertexData> vertexDatas = new ArrayList<VertexData>(originalVertices.length);
  158. ArrayList<MyFace> faces = new ArrayList<MyFace>(Math.round(originalIndices.length/3));
  159. //Init and fill vertexdata list with as many as vertices
  160. for (int i = 0; i < originalVertices.length; i++) {
  161. //Vertex v = vertices[i];
  162. VertexData vd = new VertexData();
  163. vd.setArrayIndex(i);
  164. vertexDatas.add(vd);
  165. }
  166. int pp0 = 0;
  167. int pp1 = 0;
  168. int pp2 = 0;
  169. int tIndexPP0 = 0;
  170. int tIndexPP1 = 0;
  171. int tIndexPP2 = 0;
  172. //GO through indices array and create a face for every three indices (must be triangle array!)
  173. for (int i = 0; i < originalIndices.length/3; i++) {
  174. //int currentIndex = indices[i];
  175. //Next 3 vertex indices as the new faces pointers
  176. pp0 = originalIndices[i*3];
  177. pp1 = originalIndices[i*3+1];
  178. pp2 = originalIndices[i*3+2];
  179. if (originalTexCoords.length > 0){
  180. //Next 3 texture texture indices //(vertex and texture indices indexed in the same order)
  181. tIndexPP0 = originalTexIndices[i*3];
  182. tIndexPP1 = originalTexIndices[i*3+1];
  183. tIndexPP2 = originalTexIndices[i*3+2];
  184. }
  185. MyFace myFace = new MyFace();
  186. myFace.p0 = pp0;
  187. myFace.p1 = pp1;
  188. myFace.p2 = pp2;
  189. int vertexPointer = pp0;
  190. int texturePointer = tIndexPP0;
  191. for (int j = 0; j < 3; j++) {
  192. if (j == 0) {
  193. vertexPointer = pp0;
  194. texturePointer = tIndexPP0;
  195. }
  196. else if(j == 1){
  197. vertexPointer = pp1;
  198. texturePointer = tIndexPP1;
  199. }
  200. else if(j == 2){
  201. vertexPointer = pp2;
  202. texturePointer = tIndexPP2;
  203. }
  204. //Get the vertexdata at the index, the face points to
  205. VertexData myVertexData = vertexDatas.get(vertexPointer);
  206. Vertex newVertex = new Vertex(
  207. originalVertices[vertexPointer].x,
  208. originalVertices[vertexPointer].y,
  209. originalVertices[vertexPointer].z,
  210. originalVertices[vertexPointer].getR(),
  211. originalVertices[vertexPointer].getG(),
  212. originalVertices[vertexPointer].getB(),
  213. originalVertices[vertexPointer].getA()
  214. );
  215. // Create texcoords and add to vertex
  216. float[] tex = new float[2];
  217. if (originalTexCoords.length > 0){
  218. tex[0] = originalTexCoords[texturePointer][0];
  219. tex[1] = originalTexCoords[texturePointer][1];
  220. if (flipTextureY){
  221. tex[1] = 1.0f-tex[1];
  222. }
  223. if (flipTextureX){
  224. tex[0] = 1.0f-tex[0];
  225. }
  226. newVertex.setTexCoordU(tex[0]);
  227. newVertex.setTexCoordV(tex[1]);
  228. }
  229. //Check if the vertex data at the pointer is empty thats the case before first time a vertex is added to it here
  230. if (myVertexData.getVertex() == null){
  231. myVertexData.setVertex(newVertex);
  232. myVertexData.addNeighborFace(myFace);
  233. logger.debug("vdP" + j + " vertex in vertexData not initialzied -> set it");
  234. // logger.debug("vdP0 is empty -> adding first vertex, texture tuple");
  235. }else{//Vertex data at index already contains one or more vertices
  236. //Check if the vertex data at the index contains a vertex that is equal to the new vertex and its texture information
  237. //-> if true, just add the vertex to that vertexdata and the face it also is in
  238. //-> if false, check if a duplicate vertexdata is registered in the vertexdata the face points to
  239. // -> if true, add the vertex to the duplicate, change face index to the duplicates index
  240. // -> if false, create new vertexdata at end of list, add the vertex and texcoords of the vertex, and register
  241. // it as a duplicate in the original vertexdata, change the face index to the new duplicates index
  242. if (myVertexData.equalsVertex(newVertex)){
  243. //Register das face mit dem vertex data
  244. myVertexData.addNeighborFace(myFace);
  245. logger.debug("vdP" + j + "already CONTAINS a vertex with same coords and texture information -> do nothing, just a the current face to its neighborlist");
  246. }else{
  247. //Check if already duplicates were created, maybe with the same vertex and texture information,
  248. //then we have to add the vertex to that vertexdata rather than creating a new one
  249. int duplicateIndex = myVertexData.getVertDuplicateSameVertDiffTextureCoordListIndex(newVertex);
  250. if (duplicateIndex != -1){ //Es gibt schon ein duplicate mit gleichen tex coords wie dieses hier, adde bei duplicateIndex
  251. //Change face pointer of p0 to the duplicates index
  252. if (j == 0) myFace.p0 = duplicateIndex;
  253. else if(j == 1) myFace.p1 = duplicateIndex;
  254. else if(j == 2) myFace.p2 = duplicateIndex;
  255. //wenn wir orginal hinzuf?gen wird auch allen duplicates neighbor face zugef?gt.
  256. myVertexData.addNeighborFace(myFace);
  257. logger.debug("vdP" + j + "has different texture coordiantes but a already created duplicate has the same -> change this face pointer to the duplicate one");
  258. }else{//there was no duplicate created with the same texture coords yet -> create one!
  259. //Neuen Vertex machen, an original vertices list anh?ngen, neuen index in face auf diesen setzen, face adden
  260. VertexData newVertexData = new VertexData();
  261. //Add the vertex information to the newly created vertexdata
  262. newVertexData.setVertex(newVertex);
  263. //Get new index at end of vertex list
  264. int newIndexOfNewVertexData = vertexDatas.size();
  265. //Change the index of the face to the index the new Vdata is created at
  266. if (j == 0) myFace.p0 = newIndexOfNewVertexData;
  267. else if(j == 1) myFace.p1 = newIndexOfNewVertexData;
  268. else if(j == 2) myFace.p2 = newIndexOfNewVertexData;
  269. //Tell the vertexdata the index it is in the overall data
  270. newVertexData.setArrayIndex(newIndexOfNewVertexData);
  271. //Add new vertex data at the end of the list of all vertexdatas
  272. vertexDatas.add(newVertexData);
  273. //Inform the original vertexdata, that a duplicate with diff tex coords was created and register it
  274. myVertexData.registerCreatedDuplicateDiffTexCoords(newVertexData);
  275. //Adde face zu orginal face -> damit wird auch duplicates und dem neuen hinzugef?gt,
  276. //wenn wir es vorher mit registerDuplicate am orginal registiert haben!
  277. myVertexData.addNeighborFace(myFace);
  278. //copy the face list the vertex is contained in of the original
  279. //to the duplicate (for normal generation later, so they are still neighbors)!
  280. newVertexData.addNeighborFaces(myVertexData.getFacesContainedIn());
  281. 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);
  282. newDuplicatesWithDiffTexCoordsCreated++;
  283. }//end if duplicate exists
  284. }//end if vertexdata already contains Vnew
  285. }//end if vertexdata is empty
  286. }//end for p0,p1,p2
  287. //Calculate the face's normal vector
  288. myFace.calcFaceNormal(vertexDatas);
  289. myFace.index = faces.size();
  290. //Add face to facelist
  291. faces.add(myFace);
  292. }
  293. logger.debug("-> Processed duplicate vertex/texture points.");
  294. //Create arrays
  295. Vertex[] newVertices = new Vertex[vertexDatas.size()];
  296. Vector3D[] normals = new Vector3D[vertexDatas.size()];
  297. int[] newIndices = new int[faces.size()*3];
  298. /*
  299. * Go through the final faces list and fill vertex/newIndices/normal arrays
  300. */
  301. for (int j = 0; j < faces.size(); j++) {
  302. MyFace myFace = faces.get(j);
  303. //Get vertex pointers of face to newVertices in newVertices list
  304. int indexP0 = myFace.p0;
  305. int indexP1 = myFace.p1;
  306. int indexP2 = myFace.p2;
  307. //Use pointers as newIndices and fill newIndices array
  308. newIndices[j*3] = indexP0;
  309. newIndices[j*3+1] = indexP1;
  310. newIndices[j*3+2] = indexP2;
  311. //Get the vertexdatas out of the list with the pointers
  312. VertexData vdP0 = vertexDatas.get(indexP0);
  313. VertexData vdP1 = vertexDatas.get(indexP1);
  314. VertexData vdP2 = vertexDatas.get(indexP2);
  315. //Get the vertex out of the vdata
  316. Vertex v0 = vdP0.getVertex();
  317. Vertex v1 = vdP1.getVertex();
  318. Vertex v2 = vdP2.getVertex();
  319. //Put newVertices from vertexdata list in vertex array for the geometry array
  320. newVertices[indexP0] = v0;
  321. newVertices[indexP1] = v1;
  322. newVertices[indexP2] = v2;
  323. //Get the faces normal
  324. // Vector3D faceNormal = Tools3D.getNormal(v0, v1, v2, true); //myFace.normal;//
  325. // Vector3D faceNormal = myFace.normal.getCopy();
  326. // faceNormal.normalizeLocal();
  327. Vector3D faceNormal = myFace.normalNormalized;
  328. Vector3D normalP0;
  329. if (vdP0.getNeighborFaces().size() > 1){
  330. // logger.debug("Calcing v normal of face: " + myFace.index + " P0");
  331. normalP0 = vdP0.calcVertexNormalAllNeighbors();
  332. }else{
  333. normalP0 = faceNormal;
  334. }
  335. Vector3D normalP1;
  336. if (vdP1.getNeighborFaces().size() > 1){
  337. // logger.debug("Calcing v normal of face: " + myFace.index + " P1");
  338. normalP1 = vdP1.calcVertexNormalAllNeighbors();
  339. }else{
  340. normalP1 = faceNormal;
  341. }
  342. Vector3D normalP2;
  343. if (vdP2.getNeighborFaces().size() > 1){
  344. // logger.debug("Calcing v normal of face: " + myFace.index + " P2");
  345. normalP2 = vdP2.calcVertexNormalAllNeighbors();
  346. }else{
  347. normalP2 = faceNormal;
  348. }
  349. normals[indexP0] = normalP0;
  350. normals[indexP1] = normalP1;
  351. normals[indexP2] = normalP2;
  352. ////Normalen debug linien sehen mit normals invertiert richtig
  353. //aus, aber model wird falsch geshaded!
  354. /*
  355. normals[indexP0].scale(-1);
  356. normals[indexP1].scale(-1);
  357. normals[indexP2].scale(-1);
  358. */
  359. }
  360. //Leider n?tig? da manche models newVertices enthalten, die in den faces garnicht referenziert werden, quasi tote verts
  361. for (int j = 0; j < newVertices.length; j++) {
  362. if (newVertices[j] == null){
  363. newVertices[j] = nullVect;
  364. }
  365. //Normals array should be same length as verts, check for nulls here
  366. if (normals[j] == null){
  367. normals[j] = nullVect;
  368. }
  369. //System.out.print(normals[j] + " - ");
  370. }
  371. logger.debug("----------------------------------------------------------------------------------");
  372. logger.debug("New duplicates of same vertices with different texture coordinates created: " + newDuplicatesWithDiffTexCoordsCreated);
  373. logger.debug("New duplicates of same vertices with different normal created: " + newDuplicatesWithDiffNormalCreated);
  374. logger.debug("Original number of vertices: " + originalVertices.length);
  375. logger.debug("Final number of vertices: " + vertexDatas.size());
  376. logger.debug("Original number of faces: " + originalIndices.length/3);
  377. logger.debug("Final number of faces: " + faces.size());
  378. logger.debug("Original number of indices: " + originalIndices.length);
  379. logger.debug("Final number of indices: " + newIndices.length);
  380. logger.debug("Final number of normals: " + normals.length);
  381. logger.debug("----------------------------------------------------------------------------------");
  382. if (newVertices.length > 2 && faces.size() > 0){
  383. // Create a geometryInfo with all vertices of the mesh
  384. GeometryInfo geometryInfo = new GeometryInfo(pa, newVertices, newIndices);
  385. //Set the normals for the geometry
  386. geometryInfo.setNormals(normals, true, false);
  387. //Clean up a bit
  388. vertexDatas = null;
  389. faces = null;
  390. return geometryInfo;
  391. }
  392. return null;
  393. }
  394. /**
  395. * Generates normals for the provided geometry data according to the crease angle.
  396. * <br>A crease angle of 180 will result in a all smoothed model, smoothing each vertex normal
  397. * across all its neighbor faces' face normals.
  398. * <br>A crease angle of zero (0) will result in a flat shaded geometry. Only face normals will
  399. * be used then.
  400. * <br>A crease angle of 89 will create hard edges at 90 degree angle faces and smooth faces with
  401. * less then 90 degree normals. This would be ideal to generate normals for a cube.
  402. * <br>The best crease angle for a model has to be found by testing.
  403. *
  404. * @param pa the pa
  405. * @param originalVertices the original vertices
  406. * @param originalIndices the original indices
  407. * @param originalTexCoords the original tex coords
  408. * @param originalTexIndices the original tex indices
  409. * @param creaseAngle the crease angle
  410. * @param flipTextureY the flip texture y
  411. * @param flipTextureX the flip texture x
  412. *
  413. * @return the geometry info
  414. *
  415. * indexed, geometry info with normals
  416. */
  417. public GeometryInfo generateCreaseAngleNormals(PApplet pa, Vertex[] originalVertices, int[] originalIndices, float[][] originalTexCoords, int[] originalTexIndices, float creaseAngle, boolean flipTextureY, boolean flipTextureX){
  418. int newDuplicatesWithDiffTexCoordsCreated = 0;
  419. int newDuplicatesWithDiffNormalCreated = 0;
  420. boolean useNormailizedNormalsForAdding = true;
  421. logger.debug("-> Loading model with a crease angle: " + creaseAngle);
  422. float creaseAngleRad = (float)Math.toRadians(creaseAngle);
  423. // float creaseAngleRad =
  424. float creaseCosinus = (float)Math.cos(creaseAngle);
  425. nullVect = new Vertex(0,0,0, -1, -1);
  426. ArrayList<VertexData> vertexDatas = new ArrayList<VertexData>();
  427. ArrayList<MyFace> faces = new ArrayList<MyFace>();
  428. //Init and fill vertexdata list with as many as vertices
  429. for (int i = 0; i < originalVertices.length; i++) {
  430. //Vertex v = vertices[i];
  431. VertexData vd = new VertexData();
  432. vd.setArrayIndex(i);
  433. vertexDatas.add(vd);
  434. }
  435. /////////////////////////////////////
  436. //GO through indices array and create a face for every three indices (must be triangle array!)
  437. int pp0 = 0;
  438. int pp1 = 0;
  439. int pp2 = 0;
  440. int tIndexPP0 = 0;
  441. int tIndexPP1 = 0;
  442. int tIndexPP2 = 0;
  443. for (int i = 0; i < originalIndices.length/3; i++) {
  444. //int currentIndex = indices[i];
  445. //Next 3 vertex indices as the new faces pointers for our face
  446. pp0 = originalIndices[i*3];
  447. pp1 = originalIndices[i*3+1];
  448. pp2 = originalIndices[i*3+2];
  449. if (originalTexCoords.length > 0){
  450. //Next 3 texture texture indices //(vertex and texture indices indexed in the same order)
  451. tIndexPP0 = originalTexIndices[i*3];
  452. tIndexPP1 = originalTexIndices[i*3+1];
  453. tIndexPP2 = originalTexIndices[i*3+2];
  454. }
  455. MyFace myFace = new MyFace();
  456. myFace.p0 = pp0;
  457. myFace.p1 = pp1;
  458. myFace.p2 = pp2;
  459. int vertexPointer = pp0;
  460. int texturePointer = tIndexPP0;
  461. for (int j = 0; j < 3; j++) {
  462. if (j == 0) {
  463. vertexPointer = pp0;
  464. texturePointer = tIndexPP0;
  465. }
  466. else if(j == 1){
  467. vertexPointer = pp1;
  468. texturePointer = tIndexPP1;
  469. }
  470. else if(j == 2){
  471. vertexPointer = pp2;
  472. texturePointer = tIndexPP2;
  473. }
  474. //Get the vertexdata at the index, the face points to
  475. VertexData myVertexData = vertexDatas.get(vertexPointer);
  476. Vertex newVertex = new Vertex(
  477. originalVertices[vertexPointer].x,
  478. originalVertices[vertexPointer].y,
  479. originalVertices[vertexPointer].z,
  480. originalVertices[vertexPointer].getR(),
  481. originalVertices[vertexPointer].getG(),
  482. originalVertices[vertexPointer].getB(),
  483. originalVertices[vertexPointer].getA()
  484. );
  485. //Create texcoords and add to vertex
  486. float[] tex = new float[2];
  487. if (originalTexCoords.length > 0){
  488. tex[0] = originalTexCoords[texturePointer][0];
  489. tex[1] = originalTexCoords[texturePointer][1];
  490. if (flipTextureY){
  491. tex[1] = 1.0f-tex[1];
  492. }
  493. if (flipTextureX){
  494. tex[0] = 1.0f-tex[0];
  495. }
  496. newVertex.setTexCoordU(tex[0]);
  497. newVertex.setTexCoordV(tex[1]);
  498. }
  499. //Check if the vertex data at the pointer is empty thats the case before first time a vertex is added to it here
  500. if (myVertexData.getVertex() == null){
  501. myVertexData.setVertex(newVertex);
  502. myVertexData.addNeighborFace(myFace);
  503. logger.debug("vdP" + j + " vertex in vertexData not initialized -> set it: " + newVertex);
  504. }else{//Vertex data at index already contains one or more vertices
  505. //Check if the vertex data at the index contains a vertex that is equal to the new vertex and its texture information
  506. //-> if true, just add the vertex to that vertexdata and the face it also is in
  507. //-> if false, check if a duplicate vertexdata is registered in the vertexdata the face points to
  508. // -> if true, add the vertex to the duplicate, change face index to the duplicates index
  509. // -> if false, create new vertexdata at end of list, add the vertex and texcoords of the vertex, and register
  510. // it as a duplicate in the original vertexdata, change the face index to the new duplicates index
  511. if (myVertexData.equalsVertex(newVertex)){
  512. //Register das face mit dem vertex data
  513. myVertexData.addNeighborFace(myFace);
  514. logger.debug("vdP" + j + "already CONTAINS a vertex with same coords and texture information -> do nothing, just add the current face to its neighborlist");
  515. }else{
  516. //Check if already duplicates were created, maybe with the same vertex and texture information,
  517. //then we have to add the vertex to that vertexdata rather than creating a new one
  518. int duplicateIndex = myVertexData.getVertDuplicateSameVertDiffTextureCoordListIndex(newVertex);
  519. if (duplicateIndex != -1){ //Es gibt schon ein duplicate mit gleichen tex coords wie dieses hier, adde bei duplicateIndex
  520. //Change face pointer of p0 to the duplicates index
  521. if (j == 0) myFace.p0 = duplicateIndex;
  522. else if(j == 1) myFace.p1 = duplicateIndex;
  523. else if(j == 2) myFace.p2 = duplicateIndex;
  524. //wenn wir orginal hinzuf?gen wird auch allen duplicates neighbor face zugef?gt.
  525. myVertexData.addNeighborFace(myFace);
  526. logger.debug("vdP" + j + "has different texture coordiantes but a already created duplicate has the same -> change this face pointer to the duplicate one");
  527. }else{//there was no duplicate created with the same texture coords yet -> create one!
  528. //Neuen Vertex machen, an original vertices list anh?ngen, neuen index in face auf diesen setzen, face adden
  529. VertexData newVertexData = new VertexData();
  530. //Add the vertex information to the newly created vertexdata
  531. newVertexData.setVertex(newVertex);
  532. //Get new index at end of vertex list
  533. int newIndexOfNewVertexData = vertexDatas.size();
  534. //Change the index of the face to the index the new Vdata is created at
  535. if (j == 0) myFace.p0 = newIndexOfNewVertexData;
  536. else if(j == 1) myFace.p1 = newIndexOfNewVertexData;
  537. else if(j == 2) myFace.p2 = newIndexOfNewVertexData;
  538. //Tell the vertexdata the index it is in the overall data
  539. newVertexData.setArrayIndex(newIndexOfNewVertexData);
  540. //Add new vertex data at the end of the list of all vertexdatas
  541. vertexDatas.add(newVertexData);
  542. //Inform the original vertexdata, that a duplicate with diff tex coords was created and register it
  543. myVertexData.registerCreatedDuplicateDiffTexCoords(newVertexData);
  544. //Adde face zu orginal face -> damit wird auch duplicates und dem neuen hinzugef?gt,
  545. //wenn wir es vorher mit registerDuplicate am orginal registiert haben!
  546. myVertexData.addNeighborFace(myFace);
  547. //copy the face list the vertex is contained in of the original
  548. //to the duplicate (for normal generation later, so they are still neighbors)!
  549. newVertexData.addNeighborFaces(myVertexData.getFacesContainedIn());
  550. 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);
  551. newDuplicatesWithDiffTexCoordsCreated++;
  552. }//end if duplicate exists
  553. }//end if vertexdata already contains Vnew
  554. }//end if vertexdata is empty
  555. }//end for p0,p1,p2
  556. //Calculate the face's normal vector
  557. myFace.calcFaceNormal(vertexDatas);
  558. myFace.index = faces.size();
  559. //Add face to facelist
  560. faces.add(myFace);
  561. }
  562. logger.debug("-> Processed duplicate vertex/texture points.");
  563. /////////////////////////////////////////
  564. //////////////////////////////////////
  565. if (creaseAngleRad != 0.0) {
  566. //Durch alle selbst kreierten faces gehen, und schauen ob ein vertex des faces mit einem seiner
  567. //nachbar faces einen "sharp edge" hat oder smooth ist.
  568. //wenn smooth -> als smooth neighbor des face pointers hinzuf?gen
  569. for (MyFace currentFace : faces) {
  570. //Get vertex pointers of face to vertices in vertices list
  571. int indexP0 = currentFace.p0;
  572. int indexP1 = currentFace.p1;
  573. int indexP2 = currentFace.p2;
  574. //Get the vertexdatas out of the list with the pointers
  575. VertexData vdP0 = vertexDatas.get(indexP0);
  576. VertexData vdP1 = vertexDatas.get(indexP1);
  577. VertexData vdP2 = vertexDatas.get(indexP2);
  578. int[] currentFaceVertIndices = currentFace.getVertexIndices();
  579. //Go through all 3 vertexdata entries in the current face and check for its smooth neighbors
  580. for (int faceVD = 0; faceVD < currentFaceVertIndices.length /*currentFace.getVertexIndices().length*/; faceVD++) {
  581. VertexData currentFaceVertexData = null;
  582. if (faceVD == 0) {
  583. currentFaceVertexData = vdP0; /*logger.debug("Face: " + j + " - P0");*/
  584. } else if (faceVD == 1) {
  585. currentFaceVertexData = vdP1; /*logger.debug("Face: " + j + " - P1");*/
  586. } else if (faceVD == 2) {
  587. currentFaceVertexData = vdP2; /*logger.debug("Face: " + j + " - P2");*/
  588. }
  589. ArrayList<MyFace> facesVDIsIn = currentFaceVertexData.getFacesContainedIn();
  590. //Go through all neighbor faces that the vertex(data) is a part of
  591. for (MyFace anotherFaceVDisIn : facesVDIsIn) {
  592. //Check that we are not considering the same face as the currentFace
  593. if (!anotherFaceVDisIn.equals(currentFace)) {
  594. boolean onSameSurface = isOnSameSurfaceRadians(currentFace, anotherFaceVDisIn, creaseAngleRad);
  595. // boolean onSameSurface = isOnSameSurfaceCosAngle(currentFace, anotherFaceVDisIn, creaseCosinus);
  596. //Check if the current face and the other face VD are connected
  597. //by an angle < cos_angle degrees,
  598. //if so, add the faces to the vds smooth neighbor list (for later normal generation)
  599. //if NOT so, create new VertexData, as a copy of the current one at the end of
  600. //the vertexdata list, adjust the face pointers of the current face to the new one
  601. //(we need another vertex so we have two different normals for them if the two faces arent smoothly connected)
  602. if (onSameSurface) {
  603. if (faceVD == 0) {
  604. 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() + " )");
  605. } else if (faceVD == 1) {
  606. 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() + " )");
  607. } else if (faceVD == 2) {
  608. 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() + " )");
  609. }
  610. if (faceVD == 0) {
  611. currentFace.addSmoothNeighborP0(anotherFaceVDisIn);
  612. } else if (faceVD == 1) {
  613. currentFace.addSmoothNeighborP1(anotherFaceVDisIn);
  614. } else if (faceVD == 2) {
  615. currentFace.addSmoothNeighborP2(anotherFaceVDisIn);
  616. }
  617. }//if smooth
  618. }//if not checking against this same face
  619. }
  620. }//for loop through all 3 vertexdatas of the current face
  621. }
  622. }//end if creaseAngle != 0.0
  623. ///////////////////////////////////////////////////////////////////////////
  624. ///////////////// //moved to the next loop
  625. // //Vertex normalen berechnen
  626. // for (int j = 0; j < faces.size(); j++) {
  627. // MyFace currentFace = faces.get(j);
  628. // currentFace.calcVertexNormals(useNormailizedNormalsForAdding);
  629. // }
  630. //////////////////
  631. // /|\
  632. // combine?
  633. // \|/
  634. //////////////////////////////////////////////////////////////////////
  635. //Die vertex normalen wurden pro face und pro pointer auf ein vertex in den faces berechnet
  636. //Jetzt f?gen wir den VertexDatas, die die vertices representieren diese vertex normalen hinzu.
  637. //Wenn in mehreren faces auf den gleichen vertex gezeigt wird, aber in dem face f?r diesen vertex eine
  638. //andere normale berechnet wurde (weil face mit anderen smooth ist) m?ssen wir evtl das Vertex(data) duplizieren
  639. //und diesem die andere normale hinzuf?gen
  640. for (int j = 0; j < faces.size(); j++) {
  641. MyFace currentFace = faces.get(j);
  642. //GENERATE THE FACES VERTEX NORMAL BASED ON ITS SMOOTH NEIGHBORS
  643. currentFace.calcVertexNormals(useNormailizedNormalsForAdding);
  644. int[] faceVertexPointer = currentFace.getVertexIndices();
  645. //Go trough all (3) vertexpointer p0..2 of the current face
  646. for (int i = 0; i < faceVertexPointer.length; i++) {
  647. int currentVertexPointer = faceVertexPointer[i];
  648. logger.debug("-> Processing face[" + j + "].P" + i + " Vertex: " + vertexDatas.get(currentVertexPointer).getVertex());
  649. //Hole vertexdata auf das das currentFace an dem aktuellen zeiger (p0,p1,p2) zeigt
  650. VertexData currentVertexDataP0OrP1OrP2 = vertexDatas.get(currentVertexPointer);
  651. //Get normal saved in the vertexdata at position Face.Px
  652. Vector3D currentFacesCurrentVDNormal = currentVertexDataP0OrP1OrP2.getUniqueVertexNormal();
  653. //Get vertex normal array calculated and saved in the face for each point Px
  654. Vector3D[] vertexNormalsCurrentFace = currentFace.getVertexNormals();
  655. //Check if the vertexnormal data at the pointer is null -> thats the case before first time a vertexnormal is set here
  656. if (currentFacesCurrentVDNormal == null){
  657. currentVertexDataP0OrP1OrP2.setUniqueVertexNormal(vertexNormalsCurrentFace[i]);
  658. logger.debug("Face " + j + ", vdP" + i + " (Vertex: " + vertexDatas.get(currentVertexPointer).getVertex() + ")" + " normal not yet set -> set it: " + vertexNormalsCurrentFace[i]);
  659. }else{//Vertexdata at index already contains a vertexnormal -> check if its the equal to this faces currentVD's
  660. if (currentFacesCurrentVDNormal.equalsVectorWithTolerance(vertexNormalsCurrentFace[i], ToolsMath.ZERO_TOLERANCE)){
  661. 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]);
  662. }else{
  663. int duplicateIndexOfSameVertDiffNormal = currentVertexDataP0OrP1OrP2.getVertDuplicateSameVertDiffNormalListIndex(vertexNormalsCurrentFace[i]);
  664. if (duplicateIndexOfSameVertDiffNormal != -1){ //Es gibt schon ein duplicate mit gleichen tex coords wie dieses hier, adde bei duplicateIndex
  665. //Change face pointer of p0 to the duplicates index
  666. if (i == 0) currentFace.p0 = duplicateIndexOfSameVertDiffNormal;
  667. else if(i == 1) currentFace.p1 = duplicateIndexOfSameVertDiffNormal;
  668. else if(i == 2) currentFace.p2 = duplicateIndexOfSameVertDiffNormal;
  669. 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]);
  670. }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
  671. //Neuen Vertex machen, an original vertices list anh?ngen, neuen index in face auf diesen setzen
  672. VertexData newVertexData = new VertexData();
  673. //Add the vertex information to the newly created vertexdata
  674. newVertexData.setVertex(currentVertexDataP0OrP1OrP2.getVertex());
  675. //Set the vertex normal for the new vertexdata as the vertex normal of the current face' calced normal for that vertex
  676. newVertexData.setUniqueVertexNormal(vertexNormalsCurrentFace[i]);
  677. //Get new index at end of vertex list
  678. int newIndexOfNewVertexData = vertexDatas.size();
  679. //Change the index of the face to the index the new Vdata is created at
  680. if (i == 0) currentFace.p0 = newIndexOfNewVertexData;
  681. else if(i == 1) currentFace.p1 = newIndexOfNewVertexData;
  682. else if(i == 2) currentFace.p2 = newIndexOfNewVertexData;
  683. //Tell the vertexdata the index it is in the overall data
  684. newVertexData.setArrayIndex(newIndexOfNewVertexData);
  685. //Add new vertex data at the end of the list of all vertexdatas
  686. vertexDatas.add(newVertexData);
  687. //Inform the original vertexdata, that a duplicate with diff tex coords was created and register it
  688. currentVertexDataP0OrP1OrP2.registerCreatedDuplicateDiffNormal(newVertexData);
  689. 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]);
  690. newDuplicatesWithDiffNormalCreated++;
  691. }//end if duplicate exists
  692. }//end if vertexdata already contains Vnew
  693. }//end if vertexdata is empty
  694. }
  695. }
  696. ////////////////////////////////////
  697. //////////////////////////////////////////
  698. //Create arrays
  699. Vertex[] newVertices = new Vertex[vertexDatas.size()];
  700. Vector3D[] normals = new Vector3D[vertexDatas.size()];
  701. int[] newIndices = new int[faces.size()*3];
  702. /*
  703. * Go through the final faces list and fill vertex/newIndices/normal arrays
  704. */
  705. for (int j = 0; j < faces.size(); j++) {
  706. MyFace myFace = faces.get(j);
  707. //Get vertex pointers of face to newVertices in newVertices list
  708. int indexP0 = myFace.p0;
  709. int indexP1 = myFace.p1;
  710. int indexP2 = myFace.p2;
  711. //Use pointers as newIndices and fill newIndices array
  712. newIndices[j*3] = indexP0;
  713. newIndices[j*3+1] = indexP1;
  714. newIndices[j*3+2] = indexP2;
  715. //Get the vertexdatas out of the list with the pointers
  716. VertexData vdP0 = vertexDatas.get(indexP0);
  717. VertexData vdP1 = vertexDatas.get(indexP1);
  718. VertexData vdP2 = vertexDatas.get(indexP2);
  719. //Get the vertex out of the vdata
  720. Vertex v0 = vdP0.getVertex();
  721. Vertex v1 = vdP1.getVertex();
  722. Vertex v2 = vdP2.getVertex();
  723. //Put newVertices from vertexdata list in vertex array for the geometry array
  724. newVertices[indexP0] = v0;
  725. newVertices[indexP1] = v1;
  726. newVertices[indexP2] = v2;
  727. //Get the faces normal
  728. normals[indexP0] = vdP0.uniqueVertexNormal;
  729. normals[indexP1] = vdP1.uniqueVertexNormal;
  730. normals[indexP2] = vdP2.uniqueVertexNormal;
  731. ////Normalen debug linien sehen mit normals invertiert richtig
  732. //aus, aber model wird falsch geshaded!
  733. /*
  734. normals[indexP0].scale(-1);
  735. normals[indexP1].scale(-1);
  736. normals[indexP2].scale(-1);
  737. */
  738. }
  739. //Leider n?tig? da manche models newVertices enthalten, die in den faces garnicht referenziert werden, quasi tote verts
  740. for (int j = 0; j < newVertices.length; j++) {
  741. if (newVertices[j] == null){
  742. newVertices[j] = nullVect;
  743. }
  744. //Normals array should be same length as verts, check for nulls here
  745. if (normals[j] == null){
  746. normals[j] = nullVect;
  747. }
  748. // System.out.print(normals[j] + " - ");
  749. }
  750. // logger.debug();
  751. ///////////////////////////////////////////////////////
  752. logger.debug("----------------------------------------------------------------------------------");
  753. logger.debug("New duplicates of vertices with same vertex but different texture coordinates created: " + newDuplicatesWithDiffTexCoordsCreated);
  754. logger.debug("New duplicates of vertices with same vertex but different normal created: " + newDuplicatesWithDiffNormalCreated);
  755. logger.debug("Original number of vertices: " + originalVertices.length);
  756. logger.debug("Final number of vertices: " + vertexDatas.size());
  757. logger.debug("Final number of indices: " + newIndices.length);
  758. logger.debug("Final number of faces: " + faces.size());
  759. logger.debug("Final number of normals: " + normals.length);
  760. logger.debug("----------------------------------------------------------------------------------");
  761. if (newVertices.length > 2 && faces.size() > 0){
  762. // Create a geometryInfo with all vertices of the mesh
  763. GeometryInfo geometryInfo = new GeometryInfo(pa, newVertices, newIndices);
  764. //Set the normals for the geometry
  765. geometryInfo.setNormals(normals, true, false);
  766. //Clean up a bit
  767. vertexDatas = null;
  768. faces = null;
  769. return geometryInfo;
  770. }
  771. return null;
  772. }
  773. /**
  774. * Sets the debug mode.
  775. *
  776. * @param debug the debug
  777. */
  778. public void setDebug(boolean debug) {
  779. if (debug)
  780. logger.setLevel(ILogger.DEBUG);
  781. else
  782. logger.setLevel(ILogger.ERROR);
  783. }
  784. /**
  785. * This influences the normal generation with crease angles.
  786. * If <code>useNormalsEqualToFace</code> is set to true, normals
  787. * of neighbor faces, that have the same normal as the face and vertex were checking
  788. * against will be used in the calculation.
  789. * </br>If <code>useNormalsEqualToFace</code> is set to false, these normals equal to
  790. * the test face normal will be discarded to avoid adding up redundant normals.
  791. * </br>The default is FALSE.
  792. *
  793. * @param useNormalsEqualToFace use other normals equal to face or
  794. */
  795. public void setUseNormalsEqualToFace(boolean useNormalsEqualToFace) {
  796. this.useNormalsEqualToFace = useNormalsEqualToFace;
  797. }
  798. /**
  799. * This influences the normal generation with crease angles.
  800. * <br<>If <code>useEqualNeighborNormalsAgain</code> is set to true, normals
  801. * of neighbor faces, that have the same normal as a neighbor face previously used in
  802. * the calculation for one same vertex normal will again be used and added in.
  803. * <br>If <code>useEqualNeighborNormalsAgain</code> is set to false, these normals will
  804. * not be added in the calculation again.
  805. * <br>The default is FALSE.
  806. *
  807. * @param useEqualNeighborNormalsAgain use equal neighbor normals again
  808. */
  809. public void setUseEqualNeighborNormalsAgain(boolean useEqualNeighborNormalsAgain) {
  810. this.useEqualNeighborNormalsAgain = useEqualNeighborNormalsAgain;
  811. }
  812. /**
  813. * Calculates ..
  814. *
  815. * @param face1 the face1
  816. * @param face2 the face2
  817. * @param cosAngle the cos angle
  818. *
  819. * @return true, if checks if is on same surface radians
  820. */
  821. private boolean isOnSameSurfaceRadians(MyFace face1, MyFace face2, float cosAngle) {
  822. // float cosineBetweenNormals = face1.normal.dot(face2.normal);
  823. // logger.debug(Math.acos(cosineBetweenNormals));
  824. // boolean smooth = cosineBetweenNormals > cosAngle;
  825. // //boolean smoothTriangles = (cosineBetweenNormals > cosAngle);
  826. // //logger.debug("surface: compare dot=" +dot + " cos-angle=" + cos_angle + " return " + (dot > cos_angle));
  827. // logger.debug(Vector3D.angleBetween(face1.normal, face2.normal));
  828. // logger.debug();
  829. //
  830. // return smooth;
  831. boolean debugSmoothChecking = false;
  832. float angleBetweenNorms = Vector3D.angleBetween(face1.normal, face2.normal);
  833. if (debugSmoothChecking){
  834. float angleBetweenNormsDegrees = (float)Math.toDegrees(angleBetweenNorms);
  835. logger.debug("Angle between normals :" + angleBetweenNormsDegrees);
  836. logger.debug("Crease angle: " + Math.toDegrees(cosAngle));
  837. }
  838. boolean smooth = angleBetweenNorms < cosAngle;
  839. if (debugSmoothChecking)
  840. logger.debug("-> Smooth: " + smooth);
  841. if (Float.isNaN(angleBetweenNorms)){
  842. smooth = true;
  843. if (debugSmoothChecking)
  844. logger.debug("NAN!");
  845. }
  846. return smooth;
  847. // float threshold = (float)Math.cos(creaseAngle);
  848. // float cosine = face1.normal.dot(face2.normal);
  849. // boolean smooth = cosine > threshold;
  850. //
  851. // //boolean smoothTriangles = (cosine > threshold);
  852. // //logger.debug("surface: compare dot=" +dot + " cos-angle=" + cos_angle + " return " + (dot > cos_angle));
  853. // return smooth;
  854. // return false;
  855. //// return true;
  856. }
  857. /**
  858. * Calculates ..
  859. *
  860. * @param face1 the face1
  861. * @param face2 the face2
  862. * @param cosAngle the cos angle
  863. *
  864. * @return true, if checks if is on same surface cos angle
  865. */
  866. private boolean isOnSameSurfaceCosAngle(MyFace face1, MyFace face2, float cosAngle) { //FIXME really correct?
  867. float cosineBetweenNormals = face1.normal.dot(face2.normal);
  868. boolean smooth = cosineBetweenNormals > Math.abs(cosAngle);
  869. if (Float.isNaN(cosineBetweenNormals))
  870. smooth = true;
  871. return smooth;
  872. }
  873. /**
  874. * Class representing a triangle face of a mesh.
  875. *
  876. * @author C.Ruff
  877. */
  878. private class MyFace{
  879. /** The p0. */
  880. int p0;
  881. /** The p1. */
  882. int p1;
  883. /** The p2. */
  884. int p2;
  885. /** The smooth neighbors p0. */
  886. private ArrayList<MyFace> smoothNeighborsP0;
  887. /** The smooth neighbors p1. */
  888. private ArrayList<MyFace> smoothNeighborsP1;
  889. /** The smooth neighbors p2. */
  890. private ArrayList<MyFace> smoothNeighborsP2;
  891. /** The normal. */
  892. Vector3D normal;
  893. /** The normal normalized. */
  894. Vector3D normalNormalized;
  895. /** The center. */
  896. private Vector3D center;
  897. /** The index. */
  898. int index;
  899. /** The vertex normal p0. */
  900. private Vector3D vertexNormalP0;
  901. /** The vertex normal p1. */
  902. private Vector3D vertexNormalP1;
  903. /** The vertex normal p2. */
  904. private Vector3D vertexNormalP2;
  905. /** The vertex normals. */
  906. private Vector3D[] vertexNormals;
  907. /**
  908. * Instantiates a new my face.
  909. */
  910. public MyFace(){
  911. p0 = -1;
  912. p1 = -1;
  913. p2 = -1;
  914. //normal = nullVect;
  915. smoothNeighborsP0 = new ArrayList<MyFace>();
  916. smoothNeighborsP1 = new ArrayList<MyFace>();
  917. smoothNeighborsP2 = new ArrayList<MyFace>();
  918. }
  919. /**
  920. * Gets the vertex indices.
  921. *
  922. * @return the vertex indices
  923. *
  924. * the pointers (indices) into the vertex array, this face holds (length=3 here)
  925. */
  926. public int[] getVertexIndices() {
  927. return new int[]{p0,p1,p2};
  928. }
  929. /**
  930. * Registers the face as a smooth neighbor of this faces vertex at
  931. * the index P0. This is only relevant if a crease angle is used.
  932. *
  933. * @param neighborFace the neighbor face
  934. */
  935. public void addSmoothNeighborP0(MyFace neighborFace){
  936. if (!smoothNeighborsP0.contains(neighborFace)){
  937. smoothNeighborsP0.add(neighborFace);
  938. }
  939. }
  940. /**
  941. * Registers the face as a smooth neighbor of this faces vertex at
  942. * the index P1. This is only relevant if a crease angle is used.
  943. *
  944. * @param neighborFace the neighbor face
  945. */
  946. public void addSmoothNeighborP1(MyFace neighborFace){
  947. if (!smoothNeighborsP1.contains(neighborFace)){
  948. smoothNeighborsP1.add(neighborFace);
  949. }
  950. }
  951. /**
  952. * Registers the face as a smooth neighbor of this faces vertex at
  953. * the index P2. This is only relevant if a crease angle is used.
  954. *
  955. * @param neighborFace the neighbor face
  956. */
  957. public void addSmoothNeighborP2(MyFace neighborFace){
  958. if (!smoothNeighborsP2.contains(neighborFace)){
  959. smoothNeighborsP2.add(neighborFace);
  960. }
  961. }
  962. /**
  963. * Calculates this face's face normal.
  964. *
  965. * @param vertexList the vertex list
  966. */
  967. public void calcFaceNormal(ArrayList<VertexData> vertexList){
  968. //We DONT NORMALIZE YET!
  969. this.normal = ToolsGeometry.getNormal(vertexList.get(p0).getVertex(), vertexList.get(p1).getVertex(), vertexList.get(p2).getVertex(), false);
  970. this.normalNormalized = normal.getCopy();
  971. this.normalNormalized.normalizeLocal();
  972. }
  973. /**
  974. * Gets the center point local.
  975. *
  976. * @param vertexDataList the vertex data list
  977. *
  978. * @return the center point local
  979. *
  980. * the center point of this face
  981. */
  982. public Vector3D getCenterPointLocal(ArrayList<VertexData> vertexDataList){
  983. center = vertexDataList.get(p0).getVertex().getCopy();
  984. center.addLocal(vertexDataList.get(p1).getVertex());
  985. center.addLocal(vertexDataList.get(p2).getVertex());
  986. center.scaleLocal(ToolsMath.ONE_THIRD);
  987. return this.center;
  988. }
  989. /**
  990. * Cals the vertex normals for the three points this face has.
  991. * 2 different ways are implemented from which can be chosen by
  992. * the boolean variable.
  993. * if "useNormailizedNormalsForAdding" is false, all unnormalized normals of all
  994. * smooth neighbor faces are added up and at the end normalized.
  995. * If "useNormailizedNormalsForAdding" is false, all neighbors face normals are normalized before adding up.
  996. * Also, normals that are equal to this faces normal arent added again.
  997. * Furthermore, only normals that arent equal to one already added from another
  998. * neighbor are added in. This is slower but should produce better results.
  999. *
  1000. * @param useNormailizedNormalsForAdding the use normailized normals for adding
  1001. */
  1002. public void calcVertexNormals(boolean useNormailizedNormalsForAdding) {
  1003. if (normal.equals(nullVect)){
  1004. throw new RuntimeException("We have to calculate the face normal before calling calcVertexNormals!");
  1005. }
  1006. if (useNormailizedNormalsForAdding){
  1007. //Use normalized normals for all calculations
  1008. //Also checks if normals are attempted to be added that are equal to this faces normal
  1009. //or normals that have already been added -> those are not added
  1010. // /*
  1011. Vector3D normalizedFaceNormal = this.normal.getCopy();
  1012. normalizedFaceNormal.normalizeLocal();
  1013. logger.debug("");
  1014. logger.debug("Face " + index + " normal: " + this.normal + " Normalized: " + normalizedFaceNormal);
  1015. logger.debug("P0:");
  1016. //For each face point, calc vertex normal by adding up all
  1017. //smooth connected neighbors + this faces' normal and normalize in the end
  1018. ArrayList<Vector3D> alreadyAddedInP0 = new ArrayList<Vector3D>();
  1019. // vertexNormalP0 = this.normal.getCopy(); //Init with own faces face normal
  1020. vertexNormalP0 = normalizedFaceNormal.getCopy();
  1021. for (MyFace neighborFaceP0 : smoothNeighborsP0) {
  1022. Vector3D nextSmoothNeighborNormal = neighborFaceP0.normal;
  1023. Vector3D nextSmoothNeighborNormalNormalized = nextSmoothNeighborNormal.getCopy();
  1024. //TODO doch nochmal probieren mit vorher ausgerechneter normal? sonst performance loss!
  1025. nextSmoothNeighborNormalNormalized.normalizeLocal();//neighborFaceP0.normalNormalized;
  1026. boolean alreadyAddedSameNormalIn = false;
  1027. //Dont add faces normals that are equal to this faces normals
  1028. if (!useNormalsEqualToFace && nextSmoothNeighborNormalNormalized.equalsVectorWithTolerance(normalizedFaceNormal, ToolsMath.ZERO_TOLERANCE)) {
  1029. alreadyAddedSameNormalIn = true;
  1030. logger.debug("Not using normal: " + nextSmoothNeighborNormalNormalized + " of face " + neighborFaceP0.index + " in vertex norm calc because its equal to this faces normal.");
  1031. }
  1032. // else //Dont add face normals that are equal to one already added
  1033. // {
  1034. if (!useEqualNeighborNormalsAgain) {
  1035. for (Vector3D neighBorNorm : alreadyAddedInP0) {
  1036. if (neighBorNorm.equalsVectorWithTolerance(nextSmoothNeighborNormalNormalized, ToolsMath.ZERO_TOLERANCE)) {
  1037. alreadyAddedSameNormalIn = true;
  1038. logger.debug("Already added same normal -> dont add again N: " + neighBorNorm);
  1039. }
  1040. }
  1041. }
  1042. // }
  1043. if (!alreadyAddedSameNormalIn) {
  1044. vertexNormalP0.addLocal(nextSmoothNeighborNormalNormalized);
  1045. alreadyAddedInP0.add(nextSmoothNeighborNormalNormalized);
  1046. logger.debug("Added normal: " + nextSmoothNeighborNormalNormalized + " of face: " + neighborFaceP0.index);
  1047. }
  1048. }
  1049. vertexNormalP0.normalizeLocal();
  1050. logger.debug("P1");
  1051. //For each face point, calc vertex normalby adding up all
  1052. //smooth connected neighbors + this faces' normal and normalize in the end
  1053. ArrayList<Vector3D> alreadyAddedInP1 = new ArrayList<Vector3D>();
  1054. // vertexNormalP1 = this.normal.getCopy(); //Init with own faces face normal
  1055. vertexNormalP1 = normalizedFaceNormal.getCopy();
  1056. for (MyFace neighborFaceP1 : smoothNeighborsP1) {
  1057. Vector3D nextSmoothNeighborNormal = neighborFaceP1.normal;
  1058. Vector3D nextSmoothNeighborNormalNormalized = nextSmoothNeighborNormal.getCopy();
  1059. //TODO doch nochmal probieren mit vorher ausgerechneter normal? sonst performance loss!
  1060. nextSmoothNeighborNormalNormalized.normalizeLocal();//neighborFaceP1.normalNormalized;
  1061. boolean alreadyAddedSameNormalIn = false;
  1062. //Dont add faces normals that are equal to this faces normals
  1063. if (!useNormalsEqualToFace && nextSmoothNeighborNormalNormalized.equalsVectorWithTolerance(normalizedFaceNormal, ToolsMath.ZERO_TOLERANCE)) {
  1064. alreadyAddedSameNormalIn = true;
  1065. logger.debug("Not using normal: " + nextSmoothNeighborNormalNormalized + " of face " + neighborFaceP1.index + " in vertex norm calc because its equal to this faces normal.");
  1066. }
  1067. // else //Dont add face normals that are equal to one already added
  1068. // {
  1069. if (!useEqualNeighborNormalsAgain) {
  1070. for (Vector3D neighBorNorm : alreadyAddedInP1) {
  1071. if (neighBorNorm.equalsVectorWithTolerance(nextSmoothNeighborNormalNormalized, ToolsMath.ZERO_TOLERANCE)) {
  1072. alreadyAddedSameNormalIn = true;
  1073. logger.debug("Already added same normal -> dont add again N: " + neighBorNorm);
  1074. }
  1075. }
  1076. }
  1077. // }
  1078. if (!alreadyAddedSameNormalIn) {
  1079. vertexNormalP1.addLocal(nextSmoothNeighborNormalNormalized);
  1080. alreadyAddedInP1.add(nextSmoothNeighborNormalNormalized);
  1081. logger.debug("Added normal: " + nextSmoothNeighborNormalNormalized + " of face: " + neighborFaceP1.index);
  1082. }
  1083. }
  1084. vertexNormalP1.normalizeLocal();
  1085. logger.debug("P2");
  1086. //For each face point, calc vertex normalby adding up all
  1087. //smooth connected neighbors + this faces' normal and normalize in the end
  1088. ArrayList<Vector3D> alreadyAddedInP2 = new ArrayList<Vector3D>();
  1089. // vertexNormalP2 = this.normal.getCopy(); //Init with own faces face normal
  1090. vertexNormalP2 = normalizedFaceNormal.getCopy();
  1091. for (MyFace neighborFaceP2 : smoothNeighborsP2) {
  1092. Vector3D nextSmoothNeighborNormal = neighborFaceP2.normal;
  1093. Vector3D nextSmoothNeighborNormalNormalized = nextSmoothNeighborNormal.getCopy();
  1094. //TODO doch nochmal probieren mit vorher ausgerechneter normal? sonst performance loss!
  1095. nextSmoothNeighborNormalNormalized.normalizeLocal();//neighborFaceP2.normalNormalized;
  1096. boolean alreadyAddedSameNormalIn = false;
  1097. //Dont add faces normals that are equal to this faces normals
  1098. if (!useNormalsEqualToFace && nextSmoothNeighborNormalNormalized.equalsVectorWithTolerance(normalizedFaceNormal, ToolsMath.ZERO_TOLERANCE)) {
  1099. alreadyAddedSameNormalIn = true;
  1100. logger.debug("Not using normal: " + nextSmoothNeighborNormalNormalized + " of face " + neighborFaceP2.index + " in vertex norm calc because its equal to this faces normal.");
  1101. }
  1102. // else //Dont add face normals that are equal to one already added
  1103. // {
  1104. if (!useEqualNeighborNormalsAgain) {
  1105. for (Vector3D neighBorNorm : alreadyAddedInP2) {
  1106. if (neighBorNorm.equalsVectorWithTolerance(nextSmoothNeighborNormalNormalized, ToolsMath.ZERO_TOLERANCE)) {
  1107. alreadyAddedSameNormalIn = true;
  1108. logger.debug("Already added same normal -> dont add again N: " + neighBorNorm);
  1109. }
  1110. }
  1111. }
  1112. // }
  1113. if (!alreadyAddedSameNormalIn) {
  1114. vertexNormalP2.addLocal(nextSmoothNeighborNormalNormalized);
  1115. alreadyAddedInP2.add(nextSmoothNeighborNormalNormalized);
  1116. logger.debug("Added normal: " + nextSmoothNeighborNormalNormalized + " of face: " + neighborFaceP2.index);
  1117. }
  1118. }
  1119. vertexNormalP2.normalizeLocal();
  1120. }else{
  1121. //Just add up all smooth neighbors and normalize after
  1122. //P0 Normal
  1123. vertexNormalP0 = this.normal.getCopy();
  1124. for (MyFace neighborFaceP0 : smoothNeighborsP0) {
  1125. vertexNormalP0.addLocal(neighborFaceP0.normal);
  1126. }
  1127. vertexNormalP0.normalizeLocal();
  1128. //P1 Normal
  1129. vertexNormalP1 = this.normal.getCopy();
  1130. for (MyFace neighborFaceP1 : smoothNeighborsP1) {
  1131. vertexNormalP1.addLocal(neighborFaceP1.normal);
  1132. }
  1133. vertexNormalP1.normalizeLocal();
  1134. vertexNormalP2 = this.normal.getCopy();
  1135. for (MyFace neighborFaceP2 : smoothNeighborsP2) {
  1136. vertexNormalP2.addLocal(neighborFaceP2.normal);
  1137. }
  1138. vertexNormalP2.normalizeLocal();
  1139. }
  1140. logger.debug("Face: " + index + " -> P0 VertexNormal:-> " + vertexNormalP0);
  1141. logger.debug("Face: " + index + " -> P1 VertexNormal:-> " + vertexNormalP1);
  1142. logger.debug("Face: " + index + " -> P2 VertexNormal:-> " + vertexNormalP2);
  1143. logger.debug("");
  1144. vertexNormals = new Vector3D[]{vertexNormalP0,vertexNormalP1,vertexNormalP2};
  1145. }
  1146. /**
  1147. * Gets the vertex normals.
  1148. *
  1149. * @return the vertex normals
  1150. */
  1151. public Vector3D[] getVertexNormals() {
  1152. if (vertexNormals == null){
  1153. throw new RuntimeException("We have to calculate the vertex normals first!");
  1154. }
  1155. return vertexNormals;
  1156. }
  1157. }//End MyFace class
  1158. /**
  1159. * Class to hold information about a mesh vertex.
  1160. *
  1161. * @author C.Ruff
  1162. */
  1163. private class VertexData{
  1164. /** The array index. */
  1165. private int arrayIndex;
  1166. /** The vertex. */
  1167. private Vertex vertex;
  1168. /** The faces. */
  1169. private ArrayList<MyFace> faces;
  1170. /** The duplications with diff tex coords. */
  1171. private ArrayList<VertexData> duplicationsWithDiffTexCoords;
  1172. // private ArrayList<MyFace> smoothNeighbors;
  1173. // private Vector3D vertexNormal;
  1174. // private boolean vertexNormalDirty;
  1175. /** The unique vertex normal. */
  1176. private Vector3D uniqueVertexNormal;
  1177. /** The duplications with diff normal. */
  1178. private ArrayList<VertexData> duplicationsWithDiffNormal;
  1179. //Normal calculated in the getSmoothnormals method
  1180. /** The all neighbors normal. */
  1181. private Vector3D allNeighborsNormal;
  1182. /**
  1183. * Constructor.
  1184. */
  1185. public VertexData() {
  1186. super();
  1187. faces = new ArrayList<MyFace>();
  1188. duplicationsWithDiffTexCoords = new ArrayList<VertexData>();
  1189. duplicationsWithDiffNormal = new ArrayList<VertexData>();
  1190. // smoothNeighbors = new ArrayList<MyFace>();
  1191. arrayIndex = -1;
  1192. allNeighborsNormal = null;
  1193. // vertexNormalDirty = true;
  1194. // vertexNormal = new Vector3D(0,0,0);
  1195. }
  1196. /**
  1197. * Adds and registers the vertex with this vertexdata. The Vertex
  1198. * datas vertex is null at the start and has to be initilazied once here.
  1199. *
  1200. * @param vertex the vertex
  1201. */
  1202. public void setVertex(Vertex vertex){
  1203. this.vertex = vertex;
  1204. }
  1205. /**
  1206. * Gets the vertex.
  1207. *
  1208. * @return the vertex
  1209. *
  1210. * Returns the vertex this vertex data wraps around.
  1211. */
  1212. public Vertex getVertex() {
  1213. return vertex;
  1214. }
  1215. //this is wrong here, the vertex normal when considering a crease angle
  1216. //has to be calculated per face and per face vertex instead of per vertex here
  1217. //alone. Because for one face the same vertex has to be smoothed with different
  1218. //faces than for another face.
  1219. // /**
  1220. // * Tells the VertexData, that the specified face is a neighbor which should
  1221. // * be used to calculate a smooth vertex normal later.
  1222. // *
  1223. // * @param myFace
  1224. // */
  1225. // public void addNewSmoothNeighbor(MyFace myFace){
  1226. // if (! this.smoothNeighbors.contains(myFace)){
  1227. // this.smoothNeighbors.add(myFace);
  1228. // this.vertexNormalDirty = true;
  1229. // }
  1230. // }
  1231. // /**
  1232. // * Calculates and returns the vertexnormal for this vertexdata,
  1233. // * using all the vertexes smooth neighbors and adding them up, then normalizing.
  1234. // * This should be called only after all the smooth neighbors were added.
  1235. // *
  1236. // * @return
  1237. // * the normal
  1238. // */
  1239. // public Vector3D calcVertexNormalSmoothNeighbors() {
  1240. // if (vertexNormalDirty){
  1241. // vertexNormal = new Vector3D(0,0,0);
  1242. //
  1243. // //Add up face normals of smooth neighbors
  1244. // for (int i = 0; i < smoothNeighbors.size(); i++) {
  1245. // MyFace smoothNeighbor = smoothNeighbors.get(i);
  1246. // vertexNormal.addLocal(smoothNeighbor.normal);
  1247. // }
  1248. // //Normalize in the end
  1249. // vertexNormal.normalizeLocal();
  1250. // vertexNormalDirty = false;
  1251. // return vertexNormal;
  1252. // }else{
  1253. // return vertexNormal;
  1254. // }
  1255. // }
  1256. // /**
  1257. // * @return
  1258. // * whether the vertexdata has smooth neighbors
  1259. // */
  1260. // public boolean hasSmoothNeighborFaces(){
  1261. // return !this.smoothNeighbors.isEmpty();
  1262. // }
  1263. /**
  1264. * Add and register the specified neighbor for this vertexdata.
  1265. * This also adds the face to the duplicates registered (added) with this vertexdata
  1266. * with different tex coords but same vertex pointer.
  1267. *
  1268. * @param face the face
  1269. */
  1270. public void addNeighborFace(MyFace face){
  1271. if (!faces.contains(face))
  1272. faces.add(face);
  1273. //Auch duplicates face hinzuf?gen, da sie ja den gleichen vertex sharen
  1274. //und f?r die normalenberechnung alle neighborfaces brauchen
  1275. for (VertexData vdDuplicate : this.getDuplicateVertexWithDiffTexCoordsList()){
  1276. vdDuplicate.addNeighborFace(face);
  1277. }
  1278. }
  1279. /**
  1280. * Add and register the specified neighbors for this vertexdata and ints duplicates
  1281. * with different tex coords but same vertex pointer.
  1282. *
  1283. * @param addFaces the add faces
  1284. */
  1285. public void addNeighborFaces(ArrayList<MyFace> addFaces){
  1286. for (MyFace currFace: addFaces){
  1287. if (!faces.contains(currFace)){
  1288. faces.add(currFace);
  1289. }
  1290. }
  1291. //Auch duplicates faces hinzuf?gen, da sie ja den gleichen vertex sharen
  1292. //und f?r die normalenberechnung alle neighborfaces brauchen
  1293. for (VertexData vdDuplicate : this.getDuplicateVertexWithDiffTexCoordsList()){
  1294. vdDuplicate.addNeighborFaces(addFaces);
  1295. }
  1296. }
  1297. /**
  1298. * Gets the neighbor faces.
  1299. *
  1300. * @return the neighbor faces
  1301. *
  1302. * All neighbors of this vertex, so all faces this vertex is a part of
  1303. */
  1304. public ArrayList<MyFace> getNeighborFaces(){
  1305. return this.faces;
  1306. }
  1307. /**
  1308. * Calculates and returns the vertex normal considering
  1309. * _all_ the vertexes neighbors (smooth or not!). Results
  1310. * in an all smoothed model.
  1311. *
  1312. * @return the vector3 d
  1313. *
  1314. * the resulting vertex normal
  1315. */
  1316. public Vector3D calcVertexNormalAllNeighbors(){
  1317. if (allNeighborsNormal == null ){
  1318. //Add up face normals of smooth neighbors
  1319. Vector3D allNeighborNormal = new Vector3D(0,0,0);
  1320. for (MyFace neighbor : faces) {
  1321. allNeighborNormal.addLocal(neighbor.normal);
  1322. logger.debug("Vertex index:" + this.getArrayIndex() + " calcing in neighbor normal of face: " + neighbor.index);
  1323. }
  1324. //Normalize in the end
  1325. allNeighborNormal.normalizeLocal();
  1326. allNeighborsNormal = allNeighborNormal;
  1327. return allNeighborsNormal;
  1328. }else{
  1329. return allNeighborsNormal;
  1330. }
  1331. }
  1332. ///////////// Handle vertices with same vertex but different texture coordinates
  1333. /**
  1334. * Returns the index of the already created duplicate with the same vertex and texture
  1335. * information we are checking with, or "-1" if no duplicate with that information exists.
  1336. * Then we have to create a new duplicate and register it to this Vertex Data's duplicate list.
  1337. *
  1338. * @param vertex the vertex
  1339. *
  1340. * @return the vert duplicate same vert diff texture coord list index
  1341. *
  1342. * the index of the dupicate with the same tex coords or -1 if there is none
  1343. */
  1344. public int getVertDuplicateSameVertDiffTextureCoordListIndex(Vertex vertex){
  1345. //Go through list of all duplicates
  1346. for (VertexData possibleDuplicate : duplicationsWithDiffTexCoords) {
  1347. if (possibleDuplicate.equalsVertex(vertex)) {
  1348. return possibleDuplicate.getArrayIndex();
  1349. }
  1350. }
  1351. return -1;
  1352. }
  1353. /**
  1354. * Checks if the vertex with the same coordinates and texture coordinates was already added
  1355. * to this vertexData.
  1356. *
  1357. * @param vertex the vertex
  1358. *
  1359. * @return true, if equals vertex
  1360. */
  1361. private boolean equalsVertex(Vertex vertex){
  1362. return this.vertex.equalsVector(vertex);
  1363. }//contains()
  1364. /**
  1365. * Tell the vertexdata obj, that we have created a duplicate and saved it.
  1366. *
  1367. * @param vd the vd
  1368. */
  1369. public void registerCreatedDuplicateDiffTexCoords(VertexData vd){
  1370. this.duplicationsWithDiffTexCoords.add(vd);
  1371. }
  1372. /**
  1373. * Gets the duplicate vertex with diff tex coords list.
  1374. *
  1375. * @return the duplicate vertex with diff tex coords list
  1376. */
  1377. private ArrayList<VertexData> getDuplicateVertexWithDiffTexCoordsList(){
  1378. return this.duplicationsWithDiffTexCoords;
  1379. }
  1380. ///////////// Handle vertices with same vertex but different texture coordinates
  1381. ///////////// Handle vertices with same vertex but different Vertex normal // This is only relevant if a crease angle is used!
  1382. /**
  1383. * Returns the vertex normal that has been calculated and set
  1384. * with a crease angle for a group of faces for which this normal
  1385. * is the same.
  1386. *
  1387. * @return the unique vertex normal
  1388. */
  1389. public Vector3D getUniqueVertexNormal(){
  1390. return uniqueVertexNormal;
  1391. }
  1392. /**
  1393. * Sets the vertex normal for this vertex(data). In the crease angle
  1394. * calculation process. May only set it once. Different normals belonging
  1395. * to the same vertex have to be put in another vertex data object!
  1396. * The vertex normal is calculated in the faces and then set here.
  1397. *
  1398. * @param newVertexNormal the new vertex normal
  1399. */
  1400. public void setUniqueVertexNormal(Vector3D newVertexNormal) {
  1401. this.uniqueVertexNormal = newVertexNormal;
  1402. }
  1403. /**
  1404. * The crease angle cal process tell this vertex data that it created another vertex data
  1405. * because in this one, the vertex is the same but the normal differs -> duplicate the vertex!.
  1406. *
  1407. * @param vdWithDiffNormal the vd with diff normal
  1408. */
  1409. public void registerCreatedDuplicateDiffNormal(VertexData vdWithDiffNormal) {
  1410. this.duplicationsWithDiffNormal.add(vdWithDiffNormal);
  1411. }
  1412. /**
  1413. * Asks the vertex data if a duplicate of itself with a different normal was created and registered as a duplicate.
  1414. * <br>If there is a duplicate already registered with the same normal to be checked with, we get the index of that duplicate
  1415. * in the overall vertex data list and can point the face to the duplicate so we dont have to create another vertexdata.
  1416. * <br>It is assumed that the normal we are checking against belongs to a vertex with the same values as this Vertex datas vertex!
  1417. *
  1418. * @param normalToCheckWith the normal to check with
  1419. *
  1420. * @return the vert duplicate same vert diff normal list index
  1421. *
  1422. * the index of the duplicate or -1 if there is none
  1423. */
  1424. public int getVertDuplicateSameVertDiffNormalListIndex(Vector3D normalToCheckWith) {
  1425. // Go through list of all duplicates
  1426. for (VertexData possibleDuplicate : duplicationsWithDiffNormal) {
  1427. if (possibleDuplicate.getUniqueVertexNormal().equalsVectorWithTolerance(normalToCheckWith, ToolsMath.ZERO_TOLERANCE)) {
  1428. return possibleDuplicate.getArrayIndex();
  1429. }
  1430. }
  1431. return -1;
  1432. }
  1433. ///////////// Handle vertices with same vertex but different Vertex normal
  1434. /**
  1435. * Tell the vertexdata which index its at in a list of vertexdatas for example.
  1436. *
  1437. * @param i the i
  1438. */
  1439. public void setArrayIndex(int i){
  1440. this.arrayIndex = i;
  1441. }
  1442. /**
  1443. * Gets the array index.
  1444. *
  1445. * @return the array index
  1446. *
  1447. * returns the index, the vertexData is at in the overall vertex data list.
  1448. * ->This has to be set manually by calling <code>setArrayIndex</code> first
  1449. */
  1450. public int getArrayIndex(){
  1451. return this.arrayIndex;
  1452. }
  1453. /**
  1454. * Gets the faces contained in.
  1455. *
  1456. * @return the faces contained in
  1457. *
  1458. * a list of faces, this vertex(-data) is a part of (all its neighbors)
  1459. * NOTE: not at all stages of the algorithm returns all real neighbors. Some may be deleted already.
  1460. */
  1461. public ArrayList<MyFace> getFacesContainedIn(){
  1462. return this.faces;
  1463. }
  1464. }//Vertexdata class
  1465. /*----------------------------------------------------------------------------*/
  1466. }