// try and get an entity from the entity collection in this region
 public virtual bool TryGetEntity(EntityName entName, out IEntity foundEnt) {
     bool ret = false;
     foundEnt = null;
     IEntityCollection coll;
     if (this.TryGet<IEntityCollection>(out coll)) {
         IEntity ent;
         if (coll.TryGetEntity(entName, out ent)) {
             foundEnt = ent;
             ret = true;
         }
     }
     return ret;
 }
        public override void DoTextureLoad(EntityName textureEntityName, AssetType typ, DownloadFinishedCallback finishCall)
        {
            EntityNameLL textureEnt = new EntityNameLL(textureEntityName);
            string worldID = textureEnt.EntityPart;
            OMV.UUID binID = new OMV.UUID(worldID);

            if (m_basePath == null) return;

            // do we already have the file?
            string textureFilename = Path.Combine(CacheDirBase, textureEnt.CacheFilename);
            lock (FileSystemAccessLock) {
            if (File.Exists(textureFilename)) {
                m_log.Log(LogLevel.DTEXTUREDETAIL, "DoTextureLoad: Texture file already exists for " + worldID);
                bool hasTransparancy = CheckTextureFileForTransparancy(textureFilename);
                // make the callback happen on a new thread so things don't get tangled (caller getting the callback)
                Object[] finishCallParams = { finishCall, textureEntityName.Name, hasTransparancy };
                m_completionWork.DoLater(FinishCallDoLater, finishCallParams);
                // m_completionWork.DoLater(new FinishCallDoLater(finishCall, textureEntityName.Name, hasTransparancy));
            }
            else {
                bool sendRequest = false;
                lock (m_waiting) {
                    // if this is already being requested, don't waste our time
                    if (m_waiting.ContainsKey(binID)) {
                        m_log.Log(LogLevel.DTEXTUREDETAIL, "DoTextureLoad: Already waiting for " + worldID);
                    }
                    else {
                        WaitingInfo wi = new WaitingInfo(binID, finishCall);
                        wi.filename = textureFilename;
                        wi.type = typ;
                        m_waiting.Add(binID, wi);
                        sendRequest = true;
                    }
                }
                if (sendRequest) {
                    // this is here because RequestTexture might immediately call the callback
                    //   and we should be outside the lock
                    m_log.Log(LogLevel.DTEXTUREDETAIL, "DoTextureLoad: Requesting: " + textureEntityName);
                    // m_texturePipe.RequestTexture(binID, OMV.ImageType.Normal, 50f, 0, 0, OnACDownloadFinished, false);
                    // m_comm.GridClient.Assets.RequestImage(binID, OMV.ImageType.Normal, 101300f, 0, 0, OnACDownloadFinished, false);
                    // m_comm.GridClient.Assets.RequestImage(binID, OMV.ImageType.Normal, 50f, 0, 0, OnACDownloadFinished, false);
                    ThrottleTextureRequests(binID);
                }
            }
            }
            return;
        }
