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