Exemple #1
0
        //new 3d-map texture
        private static Texture3D GenerateNewTexture3D(LoadSurfaceFormat loadSurfaceFormat, FourCC compressionFormat, GraphicsDevice device, int width, int height, int depth, bool hasMipMaps, uint pixelFlags, int rgbBitCount)
        {
            SurfaceFormat expectedFormat = SurfaceFormatFromLoadFormat(loadSurfaceFormat, compressionFormat, pixelFlags, rgbBitCount);

            Texture3D texture = new Texture3D(device, width, height, depth, hasMipMaps, expectedFormat);

            if (texture.Format != expectedFormat)
            {
                throw new InvalidDataException($"Can't generate a {expectedFormat} surface.");
            }

            return(texture);
        }
Exemple #2
0
        //new cube-map texture
        private static TextureCube GenerateNewCubeTexture(LoadSurfaceFormat loadSurfaceFormat, FourCC compressionFormat, GraphicsDevice device, int width, uint pixelFlags, int rgbBitCount)
        {
            SurfaceFormat expectedFormat = SurfaceFormatFromLoadFormat(loadSurfaceFormat, compressionFormat, pixelFlags, rgbBitCount);

            TextureCube texture = new TextureCube(device, width, true, expectedFormat); //hasMipMaps

            if (texture.Format != expectedFormat)
            {
                throw new InvalidDataException($"Can't generate a {expectedFormat} surface.");
            }

            return(texture);
        }
