Example #1
0
        /// <summary>
        /// Fetch a texture and return an OMVA.AssetTexture. The only information initialized
        /// in the AssetTexture is the UUID and the binary data.s
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        public override IPromise <OMVA.AssetTexture> FetchTexture(EntityHandle handle)
        {
            var prom = new Promise <OMVA.AssetTexture>();

            // Don't bother with async -- this call will hang until the asset is fetched
            AssetBase asset = _assetService.Get(handle.ToString());

            if (asset != null && asset.IsBinaryAsset && asset.Type == (sbyte)OMV.AssetType.Texture)
            {
                OMVA.AssetTexture tex = new OMVA.AssetTexture(((EntityHandleUUID)handle).GetUUID(), asset.Data);
                try {
                    if (tex.Decode())
                    {
                        prom.Resolve(tex);
                    }
                    else
                    {
                        prom.Reject(new Exception("FetchTexture: could not decode JPEG2000 texture. ID=" + handle.ToString()));
                    }
                }
                catch (Exception e) {
                    prom.Reject(new Exception("FetchTexture: exception decoding JPEG2000 texture. ID=" + handle.ToString()
                                              + ", e=" + e.ToString()));
                }
            }
            else
            {
                prom.Reject(new Exception("FetchTexture: asset was not of type texture. ID=" + handle.ToString()));
            }

            return(prom);
        }
