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