Exemple #3
0
 /// <summary>
 /// </summary>
 /// <param name="localID"></param>
 /// <param name="ent"></param>
 /// <param name="createIt"></param>
 /// <returns>true if we created a new entry</returns>
 public bool TryGetCreateEntity(EntityName entName, out IEntity ent, RegionCreateEntityCallback createIt)
 {
     // m_log.Log(LogLevel.DWORLDDETAIL, "TryGetCreateEntity: n={0}", entName);
     try {
         lock (this) {
             if (!TryGetEntity(entName, out ent))
             {
                 IEntity newEntity = createIt();
                 AddEntity(newEntity);
                 ent = newEntity;
             }
         }
         return(true);
     }
     catch (Exception e) {
         m_log.Log(LogLevel.DBADERROR, "TryGetCreateEntityLocalID: Failed to create entity: {0}", e.ToString());
     }
     ent = null;
     return(false);
 }
        public LLRegionContext(RegionContextBase rcontext, AssetContextBase acontext, 
                        LLTerrainInfo tinfo, OMV.Simulator sim)
            : base(rcontext, acontext)
        {
            m_terrainInfo = tinfo;

            // until we have a better protocol, we know the sims are a fixed size
            m_size = new OMV.Vector3(256f, 256f, 8000f);

            // believe it or not the world coordinates of a sim are hidden in the handle
            uint x, y;
            OMV.Utils.LongToUInts(sim.Handle, out x, out y);
            m_worldBase = new OMV.Vector3d((double)x, (double)y, 0d);

            m_simulator = sim;

            // this should be more general as "GRID/SIM"
            m_name = new EntityName(sim.Name);

            // a cache of requested localIDs so we don't ask too often
            m_recentLocalIDRequests = new Dictionary<uint, int>();

            this.RegisterInterface<LLRegionContext>(this);
        }
 public RegionContextBase GetRegion(EntityName name) {
     RegionContextBase ret = null;
     lock (m_regionList) {
         foreach (RegionContextBase rcb in m_regionList) {
             if (rcb.Name.Equals(name)) {
                 ret = rcb;
                 break;
             }
         }
     }
     return ret;
 }
 // Each entity has a scene node and this is the conversion from the name of the
 // entity to the name of the scene node that contains it.
 public static string ConvertToOgreSceneNodeName(EntityName entName)
 {
     return "SceneNode/" + entName.Name;
 }
 public bool TryGetEntity(EntityName entName, out IEntity ent)
 {
     return m_entityDictionary.TryGetValue(entName.Name, out ent);
 }
 public void RequestMesh(EntityName contextEntity, string meshName)
 {
     m_log.Log(LogLevel.DRENDERDETAIL, "Request for mesh " + meshName);
     lock (m_requestedMeshes) {
     // if this mesh was requested was requested more than some time ago, request again
     if (m_requestedMeshes.ContainsKey(meshName)) {
         if (m_requestedMeshes[meshName] < Utilities.TickCount()) {
             m_requestedMeshes.Remove(meshName);
         }
     }
     if (!m_requestedMeshes.ContainsKey(meshName)) {
         m_requestedMeshes.Add(meshName, Utilities.TickCount() + m_meshRememberTime);
         Object[] meshLaterParams = { meshName, contextEntity };
         m_workQueueReqMesh.DoLater(RequestMeshLater, (object)meshLaterParams);
     }
     }
     return;
 }
        private void CreateMaterialParameters(OMV.Primitive.TextureEntryFace textureFace, 
                    IEntity ent, OMV.Primitive prim, int pBase, ref float[] textureParams, 
                    int faceNum, out String texName)
        {
            OMV.UUID textureID = OMV.Primitive.TextureEntry.WHITE_TEXTURE;
            if (textureFace != null) {
            textureParams[pBase + (int)Ogr.CreateMaterialParam.colorR] = textureFace.RGBA.R;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.colorG] = textureFace.RGBA.G;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.colorB] = textureFace.RGBA.B;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.colorA] = textureFace.RGBA.A;
            if (m_useRendererTextureScaling) {
                textureParams[pBase + (int)Ogr.CreateMaterialParam.scaleU] = 1f / textureFace.RepeatU;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.scaleV] = 1f / textureFace.RepeatV;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.scrollU] = textureFace.OffsetU;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.scrollV] = -textureFace.OffsetV;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.rotate] = textureFace.Rotation;
            }
            else {
                textureParams[pBase + (int)Ogr.CreateMaterialParam.scaleU] = 1.0f;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.scaleV] = 1.0f;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.scrollU] = 1.0f;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.scrollV] = 1.0f;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.rotate] = 0.0f;
            }
            textureParams[pBase + (int)Ogr.CreateMaterialParam.glow] = textureFace.Glow;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.bump] = (float)textureFace.Bump;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.shiny] = (float)textureFace.Shiny;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.fullBright] = textureFace.Fullbright ? 1f : 0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.mappingType] = (float)textureFace.TexMapType;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.mediaFlags] = textureFace.MediaFlags ? 1f : 0f;

            textureParams[pBase + (int)Ogr.CreateMaterialParam.animationFlag] = 0f;
            if (prim != null && (prim.TextureAnim.Face == faceNum || (int)prim.TextureAnim.Face == 255)
                // && ((prim.TextureAnim.Flags & OpenMetaverse.Primitive.TextureAnimMode.ANIM_ON) != 0)) {
                        && ((prim.TextureAnim.Flags != 0))) {
                m_log.Log(LogLevel.DRENDERDETAIL, "Adding animation for material texture");
                textureParams[pBase + (int)Ogr.CreateMaterialParam.animationFlag] = (float)prim.TextureAnim.Flags;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.animSizeX] = (float)prim.TextureAnim.SizeX;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.animSizeY] = (float)prim.TextureAnim.SizeY;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.animStart] = prim.TextureAnim.Start;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.animRate] = prim.TextureAnim.Rate;
                textureParams[pBase + (int)Ogr.CreateMaterialParam.animLength] = prim.TextureAnim.Length;
            }
            else {
                textureParams[pBase + (int)Ogr.CreateMaterialParam.animationFlag] = 0f;
            }

            // since we can't calculate whether material is transparent or not (actually
            //   we don't have that information at this instant), assume color transparent
            if (textureFace.RGBA.A == 1.0) {
                // The vertex color doesn't have alpha. Assume the texture that goes on here does.
                // We do this because we don't have the texture at the moment
                textureParams[pBase + (int)Ogr.CreateMaterialParam.textureHasTransparent] = 2f;
            }
            else {
                // Pass the overall transparancy
                textureParams[pBase + (int)Ogr.CreateMaterialParam.textureHasTransparent] = textureFace.RGBA.A;
            }
            textureID = textureFace.TextureID;
            }
            else {
            textureParams[pBase + (int)Ogr.CreateMaterialParam.colorR] = 0.4f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.colorG] = 0.4f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.colorB] = 0.4f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.colorA] = 0.0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.scaleU] = 1.0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.scaleV] = 1.0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.scrollU] = 1.0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.scrollV] = 1.0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.rotate] = 0.0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.glow] = 0.0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.bump] = (float)OMV.Bumpiness.None;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.shiny] = (float)OMV.Shininess.None;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.fullBright] = 0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.mappingType] = 0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.mediaFlags] = 0f;
            textureParams[pBase + (int)Ogr.CreateMaterialParam.textureHasTransparent] = 0f;
            }
            EntityName textureEntityName = new EntityName(ent, textureID.ToString());
            string textureOgreResourceName = "";
            if (textureID != OMV.Primitive.TextureEntry.WHITE_TEXTURE) {
            textureOgreResourceName = EntityNameOgre.ConvertToOgreNameX(textureEntityName, null);
            }
            texName = textureOgreResourceName;
        }
        /// <summary>
        /// Create a mesh for the avatar. We either use the specified avatar mesh or create the
        /// mesh from the LAD definition file.
        /// </summary>
        public bool CreateAvatarMeshResource(float priority, IEntity ent, string meshName, EntityName contextEntity)
        {
            if (m_defaultAvatarMesh != null && m_defaultAvatarMesh.Length > 0) {
            return CreateAvatarMeshFromDefault(priority, ent, meshName, contextEntity);
            }

            string meshInfoDir = LookingGlassBase.Instance.AppParams.ParamString("Renderer.Avatar.Mesh.InfoDir");
            string meshInfoDefn = LookingGlassBase.Instance.AppParams.ParamString("Renderer.Avatar.Mesh.Description");
            string meshDescriptionDir = LookingGlassBase.Instance.AppParams.ParamString("Renderer.Avatar.Mesh.DescriptionDir");

            Dictionary<string, OMVR.LindenMesh> meshTypes = new Dictionary<string, OMVR.LindenMesh>();

            XmlDocument lad = new XmlDocument();
            lad.Load(Path.Combine(meshInfoDir, meshInfoDefn));

            XmlNodeList meshes = lad.GetElementsByTagName("mesh");
            foreach (XmlNode meshNode in meshes) {
            string type = meshNode.Attributes.GetNamedItem("type").Value;
            int lod = Int32.Parse(meshNode.Attributes.GetNamedItem("lod").Value);
            string fileName = meshNode.Attributes.GetNamedItem("file_name").Value;
            //string minPixelWidth = meshNode.Attributes.GetNamedItem("min_pixel_width").Value;

            // for the moment, ignore the skirt
            if (type == "skirtMesh") continue;

            if (lod == 0) {
                // only collect the meshes with the highest resolution
                try {
                    fileName = Path.Combine(meshDescriptionDir, fileName);
                    if (!meshTypes.ContainsKey(type)) {
                        OMVR.LindenMesh lmesh = new OMVR.LindenMesh(type);
                        lmesh.LoadMesh(fileName);
                        meshTypes.Add(type, lmesh);
                    }
                }
                catch (Exception e) {
                    m_log.Log(LogLevel.DBADERROR, "Failure reading avatar defn file {0}: {1}", fileName, e);
                }
            }
            }
            // meshTypes now contains the pieces of the avatar.

            string[] meshOrder = {
                    "headMesh", "upperBodyMesh", "lowerBodyMesh",
                    "eyeBallLeftMesh", "hairMesh", "skirtMesh",
                    "eyelashMesh", "eyeBallRightMesh"
            };

            // Assemble into one mesh for passing to lower system
            // TODO: get and pass the skeleton information
            if (!CreateAvatarTextures(ent, false)) {
            // something about the textures can't be built yet. Try again later.
            return false;
            }

            const int faceCountsStride = 6;
            const int verticesStride = 8;
            const int indicesStride = 3;
            const int vertexColorStride = 4;
            // calculate how many floating point numbers we're pushing over
            int[] faceCounts = new int[meshTypes.Count * faceCountsStride + 2];
            faceCounts[0] = faceCounts.Length;
            faceCounts[1] = meshTypes.Count;
            int totalVertices = 0;

            try {
            for (int jj=0; jj < meshTypes.Count; jj++) {
                if (!meshTypes.ContainsKey(meshOrder[jj])) continue;
                OMVR.LindenMesh lmesh = meshTypes[meshOrder[jj]];
                int faceBase = jj * faceCountsStride + 2;
                faceCounts[faceBase + 0] = totalVertices;
                faceCounts[faceBase + 1] = lmesh.NumVertices;
                faceCounts[faceBase + 2] = verticesStride;
                totalVertices += vertexColorStride + lmesh.NumVertices * verticesStride;
                faceCounts[faceBase + 3] = totalVertices;
                faceCounts[faceBase + 4] = lmesh.NumFaces * indicesStride;
                faceCounts[faceBase + 5] = indicesStride;
                totalVertices += lmesh.NumFaces * indicesStride;
            }

            float[] faceVertices = new float[totalVertices + 2];
            faceVertices[0] = faceVertices.Length;
            int vertI = 1;
            for (int jj=0; jj < meshTypes.Count; jj++) {
                if (!meshTypes.ContainsKey(meshOrder[jj])) continue;
                OMVR.LindenMesh lmesh = meshTypes[meshOrder[jj]];
                faceVertices[vertI + 0] = 0.6f;
                faceVertices[vertI + 1] = 0.6f;
                faceVertices[vertI + 2] = 0.6f;
                faceVertices[vertI + 3] = 0.5f;
                vertI += vertexColorStride;

                for (int k = 0; k < lmesh.NumVertices; k++) {
                    OMVR.LindenMesh.Vertex thisVert = lmesh.Vertices[k];
                    // m_log.Log(LogLevel.DRENDERDETAIL, "CreateMesh: vertices: p={0}, t={1}, n={2}",
                    //     thisVert.Position.ToString(), thisVert.TexCoord.ToString(), thisVert.Normal.ToString());
                    faceVertices[vertI + 0] = thisVert.Coord.X;
                    faceVertices[vertI + 1] = thisVert.Coord.Y;
                    faceVertices[vertI + 2] = thisVert.Coord.Z;
                    faceVertices[vertI + 3] = thisVert.TexCoord.X;
                    faceVertices[vertI + 4] = thisVert.TexCoord.Y;
                    faceVertices[vertI + 5] = thisVert.Normal.X;
                    faceVertices[vertI + 6] = thisVert.Normal.Y;
                    faceVertices[vertI + 7] = thisVert.Normal.Z;
                    vertI += verticesStride;
                }
                for (int k = 0; k < lmesh.NumFaces; k++) {
                    faceVertices[vertI + 0] = lmesh.Faces[k].Indices[0];
                    faceVertices[vertI + 1] = lmesh.Faces[k].Indices[1];
                    faceVertices[vertI + 2] = lmesh.Faces[k].Indices[2];
                    vertI += indicesStride;
                }
            }
            m_log.Log(LogLevel.DRENDERDETAIL,
                "RenderOgreLL.CreateAvatarMeshResource: {0}, fcs={1}, fs={2}, vi={3}",
                ent.Name, faceCounts.Length, faceVertices.Length, vertI
                );

            // We were passed a 'context' entity. Create a scene node name to pass to
            // Ogre. If the scene node is not found, nothing bad happens.
            string contextSceneNode = EntityNameOgre.ConvertToOgreSceneNodeName(contextEntity);

            // Now create the mesh
            Ogr.CreateMeshResourceBF(priority, meshName, contextSceneNode, faceCounts, faceVertices);
            }
            catch (Exception e) {
            m_log.Log(LogLevel.DBADERROR, "Failure building avatar mesh: {0}", e);
            }

            return true;
        }
 // Each entity has a scene node and this is the conversion from the name of the
 // entity to the name of the scene node that contains it.
 public static string ConvertToOgreEntityName(EntityName entName)
 {
     return "Entity/" + entName.Name;
 }
        private void OnTextureDownloadFinished(string textureEntityName, bool hasTransparancy)
        {
            m_log.Log(LogLevel.DRENDERDETAIL, "OnTextureDownloadFinished {0}", textureEntityName);
            EntityName entName = new EntityName(textureEntityName);
            OMV.UUID id = new OMV.UUID(entName.ExtractEntityFromEntityName());

            TextureInfo info;
            lock (Textures) {
            if (!Textures.TryGetValue(id, out info)) {
                // The id of zero will say that the mipmaps need to be generated before the texture is used
                m_log.Log(LogLevel.DRENDERDETAIL, "Adding TextureInfo for {0}:{1}", entName.Name, id.ToString());
                info.Alpha = hasTransparancy;
            }
            }
        }
