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 r, int res) { return create(s, v, e, r, res, 0.15); } public Mesh create(Point3d s, Point3d v, Point3d e, double r, int res, double res2) { 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/res2)); if (steps == 0) steps = 1; sa = a/steps; } List vertices = new ArrayList(res * (steps+1)); List normals = new ArrayList(res * (steps+1)); List indices = new ArrayList(); 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, r); } 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); } public Mesh create(Point3d c, Vector3d axis, Vector3d an, double R, double r, double a, int res, double res2) { int steps = 0; double sa = 0.0; Vector3d rn = new Vector3d(axis); rn.normalize(); Vector3d r1 = new Vector3d(an); r1.normalize(); r1.scale(R); if ((a +0.0001) > Math.PI) { steps = 1; } else { steps = (int)(Math.ceil(a/res2)); if (steps == 0) steps = 1; sa = a/steps; } List vertices = new ArrayList(res * (steps+1)); List normals = new ArrayList(res * (steps+1)); List indices = new ArrayList(); for (int i = 0; i <= steps; i++) { Vector3d p; Vector3d t; 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, r); } 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); } public Mesh create(Point3d c, Vector3d axis, Vector3d an, double R, double r, double starta, double a, int res, double res2) { int steps = 0; double sa = 0.0; Vector3d rn = new Vector3d(axis); rn.normalize(); Vector3d r1 = new Vector3d(an); r1.normalize(); r1.scale(R); if ((a +0.0001) > Math.PI) { steps = 1; } else { steps = (int)(Math.ceil(a/res2)); if (steps == 0) steps = 1; sa = a/steps; } List vertices = new ArrayList(res * (steps+1)); List normals = new ArrayList(res * (steps+1)); List indices = new ArrayList(); for (int i = 0; i <= steps; i++) { Vector3d p; Vector3d t; p = new Vector3d(); double ca = sa * i + starta; 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, r); } 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 points, List 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 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); } } } } }