]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d/src/org/simantics/g3d/shape/Tube.java
Copyrights
[simantics/3d.git] / org.simantics.g3d / src / org / simantics / g3d / shape / Tube.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.shape;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.List;\r
16 \r
17 import javax.vecmath.AxisAngle4d;\r
18 import javax.vecmath.Vector3d;\r
19 \r
20 import org.simantics.g3d.math.MathTools;\r
21 \r
22 \r
23 public class Tube {\r
24         List<Vector3d> vertices;\r
25         List<Color4d> colors;\r
26         List<Double> radiis;\r
27         Double radius = 1.0;\r
28         int resolution = 8;\r
29         \r
30         \r
31         public void setResolution(int resolution) {\r
32                 if (resolution > 2)\r
33                         this.resolution = resolution;\r
34         }\r
35         \r
36         public void setVertices(List<Vector3d> vertices) {\r
37                 this.vertices = vertices;\r
38         }\r
39 \r
40         public void setColors(List<Color4d> colors) {\r
41                 this.colors = colors;\r
42         }\r
43         \r
44         public void setRadiis(List<Double> radiis) {\r
45                 this.radiis = radiis;\r
46         }\r
47         \r
48         public void setRadius(Double radius) {\r
49                 this.radius = radius;\r
50         }\r
51         \r
52         \r
53         \r
54         public Mesh create() {\r
55                 if (vertices.size() < 2 )\r
56                         throw new IllegalArgumentException("Tube must have at least two vertices");\r
57                 \r
58                 Vector3d t = new Vector3d();\r
59                 \r
60                 for (int i = 0; i < vertices.size() - 1; i++) {\r
61                         t.set(vertices.get(i+1));\r
62                         t.sub(vertices.get(i));\r
63                         if (t.lengthSquared() < 0.0001)\r
64                                 throw new IllegalArgumentException("vertices at index " + i + " are too close to each other");\r
65                 }\r
66                 \r
67                 List<Vector3d> points = new ArrayList<Vector3d>(vertices.size()*resolution);\r
68                 List<Vector3d> normals = new ArrayList<Vector3d>(vertices.size()*resolution);\r
69                 \r
70                 for (int i = 0; i < vertices.size(); i++) {\r
71                         createCircle(i,points,normals);\r
72                 }\r
73                 \r
74                 int index[] = new int[(vertices.size()-1)*resolution*6];\r
75                 \r
76                 createIndices(index);\r
77                 List<Integer> indices = new ArrayList<Integer>();\r
78                 for (int i = 0; i < index.length; i++) {\r
79                         indices.add(index[i]);\r
80                 }\r
81                 \r
82                 \r
83                 \r
84                 vertices.clear();\r
85                 if (colors != null)\r
86                         colors.clear();\r
87                 if (radiis != null)\r
88                         radiis.clear();\r
89                 \r
90                 return new Mesh(points, normals, indices);\r
91                 \r
92         }\r
93         \r
94         private void createCircle(int i, List<Vector3d> points, List<Vector3d> normals) {\r
95                 final Vector3d up = new Vector3d(0,1,0);\r
96                 final Vector3d up2 = new Vector3d(0,0,1);\r
97                 Vector3d p = vertices.get(i);\r
98                 Vector3d t = getTangent(i);\r
99                 Vector3d n = new Vector3d();\r
100                 if (up.dot(t) < 0.99) {\r
101                         n.cross(up, t);\r
102                 } else {\r
103                         n.cross(up2, t);\r
104                 }\r
105                 n.normalize();\r
106                 if (radiis != null) {\r
107                         n.scale(radiis.get(i));\r
108                 } else {\r
109                         n.scale(radius);\r
110                 }\r
111                 \r
112                 for (int index = 0; index < resolution; index ++) {\r
113                         Vector3d v;\r
114                         if (index == 0) {\r
115                                 v = new Vector3d(n);\r
116                                 \r
117                         } else {\r
118                                 AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)resolution);\r
119                                 v = new Vector3d();\r
120                                 MathTools.rotate(MathTools.getQuat(aa), n, v);\r
121                         }\r
122                         //int vIndex = (i*resolution + index)*3;\r
123                         Vector3d pt = new Vector3d(p);\r
124                         pt.add(v);\r
125                         //points.set(vIndex, pt);\r
126                         points.add(pt);\r
127                         v.normalize();\r
128                         //normals.set(vIndex, v);\r
129                         normals.add(v);\r
130                 }\r
131         }\r
132         \r
133         private Vector3d getTangent(int i) {\r
134                 Vector3d p,n;\r
135                 if (i == 0) {\r
136                         p = vertices.get(0);\r
137                         n = vertices.get(1);\r
138                 } else if (i == vertices.size() - 1) {\r
139                         p = vertices.get(i-1);\r
140                         n = vertices.get(i);\r
141                 } else {\r
142                         p = vertices.get(i-1);\r
143                         n = vertices.get(i+1);\r
144                 }\r
145                 n = new Vector3d(n);\r
146                 n.sub(p);\r
147                 n.normalize();\r
148                 return n;\r
149         }\r
150         \r
151         private void createIndices(int index[]) {\r
152                 for (int c = 0; c < vertices.size() - 1; c++) {\r
153                         for (int s = 0; s < resolution; s++) {\r
154                                 int ii = (c * resolution + s) * 6;\r
155                                 int iv = c*resolution + s;\r
156                                 \r
157                                 /*\r
158                              iv+1 ---- iv + resolution + 1\r
159                                       | /|\r
160                                       |/ |\r
161                                    iv ---- iv + resolution \r
162                                 */\r
163                                 if (s < resolution - 1) {\r
164                                         index[ii+2] = iv;\r
165                                         index[ii+1] = iv+resolution;\r
166                                         index[ii+0] = iv+resolution+1;\r
167                                         \r
168                                         index[ii+5] = iv;\r
169                                         index[ii+4] = iv+resolution+1;\r
170                                         index[ii+3] = iv+1;\r
171                                 } else {\r
172                                         index[ii+2] = iv;\r
173                                         index[ii+1] = iv+resolution;\r
174                                         index[ii+0] = iv+1;\r
175                                         \r
176                                         index[ii+5] = iv;\r
177                                         index[ii+4] = iv+1;\r
178                                         index[ii+3] = iv+1-resolution;\r
179                                 }\r
180                         }\r
181                 }\r
182         }\r
183 \r
184 }\r