コード例 #1
0
ファイル: HSDScene.cs プロジェクト: youdontown/StudioSB
        private void RefreshTextures()
        {
            if (RootJOBJ == null)
            {
                return;
            }
            Surfaces.Clear();
            tobjToSurface.Clear();
            var tobjs = GetTOBJS();
            List <HSD_Image> Process = new List <HSD_Image>();

            foreach (var tobj in tobjs)
            {
                var surface = new SBSurface();
                surface.Name = "TOBJ_" + tobjs.IndexOf(tobj);
                surface.Arrays.Add(new MipArray()
                {
                    Mipmaps = new List <byte[]>()
                    {
                        tobj.GetDecodedImageData()
                    }
                });
                surface.Width          = tobj.ImageData.Width;
                surface.Height         = tobj.ImageData.Height;
                surface.PixelFormat    = PixelFormat.Bgra;
                surface.PixelType      = PixelType.UnsignedByte;
                surface.InternalFormat = InternalFormat.Rgba;
                tobjToSurface.Add(tobj._s, surface);
                Surfaces.Add(surface);
            }
        }
コード例 #2
0
        /// <summary>
        /// Binds a surface to the shader
        /// </summary>
        /// <param name="shader"></param>
        /// <param name="ssbhScene"></param>
        /// <param name="surface"></param>
        /// <param name="surfaceInfo"></param>
        /// <param name="attributeName"></param>
        /// <param name="TextureUnit"></param>
        private void BindSurface(Shader shader, SBSceneSSBH ssbhScene, SBSurface surface, DefaultTextureName surfaceInfo, string attributeName, int TextureUnit)
        {
            if (surface != null)
            {
                if (ssbhScene.surfaceToRenderTexture.ContainsKey(surface))
                {
                    shader.SetTexture(attributeName, ssbhScene.surfaceToRenderTexture[surface], TextureUnit);
                    return;
                }
            }

            shader.SetTexture(attributeName, DefaultTextures.Instance.GetTextureByName(surfaceInfo.DefaultTexture), TextureUnit);
        }
コード例 #3
0
        private SBSurface OpenFile(string FilePath)
        {
            SBSurface Surface = null;

            if (FilePath.EndsWith(".nutexb"))
            {
                Surface = IO_NUTEXB.Open(FilePath);
            }
            if (FilePath.EndsWith(".dds"))
            {
                Surface = IO_DDS.Import(FilePath);
            }

            return(Surface);
        }
コード例 #4
0
        /// <summary>
        /// Binds the material to shader
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="shader"></param>
        public void Bind(SBScene scene, Shader shader)
        {
            var ssbhScene = (SBSceneSSBH)scene;

            BindRasterizerState();

            int TextureUnit = 0;

            foreach (var p in Properties)
            {
                if (shader.GetUniformLocation(p.Name) != -1 || shader.GetAttribLocation(p.Name) != -1)
                {
                    if (p.PropertyType == typeof(SBMatAttrib <string>))
                    {
                        var       value       = ((SBMatAttrib <string>)MatAttribs[p.Name]).AnimatedValue;
                        SBSurface surface     = ssbhScene.nameToSurface.ContainsKey(value) ? ssbhScene.nameToSurface[value] : null;
                        var       surfaceInfo = nameToDefaultTexture[p.Name];
                        BindSurface(shader, ssbhScene, surface, surfaceInfo, p.Name, TextureUnit++);
                    }
                    else
                    if (p.PropertyType == typeof(SBMatAttrib <Vector4>))
                    {
                        shader.SetVector4(p.Name, ((SBMatAttrib <Vector4>)MatAttribs[p.Name]).AnimatedValue);
                    }
                    else
                    if (p.PropertyType == typeof(SBMatAttrib <float>))
                    {
                        shader.SetFloat(p.Name, ((SBMatAttrib <float>)MatAttribs[p.Name]).AnimatedValue);
                    }
                    else
                    if (p.PropertyType == typeof(SBMatAttrib <bool>))
                    {
                        shader.SetBoolToInt(p.Name, ((SBMatAttrib <bool>)MatAttribs[p.Name]).AnimatedValue);
                    }
                    else
                    if (p.PropertyType == typeof(bool))
                    {
                        var value = p.GetValue(this); // slow
                        shader.SetBoolToInt(p.Name, (bool)value);
                    }
                }
            }

            shader.SetTexture("diffusePbrCube", DefaultTextures.Instance.diffusePbr, TextureUnit++);
            shader.SetTexture("specularPbrCube", DefaultTextures.Instance.specularPbr, TextureUnit++);
            shader.SetTexture("iblLut", DefaultTextures.Instance.iblLut, TextureUnit++);
            shader.SetTexture("uvPattern", DefaultTextures.Instance.uvPattern, TextureUnit++);
        }
