]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.g3d.jme/src/org/simantics/g3d/jme/shape/TubeActor.java
Alpha-version of jME-bindings for g3d.
[simantics/3d.git] / org.simantics.g3d.jme / src / org / simantics / g3d / jme / shape / TubeActor.java
diff --git a/org.simantics.g3d.jme/src/org/simantics/g3d/jme/shape/TubeActor.java b/org.simantics.g3d.jme/src/org/simantics/g3d/jme/shape/TubeActor.java
new file mode 100644 (file)
index 0000000..fbdef41
--- /dev/null
@@ -0,0 +1,205 @@
+package org.simantics.g3d.jme.shape;\r
+\r
+import java.util.List;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+\r
+import com.jme3.app.Application;\r
+import com.jme3.material.Material;\r
+import com.jme3.math.ColorRGBA;\r
+import com.jme3.scene.Geometry;\r
+import com.jme3.scene.Mesh;\r
+import com.jme3.scene.VertexBuffer.Type;\r
+\r
+public class TubeActor extends Geometry {\r
+       \r
+       List<Vector3d> vertices;\r
+       List<ColorRGBA> colors;\r
+       List<Double> radiis;\r
+       Double radius = 1.0;\r
+       int resolution = 8;\r
+       \r
+       public TubeActor() {\r
+               super();\r
+       }\r
+       \r
+       public void setResolution(int resolution) {\r
+               if (resolution > 2)\r
+                       this.resolution = resolution;\r
+       }\r
+       \r
+       public void setVertices(List<Vector3d> vertices) {\r
+               this.vertices = vertices;\r
+       }\r
+\r
+       public void setColors(List<ColorRGBA> colors) {\r
+               this.colors = colors;\r
+       }\r
+       \r
+       public void setRadiis(List<Double> radiis) {\r
+               this.radiis = radiis;\r
+       }\r
+       \r
+       public void setRadius(Double radius) {\r
+               this.radius = radius;\r
+       }\r
+       \r
+       \r
+       \r
+       public void createTube(Application app) {\r
+               if (vertices.size() < 2 )\r
+                       throw new IllegalArgumentException("Tube must have at least two vertices");\r
+               \r
+               Vector3d t = new Vector3d();\r
+               \r
+               for (int i = 0; i < vertices.size() - 1; i++) {\r
+                       t.set(vertices.get(i+1));\r
+                       t.sub(vertices.get(i));\r
+                       if (t.lengthSquared() < 0.0001)\r
+                               throw new IllegalArgumentException("vertices at index " + i + " are too close to each other");\r
+               }\r
+               \r
+               float points[] = new float[vertices.size()*resolution*3];\r
+               float normals[] = new float[vertices.size()*resolution*3];\r
+               float clrs[] = null;\r
+               if (this.colors != null)\r
+                       clrs = new float[vertices.size()*resolution*4];\r
+               \r
+               for (int i = 0; i < vertices.size(); i++) {\r
+                       createCircle(i,points,normals, clrs);\r
+               }\r
+               \r
+               int index[] = new int[(vertices.size()-1)*resolution*6];\r
+               \r
+               createIndices(index);\r
+               \r
+               Mesh mesh = new Mesh();\r
+               mesh.setBuffer(Type.Index, 3, index);\r
+               mesh.setBuffer(Type.Position, 3, points);\r
+               mesh.setBuffer(Type.Normal, 3, normals);\r
+               if (clrs != null)\r
+                       mesh.setBuffer(Type.Color, 4, clrs);\r
+               setMesh(mesh);\r
+               updateModelBound();\r
+               \r
+               ColorRGBA color = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);\r
+               Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");\r
+               mat.setColor("Diffuse", color);\r
+               mat.setColor("Ambient", color);\r
+               mat.setColor("Specular", new ColorRGBA(1, 1, 1, 1));\r
+               mat.setBoolean("UseMaterialColors", true);\r
+               if (clrs != null)\r
+                       mat.setBoolean("UseVertexColor", true);\r
+               setMaterial(mat);\r
+               \r
+               vertices.clear();\r
+               if (colors != null)\r
+                       colors.clear();\r
+               if (radiis != null)\r
+                       radiis.clear();\r
+               \r
+       }\r
+       \r
+       private void createCircle(int i, float points[],float normals[], float clrs[]) {\r
+               final Vector3d up = new Vector3d(0,1,0);\r
+               final Vector3d up2 = new Vector3d(0,0,1);\r
+               ColorRGBA c = null;\r
+               if (clrs != null)\r
+                       c = this.colors.get(i);\r
+               Vector3d p = vertices.get(i);\r
+               Vector3d t = getTangent(i);\r
+               Vector3d n = new Vector3d();\r
+               if (up.dot(t) < 0.99) {\r
+                       n.cross(up, t);\r
+               } else {\r
+                       n.cross(up2, t);\r
+               }\r
+               n.normalize();\r
+               if (radiis != null) {\r
+                       n.scale(radiis.get(i));\r
+               } else {\r
+                       n.scale(radius);\r
+               }\r
+               \r
+               for (int index = 0; index < resolution; index ++) {\r
+                       Vector3d v;\r
+                       if (index == 0) {\r
+                               v = new Vector3d(n);\r
+                               \r
+                       } else {\r
+                               AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)resolution);\r
+                               v = new Vector3d();\r
+                               MathTools.rotate(MathTools.getQuat(aa), n, v);\r
+                       }\r
+                       int vIndex = (i*resolution + index)*3; \r
+                       points[vIndex+0] = (float)(p.x+v.x);\r
+                       points[vIndex+1] = (float)(p.y + v.y);\r
+                       points[vIndex+2] = (float)(p.z + v.z);\r
+                       v.normalize();\r
+                       normals[vIndex+0] = (float)(v.x);\r
+                       normals[vIndex+1] = (float)(v.y);\r
+                       normals[vIndex+2] = (float)(v.z);\r
+                       if (colors != null) {\r
+                               int cIndex = (i*resolution + index)*4;\r
+                               clrs[cIndex] = c.r;\r
+                               clrs[cIndex+1] = c.g;\r
+                               clrs[cIndex+2] = c.b;\r
+                               clrs[cIndex+3] = c.a;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       private Vector3d getTangent(int i) {\r
+               Vector3d p,n;\r
+               if (i == 0) {\r
+                       p = vertices.get(0);\r
+                       n = vertices.get(1);\r
+               } else if (i == vertices.size() - 1) {\r
+                       p = vertices.get(i-1);\r
+                       n = vertices.get(i);\r
+               } else {\r
+                       p = vertices.get(i-1);\r
+                       n = vertices.get(i+1);\r
+               }\r
+               n = new Vector3d(n);\r
+               n.sub(p);\r
+               n.normalize();\r
+               return n;\r
+       }\r
+       \r
+       private void createIndices(int index[]) {\r
+               for (int c = 0; c < vertices.size() - 1; c++) {\r
+                       for (int s = 0; s < resolution; s++) {\r
+                               int ii = (c * resolution + s) * 6;\r
+                               int iv = c*resolution + s;\r
+                               \r
+                               /*\r
+                            iv+1 ---- iv + resolution + 1\r
+                                     | /|\r
+                                     |/ |\r
+                                  iv ---- iv + resolution \r
+                               */\r
+                               if (s < resolution - 1) {\r
+                                       index[ii+2] = iv;\r
+                                       index[ii+1] = iv+resolution;\r
+                                       index[ii+0] = iv+resolution+1;\r
+                                       \r
+                                       index[ii+5] = iv;\r
+                                       index[ii+4] = iv+resolution+1;\r
+                                       index[ii+3] = iv+1;\r
+                               } else {\r
+                                       index[ii+2] = iv;\r
+                                       index[ii+1] = iv+resolution;\r
+                                       index[ii+0] = iv+1;\r
+                                       \r
+                                       index[ii+5] = iv;\r
+                                       index[ii+4] = iv+1;\r
+                                       index[ii+3] = iv+1-resolution;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r