示例#1
0
        /// <summary>
        /// Gets the texture maps for the model
        /// </summary>
        /// <returns>The texture maps in byte arrays inside a ModelTextureData class</returns>
        public ModelTextureData GetModelMaps(Color?customColor = null, bool colorChangeShader = false)
        {
            var texMapData = GetTexMapData();

            var dimensions = EqualizeTextureSizes(texMapData);

            var materialType = GetMaterialType(_mtrlData.MTRLPath);

            var diffuseMap  = new List <byte>();
            var normalMap   = new List <byte>();
            var specularMap = new List <byte>();
            var emissiveMap = new List <byte>();
            var alphaMap    = new List <byte>();

            var diffuseColorList  = new List <Color>();
            var specularColorList = new List <Color>();
            var emissiveColorList = new List <Color>();

            if (texMapData.ColorSet != null)
            {
                var colorPixels = texMapData.ColorSet.Data;

                for (var i = 0; i < texMapData.ColorSet.Data.Length; i += 16)
                {
                    int red   = colorPixels[i];
                    int green = colorPixels[i + 1];
                    int blue  = colorPixels[i + 2];
                    int alpha = colorPixels[i + 3];

                    diffuseColorList.Add(new Color(red, green, blue));

                    red   = colorPixels[i + 4];
                    green = colorPixels[i + 5];
                    blue  = colorPixels[i + 6];
                    alpha = colorPixels[i + 7];

                    specularColorList.Add(new Color(red, green, blue));

                    red   = colorPixels[i + 8];
                    green = colorPixels[i + 9];
                    blue  = colorPixels[i + 10];
                    alpha = colorPixels[i + 11];

                    emissiveColorList.Add(new Color(red, green, blue));
                }
            }
            else
            {
                for (var i = 0; i < 1024; i += 16)
                {
                    if (!materialType.Equals("other") && !materialType.Equals("housing"))
                    {
                        if (customColor != null)
                        {
                            diffuseColorList.Add(customColor.GetValueOrDefault());
                        }
                        else
                        {
                            if (!materialType.Equals("body"))
                            {
                                diffuseColorList.Add(new Color(96, 57, 19));
                            }
                            else
                            {
                                diffuseColorList.Add(new Color(255, 255, 255));
                            }
                        }
                    }
                    else
                    {
                        diffuseColorList.Add(new Color(255, 255, 255));
                    }

                    specularColorList.Add(new Color(25, 25, 25));
                    emissiveColorList.Add(new Color(0, 0, 0));
                }
            }

            byte[] diffusePixels = null, specularPixels = null, multiPixels = null, skinPixels = null, normalPixels = null;

            if (texMapData.Normal != null)
            {
                normalPixels = texMapData.Normal.Data;
            }

            if (texMapData.Diffuse != null)
            {
                diffusePixels = texMapData.Diffuse.Data;
            }

            if (texMapData.Specular != null)
            {
                specularPixels = texMapData.Specular.Data;
            }

            if (texMapData.Multi != null)
            {
                multiPixels = texMapData.Multi.Data;
            }

            if (texMapData.Skin != null)
            {
                skinPixels = texMapData.Skin.Data;
            }

            byte diffR = 255, diffG = 255, diffB = 255;
            byte specR = 255, specG = 255, specB = 255;
            byte normR = 255, normG = 255, normB = 255;

            var dataLength = 0;

            if (normalPixels != null)
            {
                dataLength = normalPixels.Length;
            }
            else if (diffusePixels != null)
            {
                dataLength = diffusePixels.Length;
            }

            for (var i = 3; i < dataLength; i += 4)
            {
                var alpha = 255;

                if (normalPixels != null)
                {
                    normR = normalPixels[i - 3];
                    normG = normalPixels[i - 2];
                    alpha = normalPixels[i - 1]; // This is the normal maps blue channel, and usually acts as the alpha channel


                    if (materialType.Equals("hair") || materialType.Equals("etc") || materialType.Equals("tail"))
                    {
                        normR = normalPixels[i - 3];
                        normG = normalPixels[i - 2];
                        normB = normalPixels[i - 1];
                        alpha = normalPixels[i];
                    }
                }
                else if (diffusePixels != null)
                {
                    alpha = diffusePixels[i];
                }

                if (materialType.Equals("housing"))
                {
                    if (colorChangeShader)
                    {
                        alpha = normalPixels != null ? normalPixels[i] : 255;
                    }
                    else
                    {
                        alpha = diffusePixels != null ? diffusePixels[i] : 255;
                    }
                }

                if (multiPixels != null)
                {
                    diffR = multiPixels[i - 3];
                    diffG = multiPixels[i - 3];
                    diffB = multiPixels[i - 3];

                    specR = multiPixels[i - 1];
                    specG = multiPixels[i - 1];
                    specB = multiPixels[i - 1];
                }
                else
                {
                    if (diffusePixels != null)
                    {
                        diffR = diffusePixels[i - 3];
                        diffG = diffusePixels[i - 2];
                        diffB = diffusePixels[i - 1];
                    }

                    if (specularPixels != null)
                    {
                        if (specularPixels.Length > i)
                        {
                            specR = specularPixels[i - 3];
                            specG = specularPixels[i - 2];
                            specB = specularPixels[i - 1];
                        }
                    }

                    if (skinPixels != null)
                    {
                        specR = skinPixels[i - 3];
                        specG = skinPixels[i - 2];
                        specB = skinPixels[i - 1];
                    }
                }

                Color diffuseColor, specularColor, emissiveColor, alphaColor;

                var pixel        = 0f;
                var blendPercent = 0f;

                if (normalPixels != null)
                {
                    pixel        = (normalPixels[i] / 255f) * 15f;
                    blendPercent = (float)(pixel - Math.Truncate(pixel));
                }

                if (materialType.Equals("hair") || materialType.Equals("etc") || materialType.Equals("tail"))
                {
                    pixel        = 0;
                    blendPercent = 0;
                }

                if (blendPercent != 0)
                {
                    var firstColorLocation  = (int)Math.Truncate(pixel);
                    var secondColorLocation = firstColorLocation + 1;

                    var diffColor1 = diffuseColorList[secondColorLocation];
                    var diffColor2 = diffuseColorList[firstColorLocation];

                    var firstColor  = new Color(diffColor1.R, diffColor1.G, diffColor1.B, alpha);
                    var secondColor = new Color(diffColor2.R, diffColor2.G, diffColor2.B, alpha);

                    var diffuseBlend = Blend(firstColor, secondColor, blendPercent);

                    var specColor1 = specularColorList[secondColorLocation];
                    var specColor2 = specularColorList[firstColorLocation];

                    firstColor  = new Color(specColor1.R, specColor1.G, specColor1.B, (byte)255);
                    secondColor = new Color(specColor2.R, specColor2.G, specColor2.B, (byte)255);

                    var specBlend = Blend(firstColor, secondColor, blendPercent);

                    var emisColor1 = emissiveColorList[secondColorLocation];
                    var emisColor2 = emissiveColorList[firstColorLocation];

                    firstColor  = new Color(emisColor1.R, emisColor1.G, emisColor1.B, (byte)255);
                    secondColor = new Color(emisColor2.R, emisColor2.G, emisColor2.B, (byte)255);

                    var emisBlend = Blend(firstColor, secondColor, blendPercent);

                    diffuseColor  = new Color((int)((diffuseBlend.R / 255f) * diffR), (int)((diffuseBlend.G / 255f) * diffG), (int)((diffuseBlend.B / 255f) * diffB), alpha);
                    specularColor = new Color((int)((specBlend.R / 255f) * specR), (int)((specBlend.G / 255f) * specG), (int)((specBlend.B / 255f) * specB), 255);
                    emissiveColor = new Color((int)emisBlend.R, (int)emisBlend.G, (int)emisBlend.B, (int)255);
                }
                else
                {
                    var colorLoc = (int)Math.Floor(pixel + 0.5f);

                    var diffColor = diffuseColorList[colorLoc];
                    var specColor = specularColorList[colorLoc];
                    var emisColor = emissiveColorList[colorLoc];

                    if (materialType.Equals("hair") || materialType.Equals("etc") || materialType.Equals("tail"))
                    {
                        diffuseColor  = new Color((int)((diffColor.R / 255f) * specR), (int)((diffColor.G / 255f) * specR), (int)((diffColor.B / 255f) * specR), alpha);
                        specularColor = new Color((int)((specColor.R / 255f) * specG), (int)((specColor.G / 255f) * specG), (int)((specColor.B / 255f) * specG), 255);
                    }
                    else
                    {
                        diffuseColor = new Color((int)((diffColor.R / 255f) * diffR), (int)((diffColor.G / 255f) * diffG), (int)((diffColor.B / 255f) * diffB), alpha);

                        if (materialType.Equals("body"))
                        {
                            specularColor = new Color((int)((specColor.R / 255f) * specG),
                                                      (int)((specColor.G / 255f) * specG), (int)((specColor.B / 255f) * specG), 255);
                        }
                        else if (materialType.Equals("housing"))
                        {
                            specularColor = new Color((int)((specColor.R / 255f) * specG), (int)((specColor.G / 255f) * specG), (int)((specColor.B / 255f) * specG), 255);
                        }
                        else
                        {
                            specularColor = new Color((int)((specColor.R / 255f) * specB), (int)((specColor.G / 255f) * specB), (int)((specColor.B / 255f) * specB), 255);
                        }
                    }

                    emissiveColor = new Color((int)emisColor.R, (int)emisColor.G, (int)emisColor.B, (int)255);
                }

                alphaColor = new Color((int)alpha, (int)alpha, (int)alpha, (int)alpha);

                diffuseMap.AddRange(BitConverter.GetBytes(diffuseColor.ToRgba()));
                specularMap.AddRange(BitConverter.GetBytes(specularColor.ToRgba()));
                emissiveMap.AddRange(BitConverter.GetBytes(emissiveColor.ToRgba()));
                alphaMap.AddRange(BitConverter.GetBytes(alphaColor.ToRgba()));
                normalMap.AddRange(BitConverter.GetBytes(new Color(normR, normG, normB, (byte)255).ToRgba()));
            }

            var modelTextureData = new ModelTextureData
            {
                Width    = dimensions.Width,
                Height   = dimensions.Height,
                Normal   = normalMap.ToArray(),
                Diffuse  = diffuseMap.ToArray(),
                Specular = specularMap.ToArray(),
                Emissive = emissiveMap.ToArray(),
                Alpha    = alphaMap.ToArray()
            };

            return(modelTextureData);
        }
