1 package org.simantics.g3d.jme.shape;
\r
3 import java.util.List;
\r
5 import javax.vecmath.AxisAngle4d;
\r
6 import javax.vecmath.Vector3d;
\r
8 import org.simantics.g3d.math.MathTools;
\r
10 import com.jme3.app.Application;
\r
11 import com.jme3.material.Material;
\r
12 import com.jme3.math.ColorRGBA;
\r
13 import com.jme3.scene.Geometry;
\r
14 import com.jme3.scene.Mesh;
\r
15 import com.jme3.scene.VertexBuffer.Type;
\r
17 public class TubeActor extends Geometry {
\r
19 List<Vector3d> vertices;
\r
20 List<ColorRGBA> colors;
\r
21 List<Double> radiis;
\r
22 Double radius = 1.0;
\r
25 public TubeActor() {
\r
29 public void setResolution(int resolution) {
\r
31 this.resolution = resolution;
\r
34 public void setVertices(List<Vector3d> vertices) {
\r
35 this.vertices = vertices;
\r
38 public void setColors(List<ColorRGBA> colors) {
\r
39 this.colors = colors;
\r
42 public void setRadiis(List<Double> radiis) {
\r
43 this.radiis = radiis;
\r
46 public void setRadius(Double radius) {
\r
47 this.radius = radius;
\r
52 public void createTube(Application app) {
\r
53 if (vertices.size() < 2 )
\r
54 throw new IllegalArgumentException("Tube must have at least two vertices");
\r
56 Vector3d t = new Vector3d();
\r
58 for (int i = 0; i < vertices.size() - 1; i++) {
\r
59 t.set(vertices.get(i+1));
\r
60 t.sub(vertices.get(i));
\r
61 if (t.lengthSquared() < 0.0001)
\r
62 throw new IllegalArgumentException("vertices at index " + i + " are too close to each other");
\r
65 float points[] = new float[vertices.size()*resolution*3];
\r
66 float normals[] = new float[vertices.size()*resolution*3];
\r
67 float clrs[] = null;
\r
68 if (this.colors != null)
\r
69 clrs = new float[vertices.size()*resolution*4];
\r
71 for (int i = 0; i < vertices.size(); i++) {
\r
72 createCircle(i,points,normals, clrs);
\r
75 int index[] = new int[(vertices.size()-1)*resolution*6];
\r
77 createIndices(index);
\r
79 Mesh mesh = new Mesh();
\r
80 mesh.setBuffer(Type.Index, 3, index);
\r
81 mesh.setBuffer(Type.Position, 3, points);
\r
82 mesh.setBuffer(Type.Normal, 3, normals);
\r
84 mesh.setBuffer(Type.Color, 4, clrs);
\r
88 ColorRGBA color = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);
\r
89 Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
\r
90 mat.setColor("Diffuse", color);
\r
91 mat.setColor("Ambient", color);
\r
92 mat.setColor("Specular", new ColorRGBA(1, 1, 1, 1));
\r
93 mat.setBoolean("UseMaterialColors", true);
\r
95 mat.setBoolean("UseVertexColor", true);
\r
101 if (radiis != null)
\r
106 private void createCircle(int i, float points[],float normals[], float clrs[]) {
\r
107 final Vector3d up = new Vector3d(0,1,0);
\r
108 final Vector3d up2 = new Vector3d(0,0,1);
\r
109 ColorRGBA c = null;
\r
111 c = this.colors.get(i);
\r
112 Vector3d p = vertices.get(i);
\r
113 Vector3d t = getTangent(i);
\r
114 Vector3d n = new Vector3d();
\r
115 if (up.dot(t) < 0.99) {
\r
121 if (radiis != null) {
\r
122 n.scale(radiis.get(i));
\r
127 for (int index = 0; index < resolution; index ++) {
\r
130 v = new Vector3d(n);
\r
133 AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)resolution);
\r
134 v = new Vector3d();
\r
135 MathTools.rotate(MathTools.getQuat(aa), n, v);
\r
137 int vIndex = (i*resolution + index)*3;
\r
138 points[vIndex+0] = (float)(p.x+v.x);
\r
139 points[vIndex+1] = (float)(p.y + v.y);
\r
140 points[vIndex+2] = (float)(p.z + v.z);
\r
142 normals[vIndex+0] = (float)(v.x);
\r
143 normals[vIndex+1] = (float)(v.y);
\r
144 normals[vIndex+2] = (float)(v.z);
\r
145 if (colors != null) {
\r
146 int cIndex = (i*resolution + index)*4;
\r
147 clrs[cIndex] = c.r;
\r
148 clrs[cIndex+1] = c.g;
\r
149 clrs[cIndex+2] = c.b;
\r
150 clrs[cIndex+3] = c.a;
\r
155 private Vector3d getTangent(int i) {
\r
158 p = vertices.get(0);
\r
159 n = vertices.get(1);
\r
160 } else if (i == vertices.size() - 1) {
\r
161 p = vertices.get(i-1);
\r
162 n = vertices.get(i);
\r
164 p = vertices.get(i-1);
\r
165 n = vertices.get(i+1);
\r
167 n = new Vector3d(n);
\r
173 private void createIndices(int index[]) {
\r
174 for (int c = 0; c < vertices.size() - 1; c++) {
\r
175 for (int s = 0; s < resolution; s++) {
\r
176 int ii = (c * resolution + s) * 6;
\r
177 int iv = c*resolution + s;
\r
180 iv+1 ---- iv + resolution + 1
\r
183 iv ---- iv + resolution
\r
185 if (s < resolution - 1) {
\r
187 index[ii+1] = iv+resolution;
\r
188 index[ii+0] = iv+resolution+1;
\r
191 index[ii+4] = iv+resolution+1;
\r
192 index[ii+3] = iv+1;
\r
195 index[ii+1] = iv+resolution;
\r
196 index[ii+0] = iv+1;
\r
199 index[ii+4] = iv+1;
\r
200 index[ii+3] = iv+1-resolution;
\r