コード例 #5
0
ファイル: IO_NUTEXB.cs プロジェクト: ssbucarlos/StudioSB
        public static void Export(string FileName, SBSurface surface)
        {
            using (BinaryWriter writer = new BinaryWriter(new FileStream(FileName, FileMode.Create)))
            {
                writer.Write(SwitchSwizzler.CreateBuffer(surface));

                uint ImageSize = (uint)writer.BaseStream.Position;

                foreach (var mip in surface.Arrays)
                {
                    foreach (var m in mip.Mipmaps)
                    {
                        writer.Write(m.Length);
                    }
                    for (int i = mip.Mipmaps.Count; i < 0x10; i++)
                    {
                        writer.Write(0);
                    }
                }

                writer.Write(new char[] { ' ', 'X', 'N', 'T' });
                writer.Write(surface.Name.ToCharArray());
                writer.Write(new byte[0x40 - surface.Name.Length]);
                writer.Write(surface.Width);
                writer.Write(surface.Height);
                writer.Write(surface.Depth);
                writer.Write((byte)TexFormatByInternalFormat(surface.InternalFormat)); // format
                writer.Write((byte)4);                                                 // unknown usually 4
                writer.Write((short)0);                                                // pad
                writer.Write(surface.IsCubeMap ? 9 : 4);                               // unknown usually 4 9 for cubemap
                writer.Write(surface.Arrays[0].Mipmaps.Count);
                writer.Write(0x1000);                                                  // alignment
                writer.Write(surface.Arrays.Count);                                    // array count
                writer.Write(ImageSize);

                writer.Write(new char[] { ' ', 'X', 'E', 'T' });
                writer.Write((short)1); // version major
                writer.Write((short)2); // version minor
            }
        }