Exemple #3
0
        //new 2d-map texture
        private static Texture2D GenerateNewTexture2D(LoadSurfaceFormat loadSurfaceFormat, FourCC compressionFormat, GraphicsDevice device, int width, int height, bool hasMipMaps, uint pixelFlags, int rgbBitCount)
        {
            SurfaceFormat expectedFormat = SurfaceFormatFromLoadFormat(loadSurfaceFormat, compressionFormat, pixelFlags, rgbBitCount);

            Texture2D texture = new Texture2D(device, width, height, hasMipMaps, expectedFormat);

            texture.Tag = new Formats.Msts.Models.AceInfo()
            {
                AlphaBits = XNATextureNumAlphaBits(texture)
            };

            if (texture.Format != expectedFormat)
            {
                throw new InvalidDataException($"Can't generate a {expectedFormat} surface.");
            }

            return(texture);
        }
        //new 3d-map texture
        private static Texture3D GenerateNewTexture3D(LoadSurfaceFormat loadSurfaceFormat, FourCC compressionFormat, GraphicsDevice device, int width, int height, int depth, bool hasMipMaps, uint pixelFlags, int rgbBitCount)
        {
            SurfaceFormat surfaceFormat = SurfaceFormatFromLoadFormat(loadSurfaceFormat, compressionFormat, pixelFlags, rgbBitCount);

            Texture3D tx = new Texture3D(device, width, height, depth, hasMipMaps, surfaceFormat);

            if (tx.Format != surfaceFormat)
            {
                throw new Exception("Can't generate a " + surfaceFormat.ToString() + " surface.");
            }

            return tx;
        }
        //try to evaluate the xna compatible surface for the present data
        private static SurfaceFormat SurfaceFormatFromLoadFormat(LoadSurfaceFormat loadSurfaceFormat, FourCC compressionFormat, uint pixelFlags, int rgbBitCount)
        {
            if (loadSurfaceFormat == LoadSurfaceFormat.Unknown)
            {
                switch (compressionFormat)
                {
                    case FourCC.D3DFMT_DXT1:
                        return SurfaceFormat.Dxt1;
                    case FourCC.D3DFMT_DXT3:
                        return SurfaceFormat.Dxt3;
                    case FourCC.D3DFMT_DXT5:
                        return SurfaceFormat.Dxt5;
                    case 0:
                        if (rgbBitCount == 8)
                        {
                            return SurfaceFormat.Alpha8;
                        }
                        if (rgbBitCount == 16)
                        {
                            if (HasAlphaTest(pixelFlags))
                            {
                                return SurfaceFormat.Bgr565;
                            }
                            else
                            {
                                return SurfaceFormat.Bgra4444;
                            }
                        }
                        if (rgbBitCount == 32 || rgbBitCount == 24)
                        {
                            return SurfaceFormat.Color;
                        }
                        break;
                    default:
                        throw new Exception("Unsuported format");
                }
            }
            else
            {
                switch (loadSurfaceFormat)
                {
                    case LoadSurfaceFormat.Alpha8:
                        return SurfaceFormat.Alpha8;
                    case LoadSurfaceFormat.Bgr565:
                        return SurfaceFormat.Bgr565;
                    case LoadSurfaceFormat.Bgra4444:
                        return SurfaceFormat.Bgra4444;
                    case LoadSurfaceFormat.Bgra5551:
                        return SurfaceFormat.Bgra5551;
                    case LoadSurfaceFormat.A8R8G8B8:
                        return SurfaceFormat.Color;
                    case LoadSurfaceFormat.Dxt1:
                        return SurfaceFormat.Dxt1;
                    case LoadSurfaceFormat.Dxt3:
                        return SurfaceFormat.Dxt3;
                    case LoadSurfaceFormat.Dxt5:
                        return SurfaceFormat.Dxt5;
                    //Updated at load time to X8R8B8B8
                    case LoadSurfaceFormat.R8G8B8:
                        return SurfaceFormat.Color;
                    case LoadSurfaceFormat.X8B8G8R8:
                        return SurfaceFormat.Color;
                    case LoadSurfaceFormat.X8R8G8B8:
                        return SurfaceFormat.Color;
                    case LoadSurfaceFormat.A8B8G8R8:
                        return SurfaceFormat.Color;
                    case LoadSurfaceFormat.R32F:
                        return SurfaceFormat.Single;
                    case LoadSurfaceFormat.A32B32G32R32F:
                        return SurfaceFormat.Vector4;
                    case LoadSurfaceFormat.G32R32F:
                        return SurfaceFormat.Vector2;
                    case LoadSurfaceFormat.R16F:
                        return SurfaceFormat.HalfSingle;
                    case LoadSurfaceFormat.G16R16F:
                        return SurfaceFormat.HalfVector2;
                    case LoadSurfaceFormat.A16B16G16R16F:
                        return SurfaceFormat.HalfVector4;
                    case LoadSurfaceFormat.CxV8U8:
                        return SurfaceFormat.NormalizedByte2;
                    case LoadSurfaceFormat.Q8W8V8U8:
                        return SurfaceFormat.NormalizedByte4;
                    case LoadSurfaceFormat.G16R16:
                        return SurfaceFormat.Rg32;
                    case LoadSurfaceFormat.A2B10G10R10:
                        return SurfaceFormat.Rgba1010102;
                    case LoadSurfaceFormat.A16B16G16R16:
                        return SurfaceFormat.Rgba64;
                    default:
                        throw new Exception(loadSurfaceFormat.ToString() + " is an unsuported format");
                }
            }

            throw new Exception("Unsuported format");
        }
        //Get the byte data from a mip-map level.
        private static void GetMipMaps(int offsetInStream, int map, bool hasMipMaps, int width, int height, bool isCompressed, FourCC compressionFormat, int rgbBitCount, bool partOfCubeMap, BinaryReader reader, LoadSurfaceFormat loadSurfaceFormat, ref byte[] data, out int numBytes)
        {
            int seek = 128 + offsetInStream;

            for (int i = 0; i < map; i++)
            {
                seek += MipMapSizeInBytes(i, width, height, isCompressed, compressionFormat, rgbBitCount);
            }

            reader.BaseStream.Seek(seek, SeekOrigin.Begin);

            numBytes = MipMapSizeInBytes(map, width, height, isCompressed, compressionFormat, rgbBitCount);

            if (isCompressed == false && rgbBitCount == 24)
            {
                numBytes += (numBytes / 3);
            }

            if (data == null || data.Length < numBytes)
            {
                data = new byte[numBytes];
            }

            if (isCompressed == false && loadSurfaceFormat == LoadSurfaceFormat.R8G8B8)
            {
                for (int i = 0; i < numBytes; i += 4)
                {
                    data[i] = reader.ReadByte();
                    data[i + 1] = reader.ReadByte();
                    data[i + 2] = reader.ReadByte();
                    data[i + 3] = 255;
                }
            }
            else
            {
                reader.Read(data, 0, numBytes);
            }

            if (loadSurfaceFormat == LoadSurfaceFormat.X8R8G8B8 || loadSurfaceFormat == LoadSurfaceFormat.X8B8G8R8)
            {
                for (int i = 0; i < numBytes; i += 4)
                {
                    data[i + 3] = 255;
                }
            }

            if (loadSurfaceFormat == LoadSurfaceFormat.A8R8G8B8 ||
                loadSurfaceFormat == LoadSurfaceFormat.X8R8G8B8 ||
                loadSurfaceFormat == LoadSurfaceFormat.R8G8B8)
            {
                int bytesPerPixel = (rgbBitCount == 32 || rgbBitCount == 24) ? 4 : 3;

                byte g, b;
                if (bytesPerPixel == 3)
                {
                    for (int i = 0; i < numBytes - 2; i += 3)
                    {
                        g = data[i];
                        b = data[i + 2];
                        data[i] = b;
                        data[i + 2] = g;
                    }
                }
                else
                {
                    for (int i = 0; i < numBytes - 3; i += 4)
                    {
                        g = data[i];
                        b = data[i + 2];
                        data[i] = b;
                        data[i + 2] = g;
                    }
                }
            }
        }
