private bool IsAlphaImage(TextureExtended tex)
        {
            bool alphaimage = false;
            // Check if we've already run this through our image alpha checker
            if (tex.Userdata == null)
            {
                // Check if this image has an alpha channel in use
                // All textures are 32 Bit and alpha capable, so we have to scan it for an
                // alpha pixel
                Color[,] imgcolors;

                try
                {
                    imgcolors = tex.Retrieve();
                    for (int i = 0; i < imgcolors.GetUpperBound(0); i++)
                    {
                        for (int j = 0; j < imgcolors.GetUpperBound(1); j++)
                        {
                            if (imgcolors[i, j].A != 255)
                            {
                                alphaimage = true;
                                break;
                            }
                        }
                        if (alphaimage)
                            break;
                    }
                }
                catch (OutOfMemoryException)
                {
                    alphaimage = false;
                }
                // Save result
                tex.Userdata = (object)alphaimage;
            }
            else
            {
                // Use cached result
                alphaimage = (bool)tex.Userdata;
            }
            return alphaimage;
        }
        /// <summary>
        /// Bread and butter of the texture system.
        /// This is the start point for the texture-> graphics pipeline
        /// </summary>
        /// <param name="tex"></param>
        /// <param name="vObj"></param>
        /// <param name="AssetID"></param>
        public void applyTexture(TextureExtended tex, VObject vObj, UUID AssetID)
        {
            //return;
            try
            {
                // works
                if (vObj.Mesh == null)
                    return;

                // Check if we have a  sculptie and its sculpting texture
                // If yes, don't apply the texture
                if (vObj.Prim.Sculpt != null && vObj.Prim.Sculpt.SculptTexture == AssetID)
                {
                    m_log.Debug("[TEXTURE]: Skipping applyTexture for sculpt " + AssetID);
                    return;
                }

                bool alphaimage = false;

#if YK_ADD_DEFAULT_TEXTURE
                if (tex == null)
                    tex = defaultTexture;
#endif
                // Check if we've already run this through our image alpha checker
                if (tex.Userdata == null)
                {
                    // Check if this image has an alpha channel in use
                    // All textures are 32 Bit and alpha capable, so we have to scan it for an 
                    // alpha pixel
                    Color[,] imgcolors;

                    //tex.Lock();
                    try
                    {
                        imgcolors = tex.Retrieve();
                        //tex.Unlock();
                        for (int i = 0; i < imgcolors.GetUpperBound(0); i++)
                        {
                            for (int j = 0; j < imgcolors.GetUpperBound(1); j++)
                            {
                                if (imgcolors[i, j].A != 255)
                                {
                                    alphaimage = true;
                                    break;
                                }
                            }
                            if (alphaimage)
                                break;
                        }
                    }
                    catch (OutOfMemoryException)
                    {
                        alphaimage = false;
                    }
                    // Save result
                    tex.Userdata = (object)alphaimage;
                }
                else
                {
                    // Use cached result
                    alphaimage = (bool)tex.Userdata;
                }


//#if NOTYET
                if (vObj._3DiIrrfileUUID != UUID.Zero && vObj.IrrData != null)
                {
#if DebugTexturePipeline
                    m_log.Debug("[3Di Mesh]: 3Di mesh applyTexture for tex " + AssetID + " for irrfile " + vObj._3DiIrrfileUUID);
#endif
                    for (int iTex = 0; iTex < vObj.IrrData.Materials.Count; iTex++)
                    {
#if DebugTexturePipeline
                        m_log.Debug("[3Di Mesh]: This mesh references a texture num " + iTex + ": " + vObj.IrrData.Materials[iTex].Texture1);
#endif
                        if (System.IO.Path.GetFileNameWithoutExtension(vObj.IrrData.Materials[iTex].Texture1) == AssetID.ToString())
                        {
#if DebugTexturePipeline
                            m_log.Debug("[3Di Mesh]: Found the texture reference inside the mesh; loading texture and re-assigning the reference.");
#endif
                            Texture loadedTex = device.VideoDriver.GetTexture(AssetID.ToString() + tex.extension);
                            if (vObj.Node.Children.Length > 0)
                            {
                                vObj.Node.Children[0].GetMaterial(iTex).Texture1 = loadedTex;
                            }
                            else
                            {
#if DebugTexturePipeline
                                m_log.Debug("[3Di Mesh]: Could not assign texture; mesh child not found");
#endif
                            }
                        }
                    }
#if DebugTexturePipeline
                    m_log.Debug("[3Di Mesh]: Finished all materials in this mesh.");
#endif
                    if (alphaimage)
                    {
                        vObj.Node.Children[0].SetMaterialType(MaterialType.TransparentAlphaChannel);
                        device.SceneManager.RegisterNodeForRendering(vObj.Node.Children[0], SceneNodeRenderPass.Transparent);
                    }

                }
                else 
//#endif


                // Apply the Texture based on the TextureEntry
                if(vObj.Prim.Textures != null)
                {
                    device.SceneManager.MeshCache.RemoveMesh(vObj.Mesh);
                    // Check the default texture to ensure that it's not null (why would it be null?)
                    if (vObj.Prim.Textures.DefaultTexture != null)
                    {
                        Color4 coldata = vObj.Prim.Textures.DefaultTexture.RGBA;

                        float shinyval = 0;
                        switch (vObj.Prim.Textures.DefaultTexture.Shiny)
                        {
                            case Shininess.Low:
                                shinyval = 0.8f;
                                coldata.R *= 0.8f;
                                coldata.B *= 0.8f;
                                coldata.G *= 0.8f;
                                break;
                            case Shininess.Medium:
                                shinyval = 0.7f;
                                coldata.R *= 0.6f;
                                coldata.B *= 0.6f;
                                coldata.G *= 0.6f;
                                break;
                            case Shininess.High:
                                shinyval = 0.6f;
                                coldata.R *= 0.3f;
                                coldata.B *= 0.3f;
                                coldata.G *= 0.3f;
                                break;
                        }
                        
                        // The mesh buffers correspond to the faces defined in the textureentry

                        int mbcount = vObj.Mesh.MeshBufferCount;
                        for (int j = 0; j < mbcount; j++)
                        {
                            // Only apply default texture if there isn't one already!
                            // we don't want to overwrite a face specific texture with the default
                            if (vObj.Prim.Textures.DefaultTexture.TextureID == AssetID)
                            {
                                ApplyFaceSettings(vObj, alphaimage, vObj.Prim.Textures.DefaultTexture, tex, j, shinyval, coldata);

                            }
                            else
                            {
                                // Apply color settings
                                ApplyFaceSettings(vObj, alphaimage, vObj.Prim.Textures.DefaultTexture, null, j, shinyval, coldata);
                            }


                            vObj.Mesh.GetMeshBuffer(j).Material.NormalizeNormals = true;
                            vObj.Mesh.GetMeshBuffer(j).Material.GouraudShading = true;
                            vObj.Mesh.GetMeshBuffer(j).Material.BackfaceCulling = (this.texDownloadStyle == TextureDownloadStyle.TEX_DOWNLOAD_ASSETSERVER);
                        }

                    }

                    // default taken care of..   now on to the individual face settings.
                    for (int i = 0; i < vObj.Prim.Textures.FaceTextures.Length; i++)
                    {
                        if (vObj.Prim.Textures.FaceTextures[i] != null)
                        {
                            Primitive.TextureEntryFace teface = vObj.Prim.Textures.FaceTextures[i];

                            if (vObj.Mesh.MeshBufferCount > i)
                            {
                                //if (tex.
                                Color4 coldata = teface.RGBA;
                                float shinyval = 0;
                                switch (teface.Shiny)
                                {
                                    case Shininess.Low:
                                        shinyval = 0.8f;
                                        coldata.R *= 0.8f;
                                        coldata.B *= 0.8f;
                                        coldata.G *= 0.8f;
                                        break;
                                    case Shininess.Medium:
                                        shinyval = 0.7f;
                                        coldata.R *= 0.6f;
                                        coldata.B *= 0.6f;
                                        coldata.G *= 0.6f;
                                        break;
                                    case Shininess.High:
                                        shinyval = 0.6f;
                                        coldata.R *= 0.3f;
                                        coldata.B *= 0.3f;
                                        coldata.G *= 0.3f;
                                        break;
                                }

                                // Apply texture only if this face has it linked
                                if (teface.TextureID == AssetID)
                                {
                                    ApplyFaceSettings(vObj, alphaimage, teface, tex, i, shinyval, coldata);
                                }
                                else
                                {
                                    // Only apply the color settings..
                                    ApplyFaceSettings(vObj, alphaimage, teface, null, i, shinyval, coldata);
                                }
                                vObj.Mesh.GetMeshBuffer(i).Material.NormalizeNormals = true;
                                vObj.Mesh.GetMeshBuffer(i).Material.GouraudShading = true;
                                vObj.Mesh.GetMeshBuffer(i).Material.BackfaceCulling = (this.texDownloadStyle == TextureDownloadStyle.TEX_DOWNLOAD_ASSETSERVER);
                            }
                            else
                            {
                                m_log.Warn("[TEXTUREDEF]: Unable to apply Texture to face because mesh buffer doesn't have definition for face");

                            }
                        }// end check if textureentry face is null
                    } // end loop over textureentry faces array

                    if (vObj.Node is MeshSceneNode)
                    {
                        MeshSceneNode msn = (MeshSceneNode)vObj.Node;
                        
                        msn.SetMesh(vObj.Mesh);
                        if (vObj.Prim.Textures != null)
                        {
                            // Check the default texture to ensure that it's not null (why would it be null?)
                            if (vObj.Prim.Textures.DefaultTexture != null)
                            {
                                Color4 coldata = vObj.Prim.Textures.DefaultTexture.RGBA;
                                IrrlichtNETCP.Color objColor = new Color(
                                    Util.Clamp<int>((int)(coldata.A * 255), 0, 255),
                                    Util.Clamp<int>((int)(coldata.R * 255), 0, 255),
                                    Util.Clamp<int>((int)(coldata.G * 255), 0, 255),
                                    Util.Clamp<int>((int)(coldata.B * 255), 0, 255)
                                    );

                                // Set material color.
                                for (int i = 0; i < msn.MaterialCount; i++)
                                {
#if MATERIAL_DEBUG
                                    lock(NativeElement.Elements) {System.Diagnostics.Debug.WriteLine("Element count before get:" + NativeElement.Elements.Count);}
#endif
                                    msn.GetMaterial(i).AmbientColor = objColor;
#if MATERIAL_DEBUG
                                    lock (NativeElement.Elements) { System.Diagnostics.Debug.WriteLine("Element count after get:" + NativeElement.Elements.Count); }
#endif
                                    msn.GetMaterial(i).DiffuseColor = objColor;
                                    msn.GetMaterial(i).SpecularColor = Color.Black;
                                    msn.GetMaterial(i).EmissiveColor = Color.Black;
                                    msn.GetMaterial(i).Shininess = 0;
                                }
                            }
                        }

#if RECALC_BOUNDINGBOX
                        Box3D box = new Box3D(0, 0, 0, 0, 0, 0);
                        for (int i = 0; i < msn.GetMesh().MeshBufferCount; i++)
                        {
                            msn.GetMesh().GetMeshBuffer(i).RecalculateBoundingBox();
                            box.AddInternalBox(msn.GetMesh().GetMeshBuffer(i).BoundingBox);
                        }
                        msn.GetMesh().BoundingBox = box;
#endif
                    }
                    else
                    {
                        // Swap out the visible untextured object with a textured one.
                        // SceneNode sn = device.SceneManager.AddMeshSceneNode(vObj.Mesh, ParentNode, -1);
                        // ZAKI: Change TextureManager Parent to actual parent node
                        SceneNode sn = device.SceneManager.AddMeshSceneNode(vObj.Mesh, vObj.Node.Parent, -1);
                        sn.Position = vObj.Node.Position;
                        sn.Rotation = vObj.Node.Rotation;
                        sn.Scale = vObj.Node.Scale;
                        sn.DebugDataVisible = DebugSceneType.Off;

                        // If it's translucent, register it for the Transparent phase of rendering
                        if (vObj.Prim.Textures.DefaultTexture.RGBA.A != 1)
                        {
                            device.SceneManager.RegisterNodeForRendering(sn, SceneNodeRenderPass.Transparent);
                        }
                        // Add the new triangle selector
                        sn.TriangleSelector = device.SceneManager.CreateTriangleSelector(vObj.Mesh, sn);
                        sn.TriangleSelector.Drop();
                        Reference.Viewer.EntityManager.AddTriangleSelector(sn.TriangleSelector, sn); 

                        // Delete the old node. 
                        SceneNode oldnode = vObj.Node;
                        Reference.Viewer.EntityManager.DeleteNode(oldnode);

                        // Assign new node
                        vObj.Node = sn;

                    }
                } // prim texture is not null


            }
            catch (AccessViolationException)
            {
                VUtil.LogConsole(this.ToString() + "[ACCESSVIOLATION]", " TextureManager::ApplyTexture");
                m_log.Error("[TEXTURE]: Failed to load texture.");
            }
            catch (NullReferenceException)
            {
                m_log.Error("unable to update texture");
            }
        }