コード例 #6
0
ファイル: SwitchSwizzler.cs プロジェクト: youdontown/StudioSB
        /**
         * Ported from https://github.com/KillzXGaming/Switch-Toolbox
         */
        public static byte[] GetImageData(SBSurface surface, byte[] ImageData, int ArrayLevel, int MipLevel, int MipCount, int target = 1)
        {
            uint bpp       = TextureFormatInfo.GetBPP(surface.InternalFormat);
            uint blkWidth  = TextureFormatInfo.GetBlockWidth(surface.InternalFormat);
            uint blkHeight = TextureFormatInfo.GetBlockHeight(surface.InternalFormat);
            uint blkDepth  = TextureFormatInfo.GetBlockDepth(surface.InternalFormat);

            uint blockHeight     = GetBlockHeight(DivRoundUp((uint)surface.Height, blkHeight));
            int  BlockHeightLog2 = Convert.ToString(blockHeight, 2).Length - 1;

            uint Pitch         = 0;
            uint DataAlignment = 512;
            uint TileMode      = 0;

            int linesPerBlockHeight = (1 << BlockHeightLog2) * 8;

            uint ArrayOffset = 0;

            for (int arrayLevel = 0; arrayLevel < surface.ArrayCount; arrayLevel++)
            {
                uint SurfaceSize      = 0;
                int  blockHeightShift = 0;

                List <uint> MipOffsets = new List <uint>();

                for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
                {
                    uint width  = (uint)Math.Max(1, surface.Width >> mipLevel);
                    uint height = (uint)Math.Max(1, surface.Height >> mipLevel);
                    uint depth  = (uint)Math.Max(1, surface.Depth >> mipLevel);

                    uint size = DivRoundUp(width, blkWidth) * DivRoundUp(height, blkHeight) * bpp;

                    if (Pow2RoundUp(DivRoundUp(height, blkWidth)) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }

                    //SBConsole.WriteLine(height + " " + blkWidth + " " + Pow2RoundUp(DivRoundUp(height, blkWidth)) + " " + blockHeight + " " + blockHeightShift + " " + linesPerBlockHeight + " " + BlockHeightLog2 + " " + (int)Math.Max(0, BlockHeightLog2 - blockHeightShift));

                    uint width__  = DivRoundUp(width, blkWidth);
                    uint height__ = DivRoundUp(height, blkHeight);

                    //Calculate the mip size instead
                    byte[] AlignedData = new byte[(RoundUp(SurfaceSize, DataAlignment) - SurfaceSize)];
                    SurfaceSize += (uint)AlignedData.Length;
                    MipOffsets.Add(SurfaceSize);

                    //Get the first mip offset and current one and the total image size
                    int msize = (int)((MipOffsets[0] + ImageData.Length - MipOffsets[mipLevel]) / surface.ArrayCount);

                    if (msize > ImageData.Length - (ArrayOffset + MipOffsets[mipLevel]))
                    {
                        msize = (int)(ImageData.Length - (ArrayOffset + MipOffsets[mipLevel]));
                    }

                    byte[] data_ = new byte[msize];
                    if (ArrayLevel == arrayLevel && MipLevel == mipLevel)
                    {
                        Array.Copy(ImageData, ArrayOffset + MipOffsets[mipLevel], data_, 0, msize);
                    }
                    try
                    {
                        Pitch        = RoundUp(width__ * bpp, 64);
                        SurfaceSize += Pitch * RoundUp(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);

                        if (ArrayLevel == arrayLevel && MipLevel == mipLevel)
                        {
                            //SBConsole.WriteLine($"{width} {height} {blkWidth} {blkHeight} {target} {bpp} {TileMode} {(int)Math.Max(0, BlockHeightLog2 - blockHeightShift)} {data_.Length}");
                            byte[] result = Deswizzle(width, height, depth, blkWidth, blkHeight, blkDepth, target, bpp, TileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), data_);
                            //Create a copy and use that to remove uneeded data
                            byte[] result_ = new byte[size];
                            Array.Copy(result, 0, result_, 0, size);
                            result = null;

                            return(result_);
                        }
                    }
                    catch (Exception e)
                    {
                        System.Windows.Forms.MessageBox.Show($"Failed to swizzle texture {surface.Name}!");
                        Console.WriteLine(e);

                        return(new byte[0]);
                    }
                }

                ArrayOffset += (uint)(ImageData.Length / surface.ArrayCount);
            }
            return(new byte[0]);
        }
