]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - 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
diff --git a/org.simantics.g3d/src/org/simantics/g3d/shape/ArcCylinder.java b/org.simantics.g3d/src/org/simantics/g3d/shape/ArcCylinder.java
new file mode 100644 (file)
index 0000000..ab61784
--- /dev/null
@@ -0,0 +1,152 @@
+package org.simantics.g3d.shape;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.vecmath.AxisAngle4d;
+import javax.vecmath.Point3d;
+import javax.vecmath.Quat4d;
+import javax.vecmath.Tuple3d;
+import javax.vecmath.Vector3d;
+
+import org.simantics.g3d.math.MathTools;
+
+public class ArcCylinder {
+
+       public Mesh create(Point3d s, Point3d v, Point3d e, double rad, int res) {
+               
+               Vector3d v1 = new Vector3d(s);
+               v1.sub(v);
+               
+               Vector3d v2 = new Vector3d(e);
+               v2.sub(v);
+               
+               double a = v2.angle(v1);
+               int steps = 0;
+               double sa = 0.0;
+               
+               Vector3d rn = new Vector3d();
+               Vector3d r1 = null;
+               Vector3d c = null;
+               
+               if ((a +0.0001) > Math.PI) {
+                       steps = 1;
+               } else {
+                       c = new Vector3d(v2);
+                       c.add(v1);
+                       c.normalize();
+                       c.scale(v1.length() * (1.0/Math.cos(a*0.5)));
+                       c.add(v);
+                       
+                       r1 = new Vector3d(s);
+                       r1.sub(c);
+                       
+                       Vector3d r2 = new Vector3d(e);
+                       r2.sub(c);
+                       
+                       a = r2.angle(r1);
+                       
+                       rn.cross(v2, v1);
+                       rn.normalize();
+                       
+                       steps = (int)(Math.ceil(a/0.1));
+                       if (steps == 0)
+                               steps = 1;
+                       sa = a/steps;
+               }
+
+               
+               List<Tuple3d> vertices = new ArrayList<Tuple3d>(res * (steps+1));
+               List<Tuple3d> normals = new ArrayList<Tuple3d>(res * (steps+1));
+               List<Integer> indices = new ArrayList<Integer>();
+               
+               for (int i = 0; i <= steps; i++) {
+                       Vector3d p;
+                       Vector3d t;
+                       if (i == 0) {
+                               p = new Vector3d(s);
+                               t = new Vector3d(v1);
+                               t.negate();
+                               t.normalize();
+                       } else if (i == steps) {
+                               p = new Vector3d(e);
+                               t = new Vector3d(v2);
+                               t.normalize();
+                       } else {
+                               p = new Vector3d();
+                               double ca = sa * i;
+                               Quat4d q = MathTools.getQuat(new AxisAngle4d(rn, ca));
+                               MathTools.rotate(q, r1, p);
+                               t = new Vector3d();
+                               t.cross(rn,p);
+                               t.normalize();
+                               p.add(c);
+                               
+                       }
+                       createCircle(vertices, normals, p, t, rn, res, rad);
+               }
+               int count = steps*res*6;
+               for (int i = 0; i < count; i++) {
+                       indices.add(-1);
+               }       
+               createIndices(steps, res, indices);
+               return new Mesh(vertices, normals, indices);
+       }
+       
+       private static void createCircle(List<Tuple3d> points, List<Tuple3d> normals, Tuple3d p, Vector3d t, Vector3d n, int res, double radius) {
+               n = new Vector3d(n);
+               n.scale(radius);
+               
+               for (int index = 0; index < res; index ++) {
+                       Vector3d v;
+                       if (index == 0) {
+                               v = new Vector3d(n);
+                               
+                       } else {
+                               AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)res);
+                               v = new Vector3d();
+                               MathTools.rotate(MathTools.getQuat(aa), n, v);
+                       }
+                       //int vIndex = (i*resolution + index)*3;
+                       Vector3d pt = new Vector3d(p);
+                       pt.add(v);
+                       //points.set(vIndex, pt);
+                       points.add(pt);
+                       v.normalize();
+                       //normals.set(vIndex, v);
+                       normals.add(v);
+               }
+       }
+       private static void createIndices(int steps, int resolution, List<Integer> index) {
+               for (int c = 0; c < steps; c++) {
+                       for (int s = 0; s < resolution; s++) {
+                               int ii = (c * resolution + s) * 6;
+                               int iv = c*resolution + s;
+                               
+                               /*
+                            iv+1 ---- iv + resolution + 1
+                                     | /|
+                                     |/ |
+                                  iv ---- iv + resolution 
+                               */
+                               if (s < resolution - 1) {
+                                       index.set(ii+2,iv);
+                                       index.set(ii+1,iv+resolution);
+                                       index.set(ii+0,iv+resolution+1);
+                                       
+                                       index.set(ii+5,iv);
+                                       index.set(ii+4,iv+resolution+1);
+                                       index.set(ii+3,iv+1);
+                               } else {
+                                       index.set(ii+2,iv);
+                                       index.set(ii+1,iv+resolution);
+                                       index.set(ii+0,iv+1);
+                                       
+                                       index.set(ii+5,iv);
+                                       index.set(ii+4,iv+1);
+                                       index.set(ii+3,iv+1-resolution);
+                               }
+                       }
+               }
+       }
+}