如何用JavaFX创建空心圆柱和截锥?

时间:2015-09-04 07:28:16

标签: math javafx 3d geometry

我正在学习JavaFX 3D。到目前为止,我还没有找到一种方法来创建以下对象:

  • 空心圆柱
  • 截锥

有人可以给我一个简短的代码示例吗?

任何帮助将不胜感激。 : - )

3 个答案:

答案 0 :(得分:2)

我知道这是一个老问题,但我一直在努力解决类似的问题所以这里是我的截锥的解决方案:

public class Cone extends Group{

int rounds = 360;
int r1 = 100;
int r2 = 50;
int h = 100;

public Cone() {
    Group cone = new Group();
    PhongMaterial material = new PhongMaterial(Color.BLUE);

    float[] points = new float[rounds *12];
    float[] textCoords = {
            0.5f, 0,
            0, 1,
            1, 1
    };
    int[] faces = new int[rounds *12];

    for(int i= 0; i<rounds; i++){
        int index = i*12;
        //0
        points[index] = (float)Math.cos(Math.toRadians(i))*r2;
        points[index+1] = (float)Math.sin(Math.toRadians(i))*r2;
        points[index+2] = h/2;
        //1
        points[index+3] = (float)Math.cos(Math.toRadians(i))*r1;
        points[index+4] = (float)Math.sin(Math.toRadians(i))*r1;
        points[index+5] = -h/2;
        //2
        points[index+6] = (float)Math.cos(Math.toRadians(i+1))*r1;
        points[index+7] = (float)Math.sin(Math.toRadians(i+1))*r1;
        points[index+8] = -h/2;
        //3
        points[index+9] = (float)Math.cos(Math.toRadians(i+1))*r2;
        points[index+10] = (float)Math.sin(Math.toRadians(i+1))*r2;
        points[index+11] = h/2;        
    }

    for(int i = 0; i<rounds ; i++){
        int index = i*12;
        faces[index]=i*4;
        faces[index+1]=0;
        faces[index+2]=i*4+1;
        faces[index+3]=1;
        faces[index+4]=i*4+2;
        faces[index+5]=2;

        faces[index+6]=i*4;
        faces[index+7]=0;
        faces[index+8]=i*4+2;
        faces[index+9]=1;
        faces[index+10]=i*4+3;
        faces[index+11]=2;
    }

    TriangleMesh mesh = new TriangleMesh();
    mesh.getPoints().addAll(points);
    mesh.getTexCoords().addAll(textCoords);
    mesh.getFaces().addAll(faces);

    Cylinder circle1 = new Cylinder(r1, 0.1);
    circle1.setMaterial(material);
    circle1.setTranslateZ( -h / 2);
    circle1.setRotationAxis(Rotate.X_AXIS);
    circle1.setRotate(90);

    Cylinder circle2 = new Cylinder(r2, 0.1);
    circle2.setMaterial(material);
    circle2.setTranslateZ( h / 2);
    circle2.setRotationAxis(Rotate.X_AXIS);
    circle2.setRotate(90);


     MeshView meshView = new MeshView();
    meshView.setMesh(mesh);
    meshView.setMaterial(material);
    //meshView.setDrawMode(DrawMode.LINE);
    cone.getChildren().addAll(meshView);
    Rotate r1 = new Rotate(90, Rotate.X_AXIS);
    cone.getTransforms().add(r1);
    getChildren().addAll(cone);
}

希望这可以帮助将来的某个人!

答案 1 :(得分:0)

第一个 - 创建一个圆柱体,并使用两个不同的外观对象 - 一个用于圆柱体,侧面,一个用于两个底座。对于这两个基础,使用不可见的外观(渲染属性)。有关如何将不同外观设置为基础的信息,请设置线程:  http://forum.java.sun.com/thread.jspa?threadID=663825&tstart=0

第二种 - 使用剪裁平面夹住圆筒的底部和顶部,你有一个空心圆柱。

这两种方法会给你一个空心圆柱体,内部完全是空的。

如果您正在寻找具有给定厚度的墙,则可在互联网上设置布尔操作集。创建一个大圆柱体,并减去一个较小的圆柱体。有关布尔运算集的信息,请设置此线程:http://forum.java.sun.com/thread.jspa?threadID=658612&tstart=0

最后,自己创建一个圆柱体几何体非常容易,并且可以通过循环轻松实现自动化。我将创建四个单独的几何图形:一个用于内部圆柱体,内部具有渲染面,一个用于外部圆柱体,外部具有渲染面,一个用于底部,一个圆盘在中间和底部表面具有孔渲染,一个用于顶部,另一个圆盘在中间有一个孔,顶部表面渲染。

使用三角形条带阵列可以很容易地完成所有操作。

答案 2 :(得分:0)

我开始使用此页面上其他答案中提供的代码,但我希望将其作为单个网格,两端没有圆柱体。我还计算出了更好的纹理坐标和法线。 (我使用Vecmath进行常规计算。应该将其更改为Apache Commons Math或更现代的方法...)