コード例 #7
0
ファイル: SwitchSwizzler.cs プロジェクト: youdontown/StudioSB
        public static byte[] CreateBuffer(SBSurface surface, int target = 1)
        {
            List <byte> ImageData = new List <byte>();

            if (surface.Arrays.Count == 0)
            {
                return(ImageData.ToArray());
            }

            var  MipCount  = surface.Arrays[0].Mipmaps.Count;
            uint bpp       = TextureFormatInfo.GetBPP(surface.InternalFormat);
            uint blkWidth  = TextureFormatInfo.GetBlockWidth(surface.InternalFormat);
            uint blkHeight = TextureFormatInfo.GetBlockHeight(surface.InternalFormat);
            uint blkDepth  = TextureFormatInfo.GetBlockDepth(surface.InternalFormat);

            uint blockHeight     = GetBlockHeight(DivRoundUp((uint)surface.Height, blkHeight));
            uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;

            uint Pitch         = 0;
            uint DataAlignment = 512;
            uint TileMode      = 0;

            int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;

            //uint ArrayOffset = 0;
            for (int arrayLevel = 0; arrayLevel < surface.Arrays.Count; arrayLevel++)
            {
                uint SurfaceSize      = 0;
                int  blockHeightShift = 0;

                List <uint> MipOffsets = new List <uint>();

                for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
                {
                    uint width  = (uint)Math.Max(1, surface.Width >> mipLevel);
                    uint height = (uint)Math.Max(1, surface.Height >> mipLevel);
                    uint depth  = (uint)Math.Max(1, surface.Depth >> mipLevel);

                    uint size = DivRoundUp(width, blkWidth) * DivRoundUp(height, blkHeight) * bpp;

                    if (Pow2RoundUp(DivRoundUp(height, blkWidth)) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }


                    uint width__  = DivRoundUp(width, blkWidth);
                    uint height__ = DivRoundUp(height, blkHeight);

                    //Calculate the mip size instead
                    byte[] AlignedData = new byte[(RoundUp(SurfaceSize, DataAlignment) - SurfaceSize)];
                    SurfaceSize += (uint)AlignedData.Length;
                    MipOffsets.Add(SurfaceSize);

                    //Get the first mip offset and current one and the total image size
                    int msize = (int)((MipOffsets[0] + surface.Arrays[arrayLevel].Mipmaps[mipLevel].Length - MipOffsets[mipLevel]) / surface.ArrayCount);

                    //try
                    {
                        Pitch        = RoundUp(width__ * bpp, 64);
                        SurfaceSize += Pitch * RoundUp(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);

                        //Console.WriteLine($"{width} {height} {blkWidth} {blkHeight} {target} {bpp} {TileMode} {(int)Math.Max(0, BlockHeightLog2 - blockHeightShift)}");
                        var mipData = surface.Arrays[arrayLevel].Mipmaps[mipLevel];

                        /*byte[] padded = new byte[mipData.Length * 2];
                         * Array.Copy(mipData, 0, padded, 0, mipData.Length);
                         * mipData = padded;*/
                        byte[] result = Swizzle(width, height, depth, blkWidth, blkHeight, blkDepth, target, bpp, TileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), mipData);
                        //Console.WriteLine(result.Length + " " + surface.Mipmaps[mipLevel].Length);
                        ImageData.AddRange(result);
                    }

                    /*catch (Exception e)
                     * {
                     *  System.Windows.Forms.MessageBox.Show($"Failed to swizzle texture {surface.Name}!");
                     *  Console.WriteLine(e);
                     *
                     *  return new byte[0];
                     * }*/
                }

                // alignment
                if (arrayLevel != surface.Arrays.Count - 1)
                {
                    ImageData.AddRange(new byte[0x1000 - (ImageData.Count % 0x1000)]);
                }
            }
            return(ImageData.ToArray());
        }
