]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d/src/org/simantics/g3d/shape/ArcCylinder.java
Support for capped tube
[simantics/3d.git] / org.simantics.g3d / src / org / simantics / g3d / shape / ArcCylinder.java
1 package org.simantics.g3d.shape;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.vecmath.AxisAngle4d;
7 import javax.vecmath.Point3d;
8 import javax.vecmath.Quat4d;
9 import javax.vecmath.Tuple3d;
10 import javax.vecmath.Vector3d;
11
12 import org.simantics.g3d.math.MathTools;
13
14 public class ArcCylinder {
15         
16         public Mesh create(Point3d s, Point3d v, Point3d e, double r, int res) {
17                 return create(s, v, e, r, res, 0.15);
18         }
19
20         public Mesh create(Point3d s, Point3d v, Point3d e, double r, int res, double res2) {
21                 
22                 Vector3d v1 = new Vector3d(s);
23                 v1.sub(v);
24                 
25                 Vector3d v2 = new Vector3d(e);
26                 v2.sub(v);
27                 
28                 double a = v2.angle(v1);
29                 int steps = 0;
30                 double sa = 0.0;
31                 
32                 Vector3d rn = new Vector3d();
33                 Vector3d r1 = null;
34                 Vector3d c = null;
35                 
36                 if ((a +0.0001) > Math.PI) {
37                         steps = 1;
38                 } else {
39                         c = new Vector3d(v2);
40                         c.add(v1);
41                         c.normalize();
42                         c.scale(v1.length() * (1.0/Math.cos(a*0.5)));
43                         c.add(v);
44                         
45                         r1 = new Vector3d(s);
46                         r1.sub(c);
47                         
48                         Vector3d r2 = new Vector3d(e);
49                         r2.sub(c);
50                         
51                         a = r2.angle(r1);
52                         
53                         rn.cross(v2, v1);
54                         rn.normalize();
55                         
56                         steps = (int)(Math.ceil(a/res2));
57                         if (steps == 0)
58                                 steps = 1;
59                         sa = a/steps;
60                 }
61
62                 
63                 List<Tuple3d> vertices = new ArrayList<Tuple3d>(res * (steps+1));
64                 List<Tuple3d> normals = new ArrayList<Tuple3d>(res * (steps+1));
65                 List<Integer> indices = new ArrayList<Integer>();
66                 
67                 for (int i = 0; i <= steps; i++) {
68                         Vector3d p;
69                         Vector3d t;
70                         if (i == 0) {
71                                 p = new Vector3d(s);
72                                 t = new Vector3d(v1);
73                                 t.negate();
74                                 t.normalize();
75                         } else if (i == steps) {
76                                 p = new Vector3d(e);
77                                 t = new Vector3d(v2);
78                                 t.normalize();
79                         } else {
80                                 p = new Vector3d();
81                                 double ca = sa * i;
82                                 Quat4d q = MathTools.getQuat(new AxisAngle4d(rn, ca));
83                                 MathTools.rotate(q, r1, p);
84                                 t = new Vector3d();
85                                 t.cross(rn,p);
86                                 t.normalize();
87                                 p.add(c);
88                                 
89                         }
90                         createCircle(vertices, normals, p, t, rn, res, r);
91                 }
92                 int count = steps*res*6;
93                 for (int i = 0; i < count; i++) {
94                         indices.add(-1);
95                 }       
96                 createIndices(steps, res, indices);
97                 return new Mesh(vertices, normals, indices);
98         }
99         
100         private static void createCircle(List<Tuple3d> points, List<Tuple3d> normals, Tuple3d p, Vector3d t, Vector3d n, int res, double radius) {
101                 n = new Vector3d(n);
102                 n.scale(radius);
103                 
104                 for (int index = 0; index < res; index ++) {
105                         Vector3d v;
106                         if (index == 0) {
107                                 v = new Vector3d(n);
108                                 
109                         } else {
110                                 AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)res);
111                                 v = new Vector3d();
112                                 MathTools.rotate(MathTools.getQuat(aa), n, v);
113                         }
114                         //int vIndex = (i*resolution + index)*3;
115                         Vector3d pt = new Vector3d(p);
116                         pt.add(v);
117                         //points.set(vIndex, pt);
118                         points.add(pt);
119                         v.normalize();
120                         //normals.set(vIndex, v);
121                         normals.add(v);
122                 }
123         }
124         private static void createIndices(int steps, int resolution, List<Integer> index) {
125                 for (int c = 0; c < steps; c++) {
126                         for (int s = 0; s < resolution; s++) {
127                                 int ii = (c * resolution + s) * 6;
128                                 int iv = c*resolution + s;
129                                 
130                                 /*
131                              iv+1 ---- iv + resolution + 1
132                                       | /|
133                                       |/ |
134                                    iv ---- iv + resolution 
135                                 */
136                                 if (s < resolution - 1) {
137                                         index.set(ii+2,iv);
138                                         index.set(ii+1,iv+resolution);
139                                         index.set(ii+0,iv+resolution+1);
140                                         
141                                         index.set(ii+5,iv);
142                                         index.set(ii+4,iv+resolution+1);
143                                         index.set(ii+3,iv+1);
144                                 } else {
145                                         index.set(ii+2,iv);
146                                         index.set(ii+1,iv+resolution);
147                                         index.set(ii+0,iv+1);
148                                         
149                                         index.set(ii+5,iv);
150                                         index.set(ii+4,iv+1);
151                                         index.set(ii+3,iv+1-resolution);
152                                 }
153                         }
154                 }
155         }
156 }