1 package org.simantics.opencascade.jme;
\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
9 import javax.vecmath.Matrix4d;
\r
10 import javax.vecmath.Point3d;
\r
11 import javax.vecmath.Vector3d;
\r
12 import javax.vecmath.Vector3f;
\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
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
37 public class JmeOCCTTool {
\r
40 public static Spatial vtkOCCShapeToAssembly(TopoDS_Shape shape) {
\r
41 double deflection = 0.001;
\r
43 if (deflection <= 0.0) {
\r
44 deflection = 0.0005;
\r
45 System.out.println("Bad value for deflection. Using: " + deflection);
\r
48 // FIXME : leaks memory!
\r
49 //BRepTools.clean(shape);
\r
51 double mass = OCCTTool.getMass(shape);
\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
58 double length = OCCTTool.getBoundingBoxDiagonal(shape);
\r
59 deflection *= length; // use relative units
\r
61 BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection);
\r
64 TopExp_Explorer expFace = new TopExp_Explorer();
\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
71 if (partGrid == null)
\r
74 //gridToAssembly(assemblies, partGrid, stlSurfaceData, stlEdgeData);
\r
75 gridToAssembly(node, partGrid);
\r
81 if (faceNumber == 0) {
\r
83 .println("Cad import: error: no surface triangulation was generated.");
\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
101 public static Mesh createPartGrid ( TopoDS_Face face)
\r
103 TopLoc_Location Location = new TopLoc_Location();
\r
105 Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);
\r
107 if(triangulation == null) {
\r
109 System.out.println("Encountered empty triangulation after face");
\r
113 boolean reverse = face.orientation()==TopAbs_Orientation.REVERSED;
\r
115 int[]triangles = triangulation.triangles();
\r
116 double[]nodes = triangulation.nodes();
\r
118 int nofTriangles = triangulation.nbTriangles();
\r
119 int nofNodes = triangulation.nbNodes();
\r
121 triangulation.delete();
\r
123 if(nofTriangles < 1) {
\r
124 System.out.println("No triangles for mesh on face");
\r
130 System.out.println("No nodes for mesh on face:");
\r
135 Mesh mesh = new Mesh();
\r
137 int index[] = new int[nofTriangles*3];
\r
139 for(int i = 0; i < nofTriangles; i++)
\r
143 n0 = triangles[3 * i];
\r
144 n1 = triangles[3 * i + 1];
\r
145 n2 = triangles[3 * i + 2];
\r
147 n0 = triangles[3 * i + 2];
\r
148 n1 = triangles[3 * i + 1];
\r
149 n2 = triangles[3 * i];
\r
160 GP_Trsf transformation = Location.transformation();
\r
163 double d_mat[] = new double[16];
\r
164 transformation.getValues(d_mat);
\r
166 Matrix4d mat = new Matrix4d(d_mat);
\r
168 float vertex[] = new float[nofNodes*3];
\r
170 for(int i = 0; i < nofNodes; i++) {
\r
171 // FIXME: GP_Trsf.transform(double[]) leaks memory
\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
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
183 transformation.delete();
\r
185 mesh.setBuffer(Type.Position, 3, vertex);
\r
186 mesh.setBuffer(Type.Index, 3, index);
\r
193 public static Mesh createPartGrid ( List<Double> meshPoints, List<Integer> meshTriangles)
\r
200 int nofTriangles = meshTriangles.size() / 3;
\r
201 int nofNodes = meshPoints.size() /3;
\r
204 if(nofTriangles < 1) {
\r
205 System.out.println("No triangles for mesh on face");
\r
210 System.out.println("No nodes for mesh on face:");
\r
213 Mesh mesh = new Mesh();
\r
214 //System.out.println("v " + nofNodes + " t " +nofTriangles);
\r
215 int index[] = new int[nofTriangles*3];
\r
217 for(int i = 0; i < nofTriangles; i++)
\r
220 n0 = meshTriangles.get(3 * i);
\r
221 n1 = meshTriangles.get(3 * i + 1);
\r
222 n2 = meshTriangles.get(3 * i + 2);
\r
224 index[i * 3 ] = n0;
\r
225 index[i * 3 + 1] = n1;
\r
226 index[i * 3 + 2] = n2;
\r
230 float vertex[] = new float[nofNodes*3];
\r
232 for(int i = 0; i < nofNodes; i++) {
\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
240 float normal[] = calcNormals(vertex, index);
\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
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
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
283 for (int i = 0; i < nnodes.length; i+=3) {
\r
295 public static Mesh createEdgeMesh(Mesh triMesh) {
\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
303 if (!triEdgeIndices.contains(tri[0], tri[1])) {
\r
304 triEdgeIndices.add(tri[0], tri[1]);
\r
306 if (!triEdgeIndices.contains(tri[1], tri[2])) {
\r
307 triEdgeIndices.add(tri[1], tri[2]);
\r
309 if (!triEdgeIndices.contains(tri[2], tri[0])) {
\r
310 triEdgeIndices.add(tri[2], tri[0]);
\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
324 // create a new mesh, containing boundary vertices and edges of the original mesh.
\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
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
339 // create vertices for edge mesh, and map new vertices to orignals.
\r
340 float vertex[] = new float[vertices.size() * 3];
\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
348 indexMap.put(i, i2);
\r
353 // create line indices for the edge mesh.
\r
354 List<Integer> indices = new ArrayList<Integer>();
\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
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
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
381 public static Mesh createVertexMesh(Mesh edgeMesh) {
\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
389 if (!edgeIndices.contains(s, e)) {
\r
390 edgeIndices.add(s, e);
\r
391 edgeIndices.add(e, s);
\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
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
409 double angle = Math.PI - v1.angle(v2);
\r
410 if (angle > Math.PI/6)
\r
415 float vertex[] = new float[vertices.size() * 3];
\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
423 indexMap.put(i, i2);
\r
428 int index[] = new int[vertices.size()];
\r
429 for (int i = 0; i < vertices.size(); i++) {
\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