コード例 #8
0
        public static void Open(string FilePath, SBScene Scene)
        {
            using (BinaryReader reader = new BinaryReader(new FileStream(FilePath, FileMode.Open)))
            {
                // TODO: Why are there empty streams?
                if (reader.BaseStream.Length == 0)
                {
                    return;
                }

                SBSurface surface = new SBSurface();

                reader.BaseStream.Position = reader.BaseStream.Length - 0xB0;

                int[] mipmapSizes = new int[16];
                for (int i = 0; i < mipmapSizes.Length; i++)
                {
                    mipmapSizes[i] = reader.ReadInt32();
                }

                reader.ReadChars(4); // TNX magic

                string texName = ReadTexName(reader);
                surface.Name = texName;

                surface.Width  = reader.ReadInt32();
                surface.Height = reader.ReadInt32();
                surface.Depth  = reader.ReadInt32();

                var Format = (NUTEX_FORMAT)reader.ReadByte();

                // hack
                surface.IsSRGB = Format.ToString().ToLower().Contains("srgb");

                SBConsole.WriteLine($"Loaded NUTEX: {surface.Name} Format: {Format.ToString()}");

                if (pixelFormatByNuTexFormat.ContainsKey(Format))
                {
                    surface.PixelFormat = pixelFormatByNuTexFormat[Format];
                }
                if (internalFormatByNuTexFormat.ContainsKey(Format))
                {
                    surface.InternalFormat = internalFormatByNuTexFormat[Format];
                }

                reader.ReadByte();

                ushort Padding = reader.ReadUInt16();
                reader.ReadUInt32();

                int    MipCount     = reader.ReadInt32();
                int    Alignment    = reader.ReadInt32();
                int    ArrayCount   = reader.ReadInt32();
                int    ImageSize    = reader.ReadInt32();
                char[] Magic        = reader.ReadChars(4);
                int    MajorVersion = reader.ReadInt16();
                int    MinorVersion = reader.ReadInt16();

                uint blkWidth  = (uint)blkDims[Format].X;
                uint blkHeight = (uint)blkDims[Format].Y;

                uint blockHeight     = Tools.SwitchSwizzler.GetBlockHeight(Tools.SwitchSwizzler.DivRoundUp((uint)surface.Height, blkHeight));
                uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
                uint tileMode        = 0;

                uint bpp = GetBpps(Format);

                //TODO: Read mipmaps
                reader.BaseStream.Position = 0;
                int blockHeightShift = 0;
                for (int i = 0; i < 1; i++)
                {
                    int size = mipmapSizes[i];

                    if (i == 0 && size % Alignment != 0)
                    {
                        size += Alignment - (size % Alignment);
                    }

                    byte[] deswiz  = Tools.SwitchSwizzler.Deswizzle((uint)surface.Width, (uint)surface.Height, blkWidth, blkHeight, 0, bpp, tileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), reader.ReadBytes(ImageSize));
                    byte[] trimmed = new byte[mipmapSizes[0]];
                    Array.Copy(deswiz, 0, trimmed, 0, trimmed.Length);

                    surface.Mipmaps.Add(trimmed);
                }

                Scene.Surfaces.Add(surface);
            }
        }
コード例 #9
0
ファイル: IO_NUTEXB.cs プロジェクト: ssbucarlos/StudioSB
        public static SBSurface Open(string FilePath)
        {
            using (BinaryReader reader = new BinaryReader(new FileStream(FilePath, FileMode.Open)))
            {
                // TODO: Why are there empty streams?
                if (reader.BaseStream.Length == 0)
                {
                    return(null);
                }

                SBSurface surface = new SBSurface();

                reader.BaseStream.Position = reader.BaseStream.Length - 0xB0;

                int[] mipmapSizes = new int[16];
                for (int i = 0; i < mipmapSizes.Length; i++)
                {
                    mipmapSizes[i] = reader.ReadInt32();
                }

                reader.ReadChars(4); // TNX magic

                string texName = ReadTexName(reader);
                surface.Name = texName;

                surface.Width  = reader.ReadInt32();
                surface.Height = reader.ReadInt32();
                surface.Depth  = reader.ReadInt32();

                var Format = (NUTEX_FORMAT)reader.ReadByte();

                reader.ReadByte();

                ushort Padding = reader.ReadUInt16();
                reader.ReadUInt32();

                int MipCount  = reader.ReadInt32();
                int Alignment = reader.ReadInt32();
                surface.ArrayCount = reader.ReadInt32();
                int    ImageSize    = reader.ReadInt32();
                char[] Magic        = reader.ReadChars(4);
                int    MajorVersion = reader.ReadInt16();
                int    MinorVersion = reader.ReadInt16();

                if (pixelFormatByNuTexFormat.ContainsKey(Format))
                {
                    surface.PixelFormat = pixelFormatByNuTexFormat[Format];
                }

                if (internalFormatByNuTexFormat.ContainsKey(Format))
                {
                    surface.InternalFormat = internalFormatByNuTexFormat[Format];
                }

                surface.PixelType = GetPixelType(Format);

                reader.BaseStream.Position = 0;
                byte[] ImageData = reader.ReadBytes(ImageSize);

                for (int array = 0; array < surface.ArrayCount; array++)
                {
                    MipArray arr = new MipArray();
                    for (int i = 0; i < MipCount; i++)
                    {
                        byte[] deswiz = SwitchSwizzler.GetImageData(surface, ImageData, array, i, MipCount);
                        arr.Mipmaps.Add(deswiz);
                    }
                    surface.Arrays.Add(arr);
                }

                return(surface);
            }
        }
