159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer in the
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   documentation and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   may be used to endorse or promote products derived from this software
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   without specific prior written permission.
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// $Id: Cylinder.java 4131 2009-03-19 20:15:28Z blaine.dev $
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.scene.shape;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.InputCapsule;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeExporter;
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeImporter;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.OutputCapsule;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.FastMath;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh;
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Type;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.mesh.IndexBuffer;
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils;
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static com.jme3.util.BufferUtils.*;
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException;
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.FloatBuffer;
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * A simple cylinder, defined by it's height and radius.
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * (Ported to jME3)
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Mark Powell
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @version $Revision: 4131 $, $Date: 2009-03-19 16:15:28 -0400 (Thu, 19 Mar 2009) $
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class Cylinder extends Mesh {
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int axisSamples;
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int radialSamples;
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float radius;
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float radius2;
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float height;
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private boolean closed;
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private boolean inverted;
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Default constructor for serialization only. Do not use.
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Cylinder() {
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Creates a new Cylinder. By default its center is the origin. Usually, a
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * higher sample number creates a better looking cylinder, but at the cost
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * of more vertex information.
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param axisSamples
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            Number of triangle samples along the axis.
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param radialSamples
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            Number of triangle samples along the radial.
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param radius
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            The radius of the cylinder.
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param height
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            The cylinder's height.
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Cylinder(int axisSamples, int radialSamples,
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float radius, float height) {
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this(axisSamples, radialSamples, radius, height, false);
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Creates a new Cylinder. By default its center is the origin. Usually, a
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * higher sample number creates a better looking cylinder, but at the cost
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * of more vertex information. <br>
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * If the cylinder is closed the texture is split into axisSamples parts:
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * top most and bottom most part is used for top and bottom of the cylinder,
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * rest of the texture for the cylinder wall. The middle of the top is
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * mapped to texture coordinates (0.5, 1), bottom to (0.5, 0). Thus you need
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * a suited distorted texture.
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param axisSamples
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            Number of triangle samples along the axis.
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param radialSamples
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            Number of triangle samples along the radial.
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param radius
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            The radius of the cylinder.
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param height
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            The cylinder's height.
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param closed
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            true to create a cylinder with top and bottom surface
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Cylinder(int axisSamples, int radialSamples,
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float radius, float height, boolean closed) {
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this(axisSamples, radialSamples, radius, height, closed, false);
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Creates a new Cylinder. By default its center is the origin. Usually, a
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * higher sample number creates a better looking cylinder, but at the cost
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * of more vertex information. <br>
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * If the cylinder is closed the texture is split into axisSamples parts:
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * top most and bottom most part is used for top and bottom of the cylinder,
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * rest of the texture for the cylinder wall. The middle of the top is
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * mapped to texture coordinates (0.5, 1), bottom to (0.5, 0). Thus you need
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * a suited distorted texture.
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param axisSamples
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            Number of triangle samples along the axis.
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param radialSamples
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            Number of triangle samples along the radial.
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param radius
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            The radius of the cylinder.
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param height
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            The cylinder's height.
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param closed
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            true to create a cylinder with top and bottom surface
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param inverted
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            true to create a cylinder that is meant to be viewed from the
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            interior.
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Cylinder(int axisSamples, int radialSamples,
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float radius, float height, boolean closed, boolean inverted) {
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this(axisSamples, radialSamples, radius, radius, height, closed, inverted);
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Cylinder(int axisSamples, int radialSamples,
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float radius, float radius2, float height, boolean closed, boolean inverted) {
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super();
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        updateGeometry(axisSamples, radialSamples, radius, radius2, height, closed, inverted);
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the number of samples along the cylinder axis
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public int getAxisSamples() {
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return axisSamples;
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return Returns the height.
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getHeight() {
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return height;
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return number of samples around cylinder
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public int getRadialSamples() {
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return radialSamples;
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return Returns the radius.
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getRadius() {
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return radius;
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getRadius2() {
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return radius2;
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return true if end caps are used.
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isClosed() {
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return closed;
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return true if normals and uvs are created for interior use
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isInverted() {
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return inverted;
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Rebuilds the cylinder based on a new set of parameters.
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param axisSamples the number of samples along the axis.
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param radialSamples the number of samples around the radial.
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param radius the radius of the bottom of the cylinder.
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param radius2 the radius of the top of the cylinder.
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param height the cylinder's height.
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param closed should the cylinder have top and bottom surfaces.
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param inverted is the cylinder is meant to be viewed from the inside.
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateGeometry(int axisSamples, int radialSamples,
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float radius, float radius2, float height, boolean closed, boolean inverted) {
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.axisSamples = axisSamples + (closed ? 2 : 0);
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.radialSamples = radialSamples;
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.radius = radius;
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.radius2 = radius2;
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.height = height;
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.closed = closed;
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.inverted = inverted;
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        VertexBuffer pvb = getBuffer(Type.Position);
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        VertexBuffer nvb = getBuffer(Type.Normal);
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        VertexBuffer tvb = getBuffer(Type.TexCoord);
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Vertices
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int vertCount = axisSamples * (radialSamples + 1) + (closed ? 2 : 0);
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setBuffer(Type.Position, 3, createVector3Buffer(getFloatBuffer(Type.Position), vertCount));
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Normals
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setBuffer(Type.Normal, 3, createVector3Buffer(getFloatBuffer(Type.Normal), vertCount));
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Texture co-ordinates
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setBuffer(Type.TexCoord, 2, createVector2Buffer(vertCount));
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int triCount = ((closed ? 2 : 0) + 2 * (axisSamples - 1)) * radialSamples;
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setBuffer(Type.Index, 3, createShortBuffer(getShortBuffer(Type.Index), 3 * triCount));
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // generate geometry
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float inverseRadial = 1.0f / radialSamples;
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float inverseAxisLess = 1.0f / (closed ? axisSamples - 3 : axisSamples - 1);
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float inverseAxisLessTexture = 1.0f / (axisSamples - 1);
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float halfHeight = 0.5f * height;
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Generate points on the unit circle to be used in computing the mesh
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // points on a cylinder slice.
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float[] sin = new float[radialSamples + 1];
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float[] cos = new float[radialSamples + 1];
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float angle = FastMath.TWO_PI * inverseRadial * radialCount;
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cos[radialCount] = FastMath.cos(angle);
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sin[radialCount] = FastMath.sin(angle);
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        sin[radialSamples] = sin[0];
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        cos[radialSamples] = cos[0];
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // calculate normals
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f[] vNormals = null;
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f vNormal = Vector3f.UNIT_Z;
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if ((height != 0.0f) && (radius != radius2)) {
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vNormals = new Vector3f[radialSamples];
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Vector3f vHeight = Vector3f.UNIT_Z.mult(height);
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Vector3f vRadial = new Vector3f();
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                vRadial.set(cos[radialCount], sin[radialCount], 0.0f);
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector3f vRadius = vRadial.mult(radius);
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector3f vRadius2 = vRadial.mult(radius2);
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector3f vMantle = vHeight.subtract(vRadius2.subtract(vRadius));
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector3f vTangent = vRadial.cross(Vector3f.UNIT_Z);
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                vNormals[radialCount] = vMantle.cross(vTangent).normalize();
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FloatBuffer nb = getFloatBuffer(Type.Normal);
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FloatBuffer pb = getFloatBuffer(Type.Position);
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FloatBuffer tb = getFloatBuffer(Type.TexCoord);
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // generate the cylinder itself
28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f tempNormal = new Vector3f();
28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int axisCount = 0, i = 0; axisCount < axisSamples; axisCount++, i++) {
28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float axisFraction;
28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float axisFractionTexture;
28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int topBottom = 0;
29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!closed) {
29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                axisFraction = axisCount * inverseAxisLess; // in [0,1]
29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                axisFractionTexture = axisFraction;
29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (axisCount == 0) {
29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    topBottom = -1; // bottom
29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    axisFraction = 0;
29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    axisFractionTexture = inverseAxisLessTexture;
29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else if (axisCount == axisSamples - 1) {
29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    topBottom = 1; // top
30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    axisFraction = 1;
30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    axisFractionTexture = 1 - inverseAxisLessTexture;
30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    axisFraction = (axisCount - 1) * inverseAxisLess;
30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    axisFractionTexture = axisCount * inverseAxisLessTexture;
30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // compute center of slice
30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float z = -halfHeight + height * axisFraction;
31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Vector3f sliceCenter = new Vector3f(0, 0, z);
31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // compute slice vertices with duplication at end point
31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int save = i;
31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (int radialCount = 0; radialCount < radialSamples; radialCount++, i++) {
31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float radialFraction = radialCount * inverseRadial; // in [0,1)
31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                tempNormal.set(cos[radialCount], sin[radialCount], 0.0f);
31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (vNormals != null) {
31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    vNormal = vNormals[radialCount];
32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else if (radius == radius2) {
32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    vNormal = tempNormal;
32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (topBottom == 0) {
32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (!inverted)
32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        nb.put(vNormal.x).put(vNormal.y).put(vNormal.z);
32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    else
32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        nb.put(-vNormal.x).put(-vNormal.y).put(-vNormal.z);
32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    nb.put(0).put(0).put(topBottom * (inverted ? -1 : 1));
33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                tempNormal.multLocal((radius - radius2) * axisFraction + radius2)
33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        .addLocal(sliceCenter);
33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                pb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z);
33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                tb.put((inverted ? 1 - radialFraction : radialFraction))
33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        .put(axisFractionTexture);
33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            BufferUtils.copyInternalVector3(pb, save, i);
34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            BufferUtils.copyInternalVector3(nb, save, i);
34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            tb.put((inverted ? 0.0f : 1.0f))
34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    .put(axisFractionTexture);
34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (closed) {
34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            pb.put(0).put(0).put(-halfHeight); // bottom center
35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            nb.put(0).put(0).put(-1 * (inverted ? -1 : 1));
35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            tb.put(0.5f).put(0);
35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            pb.put(0).put(0).put(halfHeight); // top center
35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            nb.put(0).put(0).put(1 * (inverted ? -1 : 1));
35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            tb.put(0.5f).put(1);
35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        IndexBuffer ib = getIndexBuffer();
35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int index = 0;
35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Connectivity
36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int axisCount = 0, axisStart = 0; axisCount < axisSamples - 1; axisCount++) {
36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int i0 = axisStart;
36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int i1 = i0 + 1;
36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            axisStart += radialSamples + 1;
36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int i2 = axisStart;
36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int i3 = i2 + 1;
36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (int i = 0; i < radialSamples; i++) {
36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (closed && axisCount == 0) {
36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (!inverted) {
36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        ib.put(index++, i0++);
37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        ib.put(index++, vertCount - 2);
37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        ib.put(index++, i1++);
37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        ib.put(index++, i0++);
37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        ib.put(index++, i1++);
37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        ib.put(index++, vertCount - 2);
37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else if (closed && axisCount == axisSamples - 2) {
37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ib.put(index++, i2++);
37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ib.put(index++, inverted ? vertCount - 1 : i3++);
38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ib.put(index++, inverted ? i3++ : vertCount - 1);
38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ib.put(index++, i0++);
38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ib.put(index++, inverted ? i2 : i1);
38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ib.put(index++, inverted ? i1 : i2);
38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ib.put(index++, i1++);
38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ib.put(index++, inverted ? i2++ : i3++);
38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ib.put(index++, inverted ? i3++ : i2++);
38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        updateBound();
39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void read(JmeImporter e) throws IOException {
39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.read(e);
39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        InputCapsule capsule = e.getCapsule(this);
39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        axisSamples = capsule.readInt("axisSamples", 0);
39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        radialSamples = capsule.readInt("radialSamples", 0);
40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        radius = capsule.readFloat("radius", 0);
40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        radius2 = capsule.readFloat("radius2", 0);
40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        height = capsule.readFloat("height", 0);
40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        closed = capsule.readBoolean("closed", false);
40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        inverted = capsule.readBoolean("inverted", false);
40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void write(JmeExporter e) throws IOException {
40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.write(e);
40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        OutputCapsule capsule = e.getCapsule(this);
41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(axisSamples, "axisSamples", 0);
41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(radialSamples, "radialSamples", 0);
41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(radius, "radius", 0);
41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(radius2, "radius2", 0);
41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(height, "height", 0);
41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(closed, "closed", false);
41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(inverted, "inverted", false);
41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
421