/// <summary>
        /// generates renderOps from billboards.  nulls billboards when done.
        /// </summary>
        public void FinishRebuild()
        {
            foreach (string textureName in billboards.Keys)
            {
                foreach (int alpha in billboards[textureName].Keys)
                {
                    List<float[]>bbList = billboards[textureName][alpha];

                    RenderOperation renderOp = new RenderOperation();
                    renderOp.operationType = OperationType.TriangleList;
                    renderOp.useIndices = false;

                    VertexData vertexData = new VertexData();

                    vertexData.vertexCount = 6 * bbList.Count;
                    vertexData.vertexStart = 0;

                    // free the original vertex declaration to avoid a leak
                    HardwareBufferManager.Instance.DestroyVertexDeclaration(vertexData.vertexDeclaration);

                    // use common vertex declaration
                    vertexData.vertexDeclaration = TreeGroup.BillboardVertexDeclaration;

                    // create the hardware vertex buffer and set up the buffer binding
                    HardwareVertexBuffer hvBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                        vertexData.vertexDeclaration.GetVertexSize(0), vertexData.vertexCount,
                        BufferUsage.StaticWriteOnly, false);

                    vertexData.vertexBufferBinding.SetBinding(0, hvBuffer);

                    renderOp.vertexData = vertexData;

                    // lock the vertex buffer
                    IntPtr ipBuf = hvBuffer.Lock(BufferLocking.Discard);

                    int bufferOff = 0;

                    unsafe
                    {
                        float* buffer = (float*)ipBuf.ToPointer();
                        foreach (float[] src in bbList)
                        {
                            buffer[bufferOff++] = src[0];
                            buffer[bufferOff++] = src[1];
                            buffer[bufferOff++] = src[2];
                            buffer[bufferOff++] = src[3];
                            buffer[bufferOff++] = src[4];

                            buffer[bufferOff++] = src[5];
                            buffer[bufferOff++] = src[6];
                            buffer[bufferOff++] = src[7];
                            buffer[bufferOff++] = src[8];
                            buffer[bufferOff++] = src[9];

                            buffer[bufferOff++] = src[10];
                            buffer[bufferOff++] = src[11];
                            buffer[bufferOff++] = src[12];
                            buffer[bufferOff++] = src[13];
                            buffer[bufferOff++] = src[14];

                            buffer[bufferOff++] = src[10];
                            buffer[bufferOff++] = src[11];
                            buffer[bufferOff++] = src[12];
                            buffer[bufferOff++] = src[13];
                            buffer[bufferOff++] = src[14];

                            buffer[bufferOff++] = src[15];
                            buffer[bufferOff++] = src[16];
                            buffer[bufferOff++] = src[17];
                            buffer[bufferOff++] = src[18];
                            buffer[bufferOff++] = src[19];

                            buffer[bufferOff++] = src[0];
                            buffer[bufferOff++] = src[1];
                            buffer[bufferOff++] = src[2];
                            buffer[bufferOff++] = src[3];
                            buffer[bufferOff++] = src[4];
                        }
                    }
                    hvBuffer.Unlock();

                    TreeBillboardRenderOp op = new TreeBillboardRenderOp(textureName, alpha, renderOp);

                    renderOps.Add(op);
                }
            }

            billboards = null;
        }
        /// <summary>
        /// generates renderOps from billboards.  nulls billboards when done.
        /// </summary>
        public void FinishRebuild()
        {
            foreach (string textureName in billboards.Keys)
            {
                foreach (int alpha in billboards[textureName].Keys)
                {
                    List <float[]> bbList = billboards[textureName][alpha];

                    RenderOperation renderOp = new RenderOperation();
                    renderOp.operationType = OperationType.TriangleList;
                    renderOp.useIndices    = false;

                    VertexData vertexData = new VertexData();

                    vertexData.vertexCount = 6 * bbList.Count;
                    vertexData.vertexStart = 0;

                    // free the original vertex declaration to avoid a leak
                    HardwareBufferManager.Instance.DestroyVertexDeclaration(vertexData.vertexDeclaration);

                    // use common vertex declaration
                    vertexData.vertexDeclaration = TreeGroup.BillboardVertexDeclaration;

                    // create the hardware vertex buffer and set up the buffer binding
                    HardwareVertexBuffer hvBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                        vertexData.vertexDeclaration.GetVertexSize(0), vertexData.vertexCount,
                        BufferUsage.StaticWriteOnly, false);

                    vertexData.vertexBufferBinding.SetBinding(0, hvBuffer);

                    renderOp.vertexData = vertexData;

                    // lock the vertex buffer
                    IntPtr ipBuf = hvBuffer.Lock(BufferLocking.Discard);

                    int bufferOff = 0;

                    unsafe
                    {
                        float *buffer = (float *)ipBuf.ToPointer();
                        foreach (float[] src in bbList)
                        {
                            buffer[bufferOff++] = src[0];
                            buffer[bufferOff++] = src[1];
                            buffer[bufferOff++] = src[2];
                            buffer[bufferOff++] = src[3];
                            buffer[bufferOff++] = src[4];

                            buffer[bufferOff++] = src[5];
                            buffer[bufferOff++] = src[6];
                            buffer[bufferOff++] = src[7];
                            buffer[bufferOff++] = src[8];
                            buffer[bufferOff++] = src[9];

                            buffer[bufferOff++] = src[10];
                            buffer[bufferOff++] = src[11];
                            buffer[bufferOff++] = src[12];
                            buffer[bufferOff++] = src[13];
                            buffer[bufferOff++] = src[14];

                            buffer[bufferOff++] = src[10];
                            buffer[bufferOff++] = src[11];
                            buffer[bufferOff++] = src[12];
                            buffer[bufferOff++] = src[13];
                            buffer[bufferOff++] = src[14];

                            buffer[bufferOff++] = src[15];
                            buffer[bufferOff++] = src[16];
                            buffer[bufferOff++] = src[17];
                            buffer[bufferOff++] = src[18];
                            buffer[bufferOff++] = src[19];

                            buffer[bufferOff++] = src[0];
                            buffer[bufferOff++] = src[1];
                            buffer[bufferOff++] = src[2];
                            buffer[bufferOff++] = src[3];
                            buffer[bufferOff++] = src[4];
                        }
                    }
                    hvBuffer.Unlock();

                    TreeBillboardRenderOp op = new TreeBillboardRenderOp(textureName, alpha, renderOp);

                    renderOps.Add(op);
                }
            }

            billboards = null;
        }