]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d/src/org/simantics/g3d/shape/ArcCylinder.java
6f82e33cab924b4de7c082550970f02597ca7ee2
[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         public Mesh create(Point3d c, Vector3d axis, Vector3d an, double R, double r, double a, int res, double res2) {
101                 
102         
103                 
104                 int steps = 0;
105                 double sa = 0.0;
106                 
107                 Vector3d rn = new Vector3d(axis);
108                 rn.normalize();
109                 Vector3d r1 = new Vector3d(an);
110                 r1.normalize();
111                 r1.scale(R);
112
113                 
114                 if ((a +0.0001) > Math.PI) {
115                         steps = 1;
116                 } else {
117                         steps = (int)(Math.ceil(a/res2));
118                         if (steps == 0)
119                                 steps = 1;
120                         sa = a/steps;
121                 }
122
123                 List<Tuple3d> vertices = new ArrayList<Tuple3d>(res * (steps+1));
124                 List<Tuple3d> normals = new ArrayList<Tuple3d>(res * (steps+1));
125                 List<Integer> indices = new ArrayList<Integer>();
126                 
127                 for (int i = 0; i <= steps; i++) {
128                         Vector3d p;
129                         Vector3d t;
130                         p = new Vector3d();
131                         double ca = sa * i;
132                         Quat4d q = MathTools.getQuat(new AxisAngle4d(rn, ca));
133                         MathTools.rotate(q, r1, p);
134                         t = new Vector3d();
135                         t.cross(rn,p);
136                         t.normalize();
137                         p.add(c);
138                                 
139                         
140                         createCircle(vertices, normals, p, t, rn, res, r);
141                 }
142                 int count = steps*res*6;
143                 for (int i = 0; i < count; i++) {
144                         indices.add(-1);
145                 }       
146                 createIndices(steps, res, indices);
147                 return new Mesh(vertices, normals, indices);
148         }
149         
150         private static void createCircle(List<Tuple3d> points, List<Tuple3d> normals, Tuple3d p, Vector3d t, Vector3d n, int res, double radius) {
151                 n = new Vector3d(n);
152                 n.scale(radius);
153                 
154                 for (int index = 0; index < res; index ++) {
155                         Vector3d v;
156                         if (index == 0) {
157                                 v = new Vector3d(n);
158                                 
159                         } else {
160                                 AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)res);
161                                 v = new Vector3d();
162                                 MathTools.rotate(MathTools.getQuat(aa), n, v);
163                         }
164                         //int vIndex = (i*resolution + index)*3;
165                         Vector3d pt = new Vector3d(p);
166                         pt.add(v);
167                         //points.set(vIndex, pt);
168                         points.add(pt);
169                         v.normalize();
170                         //normals.set(vIndex, v);
171                         normals.add(v);
172                 }
173         }
174         private static void createIndices(int steps, int resolution, List<Integer> index) {
175                 for (int c = 0; c < steps; c++) {
176                         for (int s = 0; s < resolution; s++) {
177                                 int ii = (c * resolution + s) * 6;
178                                 int iv = c*resolution + s;
179                                 
180                                 /*
181                                  iv+1 ---- iv + resolution + 1
182                                           | /|
183                                           |/ |
184                                    iv ---- iv + resolution 
185                                 */
186                                 if (s < resolution - 1) {
187                                         index.set(ii+2,iv);
188                                         index.set(ii+1,iv+resolution);
189                                         index.set(ii+0,iv+resolution+1);
190                                         
191                                         index.set(ii+5,iv);
192                                         index.set(ii+4,iv+resolution+1);
193                                         index.set(ii+3,iv+1);
194                                 } else {
195                                         index.set(ii+2,iv);
196                                         index.set(ii+1,iv+resolution);
197                                         index.set(ii+0,iv+1);
198                                         
199                                         index.set(ii+5,iv);
200                                         index.set(ii+4,iv+1);
201                                         index.set(ii+3,iv+1-resolution);
202                                 }
203                         }
204                 }
205         }
206 }