|
|
@ -40,14 +40,11 @@ import com.jme3.math.FastMath; |
|
|
|
import com.jme3.math.Vector3f; |
|
|
|
import com.jme3.math.Vector3f; |
|
|
|
import com.jme3.scene.Mesh; |
|
|
|
import com.jme3.scene.Mesh; |
|
|
|
import com.jme3.scene.VertexBuffer.Type; |
|
|
|
import com.jme3.scene.VertexBuffer.Type; |
|
|
|
import com.jme3.scene.mesh.IndexBuffer; |
|
|
|
|
|
|
|
import com.jme3.util.BufferUtils; |
|
|
|
import com.jme3.util.BufferUtils; |
|
|
|
import static com.jme3.util.BufferUtils.*; |
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
import java.io.IOException; |
|
|
|
import java.nio.FloatBuffer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* A simple cylinder, defined by it's height and radius. |
|
|
|
* A simple cylinder, defined by its height and radius. |
|
|
|
* (Ported to jME3) |
|
|
|
* (Ported to jME3) |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Mark Powell |
|
|
|
* @author Mark Powell |
|
|
@ -127,10 +124,10 @@ public class Cylinder extends Mesh { |
|
|
|
* mapped to texture coordinates (0.5, 1), bottom to (0.5, 0). Thus you need |
|
|
|
* mapped to texture coordinates (0.5, 1), bottom to (0.5, 0). Thus you need |
|
|
|
* a suited distorted texture. |
|
|
|
* a suited distorted texture. |
|
|
|
* |
|
|
|
* |
|
|
|
* @param axisSamples |
|
|
|
* @param axisSamples The number of vertices samples along the axis. It is equal to the number of segments + 1; so |
|
|
|
* Number of triangle samples along the axis. |
|
|
|
* that, for instance, 4 samples mean the cylinder will be made of 3 segments. |
|
|
|
* @param radialSamples |
|
|
|
* @param radialSamples The number of triangle samples along the radius. For instance, 4 means that the sides of the |
|
|
|
* Number of triangle samples along the radial. |
|
|
|
* cylinder are made of 4 rectangles, and the top and bottom are made of 4 triangles. |
|
|
|
* @param radius |
|
|
|
* @param radius |
|
|
|
* The radius of the cylinder. |
|
|
|
* The radius of the cylinder. |
|
|
|
* @param height |
|
|
|
* @param height |
|
|
@ -201,194 +198,240 @@ public class Cylinder extends Mesh { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* Rebuilds the cylinder based on a new set of parameters. |
|
|
|
* Rebuilds the cylinder based on a new set of parameters. |
|
|
|
* |
|
|
|
* |
|
|
|
* @param axisSamples the number of samples along the axis. |
|
|
|
* @param axisSamples The number of vertices samples along the axis. It is equal to the number of segments + 1; so |
|
|
|
* @param radialSamples the number of samples around the radial. |
|
|
|
* that, for instance, 4 samples mean the cylinder will be made of 3 segments. |
|
|
|
* @param radius the radius of the bottom of the cylinder. |
|
|
|
* @param radialSamples The number of triangle samples along the radius. For instance, 4 means that the sides of the |
|
|
|
* @param radius2 the radius of the top of the cylinder. |
|
|
|
* cylinder are made of 4 rectangles, and the top and bottom are made of 4 triangles. |
|
|
|
|
|
|
|
* @param topRadius the radius of the top of the cylinder. |
|
|
|
|
|
|
|
* @param bottomRadius the radius of the bottom of the cylinder. |
|
|
|
* @param height the cylinder's height. |
|
|
|
* @param height the cylinder's height. |
|
|
|
* @param closed should the cylinder have top and bottom surfaces. |
|
|
|
* @param closed should the cylinder have top and bottom surfaces. |
|
|
|
* @param inverted is the cylinder is meant to be viewed from the inside. |
|
|
|
* @param inverted is the cylinder is meant to be viewed from the inside. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void updateGeometry(int axisSamples, int radialSamples, |
|
|
|
public void updateGeometry(int axisSamples, int radialSamples, |
|
|
|
float radius, float radius2, float height, boolean closed, boolean inverted) { |
|
|
|
float topRadius, float bottomRadius, float height, boolean closed, boolean inverted) |
|
|
|
this.axisSamples = axisSamples; |
|
|
|
{ |
|
|
|
|
|
|
|
// Ensure there's at least two axis samples and 3 radial samples, and positive geometries.
|
|
|
|
|
|
|
|
if( axisSamples < 2 |
|
|
|
|
|
|
|
|| radialSamples < 3 |
|
|
|
|
|
|
|
|| topRadius <= 0 |
|
|
|
|
|
|
|
|| bottomRadius <= 0 |
|
|
|
|
|
|
|
|| height <= 0 ) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.axisSamples = axisSamples; |
|
|
|
this.radialSamples = radialSamples; |
|
|
|
this.radialSamples = radialSamples; |
|
|
|
this.radius = radius; |
|
|
|
this.radius = bottomRadius; |
|
|
|
this.radius2 = radius2; |
|
|
|
this.radius2 = topRadius; |
|
|
|
this.height = height; |
|
|
|
this.height = height; |
|
|
|
this.closed = closed; |
|
|
|
this.closed = closed; |
|
|
|
this.inverted = inverted; |
|
|
|
this.inverted = inverted; |
|
|
|
|
|
|
|
|
|
|
|
// VertexBuffer pvb = getBuffer(Type.Position);
|
|
|
|
// Vertices : One per radial sample plus one duplicate for texture closing around the sides.
|
|
|
|
// VertexBuffer nvb = getBuffer(Type.Normal);
|
|
|
|
int verticesCount = axisSamples * (radialSamples +1); |
|
|
|
// VertexBuffer tvb = getBuffer(Type.TexCoord);
|
|
|
|
// Triangles: Two per side rectangle, which is the product of numbers of samples.
|
|
|
|
axisSamples += (closed ? 2 : 0); |
|
|
|
int trianglesCount = axisSamples * radialSamples * 2 ; |
|
|
|
|
|
|
|
if( closed ) |
|
|
|
// Vertices
|
|
|
|
{ |
|
|
|
int vertCount = axisSamples * (radialSamples + 1) + (closed ? 2 : 0); |
|
|
|
// If there are caps, add two additional rims and two summits.
|
|
|
|
|
|
|
|
verticesCount += 2 + 2 * (radialSamples +1); |
|
|
|
setBuffer(Type.Position, 3, createVector3Buffer(getFloatBuffer(Type.Position), vertCount)); |
|
|
|
// Add one triangle per radial sample, twice, to form the caps.
|
|
|
|
|
|
|
|
trianglesCount += 2 * radialSamples ; |
|
|
|
// Normals
|
|
|
|
} |
|
|
|
setBuffer(Type.Normal, 3, createVector3Buffer(getFloatBuffer(Type.Normal), vertCount)); |
|
|
|
|
|
|
|
|
|
|
|
// Compute the points along a unit circle:
|
|
|
|
// Texture co-ordinates
|
|
|
|
float[][] circlePoints = new float[radialSamples+1][2]; |
|
|
|
setBuffer(Type.TexCoord, 2, createVector2Buffer(vertCount)); |
|
|
|
for (int circlePoint = 0; circlePoint < radialSamples; circlePoint++) |
|
|
|
|
|
|
|
{ |
|
|
|
int triCount = ((closed ? 2 : 0) + 2 * (axisSamples - 1)) * radialSamples; |
|
|
|
float angle = FastMath.TWO_PI / radialSamples * circlePoint; |
|
|
|
|
|
|
|
circlePoints[circlePoint][0] = FastMath.cos(angle); |
|
|
|
setBuffer(Type.Index, 3, createShortBuffer(getShortBuffer(Type.Index), 3 * triCount)); |
|
|
|
circlePoints[circlePoint][1] = FastMath.sin(angle); |
|
|
|
|
|
|
|
|
|
|
|
// generate geometry
|
|
|
|
|
|
|
|
float inverseRadial = 1.0f / radialSamples; |
|
|
|
|
|
|
|
float inverseAxisLess = 1.0f / (closed ? axisSamples - 3 : axisSamples - 1); |
|
|
|
|
|
|
|
float inverseAxisLessTexture = 1.0f / (axisSamples - 1); |
|
|
|
|
|
|
|
float halfHeight = 0.5f * height; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate points on the unit circle to be used in computing the mesh
|
|
|
|
|
|
|
|
// points on a cylinder slice.
|
|
|
|
|
|
|
|
float[] sin = new float[radialSamples + 1]; |
|
|
|
|
|
|
|
float[] cos = new float[radialSamples + 1]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int radialCount = 0; radialCount < radialSamples; radialCount++) { |
|
|
|
|
|
|
|
float angle = FastMath.TWO_PI * inverseRadial * radialCount; |
|
|
|
|
|
|
|
cos[radialCount] = FastMath.cos(angle); |
|
|
|
|
|
|
|
sin[radialCount] = FastMath.sin(angle); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
sin[radialSamples] = sin[0]; |
|
|
|
// Add an additional point for closing the texture around the side of the cylinder.
|
|
|
|
cos[radialSamples] = cos[0]; |
|
|
|
circlePoints[radialSamples][0] = circlePoints[0][0]; |
|
|
|
|
|
|
|
circlePoints[radialSamples][1] = circlePoints[0][1]; |
|
|
|
// calculate normals
|
|
|
|
|
|
|
|
Vector3f[] vNormals = null; |
|
|
|
// Calculate normals.
|
|
|
|
Vector3f vNormal = Vector3f.UNIT_Z; |
|
|
|
//
|
|
|
|
|
|
|
|
// A---------B
|
|
|
|
if ((height != 0.0f) && (radius != radius2)) { |
|
|
|
// \ |
|
|
|
|
vNormals = new Vector3f[radialSamples]; |
|
|
|
// \ |
|
|
|
|
Vector3f vHeight = Vector3f.UNIT_Z.mult(height); |
|
|
|
// \ |
|
|
|
|
Vector3f vRadial = new Vector3f(); |
|
|
|
// D-----C
|
|
|
|
|
|
|
|
//
|
|
|
|
for (int radialCount = 0; radialCount < radialSamples; radialCount++) { |
|
|
|
// Let be B and C the top and bottom points of the axis, and A and D the top and bottom edges.
|
|
|
|
vRadial.set(cos[radialCount], sin[radialCount], 0.0f); |
|
|
|
// The normal in A and D is simply orthogonal to AD, which means we can get it once per sample.
|
|
|
|
Vector3f vRadius = vRadial.mult(radius); |
|
|
|
//
|
|
|
|
Vector3f vRadius2 = vRadial.mult(radius2); |
|
|
|
Vector3f[] circleNormals = new Vector3f[radialSamples+1]; |
|
|
|
Vector3f vMantle = vHeight.subtract(vRadius2.subtract(vRadius)); |
|
|
|
for (int circlePoint = 0; circlePoint < radialSamples+1; circlePoint++) |
|
|
|
Vector3f vTangent = vRadial.cross(Vector3f.UNIT_Z); |
|
|
|
{ |
|
|
|
vNormals[radialCount] = vMantle.cross(vTangent).normalize(); |
|
|
|
// The normal is the orthogonal to the side, which can be got without trigonometry.
|
|
|
|
} |
|
|
|
// The edge direction is oriented so that it goes up by Height, and out by the radius difference; let's use
|
|
|
|
} |
|
|
|
// those values in reverse order.
|
|
|
|
|
|
|
|
Vector3f normal = new Vector3f(height * circlePoints[circlePoint][0], height * circlePoints[circlePoint][1], bottomRadius - topRadius ); |
|
|
|
FloatBuffer nb = getFloatBuffer(Type.Normal); |
|
|
|
circleNormals[circlePoint] = normal.normalizeLocal(); |
|
|
|
FloatBuffer pb = getFloatBuffer(Type.Position); |
|
|
|
|
|
|
|
FloatBuffer tb = getFloatBuffer(Type.TexCoord); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// generate the cylinder itself
|
|
|
|
|
|
|
|
Vector3f tempNormal = new Vector3f(); |
|
|
|
|
|
|
|
for (int axisCount = 0, i = 0; axisCount < axisSamples; axisCount++, i++) { |
|
|
|
|
|
|
|
float axisFraction; |
|
|
|
|
|
|
|
float axisFractionTexture; |
|
|
|
|
|
|
|
int topBottom = 0; |
|
|
|
|
|
|
|
if (!closed) { |
|
|
|
|
|
|
|
axisFraction = axisCount * inverseAxisLess; // in [0,1]
|
|
|
|
|
|
|
|
axisFractionTexture = axisFraction; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (axisCount == 0) { |
|
|
|
|
|
|
|
topBottom = -1; // bottom
|
|
|
|
|
|
|
|
axisFraction = 0; |
|
|
|
|
|
|
|
axisFractionTexture = inverseAxisLessTexture; |
|
|
|
|
|
|
|
} else if (axisCount == axisSamples - 1) { |
|
|
|
|
|
|
|
topBottom = 1; // top
|
|
|
|
|
|
|
|
axisFraction = 1; |
|
|
|
|
|
|
|
axisFractionTexture = 1 - inverseAxisLessTexture; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
axisFraction = (axisCount - 1) * inverseAxisLess; |
|
|
|
|
|
|
|
axisFractionTexture = axisCount * inverseAxisLessTexture; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// compute center of slice
|
|
|
|
|
|
|
|
float z = -halfHeight + height * axisFraction; |
|
|
|
|
|
|
|
Vector3f sliceCenter = new Vector3f(0, 0, z); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// compute slice vertices with duplication at end point
|
|
|
|
|
|
|
|
int save = i; |
|
|
|
|
|
|
|
for (int radialCount = 0; radialCount < radialSamples; radialCount++, i++) { |
|
|
|
|
|
|
|
float radialFraction = radialCount * inverseRadial; // in [0,1)
|
|
|
|
|
|
|
|
tempNormal.set(cos[radialCount], sin[radialCount], 0.0f); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (vNormals != null) { |
|
|
|
|
|
|
|
vNormal = vNormals[radialCount]; |
|
|
|
|
|
|
|
} else if (radius == radius2) { |
|
|
|
|
|
|
|
vNormal = tempNormal; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (topBottom == 0) { |
|
|
|
|
|
|
|
if (!inverted) |
|
|
|
|
|
|
|
nb.put(vNormal.x).put(vNormal.y).put(vNormal.z); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
nb.put(-vNormal.x).put(-vNormal.y).put(-vNormal.z); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
nb.put(0).put(0).put(topBottom * (inverted ? -1 : 1)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tempNormal.multLocal((radius - radius2) * axisFraction + radius2) |
|
|
|
|
|
|
|
.addLocal(sliceCenter); |
|
|
|
|
|
|
|
pb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tb.put((inverted ? 1 - radialFraction : radialFraction)) |
|
|
|
|
|
|
|
.put(axisFractionTexture); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BufferUtils.copyInternalVector3(pb, save, i); |
|
|
|
|
|
|
|
BufferUtils.copyInternalVector3(nb, save, i); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tb.put((inverted ? 0.0f : 1.0f)) |
|
|
|
|
|
|
|
.put(axisFractionTexture); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (closed) { |
|
|
|
float[] vertices = new float[verticesCount * 3]; |
|
|
|
pb.put(0).put(0).put(-halfHeight); // bottom center
|
|
|
|
float[] normals = new float[verticesCount * 3]; |
|
|
|
nb.put(0).put(0).put(-1 * (inverted ? -1 : 1)); |
|
|
|
float[] textureCoords = new float[verticesCount * 2]; |
|
|
|
tb.put(0.5f).put(0); |
|
|
|
int currentIndex = 0; |
|
|
|
pb.put(0).put(0).put(halfHeight); // top center
|
|
|
|
|
|
|
|
nb.put(0).put(0).put(1 * (inverted ? -1 : 1)); |
|
|
|
// Add a circle of points for each axis sample.
|
|
|
|
tb.put(0.5f).put(1); |
|
|
|
for(int axisSample = 0; axisSample < axisSamples; axisSample++ ) |
|
|
|
} |
|
|
|
{ |
|
|
|
|
|
|
|
float currentHeight = -height / 2 + height * axisSample / (axisSamples-1); |
|
|
|
IndexBuffer ib = getIndexBuffer(); |
|
|
|
float currentRadius = bottomRadius + (topRadius - bottomRadius) * axisSample / (axisSamples-1); |
|
|
|
int index = 0; |
|
|
|
|
|
|
|
// Connectivity
|
|
|
|
for (int circlePoint = 0; circlePoint < radialSamples + 1; circlePoint++) |
|
|
|
for (int axisCount = 0, axisStart = 0; axisCount < axisSamples - 1; axisCount++) { |
|
|
|
{ |
|
|
|
int i0 = axisStart; |
|
|
|
// Position, by multipliying the position on a unit circle with the current radius.
|
|
|
|
int i1 = i0 + 1; |
|
|
|
vertices[currentIndex*3] = circlePoints[circlePoint][0] * currentRadius; |
|
|
|
axisStart += radialSamples + 1; |
|
|
|
vertices[currentIndex*3 +1] = circlePoints[circlePoint][1] * currentRadius; |
|
|
|
int i2 = axisStart; |
|
|
|
vertices[currentIndex*3 +2] = currentHeight; |
|
|
|
int i3 = i2 + 1; |
|
|
|
|
|
|
|
for (int i = 0; i < radialSamples; i++) { |
|
|
|
// Normal
|
|
|
|
if (closed && axisCount == 0) { |
|
|
|
Vector3f currentNormal = circleNormals[circlePoint]; |
|
|
|
if (!inverted) { |
|
|
|
normals[currentIndex*3] = currentNormal.x; |
|
|
|
ib.put(index++, i0++); |
|
|
|
normals[currentIndex*3+1] = currentNormal.y; |
|
|
|
ib.put(index++, vertCount - 2); |
|
|
|
normals[currentIndex*3+2] = currentNormal.z; |
|
|
|
ib.put(index++, i1++); |
|
|
|
|
|
|
|
} else { |
|
|
|
// Texture
|
|
|
|
ib.put(index++, i0++); |
|
|
|
// The X is the angular position of the point.
|
|
|
|
ib.put(index++, i1++); |
|
|
|
textureCoords[currentIndex *2] = (float) circlePoint / radialSamples; |
|
|
|
ib.put(index++, vertCount - 2); |
|
|
|
// Depending on whether there is a cap, the Y is either the height scaled to [0,1], or the radii of
|
|
|
|
} |
|
|
|
// the cap count as well.
|
|
|
|
} else if (closed && axisCount == axisSamples - 2) { |
|
|
|
if (closed) |
|
|
|
ib.put(index++, i2++); |
|
|
|
textureCoords[currentIndex *2 +1] = (bottomRadius + height / 2 + currentHeight) / (bottomRadius + height + topRadius); |
|
|
|
ib.put(index++, inverted ? vertCount - 1 : i3++); |
|
|
|
else |
|
|
|
ib.put(index++, inverted ? i3++ : vertCount - 1); |
|
|
|
textureCoords[currentIndex *2 +1] = height / 2 + currentHeight; |
|
|
|
} else { |
|
|
|
|
|
|
|
ib.put(index++, i0++); |
|
|
|
currentIndex++; |
|
|
|
ib.put(index++, inverted ? i2 : i1); |
|
|
|
} |
|
|
|
ib.put(index++, inverted ? i1 : i2); |
|
|
|
} |
|
|
|
ib.put(index++, i1++); |
|
|
|
|
|
|
|
ib.put(index++, inverted ? i2++ : i3++); |
|
|
|
// If closed, add duplicate rims on top and bottom, with normals facing up and down.
|
|
|
|
ib.put(index++, inverted ? i3++ : i2++); |
|
|
|
if (closed) |
|
|
|
} |
|
|
|
{ |
|
|
|
} |
|
|
|
// Bottom
|
|
|
|
|
|
|
|
for (int circlePoint = 0; circlePoint < radialSamples + 1; circlePoint++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vertices[currentIndex*3] = circlePoints[circlePoint][0] * bottomRadius; |
|
|
|
|
|
|
|
vertices[currentIndex*3 +1] = circlePoints[circlePoint][1] * bottomRadius; |
|
|
|
|
|
|
|
vertices[currentIndex*3 +2] = -height/2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
normals[currentIndex*3] = 0; |
|
|
|
|
|
|
|
normals[currentIndex*3+1] = 0; |
|
|
|
|
|
|
|
normals[currentIndex*3+2] = -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
textureCoords[currentIndex *2] = (float) circlePoint / radialSamples; |
|
|
|
|
|
|
|
textureCoords[currentIndex *2 +1] = bottomRadius / (bottomRadius + height + topRadius); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentIndex++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Top
|
|
|
|
|
|
|
|
for (int circlePoint = 0; circlePoint < radialSamples + 1; circlePoint++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vertices[currentIndex*3] = circlePoints[circlePoint][0] * topRadius; |
|
|
|
|
|
|
|
vertices[currentIndex*3 +1] = circlePoints[circlePoint][1] * topRadius; |
|
|
|
|
|
|
|
vertices[currentIndex*3 +2] = height/2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
normals[currentIndex*3] = 0; |
|
|
|
|
|
|
|
normals[currentIndex*3+1] = 0; |
|
|
|
|
|
|
|
normals[currentIndex*3+2] = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
textureCoords[currentIndex *2] = (float) circlePoint / radialSamples; |
|
|
|
|
|
|
|
textureCoords[currentIndex *2 +1] = (bottomRadius + height) / (bottomRadius + height + topRadius); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentIndex++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add the centers of the caps.
|
|
|
|
|
|
|
|
vertices[currentIndex*3] = 0; |
|
|
|
|
|
|
|
vertices[currentIndex*3 +1] = 0; |
|
|
|
|
|
|
|
vertices[currentIndex*3 +2] = -height/2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
normals[currentIndex*3] = 0; |
|
|
|
|
|
|
|
normals[currentIndex*3+1] = 0; |
|
|
|
|
|
|
|
normals[currentIndex*3+2] = -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
textureCoords[currentIndex *2] = 0.5f; |
|
|
|
|
|
|
|
textureCoords[currentIndex *2+1] = 0f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentIndex++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vertices[currentIndex*3] = 0; |
|
|
|
|
|
|
|
vertices[currentIndex*3 +1] = 0; |
|
|
|
|
|
|
|
vertices[currentIndex*3 +2] = height/2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
normals[currentIndex*3] = 0; |
|
|
|
|
|
|
|
normals[currentIndex*3+1] = 0; |
|
|
|
|
|
|
|
normals[currentIndex*3+2] = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
textureCoords[currentIndex *2] = 0.5f; |
|
|
|
|
|
|
|
textureCoords[currentIndex *2+1] = 1f; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add the triangles indexes.
|
|
|
|
|
|
|
|
short[] indices = new short[trianglesCount * 3]; |
|
|
|
|
|
|
|
currentIndex = 0; |
|
|
|
|
|
|
|
for (short axisSample = 0; axisSample < axisSamples - 1; axisSample++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for (int circlePoint = 0; circlePoint < radialSamples; circlePoint++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
indices[currentIndex++] = (short) (axisSample * (radialSamples + 1) + circlePoint); |
|
|
|
|
|
|
|
indices[currentIndex++] = (short) (axisSample * (radialSamples + 1) + circlePoint + 1); |
|
|
|
|
|
|
|
indices[currentIndex++] = (short) ((axisSample + 1) * (radialSamples + 1) + circlePoint); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
indices[currentIndex++] = (short) ((axisSample + 1) * (radialSamples + 1) + circlePoint); |
|
|
|
|
|
|
|
indices[currentIndex++] = (short) (axisSample * (radialSamples + 1) + circlePoint + 1); |
|
|
|
|
|
|
|
indices[currentIndex++] = (short) ((axisSample + 1) * (radialSamples + 1) + circlePoint + 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Add caps if needed.
|
|
|
|
|
|
|
|
if(closed) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
short bottomCapIndex = (short) (verticesCount - 2); |
|
|
|
|
|
|
|
short topCapIndex = (short) (verticesCount - 1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int bottomRowOffset = (axisSamples) * (radialSamples +1 ); |
|
|
|
|
|
|
|
int topRowOffset = (axisSamples+1) * (radialSamples +1 ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int circlePoint = 0; circlePoint < radialSamples; circlePoint++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
indices[currentIndex++] = (short) (bottomRowOffset + circlePoint +1); |
|
|
|
|
|
|
|
indices[currentIndex++] = (short) (bottomRowOffset + circlePoint); |
|
|
|
|
|
|
|
indices[currentIndex++] = bottomCapIndex; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
indices[currentIndex++] = (short) (topRowOffset + circlePoint); |
|
|
|
|
|
|
|
indices[currentIndex++] = (short) (topRowOffset + circlePoint +1); |
|
|
|
|
|
|
|
indices[currentIndex++] = topCapIndex; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If inverted, the triangles and normals are all reverted.
|
|
|
|
|
|
|
|
if (inverted) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for (int i = 0; i < indices.length / 2; i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
short temp = indices[i]; |
|
|
|
|
|
|
|
indices[i] = indices[indices.length - 1 - i]; |
|
|
|
|
|
|
|
indices[indices.length - 1 - i] = temp; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i< normals.length; i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
normals[i] = -normals[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Fill in the buffers.
|
|
|
|
|
|
|
|
setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices)); |
|
|
|
|
|
|
|
setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals)); |
|
|
|
|
|
|
|
setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(textureCoords)); |
|
|
|
|
|
|
|
setBuffer(Type.Index, 3, BufferUtils.createShortBuffer(indices)); |
|
|
|
|
|
|
|
|
|
|
|
updateBound(); |
|
|
|
updateBound(); |
|
|
|
setStatic(); |
|
|
|
setStatic(); |
|
|
|
} |
|
|
|
} |
|
|
@ -418,6 +461,4 @@ public class Cylinder extends Mesh { |
|
|
|
capsule.write(closed, "closed", false); |
|
|
|
capsule.write(closed, "closed", false); |
|
|
|
capsule.write(inverted, "inverted", false); |
|
|
|
capsule.write(inverted, "inverted", false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|