--- /dev/null
+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);
+ }
+ }
+ }
+ }
+}