コード例 #10
0
        public static SBSurface Import(string FileName)
        {
            SBSurface surface = new SBSurface();

            using (BinaryReaderExt reader = new BinaryReaderExt(new FileStream(FileName, FileMode.Open)))
            {
                DDS_Header header = new DDS_Header();
                header.Read(reader);

                surface.Name   = Path.GetFileNameWithoutExtension(FileName);
                surface.Width  = header.dwWidth;
                surface.Height = header.dwHeight;
                if (header.dwFlags.HasFlag(DDSD.DEPTH))
                {
                    surface.Depth = header.dwDepth;
                }
                else
                {
                    surface.Depth = 1;
                }

                if (header.ddspf.dwFourCC == 0x31545844)
                {
                    surface.InternalFormat = InternalFormat.CompressedRgbaS3tcDxt1Ext;
                }
                else
                if (header.ddspf.dwFourCC == 0x30315844)
                {
                    surface.InternalFormat = DXGItoInternal(header.DXT10Header.dxgiFormat);
                    if (surface.InternalFormat == 0)
                    {
                        System.Windows.Forms.MessageBox.Show("DDS format not supported " + header.DXT10Header.dxgiFormat);

                        return(null);
                    }
                }
                else
                {
                    if (((FourCC_DXGI)header.ddspf.dwFourCC) == FourCC_DXGI.D3DFMT_A32B32G32R32F)
                    {
                        surface.InternalFormat = InternalFormat.Rgba32f;
                        surface.PixelFormat    = PixelFormat.Rgba;
                        surface.PixelType      = PixelType.Float;
                    }
                    else
                    {
                        System.Windows.Forms.MessageBox.Show("DDS format not supported " + header.ddspf.dwFourCC.ToString("X"));
                        return(null);
                    }
                }


                // TODO: read other mips
                int w = surface.Width;
                int h = surface.Height;
                //SBConsole.WriteLine(header.dwCaps.ToString() + " " + header.dwCaps2.ToString() + " " + header.dwFlags.ToString());
                for (int array = 0; array < (header.dwCaps2.HasFlag(DDSCAPS2.CUBEMAP_ALLFACES) ? 6 : 1); array++)
                {
                    w = surface.Width;
                    h = surface.Height;
                    var mip = new MipArray();

                    for (int i = 0; i < (header.dwFlags.HasFlag(DDSD.MIPMAPCOUNT) ? header.dwMipMapCount : 1); i++)
                    {
                        var mipSize = Math.Max(1, ((w + 3) / 4)) * Math.Max(1, ((h + 3) / 4)) * (int)TextureFormatInfo.GetBPP(surface.InternalFormat);

                        if (mipSize % TextureFormatInfo.GetBPP(surface.InternalFormat) != 0)
                        {
                            mipSize += (int)(TextureFormatInfo.GetBPP(surface.InternalFormat) - (mipSize % TextureFormatInfo.GetBPP(surface.InternalFormat)));
                        }

                        var data = reader.ReadBytes(mipSize);

                        mip.Mipmaps.Add(data);
                        w /= 2;
                        h /= 2;
                    }

                    surface.Arrays.Add(mip);
                }
                if (reader.Position != reader.BaseStream.Length)
                {
                    SBConsole.WriteLine("Warning: error reading dds " + reader.Position.ToString("X"));
                }
            }



            return(surface);
        }
