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"); } }