private void setGeometryData() {
        // allocate vertices
        int vertCount = (circleSamples + 1) * (radialSamples + 1);
        FloatBuffer fpb = BufferUtils.createVector3Buffer(vertCount);
        setBuffer(Type.Position, 3, fpb);

        // allocate normals if requested
        FloatBuffer fnb = BufferUtils.createVector3Buffer(vertCount);
        setBuffer(Type.Normal, 3, fnb);

        // allocate texture coordinates
        FloatBuffer ftb = BufferUtils.createVector2Buffer(vertCount);
        setBuffer(Type.TexCoord, 2, ftb);

        // generate geometry
        float inverseCircleSamples = 1.0f / circleSamples;
        float inverseRadialSamples = 1.0f / radialSamples;
        int i = 0;
        // generate the cylinder itself
        Vector3f radialAxis = new Vector3f(), torusMiddle = new Vector3f(), tempNormal = new Vector3f();
        for (int circleCount = 0; circleCount < circleSamples; circleCount++) {
            // compute center point on torus circle at specified angle
            float circleFraction = circleCount * inverseCircleSamples;
            float theta = FastMath.TWO_PI * circleFraction;
            float cosTheta = FastMath.cos(theta);
            float sinTheta = FastMath.sin(theta);
            radialAxis.set(cosTheta, sinTheta, 0);
            radialAxis.mult(outerRadius, torusMiddle);

            // compute slice vertices with duplication at end point
            int iSave = i;
            for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
                float radialFraction = radialCount * inverseRadialSamples;
                // in [0,1)
                float phi = FastMath.TWO_PI * radialFraction;
                float cosPhi = FastMath.cos(phi);
                float sinPhi = FastMath.sin(phi);
                tempNormal.set(radialAxis).multLocal(cosPhi);
                tempNormal.z += sinPhi;
                fnb.put(tempNormal.x).put(tempNormal.y).put(
                        tempNormal.z);
       
                tempNormal.multLocal(innerRadius).addLocal(torusMiddle);
                fpb.put(tempNormal.x).put(tempNormal.y).put(
                        tempNormal.z);

                ftb.put(radialFraction).put(circleFraction);
                i++;
            }

            BufferUtils.copyInternalVector3(fpb, iSave, i);
            BufferUtils.copyInternalVector3(fnb, iSave, i);

            ftb.put(1.0f).put(circleFraction);

            i++;
        }

        // duplicate the cylinder ends to form a torus
        for (int iR = 0; iR <= radialSamples; iR++, i++) {
            BufferUtils.copyInternalVector3(fpb, iR, i);
            BufferUtils.copyInternalVector3(fnb, iR, i);
            BufferUtils.copyInternalVector2(ftb, iR, i);
            ftb.put(i * 2 + 1, 1.0f);
        }
    }
Constructs a new Torus. Center is the origin, but the Torus may be
transformed.

@param circleSamples
           The number of samples along the circles.
@param radialSamples
           The number of samples along the radial.
@param innerRadius minor radius of the torus
@param outerRadius major radius of the torus
jme3-core/src/main/java/com/jme3/scene/shape/Torus.java