Commit d72c407e authored by nadro's avatar nadro

- Fixed issue with DXT file formats in D3D9.

- Added cube maps support to PVR file loader.
- Added support for load cube maps directly via IVideoDriver::getTexture call.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5259 dfc29bdd-3216-0410-991c-e03cc46cb475
parent deacb5b9
......@@ -16,6 +16,16 @@ namespace irr
namespace video
{
//! Enumeration describing the type of ITexture.
enum E_TEXTURE_TYPE
{
//! 2D texture.
ETT_2D,
//! Cubemap texture.
ETT_CUBEMAP
};
//! Interface for software image data.
/** Image loaders create these images from files. IVideoDrivers convert
these images into their (hardware) textures.
......
......@@ -47,8 +47,9 @@ public:
//! Creates a multiple surfaces from the file eg. whole cube map.
/** \param file File handle to check.
\param type Pointer to E_TEXTURE_TYPE where a recommended type of the texture will be stored.
\return Array of pointers to newly created images. */
virtual core::array<IImage*> IImageLoader::loadImages(io::IReadFile* file) const
virtual core::array<IImage*> IImageLoader::loadImages(io::IReadFile* file, E_TEXTURE_TYPE* type) const
{
core::array<IImage*> image;
......
......@@ -92,16 +92,6 @@ enum E_TEXTURE_LOCK_MODE
ETLM_WRITE_ONLY
};
//! Enumeration describing the type of ITexture.
enum E_TEXTURE_TYPE
{
//! 2D texture.
ETT_2D,
//! Cubemap texture.
ETT_CUBEMAP
};
//! Where did the last IVideoDriver::getTexture call find this texture
enum E_TEXTURE_SOURCE
{
......
......@@ -1189,20 +1189,22 @@ namespace video
method is useful for example if you want to read a heightmap
for a terrain renderer.
\param filename Name of the file from which the images are created.
\param type Pointer to E_TEXTURE_TYPE where a recommended type of the texture will be stored.
\return The array of created images.
If you no longer need those images, you should call IImage::drop() on each of them.
See IReferenceCounted::drop() for more information. */
virtual core::array<IImage*> createImagesFromFile(const io::path& filename) = 0;
virtual core::array<IImage*> createImagesFromFile(const io::path& filename, E_TEXTURE_TYPE* type = 0) = 0;
//! Creates a software images from a file.
/** No hardware texture will be created for those images. This
method is useful for example if you want to read a heightmap
for a terrain renderer.
\param file File from which the image is created.
\param type Pointer to E_TEXTURE_TYPE where a recommended type of the texture will be stored.
\return The array of created images.
If you no longer need those images, you should call IImage::drop() on each of them.
See IReferenceCounted::drop() for more information. */
virtual core::array<IImage*> createImagesFromFile(io::IReadFile* file) = 0;
virtual core::array<IImage*> createImagesFromFile(io::IReadFile* file, E_TEXTURE_TYPE* type = 0) = 0;
//! Creates a software image from a file.
/** No hardware texture will be created for this image. This
......
......@@ -3375,6 +3375,16 @@ D3DFORMAT CD3D9Driver::getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const
return D3DFMT_R8G8B8;
case ECF_A8R8G8B8:
return D3DFMT_A8R8G8B8;
case ECF_DXT1:
return D3DFMT_DXT1;
case ECF_DXT2:
return D3DFMT_DXT2;
case ECF_DXT3:
return D3DFMT_DXT3;
case ECF_DXT4:
return D3DFMT_DXT4;
case ECF_DXT5:
return D3DFMT_DXT5;
case ECF_R16F:
return D3DFMT_R16F;
case ECF_G16R16F:
......
......@@ -264,8 +264,8 @@ void CD3D9Texture::regenerateMipMapLevels(void* data, u32 layer)
if (data)
{
u32 width = Size.Width >> layer;
u32 height = Size.Height >> layer;
u32 width = Size.Width;
u32 height = Size.Height;
u8* tmpData = static_cast<u8*>(data);
u32 dataSize = 0;
u32 level = 0;
......
// Copyright (C) 2013-2015 Patryk Nadrowski
// Copyright (C) 2013-2016 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
......@@ -13,19 +13,14 @@
namespace irr
{
namespace video
{
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderPVR::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension(filename, "pvr");
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderPVR::isALoadableFileFormat(io::IReadFile* file) const
{
if (!file)
......@@ -37,7 +32,6 @@ bool CImageLoaderPVR::isALoadableFileFormat(io::IReadFile* file) const
/*if (header.Version == 0x03525650) // TO-DO - fix endiannes
{
printf("Bad endian2\n");
fourCC[0] = os::Byteswap::byteswap(fourCC[0]);
fourCC[1] = os::Byteswap::byteswap(fourCC[1]);
fourCC[2] = os::Byteswap::byteswap(fourCC[2]);
......@@ -47,15 +41,35 @@ bool CImageLoaderPVR::isALoadableFileFormat(io::IReadFile* file) const
return (fourCC[0] == 'P' && fourCC[1] == 'V' && fourCC[2] == 'R');
}
//! creates a surface from the file
IImage* CImageLoaderPVR::loadImage(io::IReadFile* file) const
{
core::array<IImage*> imageArray = loadImages(file, 0);
const u32 imageCount = imageArray.size();
for (u32 i = 1; i < imageCount; ++i)
{
if (imageArray[i])
imageArray[i]->drop();
}
if (imageCount > 1)
imageArray.erase(1, imageCount - 1);
return (imageCount > 1) ? imageArray[0] : 0;
}
core::array<IImage*> CImageLoaderPVR::loadImages(io::IReadFile* file, E_TEXTURE_TYPE* type) const
{
// TO-DO -> use 'move' feature from C++11 standard.
SPVRHeader header;
IImage* image = 0;
core::array<IImage*> imageArray;
core::array<u8*> mipMapsDataArray;
ECOLOR_FORMAT format = ECF_UNKNOWN;
u32 dataSize = 0;
u32 mipMapsDataSize = 0;
file->seek(0);
file->read(&header, sizeof(SPVRHeader));
......@@ -93,102 +107,144 @@ IImage* CImageLoaderPVR::loadImage(io::IReadFile* file) const
}
else // Compressed texture formats
{
switch(header.PixelFormat)
switch (header.PixelFormat)
{
case 0: // PVRTC 2bpp RGB
format = ECF_PVRTC_RGB2;
break;
case 1: // PVRTC 2bpp RGBA
format = ECF_PVRTC_ARGB2;
break;
case 2: // PVRTC 4bpp RGB
format = ECF_PVRTC_RGB4;
break;
case 3: // PVRTC 4bpp RGBA
format = ECF_PVRTC_ARGB4;
break;
case 4: // PVRTC-II 2bpp
format = ECF_PVRTC2_ARGB2;
break;
case 5: // PVRTC-II 4bpp
format = ECF_PVRTC2_ARGB4;
break;
case 6: // ETC1
format = ECF_ETC1;
break;
case 7: // DXT1 / BC1
format = ECF_DXT1;
break;
case 8: // DXT2
case 9: // DXT3 / BC2
format = ECF_DXT3;
break;
case 10: // DXT4
case 11: // DXT5 / BC3
format = ECF_DXT5;
break;
case 22: // ETC2 RGB
format = ECF_ETC2_RGB;
break;
case 23: // ETC2 RGBA
format = ECF_ETC2_ARGB;
break;
default:
format = ECF_UNKNOWN;
break;
case 0: // PVRTC 2bpp RGB
format = ECF_PVRTC_RGB2;
break;
case 1: // PVRTC 2bpp RGBA
format = ECF_PVRTC_ARGB2;
break;
case 2: // PVRTC 4bpp RGB
format = ECF_PVRTC_RGB4;
break;
case 3: // PVRTC 4bpp RGBA
format = ECF_PVRTC_ARGB4;
break;
case 4: // PVRTC-II 2bpp
format = ECF_PVRTC2_ARGB2;
break;
case 5: // PVRTC-II 4bpp
format = ECF_PVRTC2_ARGB4;
break;
case 6: // ETC1
format = ECF_ETC1;
break;
case 7: // DXT1 / BC1
format = ECF_DXT1;
break;
case 8: // DXT2
case 9: // DXT3 / BC2
format = ECF_DXT3;
break;
case 10: // DXT4
case 11: // DXT5 / BC3
format = ECF_DXT5;
break;
case 22: // ETC2 RGB
format = ECF_ETC2_RGB;
break;
case 23: // ETC2 RGBA
format = ECF_ETC2_ARGB;
break;
default:
format = ECF_UNKNOWN;
break;
}
if (format != ECF_UNKNOWN)
{
// 3D textures, texture arrays, cube maps textures aren't currently supported
if (header.Depth < 2 && header.NumSurfaces < 2 && header.NumFaces < 2)
imageArray.set_used(1);
E_TEXTURE_TYPE tmpType = ETT_2D;
// check for texture type
if (header.NumFaces == 6) // cube map
{
dataSize = IImage::getDataSizeFromFormat(format, header.Width, header.Height);
imageArray.set_used(6);
tmpType = ETT_CUBEMAP;
u8* data = new u8[dataSize];
file->read(data, dataSize);
imageArray.reallocate(6);
}
else if (header.Depth > 1) // 3d texture
{
// TO-DO
}
else if (header.NumSurfaces > 1) // texture array
{
// To-DO
}
image = new CImage(format, core::dimension2d<u32>(header.Width, header.Height), data, true, true);
if (type)
*type = tmpType;
if (header.MipMapCount > 1)
{
u32 tmpWidth = header.Width;
u32 tmpHeight = header.Height;
// prepare mipmaps data
do
dataSize = 0;
for (u32 i = 1; i < header.MipMapCount; ++i)
{
u32 tmpWidth = header.Width >> i;
u32 tmpHeight = header.Height >> i;
dataSize += IImage::getDataSizeFromFormat(format, tmpWidth, tmpHeight);
}
if (header.MipMapCount > 1)
{
for (u32 j = 0; j < imageArray.size(); ++j)
mipMapsDataArray.push_back(new u8[dataSize]);
}
// read texture
dataSize = 0;
long offset = 0;
for (u32 i = 0; i < header.MipMapCount; ++i)
{
if (i == 0)
{
for (u32 j = 0; j < imageArray.size(); ++j)
{
if (tmpWidth > 1)
tmpWidth >>= 1;
dataSize = IImage::getDataSizeFromFormat(format, header.Width, header.Height);
if (tmpHeight > 1)
tmpHeight >>= 1;
u8* data = new u8[dataSize];
file->read(data, dataSize);
mipMapsDataSize += IImage::getDataSizeFromFormat(format, tmpWidth, tmpHeight);
imageArray[j] = new CImage(format, core::dimension2d<u32>(header.Width, header.Height), data, true, true);
}
while (tmpWidth != 1 || tmpHeight != 1);
}
else
{
u32 tmpWidth = header.Width >> i;
u32 tmpHeight = header.Height >> i;
u8* mipMapsData = new u8[mipMapsDataSize];
file->read(mipMapsData, mipMapsDataSize);
dataSize = IImage::getDataSizeFromFormat(format, tmpWidth, tmpHeight);
image->setMipMapsData(mipMapsData, true, true);
for (u32 j = 0; j < imageArray.size(); ++j)
file->read(mipMapsDataArray[j] + offset, dataSize);
offset += dataSize;
}
}
// assign mipmaps data
for (u32 i = 0; i < mipMapsDataArray.size(); ++i)
imageArray[i]->setMipMapsData(mipMapsDataArray[i], true, true);
}
}
return image;
return imageArray;
}
//! creates a loader which is able to load pvr images
IImageLoader* createImageLoaderPVR()
{
return new CImageLoaderPVR();
}
} // end namespace video
} // end namespace irr
}
}
#endif
// Copyright (C) 2013-2015 Patryk Nadrowski
// Copyright (C) 2013-2016 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
......@@ -16,10 +16,8 @@ namespace irr
namespace video
{
// byte-align structures
#include "irrpack.h"
/* structures */
struct SPVRHeader
{
u32 Version;
......@@ -36,29 +34,22 @@ struct SPVRHeader
u32 MetDataSize;
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
/*!
Surface Loader for PVR images
*/
class CImageLoaderPVR : public IImageLoader
{
public:
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! returns true if the file maybe is able to be loaded by this class
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const;
virtual core::array<IImage*> loadImages(io::IReadFile* file, E_TEXTURE_TYPE* type) const;
};
} // end namespace video
} // end namespace irr
}
}
#endif // compiled with PVR loader
#endif
#endif
......@@ -493,7 +493,7 @@ ITexture* CNullDriver::addTextureCubemap(const io::path& name, IImage* imagePosX
ITexture* t = 0;
core::array<IImage*> imageArray(1);
core::array<IImage*> imageArray(6);
imageArray.push_back(imagePosX);
imageArray.push_back(imageNegX);
imageArray.push_back(imagePosY);
......@@ -614,20 +614,37 @@ ITexture* CNullDriver::getTexture(io::IReadFile* file)
video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const io::path& hashName )
{
ITexture* texture = 0;
IImage* image = createImageFromFile(file);
if (image)
{
core::array<IImage*> imageArray(1);
imageArray.push_back(image);
E_TEXTURE_TYPE type = ETT_2D;
if (checkImage(imageArray))
core::array<IImage*> imageArray = createImagesFromFile(file, &type);
if (checkImage(imageArray))
{
switch (type)
{
texture = createDeviceDependentTexture(hashName.size() ? hashName : file->getFileName(), image);
case ETT_2D:
texture = createDeviceDependentTexture(hashName.size() ? hashName : file->getFileName(), imageArray[0]);
break;
case ETT_CUBEMAP:
if (imageArray.size() >= 6 && imageArray[0] && imageArray[1] && imageArray[2] && imageArray[3] && imageArray[4] && imageArray[5])
{
texture = createDeviceDependentTextureCubemap(hashName.size() ? hashName : file->getFileName(), imageArray);
}
break;
default:
_IRR_DEBUG_BREAK_IF(true);
break;
}
os::Printer::log("Loaded texture", file->getFileName());
image->drop();
if (texture)
os::Printer::log("Loaded texture", file->getFileName());
}
for (u32 i = 0; i < imageArray.size(); ++i)
{
if (imageArray[i])
imageArray[i]->drop();
}
return texture;
......@@ -1481,7 +1498,7 @@ bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const
return (TextureCreationFlags & flag)!=0;
}
core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename)
core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename, E_TEXTURE_TYPE* type)
{
// TO-DO -> use 'move' feature from C++11 standard.
......@@ -1493,7 +1510,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename)
if (file)
{
imageArray = createImagesFromFile(file);
imageArray = createImagesFromFile(file, type);
file->drop();
}
else
......@@ -1503,7 +1520,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename)
return imageArray;
}
core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file)
core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file, E_TEXTURE_TYPE* type)
{
// TO-DO -> use 'move' feature from C++11 standard.
......@@ -1520,7 +1537,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file)
{
// reset file position which might have changed due to previous loadImage calls
file->seek(0);
imageArray = SurfaceLoader[i]->loadImages(file);
imageArray = SurfaceLoader[i]->loadImages(file, type);
if (imageArray.size() == 0)
{
......@@ -1544,7 +1561,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file)
if (SurfaceLoader[i]->isALoadableFileFormat(file))
{
file->seek(0);
imageArray = SurfaceLoader[i]->loadImages(file);
imageArray = SurfaceLoader[i]->loadImages(file, type);
if (imageArray.size() == 0)
{
......
......@@ -341,9 +341,9 @@ namespace video
//! Returns if a texture creation flag is enabled or disabled.
virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const _IRR_OVERRIDE_;
virtual core::array<IImage*> createImagesFromFile(const io::path& filename) _IRR_OVERRIDE_;
virtual core::array<IImage*> createImagesFromFile(const io::path& filename, E_TEXTURE_TYPE* type = 0) _IRR_OVERRIDE_;
virtual core::array<IImage*> createImagesFromFile(io::IReadFile* file) _IRR_OVERRIDE_;
virtual core::array<IImage*> createImagesFromFile(io::IReadFile* file, E_TEXTURE_TYPE* type = 0) _IRR_OVERRIDE_;
//! Creates a software image from a byte array.
/** \param useForeignMemory: If true, the image will use the data pointer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment