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