Example #2
0
        public void Bake()
        {
            bakedTexture = new AssetTexture(new ManagedImage(bakeWidth, bakeHeight,
                ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump));

            // Base color for eye bake is white, color of layer0 for others
            if (bakeType == BakeType.Eyes)
            {
                InitBakedLayerColor(Color4.White);
            }
            else if (textures.Count > 0)
            {
                InitBakedLayerColor(textures[0].Color);
            }

            // Do we have skin texture?
            bool SkinTexture = textures.Count > 0 && textures[0].Texture != null;

            if (bakeType == BakeType.Head)
            {
                DrawLayer(LoadResourceLayer("head_color.tga"), false);
                AddAlpha(bakedTexture.Image, LoadResourceLayer("head_alpha.tga"));
                MultiplyLayerFromAlpha(bakedTexture.Image, LoadResourceLayer("head_skingrain.tga"));
            }

            if (!SkinTexture && bakeType == BakeType.UpperBody)
            {
                DrawLayer(LoadResourceLayer("upperbody_color.tga"), false);
            }

            if (!SkinTexture && bakeType == BakeType.LowerBody)
            {
                DrawLayer(LoadResourceLayer("lowerbody_color.tga"), false);
            }

            ManagedImage alphaWearableTexture = null;

            // Layer each texture on top of one other, applying alpha masks as we go
            for (int i = 0; i < textures.Count; i++)
            {
                // Skip if we have no texture on this layer
                if (textures[i].Texture == null) continue;

                // Is this Alpha wearable and does it have an alpha channel?
                if (textures[i].TextureIndex >= AvatarTextureIndex.LowerAlpha &&
                    textures[i].TextureIndex <= AvatarTextureIndex.HairAlpha)
                {
                    if (textures[i].Texture.Image.Alpha != null)
                    {
                        alphaWearableTexture = textures[i].Texture.Image.Clone();
                    }
                    continue;
                }

                // Don't draw skin and tattoo on head bake first
                // For head bake the skin and texture are drawn last, go figure
                if (bakeType == BakeType.Head && (i == 0 || i == 1)) continue;

                ManagedImage texture = textures[i].Texture.Image.Clone();
                //File.WriteAllBytes(bakeType + "-texture-layer-" + i + ".tga", texture.ExportTGA());

                // Resize texture to the size of baked layer
                // FIXME: if texture is smaller than the layer, don't stretch it, tile it
                if (texture.Width != bakeWidth || texture.Height != bakeHeight)
                {
                    try { texture.ResizeNearestNeighbor(bakeWidth, bakeHeight); }
                    catch (Exception) { continue; }
                }

                // Special case for hair layer for the head bake
                // If we don't have skin texture, we discard hair alpha
                // and apply hair(i==2) pattern over the texture
                if (!SkinTexture && bakeType == BakeType.Head && i == 2)
                {
                    if (texture.Alpha != null)
                    {
                        for (int j = 0; j < texture.Alpha.Length; j++) texture.Alpha[j] = (byte)255;
                    }
                    MultiplyLayerFromAlpha(texture, LoadResourceLayer("head_hair.tga"));
                }

                // Aply tint and alpha masks except for skin that has a texture
                // on layer 0 which always overrides other skin settings
                if (!(IsSkin && i == 0))
                {
                    ApplyTint(texture, textures[i].Color);

                    // For hair bake, we skip all alpha masks
                    // and use one from the texture, for both
                    // alpha and morph layers
                    if (bakeType == BakeType.Hair)
                    {
                        if (texture.Alpha != null)
                        {
                            bakedTexture.Image.Bump = texture.Alpha;
                        }
                        else
                        {
                            for (int j = 0; j < bakedTexture.Image.Bump.Length; j++) bakedTexture.Image.Bump[j] = byte.MaxValue;
                        }
                    }
                    // Apply parametrized alpha masks
                    else if (textures[i].AlphaMasks != null && textures[i].AlphaMasks.Count > 0)
                    {
                        // Combined mask for the layer, fully transparent to begin with
                        ManagedImage combinedMask = new ManagedImage(bakeWidth, bakeHeight, ManagedImage.ImageChannels.Alpha);

                        int addedMasks = 0;

                        // First add mask in normal blend mode
                        foreach (KeyValuePair<VisualAlphaParam, float> kvp in textures[i].AlphaMasks)
                        {
                            if (!MaskBelongsToBake(kvp.Key.TGAFile)) continue;

                            if (kvp.Key.MultiplyBlend == false && (kvp.Value > 0f || !kvp.Key.SkipIfZero))
                            {
                                ApplyAlpha(combinedMask, kvp.Key, kvp.Value);
                                //File.WriteAllBytes(bakeType + "-layer-" + i + "-mask-" + addedMasks + ".tga", combinedMask.ExportTGA());
                                addedMasks++;
                            }
                        }

                        // If there were no mask in normal blend mode make aplha fully opaque
                        if (addedMasks == 0) for (int l = 0; l < combinedMask.Alpha.Length; l++) combinedMask.Alpha[l] = 255;

                        // Add masks in multiply blend mode
                        foreach (KeyValuePair<VisualAlphaParam, float> kvp in textures[i].AlphaMasks)
                        {
                            if (!MaskBelongsToBake(kvp.Key.TGAFile)) continue;

                            if (kvp.Key.MultiplyBlend == true && (kvp.Value > 0f || !kvp.Key.SkipIfZero))
                            {
                                ApplyAlpha(combinedMask, kvp.Key, kvp.Value);
                                //File.WriteAllBytes(bakeType + "-layer-" + i + "-mask-" + addedMasks + ".tga", combinedMask.ExportTGA());
                                addedMasks++;
                            }
                        }

                        if (addedMasks > 0)
                        {
                            // Apply combined alpha mask to the cloned texture
                            AddAlpha(texture, combinedMask);
                        }

                        // Is this layer used for morph mask? If it is, use its
                        // alpha as the morth for the whole bake
                        if (Textures[i].TextureIndex == AppearanceManager.MorphLayerForBakeType(bakeType))
                        {
                            bakedTexture.Image.Bump = texture.Alpha;
                        }

                        //File.WriteAllBytes(bakeType + "-masked-texture-" + i + ".tga", texture.ExportTGA());
                    }
                }

                bool useAlpha = i == 0 && (BakeType == BakeType.Skirt || BakeType == BakeType.Hair);
                DrawLayer(texture, useAlpha);
                //File.WriteAllBytes(bakeType + "-layer-" + i + ".tga", texture.ExportTGA());
            }

            // For head and tattoo, we add skin last
            if (IsSkin && bakeType == BakeType.Head)
            {
                ManagedImage texture;
                if (textures[0].Texture != null)
                {
                    texture = textures[0].Texture.Image.Clone();
                    if (texture.Width != bakeWidth || texture.Height != bakeHeight)
                    {
                        try { texture.ResizeNearestNeighbor(bakeWidth, bakeHeight); }
                        catch (Exception) { }
                    }
                    DrawLayer(texture, false);
                }

                // Add head tattoo here (if available, order-dependant)
                if (textures.Count > 1 && textures[1].Texture != null)
                {
                    texture = textures[1].Texture.Image.Clone();
                    if (texture.Width != bakeWidth || texture.Height != bakeHeight)
                    {
                        try { texture.ResizeNearestNeighbor(bakeWidth, bakeHeight); }
                        catch (Exception) { }
                    }
                    DrawLayer(texture, false);
                }
            }

            // Apply any alpha wearable textures to make parts of the avatar disappear
            if (alphaWearableTexture != null)
            {
                AddAlpha(bakedTexture.Image, alphaWearableTexture);
            }

            // We are done, encode asset for finalized bake
            bakedTexture.Encode();
            //File.WriteAllBytes(bakeType + ".tga", bakedTexture.Image.ExportTGA());
        }
