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