-package org.simantics.g3d.shape;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import javax.vecmath.AxisAngle4d;\r
-import javax.vecmath.Vector3d;\r
-\r
-import org.simantics.g3d.math.MathTools;\r
-\r
-\r
-public class Tube {\r
- List<Vector3d> vertices;\r
- List<Color4d> colors;\r
- List<Double> radiis;\r
- Double radius = 1.0;\r
- int resolution = 8;\r
- \r
- \r
- public void setResolution(int resolution) {\r
- if (resolution > 2)\r
- this.resolution = resolution;\r
- }\r
- \r
- public void setVertices(List<Vector3d> vertices) {\r
- this.vertices = vertices;\r
- }\r
-\r
- public void setColors(List<Color4d> colors) {\r
- this.colors = colors;\r
- }\r
- \r
- public void setRadiis(List<Double> radiis) {\r
- this.radiis = radiis;\r
- }\r
- \r
- public void setRadius(Double radius) {\r
- this.radius = radius;\r
- }\r
- \r
- \r
- \r
- public Mesh create() {\r
- if (vertices.size() < 2 )\r
- throw new IllegalArgumentException("Tube must have at least two vertices");\r
- \r
- Vector3d t = new Vector3d();\r
- \r
- for (int i = 0; i < vertices.size() - 1; i++) {\r
- t.set(vertices.get(i+1));\r
- t.sub(vertices.get(i));\r
- if (t.lengthSquared() < 0.0001)\r
- throw new IllegalArgumentException("vertices at index " + i + " are too close to each other");\r
- }\r
- \r
- List<Vector3d> points = new ArrayList<Vector3d>(vertices.size()*resolution);\r
- List<Vector3d> normals = new ArrayList<Vector3d>(vertices.size()*resolution);\r
- \r
- for (int i = 0; i < vertices.size(); i++) {\r
- createCircle(i,points,normals);\r
- }\r
- \r
- int index[] = new int[(vertices.size()-1)*resolution*6];\r
- \r
- createIndices(index);\r
- List<Integer> indices = new ArrayList<Integer>();\r
- for (int i = 0; i < index.length; i++) {\r
- indices.add(index[i]);\r
- }\r
- \r
- \r
- \r
- vertices.clear();\r
- if (colors != null)\r
- colors.clear();\r
- if (radiis != null)\r
- radiis.clear();\r
- \r
- return new Mesh(points, normals, indices);\r
- \r
- }\r
- \r
- private void createCircle(int i, List<Vector3d> points, List<Vector3d> normals) {\r
- final Vector3d up = new Vector3d(0,1,0);\r
- final Vector3d up2 = new Vector3d(0,0,1);\r
- Vector3d p = vertices.get(i);\r
- Vector3d t = getTangent(i);\r
- Vector3d n = new Vector3d();\r
- if (up.dot(t) < 0.99) {\r
- n.cross(up, t);\r
- } else {\r
- n.cross(up2, t);\r
- }\r
- n.normalize();\r
- if (radiis != null) {\r
- n.scale(radiis.get(i));\r
- } else {\r
- n.scale(radius);\r
- }\r
- \r
- for (int index = 0; index < resolution; index ++) {\r
- Vector3d v;\r
- if (index == 0) {\r
- v = new Vector3d(n);\r
- \r
- } else {\r
- AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)resolution);\r
- v = new Vector3d();\r
- MathTools.rotate(MathTools.getQuat(aa), n, v);\r
- }\r
- //int vIndex = (i*resolution + index)*3;\r
- Vector3d pt = new Vector3d(p);\r
- pt.add(v);\r
- //points.set(vIndex, pt);\r
- points.add(pt);\r
- v.normalize();\r
- //normals.set(vIndex, v);\r
- normals.add(v);\r
- }\r
- }\r
- \r
- private Vector3d getTangent(int i) {\r
- Vector3d p,n;\r
- if (i == 0) {\r
- p = vertices.get(0);\r
- n = vertices.get(1);\r
- } else if (i == vertices.size() - 1) {\r
- p = vertices.get(i-1);\r
- n = vertices.get(i);\r
- } else {\r
- p = vertices.get(i-1);\r
- n = vertices.get(i+1);\r
- }\r
- n = new Vector3d(n);\r
- n.sub(p);\r
- n.normalize();\r
- return n;\r
- }\r
- \r
- private void createIndices(int index[]) {\r
- for (int c = 0; c < vertices.size() - 1; c++) {\r
- for (int s = 0; s < resolution; s++) {\r
- int ii = (c * resolution + s) * 6;\r
- int iv = c*resolution + s;\r
- \r
- /*\r
- iv+1 ---- iv + resolution + 1\r
- | /|\r
- |/ |\r
- iv ---- iv + resolution \r
- */\r
- if (s < resolution - 1) {\r
- index[ii+2] = iv;\r
- index[ii+1] = iv+resolution;\r
- index[ii+0] = iv+resolution+1;\r
- \r
- index[ii+5] = iv;\r
- index[ii+4] = iv+resolution+1;\r
- index[ii+3] = iv+1;\r
- } else {\r
- index[ii+2] = iv;\r
- index[ii+1] = iv+resolution;\r
- index[ii+0] = iv+1;\r
- \r
- index[ii+5] = iv;\r
- index[ii+4] = iv+1;\r
- index[ii+3] = iv+1-resolution;\r
- }\r
- }\r
- }\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.g3d.shape;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.vecmath.AxisAngle4d;
+import javax.vecmath.Tuple3d;
+import javax.vecmath.Vector3d;
+
+import org.simantics.g3d.math.MathTools;
+
+
+public class Tube {
+ List<Tuple3d> vertices;
+ List<Vector3d> tangents;
+ List<Color4d> colors;
+ List<Double> radiis;
+ Double radius = 1.0;
+ int resolution = 8;
+
+ boolean cap = false;
+
+
+ public void setResolution(int resolution) {
+ if (resolution > 2)
+ this.resolution = resolution;
+ }
+
+ public void setVertices(List<Tuple3d> vertices) {
+ this.vertices = vertices;
+ }
+
+ public void setTangents(List<Vector3d> tangents) {
+ this.tangents = tangents;
+ }
+
+ public void setColors(List<Color4d> colors) {
+ this.colors = colors;
+ }
+
+ public void setRadiis(List<Double> radiis) {
+ this.radiis = radiis;
+ }
+
+ public void setRadius(Double radius) {
+ this.radius = radius;
+ }
+
+
+ public void setCap(boolean cap) {
+ this.cap = cap;
+ }
+
+
+ public Mesh create() {
+ if (vertices.size() < 2 )
+ throw new IllegalArgumentException("Tube must have at least two vertices");
+
+ Vector3d t = new Vector3d();
+
+ for (int i = 0; i < vertices.size() - 1; i++) {
+ t.set(vertices.get(i+1));
+ t.sub(vertices.get(i));
+ if (t.lengthSquared() < 0.000001)
+ throw new IllegalArgumentException("vertices at index " + i + " are too close to each other");
+ }
+
+ int vcount = vertices.size()*resolution;
+ int icount = (vertices.size()-1)*resolution*6;
+
+ if (cap) {
+ vcount+=2;
+ icount+=resolution * 6;
+ }
+
+ List<Vector3d> points = new ArrayList<Vector3d>(vcount);
+ List<Vector3d> normals = new ArrayList<Vector3d>(vcount);
+
+ for (int i = 0; i < vertices.size(); i++) {
+ createCircle(i,points,normals);
+ }
+ if (cap) {
+ int l = vertices.size()-1;
+ points.add(new Vector3d(vertices.get(0)));
+ points.add(new Vector3d(vertices.get(l)));
+ Vector3d n1 = new Vector3d(vertices.get(1));
+ n1.sub(vertices.get(0));
+ n1.normalize();
+ normals.add(n1);
+
+ Vector3d n2 = new Vector3d(vertices.get(l-1));
+ n2.sub(vertices.get(l));
+ n2.normalize();
+ normals.add(n2);
+ }
+
+
+
+
+ int index[] = new int[icount];
+
+ createIndices(index);
+ List<Integer> indices = new ArrayList<Integer>();
+ for (int i = 0; i < index.length; i++) {
+ indices.add(index[i]);
+ }
+
+
+
+ vertices.clear();
+ if (colors != null)
+ colors.clear();
+ if (radiis != null)
+ radiis.clear();
+
+ return Mesh.create(points, normals, indices);
+
+ }
+
+ private void createCircle(int i, List<Vector3d> points, List<Vector3d> normals) {
+ final Vector3d up = new Vector3d(0,1,0);
+ final Vector3d up2 = new Vector3d(0,0,1);
+ Tuple3d p = vertices.get(i);
+ Vector3d t = getTangent(i);
+ Vector3d n = new Vector3d();
+ if (Math.abs(up.dot(t)) < 0.99) {
+ n.cross(up, t);
+ } else {
+ n.cross(up2, t);
+ }
+ n.normalize();
+ if (radiis != null) {
+ n.scale(radiis.get(i));
+ } else {
+ n.scale(radius);
+ }
+
+ for (int index = 0; index < resolution; index ++) {
+ Vector3d v;
+ if (index == 0) {
+ v = new Vector3d(n);
+
+ } else {
+ AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)resolution);
+ 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 Vector3d getTangent(int i) {
+ Tuple3d p,n;
+ if (tangents != null)
+ return tangents.get(i);
+ if (i == 0) {
+ p = vertices.get(0);
+ n = vertices.get(1);
+ } else if (i == vertices.size() - 1) {
+ p = vertices.get(i-1);
+ n = vertices.get(i);
+ } else {
+ p = vertices.get(i-1);
+ n = vertices.get(i+1);
+ }
+ Vector3d nn = new Vector3d(n);
+ nn.sub(p);
+ nn.normalize();
+ return nn;
+ }
+
+ private void createIndices(int index[]) {
+ for (int c = 0; c < vertices.size() - 1; 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[ii+2] = iv;
+ index[ii+1] = iv+resolution;
+ index[ii+0] = iv+resolution+1;
+
+ index[ii+5] = iv;
+ index[ii+4] = iv+resolution+1;
+ index[ii+3] = iv+1;
+ } else {
+ index[ii+2] = iv;
+ index[ii+1] = iv+resolution;
+ index[ii+0] = iv+1;
+
+ index[ii+5] = iv;
+ index[ii+4] = iv+1;
+ index[ii+3] = iv+1-resolution;
+ }
+ }
+ }
+ if (cap) {
+ int c = 0;
+ int isi = ((vertices.size()-1) * resolution) * 6;
+ int ivi = vertices.size() * resolution;
+ for (int s = 0; s < resolution; s++) {
+ int ii = isi + s*3;
+ int iv = c*resolution + s;
+ if (s < resolution - 1) {
+ index[ii+2] = iv;
+ index[ii+1] = iv+1;
+ index[ii+0] = ivi;
+ } else {
+ index[ii+2] = iv;
+ index[ii+1] = iv+1-resolution;
+ index[ii+0] = ivi;
+ }
+
+ }
+ isi += resolution * 3;
+ c = (vertices.size()-1);
+ for (int s = 0; s < resolution; s++) {
+ int ii = isi + s*3;
+ int iv = c*resolution + s;
+ if (s < resolution - 1) {
+ index[ii+2] = iv;
+ index[ii+1] = iv+1;
+ index[ii+0] = ivi+1;
+ } else {
+ index[ii+2] = iv;
+ index[ii+1] = iv+1-resolution;
+ index[ii+0] = ivi+1;
+ }
+
+ }
+
+ }
+ }
+
+}