I\'m learning JavaFX 3D. So far I have not found a way how I can create the following objects:
Can someone p
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);
}