]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d/src/org/simantics/g3d/shape/Tube.java
Fix error in inserting dual inline components
[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                 if (tangents == null) {
73                 for (int i = 0; i < vertices.size() - 1; i++) {
74                         t.set(vertices.get(i+1));
75                         t.sub(vertices.get(i));
76                         if (t.lengthSquared() < 0.0000001)
77                                 throw new IllegalArgumentException("vertices at index " + i + " are too close to each other");
78                 }
79                 }
80                 
81                 int vcount = vertices.size()*resolution;
82                 int icount = (vertices.size()-1)*resolution*6;
83                 
84                 if (cap) {
85                         vcount+=2;
86                         icount+=resolution * 6;
87                 }
88                 
89                 List<Vector3d> points = new ArrayList<Vector3d>(vcount);
90                 List<Vector3d> normals = new ArrayList<Vector3d>(vcount);
91                 
92                 for (int i = 0; i < vertices.size(); i++) {
93                         createCircle(i,points,normals);
94                 }
95                 if (cap) {
96                         int l = vertices.size()-1;
97                         points.add(new Vector3d(vertices.get(0)));
98                         points.add(new Vector3d(vertices.get(l)));
99                         Vector3d n1 = new Vector3d(vertices.get(1));
100                         n1.sub(vertices.get(0));
101                         n1.normalize();
102                         normals.add(n1);
103                         
104                         Vector3d n2 = new Vector3d(vertices.get(l-1));
105                         n2.sub(vertices.get(l));
106                         n2.normalize();
107                         normals.add(n2);
108                 }
109                 
110                 
111                 
112
113                 int index[] = new int[icount];
114                 
115                 createIndices(index);
116                 List<Integer> indices = new ArrayList<Integer>();
117                 for (int i = 0; i < index.length; i++) {
118                         indices.add(index[i]);
119                 }
120                 
121                 
122                 
123                 vertices.clear();
124                 if (colors != null)
125                         colors.clear();
126                 if (radiis != null)
127                         radiis.clear();
128                 
129                 return Mesh.create(points, normals, indices);
130                 
131         }
132         
133         private void createCircle(int i, List<Vector3d> points, List<Vector3d> normals) {
134                 final Vector3d up = new Vector3d(0,1,0);
135                 final Vector3d up2 = new Vector3d(0,0,1);
136                 Tuple3d p = vertices.get(i);
137                 Vector3d t = getTangent(i);
138                 Vector3d n = new Vector3d();
139                 if (Math.abs(up.dot(t)) < 0.99) {
140                         n.cross(up, t);
141                 } else {
142                         n.cross(up2, t);
143                 }
144                 n.normalize();
145                 if (radiis != null) {
146                         n.scale(radiis.get(i));
147                 } else {
148                         n.scale(radius);
149                 }
150                 
151                 for (int index = 0; index < resolution; index ++) {
152                         Vector3d v;
153                         if (index == 0) {
154                                 v = new Vector3d(n);
155                                 
156                         } else {
157                                 AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)resolution);
158                                 v = new Vector3d();
159                                 MathTools.rotate(MathTools.getQuat(aa), n, v);
160                         }
161                         //int vIndex = (i*resolution + index)*3;
162                         Vector3d pt = new Vector3d(p);
163                         pt.add(v);
164                         //points.set(vIndex, pt);
165                         points.add(pt);
166                         v.normalize();
167                         //normals.set(vIndex, v);
168                         normals.add(v);
169                 }
170         }
171         
172         private Vector3d getTangent(int i) {
173                 Tuple3d p,n;
174                 if (tangents != null)
175                         return tangents.get(i);
176                 if (i == 0) {
177                         p = vertices.get(0);
178                         n = vertices.get(1);
179                 } else if (i == vertices.size() - 1) {
180                         p = vertices.get(i-1);
181                         n = vertices.get(i);
182                 } else {
183                         p = vertices.get(i-1);
184                         n = vertices.get(i+1);
185                 }
186                 Vector3d nn = new Vector3d(n);
187                 nn.sub(p);
188                 nn.normalize();
189                 return nn;
190         }
191         
192         private void createIndices(int index[]) {
193                 for (int c = 0; c < vertices.size() - 1; c++) {
194                         for (int s = 0; s < resolution; s++) {
195                                 int ii = (c * resolution + s) * 6;
196                                 int iv = c*resolution + s;
197                                 
198                                 /*
199                                  iv+1 ---- iv + resolution + 1
200                                           | /|
201                                           |/ |
202                                    iv ---- iv + resolution 
203                                 */
204                                 if (s < resolution - 1) {
205                                         index[ii+2] = iv;
206                                         index[ii+1] = iv+resolution;
207                                         index[ii+0] = iv+resolution+1;
208                                         
209                                         index[ii+5] = iv;
210                                         index[ii+4] = iv+resolution+1;
211                                         index[ii+3] = iv+1;
212                                 } else {
213                                         index[ii+2] = iv;
214                                         index[ii+1] = iv+resolution;
215                                         index[ii+0] = iv+1;
216                                         
217                                         index[ii+5] = iv;
218                                         index[ii+4] = iv+1;
219                                         index[ii+3] = iv+1-resolution;
220                                 }
221                         }
222                 }
223                 if (cap) {
224                         int c = 0;
225                         int isi = ((vertices.size()-1) * resolution) * 6;
226                         int ivi = vertices.size() * resolution;
227                         for (int s = 0; s < resolution; s++) {
228                                 int ii = isi + s*3;
229                                 int iv = c*resolution + s;
230                                 if (s < resolution - 1) {
231                                         index[ii+2] = iv;
232                                         index[ii+1] = iv+1;
233                                         index[ii+0] = ivi;
234                                 } else {
235                                         index[ii+2] = iv;
236                                         index[ii+1] = iv+1-resolution;
237                                         index[ii+0] = ivi;
238                                 }
239                                 
240                         }
241                         isi += resolution * 3;
242                         c = (vertices.size()-1);
243                         for (int s = 0; s < resolution; s++) {
244                                 int ii = isi + s*3;
245                                 int iv = c*resolution + s;
246                                 if (s < resolution - 1) {
247                                         index[ii+2] = iv;
248                                         index[ii+1] = iv+1;
249                                         index[ii+0] = ivi+1;
250                                 } else {
251                                         index[ii+2] = iv;
252                                         index[ii+1] = iv+1-resolution;
253                                         index[ii+0] = ivi+1;
254                                 }
255                                 
256                         }
257                         
258                 }
259         }
260
261 }