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