Exemple #7
0
        //loads the data from a stream in to a texture object.
        private static void InternalDDSFromStream(Stream stream, GraphicsDevice device, int streamOffset, bool loadMipMap, out Texture texture)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream), "Can't read from a null stream");
            }

            using (BinaryReader reader = new BinaryReader(stream))
            {
                if (streamOffset > reader.BaseStream.Length)
                {
                    throw new Exception("The stream you offered is smaller then the offset you are proposing for it.");
                }

                reader.BaseStream.Seek(streamOffset, SeekOrigin.Begin);

                //First element of a dds file is a "magic-number" a system to identify that the file is a dds if translated as asci chars the first 4 charachters should be 'DDS '
                if (!(reader.ReadUInt32() == DDS_MAGIC))
                {
                    throw new InvalidDataException("Can't open non DDS data.");
                }

                reader.BaseStream.Position += 8;

                //size in pixels for the texture.
                int height = reader.ReadInt32();
                int width  = reader.ReadInt32();

                reader.BaseStream.Position += 4;

                //depth
                int depth = reader.ReadInt32();

                //number of mip-maps.
                int numMips = reader.ReadInt32();

                reader.BaseStream.Position += 4 * 12;

                //pixel format flags
                uint pixelFlags = reader.ReadUInt32();

                // (FOURCC code)
                uint pixelFourCC = reader.ReadUInt32();

                //color bit depth
                int rgbBitCount = reader.ReadInt32();

                //mask for red.
                uint rBitMask = reader.ReadUInt32();

                //mask for green.
                uint gBitMask = reader.ReadUInt32();

                //mask for blue.
                uint bBitMask = reader.ReadUInt32();


                //mask for alpha.
                uint aBitMask = reader.ReadUInt32();

                //reader.BaseStream.Position += 16;

                //texture + mip-map flags.
                int ddsCaps1 = reader.ReadInt32();

                //extra info flags.
                int ddsCaps2 = reader.ReadInt32();
                //ddsCaps3
                //reader.ReadInt32();
                //ddsCaps4
                //reader.ReadInt32();

                //reader.ReadInt32();

                reader.BaseStream.Position += 12;

                bool isCubeMap       = IsCubemapTest(ddsCaps1, ddsCaps2);
                bool isVolumeTexture = IsVolumeTextureTest(ddsCaps2);

                FourCC compressionFormat = GetCompressionFormat(pixelFlags, pixelFourCC);

                if (compressionFormat == FourCC.DX10)
                {
                    throw new NotImplementedException("The Dxt 10 header reader is not implemented");
                }

                LoadSurfaceFormat loadSurfaceFormat = GetLoadSurfaceFormat(pixelFlags, pixelFourCC, rgbBitCount, rBitMask, gBitMask, bBitMask, aBitMask);

                bool isCompressed  = IsCompressedTest(pixelFlags);
                bool hasMipMaps    = CheckFullMipChain(width, height, numMips);
                bool hasAnyMipmaps = numMips > 0;
                hasMipMaps &= loadMipMap;

                if (isCubeMap)
                {
                    TextureCube tex = GenerateNewCubeTexture(loadSurfaceFormat, compressionFormat, device, width, pixelFlags, rgbBitCount);

                    int byteAcumulator = 0;

                    if (numMips == 0)
                    {
                        numMips = 1;
                    }

                    if (!hasMipMaps)
                    {
                        for (int j = 0; j < numMips; j++)
                        {
                            byteAcumulator += MipMapSizeInBytes(j, width, height, isCompressed, compressionFormat, rgbBitCount);
                        }
                    }

                    for (int j = 0; j < numMips; j++)
                    {
                        byte[] localMipData = mipData;
                        GetMipMaps(streamOffset, j, width, height, isCompressed, compressionFormat, rgbBitCount, reader, loadSurfaceFormat, ref localMipData, out int numBytes);
                        mipData = localMipData;

                        if (hasMipMaps)
                        {
                            byteAcumulator += numBytes;
                        }

                        if (j == 0 || hasMipMaps)
                        {
                            tex.SetData(CubeMapFace.PositiveX, j, null, localMipData, 0, numBytes);
                        }
                        else
                        {
                            break;
                        }
                    }

                    for (int j = 0; j < numMips; j++)
                    {
                        byte[] localMipData = mipData;
                        GetMipMaps(byteAcumulator + streamOffset, j, width, height, isCompressed, compressionFormat, rgbBitCount, reader, loadSurfaceFormat, ref localMipData, out int numBytes);
                        mipData = localMipData;

                        if (j == 0 || hasMipMaps)
                        {
                            tex.SetData(CubeMapFace.NegativeX, j, null, localMipData, 0, numBytes);
                        }
                        else
                        {
                            break;
                        }
                    }

                    for (int j = 0; j < numMips; j++)
                    {
                        byte[] localMipData = mipData;
                        GetMipMaps((byteAcumulator * 2) + streamOffset, j, width, height, isCompressed, compressionFormat, rgbBitCount, reader, loadSurfaceFormat, ref localMipData, out int numBytes);
                        mipData = localMipData;

                        if (j == 0 || hasMipMaps)
                        {
                            tex.SetData(CubeMapFace.PositiveY, j, null, localMipData, 0, numBytes);
                        }
                        else
                        {
                            break;
                        }
                    }

                    for (int j = 0; j < numMips; j++)
                    {
                        byte[] localMipData = mipData;
                        GetMipMaps((byteAcumulator * 3) + streamOffset, j, width, height, isCompressed, compressionFormat, rgbBitCount, reader, loadSurfaceFormat, ref localMipData, out int numBytes);
                        mipData = localMipData;

                        if (j == 0 || hasMipMaps)
                        {
                            tex.SetData(CubeMapFace.NegativeY, j, null, localMipData, 0, numBytes);
                        }
                        else
                        {
                            break;
                        }
                    }

                    for (int j = 0; j < numMips; j++)
                    {
                        byte[] localMipData = mipData;
                        GetMipMaps((byteAcumulator * 4) + streamOffset, j, width, height, isCompressed, compressionFormat, rgbBitCount, reader, loadSurfaceFormat, ref localMipData, out int numBytes);
                        mipData = localMipData;

                        if (j == 0 || hasMipMaps)
                        {
                            tex.SetData(CubeMapFace.PositiveZ, j, null, localMipData, 0, numBytes);
                        }
                        else
                        {
                            break;
                        }
                    }

                    for (int j = 0; j < numMips; j++)
                    {
                        byte[] localMipData = mipData;
                        GetMipMaps((byteAcumulator * 5) + streamOffset, j, width, height, isCompressed, compressionFormat, rgbBitCount, reader, loadSurfaceFormat, ref localMipData, out int numBytes);
                        mipData = localMipData;

                        if (j == 0 || hasMipMaps)
                        {
                            tex.SetData(CubeMapFace.NegativeZ, j, null, localMipData, 0, numBytes);
                        }
                        else
                        {
                            break;
                        }
                    }

                    texture = tex;
                }
                else if (isVolumeTexture)
                {
                    Texture3D tex = GenerateNewTexture3D(loadSurfaceFormat, compressionFormat, device, width, height, depth, hasMipMaps, pixelFlags, rgbBitCount);

                    int localStreamOffset = streamOffset;
                    for (int i = 0; i < tex.LevelCount; i++)
                    {
                        int localWidth  = MipMapSize(i, width);
                        int localHeight = MipMapSize(i, height);
                        int localDepth  = MipMapSize(i, depth);
                        for (int j = 0; j < localDepth; j++)
                        {
                            byte[] localMipData = mipData;
                            GetMipMaps(localStreamOffset, 0, localWidth, localHeight, isCompressed, compressionFormat, rgbBitCount, reader, loadSurfaceFormat, ref localMipData, out int numBytes);
                            localStreamOffset += numBytes;
                            mipData            = localMipData;

                            tex.SetData(i, 0, 0, localWidth, localHeight, j, j + 1, localMipData, 0, numBytes);
                        }
                    }

                    texture = tex;
                }
                else
                {
                    Texture2D tex = GenerateNewTexture2D(loadSurfaceFormat, compressionFormat, device, width, height, hasMipMaps, pixelFlags, rgbBitCount);

                    for (int i = 0; i < tex.LevelCount; i++)
                    {
                        byte[] localMipData = mipData;
                        GetMipMaps(streamOffset, i, width, height, isCompressed, compressionFormat, rgbBitCount, reader, loadSurfaceFormat, ref localMipData, out int numBytes);
                        mipData = localMipData;

                        tex.SetData(i, null, localMipData, 0, numBytes);
                    }

                    texture = tex;
                }
            }
        }
