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