 /**
 * Create a cone shape. Origin is center of base (bottom circle). Height is along the Y axis
 * @param m A given TirangleMesh
 * @param res The resolution of the circles
 * @param radius The base radius
 * @param topRadius The top radius. If this is > 0 the cone is capped
 * @param height The height of the cone along the Y axis
 * @param texture The texture
 */
public static void createCone(TriangleMesh m, int res, float radius, float topRadius, float height, TextureMapping texture)
{
  if (texture == null)
    texture = defaultTextureMapping;

  m.setVertexFormat(VertexFormat.POINT_NORMAL_TEXCOORD);
      
  float[] v = new float[res * 6]; //vertices
  float[] n = new float[(res+2)*3]; //face normals
  float[] uv = new float[(res * 8) + 4]; //texture coordinates
  int[] f = new int[18*(2*res-2)]; // faces ((divisions * 18) + ((divisions-2)*18))
  
  float radPerDiv = ((float)Math.PI * 2f) / res;
  
  int tv = res * 3; //top plane vertices start index
  int tuv = (res+1) * 2; //top plane uv start index
  int bcuv = tuv * 2;//(res * 4) + 4; //bottom cap uv start index
  int tcuv = bcuv + (res * 2); //bottom cap uv start index
  for(int i = 0; i < res; i++)
  {
    int vi = i*3;  
    float cos = (float) Math.cos(radPerDiv*(i));
    float sin = (float) Math.sin(radPerDiv*(i));
    //bottom plane vertices
    v[vi] = cos * radius; //X
    v[vi + 1] = 0; //Y
    v[vi + 2] = sin * radius; //Z
    
    //top plane vertices
    v[tv + vi] = cos * topRadius; //X
    v[tv + vi + 1] = height; //Y
    v[tv + vi + 2] = sin * topRadius; //Z
    
    int uvi = i*2;
    //texture coordinate side down
    uv[uvi] = 1f-((float)i/(float)res);
    uv[uvi + 1] = 1f;
    
    //texture coordinate side up
    uv[tuv + uvi] = uv[uvi];
    uv[tuv + uvi + 1] = 0;
    
    //texture coordinate bottom cap
    uv[bcuv + uvi] = (1f+cos)/2f;
    uv[bcuv + uvi + 1] = (1f+sin)/2f;
    
    //texture coordinate top cap
    uv[tcuv + uvi] = (1f-cos)/2f;
    uv[tcuv + uvi + 1] = (1f+sin)/2f;
    
    //face normals
    if(i>0)
    {
      Vector3f p0 = new Vector3f(v[vi - 3], v[vi - 2], v[vi - 1]);
      Vector3f p1 = new Vector3f(v[vi], v[vi + 1], v[vi + 2]);
      Vector3f p2 = new Vector3f(v[tv + vi], v[tv + vi + 1], v[tv + vi + 2]);
      p1.sub(p0);
      p2.sub(p0);
      p0.cross(p2, p1);
      p0.normalize();
      n[vi - 3] = p0.x;
      n[vi - 2] = p0.y;
      n[vi - 1] = p0.z;
    }
    if(i==res-1)
    {
      Vector3f p0 = new Vector3f(v[vi], v[vi + 1], v[vi + 2]);
      Vector3f p1 = new Vector3f(v[0], v[1], v[2]);
      Vector3f p2 = new Vector3f(v[tv], v[tv + 1], v[tv + 2]);
      p1.sub(p0);
      p2.sub(p0);
      p0.cross(p2, p1);
      p0.normalize();
      n[vi] = p0.x;
      n[vi + 1] = p0.y;
      n[vi + 2] = p0.z;
    }
    
    //faces around
    int fi = i*18; 
    //first triangle of face
    f[fi] = i; //vertex
    f[fi+1] = i; //normal
    f[fi+2] = i; //uv
    
    f[fi+3] = res+i; //vertex
    f[fi+4] = i; //normal
    f[fi+5] = res+1+i; //uv
    
    f[fi+6] = i+1; //vertex
    f[fi+7] = i+1; //normal
    f[fi+8] = i+1; //uv
    
    //second triangle of face 
    f[fi+9] = i+1; //vertex
    f[fi+10] = i+1; //normal
    f[fi+11] = i+1; //uv
    
    f[fi+12] = res+i; //vertex
    f[fi+13] = i; //normal
    f[fi+14] = res+1+i; //uv
    
    f[fi+15] = res+i+1; //vertex
    f[fi+16] = i+1; //normal
    f[fi+17] = res+2+i; //uv
    
    //wrap around, use the first vertices/normals
    if(i==res-1)
    {
      f[fi+6] = 0; //vertex
      f[fi+9] = 0; //vertex
      f[fi+15] = res; //vertex
      
      f[fi+7] = 0; //normal
      f[fi+10] = 0; //normal
      f[fi+16] = 0; //normal
    }
    
    //top and bottom caps
    int fi2 = (i*9)+(res*18); //start index for bottom cap. Start after cone side is done
    int fi3 = fi2 + (res*9) - 18; //fi2 + ((divisions - 2) * 9) //start index for top cap. Start after the bottom cap is done 
    int uv2 = (res*2)+2; //start index of bottom cap texture coordinate 
    int uv3 = (res*3)+2; //start index of top cap texture coordinate 
    if(i<res-2)
    {
      //bottom cap
      f[fi2] = 0;
      f[fi2+1] = res; //normal
      f[fi2+2] = uv2; //uv
      
      f[fi2+3] = i+1;
      f[fi2+4] = res; //normal
      f[fi2+5] = uv2 + i+1; //uv
      
      f[fi2+6] = i+2;
      f[fi2+7] = res; //normal
      f[fi2+8] = uv2 + i+2; //uv
      
      //top cap
      f[fi3] = res;
      f[fi3+1] = res + 1; //normal
      f[fi3+2] = uv3; //uv
      
      f[fi3+3] = res+i+2;
      f[fi3+4] = res + 1; //normal
      f[fi3+5] = uv3  + i+2; //uv
      
      f[fi3+6] = res+i+1;
      f[fi3+7] = res + 1; //normal
      f[fi3+8] = uv3  + i+1; //uv
    }
  }
  
  //smooth normals
  float[] ns = new float[n.length];
  Vector3f n0 = new Vector3f();
  Vector3f n1 = new Vector3f();
  for(int i = 0; i < res; i++)
  {
    int p0 = i*3;
    int p1 = (i-1)*3;
    if(i==0)
      p1 = (res-1)*3;    
    n0.set(n[p0], n[p0+1], n[p0+2]);
    n1.set(n[p1], n[p1+1], n[p1+2]);
    n0.add(n1);
    n0.normalize();
    
    ns[p0] = n0.x;
    ns[p0+1] = n0.y;
    ns[p0+2] = n0.z;
  }
  
  int ni = res * 3;
  ns[ni + 1] = -1; //bottom cap normal Y axis
  ns[ni + 4] = 1; //top cap normal Y axis
  
  uv[tuv-1] = 1; //bottom ring end uv coordinate
  
  //set all data to mesh
  m.getPoints().setAll(v);
  m.getNormals().setAll(ns);
  m.getTexCoords().setAll(uv);
  m.getFaces().setAll(f);
}

编辑: 这是空心圆锥体(或圆柱体,将两个弧度都设置为相同值)的代码。在这里,我使用JavaFX向量代替Vecmath

/**
 * Create a hollow cone shape. Origin is center of base (bottom circle). Height is along the Y axis
 * @param m A given TirangleMesh
 * @param res The resolution of the circles
 * @param radius The base radius
 * @param topRadius The top radius. If this is > 0 the cone is capped
 * @param height The height of the cone along the Y axis
 * @param thickness The thickness of the cone wall
 * @param center If the origo shall be in the center, False
 * @param texture The texture
 */
public static void createHollowCone(TriangleMesh m, int res, float radius, float topRadius, float height, float thickness, boolean center, TextureMapping texture)
{
  if (texture == null)
    texture = defaultTextureMapping;
  
  m.setVertexFormat(VertexFormat.POINT_NORMAL_TEXCOORD);

  float[] v = new float[res * 12]; //vertices
  float[] n = new float[res*3]; //face normals (raw)
  float[] uv = new float[(res * 24) + 8]; //texture coordinates
  int[] f = new int[res*72]; // faces 
  
  float radPerDiv = ((float)Math.PI * 2f) / res;
  float buvf = 1-(thickness/radius);
  float tuvf = 1-(thickness/topRadius);
  
  int otcvsi = res * 3; //outside top circle vertices start index
  int ibcvsi = res * 6; //inside bottom circle vertices start index
  int itcvsi = res * 9; //inside top circle vertices start index
  
  int ifsi = res*18; //inside faces start index
  int bfsi = res*36; //bottom faces start index
  int tfsi = res*54; //bottom faces start index
  
  int tuvsi = (res+1) * 2; //top plane uv start index
  int bcuvsi = tuvsi * 2;//(res * 4) + 4; //bottom cap uv start index
  int tcuvsi = bcuvsi + (res * 4); //bottom cap uv start index
  
  int bcfuvsi = bcuvsi/2; //bottom cap faces uv start index
  int tcfuvsi = tcuvsi/2; //top cap faces uv start index
  for(int i = 0; i < res; i++)
  {
    int vi = i*3;  
    float cos = (float) Math.cos(radPerDiv*(i));
    float sin = (float) Math.sin(radPerDiv*(i));
    
    //outside bottom circle vertices
    v[vi] = cos * radius; //X
    v[vi + 1] = center?-height/2f:0; //Y
    v[vi + 2] = sin * radius; //Z
    
    //outside top circle vertices
    v[otcvsi + vi] = cos * topRadius; //X
    v[otcvsi + vi + 1] = center?height/2f:height; //Y
    v[otcvsi + vi + 2] = sin * topRadius; //Z
    
    //inside bottom circle vertices
    v[ibcvsi + vi] = cos * (radius-thickness); //X
    v[ibcvsi + vi + 1] = center?-height/2f:0; //Y
    v[ibcvsi + vi + 2] = sin * (radius-thickness); //Z
    
    //inside top circle vertices
    v[itcvsi + vi] = cos * (topRadius-thickness); //X
    v[itcvsi + vi + 1] = center?height/2f:height; //Y
    v[itcvsi + vi + 2] = sin * (topRadius-thickness); //Z
    
    
    int uvi = i*2;
    //texture coordinate outer side down
    uv[uvi] = 1f-((float)i/(float)res);
    uv[uvi + 1] = 1f;
    
    //texture coordinate outer side up
    uv[tuvsi + uvi] = uv[uvi];
    uv[tuvsi + uvi + 1] = 0;
    
    //texture coordinate bottom
    uv[bcuvsi + uvi] = (1f+cos)/2f;
    uv[bcuvsi + uvi + 1] = (1f-sin)/2f;
     
    uv[(res*2)+bcuvsi + uvi] = (1f+(cos*buvf))/2f;
    uv[(res*2)+bcuvsi + uvi + 1] = (1f-(sin*buvf))/2f;
    
    //texture coordinate top cap
    uv[tcuvsi + uvi] = (1f+cos)/2f;
    uv[tcuvsi + uvi + 1] = (1f+sin)/2f;
    
    uv[(res*2)+tcuvsi + uvi] = (1f+(cos*tuvf))/2f;
    uv[(res*2)+tcuvsi + uvi + 1] = (1f+(sin*tuvf))/2f;      
    //face normals
    if(i>0)
    {
      Point3D p0 = new Point3D(v[vi - 3], v[vi - 2], v[vi - 1]);
      Point3D p1 = new Point3D(v[vi], v[vi + 1], v[vi + 2]);
      Point3D p2 = new Point3D(v[otcvsi + vi], v[otcvsi + vi + 1], v[otcvsi + vi + 2]);
      p1 = p1.subtract(p0);
      p2 = p2.subtract(p0);
      p0 = p2.crossProduct(p1);
      p0 = p0.normalize();
      n[vi - 3] = (float)p0.getX();
      n[vi - 2] = (float)p0.getY();
      n[vi - 1] = (float)p0.getZ();
    }
    if(i==res-1)
    {
      Point3D p0 = new Point3D(v[vi], v[vi + 1], v[vi + 2]);
      Point3D p1 = new Point3D(v[0], v[1], v[2]);
      Point3D p2 = new Point3D(v[otcvsi], v[otcvsi + 1], v[otcvsi + 2]);
      p1 = p1.subtract(p0);
      p2 = p2.subtract(p0);
      p0 = p2.crossProduct(p1);
      p0 = p0.normalize();
      n[vi] = (float)p0.getX();
      n[vi + 1] = (float)p0.getY();
      n[vi + 2] = (float)p0.getZ();
    }
   
    int fi = i*18; 
    //faces around outside
    
    //first triangle of face
    f[fi] = i; //vertex
    f[fi+1] = i; //normal
    f[fi+2] = i; //uv
    
    f[fi+3] = res+i; //vertex
    f[fi+4] = i; //normal
    f[fi+5] = res+1+i; //uv
    
    f[fi+6] = i+1; //vertex
    f[fi+7] = i+1; //normal
    f[fi+8] = i+1; //uv
    
    //second triangle of face 
    f[fi+9] = i+1; //vertex
    f[fi+10] = i+1; //normal
    f[fi+11] = i+1; //uv
    
    f[fi+12] = res+i; //vertex
    f[fi+13] = i; //normal
    f[fi+14] = res+1+i; //uv
    
    f[fi+15] = res+i+1; //vertex
    f[fi+16] = i+1; //normal
    f[fi+17] = res+2+i; //uv
    
    //faces around inside
    //first triangle of face
    f[ifsi+fi] = (res*2)+i; //vertex
    f[ifsi+fi+1] = res+i; //normal
    f[ifsi+fi+2] = res-i; //uv
    
    f[ifsi+fi+3] = (res*2)+i+1; //vertex
    f[ifsi+fi+4] = res+i+1; //normal
    f[ifsi+fi+5] = res-1-i; //uv
    
    f[ifsi+fi+6] = (res*3)+i; //vertex
    f[ifsi+fi+7] = res+i; //normal
    f[ifsi+fi+8] = res+res+1-i; //uv
    
    //second triangle of face 
    f[ifsi+fi+9] = (res*2)+i+1; //vertex
    f[ifsi+fi+10] = res+i+1; //normal
    f[ifsi+fi+11] = res-1-i; //uv
    
    f[ifsi+fi+12] = (res*3)+i+1; //vertex
    f[ifsi+fi+13] = res+i+1; //normal
    f[ifsi+fi+14] = res+res-i; //uv
    
    f[ifsi+fi+15] = (res*3)+i; //vertex
    f[ifsi+fi+16] = res+i; //normal
    f[ifsi+fi+17] = res+res+1-i; //uv
    
    //faces on bottom
    //first triangle of face

    f[bfsi+fi] = i; //vertex 0
    f[bfsi+fi+1] = res*2; //normal
    f[bfsi+fi+2] = bcfuvsi+i; //uv
    
    f[bfsi+fi+3] = i+1; //vertex 1
    f[bfsi+fi+4] = res*2; //normal
    f[bfsi+fi+5] = bcfuvsi+i+1; //uv
    
    f[bfsi+fi+6] = (res*2)+i+1; //vertex n+1
    f[bfsi+fi+7] = res*2; //normal
    f[bfsi+fi+8] = bcfuvsi+res+i+1; //uv
    
    
    //second triangle of face 
    f[bfsi+fi+9] = (res*2)+i+1; //vertex n+1
    f[bfsi+fi+10] = res*2; //normal
    f[bfsi+fi+11] = bcfuvsi+res+i+1; //uv
    
    f[bfsi+fi+12] = (res*2)+i; //vertex n
    f[bfsi+fi+13] = res*2; //normal
    f[bfsi+fi+14] = bcfuvsi+res+i; //uv
    
    f[bfsi+fi+15] = i; //vertex 0
    f[bfsi+fi+16] = res*2; //normal
    f[bfsi+fi+17] = bcfuvsi+i; //uv
    
    //faces on top
    //first triangle of face
    f[tfsi+fi] = res+i; //vertex 0
    f[tfsi+fi+1] = res*2+1; //normal
    f[tfsi+fi+2] = tcfuvsi+i; //uv
    
    f[tfsi+fi+3] = (res*3)+i; //vertex n
    f[tfsi+fi+4] = res*2+1; //normal
    f[tfsi+fi+5] = tcfuvsi+res+i; //uv
    
    f[tfsi+fi+6] = (res*3)+i+1; //vertex n+1
    f[tfsi+fi+7] = res*2+1; //normal
    f[tfsi+fi+8] = tcfuvsi+res+i+1; //uv
    
    //second triangle of face 
    f[tfsi+fi+9] = (res*3)+i+1; //vertex n+1
    f[tfsi+fi+10] = res*2+1; //normal
    f[tfsi+fi+11] = tcfuvsi+res+i+1; //uv
    
    f[tfsi+fi+12] = res+i+1; //vertex 1
    f[tfsi+fi+13] = res*2+1; //normal
    f[tfsi+fi+14] = tcfuvsi+i+1; //uv
    
    f[tfsi+fi+15] = res+i; //vertex 0
    f[tfsi+fi+16] = res*2+1; //normal
    f[tfsi+fi+17] = tcfuvsi+i; //uv
    
    //wrap around, use the first vertices/normals
    if(i==res-1)
    {
      f[fi+6] = 0; //vertex
      f[fi+9] = 0; //vertex
      f[fi+15] = res; //vertex
      
      f[ifsi+fi+3] = res*2; //vertex
      f[ifsi+fi+9] = res*2; //vertex
      f[ifsi+fi+12] = res*3; //vertex
      
      f[bfsi+fi+3] = 0; //vertex
      f[bfsi+fi+6] = res*2; //vertex
      f[bfsi+fi+9] = res*2; //vertex
      
      f[tfsi+fi+6] = res*3; //vertex
      f[tfsi+fi+9] = res*3; //vertex
      f[tfsi+fi+12] = res; //vertex
      
      
      f[fi+7] = 0; //normal
      f[fi+10] = 0; //normal
      f[fi+16] = 0; //normal
      
      f[ifsi+fi+4] = res; //normal
      f[ifsi+fi+10] = res; //normal
      f[ifsi+fi+13] = res; //normal
      
      
      f[bfsi+fi+5] = bcfuvsi; //uv
      f[bfsi+fi+8] = bcfuvsi+res; //uv
      f[bfsi+fi+11] = bcfuvsi+res; //uv
      
      f[tfsi+fi+8] = tcfuvsi+res; //uv
      f[tfsi+fi+11] = tcfuvsi+res; //uv
      f[tfsi+fi+14] = tcfuvsi; //uv
      
      
    }
    
    
  }
  
  //smooth normals
  float[] ns = new float[(n.length*2)+6];
  int ni = res * 3;
  for(int i = 0; i < res; i++)
  {
    int p0 = i*3;
    int p1 = (i-1)*3;
    if(i==0)
      p1 = (res-1)*3;    
    Point3D n0 = new Point3D(n[p0], n[p0+1], n[p0+2]);
    Point3D n1 = new Point3D(n[p1], n[p1+1], n[p1+2]);
    n0 = n0.add(n1);
    n0 = n0.normalize();

    ns[p0] = (float)n0.getX();
    ns[p0+1] = (float)n0.getY();
    ns[p0+2] = (float)n0.getZ();
    
    n0 = n0.multiply(-1);
    ns[ni+p0] = (float)n0.getX();
    ns[ni+p0+1] = (float)n0.getY();
    ns[ni+p0+2] = (float)n0.getZ();

  }
  
  ni = res * 6;
  ns[ni + 1] = -1; //bottom cap normal Y axis
  ns[ni + 4] = 1; //top cap normal Y axis
  
  uv[tuvsi-1] = 1; //bottom ring end uv coordinate
  
  
  //set all data to mesh
  m.getPoints().setAll(v);
  m.getNormals().setAll(ns);
  m.getTexCoords().setAll(uv);
  m.getFaces().setAll(f);
}