Exemple #13
0
 public bool TryGetEntity(EntityName entName, out IEntity ent)
 {
     return(m_entityDictionary.TryGetValue(entName.Name, out ent));
 }
Exemple #14
0
 public EntityName(EntityName entName)
     : this(entName.Name)
 {
 }
 /// <summary>
 /// A global call to find an entity. We ask all the regions if they have it.
 /// This is only here because the renderer looses the context for an entity
 /// when control passes into the renderer and then back. The renderer only
 /// has the name of the entity.
 /// </summary>
 /// <param name="entName">the name of the entity to look for</param>
 /// <param name="ent">place to store the reference to the found entity</param>
 /// <returns>'true' if entity found</returns>
 public bool TryGetEntity(EntityName entName, out IEntity ent) {
     IEntity ret = null;
     lock (m_regionList) {
         foreach (RegionContextBase rcb in m_regionList) {
             IEntityCollection coll;
             if (rcb.TryGet<IEntityCollection>(out coll)) {
                 coll.TryGetEntity(entName, out ret);
             }
             if (ret != null) break;
         }
     }
     ent = ret;
     return (ret != null);
 }
 // Each entity has a scene node and this is the conversion from the name of the
 // entity to the name of the scene node that contains it.
 public static EntityName ConvertToOgreMaterialName(EntityName entName)
 {
     return ConvertToOgreNameY(entName, ".material");
 }
 public bool CreateAvatarMeshFromDefault(float priority, IEntity ent, string meshName, EntityName contextEntity)
 {
     m_log.Log(LogLevel.DBADERROR, "CreateAvatarMeshFromDefault: NOT IMPLEMENTED!!");
     return true;
 }
 // One place to hide the crazy name that the face materials have
 public static string ConvertToOgreMaterialNameX(EntityName entName, int faceNum)
 {
     return ConvertToOgreNameX(entName, ".mesh-" + faceNum.ToString() + ".material");
 }
        /// <summary>
        /// Create a mesh in the renderer.
        /// </summary>
        /// <param name="sMgr">the scene manager receiving  the mesh</param>
        /// <param name="ent">The entity the mesh is coming from</param>
        /// <param name="meshName">The name the mesh should take</param>
        public bool CreateMeshResource(float priority, IEntity ent, string meshName, EntityName contextEntity)
        {
            LLEntityBase llent;
            OMV.Primitive prim;

            try {
            // this will change when we are checking for avatars and other types
            llent = (LLEntityBase)ent;
            prim = llent.Prim;
            if (prim == null) throw new LookingGlassException("ASSERT: RenderOgreLL: prim is null");
            }
            catch (Exception e) {
            m_log.Log(LogLevel.DRENDERDETAIL, "CreateMeshResource: conversion of pointers failed: " + e.ToString());
            throw e;
            }

            int meshType = 0;
            int meshFaces = 0;
            // TODO: This is the start of come code to specialize the creation of standard
            // meshes. Since a large number of prims are cubes, they can share the face vertices
            // and thus reduce the total number of Ogre's vertices stored.
            // At the moment, CheckStandardMeshType returns false so we don't do anything special yet
            lock (ent) {
            if (CheckStandardMeshType(prim, out meshType, out meshFaces)) {
                m_log.Log(LogLevel.DBADERROR, "CreateMeshResource: not implemented Standard Type");
                /*
                // while we're in the neighborhood, we can create the materials
                if (m_buildMaterialsAtMeshCreationTime) {
                    for (int j = 0; j < meshFaces; j++) {
                        CreateMaterialResource2(ent, prim, EntityNameOgre.ConvertToOgreMaterialNameX(ent.Name, j), j);
                    }
                }

                Ogr.CreateStandardMeshResource(meshName, meshType);
                 */
            }
            else {
                OMVR.FacetedMesh mesh;
                try {

                    if (prim.Sculpt != null) {
                        // looks like it's a sculpty. Do it that way
                        EntityNameLL textureEnt = EntityNameLL.ConvertTextureWorldIDToEntityName(ent.AssetContext, prim.Sculpt.SculptTexture);
                        System.Drawing.Bitmap textureBitmap = ent.AssetContext.GetTexture(textureEnt);
                        if (textureBitmap == null) {
                            m_log.Log(LogLevel.DRENDERDETAIL, "CreateMeshResource: waiting for texture for sculpty {0}", ent.Name.Name);
                            // Don't have the texture now so ask for the texture to be loaded.
                            // Note that we ignore the callback and let the work queue requeing get us back here
                            ent.AssetContext.DoTextureLoad(textureEnt, AssetContextBase.AssetType.SculptieTexture,
                                delegate(string name, bool trans) { return; });
                            // This will cause the work queue to requeue the mesh creation and call us
                            //   back later to retry creating the mesh
                            return false;
                        }
                        m_log.Log(LogLevel.DRENDERDETAIL, "CreateMeshResource: mesherizing scuplty {0}", ent.Name.Name);
                        // mesh = m_meshMaker.GenerateSculptMesh(textureBitmap, prim, OMVR.DetailLevel.Highest);
                        mesh = m_meshMaker.GenerateSculptMesh(textureBitmap, prim, OMVR.DetailLevel.Medium);
                        // mesh = m_meshMaker.GenerateSculptMesh(textureBitmap, prim, OMVR.DetailLevel.Low);
                        if (mesh.Faces.Count > 10) {
                            m_log.Log(LogLevel.DBADERROR, "CreateMeshResource: mesh has {0} faces!!!!", mesh.Faces.Count);
                        }
                        textureBitmap.Dispose();
                    }
                    else {
                        // we really should use Low for boxes, med for most things and high for megaprim curves
                        // OMVR.DetailLevel meshDetail = OMVR.DetailLevel.High;
                        OMVR.DetailLevel meshDetail = OMVR.DetailLevel.Medium;
                        if (prim.Type == OMV.PrimType.Box) {
                            meshDetail = OMVR.DetailLevel.Low;
                            // m_log.Log(LogLevel.DRENDERDETAIL, "CreateMeshResource: Low detail for {0}", ent.Name.Name);
                        }
                        mesh = m_meshMaker.GenerateFacetedMesh(prim, meshDetail);
                        if (mesh.Faces.Count > 10) {
                            m_log.Log(LogLevel.DBADERROR, "CreateMeshResource: mesh has {0} faces!!!!", mesh.Faces.Count);
                        }
                    }
                }
                catch (Exception e) {
                    m_log.Log(LogLevel.DRENDERDETAIL, "CreateMeshResource: failed mesh generate for {0}: {1}",
                        ent.Name.Name, e.ToString());
                    throw e;
                }

                // we have the face data. We package this up into a few big arrays to pass them
                //   to the real renderer.

                // we pass two one-dimensional arrays of floating point numbers over to the
                // unmanaged code. The first array contains:
                //   faceCounts[0] = total number of int's in this array (for alloc and freeing in Ogre)
                //   faceCounts[1] = number of faces
                //   faceCounts[2] = offset in second array for beginning of vertex info for face 1
                //   faceCounts[3] = number of vertices for face 1
                //   faceCounts[4] = stride for vertex info for face 1 (= 8)
                //   faceCounts[5] = offset in second array for beginning of indices info for face 1
                //   faceCounts[6] = number of indices for face 1
                //   faceCounts[7] = stride for indices (= 3)
                //   faceCounts[8] = offset in second array for beginning of vertex info for face 2
                //   faceCounts[9] = number of vertices for face 2
                //   faceCounts[10] = stride for vertex info for face 2 (= 8)
                //   etc
                // The second array starts with the vertex color:
                //   v.R, v.G, v.B, v.A
                // which is followed by the vertex info in the order:
                //   v.X, v.Y, v.Z, u.X, u.Y, n.X, n.Y, n.Z
                // this is repeated for each vertex
                // This is followed by the list of indices listed as i.X, i.Y, i.Z

                const int faceCountsStride = 6;
                const int verticesStride = 8;
                const int indicesStride = 3;
                const int vertexColorStride = 4;
                // calculate how many floating point numbers we're pushing over
                int[] faceCounts = new int[mesh.Faces.Count * faceCountsStride + 2];
                faceCounts[0] = faceCounts.Length;
                faceCounts[1] = mesh.Faces.Count;
                int totalVertices = 0;
                for (int j = 0; j < mesh.Faces.Count; j++) {
                    OMVR.Face face = mesh.Faces[j];
                    int faceBase = j * faceCountsStride + 2;
                    // m_log.Log(LogLevel.DRENDERDETAIL, "Mesh F" + j.ToString() + ":"
                    //     + " vcnt=" + face.Vertices.Count.ToString()
                    //     + " icnt=" + face.Indices.Count.ToString());
                    faceCounts[faceBase + 0] = totalVertices;
                    faceCounts[faceBase + 1] = face.Vertices.Count;
                    faceCounts[faceBase + 2] = verticesStride;
                    totalVertices += vertexColorStride + face.Vertices.Count * verticesStride;
                    faceCounts[faceBase + 3] = totalVertices;
                    faceCounts[faceBase + 4] = face.Indices.Count;
                    faceCounts[faceBase + 5] = indicesStride;
                    totalVertices += face.Indices.Count;
                }

                float[] faceVertices = new float[totalVertices+2];
                faceVertices[0] = faceVertices.Length;
                int vertI = 1;
                for (int j = 0; j < mesh.Faces.Count; j++) {
                    OMVR.Face face = mesh.Faces[j];

                    // Texture transform for this face
                    OMV.Primitive.TextureEntryFace teFace = face.TextureFace;
                    try {
                        if ((teFace != null) && !m_useRendererTextureScaling) {
                            m_meshMaker.TransformTexCoords(face.Vertices, face.Center, teFace);
                        }
                    }
                    catch {
                        m_log.Log(LogLevel.DBADERROR, "RenderOgreLL.CreateMeshResource:"
                            + " more faces in mesh than in prim:"
                            + " ent=" + ent.Name
                            + ", face=" + j.ToString()
                        );
                    }

                    // Vertices color for this face
                    OMV.Primitive.TextureEntryFace tef = prim.Textures.GetFace((uint)j);
                    if (tef != null) {
                        faceVertices[vertI + 0] = tef.RGBA.R;
                        faceVertices[vertI + 1] = tef.RGBA.G;
                        faceVertices[vertI + 2] = tef.RGBA.B;
                        faceVertices[vertI + 3] = tef.RGBA.A;
                    }
                    else {
                        faceVertices[vertI + 0] = 1f;
                        faceVertices[vertI + 1] = 1f;
                        faceVertices[vertI + 2] = 1f;
                        faceVertices[vertI + 3] = 1f;
                    }
                    vertI += vertexColorStride;
                    // Vertices for this face
                    for (int k = 0; k < face.Vertices.Count; k++) {
                        OMVR.Vertex thisVert = face.Vertices[k];
                        // m_log.Log(LogLevel.DRENDERDETAIL, "CreateMesh: vertices: p={0}, t={1}, n={2}",
                        //     thisVert.Position.ToString(), thisVert.TexCoord.ToString(), thisVert.Normal.ToString());
                        faceVertices[vertI + 0] = thisVert.Position.X;
                        faceVertices[vertI + 1] = thisVert.Position.Y;
                        faceVertices[vertI + 2] = thisVert.Position.Z;
                        faceVertices[vertI + 3] = thisVert.TexCoord.X;
                        faceVertices[vertI + 4] = thisVert.TexCoord.Y;
                        faceVertices[vertI + 5] = thisVert.Normal.X;
                        faceVertices[vertI + 6] = thisVert.Normal.Y;
                        faceVertices[vertI + 7] = thisVert.Normal.Z;
                        vertI += verticesStride;
                    }
                    for (int k = 0; k < face.Indices.Count; k += 3) {
                        faceVertices[vertI + 0] = face.Indices[k + 0];
                        faceVertices[vertI + 1] = face.Indices[k + 1];
                        faceVertices[vertI + 2] = face.Indices[k + 2];
                        vertI += indicesStride;
                    }
                }

                // while we're in the neighborhood, we can create the materials
                if (m_buildMaterialsAtMeshCreationTime) {
                    CreateMaterialResource7X(priority, ent, prim, mesh.Faces.Count);
                }

                // We were passed a 'context' entity. Create a scene node name to pass to
                // Ogre. If the scene node is not found, nothing bad happens.
                string contextSceneNode = EntityNameOgre.ConvertToOgreSceneNodeName(contextEntity);

                m_log.Log(LogLevel.DRENDERDETAIL,
                    "RenderOgreLL: {0}, f={1}, fcs={2}, fs={3}",
                    ent.Name, mesh.Faces.Count, faceCounts.Length, faceVertices.Length
                    );
                // Now create the mesh
                Ogr.CreateMeshResourceBF(priority, meshName, contextSceneNode, faceCounts, faceVertices);
            }
            }
            return true;
        }
 // Each entity has a scene node and this is the conversion from the name of the
 // entity to the name of the scene node that contains it.
 public static EntityName ConvertToOgreMeshName(EntityName entName)
 {
     return ConvertToOgreNameY(entName, ".mesh");
 }
 // if it starts with our region name, it must be ours
 public override bool isTextureOwner(EntityName textureEntityName)
 {
     return textureEntityName.Name.StartsWith(m_Name + EntityName.PartSeparator);
 }
 // ================================================
 // After here are conversion routines that are sometimes needed to link between
 // the Ogre resource names and regular entity names. Use at your peril.
 // Ogre presumes that entity name will be the filename in the cache. Make the
 // entity name on the Ogre side have the cache filename format
 // Used for meshes, materials
 public static string ConvertToOgreNameX(EntityName entName, string extension)
 {
     string entReplace = Regex.Replace(entName.EntityPart, EntityNameMatch, CachedNameReplace);
     // if the replacement didn't happen entReplace == entName
     string newName = entName.CombineEntityName(entName.HeaderPart, entName.HostPart, entReplace);
     if (extension != null) newName += extension;
     // LogManager.Log.Log(LogLevel.DRENDERDETAIL, "ConvertToOgreName: " + entName.ToString() + " => " + newName);
     return newName;
 }
 public EntityName(EntityName entName)
     : this(entName.Name)
 {
 }
 public static EntityName ConvertToOgreNameY(EntityName entName, string extension)
 {
     string entReplace = Regex.Replace(entName.EntityPart, EntityNameMatch, CachedNameReplace);
     // if the replacement didn't happen entReplace == entName
     if (extension != null) entReplace += extension;
     EntityName newName = new EntityNameOgre(entName.HeaderPart, entName.HostPart, entReplace);
     return newName;
 }
 public EntityNameLL(EntityName ent)
     : base(ent.Name)
 {
 }
 /// <summary>
 /// </summary>
 /// <param name="localID"></param>
 /// <param name="ent"></param>
 /// <param name="createIt"></param>
 /// <returns>true if we created a new entry</returns>
 public bool TryGetCreateEntity(EntityName entName, out IEntity ent, RegionCreateEntityCallback createIt)
 {
     // m_log.Log(LogLevel.DWORLDDETAIL, "TryGetCreateEntity: n={0}", entName);
     try {
     lock (this) {
         if (!TryGetEntity(entName, out ent)) {
             IEntity newEntity = createIt();
             AddEntity(newEntity);
             ent = newEntity;
         }
     }
     return true;
     }
     catch (Exception e) {
     m_log.Log(LogLevel.DBADERROR, "TryGetCreateEntityLocalID: Failed to create entity: {0}", e.ToString());
     }
     ent = null;
     return false;
 }