protected final void init()
    {
        double d = 1D/slices;
        double cur = 0D;
        double tcur = 0D;
        double td = d*16;
        Vector height = new Vector(0, 0, 4);
        FloatBuffer vertices = FloatBuffer.allocate(slices * 4 * 4 * 3);
        FloatBuffer normals = FloatBuffer.allocate(slices * 4 * 4 * 3);
        FloatBuffer texture = FloatBuffer.allocate(slices * 4 * 4 * 2);
        ShortBuffer indices = ShortBuffer.allocate(slices * 16);
        double maxdist = Double.MIN_VALUE; // Set this for the scaling later
        int i;
        Vector p = this.getPoint(cur % 1);
        Vector width = p.normalized().scale(2);
        Vector p1 = p.subtract(width),
               p2 = p.add(width),
               p3 = p.add(width).subtract(height),
               p4 = p.subtract(width).subtract(height);
        Vector q1, q2, q3, q4;
        int index = 0;
        short[] si = new short[16];
        for(i = 0; i < slices; i++)
        {
            cur += d;
            Vector q = this.getPoint(cur % 1);
            width = q.normalized().scale(2);
            q1 = q.subtract(width);
            q2 = q.add(width);
            q3 = q.add(width).subtract(height);
            q4 = q.subtract(width).subtract(height);
            
            double len = q.length();
            if(len > maxdist)
                maxdist = len;
            
            // Whether the normals are averaged between adjecent sides
            if(averaged)
            {
                // Normals for p and q when it is neither Z nor -Z
                Vector np = this.getTangent(cur-d).cross(Vector.Z);
                Vector nq = this.getTangent(cur).cross(Vector.Z);

                // Vertices upper quad (top of the track)
                vec2buf(p1, vertices); texture.put(new float[]{0.5f, 1.0f}); si[0] = (short)(index++);
                vec2buf(p2, vertices); texture.put(new float[]{1.0f, 1.0f}); si[1] = (short)(index++);
                vec2buf(q2, vertices); texture.put(new float[]{1.0f, 0.0f}); si[2] = (short)(index++);
                vec2buf(q1, vertices); texture.put(new float[]{0.5f, 0.0f}); si[3] = (short)(index++);
                // Normals upper quad (top of the track)
                vec2buf(Vector.Z.add(np).normalized(), normals);
                vec2buf(Vector.Z.add(np).normalized(), normals);
                vec2buf(Vector.Z.add(nq).normalized(), normals);
                vec2buf(Vector.Z.add(nq).normalized(), normals);

                // Vertices back quad (outside of the track)
                vec2buf(p2, vertices); texture.put(new float[]{0f, Math.min((float)(tcur), 1.0f)}); si[4] = (short)(index++);
                vec2buf(p3, vertices); texture.put(new float[]{0.5f, Math.min((float)(tcur+td), 1.0f)}); si[5] = (short)(index++);
                vec2buf(q3, vertices); texture.put(new float[]{0.5f, Math.min((float)(tcur+td), 1.0f)}); si[6] = (short)(index++);
                vec2buf(q2, vertices); texture.put(new float[]{0.0f, Math.min((float)(tcur), 1.0f)}); si[7] = (short)(index++);
                // Normals back quad (outside of the track)
                vec2buf(Vector.Z.add(np).normalized(), normals);
                vec2buf(Vector.Z.scale(-1).add(np).normalized(), normals);
                vec2buf(Vector.Z.scale(-1).add(nq).normalized(), normals);
                vec2buf(Vector.Z.add(nq).normalized(), normals);

                // Vertices bottom quad (bottom of the track)
                vec2buf(p3, vertices); texture.put(new float[]{0.5f, 1.0f}); si[8] = (short)(index++);
                vec2buf(p4, vertices); texture.put(new float[]{1.0f, 1.0f}); si[9] = (short)(index++);
                vec2buf(q4, vertices); texture.put(new float[]{1.0f, 0.0f}); si[10] = (short)(index++);
                vec2buf(q3, vertices); texture.put(new float[]{0.5f, 0.0f}); si[11] = (short)(index++);
                // Normals bottom quad (bottom of the track)
                vec2buf(Vector.Z.scale(-1).add(np).normalized(), normals);
                vec2buf(Vector.Z.scale(-1).add(np).normalized(), normals);
                vec2buf(Vector.Z.scale(-1).add(nq).normalized(), normals);
                vec2buf(Vector.Z.scale(-1).add(nq).normalized(), normals);

                // Vertices front quad (inside of the track)
                vec2buf(p4, vertices); texture.put(new float[]{1.0f, 0.5f}); si[12] = (short)(index++);
                vec2buf(p1, vertices); texture.put(new float[]{1.0f, 0.0f}); si[13] = (short)(index++);
                vec2buf(q1, vertices); texture.put(new float[]{0.0f, 0.0f}); si[14] = (short)(index++);
                vec2buf(q4, vertices); texture.put(new float[]{0.0f, 0.5f}); si[15] = (short)(index++);
                // Normals front quad (inside of the track)
                vec2buf(Vector.Z.scale(-1).add(np).normalized(), normals);
                vec2buf(Vector.Z.add(np).normalized(), normals);
                vec2buf(Vector.Z.add(nq).normalized(), normals);
                vec2buf(Vector.Z.scale(-1).add(nq).normalized(), normals);
            }
            else
            {
                // Vertices upper quad (top of the track)
                vec2buf(p1, vertices); si[0] = (short)(index++);
                vec2buf(p2, vertices); si[1] = (short)(index++);
                vec2buf(q2, vertices); si[2] = (short)(index++);
                vec2buf(q1, vertices); si[3] = (short)(index++);
                // Normals upper quad (top of the track)
                vec2buf(Vector.Z, normals);
                vec2buf(Vector.Z, normals);
                vec2buf(Vector.Z, normals);
                vec2buf(Vector.Z, normals);

                // Vertices back quad (outside of the track)
                vec2buf(p2, vertices); si[4] = (short)(index++);
                vec2buf(p3, vertices); si[5] = (short)(index++);
                vec2buf(q3, vertices); si[6] = (short)(index++);
                vec2buf(q2, vertices); si[7] = (short)(index++);
                // Vertices back quad (outside of the track)
                vec2buf(this.getTangent(cur-d).cross(Vector.Z), normals);
                vec2buf(this.getTangent(cur-d).cross(Vector.Z), normals);
                vec2buf(this.getTangent(cur).cross(Vector.Z), normals);
                vec2buf(this.getTangent(cur).cross(Vector.Z), normals);

                // Vertices bottom quad (bottom of the track)
                vec2buf(p3, vertices); si[8] = (short)(index++);
                vec2buf(p4, vertices); si[9] = (short)(index++);
                vec2buf(q4, vertices); si[10] = (short)(index++);
                vec2buf(q3, vertices); si[11] = (short)(index++);
                // Normals bottom quad (bottom of the track)
                vec2buf(Vector.Z.scale(-1), normals);
                vec2buf(Vector.Z.scale(-1), normals);
                vec2buf(Vector.Z.scale(-1), normals);
                vec2buf(Vector.Z.scale(-1), normals);

                // Vertices front quad (inside of the track)
                vec2buf(p4, vertices); si[12] = (short)(index++);
                vec2buf(p1, vertices); si[13] = (short)(index++);
                vec2buf(q1, vertices); si[14] = (short)(index++);
                vec2buf(q4, vertices); si[15] = (short)(index++);
                // Normals front quad (inside of the track)
                vec2buf(Vector.Z.cross(this.getTangent(cur-d)), normals);
                vec2buf(Vector.Z.cross(this.getTangent(cur-d)), normals);
                vec2buf(Vector.Z.cross(this.getTangent(cur)), normals);
                vec2buf(Vector.Z.cross(this.getTangent(cur)), normals);
            }
            
            indices.put(si);
            
            p1 = q1;
            p2 = q2;
            p3 = q3;
            p4 = q4;
            
            tcur += td;
            tcur %= 1;
        }
        
        vertices.flip();
        normals.flip();
        texture.flip();
        indices.flip();
        
        this.buf = RobotRace.VBOUtil.bufferData(vertices, normals, texture, indices);
    }