Exemple #1
0
 /// <summary>
 /// Adds layer for baking
 /// </summary>
 /// <param name="tdata">TexturaData struct that contains texture and its params</param>
 public void AddTexture(AppearanceManager.TextureData tdata)
 {
     lock (textures)
     {
         textures.Add(tdata);
     }
 }
        public void Bake()
        {
            bakedTexture = new AssetTexture(new ManagedImage(bakeWidth, bakeHeight,
                                                             ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump));

            // These are for head baking, they get special treatment
            AppearanceManager.TextureData        skinTexture    = new AppearanceManager.TextureData();
            List <AppearanceManager.TextureData> tattooTextures = new List <AppearanceManager.TextureData>();
            List <ManagedImage> alphaWearableTextures           = new List <ManagedImage>();

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

            // Sort out the special layers we need for head baking and alpha
            foreach (AppearanceManager.TextureData tex in textures)
            {
                if (tex.Texture == null)
                {
                    continue;
                }

                if (tex.TextureIndex == AvatarTextureIndex.HeadBodypaint ||
                    tex.TextureIndex == AvatarTextureIndex.UpperBodypaint ||
                    tex.TextureIndex == AvatarTextureIndex.LowerBodypaint)
                {
                    skinTexture = tex;
                }

                if (tex.TextureIndex == AvatarTextureIndex.HeadTattoo ||
                    tex.TextureIndex == AvatarTextureIndex.UpperTattoo ||
                    tex.TextureIndex == AvatarTextureIndex.LowerTattoo)
                {
                    tattooTextures.Add(tex);
                }

                if (tex.TextureIndex >= AvatarTextureIndex.LowerAlpha &&
                    tex.TextureIndex <= AvatarTextureIndex.HairAlpha)
                {
                    if (tex.Texture.Image.Alpha != null)
                    {
                        alphaWearableTextures.Add(tex.Texture.Image.Clone());
                    }
                }
            }

            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.Texture == null)
            {
                if (bakeType == BakeType.UpperBody)
                {
                    DrawLayer(LoadResourceLayer("upperbody_color.tga"), false);
                }

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

            // 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)
                {
                    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 &&
                    (textures[i].TextureIndex == AvatarTextureIndex.HeadBodypaint ||
                     textures[i].TextureIndex == AvatarTextureIndex.HeadTattoo))
                {
                    continue;
                }

                ManagedImage texture = textures[i].Texture.Image.Clone();
                //File.WriteAllBytes(bakeType + "-texture-layer-" + textures[i].TextureIndex + "-" + 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.Texture == null && bakeType == BakeType.Head && textures[i].TextureIndex == AvatarTextureIndex.Hair)
                {
                    if (texture.Alpha != null)
                    {
                        for (int j = 0; j < texture.Alpha.Length; j++)
                        {
                            texture.Alpha[j] = (byte)255;
                        }
                    }
                    MultiplyLayerFromAlpha(texture, LoadResourceLayer("head_hair.tga"));
                }

                bool processingSkin = true;

                // Aply tint and alpha masks except for skin that has a texture
                // on layer 0 which always overrides other skin settings
                if (!(textures[i].TextureIndex == AvatarTextureIndex.HeadBodypaint ||
                      textures[i].TextureIndex == AvatarTextureIndex.UpperBodypaint ||
                      textures[i].TextureIndex == AvatarTextureIndex.LowerBodypaint))
                {
                    processingSkin = false;

                    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 (bakeType == BakeType.Head)
            {
                if (skinTexture.Texture != null)
                {
                    ManagedImage texture = skinTexture.Texture.Image.Clone();
                    if (texture.Width != bakeWidth || texture.Height != bakeHeight)
                    {
                        try { texture.ResizeNearestNeighbor(bakeWidth, bakeHeight); }
                        catch (Exception) { }
                    }
                    DrawLayer(texture, false);
                }

                foreach (AppearanceManager.TextureData tex in tattooTextures)
                {
                    // Add head tattoo here (if available, order-dependant)
                    if (tex.Texture != null)
                    {
                        ManagedImage texture = tex.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
            m_log.DebugFormat("[XBakes]: Number of alpha wearable textures: {0}", alphaWearableTextures.Count);
            foreach (ManagedImage img in alphaWearableTextures)
            {
                AddAlpha(bakedTexture.Image, img);
            }

            // We are done, encode asset for finalized bake
            bakedTexture.Encode();
            //File.WriteAllBytes(bakeType + ".tga", bakedTexture.Image.ExportTGA());
        }
        public void Bake()
        {
            bakedTexture = new AssetTexture(new ManagedImage(bakeWidth, bakeHeight,
                ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump));

            // These are for head baking, they get special treatment
            AppearanceManager.TextureData skinTexture = new AppearanceManager.TextureData();
            List<AppearanceManager.TextureData> tattooTextures = new List<AppearanceManager.TextureData>();
            List<ManagedImage> alphaWearableTextures = new List<ManagedImage>();

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

            // Sort out the special layers we need for head baking and alpha
            foreach (AppearanceManager.TextureData tex in textures)
            {
                if (tex.Texture == null)
                    continue;

                if (tex.TextureIndex == AvatarTextureIndex.HeadBodypaint ||
                        tex.TextureIndex == AvatarTextureIndex.UpperBodypaint ||
                        tex.TextureIndex == AvatarTextureIndex.LowerBodypaint)
                    skinTexture = tex;

                if (tex.TextureIndex == AvatarTextureIndex.HeadTattoo ||
                        tex.TextureIndex == AvatarTextureIndex.UpperTattoo ||
                        tex.TextureIndex == AvatarTextureIndex.LowerTattoo)
                    tattooTextures.Add(tex);

                if (tex.TextureIndex >= AvatarTextureIndex.LowerAlpha &&
                    tex.TextureIndex <= AvatarTextureIndex.HairAlpha)
                {
                    if (tex.Texture.Image.Alpha != null)
                        alphaWearableTextures.Add(tex.Texture.Image.Clone());
                }
            }

            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.Texture == null)
            {
                if (bakeType == BakeType.UpperBody)
                {
                    DrawLayer(LoadResourceLayer("upperbody_color.tga"), false);
                }

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

            // 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)
                    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 &&
                        (textures[i].TextureIndex == AvatarTextureIndex.HeadBodypaint ||
                        textures[i].TextureIndex == AvatarTextureIndex.HeadTattoo))
                    continue;

                ManagedImage texture = textures[i].Texture.Image.Clone();
                //File.WriteAllBytes(bakeType + "-texture-layer-" + textures[i].TextureIndex + "-" + 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.Texture == null && bakeType == BakeType.Head && textures[i].TextureIndex == AvatarTextureIndex.Hair)
                {
                    if (texture.Alpha != null)
                    {
                        for (int j = 0; j < texture.Alpha.Length; j++) texture.Alpha[j] = (byte)255;
                    }
                    MultiplyLayerFromAlpha(texture, LoadResourceLayer("head_hair.tga"));
                }

                bool processingSkin = true;

                // Aply tint and alpha masks except for skin that has a texture
                // on layer 0 which always overrides other skin settings
                if (!(textures[i].TextureIndex == AvatarTextureIndex.HeadBodypaint ||
                        textures[i].TextureIndex == AvatarTextureIndex.UpperBodypaint ||
                        textures[i].TextureIndex == AvatarTextureIndex.LowerBodypaint))
                {
                    processingSkin = false;

                    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 (bakeType == BakeType.Head)
            {
                if (skinTexture.Texture != null)
                {
                    ManagedImage texture = skinTexture.Texture.Image.Clone();
                    if (texture.Width != bakeWidth || texture.Height != bakeHeight)
                    {
                        try { texture.ResizeNearestNeighbor(bakeWidth, bakeHeight); }
                        catch (Exception) { }
                    }
                    DrawLayer(texture, false);
                }

                foreach (AppearanceManager.TextureData tex in tattooTextures)
                {
                    // Add head tattoo here (if available, order-dependant)
                    if (tex.Texture != null)
                    {
                        ManagedImage texture = tex.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
            m_log.DebugFormat("[XBakes]: Number of alpha wearable textures: {0}", alphaWearableTextures.Count);
            foreach (ManagedImage img in alphaWearableTextures)
                AddAlpha(bakedTexture.Image, img);

            // We are done, encode asset for finalized bake
            bakedTexture.Encode();
            //File.WriteAllBytes(bakeType + ".tga", bakedTexture.Image.ExportTGA());
        }
Exemple #4
0
        private void pic_MouseClick(object sender, MouseEventArgs e)
        {
            PictureBox control = (PictureBox)sender;

            OpenFileDialog dialog = new OpenFileDialog();

            // TODO: Setup a dialog.Filter for supported image types

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    System.Drawing.Image image = System.Drawing.Image.FromFile(dialog.FileName);

                    #region Dimensions Check

                    if (control == picEyesBake)
                    {
                        // Eyes texture is 128x128
                        if (Width != 128 || Height != 128)
                        {
                            Bitmap   resized  = new Bitmap(128, 128, image.PixelFormat);
                            Graphics graphics = Graphics.FromImage(resized);

                            graphics.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                            graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                            graphics.DrawImage(image, 0, 0, 128, 128);

                            image.Dispose();
                            image = resized;
                        }
                    }
                    else
                    {
                        // Other textures are 512x512
                        if (Width != 128 || Height != 128)
                        {
                            Bitmap   resized  = new Bitmap(512, 512, image.PixelFormat);
                            Graphics graphics = Graphics.FromImage(resized);

                            graphics.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                            graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                            graphics.DrawImage(image, 0, 0, 512, 512);

                            image.Dispose();
                            image = resized;
                        }
                    }

                    #endregion Dimensions Check

                    // Set the control image
                    control.Image = image;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to load image: " + ex.Message);
                }
            }
            else
            {
                control.Image = null;
            }

            #region Baking

            Dictionary <int, float> paramValues = GetParamValues();
            Dictionary <AvatarTextureIndex, AssetTexture> layers =
                new Dictionary <AvatarTextureIndex, AssetTexture>();
            int textureCount = 0;

            if ((string)control.Tag == "Head")
            {
                if (picHair.Image != null)
                {
                    layers.Add(AvatarTextureIndex.Hair,
                               new AssetTexture(new ManagedImage((Bitmap)picHair.Image)));
                    ++textureCount;
                }
                if (picHeadBodypaint.Image != null)
                {
                    layers.Add(AvatarTextureIndex.HeadBodypaint,
                               new AssetTexture(new ManagedImage((Bitmap)picHeadBodypaint.Image)));
                    ++textureCount;
                }

                // Compute the head bake
                Baker baker = new Baker(BakeType.Head);

                foreach (KeyValuePair <AvatarTextureIndex, AssetTexture> kvp in layers)
                {
                    AppearanceManager.TextureData tdata = new AppearanceManager.TextureData();
                    tdata.Texture = kvp.Value;
                    baker.AddTexture(tdata);
                }

                baker.Bake();

                if (baker.BakedTexture != null)
                {
                    AssetTexture bakeAsset = baker.BakedTexture;
                    // Baked textures use the alpha layer for other purposes, so we need to not use it
                    bakeAsset.Image.Channels = ManagedImage.ImageChannels.Color;
                    picHeadBake.Image        = LoadTGAClass.LoadTGA(new MemoryStream(bakeAsset.Image.ExportTGA()));
                }
                else
                {
                    MessageBox.Show("Failed to create the bake layer, unknown error");
                }
            }
            else if ((string)control.Tag == "Upper")
            {
                if (picUpperBodypaint.Image != null)
                {
                    layers.Add(AvatarTextureIndex.UpperBodypaint,
                               new AssetTexture(new ManagedImage((Bitmap)picUpperBodypaint.Image)));
                    ++textureCount;
                }
                if (picUpperGloves.Image != null)
                {
                    layers.Add(AvatarTextureIndex.UpperGloves,
                               new AssetTexture(new ManagedImage((Bitmap)picUpperGloves.Image)));
                    ++textureCount;
                }
                if (picUpperUndershirt.Image != null)
                {
                    layers.Add(AvatarTextureIndex.UpperUndershirt,
                               new AssetTexture(new ManagedImage((Bitmap)picUpperUndershirt.Image)));
                    ++textureCount;
                }
                if (picUpperShirt.Image != null)
                {
                    layers.Add(AvatarTextureIndex.UpperShirt,
                               new AssetTexture(new ManagedImage((Bitmap)picUpperShirt.Image)));
                    ++textureCount;
                }
                if (picUpperJacket.Image != null)
                {
                    layers.Add(AvatarTextureIndex.UpperJacket,
                               new AssetTexture(new ManagedImage((Bitmap)picUpperJacket.Image)));
                    ++textureCount;
                }

                // Compute the upper body bake
                Baker baker = new Baker(BakeType.UpperBody);

                foreach (KeyValuePair <AvatarTextureIndex, AssetTexture> kvp in layers)
                {
                    AppearanceManager.TextureData tdata = new AppearanceManager.TextureData();
                    tdata.Texture = kvp.Value;
                    baker.AddTexture(tdata);
                }

                baker.Bake();

                if (baker.BakedTexture != null)
                {
                    AssetTexture bakeAsset = baker.BakedTexture;
                    // Baked textures use the alpha layer for other purposes, so we need to not use it
                    bakeAsset.Image.Channels = ManagedImage.ImageChannels.Color;
                    picUpperBodyBake.Image   = LoadTGAClass.LoadTGA(new MemoryStream(bakeAsset.Image.ExportTGA()));
                }
                else
                {
                    MessageBox.Show("Failed to create the bake layer, unknown error");
                }
            }
            else if ((string)control.Tag == "Lower")
            {
                if (picLowerBodypaint.Image != null)
                {
                    layers.Add(AvatarTextureIndex.LowerBodypaint,
                               new AssetTexture(new ManagedImage((Bitmap)picLowerBodypaint.Image)));
                    ++textureCount;
                }
                if (picLowerUnderpants.Image != null)
                {
                    layers.Add(AvatarTextureIndex.LowerUnderpants,
                               new AssetTexture(new ManagedImage((Bitmap)picLowerUnderpants.Image)));
                    ++textureCount;
                }
                if (picLowerSocks.Image != null)
                {
                    layers.Add(AvatarTextureIndex.LowerSocks,
                               new AssetTexture(new ManagedImage((Bitmap)picLowerSocks.Image)));
                    ++textureCount;
                }
                if (picLowerShoes.Image != null)
                {
                    layers.Add(AvatarTextureIndex.LowerShoes,
                               new AssetTexture(new ManagedImage((Bitmap)picLowerShoes.Image)));
                    ++textureCount;
                }
                if (picLowerPants.Image != null)
                {
                    layers.Add(AvatarTextureIndex.LowerPants,
                               new AssetTexture(new ManagedImage((Bitmap)picLowerPants.Image)));
                    ++textureCount;
                }

                // Compute the lower body bake
                Baker baker = new Baker(BakeType.LowerBody);

                foreach (KeyValuePair <AvatarTextureIndex, AssetTexture> kvp in layers)
                {
                    AppearanceManager.TextureData tdata = new AppearanceManager.TextureData();
                    tdata.Texture = kvp.Value;
                    baker.AddTexture(tdata);
                }

                baker.Bake();

                if (baker.BakedTexture != null)
                {
                    AssetTexture bakeAsset = baker.BakedTexture;
                    // Baked textures use the alpha layer for other purposes, so we need to not use it
                    bakeAsset.Image.Channels = ManagedImage.ImageChannels.Color;
                    picLowerBodyBake.Image   = LoadTGAClass.LoadTGA(new MemoryStream(bakeAsset.Image.ExportTGA()));
                }
                else
                {
                    MessageBox.Show("Failed to create the bake layer, unknown error");
                }
            }
            else if ((string)control.Tag == "Bake")
            {
                // Bake image has been set manually, no need to manually calculate a bake
                // FIXME:
            }

            #endregion Baking
        }