コード例 #11
0
        public static void Export(string fileName, SBSurface surface)
        {
            if (!internalFormatToDXGI.ContainsKey(surface.InternalFormat) && !internalFormatToD3D.ContainsKey(surface.InternalFormat))
            {
                System.Windows.Forms.MessageBox.Show("Unsupported DDS export format " + surface.InternalFormat.ToString());
                return;
            }
            var Header = new DDS_Header()
            {
                dwFlags             = (DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PIXELFORMAT | DDSD.LINEARSIZE),
                dwHeight            = surface.Height,
                dwWidth             = surface.Width,
                dwPitchOrLinearSize = GetPitchOrLinearSize(surface.InternalFormat, surface.Width),
                dwDepth             = surface.Depth,
                dwMipMapCount       = surface.Arrays[0].Mipmaps.Count,
                dwReserved1         = new uint[11],
                ddspf = new DDS_PIXELFORMAT()
                {
                },
                dwCaps  = 0,
                dwCaps2 = 0
            };

            if (surface.Arrays.Count > 0 && surface.Arrays[0].Mipmaps.Count > 1)
            {
                Header.dwFlags |= DDSD.MIPMAPCOUNT;
            }

            if (surface.IsCubeMap)
            {
                Header.dwCaps  |= DDSCAPS.TEXTURE | DDSCAPS.COMPLEX;
                Header.dwCaps2 |= DDSCAPS2.CUBEMAP_ALLFACES;
            }
            //TODO: format
            Header.ddspf.dwFlags  = DDPF.FOURCC;
            Header.ddspf.dwFourCC = 0x30315844;
            if (internalFormatToD3D.ContainsKey(surface.InternalFormat))
            {
                Header.ddspf.dwFourCC = (int)internalFormatToD3D[surface.InternalFormat];
            }

            if (internalFormatToDXGI.ContainsKey(surface.InternalFormat))
            {
                Header.DXT10Header.dxgiFormat        = internalFormatToDXGI[surface.InternalFormat];
                Header.DXT10Header.resourceDimension = D3D10_RESOURCE_DIMENSION.D3D10_RESOURCE_DIMENSION_TEXTURE2D;
                Header.DXT10Header.arraySize         = (uint)surface.Arrays.Count;
            }

            using (BinaryWriterExt writer = new BinaryWriterExt(new FileStream(fileName, FileMode.Create)))
            {
                Header.Write(writer);

                foreach (var arr in surface.Arrays)
                {
                    foreach (var mip in arr.Mipmaps)
                    {
                        writer.Write(mip);
                    }
                }
            }
        }
