How to create hollow cylinder and truncated cone with JavaFX?

前端 未结 3 713
既然无缘
既然无缘 2021-01-26 07:20

I\'m learning JavaFX 3D. So far I have not found a way how I can create the following objects:

  • Hollow cylinder
  • Truncated cone

Can someone p

3条回答
  •  爱一瞬间的悲伤
    2021-01-26 07:59

    I started using the code supplied in an other answer on this page, but I wanted to make it as a single mesh without the cylinders in the ends. I also calculated better texture coordinates and normals. (I use Vecmath for the normal calculation. This should probably be changed to Apache commons math or something more modern...)

     /**
     * 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

    Edit: And here is code for a hollow cone (or cylinder, just set both rads to same value) Here I am using JavaFX vectors in stead of 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);
    }
    

提交回复
热议问题