]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d/src/org/simantics/g3d/shape/Tube.java
Support for capped tube
[simantics/3d.git] / org.simantics.g3d / src / org / simantics / g3d / shape / Tube.java
1 /*******************************************************************************
2  * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g3d.shape;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import javax.vecmath.AxisAngle4d;
18 import javax.vecmath.Tuple3d;
19 import javax.vecmath.Vector3d;
20
21 import org.simantics.g3d.math.MathTools;
22
23
24 public class Tube {
25         List<Tuple3d> vertices;
26         List<Vector3d> tangents;
27         List<Color4d> colors;
28         List<Double> radiis;
29         Double radius = 1.0;
30         int resolution = 8;
31         
32         boolean cap = false;
33         
34         
35         public void setResolution(int resolution) {
36                 if (resolution > 2)
37                         this.resolution = resolution;
38         }
39         
40         public void setVertices(List<Tuple3d> vertices) {
41                 this.vertices = vertices;
42         }
43         
44         public void setTangents(List<Vector3d> tangents) {
45                 this.tangents = tangents;
46         }
47
48         public void setColors(List<Color4d> colors) {
49                 this.colors = colors;
50         }
51         
52         public void setRadiis(List<Double> radiis) {
53                 this.radiis = radiis;
54         }
55         
56         public void setRadius(Double radius) {
57                 this.radius = radius;
58         }
59         
60         
61         public void setCap(boolean cap) {
62                 this.cap = cap;
63         }
64         
65         
66         public Mesh create() {
67                 if (vertices.size() < 2 )
68                         throw new IllegalArgumentException("Tube must have at least two vertices");
69                 
70                 Vector3d t = new Vector3d();
71                 
72                 for (int i = 0; i < vertices.size() - 1; i++) {
73                         t.set(vertices.get(i+1));
74                         t.sub(vertices.get(i));
75                         if (t.lengthSquared() < 0.000001)
76                                 throw new IllegalArgumentException("vertices at index " + i + " are too close to each other");
77                 }
78                 
79                 int vcount = vertices.size()*resolution;
80                 int icount = (vertices.size()-1)*resolution*6;
81                 
82                 if (cap) {
83                         vcount+=2;
84                         icount+=resolution * 6;
85                 }
86                 
87                 List<Vector3d> points = new ArrayList<Vector3d>(vcount);
88                 List<Vector3d> normals = new ArrayList<Vector3d>(vcount);
89                 
90                 for (int i = 0; i < vertices.size(); i++) {
91                         createCircle(i,points,normals);
92                 }
93                 if (cap) {
94                         int l = vertices.size()-1;
95                         points.add(new Vector3d(vertices.get(0)));
96                         points.add(new Vector3d(vertices.get(l)));
97                         Vector3d n1 = new Vector3d(vertices.get(1));
98                         n1.sub(vertices.get(0));
99                         n1.normalize();
100                         normals.add(n1);
101                         
102                         Vector3d n2 = new Vector3d(vertices.get(l-1));
103                         n2.sub(vertices.get(l));
104                         n2.normalize();
105                         normals.add(n2);
106                 }
107                 
108                 
109                 
110
111                 int index[] = new int[icount];
112                 
113                 createIndices(index);
114                 List<Integer> indices = new ArrayList<Integer>();
115                 for (int i = 0; i < index.length; i++) {
116                         indices.add(index[i]);
117                 }
118                 
119                 
120                 
121                 vertices.clear();
122                 if (colors != null)
123                         colors.clear();
124                 if (radiis != null)
125                         radiis.clear();
126                 
127                 return Mesh.create(points, normals, indices);
128                 
129         }
130         
131         private void createCircle(int i, List<Vector3d> points, List<Vector3d> normals) {
132                 final Vector3d up = new Vector3d(0,1,0);
133                 final Vector3d up2 = new Vector3d(0,0,1);
134                 Tuple3d p = vertices.get(i);
135                 Vector3d t = getTangent(i);
136                 Vector3d n = new Vector3d();
137                 if (Math.abs(up.dot(t)) < 0.99) {
138                         n.cross(up, t);
139                 } else {
140                         n.cross(up2, t);
141                 }
142                 n.normalize();
143                 if (radiis != null) {
144                         n.scale(radiis.get(i));
145                 } else {
146                         n.scale(radius);
147                 }
148                 
149                 for (int index = 0; index < resolution; index ++) {
150                         Vector3d v;
151                         if (index == 0) {
152                                 v = new Vector3d(n);
153                                 
154                         } else {
155                                 AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)resolution);
156                                 v = new Vector3d();
157                                 MathTools.rotate(MathTools.getQuat(aa), n, v);
158                         }
159                         //int vIndex = (i*resolution + index)*3;
160                         Vector3d pt = new Vector3d(p);
161                         pt.add(v);
162                         //points.set(vIndex, pt);
163                         points.add(pt);
164                         v.normalize();
165                         //normals.set(vIndex, v);
166                         normals.add(v);
167                 }
168         }
169         
170         private Vector3d getTangent(int i) {
171                 Tuple3d p,n;
172                 if (tangents != null)
173                         return tangents.get(i);
174                 if (i == 0) {
175                         p = vertices.get(0);
176                         n = vertices.get(1);
177                 } else if (i == vertices.size() - 1) {
178                         p = vertices.get(i-1);
179                         n = vertices.get(i);
180                 } else {
181                         p = vertices.get(i-1);
182                         n = vertices.get(i+1);
183                 }
184                 Vector3d nn = new Vector3d(n);
185                 nn.sub(p);
186                 nn.normalize();
187                 return nn;
188         }
189         
190         private void createIndices(int index[]) {
191                 for (int c = 0; c < vertices.size() - 1; c++) {
192                         for (int s = 0; s < resolution; s++) {
193                                 int ii = (c * resolution + s) * 6;
194                                 int iv = c*resolution + s;
195                                 
196                                 /*
197                              iv+1 ---- iv + resolution + 1
198                                       | /|
199                                       |/ |
200                                    iv ---- iv + resolution 
201                                 */
202                                 if (s < resolution - 1) {
203                                         index[ii+2] = iv;
204                                         index[ii+1] = iv+resolution;
205                                         index[ii+0] = iv+resolution+1;
206                                         
207                                         index[ii+5] = iv;
208                                         index[ii+4] = iv+resolution+1;
209                                         index[ii+3] = iv+1;
210                                 } else {
211                                         index[ii+2] = iv;
212                                         index[ii+1] = iv+resolution;
213                                         index[ii+0] = iv+1;
214                                         
215                                         index[ii+5] = iv;
216                                         index[ii+4] = iv+1;
217                                         index[ii+3] = iv+1-resolution;
218                                 }
219                         }
220                 }
221                 if (cap) {
222                         int c = 0;
223                         int isi = ((vertices.size()-1) * resolution) * 6;
224                         int ivi = vertices.size() * resolution;
225                         for (int s = 0; s < resolution; s++) {
226                                 int ii = isi + s*3;
227                                 int iv = c*resolution + s;
228                                 if (s < resolution - 1) {
229                                         index[ii+2] = iv;
230                                         index[ii+1] = iv+1;
231                                         index[ii+0] = ivi;
232                                 } else {
233                                         index[ii+2] = iv;
234                                         index[ii+1] = iv+1-resolution;
235                                         index[ii+0] = ivi;
236                                 }
237                                 
238                         }
239                         isi += resolution * 3;
240                         c = (vertices.size()-1);
241                         for (int s = 0; s < resolution; s++) {
242                                 int ii = isi + s*3;
243                                 int iv = c*resolution + s;
244                                 if (s < resolution - 1) {
245                                         index[ii+2] = iv;
246                                         index[ii+1] = iv+1;
247                                         index[ii+0] = ivi+1;
248                                 } else {
249                                         index[ii+2] = iv;
250                                         index[ii+1] = iv+1-resolution;
251                                         index[ii+0] = ivi+1;
252                                 }
253                                 
254                         }
255                         
256                 }
257         }
258
259 }