]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - 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
diff --git a/org.simantics.opencascade.jme/src/org/simantics/opencascade/jme/JmeOCCTTool.java b/org.simantics.opencascade.jme/src/org/simantics/opencascade/jme/JmeOCCTTool.java
new file mode 100644 (file)
index 0000000..0184477
--- /dev/null
@@ -0,0 +1,441 @@
+package org.simantics.opencascade.jme;\r
+\r
+import java.nio.FloatBuffer;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+import javax.vecmath.Vector3f;\r
+\r
+import org.jcae.opencascade.jni.BRepMesh_IncrementalMesh;\r
+import org.jcae.opencascade.jni.BRep_Tool;\r
+import org.jcae.opencascade.jni.GP_Trsf;\r
+import org.jcae.opencascade.jni.Poly_Triangulation;\r
+import org.jcae.opencascade.jni.TopAbs_Orientation;\r
+import org.jcae.opencascade.jni.TopAbs_ShapeEnum;\r
+import org.jcae.opencascade.jni.TopExp_Explorer;\r
+import org.jcae.opencascade.jni.TopLoc_Location;\r
+import org.jcae.opencascade.jni.TopoDS_Face;\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.opencascade.OCCTTool;\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+import com.jme3.scene.Geometry;\r
+import com.jme3.scene.Mesh;\r
+import com.jme3.scene.Mesh.Mode;\r
+import com.jme3.scene.Node;\r
+import com.jme3.scene.Spatial;\r
+import com.jme3.scene.VertexBuffer.Type;\r
+import com.jme3.scene.mesh.IndexBuffer;\r
+\r
+\r
+\r
+public class JmeOCCTTool {\r
+\r
+       \r
+       public static Spatial vtkOCCShapeToAssembly(TopoDS_Shape shape) {\r
+               double deflection = 0.001;\r
+\r
+               if (deflection <= 0.0) {\r
+                       deflection = 0.0005;\r
+                       System.out.println("Bad value for deflection. Using: " + deflection);\r
+               }\r
+\r
+               // FIXME : leaks memory!\r
+               //BRepTools.clean(shape);\r
+\r
+               double mass = OCCTTool.getMass(shape);\r
+\r
+               if (mass < 1.0e-12) {\r
+                       System.out.println("Non 3D-shape detected");\r
+                       System.out.println("The cad import features are currently limited to 3D models.");\r
+               }\r
+\r
+               double length = OCCTTool.getBoundingBoxDiagonal(shape);\r
+               deflection *= length; // use relative units\r
+\r
+               BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection);\r
+\r
+               int faceNumber = 0;\r
+               TopExp_Explorer expFace = new TopExp_Explorer();\r
+\r
+               Node node = new Node();\r
+               for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {\r
+                       TopoDS_Face face = (TopoDS_Face) expFace.current();\r
+                       Mesh partGrid = createPartGrid(face);\r
+                       face.delete();\r
+                       if (partGrid == null)\r
+                               continue;\r
+                       faceNumber++;\r
+                       //gridToAssembly(assemblies, partGrid, stlSurfaceData, stlEdgeData);\r
+                       gridToAssembly(node, partGrid);\r
+                       \r
+               }\r
+               expFace.delete();\r
+               mesh.delete();\r
+\r
+               if (faceNumber == 0) {\r
+                       System.out\r
+                                       .println("Cad import: error: no surface triangulation was generated.");\r
+                       return null;\r
+               }\r
+\r
+               return node;\r
+       }\r
+       \r
+\r
+\r
+       public static void gridToAssembly(Node assemblies, Mesh partGrid) {\r
+               Geometry geom = new Geometry();\r
+               geom.setMesh(partGrid);\r
+               assemblies.attachChild(geom);\r
+           \r
+       }\r
+       \r
+       \r
+       \r
+       public static Mesh createPartGrid ( TopoDS_Face face)\r
+    {\r
+        TopLoc_Location Location = new TopLoc_Location();\r
+        \r
+        Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);\r
+\r
+        if(triangulation == null) {\r
+               Location.delete();\r
+               System.out.println("Encountered empty triangulation after face");\r
+               return null;\r
+        }\r
+                \r
+        boolean reverse = face.orientation()==TopAbs_Orientation.REVERSED;\r
+\r
+        int[]triangles = triangulation.triangles();\r
+        double[]nodes = triangulation.nodes();\r
+\r
+        int nofTriangles = triangulation.nbTriangles();\r
+        int nofNodes = triangulation.nbNodes();\r
+        \r
+        triangulation.delete();\r
+\r
+        if(nofTriangles < 1) {\r
+          System.out.println("No triangles for mesh on face");\r
+          Location.delete();\r
+          return null;\r
+        }\r
+\r
+        if(nofNodes < 1) {\r
+            System.out.println("No nodes for mesh on face:");\r
+            Location.delete();\r
+            return null;\r
+        }\r
+        \r
+        Mesh mesh = new Mesh();\r
+      \r
+        int index[] = new int[nofTriangles*3];\r
+        \r
+        for(int i = 0; i < nofTriangles; i++) \r
+        {\r
+          int n0, n1, n2;          \r
+          if (!reverse) {\r
+                 n0 = triangles[3 * i];\r
+                 n1 = triangles[3 * i + 1];\r
+                 n2 = triangles[3 * i + 2];\r
+          } else {\r
+                 n0 = triangles[3 * i + 2];\r
+                 n1 = triangles[3 * i + 1];\r
+                 n2 = triangles[3 * i];\r
+          }\r
+\r
+\r
+          index[i*3] = n0;\r
+          index[i*3+1] = n1;\r
+          index[i*3+2] = n2;\r
+          \r
+        }\r
+       \r
+        \r
+        GP_Trsf transformation = Location.transformation();\r
+        Location.delete();\r
+\r
+        double d_mat[] = new double[16];\r
+        transformation.getValues(d_mat);\r
+        \r
+        Matrix4d mat = new Matrix4d(d_mat);\r
+        \r
+        float vertex[] = new float[nofNodes*3];\r
+        \r
+        for(int i = 0; i < nofNodes; i++) {     \r
+          // FIXME: GP_Trsf.transform(double[]) leaks memory\r
+               \r
+          //double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]};          \r
+          //transformation.transforms(xyz);\r
+          //partPoints.InsertPoint(i, xyz);\r
+               Point3d p = new Point3d(nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]);\r
+               mat.transform(p);\r
+               vertex[3 * i] = (float)p.x;\r
+               vertex[3 * i+1] = (float)p.y;\r
+               vertex[3 * i+2] = (float)p.z;\r
+        }\r
+        \r
+        transformation.delete();\r
+        \r
+        mesh.setBuffer(Type.Position, 3, vertex);\r
+        mesh.setBuffer(Type.Index, 3, index);\r
+        return mesh;\r
+    \r
+    }\r
+       \r
+       \r
+       \r
+       public static Mesh createPartGrid ( List<Double> meshPoints, List<Integer> meshTriangles)\r
+    {\r
+       \r
+                \r
+      \r
+\r
+        \r
+        int nofTriangles = meshTriangles.size() / 3;\r
+        int nofNodes = meshPoints.size() /3;\r
+        \r
+      \r
+        if(nofTriangles < 1) {\r
+          System.out.println("No triangles for mesh on face");\r
+          return null;\r
+        }\r
+\r
+        if(nofNodes < 1) {\r
+            System.out.println("No nodes for mesh on face:");\r
+            return null;\r
+        }\r
+        Mesh mesh = new Mesh();\r
+        //System.out.println("v " + nofNodes + " t " +nofTriangles);\r
+        int index[] = new int[nofTriangles*3];\r
+        \r
+        for(int i = 0; i < nofTriangles; i++) \r
+        {\r
+          int n0, n1, n2;          \r
+          n0 = meshTriangles.get(3 * i); \r
+          n1 = meshTriangles.get(3 * i + 1);\r
+          n2 = meshTriangles.get(3 * i + 2); \r
+\r
+          index[i * 3 ] = n0;\r
+          index[i * 3 + 1] = n1;\r
+          index[i * 3 + 2] = n2;\r
+          \r
+        }\r
+\r
+        float vertex[] = new float[nofNodes*3];\r
+       \r
+        for(int i = 0; i < nofNodes; i++) {     \r
+\r
+               \r
+               vertex[3 * i] = meshPoints.get(3*i).floatValue();\r
+               vertex[3 * i+1] = meshPoints.get(3*i+1).floatValue();\r
+               vertex[3 * i+2] = meshPoints.get(3*i+2).floatValue();\r
+               \r
+        }\r
+        float normal[] = calcNormals(vertex, index);\r
+        \r
+        \r
+        mesh.setBuffer(Type.Position, 3, vertex);\r
+        mesh.setBuffer(Type.Normal, 3, normal);\r
+        mesh.setBuffer(Type.Index, 3, index);\r
+        \r
+        return mesh;\r
+    }\r
+       \r
+       private static float[] calcNormals(float[] fnodes, int[] trias) {\r
+        float nnodes[] = new float[fnodes.length];\r
+        for (int i = 0; i < nnodes.length; i++) nnodes[i] = 0.f;\r
+        Vector3f v1 = new Vector3f();\r
+        Vector3f v2 = new Vector3f();\r
+        Vector3f v3 = new Vector3f();\r
+        Vector3f t1 = new Vector3f();\r
+        Vector3f t2 = new Vector3f();\r
+        Vector3f n = new Vector3f();\r
+        for (int i = 0; i < trias.length; i+=3) {\r
+            v1.x = fnodes[trias[i]*3];\r
+            v1.y = fnodes[trias[i]*3+1];\r
+            v1.z = fnodes[trias[i]*3+2];\r
+            v2.x = fnodes[trias[i+1]*3];\r
+            v2.y = fnodes[trias[i+1]*3+1];\r
+            v2.z = fnodes[trias[i+1]*3+2];\r
+            v3.x = fnodes[trias[i+2]*3];\r
+            v3.y = fnodes[trias[i+2]*3+1];\r
+            v3.z = fnodes[trias[i+2]*3+2];\r
+            t1.sub(v3,v1);\r
+            t2.sub(v2,v1);\r
+            n.cross(t2, t1);\r
+            //n.normalize();\r
+            nnodes[trias[i]*3] += n.x;\r
+            nnodes[trias[i]*3+1] += n.y;\r
+            nnodes[trias[i]*3+2] += n.z;\r
+            nnodes[trias[i+1]*3] += n.x;\r
+            nnodes[trias[i+1]*3+1] += n.y;\r
+            nnodes[trias[i+1]*3+2] += n.z;\r
+            nnodes[trias[i+2]*3] += n.x;\r
+            nnodes[trias[i+2]*3+1] += n.y;\r
+            nnodes[trias[i+2]*3+2] += n.z;\r
+        }\r
+        for (int i = 0; i < nnodes.length; i+=3) {\r
+            n.x = nnodes[i];\r
+            n.y = nnodes[i+1];\r
+            n.z = nnodes[i+2];\r
+            n.normalize();\r
+            nnodes[i] = n.x;\r
+            nnodes[i+1] = n.y;\r
+            nnodes[i+2] = n.z;\r
+        }\r
+        return nnodes;\r
+    }\r
+       \r
+       public static Mesh createEdgeMesh(Mesh triMesh) {\r
+\r
+               // list all edges in the mesh\r
+               MapList<Integer, Integer> triEdgeIndices = new MapList<Integer, Integer>();\r
+               for (int i = 0; i < triMesh.getTriangleCount(); i++) {\r
+                       int[] tri = new int[3];\r
+                       triMesh.getTriangle(i, tri);\r
+\r
+                       if (!triEdgeIndices.contains(tri[0], tri[1])) {\r
+                               triEdgeIndices.add(tri[0], tri[1]);\r
+                       }\r
+                       if (!triEdgeIndices.contains(tri[1], tri[2])) {\r
+                               triEdgeIndices.add(tri[1], tri[2]);\r
+                       }\r
+                       if (!triEdgeIndices.contains(tri[2], tri[0])) {\r
+                               triEdgeIndices.add(tri[2], tri[0]);\r
+                       }        \r
+               }\r
+               // find, which edges are listed only once; those are boundaries of the mesh.\r
+               MapList<Integer, Integer> edgeIndices = new MapList<Integer, Integer>();\r
+               for (int s : triEdgeIndices.getKeys()) {\r
+                       for (int e : triEdgeIndices.getValues(s)) {\r
+                               if (!triEdgeIndices.contains(e, s)) {\r
+                                       edgeIndices.add(s,e);\r
+                                       edgeIndices.add(e,s);\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               // create a new mesh, containing boundary vertices and edges of the original mesh.\r
+               \r
+               // create list of edge vertices in the original mesh\r
+               List<Integer> vertices = new ArrayList<Integer>();\r
+               FloatBuffer data = triMesh.getFloatBuffer(Type.Position);\r
+               for (Integer i : edgeIndices.getKeys()) {\r
+                       List<Integer> edges = edgeIndices.getValues(i);\r
+                       if (!vertices.contains(i))\r
+                               vertices.add(i);\r
+                       if (!vertices.contains(edges.get(0)))\r
+                               vertices.add(edges.get(0));\r
+                       if (!vertices.contains(edges.get(1)))\r
+                               vertices.add(edges.get(1));\r
+\r
+               }\r
+               // create vertices for edge mesh, and map new vertices to orignals.\r
+               float vertex[] = new float[vertices.size() * 3];\r
+               int i2 = 0;\r
+               Map<Integer,Integer> indexMap = new HashMap<Integer, Integer>();\r
+               for (int i : vertices) {\r
+                       vertex[i2*3] = data.get(i*3);\r
+                       vertex[i2*3+1] = data.get(i*3+1);\r
+                       vertex[i2*3+2] = data.get(i*3+2);\r
+                       \r
+                       indexMap.put(i, i2);\r
+                       i2++;\r
+                       \r
+               }\r
+               \r
+               // create line indices for the edge mesh.\r
+               List<Integer> indices = new ArrayList<Integer>();\r
+\r
+               for (int i = 0; i < vertices.size(); i++) {\r
+                       int s = vertices.get(i);\r
+                       List<Integer> edges = edgeIndices.getValues(s);\r
+                       for (int e : edges) {\r
+                               if (edgeIndices.contains(s, e) && indexMap.containsKey(s) && indexMap.containsKey(e)) {\r
+                                       indices.add(indexMap.get(s));\r
+                                       indices.add(indexMap.get(e));\r
+                               }\r
+                       }\r
+                       \r
+               }\r
+               \r
+               int index[] = new int[indices.size()];\r
+               for (int i = 0; i < indices.size(); i++) {\r
+                       index[i] = indices.get(i);\r
+               }\r
+               \r
+               Mesh mesh = new Mesh();\r
+               mesh.setMode(Mode.Lines);\r
+               mesh.setBuffer(Type.Position, 3, vertex);\r
+               mesh.setBuffer(Type.Index, 2, index);\r
+               \r
+               return mesh;\r
+       }\r
+       \r
+       public static Mesh createVertexMesh(Mesh edgeMesh) {\r
+\r
+               MapList<Integer, Integer> edgeIndices = new MapList<Integer, Integer>();\r
+               IndexBuffer indices = edgeMesh.getIndexBuffer();\r
+               for (int i = 0; i < indices.size(); i+=2) {\r
+                       int s = indices.get(i);\r
+                       int e = indices.get(i+1);\r
+\r
+                       if (!edgeIndices.contains(s, e)) {\r
+                               edgeIndices.add(s, e);\r
+                               edgeIndices.add(e, s);\r
+                       }\r
+                                \r
+               }\r
+                               \r
+               List<Integer> vertices = new ArrayList<Integer>();\r
+               float data[] = edgeMesh.getFloatBuffer(Type.Position).array();\r
+               for (Integer i : edgeIndices.getKeys()) {\r
+                       List<Integer> edges = edgeIndices.getValues(i);\r
+                       if (edges.size() != 2)\r
+                               vertices.add(i);\r
+                       else {\r
+                               Point3d t = new Point3d(data[i*3],data[i*3+1],data[i*3+2]);\r
+                               Vector3d v1 = new Vector3d(data[edges.get(0)*3],data[edges.get(0)*3+1],data[edges.get(0)*3+2]);\r
+                               Vector3d v2 = new Vector3d(data[edges.get(1)*3],data[edges.get(1)*3+1],data[edges.get(1)*3+2]);\r
+                               \r
+                               v1.sub(t);\r
+                               v2.sub(t);\r
+                               double angle = Math.PI - v1.angle(v2);\r
+                               if (angle > Math.PI/6)\r
+                                       vertices.add(i);\r
+                       }\r
+               }\r
+               \r
+               float vertex[] = new float[vertices.size() * 3];\r
+               int i2 = 0;\r
+               Map<Integer,Integer> indexMap = new HashMap<Integer, Integer>();\r
+               for (int i : vertices) {\r
+                       vertex[i2*3] = data[i*3];\r
+                       vertex[i2*3+1] = data[i*3+1];\r
+                       vertex[i2*3+2] = data[i*3+2];\r
+                       \r
+                       indexMap.put(i, i2);\r
+                       i2++;\r
+                       \r
+               }\r
+               \r
+               int index[] = new int[vertices.size()];\r
+               for (int i = 0; i < vertices.size(); i++) {\r
+                       index[i] = i;\r
+               }\r
+               \r
+               Mesh mesh = new Mesh();\r
+               mesh.setMode(Mode.Points);\r
+               mesh.setBuffer(Type.Position, 3, vertex);\r
+               mesh.setBuffer(Type.Index, 1, index);\r
+               \r
+               return mesh;\r
+       }\r
+       \r
+}\r