* Apply fix for cylinder normal generation
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8425 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
b5f567753c
commit
1fb4a9be00
@ -1,395 +1,421 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
* met:
|
* met:
|
||||||
*
|
*
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// $Id: Cylinder.java 4131 2009-03-19 20:15:28Z blaine.dev $
|
// $Id: Cylinder.java 4131 2009-03-19 20:15:28Z blaine.dev $
|
||||||
package com.jme3.scene.shape;
|
package com.jme3.scene.shape;
|
||||||
|
|
||||||
import com.jme3.export.InputCapsule;
|
import com.jme3.export.InputCapsule;
|
||||||
import com.jme3.export.JmeExporter;
|
import com.jme3.export.JmeExporter;
|
||||||
import com.jme3.export.JmeImporter;
|
import com.jme3.export.JmeImporter;
|
||||||
import com.jme3.export.OutputCapsule;
|
import com.jme3.export.OutputCapsule;
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.scene.mesh.IndexBuffer;
|
import com.jme3.scene.mesh.IndexBuffer;
|
||||||
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.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
import static com.jme3.util.BufferUtils.*;
|
import static com.jme3.util.BufferUtils.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple cylinder, defined by it's height and radius.
|
* A simple cylinder, defined by it's height and radius.
|
||||||
* (Ported to jME3)
|
* (Ported to jME3)
|
||||||
*
|
*
|
||||||
* @author Mark Powell
|
* @author Mark Powell
|
||||||
* @version $Revision: 4131 $, $Date: 2009-03-19 16:15:28 -0400 (Thu, 19 Mar 2009) $
|
* @version $Revision: 4131 $, $Date: 2009-03-19 16:15:28 -0400 (Thu, 19 Mar 2009) $
|
||||||
*/
|
*/
|
||||||
public class Cylinder extends Mesh {
|
public class Cylinder extends Mesh {
|
||||||
|
|
||||||
private int axisSamples;
|
private int axisSamples;
|
||||||
|
|
||||||
private int radialSamples;
|
private int radialSamples;
|
||||||
|
|
||||||
private float radius;
|
private float radius;
|
||||||
private float radius2;
|
private float radius2;
|
||||||
|
|
||||||
private float height;
|
private float height;
|
||||||
private boolean closed;
|
private boolean closed;
|
||||||
private boolean inverted;
|
private boolean inverted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor for serialization only. Do not use.
|
* Default constructor for serialization only. Do not use.
|
||||||
*/
|
*/
|
||||||
public Cylinder() {
|
public Cylinder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Cylinder. By default its center is the origin. Usually, a
|
* Creates a new Cylinder. By default its center is the origin. Usually, a
|
||||||
* higher sample number creates a better looking cylinder, but at the cost
|
* higher sample number creates a better looking cylinder, but at the cost
|
||||||
* of more vertex information.
|
* of more vertex information.
|
||||||
*
|
*
|
||||||
* @param axisSamples
|
* @param axisSamples
|
||||||
* Number of triangle samples along the axis.
|
* Number of triangle samples along the axis.
|
||||||
* @param radialSamples
|
* @param radialSamples
|
||||||
* Number of triangle samples along the radial.
|
* Number of triangle samples along the radial.
|
||||||
* @param radius
|
* @param radius
|
||||||
* The radius of the cylinder.
|
* The radius of the cylinder.
|
||||||
* @param height
|
* @param height
|
||||||
* The cylinder's height.
|
* The cylinder's height.
|
||||||
*/
|
*/
|
||||||
public Cylinder(int axisSamples, int radialSamples,
|
public Cylinder(int axisSamples, int radialSamples,
|
||||||
float radius, float height) {
|
float radius, float height) {
|
||||||
this(axisSamples, radialSamples, radius, height, false);
|
this(axisSamples, radialSamples, radius, height, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Cylinder. By default its center is the origin. Usually, a
|
* Creates a new Cylinder. By default its center is the origin. Usually, a
|
||||||
* higher sample number creates a better looking cylinder, but at the cost
|
* higher sample number creates a better looking cylinder, but at the cost
|
||||||
* of more vertex information. <br>
|
* of more vertex information. <br>
|
||||||
* If the cylinder is closed the texture is split into axisSamples parts:
|
* If the cylinder is closed the texture is split into axisSamples parts:
|
||||||
* top most and bottom most part is used for top and bottom of the cylinder,
|
* top most and bottom most part is used for top and bottom of the cylinder,
|
||||||
* rest of the texture for the cylinder wall. The middle of the top is
|
* rest of the texture for the cylinder wall. The middle of the top is
|
||||||
* 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
|
||||||
* Number of triangle samples along the axis.
|
* Number of triangle samples along the axis.
|
||||||
* @param radialSamples
|
* @param radialSamples
|
||||||
* Number of triangle samples along the radial.
|
* Number of triangle samples along the radial.
|
||||||
* @param radius
|
* @param radius
|
||||||
* The radius of the cylinder.
|
* The radius of the cylinder.
|
||||||
* @param height
|
* @param height
|
||||||
* The cylinder's height.
|
* The cylinder's height.
|
||||||
* @param closed
|
* @param closed
|
||||||
* true to create a cylinder with top and bottom surface
|
* true to create a cylinder with top and bottom surface
|
||||||
*/
|
*/
|
||||||
public Cylinder(int axisSamples, int radialSamples,
|
public Cylinder(int axisSamples, int radialSamples,
|
||||||
float radius, float height, boolean closed) {
|
float radius, float height, boolean closed) {
|
||||||
this(axisSamples, radialSamples, radius, height, closed, false);
|
this(axisSamples, radialSamples, radius, height, closed, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Cylinder. By default its center is the origin. Usually, a
|
* Creates a new Cylinder. By default its center is the origin. Usually, a
|
||||||
* higher sample number creates a better looking cylinder, but at the cost
|
* higher sample number creates a better looking cylinder, but at the cost
|
||||||
* of more vertex information. <br>
|
* of more vertex information. <br>
|
||||||
* If the cylinder is closed the texture is split into axisSamples parts:
|
* If the cylinder is closed the texture is split into axisSamples parts:
|
||||||
* top most and bottom most part is used for top and bottom of the cylinder,
|
* top most and bottom most part is used for top and bottom of the cylinder,
|
||||||
* rest of the texture for the cylinder wall. The middle of the top is
|
* rest of the texture for the cylinder wall. The middle of the top is
|
||||||
* 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
|
||||||
* Number of triangle samples along the axis.
|
* Number of triangle samples along the axis.
|
||||||
* @param radialSamples
|
* @param radialSamples
|
||||||
* Number of triangle samples along the radial.
|
* Number of triangle samples along the radial.
|
||||||
* @param radius
|
* @param radius
|
||||||
* The radius of the cylinder.
|
* The radius of the cylinder.
|
||||||
* @param height
|
* @param height
|
||||||
* The cylinder's height.
|
* The cylinder's height.
|
||||||
* @param closed
|
* @param closed
|
||||||
* true to create a cylinder with top and bottom surface
|
* true to create a cylinder with top and bottom surface
|
||||||
* @param inverted
|
* @param inverted
|
||||||
* true to create a cylinder that is meant to be viewed from the
|
* true to create a cylinder that is meant to be viewed from the
|
||||||
* interior.
|
* interior.
|
||||||
*/
|
*/
|
||||||
public Cylinder(int axisSamples, int radialSamples,
|
public Cylinder(int axisSamples, int radialSamples,
|
||||||
float radius, float height, boolean closed, boolean inverted) {
|
float radius, float height, boolean closed, boolean inverted) {
|
||||||
this(axisSamples, radialSamples, radius, radius, height, closed, inverted);
|
this(axisSamples, radialSamples, radius, radius, height, closed, inverted);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cylinder(int axisSamples, int radialSamples,
|
public Cylinder(int axisSamples, int radialSamples,
|
||||||
float radius, float radius2, float height, boolean closed, boolean inverted) {
|
float radius, float radius2, float height, boolean closed, boolean inverted) {
|
||||||
super();
|
super();
|
||||||
updateGeometry(axisSamples, radialSamples, radius, radius2, height, closed, inverted);
|
updateGeometry(axisSamples, radialSamples, radius, radius2, height, closed, inverted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the number of samples along the cylinder axis
|
* @return the number of samples along the cylinder axis
|
||||||
*/
|
*/
|
||||||
public int getAxisSamples() {
|
public int getAxisSamples() {
|
||||||
return axisSamples;
|
return axisSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the height.
|
* @return Returns the height.
|
||||||
*/
|
*/
|
||||||
public float getHeight() {
|
public float getHeight() {
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return number of samples around cylinder
|
* @return number of samples around cylinder
|
||||||
*/
|
*/
|
||||||
public int getRadialSamples() {
|
public int getRadialSamples() {
|
||||||
return radialSamples;
|
return radialSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the radius.
|
* @return Returns the radius.
|
||||||
*/
|
*/
|
||||||
public float getRadius() {
|
public float getRadius() {
|
||||||
return radius;
|
return radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getRadius2() {
|
public float getRadius2() {
|
||||||
return radius2;
|
return radius2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if end caps are used.
|
* @return true if end caps are used.
|
||||||
*/
|
*/
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return closed;
|
return closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if normals and uvs are created for interior use
|
* @return true if normals and uvs are created for interior use
|
||||||
*/
|
*/
|
||||||
public boolean isInverted() {
|
public boolean isInverted() {
|
||||||
return inverted;
|
return inverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 samples along the axis.
|
||||||
* @param radialSamples the number of samples around the radial.
|
* @param radialSamples the number of samples around the radial.
|
||||||
* @param radius the radius of the bottom of the cylinder.
|
* @param radius the radius of the bottom of the cylinder.
|
||||||
* @param radius2 the radius of the top of the cylinder.
|
* @param radius2 the radius of the top 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 radius, float radius2, float height, boolean closed, boolean inverted) {
|
||||||
this.axisSamples = axisSamples + (closed ? 2 : 0);
|
this.axisSamples = axisSamples + (closed ? 2 : 0);
|
||||||
this.radialSamples = radialSamples;
|
this.radialSamples = radialSamples;
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
this.radius2 = radius2;
|
this.radius2 = radius2;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.closed = closed;
|
this.closed = closed;
|
||||||
this.inverted = inverted;
|
this.inverted = inverted;
|
||||||
|
|
||||||
// VertexBuffer pvb = getBuffer(Type.Position);
|
// VertexBuffer pvb = getBuffer(Type.Position);
|
||||||
// VertexBuffer nvb = getBuffer(Type.Normal);
|
// VertexBuffer nvb = getBuffer(Type.Normal);
|
||||||
// VertexBuffer tvb = getBuffer(Type.TexCoord);
|
// VertexBuffer tvb = getBuffer(Type.TexCoord);
|
||||||
|
|
||||||
// Vertices
|
// Vertices
|
||||||
int vertCount = axisSamples * (radialSamples + 1) + (closed ? 2 : 0);
|
int vertCount = axisSamples * (radialSamples + 1) + (closed ? 2 : 0);
|
||||||
|
|
||||||
setBuffer(Type.Position, 3, createVector3Buffer(getFloatBuffer(Type.Position), vertCount));
|
setBuffer(Type.Position, 3, createVector3Buffer(getFloatBuffer(Type.Position), vertCount));
|
||||||
|
|
||||||
// Normals
|
// Normals
|
||||||
setBuffer(Type.Normal, 3, createVector3Buffer(getFloatBuffer(Type.Normal), vertCount));
|
setBuffer(Type.Normal, 3, createVector3Buffer(getFloatBuffer(Type.Normal), vertCount));
|
||||||
|
|
||||||
// Texture co-ordinates
|
// Texture co-ordinates
|
||||||
setBuffer(Type.TexCoord, 2, createVector2Buffer(vertCount));
|
setBuffer(Type.TexCoord, 2, createVector2Buffer(vertCount));
|
||||||
|
|
||||||
int triCount = ((closed ? 2 : 0) + 2 * (axisSamples - 1)) * radialSamples;
|
int triCount = ((closed ? 2 : 0) + 2 * (axisSamples - 1)) * radialSamples;
|
||||||
|
|
||||||
setBuffer(Type.Index, 3, createShortBuffer(getShortBuffer(Type.Index), 3 * triCount));
|
setBuffer(Type.Index, 3, createShortBuffer(getShortBuffer(Type.Index), 3 * triCount));
|
||||||
|
|
||||||
// generate geometry
|
// generate geometry
|
||||||
float inverseRadial = 1.0f / radialSamples;
|
float inverseRadial = 1.0f / radialSamples;
|
||||||
float inverseAxisLess = 1.0f / (closed ? axisSamples - 3 : axisSamples - 1);
|
float inverseAxisLess = 1.0f / (closed ? axisSamples - 3 : axisSamples - 1);
|
||||||
float inverseAxisLessTexture = 1.0f / (axisSamples - 1);
|
float inverseAxisLessTexture = 1.0f / (axisSamples - 1);
|
||||||
float halfHeight = 0.5f * height;
|
float halfHeight = 0.5f * height;
|
||||||
|
|
||||||
// Generate points on the unit circle to be used in computing the mesh
|
// Generate points on the unit circle to be used in computing the mesh
|
||||||
// points on a cylinder slice.
|
// points on a cylinder slice.
|
||||||
float[] sin = new float[radialSamples + 1];
|
float[] sin = new float[radialSamples + 1];
|
||||||
float[] cos = new float[radialSamples + 1];
|
float[] cos = new float[radialSamples + 1];
|
||||||
|
|
||||||
for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
|
for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
|
||||||
float angle = FastMath.TWO_PI * inverseRadial * radialCount;
|
float angle = FastMath.TWO_PI * inverseRadial * radialCount;
|
||||||
cos[radialCount] = FastMath.cos(angle);
|
cos[radialCount] = FastMath.cos(angle);
|
||||||
sin[radialCount] = FastMath.sin(angle);
|
sin[radialCount] = FastMath.sin(angle);
|
||||||
}
|
}
|
||||||
sin[radialSamples] = sin[0];
|
sin[radialSamples] = sin[0];
|
||||||
cos[radialSamples] = cos[0];
|
cos[radialSamples] = cos[0];
|
||||||
|
|
||||||
FloatBuffer nb = getFloatBuffer(Type.Normal);
|
// calculate normals
|
||||||
FloatBuffer pb = getFloatBuffer(Type.Position);
|
Vector3f[] vNormals = null;
|
||||||
FloatBuffer tb = getFloatBuffer(Type.TexCoord);
|
Vector3f vNormal = Vector3f.UNIT_Z;
|
||||||
|
|
||||||
// generate the cylinder itself
|
if ((height != 0.0f) && (radius != radius2)) {
|
||||||
Vector3f tempNormal = new Vector3f();
|
vNormals = new Vector3f[radialSamples];
|
||||||
for (int axisCount = 0, i = 0; axisCount < axisSamples; axisCount++, i++) {
|
Vector3f vHeight = Vector3f.UNIT_Z.mult(height);
|
||||||
float axisFraction;
|
Vector3f vRadial = new Vector3f();
|
||||||
float axisFractionTexture;
|
|
||||||
int topBottom = 0;
|
for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
|
||||||
if (!closed) {
|
vRadial.set(cos[radialCount], sin[radialCount], 0.0f);
|
||||||
axisFraction = axisCount * inverseAxisLess; // in [0,1]
|
Vector3f vRadius = vRadial.mult(radius);
|
||||||
axisFractionTexture = axisFraction;
|
Vector3f vRadius2 = vRadial.mult(radius2);
|
||||||
} else {
|
Vector3f vMantle = vHeight.subtract(vRadius2.subtract(vRadius));
|
||||||
if (axisCount == 0) {
|
Vector3f vTangent = vRadial.cross(Vector3f.UNIT_Z);
|
||||||
topBottom = -1; // bottom
|
vNormals[radialCount] = vMantle.cross(vTangent).normalize();
|
||||||
axisFraction = 0;
|
}
|
||||||
axisFractionTexture = inverseAxisLessTexture;
|
}
|
||||||
} else if (axisCount == axisSamples - 1) {
|
|
||||||
topBottom = 1; // top
|
FloatBuffer nb = getFloatBuffer(Type.Normal);
|
||||||
axisFraction = 1;
|
FloatBuffer pb = getFloatBuffer(Type.Position);
|
||||||
axisFractionTexture = 1 - inverseAxisLessTexture;
|
FloatBuffer tb = getFloatBuffer(Type.TexCoord);
|
||||||
} else {
|
|
||||||
axisFraction = (axisCount - 1) * inverseAxisLess;
|
// generate the cylinder itself
|
||||||
axisFractionTexture = axisCount * inverseAxisLessTexture;
|
Vector3f tempNormal = new Vector3f();
|
||||||
}
|
for (int axisCount = 0, i = 0; axisCount < axisSamples; axisCount++, i++) {
|
||||||
}
|
float axisFraction;
|
||||||
float z = -halfHeight + height * axisFraction;
|
float axisFractionTexture;
|
||||||
|
int topBottom = 0;
|
||||||
// compute center of slice
|
if (!closed) {
|
||||||
Vector3f sliceCenter = new Vector3f(0, 0, z);
|
axisFraction = axisCount * inverseAxisLess; // in [0,1]
|
||||||
|
axisFractionTexture = axisFraction;
|
||||||
// compute slice vertices with duplication at end point
|
} else {
|
||||||
int save = i;
|
if (axisCount == 0) {
|
||||||
for (int radialCount = 0; radialCount < radialSamples; radialCount++, i++) {
|
topBottom = -1; // bottom
|
||||||
float radialFraction = radialCount * inverseRadial; // in [0,1)
|
axisFraction = 0;
|
||||||
tempNormal.set(cos[radialCount], sin[radialCount], 0);
|
axisFractionTexture = inverseAxisLessTexture;
|
||||||
if (topBottom == 0) {
|
} else if (axisCount == axisSamples - 1) {
|
||||||
if (!inverted)
|
topBottom = 1; // top
|
||||||
nb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z);
|
axisFraction = 1;
|
||||||
else
|
axisFractionTexture = 1 - inverseAxisLessTexture;
|
||||||
nb.put(-tempNormal.x).put(-tempNormal.y).put(-tempNormal.z);
|
} else {
|
||||||
} else {
|
axisFraction = (axisCount - 1) * inverseAxisLess;
|
||||||
nb.put(0).put(0).put(topBottom * (inverted ? -1 : 1));
|
axisFractionTexture = axisCount * inverseAxisLessTexture;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tempNormal.multLocal((radius - radius2) * axisFraction + radius2)
|
|
||||||
.addLocal(sliceCenter);
|
// compute center of slice
|
||||||
pb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z);
|
float z = -halfHeight + height * axisFraction;
|
||||||
|
Vector3f sliceCenter = new Vector3f(0, 0, z);
|
||||||
tb.put((inverted ? 1 - radialFraction : radialFraction))
|
|
||||||
.put(axisFractionTexture);
|
// compute slice vertices with duplication at end point
|
||||||
}
|
int save = i;
|
||||||
|
for (int radialCount = 0; radialCount < radialSamples; radialCount++, i++) {
|
||||||
BufferUtils.copyInternalVector3(pb, save, i);
|
float radialFraction = radialCount * inverseRadial; // in [0,1)
|
||||||
BufferUtils.copyInternalVector3(nb, save, i);
|
tempNormal.set(cos[radialCount], sin[radialCount], 0.0f);
|
||||||
|
|
||||||
tb.put((inverted ? 0.0f : 1.0f))
|
if (vNormals != null) {
|
||||||
.put(axisFractionTexture);
|
vNormal = vNormals[radialCount];
|
||||||
}
|
} else if (radius == radius2) {
|
||||||
|
vNormal = tempNormal;
|
||||||
if (closed) {
|
}
|
||||||
pb.put(0).put(0).put(-halfHeight); // bottom center
|
|
||||||
nb.put(0).put(0).put(-1 * (inverted ? -1 : 1));
|
if (topBottom == 0) {
|
||||||
tb.put(0.5f).put(0);
|
if (!inverted)
|
||||||
pb.put(0).put(0).put(halfHeight); // top center
|
nb.put(vNormal.x).put(vNormal.y).put(vNormal.z);
|
||||||
nb.put(0).put(0).put(1 * (inverted ? -1 : 1));
|
else
|
||||||
tb.put(0.5f).put(1);
|
nb.put(-vNormal.x).put(-vNormal.y).put(-vNormal.z);
|
||||||
}
|
} else {
|
||||||
|
nb.put(0).put(0).put(topBottom * (inverted ? -1 : 1));
|
||||||
IndexBuffer ib = getIndexBuffer();
|
}
|
||||||
int index = 0;
|
|
||||||
// Connectivity
|
tempNormal.multLocal((radius - radius2) * axisFraction + radius2)
|
||||||
for (int axisCount = 0, axisStart = 0; axisCount < axisSamples - 1; axisCount++) {
|
.addLocal(sliceCenter);
|
||||||
int i0 = axisStart;
|
pb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z);
|
||||||
int i1 = i0 + 1;
|
|
||||||
axisStart += radialSamples + 1;
|
tb.put((inverted ? 1 - radialFraction : radialFraction))
|
||||||
int i2 = axisStart;
|
.put(axisFractionTexture);
|
||||||
int i3 = i2 + 1;
|
}
|
||||||
for (int i = 0; i < radialSamples; i++) {
|
|
||||||
if (closed && axisCount == 0) {
|
BufferUtils.copyInternalVector3(pb, save, i);
|
||||||
if (!inverted) {
|
BufferUtils.copyInternalVector3(nb, save, i);
|
||||||
ib.put(index++, i0++);
|
|
||||||
ib.put(index++, vertCount - 2);
|
tb.put((inverted ? 0.0f : 1.0f))
|
||||||
ib.put(index++, i1++);
|
.put(axisFractionTexture);
|
||||||
} else {
|
}
|
||||||
ib.put(index++, i0++);
|
|
||||||
ib.put(index++, i1++);
|
if (closed) {
|
||||||
ib.put(index++, vertCount - 2);
|
pb.put(0).put(0).put(-halfHeight); // bottom center
|
||||||
}
|
nb.put(0).put(0).put(-1 * (inverted ? -1 : 1));
|
||||||
} else if (closed && axisCount == axisSamples - 2) {
|
tb.put(0.5f).put(0);
|
||||||
ib.put(index++, i2++);
|
pb.put(0).put(0).put(halfHeight); // top center
|
||||||
ib.put(index++, inverted ? vertCount - 1 : i3++);
|
nb.put(0).put(0).put(1 * (inverted ? -1 : 1));
|
||||||
ib.put(index++, inverted ? i3++ : vertCount - 1);
|
tb.put(0.5f).put(1);
|
||||||
} else {
|
}
|
||||||
ib.put(index++, i0++);
|
|
||||||
ib.put(index++, inverted ? i2 : i1);
|
IndexBuffer ib = getIndexBuffer();
|
||||||
ib.put(index++, inverted ? i1 : i2);
|
int index = 0;
|
||||||
ib.put(index++, i1++);
|
// Connectivity
|
||||||
ib.put(index++, inverted ? i2++ : i3++);
|
for (int axisCount = 0, axisStart = 0; axisCount < axisSamples - 1; axisCount++) {
|
||||||
ib.put(index++, inverted ? i3++ : i2++);
|
int i0 = axisStart;
|
||||||
}
|
int i1 = i0 + 1;
|
||||||
}
|
axisStart += radialSamples + 1;
|
||||||
}
|
int i2 = axisStart;
|
||||||
|
int i3 = i2 + 1;
|
||||||
updateBound();
|
for (int i = 0; i < radialSamples; i++) {
|
||||||
}
|
if (closed && axisCount == 0) {
|
||||||
|
if (!inverted) {
|
||||||
public void read(JmeImporter e) throws IOException {
|
ib.put(index++, i0++);
|
||||||
super.read(e);
|
ib.put(index++, vertCount - 2);
|
||||||
InputCapsule capsule = e.getCapsule(this);
|
ib.put(index++, i1++);
|
||||||
axisSamples = capsule.readInt("axisSamples", 0);
|
} else {
|
||||||
radialSamples = capsule.readInt("radialSamples", 0);
|
ib.put(index++, i0++);
|
||||||
radius = capsule.readFloat("radius", 0);
|
ib.put(index++, i1++);
|
||||||
radius2 = capsule.readFloat("radius2", 0);
|
ib.put(index++, vertCount - 2);
|
||||||
height = capsule.readFloat("height", 0);
|
}
|
||||||
closed = capsule.readBoolean("closed", false);
|
} else if (closed && axisCount == axisSamples - 2) {
|
||||||
inverted = capsule.readBoolean("inverted", false);
|
ib.put(index++, i2++);
|
||||||
}
|
ib.put(index++, inverted ? vertCount - 1 : i3++);
|
||||||
|
ib.put(index++, inverted ? i3++ : vertCount - 1);
|
||||||
public void write(JmeExporter e) throws IOException {
|
} else {
|
||||||
super.write(e);
|
ib.put(index++, i0++);
|
||||||
OutputCapsule capsule = e.getCapsule(this);
|
ib.put(index++, inverted ? i2 : i1);
|
||||||
capsule.write(axisSamples, "axisSamples", 0);
|
ib.put(index++, inverted ? i1 : i2);
|
||||||
capsule.write(radialSamples, "radialSamples", 0);
|
ib.put(index++, i1++);
|
||||||
capsule.write(radius, "radius", 0);
|
ib.put(index++, inverted ? i2++ : i3++);
|
||||||
capsule.write(radius2, "radius2", 0);
|
ib.put(index++, inverted ? i3++ : i2++);
|
||||||
capsule.write(height, "height", 0);
|
}
|
||||||
capsule.write(closed, "closed", false);
|
}
|
||||||
capsule.write(inverted, "inverted", false);
|
}
|
||||||
}
|
|
||||||
|
updateBound();
|
||||||
|
}
|
||||||
}
|
|
||||||
|
public void read(JmeImporter e) throws IOException {
|
||||||
|
super.read(e);
|
||||||
|
InputCapsule capsule = e.getCapsule(this);
|
||||||
|
axisSamples = capsule.readInt("axisSamples", 0);
|
||||||
|
radialSamples = capsule.readInt("radialSamples", 0);
|
||||||
|
radius = capsule.readFloat("radius", 0);
|
||||||
|
radius2 = capsule.readFloat("radius2", 0);
|
||||||
|
height = capsule.readFloat("height", 0);
|
||||||
|
closed = capsule.readBoolean("closed", false);
|
||||||
|
inverted = capsule.readBoolean("inverted", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(JmeExporter e) throws IOException {
|
||||||
|
super.write(e);
|
||||||
|
OutputCapsule capsule = e.getCapsule(this);
|
||||||
|
capsule.write(axisSamples, "axisSamples", 0);
|
||||||
|
capsule.write(radialSamples, "radialSamples", 0);
|
||||||
|
capsule.write(radius, "radius", 0);
|
||||||
|
capsule.write(radius2, "radius2", 0);
|
||||||
|
capsule.write(height, "height", 0);
|
||||||
|
capsule.write(closed, "closed", false);
|
||||||
|
capsule.write(inverted, "inverted", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user