示例#2
0
        /// <summary>
        /// Gets the texture maps for the model
        /// </summary>
        /// <returns>The texture maps in byte arrays inside a ModelTextureData class</returns>
        public static async Task <ModelTextureData> GetModelMaps(Tex tex, XivMtrl mtrl, CustomModelColors colors = null)
        {
            // Use static values as needed.
            if (colors == null)
            {
                colors = GetCustomColors();
            }

            var shaderInfo = mtrl.GetShaderInfo();
            var mtrlMaps   = mtrl.GetAllMapInfos();

            var texMapData = await GetTexMapData(tex, mtrl);

            var dimensions = await EqualizeTextureSizes(texMapData);

            var diffuseMap  = new List <byte>();
            var normalMap   = new List <byte>();
            var specularMap = new List <byte>();
            var emissiveMap = new List <byte>();
            var alphaMap    = new List <byte>();

            var diffuseColorList  = new List <Color>();
            var specularColorList = new List <Color>();
            var emissiveColorList = new List <Color>();

            byte[] diffusePixels = null, specularPixels = null, normalPixels = null;

            if (texMapData.Normal != null)
            {
                normalPixels = texMapData.Normal.Data;
            }

            if (texMapData.Diffuse != null)
            {
                diffusePixels = texMapData.Diffuse.Data;
            }

            if (texMapData.Specular != null)
            {
                specularPixels = texMapData.Specular.Data;
            }

            if (normalPixels == null && diffusePixels == null)
            {
                // This material doesn't actually have any readable data.

                var empty = new ModelTextureData
                {
                    Width        = 0,
                    Height       = 0,
                    Normal       = new byte[0],
                    Diffuse      = new byte[0],
                    Specular     = new byte[0],
                    Emissive     = new byte[0],
                    Alpha        = new byte[0],
                    MaterialPath = mtrl.MTRLPath.Substring(mtrl.MTRLPath.LastIndexOf('/'))
                };
                return(empty);
            }

            var dataLength = normalPixels != null ? normalPixels.Length : diffusePixels.Length;

            await Task.Run(() =>
            {
                for (var i = 3; i < dataLength; i += 4)
                {
                    // Load the individual pixels into memory.
                    Color baseNormalColor   = new Color(127, 127, 255, 255);
                    Color baseDiffuseColor  = new Color(255, 255, 255, 255);
                    Color baseSpecularColor = new Color(255, 255, 255, 255);


                    if (normalPixels != null)
                    {
                        baseNormalColor = new Color(normalPixels[i - 3], normalPixels[i - 2], normalPixels[i - 1], normalPixels[i]);
                    }

                    if (diffusePixels != null)
                    {
                        baseDiffuseColor = new Color(diffusePixels[i - 3], diffusePixels[i - 2], diffusePixels[i - 1], diffusePixels[i]);
                    }

                    if (specularPixels != null)
                    {
                        baseSpecularColor = new Color(specularPixels[i - 3], specularPixels[i - 2], specularPixels[i - 1], specularPixels[i]);
                    }

                    byte colorsetValue = baseNormalColor.A;

                    // Calculate real colors from the inputs and shader.
                    Color normalColor, diffuseColor, specularColor;
                    byte opacity;
                    ComputeShaderColors(colors, shaderInfo, baseNormalColor, baseDiffuseColor, baseSpecularColor, out normalColor, out diffuseColor, out specularColor, out opacity);
                    Color alphaColor = new Color(opacity, opacity, opacity, opacity);

                    // Apply colorset if needed.  (This could really be baked into ComputeShaderColors)
                    Color emissiveColor = new Color(0, 0, 0, 0);
                    if (mtrl.ColorSetData.Count > 0)
                    {
                        var cs = texMapData.ColorSet.Data;
                        Color finalDiffuseColor, finalSpecularColor;
                        ComputeColorsetBlending(mtrl, colorsetValue, cs, diffuseColor, specularColor, out finalDiffuseColor, out finalSpecularColor, out emissiveColor);
                        diffuseColor  = finalDiffuseColor;
                        specularColor = finalSpecularColor;
                    }

                    // White out the opacity channels where appropriate.
                    diffuseColor.A  = opacity;
                    specularColor.A = 255;
                    normalColor.A   = 255;


                    diffuseMap.AddRange(BitConverter.GetBytes(diffuseColor.ToRgba()));
                    specularMap.AddRange(BitConverter.GetBytes(specularColor.ToRgba()));
                    emissiveMap.AddRange(BitConverter.GetBytes(emissiveColor.ToRgba()));
                    alphaMap.AddRange(BitConverter.GetBytes(alphaColor.ToRgba()));
                    normalMap.AddRange(BitConverter.GetBytes(normalColor.ToRgba()));
                }
            });

            var modelTextureData = new ModelTextureData
            {
                Width        = dimensions.Width,
                Height       = dimensions.Height,
                Normal       = normalMap.ToArray(),
                Diffuse      = diffuseMap.ToArray(),
                Specular     = specularMap.ToArray(),
                Emissive     = emissiveMap.ToArray(),
                Alpha        = alphaMap.ToArray(),
                MaterialPath = mtrl.MTRLPath.Substring(mtrl.MTRLPath.LastIndexOf('/'))
            };

            return(modelTextureData);
        }