/// <summary>
        ///
        /// </summary>
        /// <param name="position"></param>
        /// <param name="xScale"></param>
        /// <param name="yScale"></param>
        /// <param name="color"></param>
        /// <param name="texcoordIndexU"></param>
        /// <param name="texcoordsIndexV"></param>
        public void CreateBillboard(Vector3 position, float xScale, float yScale, ColorEx color, short texcoordIndexU, short texcoordsIndexV)
        {
            if (mRenderMethod == BillboardMethod.Accelerated)
            {
                StaticBillboard bb = new StaticBillboard();
                bb.Position        = position;
                bb.XScale          = xScale;
                bb.YScale          = yScale;
                bb.TextCoordIndexU = texcoordIndexU;
                bb.TextCoordIndexV = texcoordsIndexV;

                uint packedColor = (uint)Root.Singleton.RenderSystem.ConvertColor(color);
                bb.Color = packedColor;
                mBillboardBuffer.Add(bb);
            }
            else
            {
                Billboard bb = mFallbackSet.CreateBillboard(position);
                bb.SetDimensions(xScale, yScale);
                bb.TexcoordRect = new RectangleF(
                    texcoordIndexU * mUFactor,
                    texcoordsIndexV * mVFactor,
                    (texcoordIndexU + 1) * mUFactor,
                    (texcoordsIndexV + 1) * mVFactor);

                bb.Color = color;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="position"></param>
        /// <param name="xScale"></param>
        /// <param name="yScale"></param>
        /// <param name="color"></param>
        /// <param name="texcoordIndexU"></param>
        /// <param name="texcoordsIndexV"></param>
        public void CreateBillboard(Vector3 position, float xScale, float yScale, ColorEx color, short texcoordIndexU, short texcoordsIndexV)
        {
            if (mRenderMethod == BillboardMethod.Accelerated)
            {
                StaticBillboard bb = new StaticBillboard();
                bb.Position = position;
                bb.XScale = xScale;
                bb.YScale = yScale;
                bb.TextCoordIndexU = texcoordIndexU;
                bb.TextCoordIndexV = texcoordsIndexV;

                uint packedColor = (uint)Root.Singleton.RenderSystem.ConvertColor(color);
                bb.Color = packedColor;
                mBillboardBuffer.Add(bb);
            }
            else
            {
                Billboard bb = mFallbackSet.CreateBillboard(position);
                bb.SetDimensions(xScale, yScale);
                bb.TexcoordRect = new RectangleF(
                    texcoordIndexU * mUFactor,
                    texcoordsIndexV * mVFactor,
                    (texcoordIndexU + 1) * mUFactor,
                    (texcoordsIndexV + 1) * mVFactor);

                bb.Color = color;
            }
        }
        /// <summary>
        ///
        /// </summary>
        public void Build()
        {
            if (mRenderMethod == BillboardMethod.Accelerated)
            {
                Clear();

                //If there are no billboards to create, exit
                if (mBillboardBuffer.Count == 0)
                {
                    return;
                }

                //Create manual mesh to store billboard quads
                mMesh    = MeshManager.Instance.CreateManual(GetUniqueID("SBSMesh"), ResourceGroupManager.DefaultResourceGroupName, null);
                mSubMesh = mMesh.CreateSubMesh();
                mSubMesh.useSharedVertices = false;

                //Setup vertex format information
                mSubMesh.vertexData             = new VertexData();
                mSubMesh.vertexData.vertexStart = 0;
                mSubMesh.vertexData.vertexCount = 4 * mBillboardBuffer.Count;

                VertexDeclaration dcl = mSubMesh.vertexData.vertexDeclaration;

                int offset = 0;
                dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Position);
                offset += VertexElement.GetTypeSize(VertexElementType.Float3);
                dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Normal);
                offset += VertexElement.GetTypeSize(VertexElementType.Float3);
                dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Diffuse);
                offset += VertexElement.GetTypeSize(VertexElementType.Color);
                dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.TexCoords);
                offset += VertexElement.GetTypeSize(VertexElementType.Float2);


                //Populate a new vertex buffer
                HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer(
                    /*offset*/ dcl, mSubMesh.vertexData.vertexCount, BufferUsage.StaticWriteOnly, false);
                unsafe
                {
                    float *pReal = (float *)vbuf.Lock(BufferLocking.Discard);

                    float minX = float.PositiveInfinity;
                    float maxX = float.NegativeInfinity;
                    float minY = float.PositiveInfinity;
                    float maxY = float.NegativeInfinity;
                    float minZ = float.PositiveInfinity;
                    float maxZ = float.NegativeInfinity;

                    foreach (StaticBillboard it in mBillboardBuffer)
                    {
                        StaticBillboard bb         = it;
                        float           halfXScale = bb.XScale * 0.5f;
                        float           halfYScale = bb.YScale * 0.5f;

                        // position
                        *pReal++ = bb.Position.x;
                        *pReal++ = bb.Position.y;
                        *pReal++ = bb.Position.z;

                        // normals (actually used as scale / translate info for vertex shader)
                        *pReal++ = halfXScale;
                        *pReal++ = halfYScale;
                        *pReal++ = 0.0f;
                        // color
                        *((uint *)pReal++) = bb.Color;
                        // uv
                        *pReal++ = (float)(bb.TextCoordIndexU * mUFactor);
                        *pReal++ = (float)(bb.TextCoordIndexV * mVFactor);


                        // position
                        *pReal++ = bb.Position.x;
                        *pReal++ = bb.Position.y;
                        *pReal++ = bb.Position.z;

                        // normals (actually used as scale / translate info for vertex shader)
                        *pReal++ = halfXScale;
                        *pReal++ = halfYScale;
                        *pReal++ = 1.0f;
                        // color
                        *((uint *)pReal++) = bb.Color;
                        // uv
                        *pReal++ = (float)((bb.TextCoordIndexU + 1) * mUFactor);
                        *pReal++ = (float)(bb.TextCoordIndexV * mVFactor);

                        // position
                        *pReal++ = bb.Position.x;
                        *pReal++ = bb.Position.y;
                        *pReal++ = bb.Position.z;

                        // normals (actually used as scale / translate info for vertex shader)
                        *pReal++ = halfXScale;
                        *pReal++ = halfYScale;
                        *pReal++ = 2.0f;
                        // color
                        *((uint *)pReal++) = bb.Color;
                        // uv
                        *pReal++ = (float)(bb.TextCoordIndexU * mUFactor);
                        *pReal++ = (float)((bb.TextCoordIndexV + 1) * mVFactor);

                        // position
                        *pReal++ = bb.Position.x;
                        *pReal++ = bb.Position.y;
                        *pReal++ = bb.Position.z;

                        // normals (actually used as scale / translate info for vertex shader)
                        *pReal++ = halfXScale;
                        *pReal++ = halfYScale;
                        *pReal++ = 3.0f;
                        // color
                        *((uint *)pReal++) = bb.Color;
                        // uv
                        *pReal++ = (float)((bb.TextCoordIndexU + 1) * mUFactor);
                        *pReal++ = (float)((bb.TextCoordIndexV + 1) * mVFactor);


                        //Update bounding box
                        if (bb.Position.x - halfXScale < minX)
                        {
                            minX = bb.Position.x - halfXScale;
                        }
                        if (bb.Position.x + halfXScale > maxX)
                        {
                            maxX = bb.Position.x + halfXScale;
                        }
                        if (bb.Position.y - halfYScale < minY)
                        {
                            minY = bb.Position.y - halfYScale;
                        }
                        if (bb.Position.y + halfYScale > maxY)
                        {
                            maxY = bb.Position.y + halfYScale;
                        }
                        if (bb.Position.z - halfXScale < minZ)
                        {
                            minZ = bb.Position.z - halfXScale;
                        }
                        if (bb.Position.z + halfXScale > maxZ)
                        {
                            maxZ = bb.Position.z + halfXScale;
                        }
                    }

                    AxisAlignedBox bounds = new AxisAlignedBox(
                        new Vector3(minX, minY, minZ),
                        new Vector3(maxX, maxY, maxZ));
                    vbuf.Unlock();
                    mSubMesh.vertexData.vertexBufferBinding.SetBinding(0, vbuf);

                    //Populate index buffer
                    mSubMesh.indexData.indexStart  = 0;
                    mSubMesh.indexData.indexCount  = 6 * mBillboardBuffer.Count;
                    mSubMesh.indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(
                        IndexType.Size16, mSubMesh.indexData.indexCount, BufferUsage.StaticWriteOnly);

                    ushort *pI = (ushort *)mSubMesh.indexData.indexBuffer.Lock(BufferLocking.Discard);
                    for (ushort i = 0; i < mBillboardBuffer.Count; i++)
                    {
                        ushort ofset = (ushort)(i * 4);

                        *pI++ = (ushort)(0 + ofset);
                        *pI++ = (ushort)(2 + ofset);
                        *pI++ = (ushort)(1 + ofset);

                        *pI++ = (ushort)(1 + ofset);
                        *pI++ = (ushort)(2 + ofset);
                        *pI++ = (ushort)(3 + ofset);
                    }

                    mSubMesh.indexData.indexBuffer.Unlock();

                    //Finish up mesh
                    mMesh.BoundingBox = bounds;
                    Vector3 tmp = bounds.Maximum - bounds.Minimum;
                    mMesh.BoundingSphereRadius = tmp.Length * 0.5f;

                    LoggingLevel lvl = LogManager.Instance.LogDetail;
                    LogManager.Instance.LogDetail = LoggingLevel.Low;
                    mMesh.Load();
                    LogManager.Instance.LogDetail = lvl;

                    //Empty the billboardBuffer now, because all billboards have been built
                    mBillboardBuffer.Clear();

                    //Create an entity for the mesh
                    mEntity             = mSceneMgr.CreateEntity(mEntityName, mMesh.Name);
                    mEntity.CastShadows = false;

                    //Apply texture
                    if (mFadeEnabled)
                    {
                        Debug.Assert(mFadeMaterial != null);
                        mEntity.MaterialName = mFadeMaterial.Name;
                    }
                    else
                    {
                        Debug.Assert(mMaterial != null);
                        mEntity.MaterialName = mMaterial.Name;
                    }

                    //Add to scene
                    mNode.AttachObject(mEntity);
                    mEntity.IsVisible = mVisible;
                }
            }
        }