I need a custom cylinder mesh for my game (I can’t use the built-in mesh as it is on the XY plane rather than the XZ plane and rotating it seems to be ineffective.). I have created a DiscMesh class that contains a cylinder on the XZ plane, but the normals do not appear correctly. I should also note that I need to set the FaceCullMode
to Front
otherwise the mesh renders inside-out. It still does this even when I reverse the order of the indecies in each triangle.
I am calculating the normals as described here in the second answer with a directly up and a directly down normal for the center point.
Screenshot:
Wireframe Screenshot:
Code:
import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.util.BufferUtils;
public class DiscMesh extends Mesh{
private static final int SUBDIVISION_COUNT = 64;
private static final float SUBDIVISION_SIZE = 6.28319f / SUBDIVISION_COUNT;
public DiscMesh(float radius, float height){
//setup mesh data variables
Vector3f[] verticies = new Vector3f[(SUBDIVISION_COUNT * 2) + 2];
Vector3f[] normals = new Vector3f[verticies.length];
int[] indecies = new int[SUBDIVISION_COUNT * 12];
int currentVertex = 0;
int currentIndex = 0;
//setup mesh data generation variables
float halfHeight = height * .5f;
int[] lowerVertexNumbers = new int[SUBDIVISION_COUNT];
int[] upperVertexNumbers = new int[SUBDIVISION_COUNT];
//add center points
Vector3f lowerCenterVertex = new Vector3f(0, 0, 0);
Vector3f upperCenterVertex = new Vector3f(0, height, 0);
int lowerCenterVertexNumber = currentVertex++;
int upperCenterVertexNumber = currentVertex++;
verticies[lowerCenterVertexNumber] = lowerCenterVertex;
verticies[upperCenterVertexNumber] = upperCenterVertex;
normals[lowerCenterVertexNumber] = new Vector3f(0, -1, 0).normalizeLocal();
normals[upperCenterVertexNumber] = new Vector3f(0, 1, 0).normalizeLocal();
//add outer points
for(int i=0;i<SUBDIVISION_COUNT;i++){
float angle = SUBDIVISION_SIZE * i;
float x = (float) (radius * Math.cos(angle));
float z = (float) (radius * Math.sin(angle));
int lowerVertexNumber = currentVertex++;
int upperVertexNumber = currentVertex++;
verticies[lowerVertexNumber] = new Vector3f(x, 0, z);
verticies[upperVertexNumber] = new Vector3f(x, height, z);
normals[lowerVertexNumber] = new Vector3f(x, 0, z).subtractLocal(0, halfHeight, 0).normalizeLocal();
normals[upperVertexNumber] = new Vector3f(x, height, z).subtractLocal(0, halfHeight, 0).normalizeLocal();
lowerVertexNumbers[i] = lowerVertexNumber;
upperVertexNumbers[i] = upperVertexNumber;
}
//add triangles
for(int i=0;i<SUBDIVISION_COUNT;i++){
int next = (i + 1) % SUBDIVISION_COUNT;
int lowerVertex = lowerVertexNumbers[i];
int upperVertex = upperVertexNumbers[i];
int nextLowerVertex = lowerVertexNumbers[next];
int nextUpperVertex = upperVertexNumbers[next];
indecies[currentIndex++] = nextUpperVertex;
indecies[currentIndex++] = upperCenterVertexNumber;
indecies[currentIndex++] = upperVertex;
indecies[currentIndex++] = nextUpperVertex;
indecies[currentIndex++] = upperVertex;
indecies[currentIndex++] = lowerVertex;
indecies[currentIndex++] = nextLowerVertex;
indecies[currentIndex++] = nextUpperVertex;
indecies[currentIndex++] = lowerVertex;
indecies[currentIndex++] = lowerVertex;
indecies[currentIndex++] = lowerCenterVertexNumber;
indecies[currentIndex++] = nextLowerVertex;
}
setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(verticies));
setBuffer(Type.Index, 3, BufferUtils.createIntBuffer(indecies));
setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
updateBound();
}
}