Exemple #8
0
        //try to evaluate the xna compatible surface for the present data
        private static SurfaceFormat SurfaceFormatFromLoadFormat(LoadSurfaceFormat loadSurfaceFormat, FourCC compressionFormat, uint pixelFlags, int rgbBitCount)
        {
            switch (loadSurfaceFormat)
            {
            case LoadSurfaceFormat.Alpha8: return(SurfaceFormat.Alpha8);

            case LoadSurfaceFormat.Bgr565: return(SurfaceFormat.Bgr565);

            case LoadSurfaceFormat.Bgra4444: return(SurfaceFormat.Bgra4444);

            case LoadSurfaceFormat.Bgra5551: return(SurfaceFormat.Bgra5551);

            case LoadSurfaceFormat.A8R8G8B8: return(SurfaceFormat.Color);

            case LoadSurfaceFormat.Dxt1: return(SurfaceFormat.Dxt1);

            case LoadSurfaceFormat.Dxt3: return(SurfaceFormat.Dxt3);

            case LoadSurfaceFormat.Dxt5: return(SurfaceFormat.Dxt5);

            case LoadSurfaceFormat.R8G8B8: return(SurfaceFormat.Color);   //Updated at load time to X8R8B8B8

            case LoadSurfaceFormat.X8B8G8R8: return(SurfaceFormat.Color);

            case LoadSurfaceFormat.X8R8G8B8: return(SurfaceFormat.Color);

            case LoadSurfaceFormat.A8B8G8R8: return(SurfaceFormat.Color);

            case LoadSurfaceFormat.R32F: return(SurfaceFormat.Single);

            case LoadSurfaceFormat.A32B32G32R32F: return(SurfaceFormat.Vector4);

            case LoadSurfaceFormat.G32R32F: return(SurfaceFormat.Vector2);

            case LoadSurfaceFormat.R16F: return(SurfaceFormat.HalfSingle);

            case LoadSurfaceFormat.G16R16F: return(SurfaceFormat.HalfVector2);

            case LoadSurfaceFormat.A16B16G16R16F: return(SurfaceFormat.HalfVector4);

            case LoadSurfaceFormat.CxV8U8: return(SurfaceFormat.NormalizedByte2);

            case LoadSurfaceFormat.Q8W8V8U8: return(SurfaceFormat.NormalizedByte4);

            case LoadSurfaceFormat.G16R16: return(SurfaceFormat.Rg32);

            case LoadSurfaceFormat.A2B10G10R10: return(SurfaceFormat.Rgba1010102);

            case LoadSurfaceFormat.A16B16G16R16: return(SurfaceFormat.Rgba64);

            case LoadSurfaceFormat.Unknown:
                switch (compressionFormat)
                {
                case FourCC.D3DFMT_DXT1: return(SurfaceFormat.Dxt1);

                case FourCC.D3DFMT_DXT3: return(SurfaceFormat.Dxt3);

                case FourCC.D3DFMT_DXT5: return(SurfaceFormat.Dxt5);

                case 0:
                    switch (rgbBitCount)
                    {
                    case 8: return(SurfaceFormat.Alpha8);

                    case 16: return(HasAlphaTest(pixelFlags) ? SurfaceFormat.Bgr565 : SurfaceFormat.Bgra4444);

                    case 24:
                    case 32: return(SurfaceFormat.Color);
                    }
                    break;

                default:
                    throw new InvalidDataException("Unsupported format");
                }
                ;
                break;

            default:
                throw new InvalidDataException(loadSurfaceFormat.ToString() + " is an unsuported format");
            }

            throw new InvalidDataException("Unsupported format");
        }
