public RendererOgreLL()
        {
            if (m_meshMaker == null) {
            Renderer.Mesher.MeshmerizerR amesher = new Renderer.Mesher.MeshmerizerR();
            // There is two ways to do scaling: in the mesh or in Ogre. We choose the latter here
            // so we can create shared vertices for the standard shapes (the cubes  that are everywhere)
            // this causes the mesherizer to not scale the node coordinates by the prim scaling factor
            // Update: scaling with Ogre has proved problematic: the scaling effects the mesh and
            // the position coordinates around the object. This is a problem for child nodes.
            // It also effects the texture mapping so texture scaling factors would have to be
            // scaled by the scale of teh face that they appear on. Ugh.
            // For the moment, turned off while I figure that stuff out.
            // m_useRendererMeshScaling = true; // use Ogre to scale the mesh
            m_useRendererMeshScaling = false; // scale the mesh in the meshmerizer
            amesher.ShouldScaleMesh = !m_useRendererMeshScaling;
            m_useRendererTextureScaling = false; // use software texture face scaling
            // m_useRendererTextureScaling = true; // use Ogre texture scaling rather than computing it
            m_meshMaker = amesher;
            }

            // magnification of passed World coordinates into Ogre coordinates
            // NOTE: scene magnification is depricated and probably doesn't work. Leave at 1.0.
            m_sceneMagnification = LookingGlassBase.Instance.AppParams.ParamFloat("Renderer.Ogre.LL.SceneMagnification");
            // true if to creat materials while we are creating the mesh
            m_buildMaterialsAtMeshCreationTime = LookingGlassBase.Instance.AppParams.ParamBool("Renderer.Ogre.LL.EarlyMaterialCreate");
            // true if to create materials while building renderinfo structure
            m_buildMaterialsAtRenderInfoTime = LookingGlassBase.Instance.AppParams.ParamBool("Renderer.Ogre.LL.RenderInfoMaterialCreate");
            // resource name of the mesh to use for an avatar
            m_defaultAvatarMesh = LookingGlassBase.Instance.AppParams.ParamString("Renderer.Ogre.LL.DefaultAvatarMesh");
        }
        private void CreateNewPrim(LLEntityBase ent)
        {
            m_log.Log(LogLevel.DRENDERDETAIL, "Create new prim {0}", ent.Name.Name);
            // entity render info is kept per region. Get the region prim structure
            RegionRenderInfo rri = GetRegionRenderInfo(ent.RegionContext);
            IEntityAvatar av;
            if (ent.TryGet<IEntityAvatar>(out av)) {
            // if this entity is an avatar, just put it on the display list
            lock (rri.renderAvatarList) {
                if (!rri.renderAvatarList.ContainsKey(av.LGID)) {
                    RenderableAvatar ravv = new RenderableAvatar();
                    ravv.avatar = av;
                    rri.renderAvatarList.Add(av.LGID, ravv);
                }
            }
            return;
            }
            OMV.Primitive prim = ent.Prim;
            /* don't do foliage yet
            if (prim.PrimData.PCode == OMV.PCode.Grass
                    || prim.PrimData.PCode == OMV.PCode.Tree
                    || prim.PrimData.PCode == OMV.PCode.NewTree) {
            lock (renderFoliageList)
                renderFoliageList[prim.LocalID] = prim;
            return;
            }
             */

            RenderablePrim render = new RenderablePrim();
            render.Prim = prim;
            render.acontext = ent.AssetContext;
            render.rcontext = ent.RegionContext;
            render.Position = prim.Position;
            render.Rotation = prim.Rotation;
            render.isVisible = true;    // initially assume visible

            if (m_meshMaker == null) {
            m_meshMaker = new Renderer.Mesher.MeshmerizerR();
            m_meshMaker.ShouldScaleMesh = false;
            }

            if (prim.Sculpt != null) {
            EntityNameLL textureEnt = EntityNameLL.ConvertTextureWorldIDToEntityName(ent.AssetContext, prim.Sculpt.SculptTexture);
            System.Drawing.Bitmap textureBitmap = ent.AssetContext.GetTexture(textureEnt);
            if (textureBitmap == null) {
                // the texture is not available. Request it.
                // Note that we just call this routine again when it is available. Hope it's not recursive
                ent.AssetContext.DoTextureLoad(textureEnt, AssetContextBase.AssetType.SculptieTexture,
                            delegate(string name, bool trans) {
                                CreateNewPrim(ent);
                                return;
                            }
                );
                return;
            }
            render.Mesh = m_meshMaker.GenerateSculptMesh(textureBitmap, prim, OMVR.DetailLevel.Medium);
            textureBitmap.Dispose();
            }
            else {
            render.Mesh = m_meshMaker.GenerateFacetedMesh(prim, OMVR.DetailLevel.High);
            }

            if (render.Mesh == null) {
            // mesh generation failed
            m_log.Log(LogLevel.DBADERROR, "FAILED MESH GENERATION: not generating new prim {0}", ent.Name.Name);
            return;
            }

            // Create a FaceData struct for each face that stores the 3D data
            // in an OpenGL friendly format
            for (int j = 0; j < render.Mesh.Faces.Count; j++) {
            OMVR.Face face = render.Mesh.Faces[j];
            FaceData data = new FaceData();

            // Vertices for this face
            data.Vertices = new float[face.Vertices.Count * 3];
            for (int k = 0; k < face.Vertices.Count; k++) {
                data.Vertices[k * 3 + 0] = face.Vertices[k].Position.X;
                data.Vertices[k * 3 + 1] = face.Vertices[k].Position.Y;
                data.Vertices[k * 3 + 2] = face.Vertices[k].Position.Z;
            }

            // Indices for this face
            data.Indices = face.Indices.ToArray();

            // Texture transform for this face
            OMV.Primitive.TextureEntryFace teFace = prim.Textures.GetFace((uint)j);
            m_meshMaker.TransformTexCoords(face.Vertices, face.Center, teFace);

            // Texcoords for this face
            data.TexCoords = new float[face.Vertices.Count * 2];
            for (int k = 0; k < face.Vertices.Count; k++) {
                data.TexCoords[k * 2 + 0] = face.Vertices[k].TexCoord.X;
                data.TexCoords[k * 2 + 1] = face.Vertices[k].TexCoord.Y;
            }

            data.Normals = new float[face.Vertices.Count * 3];
            for (int k = 0; k < face.Vertices.Count; k++) {
                data.Normals[k * 3 + 0] = face.Vertices[k].Normal.X;
                data.Normals[k * 3 + 1] = face.Vertices[k].Normal.Y;
                data.Normals[k * 3 + 2] = face.Vertices[k].Normal.Z;
            }

            // m_log.Log(LogLevel.DRENDERDETAIL, "CreateNewPrim: v={0}, i={1}, t={2}",
            //     data.Vertices.GetLength(0), data.Indices.GetLength(0), data.TexCoords.GetLength(0));

            // Texture for this face
            if (teFace.TextureID != OMV.UUID.Zero &&
                        teFace.TextureID != OMV.Primitive.TextureEntry.WHITE_TEXTURE) {
                lock (Textures) {
                    if (!Textures.ContainsKey(teFace.TextureID)) {
                        // temporarily add the entry to the table so we don't request it multiple times
                        Textures.Add(teFace.TextureID, new TextureInfo(0, true));
                        // We haven't constructed this image in OpenGL yet, get ahold of it
                        AssetContextBase.RequestTextureLoad(
                            EntityNameLL.ConvertTextureWorldIDToEntityName(ent.AssetContext, teFace.TextureID),
                            AssetContextBase.AssetType.Texture,
                            OnTextureDownloadFinished);
                    }
                }
            }

            // Set the UserData for this face to our FaceData struct
            face.UserData = data;
            render.Mesh.Faces[j] = face;
            }

            lock (rri.renderPrimList) {
            rri.renderPrimList[prim.LocalID] = render;
            }
        }