]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.opencascade.jme/src/org/simantics/opencascade/jme/JmeOCCTTool.java
Remove dependencies on log4j
[simantics/3d.git] / org.simantics.opencascade.jme / src / org / simantics / opencascade / jme / JmeOCCTTool.java
1 /*******************************************************************************\r
2  * Copyright (c) 2012, 2013 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.opencascade.jme;\r
13 \r
14 import java.nio.FloatBuffer;\r
15 import java.util.ArrayList;\r
16 import java.util.HashMap;\r
17 import java.util.List;\r
18 import java.util.Map;\r
19 \r
20 import javax.vecmath.Matrix4d;\r
21 import javax.vecmath.Point3d;\r
22 import javax.vecmath.Vector3d;\r
23 import javax.vecmath.Vector3f;\r
24 \r
25 import org.jcae.opencascade.jni.BRepMesh_IncrementalMesh;\r
26 import org.jcae.opencascade.jni.BRep_Tool;\r
27 import org.jcae.opencascade.jni.GP_Trsf;\r
28 import org.jcae.opencascade.jni.Poly_Triangulation;\r
29 import org.jcae.opencascade.jni.TopAbs_Orientation;\r
30 import org.jcae.opencascade.jni.TopAbs_ShapeEnum;\r
31 import org.jcae.opencascade.jni.TopExp_Explorer;\r
32 import org.jcae.opencascade.jni.TopLoc_Location;\r
33 import org.jcae.opencascade.jni.TopoDS_Face;\r
34 import org.jcae.opencascade.jni.TopoDS_Shape;\r
35 import org.simantics.opencascade.OCCTTool;\r
36 import org.simantics.utils.datastructures.MapList;\r
37 \r
38 import com.jme3.scene.Geometry;\r
39 import com.jme3.scene.Mesh;\r
40 import com.jme3.scene.Mesh.Mode;\r
41 import com.jme3.scene.Node;\r
42 import com.jme3.scene.Spatial;\r
43 import com.jme3.scene.VertexBuffer.Type;\r
44 import com.jme3.scene.mesh.IndexBuffer;\r
45 \r
46 \r
47 \r
48 public class JmeOCCTTool {\r
49 \r
50         \r
51         public static Spatial vtkOCCShapeToAssembly(TopoDS_Shape shape) {\r
52                 double deflection = 0.001;\r
53 \r
54                 if (deflection <= 0.0) {\r
55                         deflection = 0.0005;\r
56                         System.out.println("Bad value for deflection. Using: " + deflection);\r
57                 }\r
58 \r
59                 // FIXME : leaks memory!\r
60                 //BRepTools.clean(shape);\r
61 \r
62                 double mass = OCCTTool.getMass(shape);\r
63 \r
64                 if (mass < 1.0e-12) {\r
65                         System.out.println("Non 3D-shape detected");\r
66                         System.out.println("The cad import features are currently limited to 3D models.");\r
67                 }\r
68 \r
69                 double length = OCCTTool.getBoundingBoxDiagonal(shape);\r
70                 deflection *= length; // use relative units\r
71 \r
72                 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection);\r
73 \r
74                 int faceNumber = 0;\r
75                 TopExp_Explorer expFace = new TopExp_Explorer();\r
76 \r
77                 Node node = new Node();\r
78                 for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {\r
79                         TopoDS_Face face = (TopoDS_Face) expFace.current();\r
80                         Mesh partGrid = createPartGrid(face);\r
81                         face.delete();\r
82                         if (partGrid == null)\r
83                                 continue;\r
84                         faceNumber++;\r
85                         //gridToAssembly(assemblies, partGrid, stlSurfaceData, stlEdgeData);\r
86                         gridToAssembly(node, partGrid);\r
87                         \r
88                 }\r
89                 expFace.delete();\r
90                 mesh.delete();\r
91 \r
92                 if (faceNumber == 0) {\r
93                         System.out\r
94                                         .println("Cad import: error: no surface triangulation was generated.");\r
95                         return null;\r
96                 }\r
97 \r
98                 return node;\r
99         }\r
100         \r
101 \r
102 \r
103         public static void gridToAssembly(Node assemblies, Mesh partGrid) {\r
104                 Geometry geom = new Geometry();\r
105                 geom.setMesh(partGrid);\r
106                 assemblies.attachChild(geom);\r
107             \r
108         }\r
109         \r
110         \r
111         \r
112         public static Mesh createPartGrid ( TopoDS_Face face)\r
113     {\r
114         TopLoc_Location Location = new TopLoc_Location();\r
115         \r
116         Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);\r
117 \r
118         if(triangulation == null) {\r
119                 Location.delete();\r
120                 System.out.println("Encountered empty triangulation after face");\r
121                 return null;\r
122         }\r
123                 \r
124         boolean reverse = face.orientation()==TopAbs_Orientation.REVERSED;\r
125 \r
126         int[]triangles = triangulation.triangles();\r
127         double[]nodes = triangulation.nodes();\r
128 \r
129         int nofTriangles = triangulation.nbTriangles();\r
130         int nofNodes = triangulation.nbNodes();\r
131         \r
132         triangulation.delete();\r
133 \r
134         if(nofTriangles < 1) {\r
135           System.out.println("No triangles for mesh on face");\r
136           Location.delete();\r
137           return null;\r
138         }\r
139 \r
140         if(nofNodes < 1) {\r
141             System.out.println("No nodes for mesh on face:");\r
142             Location.delete();\r
143             return null;\r
144         }\r
145         \r
146         Mesh mesh = new Mesh();\r
147       \r
148         int index[] = new int[nofTriangles*3];\r
149         \r
150         for(int i = 0; i < nofTriangles; i++) \r
151         {\r
152           int n0, n1, n2;          \r
153           if (!reverse) {\r
154                   n0 = triangles[3 * i];\r
155                   n1 = triangles[3 * i + 1];\r
156                   n2 = triangles[3 * i + 2];\r
157           } else {\r
158                   n0 = triangles[3 * i + 2];\r
159                   n1 = triangles[3 * i + 1];\r
160                   n2 = triangles[3 * i];\r
161           }\r
162 \r
163 \r
164           index[i*3] = n0;\r
165           index[i*3+1] = n1;\r
166           index[i*3+2] = n2;\r
167           \r
168         }\r
169        \r
170         \r
171         GP_Trsf transformation = Location.transformation();\r
172         Location.delete();\r
173 \r
174         double d_mat[] = new double[16];\r
175         transformation.getValues(d_mat);\r
176         \r
177         Matrix4d mat = new Matrix4d(d_mat);\r
178         \r
179         float vertex[] = new float[nofNodes*3];\r
180         \r
181         for(int i = 0; i < nofNodes; i++) {     \r
182           // FIXME: GP_Trsf.transform(double[]) leaks memory\r
183                 \r
184           //double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]};          \r
185           //transformation.transforms(xyz);\r
186           //partPoints.InsertPoint(i, xyz);\r
187                 Point3d p = new Point3d(nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]);\r
188                 mat.transform(p);\r
189                 vertex[3 * i] = (float)p.x;\r
190                 vertex[3 * i+1] = (float)p.y;\r
191                 vertex[3 * i+2] = (float)p.z;\r
192         }\r
193         \r
194         transformation.delete();\r
195         \r
196         mesh.setBuffer(Type.Position, 3, vertex);\r
197         mesh.setBuffer(Type.Index, 3, index);\r
198         return mesh;\r
199     \r
200     }\r
201         \r
202         \r
203         \r
204         public static Mesh createPartGrid ( List<Double> meshPoints, List<Integer> meshTriangles)\r
205     {\r
206        \r
207                 \r
208       \r
209 \r
210         \r
211         int nofTriangles = meshTriangles.size() / 3;\r
212         int nofNodes = meshPoints.size() /3;\r
213         \r
214       \r
215         if(nofTriangles < 1) {\r
216           System.out.println("No triangles for mesh on face");\r
217           return null;\r
218         }\r
219 \r
220         if(nofNodes < 1) {\r
221             System.out.println("No nodes for mesh on face:");\r
222             return null;\r
223         }\r
224         Mesh mesh = new Mesh();\r
225         //System.out.println("v " + nofNodes + " t " +nofTriangles);\r
226         int index[] = new int[nofTriangles*3];\r
227         \r
228         for(int i = 0; i < nofTriangles; i++) \r
229         {\r
230           int n0, n1, n2;          \r
231           n0 = meshTriangles.get(3 * i); \r
232           n1 = meshTriangles.get(3 * i + 1);\r
233           n2 = meshTriangles.get(3 * i + 2); \r
234 \r
235           index[i * 3 ] = n0;\r
236           index[i * 3 + 1] = n1;\r
237           index[i * 3 + 2] = n2;\r
238           \r
239         }\r
240 \r
241         float vertex[] = new float[nofNodes*3];\r
242        \r
243         for(int i = 0; i < nofNodes; i++) {     \r
244 \r
245                 \r
246                 vertex[3 * i] = meshPoints.get(3*i).floatValue();\r
247                 vertex[3 * i+1] = meshPoints.get(3*i+1).floatValue();\r
248                 vertex[3 * i+2] = meshPoints.get(3*i+2).floatValue();\r
249                 \r
250         }\r
251         float normal[] = calcNormals(vertex, index);\r
252         \r
253         \r
254         mesh.setBuffer(Type.Position, 3, vertex);\r
255         mesh.setBuffer(Type.Normal, 3, normal);\r
256         mesh.setBuffer(Type.Index, 3, index);\r
257         \r
258         return mesh;\r
259     }\r
260         \r
261         private static float[] calcNormals(float[] fnodes, int[] trias) {\r
262         float nnodes[] = new float[fnodes.length];\r
263         for (int i = 0; i < nnodes.length; i++) nnodes[i] = 0.f;\r
264         Vector3f v1 = new Vector3f();\r
265         Vector3f v2 = new Vector3f();\r
266         Vector3f v3 = new Vector3f();\r
267         Vector3f t1 = new Vector3f();\r
268         Vector3f t2 = new Vector3f();\r
269         Vector3f n = new Vector3f();\r
270         for (int i = 0; i < trias.length; i+=3) {\r
271             v1.x = fnodes[trias[i]*3];\r
272             v1.y = fnodes[trias[i]*3+1];\r
273             v1.z = fnodes[trias[i]*3+2];\r
274             v2.x = fnodes[trias[i+1]*3];\r
275             v2.y = fnodes[trias[i+1]*3+1];\r
276             v2.z = fnodes[trias[i+1]*3+2];\r
277             v3.x = fnodes[trias[i+2]*3];\r
278             v3.y = fnodes[trias[i+2]*3+1];\r
279             v3.z = fnodes[trias[i+2]*3+2];\r
280             t1.sub(v3,v1);\r
281             t2.sub(v2,v1);\r
282             n.cross(t2, t1);\r
283             //n.normalize();\r
284             nnodes[trias[i]*3] += n.x;\r
285             nnodes[trias[i]*3+1] += n.y;\r
286             nnodes[trias[i]*3+2] += n.z;\r
287             nnodes[trias[i+1]*3] += n.x;\r
288             nnodes[trias[i+1]*3+1] += n.y;\r
289             nnodes[trias[i+1]*3+2] += n.z;\r
290             nnodes[trias[i+2]*3] += n.x;\r
291             nnodes[trias[i+2]*3+1] += n.y;\r
292             nnodes[trias[i+2]*3+2] += n.z;\r
293         }\r
294         for (int i = 0; i < nnodes.length; i+=3) {\r
295             n.x = nnodes[i];\r
296             n.y = nnodes[i+1];\r
297             n.z = nnodes[i+2];\r
298             n.normalize();\r
299             nnodes[i] = n.x;\r
300             nnodes[i+1] = n.y;\r
301             nnodes[i+2] = n.z;\r
302         }\r
303         return nnodes;\r
304     }\r
305         \r
306         public static Mesh createEdgeMesh(Mesh triMesh) {\r
307 \r
308                 // list all edges in the mesh\r
309                 MapList<Integer, Integer> triEdgeIndices = new MapList<Integer, Integer>();\r
310                 for (int i = 0; i < triMesh.getTriangleCount(); i++) {\r
311                         int[] tri = new int[3];\r
312                         triMesh.getTriangle(i, tri);\r
313 \r
314                         if (!triEdgeIndices.contains(tri[0], tri[1])) {\r
315                                 triEdgeIndices.add(tri[0], tri[1]);\r
316                         }\r
317                         if (!triEdgeIndices.contains(tri[1], tri[2])) {\r
318                                 triEdgeIndices.add(tri[1], tri[2]);\r
319                         }\r
320                         if (!triEdgeIndices.contains(tri[2], tri[0])) {\r
321                                 triEdgeIndices.add(tri[2], tri[0]);\r
322                         }        \r
323                 }\r
324                 // find, which edges are listed only once; those are boundaries of the mesh.\r
325                 MapList<Integer, Integer> edgeIndices = new MapList<Integer, Integer>();\r
326                 for (int s : triEdgeIndices.getKeys()) {\r
327                         for (int e : triEdgeIndices.getValues(s)) {\r
328                                 if (!triEdgeIndices.contains(e, s)) {\r
329                                         edgeIndices.add(s,e);\r
330                                         edgeIndices.add(e,s);\r
331                                 }\r
332                         }\r
333                 }\r
334                 \r
335                 // create a new mesh, containing boundary vertices and edges of the original mesh.\r
336                 \r
337                 // create list of edge vertices in the original mesh\r
338                 List<Integer> vertices = new ArrayList<Integer>();\r
339                 FloatBuffer data = triMesh.getFloatBuffer(Type.Position);\r
340                 for (Integer i : edgeIndices.getKeys()) {\r
341                         List<Integer> edges = edgeIndices.getValues(i);\r
342                         if (!vertices.contains(i))\r
343                                 vertices.add(i);\r
344                         if (!vertices.contains(edges.get(0)))\r
345                                 vertices.add(edges.get(0));\r
346                         if (!vertices.contains(edges.get(1)))\r
347                                 vertices.add(edges.get(1));\r
348 \r
349                 }\r
350                 // create vertices for edge mesh, and map new vertices to orignals.\r
351                 float vertex[] = new float[vertices.size() * 3];\r
352                 int i2 = 0;\r
353                 Map<Integer,Integer> indexMap = new HashMap<Integer, Integer>();\r
354                 for (int i : vertices) {\r
355                         vertex[i2*3] = data.get(i*3);\r
356                         vertex[i2*3+1] = data.get(i*3+1);\r
357                         vertex[i2*3+2] = data.get(i*3+2);\r
358                         \r
359                         indexMap.put(i, i2);\r
360                         i2++;\r
361                         \r
362                 }\r
363                 \r
364                 // create line indices for the edge mesh.\r
365                 List<Integer> indices = new ArrayList<Integer>();\r
366 \r
367                 for (int i = 0; i < vertices.size(); i++) {\r
368                         int s = vertices.get(i);\r
369                         List<Integer> edges = edgeIndices.getValues(s);\r
370                         for (int e : edges) {\r
371                                 if (edgeIndices.contains(s, e) && indexMap.containsKey(s) && indexMap.containsKey(e)) {\r
372                                         indices.add(indexMap.get(s));\r
373                                         indices.add(indexMap.get(e));\r
374                                 }\r
375                         }\r
376                         \r
377                 }\r
378                 \r
379                 int index[] = new int[indices.size()];\r
380                 for (int i = 0; i < indices.size(); i++) {\r
381                         index[i] = indices.get(i);\r
382                 }\r
383                 \r
384                 Mesh mesh = new Mesh();\r
385                 mesh.setMode(Mode.Lines);\r
386                 mesh.setBuffer(Type.Position, 3, vertex);\r
387                 mesh.setBuffer(Type.Index, 2, index);\r
388                 \r
389                 return mesh;\r
390         }\r
391         \r
392         public static Mesh createVertexMesh(Mesh edgeMesh) {\r
393 \r
394                 MapList<Integer, Integer> edgeIndices = new MapList<Integer, Integer>();\r
395                 IndexBuffer indices = edgeMesh.getIndexBuffer();\r
396                 for (int i = 0; i < indices.size(); i+=2) {\r
397                         int s = indices.get(i);\r
398                         int e = indices.get(i+1);\r
399 \r
400                         if (!edgeIndices.contains(s, e)) {\r
401                                 edgeIndices.add(s, e);\r
402                                 edgeIndices.add(e, s);\r
403                         }\r
404                                  \r
405                 }\r
406                                 \r
407                 List<Integer> vertices = new ArrayList<Integer>();\r
408                 float data[] = edgeMesh.getFloatBuffer(Type.Position).array();\r
409                 for (Integer i : edgeIndices.getKeys()) {\r
410                         List<Integer> edges = edgeIndices.getValues(i);\r
411                         if (edges.size() != 2)\r
412                                 vertices.add(i);\r
413                         else {\r
414                                 Point3d t = new Point3d(data[i*3],data[i*3+1],data[i*3+2]);\r
415                                 Vector3d v1 = new Vector3d(data[edges.get(0)*3],data[edges.get(0)*3+1],data[edges.get(0)*3+2]);\r
416                                 Vector3d v2 = new Vector3d(data[edges.get(1)*3],data[edges.get(1)*3+1],data[edges.get(1)*3+2]);\r
417                                 \r
418                                 v1.sub(t);\r
419                                 v2.sub(t);\r
420                                 double angle = Math.PI - v1.angle(v2);\r
421                                 if (angle > Math.PI/6)\r
422                                         vertices.add(i);\r
423                         }\r
424                 }\r
425                 \r
426                 float vertex[] = new float[vertices.size() * 3];\r
427                 int i2 = 0;\r
428                 Map<Integer,Integer> indexMap = new HashMap<Integer, Integer>();\r
429                 for (int i : vertices) {\r
430                         vertex[i2*3] = data[i*3];\r
431                         vertex[i2*3+1] = data[i*3+1];\r
432                         vertex[i2*3+2] = data[i*3+2];\r
433                         \r
434                         indexMap.put(i, i2);\r
435                         i2++;\r
436                         \r
437                 }\r
438                 \r
439                 int index[] = new int[vertices.size()];\r
440                 for (int i = 0; i < vertices.size(); i++) {\r
441                         index[i] = i;\r
442                 }\r
443                 \r
444                 Mesh mesh = new Mesh();\r
445                 mesh.setMode(Mode.Points);\r
446                 mesh.setBuffer(Type.Position, 3, vertex);\r
447                 mesh.setBuffer(Type.Index, 1, index);\r
448                 \r
449                 return mesh;\r
450         }\r
451         \r
452 }\r