]> gerrit.simantics Code Review - simantics/3d.git/blob - 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
1 package org.simantics.g3d.jme.shape;\r
2 \r
3 import java.util.List;\r
4 \r
5 import javax.vecmath.AxisAngle4d;\r
6 import javax.vecmath.Vector3d;\r
7 \r
8 import org.simantics.g3d.math.MathTools;\r
9 \r
10 import com.jme3.app.Application;\r
11 import com.jme3.material.Material;\r
12 import com.jme3.math.ColorRGBA;\r
13 import com.jme3.scene.Geometry;\r
14 import com.jme3.scene.Mesh;\r
15 import com.jme3.scene.VertexBuffer.Type;\r
16 \r
17 public class TubeActor extends Geometry {\r
18         \r
19         List<Vector3d> vertices;\r
20         List<ColorRGBA> colors;\r
21         List<Double> radiis;\r
22         Double radius = 1.0;\r
23         int resolution = 8;\r
24         \r
25         public TubeActor() {\r
26                 super();\r
27         }\r
28         \r
29         public void setResolution(int resolution) {\r
30                 if (resolution > 2)\r
31                         this.resolution = resolution;\r
32         }\r
33         \r
34         public void setVertices(List<Vector3d> vertices) {\r
35                 this.vertices = vertices;\r
36         }\r
37 \r
38         public void setColors(List<ColorRGBA> colors) {\r
39                 this.colors = colors;\r
40         }\r
41         \r
42         public void setRadiis(List<Double> radiis) {\r
43                 this.radiis = radiis;\r
44         }\r
45         \r
46         public void setRadius(Double radius) {\r
47                 this.radius = radius;\r
48         }\r
49         \r
50         \r
51         \r
52         public void createTube(Application app) {\r
53                 if (vertices.size() < 2 )\r
54                         throw new IllegalArgumentException("Tube must have at least two vertices");\r
55                 \r
56                 Vector3d t = new Vector3d();\r
57                 \r
58                 for (int i = 0; i < vertices.size() - 1; i++) {\r
59                         t.set(vertices.get(i+1));\r
60                         t.sub(vertices.get(i));\r
61                         if (t.lengthSquared() < 0.0001)\r
62                                 throw new IllegalArgumentException("vertices at index " + i + " are too close to each other");\r
63                 }\r
64                 \r
65                 float points[] = new float[vertices.size()*resolution*3];\r
66                 float normals[] = new float[vertices.size()*resolution*3];\r
67                 float clrs[] = null;\r
68                 if (this.colors != null)\r
69                         clrs = new float[vertices.size()*resolution*4];\r
70                 \r
71                 for (int i = 0; i < vertices.size(); i++) {\r
72                         createCircle(i,points,normals, clrs);\r
73                 }\r
74                 \r
75                 int index[] = new int[(vertices.size()-1)*resolution*6];\r
76                 \r
77                 createIndices(index);\r
78                 \r
79                 Mesh mesh = new Mesh();\r
80                 mesh.setBuffer(Type.Index, 3, index);\r
81                 mesh.setBuffer(Type.Position, 3, points);\r
82                 mesh.setBuffer(Type.Normal, 3, normals);\r
83                 if (clrs != null)\r
84                         mesh.setBuffer(Type.Color, 4, clrs);\r
85                 setMesh(mesh);\r
86                 updateModelBound();\r
87                 \r
88                 ColorRGBA color = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);\r
89                 Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");\r
90                 mat.setColor("Diffuse", color);\r
91                 mat.setColor("Ambient", color);\r
92                 mat.setColor("Specular", new ColorRGBA(1, 1, 1, 1));\r
93                 mat.setBoolean("UseMaterialColors", true);\r
94                 if (clrs != null)\r
95                         mat.setBoolean("UseVertexColor", true);\r
96                 setMaterial(mat);\r
97                 \r
98                 vertices.clear();\r
99                 if (colors != null)\r
100                         colors.clear();\r
101                 if (radiis != null)\r
102                         radiis.clear();\r
103                 \r
104         }\r
105         \r
106         private void createCircle(int i, float points[],float normals[], float clrs[]) {\r
107                 final Vector3d up = new Vector3d(0,1,0);\r
108                 final Vector3d up2 = new Vector3d(0,0,1);\r
109                 ColorRGBA c = null;\r
110                 if (clrs != null)\r
111                         c = this.colors.get(i);\r
112                 Vector3d p = vertices.get(i);\r
113                 Vector3d t = getTangent(i);\r
114                 Vector3d n = new Vector3d();\r
115                 if (up.dot(t) < 0.99) {\r
116                         n.cross(up, t);\r
117                 } else {\r
118                         n.cross(up2, t);\r
119                 }\r
120                 n.normalize();\r
121                 if (radiis != null) {\r
122                         n.scale(radiis.get(i));\r
123                 } else {\r
124                         n.scale(radius);\r
125                 }\r
126                 \r
127                 for (int index = 0; index < resolution; index ++) {\r
128                         Vector3d v;\r
129                         if (index == 0) {\r
130                                 v = new Vector3d(n);\r
131                                 \r
132                         } else {\r
133                                 AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)resolution);\r
134                                 v = new Vector3d();\r
135                                 MathTools.rotate(MathTools.getQuat(aa), n, v);\r
136                         }\r
137                         int vIndex = (i*resolution + index)*3; \r
138                         points[vIndex+0] = (float)(p.x+v.x);\r
139                         points[vIndex+1] = (float)(p.y + v.y);\r
140                         points[vIndex+2] = (float)(p.z + v.z);\r
141                         v.normalize();\r
142                         normals[vIndex+0] = (float)(v.x);\r
143                         normals[vIndex+1] = (float)(v.y);\r
144                         normals[vIndex+2] = (float)(v.z);\r
145                         if (colors != null) {\r
146                                 int cIndex = (i*resolution + index)*4;\r
147                                 clrs[cIndex] = c.r;\r
148                                 clrs[cIndex+1] = c.g;\r
149                                 clrs[cIndex+2] = c.b;\r
150                                 clrs[cIndex+3] = c.a;\r
151                         }\r
152                 }\r
153         }\r
154         \r
155         private Vector3d getTangent(int i) {\r
156                 Vector3d p,n;\r
157                 if (i == 0) {\r
158                         p = vertices.get(0);\r
159                         n = vertices.get(1);\r
160                 } else if (i == vertices.size() - 1) {\r
161                         p = vertices.get(i-1);\r
162                         n = vertices.get(i);\r
163                 } else {\r
164                         p = vertices.get(i-1);\r
165                         n = vertices.get(i+1);\r
166                 }\r
167                 n = new Vector3d(n);\r
168                 n.sub(p);\r
169                 n.normalize();\r
170                 return n;\r
171         }\r
172         \r
173         private void createIndices(int index[]) {\r
174                 for (int c = 0; c < vertices.size() - 1; c++) {\r
175                         for (int s = 0; s < resolution; s++) {\r
176                                 int ii = (c * resolution + s) * 6;\r
177                                 int iv = c*resolution + s;\r
178                                 \r
179                                 /*\r
180                              iv+1 ---- iv + resolution + 1\r
181                                       | /|\r
182                                       |/ |\r
183                                    iv ---- iv + resolution \r
184                                 */\r
185                                 if (s < resolution - 1) {\r
186                                         index[ii+2] = iv;\r
187                                         index[ii+1] = iv+resolution;\r
188                                         index[ii+0] = iv+resolution+1;\r
189                                         \r
190                                         index[ii+5] = iv;\r
191                                         index[ii+4] = iv+resolution+1;\r
192                                         index[ii+3] = iv+1;\r
193                                 } else {\r
194                                         index[ii+2] = iv;\r
195                                         index[ii+1] = iv+resolution;\r
196                                         index[ii+0] = iv+1;\r
197                                         \r
198                                         index[ii+5] = iv;\r
199                                         index[ii+4] = iv+1;\r
200                                         index[ii+3] = iv+1-resolution;\r
201                                 }\r
202                         }\r
203                 }\r
204         }\r
205 }\r