Example #3
0
        private static bool LoadAsset(string assetPath, byte[] data, AssetLoadedCallback assetCallback, long bytesRead, long totalBytes)
        {
            // Right now we're nastily obtaining the UUID from the filename
            string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
            int    i        = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR);

            if (i == -1)
            {
                Logger.Log(String.Format(
                               "[OarFile]: Could not find extension information in asset path {0} since it's missing the separator {1}.  Skipping",
                               assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR), Helpers.LogLevel.Warning);
                return(false);
            }

            string extension = filename.Substring(i);
            UUID   uuid;

            UUID.TryParse(filename.Remove(filename.Length - extension.Length), out uuid);

            if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
            {
                AssetType assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
                Asset     asset     = null;

                switch (assetType)
                {
                case AssetType.Animation:
                    asset = new AssetAnimation(uuid, data);
                    break;

                case AssetType.Bodypart:
                    asset = new AssetBodypart(uuid, data);
                    break;

                case AssetType.Clothing:
                    asset = new AssetClothing(uuid, data);
                    break;

                case AssetType.Gesture:
                    asset = new AssetGesture(uuid, data);
                    break;

                case AssetType.Landmark:
                    asset = new AssetLandmark(uuid, data);
                    break;

                case AssetType.LSLBytecode:
                    asset = new AssetScriptBinary(uuid, data);
                    break;

                case AssetType.LSLText:
                    asset = new AssetScriptText(uuid, data);
                    break;

                case AssetType.Notecard:
                    asset = new AssetNotecard(uuid, data);
                    break;

                case AssetType.Object:
                    asset = new AssetPrim(uuid, data);
                    break;

                case AssetType.Sound:
                    asset = new AssetSound(uuid, data);
                    break;

                case AssetType.Texture:
                    asset = new AssetTexture(uuid, data);
                    break;

                default:
                    Logger.Log("[OarFile] Unhandled asset type " + assetType, Helpers.LogLevel.Error);
                    break;
                }

                if (asset != null)
                {
                    assetCallback(asset, bytesRead, totalBytes);
                    return(true);
                }
            }

            Logger.Log("[OarFile] Failed to load asset", Helpers.LogLevel.Warning);
            return(false);
        }
