diff --git a/include/IrrCompileConfig.h b/include/IrrCompileConfig.h index bcd694ae..f81b0b42 100644 --- a/include/IrrCompileConfig.h +++ b/include/IrrCompileConfig.h @@ -279,6 +279,8 @@ B3D, MS3D or X meshes */ #define _IRR_COMPILE_WITH_PSD_LOADER_ //! Define _IRR_COMPILE_WITH_TGA_LOADER_ if you want to load .tga files #define _IRR_COMPILE_WITH_TGA_LOADER_ +//! Define _IRR_COMPILE_WITH_WAL_LOADER_ if you want to load .wal files +#define _IRR_COMPILE_WITH_WAL_LOADER_ //! Define _IRR_COMPILE_WITH_BMP_WRITER_ if you want to write .bmp files #define _IRR_COMPILE_WITH_BMP_WRITER_ diff --git a/source/Irrlicht/CImageLoaderWAL.cpp b/source/Irrlicht/CImageLoaderWAL.cpp new file mode 100644 index 00000000..3a0c2933 --- /dev/null +++ b/source/Irrlicht/CImageLoaderWAL.cpp @@ -0,0 +1,136 @@ +/* + CImageLoaderWAL by Murphy McCauley (December 2004) + An Irrlicht image loader for Quake engine WAL textures + + See the header file for additional information including use and distribution rights. +*/ + +#include "CImageLoaderWAL.h" +#include "CColorConverter.h" +#include "CImage.h" +#include "os.h" +#include "dimension2d.h" +#include "IVideoDriver.h" +#include "IFileSystem.h" +#include "IReadFile.h" +#include "irrString.h" + +namespace irr +{ +namespace video +{ + +// May or may not be fully implemented +#define TRY_LOADING_PALETTE_FROM_FILE 0 + +// Default palette for Q2 WALs. + +s32 CImageLoaderWAL::DefaultPaletteQ2[256] = { +0x000000L,0x0F0F0FL,0x1F1F1FL,0x2F2F2FL,0x3F3F3FL,0x4B4B4BL,0x5B5B5BL,0x6B6B6BL,0x7B7B7BL,0x8B8B8BL,0x9B9B9BL, +0xABABABL,0xBBBBBBL,0xCBCBCBL,0xDBDBDBL,0xEBEBEBL,0x634B23L,0x5B431FL,0x533F1FL,0x4F3B1BL,0x47371BL,0x3F2F17L, +0x3B2B17L,0x332713L,0x2F2313L,0x2B1F13L,0x271B0FL,0x23170FL,0x1B130BL,0x170F0BL,0x130F07L,0x0F0B07L,0x5F5F6FL, +0x5B5B67L,0x5B535FL,0x574F5BL,0x534B53L,0x4F474BL,0x473F43L,0x3F3B3BL,0x3B3737L,0x332F2FL,0x2F2B2BL,0x272727L, +0x232323L,0x1B1B1BL,0x171717L,0x131313L,0x8F7753L,0x7B6343L,0x735B3BL,0x674F2FL,0xCF974BL,0xA77B3BL,0x8B672FL, +0x6F5327L,0xEB9F27L,0xCB8B23L,0xAF771FL,0x93631BL,0x774F17L,0x5B3B0FL,0x3F270BL,0x231707L,0xA73B2BL,0x9F2F23L, +0x972B1BL,0x8B2713L,0x7F1F0FL,0x73170BL,0x671707L,0x571300L,0x4B0F00L,0x430F00L,0x3B0F00L,0x330B00L,0x2B0B00L, +0x230B00L,0x1B0700L,0x130700L,0x7B5F4BL,0x735743L,0x6B533FL,0x674F3BL,0x5F4737L,0x574333L,0x533F2FL,0x4B372BL, +0x433327L,0x3F2F23L,0x37271BL,0x2F2317L,0x271B13L,0x1F170FL,0x170F0BL,0x0F0B07L,0x6F3B17L,0x5F3717L,0x532F17L, +0x432B17L,0x372313L,0x271B0FL,0x1B130BL,0x0F0B07L,0xB35B4FL,0xBF7B6FL,0xCB9B93L,0xD7BBB7L,0xCBD7DFL,0xB3C7D3L, +0x9FB7C3L,0x87A7B7L,0x7397A7L,0x5B879BL,0x47778BL,0x2F677FL,0x17536FL,0x134B67L,0x0F435BL,0x0B3F53L,0x07374BL, +0x072F3FL,0x072733L,0x001F2BL,0x00171FL,0x000F13L,0x00070BL,0x000000L,0x8B5757L,0x834F4FL,0x7B4747L,0x734343L, +0x6B3B3BL,0x633333L,0x5B2F2FL,0x572B2BL,0x4B2323L,0x3F1F1FL,0x331B1BL,0x2B1313L,0x1F0F0FL,0x130B0BL,0x0B0707L, +0x000000L,0x979F7BL,0x8F9773L,0x878B6BL,0x7F8363L,0x777B5FL,0x737357L,0x6B6B4FL,0x636347L,0x5B5B43L,0x4F4F3BL, +0x434333L,0x37372BL,0x2F2F23L,0x23231BL,0x171713L,0x0F0F0BL,0x9F4B3FL,0x934337L,0x8B3B2FL,0x7F3727L,0x772F23L, +0x6B2B1BL,0x632317L,0x571F13L,0x4F1B0FL,0x43170BL,0x37130BL,0x2B0F07L,0x1F0B07L,0x170700L,0x0B0000L,0x000000L, +0x777BCFL,0x6F73C3L,0x676BB7L,0x6363A7L,0x5B5B9BL,0x53578FL,0x4B4F7FL,0x474773L,0x3F3F67L,0x373757L,0x2F2F4BL, +0x27273FL,0x231F2FL,0x1B1723L,0x130F17L,0x0B0707L,0x9BAB7BL,0x8F9F6FL,0x879763L,0x7B8B57L,0x73834BL,0x677743L, +0x5F6F3BL,0x576733L,0x4B5B27L,0x3F4F1BL,0x374313L,0x2F3B0BL,0x232F07L,0x1B2300L,0x131700L,0x0B0F00L,0x00FF00L, +0x23E70FL,0x3FD31BL,0x53BB27L,0x5FA72FL,0x5F8F33L,0x5F7B33L,0xFFFFFFL,0xFFFFD3L,0xFFFFA7L,0xFFFF7FL,0xFFFF53L, +0xFFFF27L,0xFFEB1FL,0xFFD717L,0xFFBF0FL,0xFFAB07L,0xFF9300L,0xEF7F00L,0xE36B00L,0xD35700L,0xC74700L,0xB73B00L, +0xAB2B00L,0x9B1F00L,0x8F1700L,0x7F0F00L,0x730700L,0x5F0000L,0x470000L,0x2F0000L,0x1B0000L,0xEF0000L,0x3737FFL, +0xFF0000L,0x0000FFL,0x2B2B23L,0x1B1B17L,0x13130FL,0xEB977FL,0xC37353L,0x9F5733L,0x7B3F1BL,0xEBD3C7L,0xC7AB9BL, +0xA78B77L,0x876B57L,0x9F5B53L +}; + + +bool CImageLoaderWAL::isALoadableFileExtension(const c8* fileName) const +{ + return strstr(fileName, ".wal") != 0; +} + + +bool CImageLoaderWAL::isALoadableFileFormat(irr::io::IReadFile* file) const +{ + return (file!=0); +} + + +IImage* CImageLoaderWAL::loadImage(irr::io::IReadFile* file) const +{ + // Try to get the color palette from elsewhere (usually in a pak along with the WAL). + // If this fails we use the DefaultPaletteQ2. + static s32 * palette = NULL; +#if TRY_LOADING_PALETTE_FROM_FILE + if (!palette) { + IImage * paletteImage; + // Look in a couple different places... + /* ........... */ paletteImage = createImageFromFile("pics/colormap.pcx"); + if (!paletteImage) paletteImage = createImageFromFile("pics/colormap.tga"); + if (!paletteImage) paletteImage = createImageFromFile("colormap.pcx"); + if (!paletteImage) paletteImage = createImageFromFile("colormap.tga"); + if (paletteImage && (paletteImage->getDimension().Width == 256) ) { + palette = new s32[256]; //FIXME: Never gets freed + for (u32 i = 0; i < 256; ++i) { + palette[i] = paletteImage->getPixel(i, 0).color; + } + } else { + //FIXME: try reading a simple palette from "wal.pal" + palette = DefaultPaletteQ2; + } + if (paletteImage) paletteImage->drop(); + } else { + palette = DefaultPaletteQ2; + } +#else + palette = DefaultPaletteQ2; +#endif + + SWALHeader header; + + file->seek(0); + file->read(&header, sizeof(SWALHeader)); + + file->seek(header.MipmapOffset[0]); + + // read image + + const u32 imageSize = header.ImageHeight * header.ImageWidth; + u8* data = new u8[imageSize]; + file->read(data, imageSize); + + IImage* image = 0; + + image = new CImage(ECF_A1R5G5B5, + core::dimension2d(header.ImageWidth, header.ImageHeight)); + + // I wrote an 8 to 32 converter, but this works with released Irrlicht code. + CColorConverter::convert8BitTo16Bit(data, + (s16*)image->lock(), header.ImageWidth, header.ImageHeight, DefaultPaletteQ2); + + image->unlock(); + + delete [] data; + + return image; +} + + +IImageLoader* createImageLoaderWAL() +{ + return new irr::video::CImageLoaderWAL(); +} + + +} +} + diff --git a/source/Irrlicht/CImageLoaderWAL.h b/source/Irrlicht/CImageLoaderWAL.h new file mode 100644 index 00000000..975d9ada --- /dev/null +++ b/source/Irrlicht/CImageLoaderWAL.h @@ -0,0 +1,63 @@ +/* + Thanks to: + Max McGuire for his Flipcode article about WAL textures + Nikolaus Gebhardt for the Irrlicht 3D engine +*/ + +#ifndef __C_IMAGE_LOADER_WAL_H_INCLUDED__ +#define __C_IMAGE_LOADER_WAL_H_INCLUDED__ + +#include "IImageLoader.h" + +namespace irr +{ +namespace video +{ + +#ifdef _MSC_VER +# pragma pack( push, packing ) +# pragma pack( 1 ) +# define PACK_STRUCT +#elif defined( __GNUC__ ) +# define PACK_STRUCT __attribute__((packed)) +#else +# error compiler not supported +#endif + + struct SWALHeader { + char FrameName[32]; + + u32 ImageWidth; + u32 ImageHeight; + + s32 MipmapOffset[4]; + + char NextFrameName[32]; + + u32 Flags; // surface properties, i.e. slick, sky, nodraw + u32 Contents; // i.e. solid, clip, area portal + u32 Value; // light + } PACK_STRUCT; + +#ifdef _MSC_VER +# pragma pack( pop, packing ) +#endif +#undef PACK_STRUCT + +class CImageLoaderWAL : public irr::video::IImageLoader +{ +public: + virtual bool isALoadableFileExtension(const c8* fileName) const; + + virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const; + + virtual irr::video::IImage* loadImage(irr::io::IReadFile* file) const; + +private: + static s32 DefaultPaletteQ2[256]; +}; + +} +} + +#endif diff --git a/source/Irrlicht/CNullDriver.cpp b/source/Irrlicht/CNullDriver.cpp index c5332cb8..674479e8 100644 --- a/source/Irrlicht/CNullDriver.cpp +++ b/source/Irrlicht/CNullDriver.cpp @@ -37,6 +37,9 @@ IImageLoader* createImageLoaderPCX(); //! creates a loader which is able to load png images IImageLoader* createImageLoaderPNG(); +//! creates a loader which is able to load WAL images +IImageLoader* createImageLoaderWAL(); + //! creates a loader which is able to load ppm/pgm/pbm images IImageLoader* createImageLoaderPPM(); @@ -102,6 +105,9 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d& scre #ifdef _IRR_COMPILE_WITH_PNG_LOADER_ SurfaceLoader.push_back(video::createImageLoaderPNG()); #endif +#ifdef _IRR_COMPILE_WITH_WAL_LOADER_ + SurfaceLoader.push_back(video::createImageLoaderWAL()); +#endif #ifdef _IRR_COMPILE_WITH_PPM_LOADER_ SurfaceLoader.push_back(video::createImageLoaderPPM()); #endif @@ -306,7 +312,6 @@ ITexture* CNullDriver::getTexture(const c8* filename) return texture; io::IReadFile* file = FileSystem->createAndOpenFile(filename); - bool errorReported = false; if (file) { @@ -321,12 +326,12 @@ ITexture* CNullDriver::getTexture(const c8* filename) } else { - errorReported = true; - os::Printer::log("Could not open file of texture", filename, ELL_ERROR); + os::Printer::log("Could not open file of texture", filename, ELL_WARNING); + return texture; } - if (!texture && !errorReported) - os::Printer::log("Could not load texture", filename, ELL_ERROR); + if (!texture) + os::Printer::log("Could not load texture", filename, ELL_WARNING); return texture; } @@ -355,7 +360,7 @@ ITexture* CNullDriver::getTexture(io::IReadFile* file) } if (!texture) - os::Printer::log("Could not load texture", file->getFileName(), ELL_ERROR); + os::Printer::log("Could not load texture", file->getFileName(), ELL_WARNING); return texture; } @@ -1141,7 +1146,7 @@ IImage* CNullDriver::createImageFromFile(const char* filename) file->drop(); } else - os::Printer::log("Could not open file of image", filename, ELL_ERROR); + os::Printer::log("Could not open file of image", filename, ELL_WARNING); return image; }