X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.g3d.jme%2Fsrc%2Forg%2Fsimantics%2Fg3d%2Fjme%2Fshape%2FTubeActor.java;fp=org.simantics.g3d.jme%2Fsrc%2Forg%2Fsimantics%2Fg3d%2Fjme%2Fshape%2FTubeActor.java;h=fbdef4175cc8e70435deed228f487c63e973bb8a;hb=5b4454ce3dac8d0cf04caaaa696f300c16be99a0;hp=0000000000000000000000000000000000000000;hpb=2e9c37990c979fe7a877a6a9d0de65ee27f3b56f;p=simantics%2F3d.git diff --git a/org.simantics.g3d.jme/src/org/simantics/g3d/jme/shape/TubeActor.java b/org.simantics.g3d.jme/src/org/simantics/g3d/jme/shape/TubeActor.java new file mode 100644 index 00000000..fbdef417 --- /dev/null +++ b/org.simantics.g3d.jme/src/org/simantics/g3d/jme/shape/TubeActor.java @@ -0,0 +1,205 @@ +package org.simantics.g3d.jme.shape; + +import java.util.List; + +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; + +import com.jme3.app.Application; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.VertexBuffer.Type; + +public class TubeActor extends Geometry { + + List vertices; + List colors; + List radiis; + Double radius = 1.0; + int resolution = 8; + + public TubeActor() { + super(); + } + + public void setResolution(int resolution) { + if (resolution > 2) + this.resolution = resolution; + } + + public void setVertices(List vertices) { + this.vertices = vertices; + } + + public void setColors(List colors) { + this.colors = colors; + } + + public void setRadiis(List radiis) { + this.radiis = radiis; + } + + public void setRadius(Double radius) { + this.radius = radius; + } + + + + public void createTube(Application app) { + 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.0001) + throw new IllegalArgumentException("vertices at index " + i + " are too close to each other"); + } + + float points[] = new float[vertices.size()*resolution*3]; + float normals[] = new float[vertices.size()*resolution*3]; + float clrs[] = null; + if (this.colors != null) + clrs = new float[vertices.size()*resolution*4]; + + for (int i = 0; i < vertices.size(); i++) { + createCircle(i,points,normals, clrs); + } + + int index[] = new int[(vertices.size()-1)*resolution*6]; + + createIndices(index); + + Mesh mesh = new Mesh(); + mesh.setBuffer(Type.Index, 3, index); + mesh.setBuffer(Type.Position, 3, points); + mesh.setBuffer(Type.Normal, 3, normals); + if (clrs != null) + mesh.setBuffer(Type.Color, 4, clrs); + setMesh(mesh); + updateModelBound(); + + ColorRGBA color = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); + Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md"); + mat.setColor("Diffuse", color); + mat.setColor("Ambient", color); + mat.setColor("Specular", new ColorRGBA(1, 1, 1, 1)); + mat.setBoolean("UseMaterialColors", true); + if (clrs != null) + mat.setBoolean("UseVertexColor", true); + setMaterial(mat); + + vertices.clear(); + if (colors != null) + colors.clear(); + if (radiis != null) + radiis.clear(); + + } + + private void createCircle(int i, float points[],float normals[], float clrs[]) { + final Vector3d up = new Vector3d(0,1,0); + final Vector3d up2 = new Vector3d(0,0,1); + ColorRGBA c = null; + if (clrs != null) + c = this.colors.get(i); + Vector3d p = vertices.get(i); + Vector3d t = getTangent(i); + Vector3d n = new Vector3d(); + if (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; + points[vIndex+0] = (float)(p.x+v.x); + points[vIndex+1] = (float)(p.y + v.y); + points[vIndex+2] = (float)(p.z + v.z); + v.normalize(); + normals[vIndex+0] = (float)(v.x); + normals[vIndex+1] = (float)(v.y); + normals[vIndex+2] = (float)(v.z); + if (colors != null) { + int cIndex = (i*resolution + index)*4; + clrs[cIndex] = c.r; + clrs[cIndex+1] = c.g; + clrs[cIndex+2] = c.b; + clrs[cIndex+3] = c.a; + } + } + } + + private Vector3d getTangent(int i) { + Vector3d p,n; + 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); + } + n = new Vector3d(n); + n.sub(p); + n.normalize(); + return n; + } + + 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; + } + } + } + } +}