Example #4
0
        protected void Bake()
        {
            _bakedTexture = new AssetTexture(new ManagedImage(_bakeWidth, _bakeHeight,
                ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump));

            if (_bakeType == AppearanceManager.BakeType.Eyes)
            {
                InitBakedLayerColor(255, 255, 255);
                DrawLayer(AppearanceManager.TextureIndex.EyesIris);
            }
            else if (_bakeType == AppearanceManager.BakeType.Head)
            {
                // FIXME: Need to use the visual parameters to determine the base skin color in RGB but
                // it's not apparent how to define RGB levels from the skin color parameters, so
                // for now use a grey foundation for the skin
                InitBakedLayerColor(128, 128, 128);
                DrawLayer(AppearanceManager.TextureIndex.HeadBodypaint);

                // HACK: Bake the eyelashes in if we have them
                ManagedImage eyelashes = LoadAlphaLayer("head_alpha.tga");

                if (eyelashes != null)
                {
                    Logger.DebugLog("Loaded head_alpha.tga, baking in eyelashes");
                    DrawLayer(eyelashes, true);
                }
                else
                {
                    Logger.Log("head_alpha.tga resource not found, skipping eyelashes", Helpers.LogLevel.Info);
                }
            }
            else if (_bakeType == AppearanceManager.BakeType.Skirt)
            {
                float skirtRed = 1.0f, skirtGreen = 1.0f, skirtBlue = 1.0f;

                try
                {
                    _paramValues.TryGetValue(VisualParams.Find("skirt_red", "skirt").ParamID, out skirtRed);
                    _paramValues.TryGetValue(VisualParams.Find("skirt_green", "skirt").ParamID, out skirtGreen);
                    _paramValues.TryGetValue(VisualParams.Find("skirt_blue", "skirt").ParamID, out skirtBlue);
                }
                catch
                {
                    Logger.Log("Unable to determine skirt color from visual params", Helpers.LogLevel.Warning, _client);
                }

                InitBakedLayerColor((byte)(skirtRed * 255.0f), (byte)(skirtGreen * 255.0f), (byte)(skirtBlue * 255.0f));
                DrawLayer(AppearanceManager.TextureIndex.Skirt);
            }
            else if (_bakeType == AppearanceManager.BakeType.UpperBody)
            {
                InitBakedLayerColor(128, 128, 128);
                DrawLayer(AppearanceManager.TextureIndex.UpperBodypaint);
                DrawLayer(AppearanceManager.TextureIndex.UpperUndershirt);
                DrawLayer(AppearanceManager.TextureIndex.UpperGloves);
                DrawLayer(AppearanceManager.TextureIndex.UpperShirt);
                DrawLayer(AppearanceManager.TextureIndex.UpperJacket);
            }
            else if (_bakeType == AppearanceManager.BakeType.LowerBody)
            {
                InitBakedLayerColor(128, 128, 128);
                DrawLayer(AppearanceManager.TextureIndex.LowerBodypaint);
                DrawLayer(AppearanceManager.TextureIndex.LowerUnderpants);
                DrawLayer(AppearanceManager.TextureIndex.LowerSocks);
                DrawLayer(AppearanceManager.TextureIndex.LowerShoes);
                DrawLayer(AppearanceManager.TextureIndex.LowerPants);
                DrawLayer(AppearanceManager.TextureIndex.LowerJacket);
            }
            else if (_bakeType == AppearanceManager.BakeType.Hair)
            {
                InitBakedLayerColor(255, 255, 255);
                DrawLayer(AppearanceManager.TextureIndex.Hair);
            }

            _bakedTexture.Encode();
        }
Example #5
0
        /// <summary>
        /// Adds an image to this baking texture and potentially processes it, or
        /// stores it for processing later
        /// </summary>
        /// <param name="index">The baking texture index of the image to be added</param>
        /// <param name="texture">JPEG2000 compressed image to be
        /// added to the baking texture</param>
        /// <param name="needsDecode">True if <code>Decode()</code> needs to be
        /// called for the texture, otherwise false</param>
        /// <returns>True if this texture is completely baked and JPEG2000 data 
        /// is available, otherwise false</returns>
        public bool AddTexture(AppearanceManager.TextureIndex index, AssetTexture texture, bool needsDecode)
        {
            lock (_textures)
            {
                if (needsDecode)
                {
                    try
                    {
                        texture.Decode();
                    }
                    catch (Exception e)
                    {
                        Logger.Log(String.Format("AddTexture({0}, {1})", index, texture.AssetID), Helpers.LogLevel.Error, e);
                        return false;
                    }
                }

                _textures.Add(index, texture);
                Logger.DebugLog(String.Format("Added texture {0} (ID: {1}) to bake {2}", index, texture.AssetID, _bakeType), _client);
            }

            if (_textures.Count >= _textureCount)
            {
                Bake();
                return true;
            }
            else
            {
                return false;
            }
        }