コード例 #12
0
        public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton)
        {
            SBAnimation anim = new SBAnimation();

            HSDRawFile f = new HSDRawFile(FileName);

            foreach (var root in f.Roots)
            {
                if (root == null || root.Data == null)
                {
                    continue;
                }
                anim.Name = root.Name;
                if (root.Data is HSD_AnimJoint joint)
                {
                    var joints = joint.BreathFirstList;

                    int nodeIndex = -1;
                    foreach (var j in joints)
                    {
                        nodeIndex++;
                        if (j.AOBJ == null || j.AOBJ.FObjDesc == null)
                        {
                            continue;
                        }

                        SBConsole.WriteLine(nodeIndex + " " + j.Flags.ToString("X8") + " " + j.AOBJ.Flags.ToString());

                        SBTransformAnimation a = new SBTransformAnimation();
                        if (nodeIndex < skeleton.Bones.Length)
                        {
                            a.Name = skeleton.Bones[nodeIndex].Name;
                        }
                        else
                        {
                            a.Name = "JOBJ_" + nodeIndex;
                        }
                        anim.TransformNodes.Add(a);

                        anim.FrameCount = Math.Max(anim.FrameCount, j.AOBJ.EndFrame);

                        foreach (var fobj in j.AOBJ.FObjDesc.List)
                        {
                            a.Tracks.Add(DecodeFOBJ(fobj.ToFOBJ()));
                        }
                    }
                }
                if (root.Data is HSD_FigaTree tree)
                {
                    anim.FrameCount = tree.FrameCount;
                    int nodeIndex = 0;
                    foreach (var node in tree.Nodes)
                    {
                        SBTransformAnimation a = new SBTransformAnimation();
                        a.Name = skeleton.Bones[nodeIndex++].Name;
                        anim.TransformNodes.Add(a);

                        foreach (var att in node.Tracks)
                        {
                            if (att.FOBJ == null)
                            {
                                continue;
                            }

                            a.Tracks.Add(DecodeFOBJ(att.FOBJ));
                        }
                    }
                }
                if (root.Data is HSD_MatAnimJoint matjoint)
                {
                    var joints = matjoint.BreathFirstList;

                    anim.FrameCount = 0;

                    int nodeIndex = -1;
                    foreach (var j in joints)
                    {
                        if (j.MaterialAnimation == null)
                        {
                            continue;
                        }

                        var matAnims = j.MaterialAnimation.List;

                        foreach (var manim in matAnims)
                        {
                            nodeIndex++;
                            var aobj = manim.AnimationObject;
                            if (aobj != null)
                            {
                                anim.FrameCount = Math.Max(anim.FrameCount, aobj.EndFrame);
                            }

                            var texanim = manim.TextureAnimation;

                            if (texanim == null)
                            {
                                continue;
                            }
                            var texAOBJ = texanim.AnimationObject;

                            if (texAOBJ == null || texAOBJ.FObjDesc == null)
                            {
                                continue;
                            }

                            anim.FrameCount = Math.Max(anim.FrameCount, texAOBJ.EndFrame);

                            //TODO: tex anim is a list
                            if (texanim != null)
                            {
                                SBTextureAnimation textureAnim = new SBTextureAnimation();
                                anim.TextureNodes.Add(textureAnim);
                                textureAnim.MeshName        = "DOBJ_" + nodeIndex;
                                textureAnim.TextureAttibute = texanim.GXTexMapID.ToString();

                                textureAnim.Keys = DecodeFOBJ(texAOBJ.FObjDesc.ToFOBJ()).Keys;

                                for (int i = 0; i < texanim.ImageCount; i++)
                                {
                                    HSD_TOBJ tobj = new HSD_TOBJ();
                                    tobj.ImageData = texanim.ImageBuffers.Array[i].Data;
                                    if (texanim.TlutCount > i)
                                    {
                                        tobj.TlutData = texanim.TlutBuffers.Array[i].Data;
                                    }
                                    var surface = new SBSurface();
                                    surface.Arrays.Add(new MipArray()
                                    {
                                        Mipmaps = new List <byte[]>()
                                        {
                                            tobj.GetDecodedImageData()
                                        }
                                    });
                                    surface.Width          = tobj.ImageData.Width;
                                    surface.Height         = tobj.ImageData.Height;
                                    surface.PixelFormat    = PixelFormat.Bgra;
                                    surface.PixelType      = PixelType.UnsignedByte;
                                    surface.InternalFormat = InternalFormat.Rgba;
                                    textureAnim.Surfaces.Add(surface);
                                }
                            }
                        }
                    }

                    SBConsole.WriteLine(nodeIndex);
                }
            }

            return(anim);
        }