public static BufferData bufferHalfSphere(float r, int scalex, int scaley)
        {
            BufferData.Key key = BufferData.createKey(r, scalex, scaley);
            if(cache.containsKey(key))
                return cache.get(key);
            int i, j;
            FloatBuffer buf = FloatBuffer.allocate(scalex * scaley * 3);
            FloatBuffer nbuf = FloatBuffer.allocate(scalex * scaley * 3);
            for (i = 0; i < scalex; ++i)
            {
                for (j = 0; j < scaley; ++j)
                {
                    nbuf.put(r * (float) cos(j * 2 * PI / scaley) * (float) cos(i * PI / (2 * scalex)));
                    buf.put(r * (float) cos(j * 2 * PI / scaley) * (float) cos(i * PI / (2 * scalex)));
                    nbuf.put(r * (float) sin(i * PI / (2 * scalex)));
                    buf.put(r * (float) sin(i * PI / (2 * scalex)));
                    nbuf.put(r * (float) sin(j * 2 * PI / scaley) * (float) cos(i * PI / (2 * scalex)));
                    buf.put(r * (float) sin(j * 2 * PI / scaley) * (float) cos(i * PI / (2 * scalex)));
                }
            }
            buf.flip();
            nbuf.flip();
            ShortBuffer ebuf = ShortBuffer.allocate((scalex*scaley)*4);
            for (i = 0; i < scalex; ++i)
            {
                for (j = 0; j < scaley; ++j)
                {
                    ebuf.put((short)((i % scalex) * scaley + j));
                    ebuf.put((short)(((i + 1) % scalex) * scaley + j));
                    ebuf.put((short)(((i + 1) % scalex) * scaley + (j + 1) % scaley));
                    ebuf.put((short)((i % scalex) * scaley + (j + 1) % scaley));
                }
            }
            ebuf.flip();

            BufferData bd = bufferData(buf, nbuf, ebuf);
            cache.put(key, bd);
            return bd;
        }