Exemple #9
0
        //Get the byte data from a mip-map level.
        private static void GetMipMaps(int offsetInStream, int map, int width, int height, bool isCompressed, FourCC compressionFormat, int rgbBitCount, BinaryReader reader, LoadSurfaceFormat loadSurfaceFormat, ref byte[] data, out int numBytes)
        {
            int seek = 128 + offsetInStream;

            for (int i = 0; i < map; i++)
            {
                seek += MipMapSizeInBytes(i, width, height, isCompressed, compressionFormat, rgbBitCount);
            }

            reader.BaseStream.Seek(seek, SeekOrigin.Begin);

            numBytes = MipMapSizeInBytes(map, width, height, isCompressed, compressionFormat, rgbBitCount);

            if (data == null || data.Length < numBytes)
            {
                data = new byte[numBytes];
            }

            if (!isCompressed && rgbBitCount == 24)
            {
                numBytes += (numBytes / 3);
            }
            if (!isCompressed && loadSurfaceFormat == LoadSurfaceFormat.R8G8B8)
            {
                for (int i = 0; i < numBytes; i += 4)
                {
                    data[i]     = reader.ReadByte();
                    data[i + 1] = reader.ReadByte();
                    data[i + 2] = reader.ReadByte();
                    data[i + 3] = 255;
                }
            }
            else
            {
                reader.Read(data, 0, numBytes);
            }

            if (loadSurfaceFormat == LoadSurfaceFormat.X8R8G8B8 || loadSurfaceFormat == LoadSurfaceFormat.X8B8G8R8)
            {
                for (int i = 0; i < numBytes; i += 4)
                {
                    data[i + 3] = 255;
                }
            }

            if (loadSurfaceFormat == LoadSurfaceFormat.A8R8G8B8 ||
                loadSurfaceFormat == LoadSurfaceFormat.X8R8G8B8 ||
                loadSurfaceFormat == LoadSurfaceFormat.R8G8B8)
            {
                int bytesPerPixel = (rgbBitCount == 32 || rgbBitCount == 24) ? 4 : 3;

                byte g, b;
                if (bytesPerPixel == 3)
                {
                    for (int i = 0; i < numBytes - 2; i += 3)
                    {
                        g           = data[i];
                        b           = data[i + 2];
                        data[i]     = b;
                        data[i + 2] = g;
                    }
                }
                else
                {
                    for (int i = 0; i < numBytes - 3; i += 4)
                    {
                        g           = data[i];
                        b           = data[i + 2];
                        data[i]     = b;
                        data[i + 2] = g;
                    }
                }
            }
        }